Merge "Transfer publicized bit to bridge in class merger"
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 9fcca89..584b06d 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -68,6 +68,7 @@
Path proguardCompatibilityRulesOutput = null;
private boolean allowPartiallyImplementedProguardOptions = false;
+ private boolean allowTestProguardOptions = false;
private StringConsumer mainDexListConsumer = null;
@@ -290,7 +291,8 @@
}
ProguardConfigurationParser parser = new ProguardConfigurationParser(
- factory, reporter, !allowPartiallyImplementedProguardOptions);
+ factory, reporter,
+ !allowPartiallyImplementedProguardOptions, allowTestProguardOptions);
if (!proguardConfigs.isEmpty()) {
parser.parse(proguardConfigs);
}
@@ -393,6 +395,11 @@
void allowPartiallyImplementedProguardOptions() {
allowPartiallyImplementedProguardOptions = true;
}
+
+ // Internal for-testing method to allow proguard options only available for testing.
+ void allowTestProguardOptions() {
+ allowTestProguardOptions = true;
+ }
}
// Wrapper class to ensure that R8 does not allow DEX as program inputs.
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
index 4530040..6948a08 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
public class AlwaysMaterializingUser extends Instruction {
@@ -58,8 +58,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forAlwaysMaterializingUser();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Argument.java b/src/main/java/com/android/tools/r8/ir/code/Argument.java
index f724a52..cff655a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Argument.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Argument.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
/**
@@ -76,8 +76,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forArgument();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
index e755759..01101f3 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
@@ -22,8 +22,8 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import java.util.Arrays;
import java.util.function.Function;
@@ -133,8 +133,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forArrayGet();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java b/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java
index 9a170a6..cc358f0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java
@@ -14,8 +14,8 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import java.util.function.Function;
public class ArrayLength extends Instruction {
@@ -90,8 +90,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forArrayLength();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
index a721955..023afce 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
@@ -18,8 +18,8 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions;
import java.util.Arrays;
@@ -154,8 +154,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forArrayPut();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Binop.java b/src/main/java/com/android/tools/r8/ir/code/Binop.java
index 9e6738a..e5190bb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Binop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Binop.java
@@ -13,8 +13,8 @@
import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import java.util.function.Function;
public abstract class Binop extends Instruction {
@@ -124,8 +124,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forBinop();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/CheckCast.java b/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
index 51e1891..dba575f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
+++ b/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
@@ -16,7 +16,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.function.Function;
public class CheckCast extends Instruction {
@@ -113,8 +113,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.classIsVisible(invocationContext, type, info);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forCheckCast(type, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
index 35549fb..3041aaf 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
import java.util.function.Function;
@@ -99,8 +99,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.classIsVisible(invocationContext, clazz, info);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forConstClass(clazz, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstInstruction.java b/src/main/java/com/android/tools/r8/ir/code/ConstInstruction.java
index cb9ef18..f6e212d 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstInstruction.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
public abstract class ConstInstruction extends Instruction {
@@ -29,7 +29,8 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forConstInstruction();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
index 9e1c21d..637faf7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
public class DebugLocalRead extends Instruction {
@@ -60,8 +60,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forDebugLocalRead();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
index edf68f3..53791e5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
@@ -100,8 +100,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forDebugLocalsChange();
}
public boolean apply(Int2ReferenceMap<DebugLocalInfo> locals) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
index f778037..aed2128 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
public class DebugPosition extends Instruction {
@@ -57,8 +57,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forDebugPosition();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java b/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
index 997a8c9..d88ca97 100644
--- a/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
@@ -3,13 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.code;
-import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import java.util.List;
public abstract class FieldInstruction extends Instruction {
@@ -50,27 +44,4 @@
public FieldInstruction asFieldInstruction() {
return this;
}
-
- /**
- * Returns the target of this field instruction, if such target is known, or null.
- * <p>
- * A result of null indicates that the field is either undefined or not of the right kind.
- */
- abstract DexEncodedField lookupTarget(DexType type, AppInfo appInfo);
-
- @Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- // Resolve the field if possible and decide whether the instruction can inlined.
- DexType fieldHolder = field.getHolder();
- DexEncodedField target = lookupTarget(fieldHolder, info);
- DexClass fieldClass = info.definitionFor(fieldHolder);
- if ((target != null) && (fieldClass != null)) {
- Constraint fieldConstraint = Constraint
- .deriveConstraint(invocationContext, fieldHolder, target.accessFlags, info);
- Constraint classConstraint = Constraint
- .deriveConstraint(invocationContext, fieldHolder, fieldClass.accessFlags, info);
- return Constraint.min(fieldConstraint, classConstraint);
- }
- return Constraint.NEVER;
- }
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
index 08f3b8f..1083669 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
@@ -17,12 +17,13 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.function.Function;
import org.objectweb.asm.Opcodes;
@@ -113,8 +114,9 @@
}
@Override
- DexEncodedField lookupTarget(DexType type, AppInfo appInfo) {
- return appInfo.lookupInstanceTarget(type, field);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInstanceGet(field, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java b/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java
index 6542e99..53fd31c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.function.Function;
public class InstanceOf extends Instruction {
@@ -81,8 +81,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.classIsVisible(invocationContext, type, info);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInstanceOf(type, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
index ededf98..3585348 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
@@ -15,12 +15,12 @@
import com.android.tools.r8.code.IputWide;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.Arrays;
import org.objectweb.asm.Opcodes;
@@ -113,8 +113,9 @@
}
@Override
- DexEncodedField lookupTarget(DexType type, AppInfo appInfo) {
- return appInfo.lookupInstanceTarget(type, field);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInstancePut(field, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index 62e518d..eb85222 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -17,8 +17,8 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
@@ -1056,11 +1056,11 @@
/**
* Returns the inlining constraint for this method when used in the context of the given type.
- * <p>
- * The type is used to judge visibility constraints and also for dispatch decisions.
+ *
+ * <p>The type is used to judge visibility constraints and also for dispatch decisions.
*/
- public abstract Constraint inliningConstraint(AppInfoWithLiveness info,
- DexType invocationContext);
+ public abstract Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext);
public abstract void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper);
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java b/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
index 0579362..a6e6fd1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.List;
public final class InvokeCustom extends Invoke {
@@ -101,8 +101,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.NEVER;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInvokeCustom();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
index 1ad50bc..88716dc 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
@@ -113,8 +113,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return new InliningConstraints(info).forInvokeDirect(getInvokedMethod(), invocationContext);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInvokeDirect(getInvokedMethod(), invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
index 0fb447b..06d368d 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
@@ -95,8 +95,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return new InliningConstraints(info).forInvokeInterface(getInvokedMethod(), invocationContext);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInvokeInterface(getInvokedMethod(), invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
index 56b659a..a8ec608 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeEnvironment;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
import com.android.tools.r8.ir.optimize.Inliner.InlineAction;
import com.android.tools.r8.ir.optimize.InliningOracle;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
@@ -83,12 +82,6 @@
return lookupSingleTarget(appInfo, appInfo.dexItemFactory.objectType);
}
- // TODO(christofferqa): Pass an instance of InliningConstraints instead of [info] when
- // InliningConstraints is complete.
- @Override
- public abstract Constraint inliningConstraint(
- AppInfoWithLiveness info, DexType invocationContext);
-
public abstract InlineAction computeInlining(InliningOracle decider, DexType invocationContext);
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java
index d4f6bd2..e34d25f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java
@@ -13,7 +13,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.List;
import java.util.function.Function;
@@ -69,8 +69,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.classIsVisible(invocationContext, type, info);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInvokeMultiNewArray(type, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java b/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
index 96680b3..a2a9c36 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.List;
import java.util.function.Function;
@@ -99,8 +99,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.classIsVisible(invocationContext, type, info);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInvokeNewArray(type, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java b/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
index 91f657d..8f90630 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
@@ -126,9 +126,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return new InliningConstraints(info)
- .forInvokePolymorphic(getInvokedMethod(), invocationContext);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInvokePolymorphic(getInvokedMethod(), invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
index b985916..d2183c0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
@@ -103,8 +103,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return new InliningConstraints(info).forInvokeStatic(getInvokedMethod(), invocationContext);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInvokeStatic(getInvokedMethod(), invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
index 64f0d7b..920d94b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
@@ -112,7 +112,8 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return new InliningConstraints(info).forInvokeSuper(getInvokedMethod(), invocationContext);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInvokeSuper(getInvokedMethod(), invocationContext);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
index 85c80ed..f55a407 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
@@ -95,8 +95,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return new InliningConstraints(info).forInvokeVirtual(getInvokedMethod(), invocationContext);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forInvokeVirtual(getInvokedMethod(), invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
index db151c6..6096292 100644
--- a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
import java.util.List;
@@ -47,8 +47,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forJumpInstruction();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Load.java b/src/main/java/com/android/tools/r8/ir/code/Load.java
index 10f4dad..32654b8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Load.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Load.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
public class Load extends Instruction {
@@ -51,8 +51,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forLoad();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Monitor.java b/src/main/java/com/android/tools/r8/ir/code/Monitor.java
index 97d6e01..6b3c89c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Monitor.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Monitor.java
@@ -15,7 +15,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
public class Monitor extends Instruction {
@@ -89,9 +89,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- // Conservative choice.
- return Constraint.NEVER;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forMonitor();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Move.java b/src/main/java/com/android/tools/r8/ir/code/Move.java
index b095bb4..e474bb8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Move.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Move.java
@@ -13,7 +13,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.function.Function;
public class Move extends Instruction {
@@ -100,8 +100,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forMove();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
index b7f0138..eabf7b2 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -13,7 +13,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
import java.util.HashSet;
import java.util.List;
@@ -75,9 +75,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- // TODO(64432527): Revisit this constraint.
- return Constraint.NEVER;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forMoveException();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
index 3a69ac5..edca979 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.function.Function;
public class NewArrayEmpty extends Instruction {
@@ -84,8 +84,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.classIsVisible(invocationContext, type, info);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forNewArrayEmpty(type, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
index f203597..ac46cc7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
import java.util.Arrays;
@@ -112,8 +112,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forNewArrayFilledData();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
index a5599fa..75931ad 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
@@ -13,7 +13,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.function.Function;
public class NewInstance extends Instruction {
@@ -81,8 +81,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.classIsVisible(invocationContext, clazz, info);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forNewInstance(clazz, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/NonNull.java b/src/main/java/com/android/tools/r8/ir/code/NonNull.java
index 0cf0616..462af06 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NonNull.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NonNull.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.function.Function;
public class NonNull extends Instruction {
@@ -85,8 +85,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forNonNull();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Pop.java b/src/main/java/com/android/tools/r8/ir/code/Pop.java
index 70d6af4..0fb1949 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Pop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Pop.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
public class Pop extends Instruction {
@@ -50,8 +50,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forPop();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Return.java b/src/main/java/com/android/tools/r8/ir/code/Return.java
index 6d3a85b..37cfaf0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Return.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Return.java
@@ -16,7 +16,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
public class Return extends JumpInstruction {
@@ -116,8 +116,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forReturn();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
index 1e4d125..486f9e2 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
@@ -16,12 +16,13 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.function.Function;
import org.objectweb.asm.Opcodes;
@@ -108,8 +109,9 @@
}
@Override
- DexEncodedField lookupTarget(DexType type, AppInfo appInfo) {
- return appInfo.lookupStaticTarget(type, field);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forStaticGet(field, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
index df42f42..f910ff6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
@@ -14,12 +14,12 @@
import com.android.tools.r8.code.SputWide;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import org.objectweb.asm.Opcodes;
public class StaticPut extends FieldInstruction {
@@ -107,8 +107,9 @@
}
@Override
- DexEncodedField lookupTarget(DexType type, AppInfo appInfo) {
- return appInfo.lookupStaticTarget(type, field);
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forStaticPut(field, invocationContext);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Store.java b/src/main/java/com/android/tools/r8/ir/code/Store.java
index ba5a502..b81af69 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Store.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Store.java
@@ -13,7 +13,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.utils.InternalOptions;
public class Store extends Instruction {
@@ -53,8 +53,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forStore();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Throw.java b/src/main/java/com/android/tools/r8/ir/code/Throw.java
index 5d8a4e7..4295dbe 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Throw.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Throw.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
public class Throw extends JumpInstruction {
@@ -65,8 +65,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forThrow();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Unop.java b/src/main/java/com/android/tools/r8/ir/code/Unop.java
index 6db3ad5..2f6ed7f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Unop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Unop.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
+import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.function.Function;
abstract public class Unop extends Instruction {
@@ -48,8 +48,9 @@
}
@Override
- public Constraint inliningConstraint(AppInfoWithLiveness info, DexType invocationContext) {
- return Constraint.ALWAYS;
+ public Constraint inliningConstraint(
+ InliningConstraints inliningConstraints, DexType invocationContext) {
+ return inliningConstraints.forUnop();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
index cc7f571..631f234 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
@@ -91,7 +91,9 @@
}
private Reason computeInliningReason(DexEncodedMethod target) {
- if (target.getOptimizationInfo().forceInline()) {
+ if (target.getOptimizationInfo().forceInline()
+ || (inliner.appInfo.hasLiveness()
+ && inliner.appInfo.withLiveness().forceInline.contains(target))) {
return Reason.FORCE;
}
if (inliner.appInfo.hasLiveness()
@@ -252,7 +254,7 @@
public InlineAction computeForInvokeWithReceiver(
InvokeMethodWithReceiver invoke, DexType invocationContext) {
DexEncodedMethod candidate = validateCandidate(invoke, invocationContext);
- if (candidate == null || inliner.isBlackListed(candidate.method)) {
+ if (candidate == null || inliner.isBlackListed(candidate)) {
return null;
}
@@ -268,6 +270,7 @@
if (info != null) {
info.exclude(invoke, "receiver for candidate can be null");
}
+ assert !inliner.appInfo.forceInline.contains(candidate.method);
return null;
}
@@ -293,7 +296,7 @@
@Override
public InlineAction computeForInvokeStatic(InvokeStatic invoke, DexType invocationContext) {
DexEncodedMethod candidate = validateCandidate(invoke, invocationContext);
- if (candidate == null || inliner.isBlackListed(candidate.method)) {
+ if (candidate == null || inliner.isBlackListed(candidate)) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 44ebdc7..db674bd 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -70,14 +70,14 @@
blackList.add(appInfo.dexItemFactory.kotlin.intrinsics.throwNpe);
}
- public boolean isBlackListed(DexMethod method) {
- return blackList.contains(method);
+ public boolean isBlackListed(DexEncodedMethod method) {
+ return blackList.contains(method.method) || appInfo.neverInline.contains(method);
}
private Constraint instructionAllowedForInlining(
- DexEncodedMethod method, Instruction instruction) {
- Constraint result = instruction.inliningConstraint(appInfo, method.method.holder);
- if ((result == Constraint.NEVER) && instruction.isDebugInstruction()) {
+ Instruction instruction, InliningConstraints inliningConstraints, DexType invocationContext) {
+ Constraint result = instruction.inliningConstraint(inliningConstraints, invocationContext);
+ if (result == Constraint.NEVER && instruction.isDebugInstruction()) {
return Constraint.ALWAYS;
}
return result;
@@ -85,10 +85,12 @@
public Constraint computeInliningConstraint(IRCode code, DexEncodedMethod method) {
Constraint result = Constraint.ALWAYS;
+ InliningConstraints inliningConstraints = new InliningConstraints(appInfo);
InstructionIterator it = code.instructionIterator();
while (it.hasNext()) {
Instruction instruction = it.next();
- Constraint state = instructionAllowedForInlining(method, instruction);
+ Constraint state =
+ instructionAllowedForInlining(instruction, inliningConstraints, method.method.holder);
result = Constraint.min(result, state);
if (result == Constraint.NEVER) {
break;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
index d4a06cd..78d70a0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
@@ -6,7 +6,9 @@
import com.android.tools.r8.graph.AppInfo.ResolutionResult;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
@@ -42,10 +44,72 @@
this.graphLense = graphLense;
}
+ public Constraint forAlwaysMaterializingUser() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forArgument() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forArrayGet() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forArrayLength() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forArrayPut() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forBinop() {
+ return Constraint.ALWAYS;
+ }
+
public Constraint forCheckCast(DexType type, DexType invocationContext) {
return Constraint.classIsVisible(invocationContext, type, appInfo);
}
+ public Constraint forConstClass(DexType type, DexType invocationContext) {
+ return Constraint.classIsVisible(invocationContext, type, appInfo);
+ }
+
+ public Constraint forConstInstruction() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forDebugLocalRead() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forDebugLocalsChange() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forDebugPosition() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forInstanceGet(DexField field, DexType invocationContext) {
+ return forFieldInstruction(
+ field, appInfo.lookupInstanceTarget(field.clazz, field), invocationContext);
+ }
+
+ public Constraint forInstanceOf(DexType type, DexType invocationContext) {
+ return Constraint.classIsVisible(invocationContext, type, appInfo);
+ }
+
+ public Constraint forInvokeCustom() {
+ return Constraint.NEVER;
+ }
+
+ public Constraint forInstancePut(DexField field, DexType invocationContext) {
+ return forFieldInstruction(
+ field, appInfo.lookupInstanceTarget(field.clazz, field), invocationContext);
+ }
+
public Constraint forInvokeDirect(DexMethod method, DexType invocationContext) {
return forSingleTargetInvoke(method, appInfo.lookupDirectTarget(method), invocationContext);
}
@@ -54,6 +118,14 @@
return forVirtualInvoke(method, appInfo.lookupInterfaceTargets(method), invocationContext);
}
+ public Constraint forInvokeMultiNewArray(DexType type, DexType invocationContext) {
+ return Constraint.classIsVisible(invocationContext, type, appInfo);
+ }
+
+ public Constraint forInvokeNewArray(DexType type, DexType invocationContext) {
+ return Constraint.classIsVisible(invocationContext, type, appInfo);
+ }
+
public Constraint forInvokePolymorphic(DexMethod method, DexType invocationContext) {
return Constraint.NEVER;
}
@@ -71,6 +143,90 @@
return forVirtualInvoke(method, appInfo.lookupVirtualTargets(method), invocationContext);
}
+ public Constraint forJumpInstruction() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forLoad() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forMonitor() {
+ // Conservative choice.
+ return Constraint.NEVER;
+ }
+
+ public Constraint forMove() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forMoveException() {
+ // TODO(64432527): Revisit this constraint.
+ return Constraint.NEVER;
+ }
+
+ public Constraint forNewArrayEmpty(DexType type, DexType invocationContext) {
+ return Constraint.classIsVisible(invocationContext, type, appInfo);
+ }
+
+ public Constraint forNewArrayFilledData() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forNewInstance(DexType type, DexType invocationContext) {
+ return Constraint.classIsVisible(invocationContext, type, appInfo);
+ }
+
+ public Constraint forNonNull() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forPop() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forReturn() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forStaticGet(DexField field, DexType invocationContext) {
+ return forFieldInstruction(
+ field, appInfo.lookupStaticTarget(field.clazz, field), invocationContext);
+ }
+
+ public Constraint forStaticPut(DexField field, DexType invocationContext) {
+ return forFieldInstruction(
+ field, appInfo.lookupStaticTarget(field.clazz, field), invocationContext);
+ }
+
+ public Constraint forStore() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forThrow() {
+ return Constraint.ALWAYS;
+ }
+
+ public Constraint forUnop() {
+ return Constraint.ALWAYS;
+ }
+
+ private Constraint forFieldInstruction(
+ DexField field, DexEncodedField target, DexType invocationContext) {
+ // Resolve the field if possible and decide whether the instruction can inlined.
+ DexType fieldHolder = graphLense.lookupType(field.clazz);
+ DexClass fieldClass = appInfo.definitionFor(fieldHolder);
+ if (target != null && fieldClass != null) {
+ Constraint fieldConstraint =
+ Constraint.deriveConstraint(invocationContext, fieldHolder, target.accessFlags, appInfo);
+ Constraint classConstraint =
+ Constraint.deriveConstraint(
+ invocationContext, fieldHolder, fieldClass.accessFlags, appInfo);
+ return Constraint.min(fieldConstraint, classConstraint);
+ }
+ return Constraint.NEVER;
+ }
+
private Constraint forSingleTargetInvoke(
DexMethod method, DexEncodedMethod target, DexType invocationContext) {
if (method.holder.isArrayType()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index e749479..c3a3781 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -107,6 +107,7 @@
final private AppInfoWithLiveness appInfo;
final private DexItemFactory dexItemFactory;
+ private final InliningConstraints inliningConstraints;
// Representation of an outline.
// This includes the instructions in the outline, and a map from the arguments of this outline
@@ -475,7 +476,7 @@
// See whether we could move this invoke somewhere else. We reuse the logic from inlining
// here, as the constraints are the same.
- Constraint constraint = invoke.inliningConstraint(appInfo, method.method.holder);
+ Constraint constraint = invoke.inliningConstraint(inliningConstraints, method.method.holder);
if (constraint != Constraint.ALWAYS) {
return false;
}
@@ -818,6 +819,7 @@
public Outliner(AppInfoWithLiveness appInfo, InternalOptions options) {
this.appInfo = appInfo;
this.dexItemFactory = appInfo.dexItemFactory;
+ this.inliningConstraints = new InliningConstraints(appInfo);
this.options = options;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index baacb1e..a1cc440 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1544,10 +1544,18 @@
*/
public final Map<DexItem, ProguardMemberRule> assumedValues;
/**
- * All methods that have to be inlined due to a configuration directive.
+ * All methods that should be inlined if possible due to a configuration directive.
*/
public final Set<DexItem> alwaysInline;
/**
+ * All methods that *must* be inlined due to a configuration directive (testing only).
+ */
+ public final Set<DexItem> forceInline;
+ /**
+ * All methods that *must* never be inlined due to a configuration directive (testing only).
+ */
+ public final Set<DexItem> neverInline;
+ /**
* All items with -identifiernamestring rule.
*/
public final Set<DexItem> identifierNameStrings;
@@ -1602,6 +1610,8 @@
this.noSideEffects = enqueuer.rootSet.noSideEffects;
this.assumedValues = enqueuer.rootSet.assumedValues;
this.alwaysInline = enqueuer.rootSet.alwaysInline;
+ this.forceInline = enqueuer.rootSet.forceInline;
+ this.neverInline = enqueuer.rootSet.neverInline;
this.identifierNameStrings =
Sets.union(enqueuer.rootSet.identifierNameStrings, enqueuer.identifierNameStrings);
this.protoLiteFields = enqueuer.protoLiteFields;
@@ -1640,6 +1650,8 @@
this.brokenSuperInvokes = previous.brokenSuperInvokes;
this.protoLiteFields = previous.protoLiteFields;
this.alwaysInline = previous.alwaysInline;
+ this.forceInline = previous.forceInline;
+ this.neverInline = previous.neverInline;
this.identifierNameStrings = previous.identifierNameStrings;
this.prunedTypes = mergeSets(previous.prunedTypes, removedClasses);
this.switchMaps = previous.switchMaps;
@@ -1683,6 +1695,8 @@
this.assumedValues = previous.assumedValues;
assert lense.assertNotModified(previous.alwaysInline);
this.alwaysInline = previous.alwaysInline;
+ this.forceInline = previous.forceInline;
+ this.neverInline = previous.neverInline;
this.identifierNameStrings =
rewriteMixedItemsConservatively(previous.identifierNameStrings, lense);
// Switchmap classes should never be affected by renaming.
@@ -1724,6 +1738,8 @@
this.brokenSuperInvokes = previous.brokenSuperInvokes;
this.protoLiteFields = previous.protoLiteFields;
this.alwaysInline = previous.alwaysInline;
+ this.forceInline = previous.forceInline;
+ this.neverInline = previous.neverInline;
this.identifierNameStrings = previous.identifierNameStrings;
this.prunedTypes = previous.prunedTypes;
this.switchMaps = switchMaps;
diff --git a/src/main/java/com/android/tools/r8/shaking/InlineRule.java b/src/main/java/com/android/tools/r8/shaking/InlineRule.java
new file mode 100644
index 0000000..565856c
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/InlineRule.java
@@ -0,0 +1,88 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.shaking;
+
+import com.android.tools.r8.errors.Unreachable;
+import java.util.List;
+
+public class InlineRule extends ProguardConfigurationRule {
+
+ public enum Type {
+ ALWAYS, FORCE, NEVER
+ }
+
+ public static class Builder extends ProguardConfigurationRule.Builder {
+
+ private Builder() {
+ }
+
+ Type type;
+
+ public Builder setType(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ public InlineRule build() {
+ return new InlineRule(classAnnotation, classAccessFlags,
+ negatedClassAccessFlags, classTypeNegated, classType, classNames, inheritanceAnnotation,
+ inheritanceClassName, inheritanceIsExtends, memberRules, type);
+ }
+ }
+
+ private final Type type;
+
+ private InlineRule(
+ ProguardTypeMatcher classAnnotation,
+ ProguardAccessFlags classAccessFlags,
+ ProguardAccessFlags negatedClassAccessFlags,
+ boolean classTypeNegated,
+ ProguardClassType classType,
+ ProguardClassNameList classNames,
+ ProguardTypeMatcher inheritanceAnnotation,
+ ProguardTypeMatcher inheritanceClassName,
+ boolean inheritanceIsExtends,
+ List<ProguardMemberRule> memberRules,
+ Type type) {
+ super(classAnnotation, classAccessFlags, negatedClassAccessFlags, classTypeNegated, classType,
+ classNames, inheritanceAnnotation, inheritanceClassName, inheritanceIsExtends, memberRules);
+ this.type = type;
+ }
+
+ public static InlineRule.Builder builder() {
+ return new InlineRule.Builder();
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public ProguardCheckDiscardRule asProguardCheckDiscardRule() {
+ assert type == Type.FORCE;
+ ProguardCheckDiscardRule.Builder builder = ProguardCheckDiscardRule.builder();
+ builder.setClassAnnotation(getClassAnnotation());
+ builder.setClassAccessFlags(getClassAccessFlags());
+ builder.setNegatedClassAccessFlags(getNegatedClassAccessFlags());
+ builder.setClassTypeNegated(getClassTypeNegated());
+ builder.setClassType(getClassType());
+ builder.setClassNames(getClassNames());
+ builder.setInheritanceAnnotation(getInheritanceAnnotation());
+ builder.setInheritanceIsExtends(getInheritanceIsExtends());
+ builder.setMemberRules(getMemberRules());
+ return builder.build();
+ }
+
+ @Override
+ String typeString() {
+ switch (type) {
+ case ALWAYS:
+ return "alwaysinline";
+ case FORCE:
+ return "forceinline";
+ case NEVER:
+ return "neverinline";
+ }
+ throw new Unreachable("Unknown inline type " + type);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java
deleted file mode 100644
index 8d4a14b..0000000
--- a/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-package com.android.tools.r8.shaking;
-
-import java.util.List;
-
-public class ProguardAlwaysInlineRule extends ProguardConfigurationRule {
-
- public static class Builder extends ProguardConfigurationRule.Builder {
-
- private Builder() {
- }
-
- public ProguardAlwaysInlineRule build() {
- return new ProguardAlwaysInlineRule(classAnnotation, classAccessFlags,
- negatedClassAccessFlags, classTypeNegated, classType, classNames, inheritanceAnnotation,
- inheritanceClassName, inheritanceIsExtends, memberRules);
- }
- }
-
- private ProguardAlwaysInlineRule(
- ProguardTypeMatcher classAnnotation,
- ProguardAccessFlags classAccessFlags,
- ProguardAccessFlags negatedClassAccessFlags,
- boolean classTypeNegated,
- ProguardClassType classType,
- ProguardClassNameList classNames,
- ProguardTypeMatcher inheritanceAnnotation,
- ProguardTypeMatcher inheritanceClassName,
- boolean inheritanceIsExtends,
- List<ProguardMemberRule> memberRules) {
- super(classAnnotation, classAccessFlags, negatedClassAccessFlags, classTypeNegated, classType,
- classNames, inheritanceAnnotation, inheritanceClassName, inheritanceIsExtends, memberRules);
- }
-
- public static ProguardAlwaysInlineRule.Builder builder() {
- return new ProguardAlwaysInlineRule.Builder();
- }
-
- @Override
- String typeString() {
- return "alwaysinline";
- }
-}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 1de3f17..5b22456 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -5,6 +5,7 @@
import static com.android.tools.r8.utils.DescriptorUtils.javaTypeToDescriptor;
+import com.android.tools.r8.Version;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
@@ -15,6 +16,7 @@
import com.android.tools.r8.position.Position;
import com.android.tools.r8.position.TextPosition;
import com.android.tools.r8.position.TextRange;
+import com.android.tools.r8.shaking.InlineRule.Type;
import com.android.tools.r8.shaking.ProguardConfiguration.Builder;
import com.android.tools.r8.shaking.ProguardTypeMatcher.ClassOrType;
import com.android.tools.r8.shaking.ProguardTypeMatcher.MatchSpecificType;
@@ -48,6 +50,7 @@
private final Reporter reporter;
private final boolean failOnPartiallyImplementedOptions;
+ private final boolean allowTestOptions;
private static final List<String> IGNORED_SINGLE_ARG_OPTIONS = ImmutableList.of(
"protomapping",
@@ -97,16 +100,18 @@
public ProguardConfigurationParser(
DexItemFactory dexItemFactory, Reporter reporter) {
- this(dexItemFactory, reporter, true);
+ this(dexItemFactory, reporter, true, false);
}
public ProguardConfigurationParser(
- DexItemFactory dexItemFactory, Reporter reporter, boolean failOnPartiallyImplementedOptions) {
+ DexItemFactory dexItemFactory, Reporter reporter, boolean failOnPartiallyImplementedOptions,
+ boolean allowTestOptions) {
this.dexItemFactory = dexItemFactory;
configurationBuilder = ProguardConfiguration.builder(dexItemFactory, reporter);
this.reporter = reporter;
this.failOnPartiallyImplementedOptions = failOnPartiallyImplementedOptions;
+ this.allowTestOptions = allowTestOptions;
}
public ProguardConfiguration.Builder getConfigurationBuilder() {
@@ -343,7 +348,16 @@
} else if (acceptString("packageobfuscationdictionary")) {
configurationBuilder.setPackageObfuscationDictionary(parseFileName());
} else if (acceptString("alwaysinline")) {
- ProguardAlwaysInlineRule rule = parseAlwaysInlineRule();
+ InlineRule rule = parseInlineRule(Type.ALWAYS);
+ configurationBuilder.addRule(rule);
+ } else if (allowTestOptions && acceptString("forceinline")) {
+ InlineRule rule = parseInlineRule(Type.FORCE);
+ configurationBuilder.addRule(rule);
+ // Insert a matching -checkdiscard rule to ensure force inlining happens.
+ ProguardCheckDiscardRule ruled = rule.asProguardCheckDiscardRule();
+ configurationBuilder.addRule(ruled);
+ } else if (allowTestOptions && acceptString("neverinline")) {
+ InlineRule rule = parseInlineRule(Type.NEVER);
configurationBuilder.addRule(rule);
} else if (acceptString("useuniqueclassmembernames")) {
configurationBuilder.setUseUniqueClassMemberNames(true);
@@ -367,8 +381,15 @@
configurationBuilder.addRule(parseIfRule(optionStart));
} else {
String unknownOption = acceptString();
+ String devMessage = "";
+ if (Version.isDev()
+ && unknownOption != null
+ && (unknownOption.equals("forceinline") || unknownOption.equals("neverinline"))) {
+ devMessage = ", this option needs to be turned on explicitly if used for tests.";
+ }
reporter.error(new StringDiagnostic(
- "Unknown option \"-" + unknownOption + "\"", origin, getPosition(optionStart)));
+ "Unknown option \"-" + unknownOption + "\"" + devMessage,
+ origin, getPosition(optionStart)));
}
return true;
}
@@ -563,9 +584,9 @@
return keepRuleBuilder.build();
}
- private ProguardAlwaysInlineRule parseAlwaysInlineRule()
+ private InlineRule parseInlineRule(InlineRule.Type type)
throws ProguardRuleParserException {
- ProguardAlwaysInlineRule.Builder keepRuleBuilder = ProguardAlwaysInlineRule.builder();
+ InlineRule.Builder keepRuleBuilder = InlineRule.builder().setType(type);
parseClassSpec(keepRuleBuilder, false);
return keepRuleBuilder.build();
}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java
index ce1840f..e4c5691 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java
@@ -56,7 +56,7 @@
if (!(o instanceof ProguardConfigurationRule)) {
return false;
}
- ProguardKeepRule that = (ProguardKeepRule) o;
+ ProguardConfigurationRule that = (ProguardConfigurationRule) o;
return super.equals(that);
}
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index c860d83..c95cfe9 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -60,6 +60,8 @@
Sets.newIdentityHashSet();
private final Set<DexItem> checkDiscarded = Sets.newIdentityHashSet();
private final Set<DexItem> alwaysInline = Sets.newIdentityHashSet();
+ private final Set<DexItem> forceInline = Sets.newIdentityHashSet();
+ private final Set<DexItem> neverInline = Sets.newIdentityHashSet();
private final Map<DexItem, Map<DexItem, ProguardKeepRule>> dependentNoShrinking =
new IdentityHashMap<>();
private final Map<DexItem, ProguardMemberRule> noSideEffects = new IdentityHashMap<>();
@@ -240,7 +242,7 @@
} else if (rule instanceof ProguardAssumeNoSideEffectRule) {
markMatchingVisibleMethods(clazz, memberKeepRules, rule, null);
markMatchingFields(clazz, memberKeepRules, rule, null);
- } else if (rule instanceof ProguardAlwaysInlineRule) {
+ } else if (rule instanceof InlineRule) {
markMatchingMethods(clazz, memberKeepRules, rule, null);
} else if (rule instanceof ProguardAssumeValuesRule) {
markMatchingVisibleMethods(clazz, memberKeepRules, rule, null);
@@ -310,6 +312,8 @@
keepPackageName,
checkDiscarded,
alwaysInline,
+ forceInline,
+ neverInline,
noSideEffects,
assumedValues,
dependentNoShrinking,
@@ -720,8 +724,20 @@
assumedValues.put(item, rule);
} else if (context instanceof ProguardCheckDiscardRule) {
checkDiscarded.add(item);
- } else if (context instanceof ProguardAlwaysInlineRule) {
- alwaysInline.add(item);
+ } else if (context instanceof InlineRule) {
+ switch (((InlineRule) context).getType()) {
+ case ALWAYS:
+ alwaysInline.add(item);
+ break;
+ case FORCE:
+ forceInline.add(item);
+ break;
+ case NEVER:
+ neverInline.add(item);
+ break;
+ default:
+ throw new Unreachable();
+ }
} else if (context instanceof ProguardIdentifierNameStringRule) {
if (item instanceof DexEncodedField) {
identifierNameStrings.add(((DexEncodedField) item).field);
@@ -740,6 +756,8 @@
public final Set<DexItem> keepPackageName;
public final Set<DexItem> checkDiscarded;
public final Set<DexItem> alwaysInline;
+ public final Set<DexItem> forceInline;
+ public final Set<DexItem> neverInline;
public final Map<DexItem, ProguardMemberRule> noSideEffects;
public final Map<DexItem, ProguardMemberRule> assumedValues;
private final Map<DexItem, Map<DexItem, ProguardKeepRule>> dependentNoShrinking;
@@ -775,6 +793,8 @@
Set<DexItem> keepPackageName,
Set<DexItem> checkDiscarded,
Set<DexItem> alwaysInline,
+ Set<DexItem> forceInline,
+ Set<DexItem> neverInline,
Map<DexItem, ProguardMemberRule> noSideEffects,
Map<DexItem, ProguardMemberRule> assumedValues,
Map<DexItem, Map<DexItem, ProguardKeepRule>> dependentNoShrinking,
@@ -787,6 +807,8 @@
this.keepPackageName = Collections.unmodifiableSet(keepPackageName);
this.checkDiscarded = Collections.unmodifiableSet(checkDiscarded);
this.alwaysInline = Collections.unmodifiableSet(alwaysInline);
+ this.forceInline = Collections.unmodifiableSet(forceInline);
+ this.neverInline = Collections.unmodifiableSet(neverInline);
this.noSideEffects = Collections.unmodifiableMap(noSideEffects);
this.assumedValues = Collections.unmodifiableMap(assumedValues);
this.dependentNoShrinking = dependentNoShrinking;
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index d5d0558..10f62a1 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -1546,6 +1546,12 @@
return builder;
}
+ public static R8Command.Builder allowTestProguardOptions(
+ R8Command.Builder builder) {
+ builder.allowTestProguardOptions();
+ return builder;
+ }
+
public static AndroidApp getApp(BaseCommand command) {
return command.getInputApp();
}
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index f484bc8..1379b95 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -148,7 +148,14 @@
public void resetAllowPartiallyImplementedOptions() {
handler = new KeepingDiagnosticHandler();
reporter = new Reporter(handler);
- parser = new ProguardConfigurationParser(new DexItemFactory(), reporter, false);
+ parser = new ProguardConfigurationParser(new DexItemFactory(), reporter, false, false);
+ }
+
+ @Before
+ public void resetAllowTestOptions() {
+ handler = new KeepingDiagnosticHandler();
+ reporter = new Reporter(handler);
+ parser = new ProguardConfigurationParser(new DexItemFactory(), reporter, true, true);
}
@Test
@@ -861,7 +868,7 @@
@Test
public void parseKeepdirectories() throws Exception {
ProguardConfigurationParser parser =
- new ProguardConfigurationParser(new DexItemFactory(), reporter, false);
+ new ProguardConfigurationParser(new DexItemFactory(), reporter, false, false);
parser.parse(Paths.get(KEEPDIRECTORIES));
verifyParserEndsCleanly();
}
@@ -1357,6 +1364,22 @@
}
@Test
+ public void parse_testInlineOptions() {
+ List<String> options = ImmutableList.of(
+ "-neverinline", "-forceinline");
+ for (String option : options) {
+ try {
+ reset();
+ parser.parse(createConfigurationForTesting(ImmutableList.of(option + " class A { *; }")));
+ fail("Expect to fail due to testing option being turned off.");
+ } catch (AbortException e) {
+ assertEquals(2, handler.errors.size());
+ checkDiagnostics(handler.errors, 0, null, 1, 1, "Unknown option \"" + option + "\"");
+ }
+ }
+ }
+
+ @Test
public void parse_if() throws Exception {
Path proguardConfig = writeTextToTempFile(
"-if class **$$ModuleAdapter",
diff --git a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ProguardCompatabilityTestBase.java b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ProguardCompatabilityTestBase.java
index 10c64e3..693f02d 100644
--- a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ProguardCompatabilityTestBase.java
+++ b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ProguardCompatabilityTestBase.java
@@ -99,6 +99,7 @@
throws Exception {
AndroidApp app = readClassesAndAndriodJar(programClasses);
R8Command.Builder builder = ToolHelper.prepareR8CommandBuilder(app);
+ ToolHelper.allowTestProguardOptions(builder);
builder.addProguardConfiguration(ImmutableList.of(proguardConfig), Origin.unknown());
return ToolHelper.runR8(builder.build(), configure);
}
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java b/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java
index 14391ee..22f9ef6 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java
@@ -33,13 +33,6 @@
}
}
-class B {
- // Depending on inlining option, this method is kept to make inlining of A.a() infeasible.
- void x() {
- System.out.print("" + A.a() + A.a() + A.a() + A.a() + A.a() + A.a() + A.a() + A.a());
- }
-}
-
class D {
}
@@ -52,7 +45,7 @@
@RunWith(Parameterized.class)
public class IfRuleWithInlining extends ProguardCompatabilityTestBase {
private final static List<Class> CLASSES = ImmutableList.of(
- A.class, B.class, D.class, Main.class);
+ A.class, D.class, Main.class);
private final Shrinker shrinker;
private final boolean inlineMethod;
@@ -90,11 +83,8 @@
List<String> config = ImmutableList.of(
"-keep class **.Main { public static void main(java.lang.String[]); }",
inlineMethod
- ? "-alwaysinline class **.A { int a(); }"
- : "-keep class **.B { *; }",
- inlineMethod
- ? "-checkdiscard class **.A { int a(); }"
- : "",
+ ? "-forceinline class **.A { int a(); }"
+ : "-neverinline class **.A { int a(); }",
"-if class **.A { static int a(); }",
"-keep class **.D",
"-dontobfuscate"
diff --git a/src/test/java/com/android/tools/r8/shaking/testrules/A.java b/src/test/java/com/android/tools/r8/shaking/testrules/A.java
new file mode 100644
index 0000000..af05562
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/testrules/A.java
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.shaking.testrules;
+
+public class A {
+
+ public static int m(int a, int b) {
+ int r = a + b;
+ System.out.println(a + " + " + b + " = " + r);
+ return r;
+ }
+
+ public static int method() {
+ return m(m(m(1, 2), m(3, 4)), m(m(5, 6), m(7, 8)));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/testrules/B.java b/src/test/java/com/android/tools/r8/shaking/testrules/B.java
new file mode 100644
index 0000000..4d1f085
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/testrules/B.java
@@ -0,0 +1,17 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.shaking.testrules;
+
+public class B {
+
+ public int m(int a, int b) {
+ int r = a + b;
+ System.out.println(a + " + " + b + " = " + r);
+ return r;
+ }
+ public int method() {
+ return m(m(m(1, 2), m(3, 4)), m(m(5, 6), m(7, 8)));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/testrules/C.java b/src/test/java/com/android/tools/r8/shaking/testrules/C.java
new file mode 100644
index 0000000..5ee4d53
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/testrules/C.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.shaking.testrules;
+
+public class C {
+
+ private static int i;
+
+ public static int x() {
+ return i;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java b/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java
new file mode 100644
index 0000000..e4be101
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java
@@ -0,0 +1,120 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.shaking.testrules;
+import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.fail;
+
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+
+public class ForceInlineTest extends TestBase {
+
+ private DexInspector runTest(List<String> proguardConfiguration) throws Exception {
+ R8Command.Builder builder =
+ ToolHelper.prepareR8CommandBuilder(readClasses(Main.class, A.class, B.class, C.class));
+ ToolHelper.allowTestProguardOptions(builder);
+ builder.addProguardConfiguration(proguardConfiguration, Origin.unknown());
+ return new DexInspector(ToolHelper.runR8(builder.build()));
+ }
+
+ @Test
+ public void testDefaultInlining() throws Exception {
+ DexInspector inspector = runTest(ImmutableList.of(
+ "-keep class **.Main { *; }",
+ "-dontobfuscate"
+ ));
+
+ ClassSubject classA = inspector.clazz(A.class);
+ ClassSubject classB = inspector.clazz(B.class);
+ ClassSubject classC = inspector.clazz(C.class);
+ ClassSubject classMain = inspector.clazz(Main.class);
+ assertThat(classA, isPresent());
+ assertThat(classB, isPresent());
+ assertThat(classC, isPresent());
+ assertThat(classMain, isPresent());
+
+ // By default A.m *will not* be inlined (called several times and not small).
+ assertThat(classA.method("int", "m", ImmutableList.of("int", "int")), isPresent());
+ // By default A.method *will* be inlined (called only once).
+ assertThat(classA.method("int", "method", ImmutableList.of()), not(isPresent()));
+ // By default B.m *will not* be inlined (called several times and not small).
+ assertThat(classB.method("int", "m", ImmutableList.of("int", "int")), isPresent());
+ // By default B.method *will* be inlined (called only once).
+ assertThat(classB.method("int", "method", ImmutableList.of()), not(isPresent()));
+ }
+
+ @Test
+ public void testNeverInline() throws Exception {
+ DexInspector inspector = runTest(ImmutableList.of(
+ "-neverinline class **.A { method(); }",
+ "-neverinline class **.B { method(); }",
+ "-keep class **.Main { *; }",
+ "-dontobfuscate"
+ ));
+
+ ClassSubject classA = inspector.clazz(A.class);
+ ClassSubject classB = inspector.clazz(B.class);
+ ClassSubject classC = inspector.clazz(C.class);
+ ClassSubject classMain = inspector.clazz(Main.class);
+ assertThat(classA, isPresent());
+ assertThat(classB, isPresent());
+ assertThat(classC, isPresent());
+ assertThat(classMain, isPresent());
+
+ // Compared to the default method is no longer inlined.
+ assertThat(classA.method("int", "m", ImmutableList.of("int", "int")), isPresent());
+ assertThat(classA.method("int", "method", ImmutableList.of()), isPresent());
+ assertThat(classB.method("int", "m", ImmutableList.of("int", "int")), isPresent());
+ assertThat(classB.method("int", "method", ImmutableList.of()), isPresent());
+ }
+
+ @Test
+ public void testForceInline() throws Exception {
+ DexInspector inspector = runTest(ImmutableList.of(
+ "-forceinline class **.A { int m(int, int); }",
+ "-forceinline class **.B { int m(int, int); }",
+ "-keep class **.Main { *; }",
+ "-dontobfuscate"
+ ));
+
+ ClassSubject classA = inspector.clazz(A.class);
+ ClassSubject classB = inspector.clazz(B.class);
+ ClassSubject classC = inspector.clazz(C.class);
+ ClassSubject classMain = inspector.clazz(Main.class);
+
+ // Compared to the default m is now inlined and method still is, so classes A and B are gone.
+ assertThat(classA, not(isPresent()));
+ assertThat(classB, not(isPresent()));
+ assertThat(classC, isPresent());
+ assertThat(classMain, isPresent());
+ }
+
+ @Test
+ public void testForceInlineFails() throws Exception {
+ try {
+ DexInspector inspector = runTest(ImmutableList.of(
+ "-forceinline class **.A { int x(); }",
+ "-keep class **.Main { *; }",
+ "-dontobfuscate"
+ ));
+ fail("Force inline of non-inlinable method succeeded");
+ } catch (Throwable t) {
+ // Ignore assertion error.
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/shaking/testrules/Main.java b/src/test/java/com/android/tools/r8/shaking/testrules/Main.java
new file mode 100644
index 0000000..d326216
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/testrules/Main.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.shaking.testrules;
+
+public class Main {
+
+ public static void main(String[] args) {
+ System.out.println(A.method());
+ System.out.println(new B().method());
+ System.out.println(C.x());
+ }
+}
diff --git a/src/test/sampleApks/split/split.spec b/src/test/sampleApks/split/split.spec
index a06e259..ed40b98 100644
--- a/src/test/sampleApks/split/split.spec
+++ b/src/test/sampleApks/split/split.spec
@@ -1 +1,2 @@
com.android.tools.r8.sample.split.SplitClass:split
+com.android.tools.r8.sample.split.SplitInheritBase:split
diff --git a/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/BaseClass.java b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/BaseClass.java
new file mode 100644
index 0000000..eef119c
--- /dev/null
+++ b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/BaseClass.java
@@ -0,0 +1,104 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.sample.split;
+
+
+public class BaseClass {
+
+ int initialValue;
+
+ public BaseClass(int initialValue) {
+ this.initialValue = initialValue;
+ }
+
+ public int calculate(int x) {
+ int result = 2;
+ for (int i = 0; i < 42; i++) {
+ result += initialValue + x;
+ }
+ return result;
+ }
+
+ public int largeMethod(int x, int y) {
+ int a = x + y;
+ int b;
+ int c;
+ double d;
+ String s;
+ if (a < 22) {
+ b = a * 42 / y;
+ c = b - 80;
+ d = a + b + c * y - x * a;
+ s = "foobar";
+ } else if (a < 42) {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "foo";
+ } else {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "bar";
+ }
+ if (s.equals("bar")) {
+ d = 49;
+ s += b;
+ } else {
+ b = 63;
+ s = "barbar" + b;
+ }
+
+ if (a < 22) {
+ b = a * 42 / y;
+ c = b - 80;
+ d = a + b + c * y - x * a;
+ s = "foobar";
+ } else if (a < 42) {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "foo";
+ } else {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "bar";
+ }
+ if (s.equals("bar")) {
+ d = 49;
+ s += b;
+ } else {
+ b = 63;
+ s = "barbar" + b;
+ }
+
+ if (a < 22) {
+ b = a * 42 / y;
+ c = b - 80;
+ d = a + b + c * y - x * a;
+ s = "foobar";
+ } else if (a < 42) {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "foo";
+ } else {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "bar";
+ }
+ if (s.equals("bar")) {
+ d = 49;
+ s += b;
+ } else {
+ b = 63;
+ s = "barbar" + b;
+ }
+
+ return a + b - c * x;
+ }
+}
diff --git a/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/R8Activity.java b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/R8Activity.java
index a80cf55..307cac9 100644
--- a/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/R8Activity.java
+++ b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/R8Activity.java
@@ -8,33 +8,201 @@
import android.os.Bundle;
import com.android.tools.r8.sample.split.R;
import com.android.tools.r8.sample.split.SplitClass;
+import java.util.ArrayList;
+import java.util.List;
+
public class R8Activity extends Activity {
+ // Enables easy splitting of iterations to better see effect of jit in later versions of art
+ public static final int ITERATIONS = 100000;
+ public static final int SPLITS = 1;
+
private int res = 0;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(android.R.style.Theme_Light);
setContentView(R.layout.main);
- // Currently this is split up into 100 iterations to be able to better see
- // the impact of the jit on later versions of art.
long total = 0;
- for (int i = 0; i < 100; i++) {
+ for (int i = 0; i < SPLITS; i++) {
+ total += benchmarkCallBaseline();
+ }
+ System.out.println("CallBaseline Total: " + total);
+
+ total = 0;
+ for (int i = 0; i < SPLITS; i++) {
total += benchmarkCall();
}
- System.out.println("Total: " + total);
+ System.out.println("Call Total: " + total);
+
+ total = 0;
+ for (int i = 0; i < SPLITS; i++) {
+ total += benchmarkCallLocal();
+ }
+ System.out.println("CallLocal Total: " + total);
+
+ total = 0;
+ for (int i = 0; i < SPLITS; i++) {
+ total += benchmarkSplitCallback();
+ }
+ System.out.println("Callback Total: " + total);
+
+ total = 0;
+ for (int i = 0; i < SPLITS; i++) {
+ total += benchmarkConstructor();
+ }
+ System.out.println("Constructor Total: " + total);
+
+ total = 0;
+ for (int i = 0; i < SPLITS; i++) {
+ total += benchmarkConstructorLocal();
+ }
+ System.out.println("ConstructorLocal Total: " + total);
+
+ total = 0;
+ for (int i = 0; i < SPLITS; i++) {
+ total += benchmarkInheritanceConstructor();
+ }
+ System.out.println("InheritanceConstructor Total: " + total);
+
+ total = 0;
+ for (int i = 0; i < SPLITS; i++) {
+ total += benchmarkLargeMethodCall();
+ }
+ System.out.println("LargeMethodCall Total: " + total);
+
+ total = 0;
+ for (int i = 0; i < SPLITS; i++) {
+ total += benchmarkSplitCallbackLong();
+ }
+ System.out.println("CallbackLarge Total: " + total);
+
+ total = 0;
+ for (int i = 0; i < SPLITS; i++) {
+ total += benchmarkLargeMethodCallLocally();
+ }
+ System.out.println("LargeMethodCallLocal Total: " + total);
+
}
- public long benchmarkCall() {
+ private long benchmarkCall() {
SplitClass split = new SplitClass(3);
long start = System.nanoTime();
- for (int i = 0; i < 1000; i++) {
+ for (int i = 0; i < ITERATIONS / SPLITS; i++) {
// Ensure no dead code elimination.
res = split.calculate(i);
}
long finish = System.nanoTime();
- long timeElapsed = finish - start;
- System.out.println("Took: " + timeElapsed);
+ long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
+
+ private long benchmarkCallLocal() {
+ long start = System.nanoTime();
+ for (int i = 0; i < ITERATIONS / SPLITS; i++) {
+ // Ensure no dead code elimination.
+ res = calculate(i);
+ }
+ long finish = System.nanoTime();
+ long timeElapsed = (finish - start) / 1000;
+ return timeElapsed;
+ }
+
+ private long benchmarkCallBaseline() {
+ SplitClass split = new SplitClass(3);
+ long start = System.nanoTime();
+ for (int i = 0; i < ITERATIONS / SPLITS; i++) {
+ int result = 2;
+ for (int j = 0; j < 42; j++) {
+ result += result + i;
+ }
+ res = result;
+ }
+ long finish = System.nanoTime();
+ long timeElapsed = (finish - start) / 1000;
+ return timeElapsed;
+ }
+
+ private long benchmarkInheritanceConstructor() {
+ List<SplitInheritBase> instances = new ArrayList<SplitInheritBase>();
+ long start = System.nanoTime();
+ for (int i = 0; i < ITERATIONS / SPLITS; i++) {
+ instances.add(new SplitInheritBase(i));
+ }
+ long finish = System.nanoTime();
+ long timeElapsed = (finish - start) / 1000;
+ return timeElapsed;
+ }
+
+ private long benchmarkConstructor() {
+ List<SplitClass> instances = new ArrayList<SplitClass>();
+ long start = System.nanoTime();
+ for (int i = 0; i < ITERATIONS / SPLITS; i++) {
+ instances.add(new SplitClass(i));
+ }
+ long finish = System.nanoTime();
+ long timeElapsed = (finish - start) / 1000;
+ return timeElapsed;
+ }
+
+ private long benchmarkConstructorLocal() {
+ List<BaseClass> instances = new ArrayList<BaseClass>();
+ long start = System.nanoTime();
+ for (int i = 0; i < ITERATIONS / SPLITS; i++) {
+ instances.add(new BaseClass(i));
+ }
+ long finish = System.nanoTime();
+ long timeElapsed = (finish - start) / 1000;
+ return timeElapsed;
+ }
+
+ private long benchmarkLargeMethodCall() {
+ SplitClass split = new SplitClass(3);
+ long start = System.nanoTime();
+ for (int i = 0; i < ITERATIONS / SPLITS; i++) {
+ // Ensure no dead code elimination.
+ res = split.largeMethod(i, i + 1);
+ }
+ long finish = System.nanoTime();
+ long timeElapsed = (finish - start) / 1000;
+ return timeElapsed;
+ }
+
+ private long benchmarkSplitCallback() {
+ SplitClass split = new SplitClass(3);
+ long start = System.nanoTime();
+ res = split.callBase();
+ long finish = System.nanoTime();
+ long timeElapsed = (finish - start) / 1000;
+ return timeElapsed;
+ }
+
+ private long benchmarkSplitCallbackLong() {
+ SplitClass split = new SplitClass(3);
+ long start = System.nanoTime();
+ res = split.callBaseLarge();
+ long finish = System.nanoTime();
+ long timeElapsed = (finish - start) / 1000;
+ return timeElapsed;
+ }
+
+ private long benchmarkLargeMethodCallLocally() {
+ BaseClass base = new BaseClass(3);
+ long start = System.nanoTime();
+ for (int i = 0; i < ITERATIONS / SPLITS; i++) {
+ // Ensure no dead code elimination.
+ res = base.largeMethod(i, i + 1);
+ }
+ long finish = System.nanoTime();
+ long timeElapsed = (finish - start) / 1000;
+ return timeElapsed;
+ }
+
+ public int calculate(int x) {
+ int result = 2;
+ for (int i = 0; i < 42; i++) {
+ result += res + x;
+ }
+ return result;
+ }
}
diff --git a/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitClass.java b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitClass.java
index 9b6990d..b493326 100644
--- a/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitClass.java
+++ b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitClass.java
@@ -4,13 +4,17 @@
package com.android.tools.r8.sample.split;
+import com.android.tools.r8.sample.split.R8Activity;
+
public class SplitClass {
- final int initialValue;
+ int initialValue;
public SplitClass(int initialValue) {
this.initialValue = initialValue;
}
+
+
public int calculate(int x) {
int result = 2;
for (int i = 0; i < 42; i++) {
@@ -18,4 +22,104 @@
}
return result;
}
+
+ public int largeMethod(int x, int y) {
+ int a = x + y;
+ int b;
+ int c;
+ double d;
+ String s;
+ if (a < 22) {
+ b = a * 42 / y;
+ c = b - 80;
+ d = a + b + c * y - x * a;
+ s = "foobar";
+ } else if (a < 42) {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "foo";
+ } else {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "bar";
+ }
+ if (s.equals("bar")) {
+ d = 49;
+ s += b;
+ } else {
+ b = 63;
+ s = "barbar" + b;
+ }
+
+ if (a < 22) {
+ b = a * 42 / y;
+ c = b - 80;
+ d = a + b + c * y - x * a;
+ s = "foobar";
+ } else if (a < 42) {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "foo";
+ } else {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "bar";
+ }
+ if (s.equals("bar")) {
+ d = 49;
+ s += b;
+ } else {
+ b = 63;
+ s = "barbar" + b;
+ }
+
+ if (a < 22) {
+ b = a * 42 / y;
+ c = b - 80;
+ d = a + b + c * y - x * a;
+ s = "foobar";
+ } else if (a < 42) {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "foo";
+ } else {
+ b = x * 42 / y;
+ c = b - 850;
+ d = a + b + c * x - x * a;
+ s = "bar";
+ }
+ if (s.equals("bar")) {
+ d = 49;
+ s += b;
+ } else {
+ b = 63;
+ s = "barbar" + b;
+ }
+
+ return a + b - c * x;
+ }
+
+ public int callBase() {
+ BaseClass base = new BaseClass(initialValue);
+ for (int i = 0; i < R8Activity.ITERATIONS / R8Activity.SPLITS; i++) {
+ // Ensure no dead code elimination.
+ initialValue = base.calculate(i);
+ }
+ return initialValue;
+ }
+
+ public int callBaseLarge() {
+ BaseClass base = new BaseClass(initialValue);
+ for (int i = 0; i < R8Activity.ITERATIONS / R8Activity.SPLITS; i++) {
+ // Ensure no dead code elimination.
+ initialValue = base.largeMethod(i, i + 1);
+ }
+ return initialValue;
+ }
+
}
diff --git a/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitInheritBase.java b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitInheritBase.java
new file mode 100644
index 0000000..6c5ed1e
--- /dev/null
+++ b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitInheritBase.java
@@ -0,0 +1,17 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.sample.split;
+
+public class SplitInheritBase extends BaseClass {
+
+ public SplitInheritBase(int initialValue) {
+ super(initialValue);
+ initialValue = calculate(initialValue);
+ }
+
+ public int calculate(int x) {
+ return super.calculate(x) * 2;
+ }
+}
diff --git a/tools/build_sample_apk.py b/tools/build_sample_apk.py
index 90e34ed..b74356b 100755
--- a/tools/build_sample_apk.py
+++ b/tools/build_sample_apk.py
@@ -26,7 +26,7 @@
DEFAULT_KEYSTORE = os.path.join(os.getenv('HOME'), '.android', 'debug.keystore')
PACKAGE_PREFIX = 'com.android.tools.r8.sample'
STANDARD_ACTIVITY = "R8Activity"
-BENCHMARK_ITERATIONS = 100
+BENCHMARK_ITERATIONS = 30
SAMPLE_APKS = [
'simple',
@@ -161,11 +161,15 @@
utils.PrintCmd(command)
subprocess.check_call(command)
-def run_adb(args):
+def run_adb(args, ignore_exit=False):
command = ['adb']
command.extend(args)
utils.PrintCmd(command)
- subprocess.check_call(command)
+ # On M adb install-multiple exits 1 but succeed in installing.
+ if ignore_exit:
+ subprocess.call(command)
+ else:
+ subprocess.check_call(command)
def adb_install(apks):
args = [
@@ -173,7 +177,7 @@
'-r',
'-d']
args.extend(apks)
- run_adb(args)
+ run_adb(args, ignore_exit=True)
def create_temp_apk(app, prefix):
temp_apk_path = os.path.join(get_bin_path(app), '%s.ap_' % app)
@@ -192,7 +196,7 @@
run_adb(args)
def start_logcat():
- return subprocess.Popen(['adb', 'logcat'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ return subprocess.Popen(['adb', 'logcat'], bufsize=1024*1024, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def start(app):
args = ['shell', 'am', 'start', '-n', get_qualified_activity(app)]
@@ -211,34 +215,35 @@
return lines
def store_or_print_benchmarks(lines, output):
- single_runs = []
- total_time = None
- # We assume that the individual runs are prefixed with 'Took: ' and the total time is
- # prefixed with 'Total: '. The logcat lines looks like:
- # 06-28 12:22:00.991 13698 13698 I System.out: Took: 61614
+ results = {}
+ overall_total = 0
+ # We assume that the total times are
+ # prefixed with 'NAME Total: '. The logcat lines looks like:
+ # 06-28 12:22:00.991 13698 13698 I System.out: Call Total: 61614
for l in lines:
- if 'Took: ' in l:
- timing = l.split('Took: ')[1]
- single_runs.append(timing)
if 'Total: ' in l:
- timing = l.split('Total: ')[1]
- total_time = timing
- assert len(single_runs) > 0
- assert total_time
- if not output:
- print 'Individual timings: \n%s' % ''.join(single_runs)
- print 'Total time: \n%s' % total_time
- return
+ split = l.split('Total: ')
+ time = split[1]
+ name = split[0].split()[-1]
+ overall_total += int(time)
+ print '%s: %s' % (name, time)
+ results[name] = time
+ print 'Total: %s' % overall_total
+ if not output:
+ return overall_total
+ results['total'] = str(overall_total)
output_dir = os.path.join(output, str(uuid.uuid4()))
os.makedirs(output_dir)
- single_run_file = os.path.join(output_dir, 'single_runs')
- with open(single_run_file, 'w') as f:
- f.writelines(single_runs)
- total_file = os.path.join(output_dir, 'total')
- with open(total_file, 'w') as f:
- f.write(total_time)
- print 'Result stored in %s and %s' % (single_run_file, total_file)
+ written_files = []
+ for name, time in results.iteritems():
+ total_file = os.path.join(output_dir, name)
+ written_files.append(total_file)
+ with open(total_file, 'w') as f:
+ f.write(time)
+
+ print 'Result stored in: \n%s' % ('\n'.join(written_files))
+ return overall_total
def benchmark(app, output_dir):
# Ensure app is not running
@@ -248,9 +253,14 @@
start(app)
# We could do better here by continiously parsing the logcat for a marker, but
# this works nicely with the current setup.
- time.sleep(3)
+ time.sleep(8)
kill(app)
- store_or_print_benchmarks(stop_logcat(logcat), output_dir)
+ return float(store_or_print_benchmarks(stop_logcat(logcat), output_dir))
+
+def ensure_no_logcat():
+ output = subprocess.check_output(['ps', 'aux'])
+ if 'adb logcat' in output:
+ raise Exception('You have adb logcat running, please close it and rerun')
def Main():
(options, args) = parse_options()
@@ -283,11 +293,14 @@
apks.append(split_apk_path)
print('Generated apks available at: %s' % ' '.join(apks))
- if options.install:
+ if options.install or options.benchmark:
adb_install(apks)
+ grand_total = 0
if options.benchmark:
+ ensure_no_logcat()
for _ in range(BENCHMARK_ITERATIONS):
- benchmark(options.app, options.benchmark_output_dir)
+ grand_total += benchmark(options.app, options.benchmark_output_dir)
+ print 'Combined average: %s' % (grand_total/BENCHMARK_ITERATIONS)
if __name__ == '__main__':
sys.exit(Main())
diff --git a/tools/track_memory.sh b/tools/track_memory.sh
index c0b4716..4629d4b 100755
--- a/tools/track_memory.sh
+++ b/tools/track_memory.sh
@@ -16,7 +16,7 @@
function Exit {
kill $lid
- exit 0
+ exit $code
}
function Kill {
@@ -41,3 +41,4 @@
trap "Exit" EXIT
trap "Kill" SIGINT
wait $pid
+code=$?