Merge commit 'ce97caf83654441074df1d25070f94ef3251971a' into dev-release
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 3cd04b1..c443620 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexProgramClass;
@@ -33,7 +32,6 @@
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.InternalOptions.DesugarState;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
@@ -167,10 +165,7 @@
DexApplication app = new ApplicationReader(inputApp, options, timing).read(executor);
PrefixRewritingMapper rewritePrefix =
options.desugaredLibraryConfiguration.createPrefixRewritingMapper(options);
- AppInfo appInfo =
- options.desugarState == DesugarState.ON
- ? new AppInfoWithClassHierarchy(app)
- : new AppInfo(app);
+ AppInfo appInfo = new AppInfo(app);
final CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 5c815bc..5781482 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -405,8 +405,6 @@
assert !internal.enableLambdaMerging;
assert !internal.enableTreeShakingOfLibraryMethodOverrides;
- // TODO(b/137168535) Disable non-null tracking for now.
- internal.enableNonNullTracking = false;
internal.desugarState = getDesugarState();
internal.encodeChecksums = getIncludeClassesChecksum();
internal.dexClassChecksumFilter = getDexClassChecksumFilter();
diff --git a/src/main/java/com/android/tools/r8/ExtractMarker.java b/src/main/java/com/android/tools/r8/ExtractMarker.java
index bda3597..0b1fead 100644
--- a/src/main/java/com/android/tools/r8/ExtractMarker.java
+++ b/src/main/java/com/android/tools/r8/ExtractMarker.java
@@ -26,7 +26,6 @@
import java.util.Collection;
import java.util.concurrent.ExecutionException;
-@Keep
public class ExtractMarker {
public static class VdexOrigin extends Origin {
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index dea3bb8..4ba88f4 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.GraphLense;
@@ -122,7 +121,7 @@
options.desugaredLibraryConfiguration.createPrefixRewritingMapper(options);
app = new L8TreePruner(options).prune(app, rewritePrefix);
- AppInfo appInfo = new AppInfoWithClassHierarchy(app);
+ AppInfo appInfo = new AppInfo(app);
AppView<?> appView = AppView.createForL8(appInfo, options, rewritePrefix);
IRConverter converter = new IRConverter(appView, timing);
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index ff26467..b1072df 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -174,8 +174,6 @@
assert !internal.enableLambdaMerging;
assert !internal.enableTreeShakingOfLibraryMethodOverrides;
- // TODO(b/137168535) Disable non-null tracking for now.
- internal.enableNonNullTracking = false;
assert internal.desugarState == DesugarState.ON;
assert internal.enableInheritanceClassInDexDistributor;
internal.enableInheritanceClassInDexDistributor = false;
diff --git a/src/main/java/com/android/tools/r8/PrintUses.java b/src/main/java/com/android/tools/r8/PrintUses.java
index 9a26221..5fe37ab 100644
--- a/src/main/java/com/android/tools/r8/PrintUses.java
+++ b/src/main/java/com/android/tools/r8/PrintUses.java
@@ -100,7 +100,7 @@
@Override
public boolean registerInvokeVirtual(DexMethod method) {
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.unsafeResolveMethodDueToDexFormat(method);
DexEncodedMethod target =
resolutionResult.isVirtualTarget() ? resolutionResult.getSingleTarget() : null;
if (target != null && target.method != method) {
@@ -203,9 +203,7 @@
private void addField(DexField field, boolean isStatic) {
addType(field.type);
DexEncodedField baseField =
- isStatic
- ? appInfo.lookupStaticTarget(field.holder, field)
- : appInfo.lookupInstanceTarget(field.holder, field);
+ isStatic ? appInfo.lookupStaticTarget(field) : appInfo.lookupInstanceTarget(field);
if (baseField != null && baseField.holder() != field.holder) {
field = baseField.field;
}
@@ -250,7 +248,7 @@
private void registerMethod(ProgramMethod method) {
DexEncodedMethod superTarget =
appInfo
- .resolveMethod(method.getHolder(), method.getReference())
+ .resolveMethodOn(method.getHolder(), method.getReference())
.lookupInvokeSpecialTarget(context, appInfo);
if (superTarget != null) {
addMethod(superTarget.method);
@@ -275,7 +273,8 @@
// If clazz overrides any methods in superType, we should keep those as well.
clazz.forEachMethod(
method -> {
- ResolutionResult resolutionResult = appInfo.resolveMethod(superType, method.method);
+ ResolutionResult resolutionResult =
+ appInfo.resolveMethodOn(superType, method.method, superType != clazz.superType);
DexEncodedMethod dexEncodedMethod = resolutionResult.getSingleTarget();
if (dexEncodedMethod != null) {
addMethod(dexEncodedMethod.method);
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 51b0aaf..382dd08 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -50,7 +50,6 @@
import com.android.tools.r8.ir.optimize.enums.EnumValueInfoMapCollector;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
import com.android.tools.r8.jar.CfApplicationWriter;
-import com.android.tools.r8.kotlin.KotlinInfoCollector;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.Minifier;
import com.android.tools.r8.naming.NamingLens;
@@ -318,11 +317,6 @@
}
}
- // Compute kotlin info before setting the roots and before
- // kotlin metadata annotation is removed.
- KotlinInfoCollector.computeKotlinInfoForProgramClasses(
- application, appView, executorService);
-
// Add synthesized -assumenosideeffects from min api if relevant.
if (options.isGeneratingDex()) {
if (!ProguardConfigurationUtils.hasExplicitAssumeValuesOrAssumeNoSideEffectsRuleForMinSdk(
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
index e9997b0..6f4e958 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.ValueType;
@@ -167,8 +167,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forBinop();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
index 85c4773..1290256 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -43,8 +43,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forArrayLength();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
index 010bcfd..02e20ea 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.ValueType;
@@ -88,8 +88,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forArrayGet();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
index 52df928..1976942 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -78,8 +78,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forArrayPut();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
index 19ca32e..a46e68c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
@@ -40,7 +42,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
registry.registerCheckCast(type);
}
@@ -59,8 +61,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
- return inliningConstraints.forCheckCast(type, invocationContext);
+ InliningConstraints inliningConstraints, DexProgramClass context) {
+ return inliningConstraints.forCheckCast(type, context);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
index 259bfe3..8d128be 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.Cmp;
import com.android.tools.r8.ir.code.Cmp.Bias;
@@ -92,8 +92,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forBinop();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
index a203742..05d8568 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
@@ -5,6 +5,8 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
@@ -71,7 +73,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
registry.registerConstClass(type);
}
@@ -82,8 +84,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
- return inliningConstraints.forConstClass(type, invocationContext);
+ InliningConstraints inliningConstraints, DexProgramClass context) {
+ return inliningConstraints.forConstClass(type, context);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
index 04e569b..89fae02 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
@@ -4,8 +4,9 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexMethodHandle;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.graph.UseRegistry.MethodHandleUse;
@@ -40,7 +41,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
registry.registerMethodHandle(handle, MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
}
@@ -58,8 +59,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forConstMethodHandle();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
index a67c3ed..8283278 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
@@ -4,8 +4,9 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -40,7 +41,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
registry.registerProto(type);
}
@@ -58,8 +59,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forConstMethodType();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
index c3be968..889a63c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -35,8 +35,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forConstInstruction();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
index da5d12a..5451986 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -133,8 +133,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forConstInstruction();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
index 08ee865..3b113cb 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -65,8 +65,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forConstInstruction();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
index fbc4939..94eadd1 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
@@ -5,8 +5,9 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -64,7 +65,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
if (nameComputationInfo.needsToRegisterReference()) {
assert item.isDexType();
registry.registerTypeReference(item.asDexType());
@@ -81,8 +82,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
- return inliningConstraints.forDexItemBasedConstString(item, invocationContext);
+ InliningConstraints inliningConstraints, DexProgramClass context) {
+ return inliningConstraints.forDexItemBasedConstString(item, context);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
index 5812288..7e31f5b 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
@@ -5,7 +5,9 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
@@ -64,7 +66,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
switch (opcode) {
case Opcodes.GETFIELD:
registry.registerInstanceFieldRead(field);
@@ -123,17 +125,16 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
switch (opcode) {
case Opcodes.GETSTATIC:
- return inliningConstraints.forStaticGet(field, invocationContext);
+ return inliningConstraints.forStaticGet(field, context);
case Opcodes.PUTSTATIC:
- return inliningConstraints.forStaticPut(field, invocationContext);
+ return inliningConstraints.forStaticPut(field, context);
case Opcodes.GETFIELD:
- return inliningConstraints.forInstanceGet(field, invocationContext);
+ return inliningConstraints.forInstanceGet(field, context);
case Opcodes.PUTFIELD:
- return inliningConstraints.forInstancePut(field, invocationContext);
+ return inliningConstraints.forInstancePut(field, context);
default:
throw new Unreachable("Unexpected opcode " + opcode);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
index 88d5ece..72f5be9 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -293,8 +294,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return ConstraintWithTarget.ALWAYS;
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
index 412c97c7..bbb8996 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -60,8 +60,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forJumpInstruction();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIf.java b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
index ebc6a98..a6d0fca 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.If.Type;
@@ -93,8 +93,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forJumpInstruction();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
index c2f34f7..24c81a5 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.If.Type;
@@ -94,8 +94,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forJumpInstruction();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
index 986d11f..4ce64a4 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -51,8 +51,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return ConstraintWithTarget.ALWAYS;
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
index a355f58..115d27a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
@@ -4,7 +4,9 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
@@ -49,7 +51,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType context) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
registry.registerInitClass(clazz);
}
@@ -66,7 +68,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType context) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forInitClass(clazz, context);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
index 5d0997f..ca6b7ed 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
@@ -49,7 +51,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
registry.registerTypeReference(type);
}
@@ -67,8 +69,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
- return inliningConstraints.forInstanceOf(type, invocationContext);
+ InliningConstraints inliningConstraints, DexProgramClass context) {
+ return inliningConstraints.forInstanceOf(type, context);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
index d3cc826..05f1181 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
@@ -4,8 +4,11 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ClasspathMethod;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -28,7 +31,15 @@
return printer.toString();
}
- public void registerUse(UseRegistry registry, DexType clazz) {
+ public void registerUse(UseRegistry registry, ProgramMethod context) {
+ internalRegisterUse(registry, context);
+ }
+
+ public void registerUseForDesugaring(UseRegistry registry, ClasspathMethod context) {
+ internalRegisterUse(registry, context);
+ }
+
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
// Intentionally empty.
}
@@ -153,6 +164,5 @@
}
public abstract ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext);
+ InliningConstraints inliningConstraints, DexProgramClass context);
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
index 1a5dd5c..1146ff2 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
@@ -83,7 +84,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
switch (opcode) {
case Opcodes.INVOKEINTERFACE:
registry.registerInvokeInterface(method);
@@ -94,7 +95,7 @@
case Opcodes.INVOKESPECIAL:
if (method.name.toString().equals(Constants.INSTANCE_INITIALIZER_NAME)) {
registry.registerInvokeDirect(method);
- } else if (method.holder == clazz) {
+ } else if (method.holder == context.getHolderType()) {
registry.registerInvokeDirect(method);
} else {
registry.registerInvokeSuper(method);
@@ -196,8 +197,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
GraphLense graphLense = inliningConstraints.getGraphLense();
AppView<?> appView = inliningConstraints.getAppView();
DexMethod target = method;
@@ -215,7 +215,7 @@
if (appView.dexItemFactory().isConstructor(target)) {
type = Type.DIRECT;
assert noNeedToUseGraphLense(target, type, graphLense);
- } else if (target.holder == invocationContext) {
+ } else if (target.holder == context.type) {
// The method could have been publicized.
type = graphLense.lookupMethod(target, null, Type.DIRECT).getType();
assert type == Type.DIRECT || type == Type.VIRTUAL;
@@ -232,37 +232,39 @@
}
break;
- case Opcodes.INVOKESTATIC: {
- // Static invokes may have changed as a result of horizontal class merging.
- GraphLenseLookupResult lookup = graphLense.lookupMethod(target, null, Type.STATIC);
- target = lookup.getMethod();
- type = lookup.getType();
- break;
- }
-
- case Opcodes.INVOKEVIRTUAL: {
- type = Type.VIRTUAL;
- // Instructions that target a private method in the same class translates to
- // invoke-direct.
- if (target.holder == invocationContext) {
- DexClass clazz = appView.definitionFor(target.holder);
- if (clazz != null && clazz.lookupDirectMethod(target) != null) {
- type = Type.DIRECT;
- }
+ case Opcodes.INVOKESTATIC:
+ {
+ // Static invokes may have changed as a result of horizontal class merging.
+ GraphLenseLookupResult lookup = graphLense.lookupMethod(target, null, Type.STATIC);
+ target = lookup.getMethod();
+ type = lookup.getType();
}
-
- // Virtual invokes may have changed to interface invokes as a result of member rebinding.
- GraphLenseLookupResult lookup = graphLense.lookupMethod(target, null, type);
- target = lookup.getMethod();
- type = lookup.getType();
break;
- }
+
+ case Opcodes.INVOKEVIRTUAL:
+ {
+ type = Type.VIRTUAL;
+ // Instructions that target a private method in the same class translates to
+ // invoke-direct.
+ if (target.holder == context.type) {
+ DexClass clazz = appView.definitionFor(target.holder);
+ if (clazz != null && clazz.lookupDirectMethod(target) != null) {
+ type = Type.DIRECT;
+ }
+ }
+
+ // Virtual invokes may have changed to interface invokes as a result of member rebinding.
+ GraphLenseLookupResult lookup = graphLense.lookupMethod(target, null, type);
+ target = lookup.getMethod();
+ type = lookup.getType();
+ }
+ break;
default:
throw new Unreachable("Unexpected opcode " + opcode);
}
- return inliningConstraints.forInvoke(target, type, invocationContext);
+ return inliningConstraints.forInvoke(target, type, context);
}
private static boolean noNeedToUseGraphLense(
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
index 458bc23..fac04cd 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
@@ -6,7 +6,9 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexCallSite;
+import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexMethodHandle;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
@@ -82,7 +84,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
registry.registerCallSite(callSite);
}
@@ -110,8 +112,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forInvokeCustom();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
index 7e678dc..2fc78ea 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -45,7 +45,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
throw error();
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
index 3901a1a..6cc49de 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -58,8 +58,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return ConstraintWithTarget.ALWAYS;
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
index 80d6a8e..0680d73 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -87,8 +87,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forLoad();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
index c2775a0..f34a7d7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.ValueType;
@@ -139,8 +139,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forBinop();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
index 6386b3c..7fd0167 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.Monitor.Type;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -52,8 +52,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forMonitor();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
index d12d76b..1f787f8 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
@@ -45,7 +47,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
registry.registerTypeReference(type);
}
@@ -64,8 +66,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
- return inliningConstraints.forInvokeMultiNewArray(type, invocationContext);
+ InliningConstraints inliningConstraints, DexProgramClass context) {
+ return inliningConstraints.forInvokeMultiNewArray(type, context);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
index 02b2a83..cd61c29 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.ValueType;
@@ -81,8 +81,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forUnop();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNew.java b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
index be087af..8bd1249 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNew.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
@@ -39,7 +41,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
registry.registerNewInstance(type);
}
@@ -55,8 +57,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
- return inliningConstraints.forNewInstance(type, invocationContext);
+ InliningConstraints inliningConstraints, DexProgramClass context) {
+ return inliningConstraints.forNewInstance(type, context);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
index 1ce6048..9ef5f1b 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
@@ -5,6 +5,8 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
@@ -78,7 +80,7 @@
}
@Override
- public void registerUse(UseRegistry registry, DexType clazz) {
+ void internalRegisterUse(UseRegistry registry, DexClassAndMethod context) {
if (!type.isPrimitiveArrayType()) {
registry.registerTypeReference(type);
}
@@ -98,8 +100,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
- return inliningConstraints.forNewArrayEmpty(type, invocationContext);
+ InliningConstraints inliningConstraints, DexProgramClass context) {
+ return inliningConstraints.forNewArrayEmpty(type, context);
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNop.java b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
index be9170c..4578bff 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -39,8 +39,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return ConstraintWithTarget.ALWAYS;
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
index dbedc8a..afbff92 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.ValueType;
@@ -152,8 +152,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forUnop();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
index 2dac0c6..93febbb 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -67,8 +67,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return ConstraintWithTarget.ALWAYS;
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
index e1b6de1..5934617 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -75,8 +75,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forReturn();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
index 0bbe1cd..c9d7f51 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -44,8 +44,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forReturn();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
index 5821c3f..ef291d0 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
@@ -6,7 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -315,8 +315,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return ConstraintWithTarget.ALWAYS;
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStore.java b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
index d560b82..d8f13d1 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
@@ -86,8 +86,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forStore();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
index bfbe30f..3169da0 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -103,8 +103,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forJumpInstruction();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
index c0c094d..9b88cb5 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
@@ -46,8 +46,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints,
- DexType invocationContext) {
+ InliningConstraints inliningConstraints, DexProgramClass context) {
return inliningConstraints.forJumpInstruction();
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index ef53aaa..0b5d100 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -3,28 +3,17 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import com.android.tools.r8.graph.ResolutionResult.ArrayCloneMethodResult;
-import com.android.tools.r8.graph.ResolutionResult.ClassNotFoundResult;
-import com.android.tools.r8.graph.ResolutionResult.IllegalAccessOrNoSuchMethodResult;
-import com.android.tools.r8.graph.ResolutionResult.IncompatibleClassResult;
-import com.android.tools.r8.graph.ResolutionResult.NoSuchMethodResult;
-import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
+import com.android.tools.r8.graph.FieldResolutionResult.SuccessfulFieldResolutionResult;
import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
-import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.ListUtils;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
public class AppInfo implements DexDefinitionSupplier {
@@ -33,29 +22,44 @@
private final DexItemFactory dexItemFactory;
// TODO(b/151804585): Remove this cache.
- private final ConcurrentHashMap<DexType, Map<DexField, DexEncodedField>> fieldDefinitionsCache =
- new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<DexType, Map<DexField, DexEncodedField>> fieldDefinitionsCache;
// For some optimizations, e.g. optimizing synthetic classes, we may need to resolve the current
// class being optimized.
- private final ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses =
- new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses;
// Set when a new AppInfo replaces a previous one. All public methods should verify that the
// current instance is not obsolete, to ensure that we almost use the most recent AppInfo.
- private boolean obsolete;
+ private final BooleanBox obsolete;
public AppInfo(DexApplication application) {
- this.app = application;
- this.dexItemFactory = app.dexItemFactory;
+ this(application, new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), new BooleanBox());
}
- protected AppInfo(AppInfo previous) {
- assert !previous.isObsolete();
- this.app = previous.app;
- this.dexItemFactory = app.dexItemFactory;
- this.fieldDefinitionsCache.putAll(previous.fieldDefinitionsCache);
- copyMetadataFromPrevious(previous);
+ // For desugaring.
+ protected AppInfo(AppInfo appInfo) {
+ this(appInfo.app, appInfo.fieldDefinitionsCache, appInfo.synthesizedClasses, appInfo.obsolete);
+ }
+
+ // For AppInfoWithLiveness.
+ protected AppInfo(AppInfoWithClassHierarchy previous) {
+ this(
+ ((AppInfo) previous).app,
+ new ConcurrentHashMap<>(((AppInfo) previous).fieldDefinitionsCache),
+ new ConcurrentHashMap<>(((AppInfo) previous).synthesizedClasses),
+ new BooleanBox());
+ }
+
+ private AppInfo(
+ DexApplication application,
+ ConcurrentHashMap<DexType, Map<DexField, DexEncodedField>> fieldDefinitionsCache,
+ ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses,
+ BooleanBox obsolete) {
+ this.app = application;
+ this.dexItemFactory = application.dexItemFactory;
+ this.fieldDefinitionsCache = fieldDefinitionsCache;
+ this.synthesizedClasses = synthesizedClasses;
+ this.obsolete = obsolete;
}
protected InternalOptions options() {
@@ -67,15 +71,15 @@
}
public boolean isObsolete() {
- return obsolete;
+ return obsolete.get();
}
public void markObsolete() {
- obsolete = true;
+ obsolete.set();
}
public void unsetObsolete() {
- obsolete = false;
+ obsolete.unset();
}
public boolean checkIfObsolete() {
@@ -205,31 +209,19 @@
fieldDefinitionsCache.remove(type);
}
- // TODO(b/147578480): Temporary API since most of the code base use a type instead
- // of a DexProgramClass as the invocationContext.
- DexProgramClass toProgramClass(DexType type) {
- assert type.isClassType();
- return DexProgramClass.asProgramClassOrNull(definitionFor(type));
- }
-
/**
* Lookup static method on the method holder, or answers null.
*
* @param method the method to lookup
- * @param invocationContext the class the invoke is contained in, i.e., the holder of the caller.
+ * @param context the method the invoke is contained in, i.e., the caller.
* @return The actual target for {@code method} if on the holder, or {@code null}.
*/
- @Deprecated // TODO(b/147578480): Remove
- public DexEncodedMethod lookupStaticTargetOnItself(DexMethod method, DexType invocationContext) {
- return lookupStaticTargetOnItself(method, toProgramClass(invocationContext));
- }
-
public final DexEncodedMethod lookupStaticTargetOnItself(
- DexMethod method, DexProgramClass invocationContext) {
- if (method.holder != invocationContext.type) {
+ DexMethod method, ProgramMethod context) {
+ if (method.holder != context.getHolderType()) {
return null;
}
- DexEncodedMethod singleTarget = invocationContext.lookupDirectMethod(method);
+ DexEncodedMethod singleTarget = context.getHolder().lookupDirectMethod(method);
if (singleTarget != null && singleTarget.isStatic()) {
return singleTarget;
}
@@ -240,334 +232,21 @@
* Lookup direct method on the method holder, or answers null.
*
* @param method the method to lookup
- * @param invocationContext the class the invoke is contained in, i.e., the holder of the caller.
+ * @param context the method the invoke is contained in, i.e., the caller.
* @return The actual target for {@code method} if on the holder, or {@code null}.
*/
- @Deprecated // TODO(b/147578480): Remove
- public DexEncodedMethod lookupDirectTargetOnItself(DexMethod method, DexType invocationContext) {
- return lookupDirectTargetOnItself(method, toProgramClass(invocationContext));
- }
-
public final DexEncodedMethod lookupDirectTargetOnItself(
- DexMethod method, DexProgramClass invocationContext) {
- if (method.holder != invocationContext.type) {
+ DexMethod method, ProgramMethod context) {
+ if (method.holder != context.getHolderType()) {
return null;
}
- DexEncodedMethod singleTarget = invocationContext.lookupDirectMethod(method);
+ DexEncodedMethod singleTarget = context.getHolder().lookupDirectMethod(method);
if (singleTarget != null && !singleTarget.isStatic()) {
return singleTarget;
}
return null;
}
- /**
- * Implements resolution of a method descriptor against a target type.
- *
- * <p>This method will query the definition of the holder to decide on which resolution to use. If
- * the holder is an interface, it delegates to {@link #resolveMethodOnInterface(DexType,
- * DexMethod)}, otherwise {@link #resolveMethodOnClass(DexType, DexMethod)} is used.
- *
- * <p>This is to overcome the shortcoming of the DEX file format that does not allow to encode the
- * kind of a method reference.
- */
- public ResolutionResult resolveMethod(DexType holder, DexMethod method) {
- assert checkIfObsolete();
- if (holder.isArrayType()) {
- return resolveMethodOnArray(holder, method);
- }
- DexClass definition = definitionFor(holder);
- if (definition == null) {
- return ClassNotFoundResult.INSTANCE;
- }
- return resolveMethod(definition, method);
- }
-
- public ResolutionResult resolveMethod(DexClass holder, DexMethod method) {
- return holder.isInterface()
- ? resolveMethodOnInterface(holder, method)
- : resolveMethodOnClass(holder, method);
- }
-
- /**
- * Implements resolution of a method descriptor against a target type.
- *
- * <p>The boolean isInterface parameter denotes if the method reference is an interface method
- * reference, and if so method resolution is done according to interface method resolution.
- *
- * @param holder Type at which to initiate the resolution.
- * @param method Method descriptor for resolution (the field method.holder is ignored).
- * @param isInterface Indicates if resolution is to be done according to class or interface.
- * @return The result of resolution.
- */
- public ResolutionResult resolveMethod(DexType holder, DexMethod method, boolean isInterface) {
- assert checkIfObsolete();
- return isInterface
- ? resolveMethodOnInterface(holder, method)
- : resolveMethodOnClass(holder, method);
- }
-
- /**
- * Implements resolution of a method descriptor against an array type.
- *
- * <p>See <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html#jls-10.7">Section
- * 10.7 of the Java Language Specification</a>. All invokations will have target java.lang.Object
- * except clone which has no target.
- */
- private ResolutionResult resolveMethodOnArray(DexType holder, DexMethod method) {
- assert checkIfObsolete();
- assert holder.isArrayType();
- if (method.name == dexItemFactory.cloneMethodName) {
- return ArrayCloneMethodResult.INSTANCE;
- } else {
- return resolveMethodOnClass(dexItemFactory.objectType, method);
- }
- }
-
- /**
- * Implements resolution of a method descriptor against a class type.
- * <p>
- * See <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">
- * Section 5.4.3.3 of the JVM Spec</a>.
- * <p>
- * The resolved method is not the method that will actually be invoked. Which methods gets
- * invoked depends on the invoke instruction used. However, it is always safe to rewrite
- * any invoke on the given descriptor to a corresponding invoke on the resolved descriptor, as the
- * resolved method is used as basis for dispatch.
- */
- public ResolutionResult resolveMethodOnClass(DexType holder, DexMethod method) {
- assert checkIfObsolete();
- if (holder.isArrayType()) {
- return resolveMethodOnArray(holder, method);
- }
- DexClass clazz = definitionFor(holder);
- if (clazz == null) {
- return ClassNotFoundResult.INSTANCE;
- }
- // Step 1: If holder is an interface, resolution fails with an ICCE. We return null.
- if (clazz.isInterface()) {
- return IncompatibleClassResult.INSTANCE;
- }
- return resolveMethodOnClass(clazz, method);
- }
-
- public ResolutionResult resolveMethodOnClass(DexClass clazz, DexMethod method) {
- assert checkIfObsolete();
- assert !clazz.isInterface();
- // Step 2:
- ResolutionResult result = resolveMethodOnClassStep2(clazz, method, clazz);
- if (result != null) {
- return result;
- }
- // Finally Step 3:
- return resolveMethodStep3(clazz, method);
- }
-
- /**
- * Implements step 2 of method resolution on classes as per <a
- * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">Section
- * 5.4.3.3 of the JVM Spec</a>.
- */
- private ResolutionResult resolveMethodOnClassStep2(
- DexClass clazz, DexMethod method, DexClass initialResolutionHolder) {
- // Pt. 1: Signature polymorphic method check.
- // See also <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.9">
- // Section 2.9 of the JVM Spec</a>.
- DexEncodedMethod result = clazz.lookupSignaturePolymorphicMethod(method.name, dexItemFactory);
- if (result != null) {
- return new SingleResolutionResult(initialResolutionHolder, clazz, result);
- }
- // Pt 2: Find a method that matches the descriptor.
- result = clazz.lookupMethod(method);
- if (result != null) {
- // If the resolved method is private, then it can only be accessed if the symbolic reference
- // that initiated the resolution was the type at which the method resolved on. If that is not
- // the case, then the error is either an IllegalAccessError, or in the case where access is
- // allowed because of nests, a NoSuchMethodError. Which error cannot be determined without
- // knowing the calling context.
- if (result.isPrivateMethod() && clazz != initialResolutionHolder) {
- return new IllegalAccessOrNoSuchMethodResult(result);
- }
- return new SingleResolutionResult(initialResolutionHolder, clazz, result);
- }
- // Pt 3: Apply step two to direct superclass of holder.
- if (clazz.superType != null) {
- DexClass superClass = definitionFor(clazz.superType);
- if (superClass != null) {
- return resolveMethodOnClassStep2(superClass, method, initialResolutionHolder);
- }
- }
- return null;
- }
-
- /**
- * Implements step 3 of <a
- * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">Section
- * 5.4.3.3 of the JVM Spec</a>. As this is the same for interfaces and classes, we share one
- * implementation.
- */
- private ResolutionResult resolveMethodStep3(DexClass clazz, DexMethod method) {
- MaximallySpecificMethodsBuilder builder = new MaximallySpecificMethodsBuilder();
- resolveMethodStep3Helper(method, clazz, builder);
- return builder.resolve(clazz);
- }
-
- // Non-private lookup (ie, not resolution) to find interface targets.
- DexClassAndMethod lookupMaximallySpecificTarget(DexClass clazz, DexMethod method) {
- MaximallySpecificMethodsBuilder builder = new MaximallySpecificMethodsBuilder();
- resolveMethodStep3Helper(method, clazz, builder);
- return builder.lookup();
- }
-
- // Non-private lookup (ie, not resolution) to find interface targets.
- DexClassAndMethod lookupMaximallySpecificTarget(LambdaDescriptor lambda, DexMethod method) {
- MaximallySpecificMethodsBuilder builder = new MaximallySpecificMethodsBuilder();
- resolveMethodStep3Helper(method, dexItemFactory.objectType, lambda.interfaces, builder);
- return builder.lookup();
- }
-
- /** Helper method that builds the set of maximally specific methods. */
- private void resolveMethodStep3Helper(
- DexMethod method, DexClass clazz, MaximallySpecificMethodsBuilder builder) {
- resolveMethodStep3Helper(
- method, clazz.superType, Arrays.asList(clazz.interfaces.values), builder);
- }
-
- private void resolveMethodStep3Helper(
- DexMethod method,
- DexType superType,
- List<DexType> interfaces,
- MaximallySpecificMethodsBuilder builder) {
- for (DexType iface : interfaces) {
- DexClass definiton = definitionFor(iface);
- if (definiton == null) {
- // Ignore missing interface definitions.
- continue;
- }
- assert definiton.isInterface();
- DexEncodedMethod result = definiton.lookupMethod(method);
- if (isMaximallySpecificCandidate(result)) {
- // The candidate is added and doing so will prohibit shadowed methods from being in the set.
- builder.addCandidate(definiton, result, this);
- } else {
- // Look at the super-interfaces of this class and keep searching.
- resolveMethodStep3Helper(method, definiton, builder);
- }
- }
- // Now look at indirect super interfaces.
- if (superType != null) {
- DexClass superClass = definitionFor(superType);
- if (superClass != null) {
- resolveMethodStep3Helper(method, superClass, builder);
- }
- }
- }
-
- /**
- * A candidate for being a maximally specific method must have neither its private, nor its static
- * flag set. A candidate may still not be maximally specific, which entails that no subinterfaces
- * from also contribute with a candidate to the type. That is not determined by this method.
- */
- private boolean isMaximallySpecificCandidate(DexEncodedMethod method) {
- return method != null && !method.accessFlags.isPrivate() && !method.accessFlags.isStatic();
- }
-
- /**
- * Implements resolution of a method descriptor against an interface type.
- * <p>
- * See <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">
- * Section 5.4.3.4 of the JVM Spec</a>.
- * <p>
- * The resolved method is not the method that will actually be invoked. Which methods gets
- * invoked depends on the invoke instruction used. However, it is always save to rewrite
- * any invoke on the given descriptor to a corresponding invoke on the resolved descriptor, as the
- * resolved method is used as basis for dispatch.
- */
- public ResolutionResult resolveMethodOnInterface(DexType holder, DexMethod desc) {
- assert checkIfObsolete();
- if (holder.isArrayType()) {
- return IncompatibleClassResult.INSTANCE;
- }
- // Step 1: Lookup interface.
- DexClass definition = definitionFor(holder);
- // If the definition is not an interface, resolution fails with an ICCE. We just return the
- // empty result here.
- if (definition == null) {
- return ClassNotFoundResult.INSTANCE;
- }
- if (!definition.isInterface()) {
- return IncompatibleClassResult.INSTANCE;
- }
- return resolveMethodOnInterface(definition, desc);
- }
-
- public ResolutionResult resolveMethodOnInterface(DexClass definition, DexMethod desc) {
- assert checkIfObsolete();
- assert definition.isInterface();
- // Step 2: Look for exact method on interface.
- DexEncodedMethod result = definition.lookupMethod(desc);
- if (result != null) {
- return new SingleResolutionResult(definition, definition, result);
- }
- // Step 3: Look for matching method on object class.
- DexClass objectClass = definitionFor(dexItemFactory.objectType);
- if (objectClass == null) {
- return ClassNotFoundResult.INSTANCE;
- }
- result = objectClass.lookupMethod(desc);
- if (result != null && result.accessFlags.isPublic() && !result.accessFlags.isAbstract()) {
- return new SingleResolutionResult(definition, objectClass, result);
- }
- // Step 3: Look for maximally-specific superinterface methods or any interface definition.
- // This is the same for classes and interfaces.
- return resolveMethodStep3(definition, desc);
- }
-
- /**
- * Implements resolution of a field descriptor against the holder of the field. See also {@link
- * #resolveFieldOn}.
- */
- public DexEncodedField resolveField(DexField field) {
- assert checkIfObsolete();
- return resolveFieldOn(field.holder, field);
- }
-
- /**
- * Implements resolution of a field descriptor against a type.
- * <p>
- * See <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.2">
- * Section 5.4.3.2 of the JVM Spec</a>.
- */
- public DexEncodedField resolveFieldOn(DexType type, DexField desc) {
- assert checkIfObsolete();
- DexClass holder = definitionFor(type);
- return holder != null ? resolveFieldOn(holder, desc) : null;
- }
-
- public DexEncodedField resolveFieldOn(DexClass holder, DexField desc) {
- assert checkIfObsolete();
- assert holder != null;
- // Step 1: Class declares the field.
- DexEncodedField result = holder.lookupField(desc);
- if (result != null) {
- return result;
- }
- // Step 2: Apply recursively to direct superinterfaces. First match succeeds.
- for (DexType iface : holder.interfaces.values) {
- result = resolveFieldOn(iface, desc);
- if (result != null) {
- return result;
- }
- }
- // Step 3: Apply recursively to superclass.
- if (holder.superType != null) {
- result = resolveFieldOn(holder.superType, desc);
- if (result != null) {
- return result;
- }
- }
- return null;
- }
-
public boolean hasClassHierarchy() {
assert checkIfObsolete();
return false;
@@ -593,107 +272,19 @@
return app.mainDexList.contains(type);
}
- private static class MaximallySpecificMethodsBuilder {
-
- // The set of actual maximally specific methods.
- // This set is linked map so that in the case where a number of methods remain a deterministic
- // choice can be made. The map is from definition classes to their maximally specific method, or
- // in the case that a type has a candidate which is shadowed by a subinterface, the map will
- // map the class to a null entry, thus any addition to the map must check for key containment
- // prior to writing.
- LinkedHashMap<DexClass, DexEncodedMethod> maximallySpecificMethods = new LinkedHashMap<>();
-
- void addCandidate(DexClass holder, DexEncodedMethod method, AppInfo appInfo) {
- // If this candidate is already a candidate or it is shadowed, then no need to continue.
- if (maximallySpecificMethods.containsKey(holder)) {
- return;
- }
- maximallySpecificMethods.put(holder, method);
- // Prune exiting candidates and prohibit future candidates in the super hierarchy.
- assert holder.isInterface();
- assert holder.superType == appInfo.dexItemFactory.objectType;
- for (DexType iface : holder.interfaces.values) {
- markShadowed(iface, appInfo);
- }
- }
-
- private void markShadowed(DexType type, AppInfo appInfo) {
- if (type == null) {
- return;
- }
- DexClass clazz = appInfo.definitionFor(type);
- if (clazz == null) {
- return;
- }
- assert clazz.isInterface();
- assert clazz.superType == appInfo.dexItemFactory.objectType;
- // A null entry signifies that the candidate is shadowed blocking future candidates.
- // If the candidate is already shadowed at this type there is no need to shadow further up.
- if (maximallySpecificMethods.containsKey(clazz)
- && maximallySpecificMethods.get(clazz) == null) {
- return;
- }
- maximallySpecificMethods.put(clazz, null);
- for (DexType iface : clazz.interfaces.values) {
- markShadowed(iface, appInfo);
- }
- }
-
- DexClassAndMethod lookup() {
- SingleResolutionResult result = internalResolve(null).asSingleResolution();
- return result != null
- ? DexClassAndMethod.create(result.getResolvedHolder(), result.getResolvedMethod())
- : null;
- }
-
- ResolutionResult resolve(DexClass initialResolutionHolder) {
- assert initialResolutionHolder != null;
- return internalResolve(initialResolutionHolder);
- }
-
- private ResolutionResult internalResolve(DexClass initialResolutionHolder) {
- if (maximallySpecificMethods.isEmpty()) {
- return NoSuchMethodResult.INSTANCE;
- }
- // Fast path in the common case of a single method.
- if (maximallySpecificMethods.size() == 1) {
- return singleResultHelper(
- initialResolutionHolder, maximallySpecificMethods.entrySet().iterator().next());
- }
- Entry<DexClass, DexEncodedMethod> firstMaximallySpecificMethod = null;
- List<Entry<DexClass, DexEncodedMethod>> nonAbstractMethods =
- new ArrayList<>(maximallySpecificMethods.size());
- for (Entry<DexClass, DexEncodedMethod> entry : maximallySpecificMethods.entrySet()) {
- DexEncodedMethod method = entry.getValue();
- if (method == null) {
- // Ignore shadowed candidates.
- continue;
- }
- if (firstMaximallySpecificMethod == null) {
- firstMaximallySpecificMethod = entry;
- }
- if (method.isNonAbstractVirtualMethod()) {
- nonAbstractMethods.add(entry);
- }
- }
- // If there are no non-abstract methods, then any candidate will suffice as a target.
- // For deterministic resolution, we return the first mapped method (of the linked map).
- if (nonAbstractMethods.isEmpty()) {
- return singleResultHelper(initialResolutionHolder, firstMaximallySpecificMethod);
- }
- // If there is exactly one non-abstract method (a default method) it is the resolution target.
- if (nonAbstractMethods.size() == 1) {
- return singleResultHelper(initialResolutionHolder, nonAbstractMethods.get(0));
- }
- return IncompatibleClassResult.create(ListUtils.map(nonAbstractMethods, Entry::getValue));
- }
+ public final FieldResolutionResult resolveField(DexField field, ProgramMethod context) {
+ return resolveFieldOn(field.holder, field, context);
}
- private static SingleResolutionResult singleResultHelper(
- DexClass initialResolutionResult, Entry<DexClass, DexEncodedMethod> entry) {
- return new SingleResolutionResult(
- initialResolutionResult != null ? initialResolutionResult : entry.getKey(),
- entry.getKey(),
- entry.getValue());
+ public FieldResolutionResult resolveFieldOn(DexType type, DexField field, ProgramMethod context) {
+ // Only allow resolution if the field is declared in the context.
+ if (type != context.getHolderType()) {
+ return FieldResolutionResult.failure();
+ }
+ DexProgramClass clazz = context.getHolder();
+ DexEncodedField definition = clazz.lookupField(field);
+ return definition != null
+ ? new SuccessfulFieldResolutionResult(clazz, clazz, definition)
+ : FieldResolutionResult.unknown();
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index 3d9e26c..a0fd03b 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -7,15 +7,27 @@
import static com.android.tools.r8.utils.TraversalContinuation.BREAK;
import static com.android.tools.r8.utils.TraversalContinuation.CONTINUE;
+import com.android.tools.r8.graph.FieldResolutionResult.SuccessfulFieldResolutionResult;
+import com.android.tools.r8.graph.ResolutionResult.ArrayCloneMethodResult;
+import com.android.tools.r8.graph.ResolutionResult.ClassNotFoundResult;
+import com.android.tools.r8.graph.ResolutionResult.IllegalAccessOrNoSuchMethodResult;
+import com.android.tools.r8.graph.ResolutionResult.IncompatibleClassResult;
+import com.android.tools.r8.graph.ResolutionResult.NoSuchMethodResult;
+import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
+import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.TraversalContinuation;
import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.Sets;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
@@ -30,10 +42,21 @@
super(application);
}
- public AppInfoWithClassHierarchy(AppInfo previous) {
+ // For desugaring.
+ private AppInfoWithClassHierarchy(AppInfo appInfo) {
+ super(appInfo);
+ }
+
+ // For AppInfoWithLiveness.
+ protected AppInfoWithClassHierarchy(AppInfoWithClassHierarchy previous) {
super(previous);
}
+ public static AppInfoWithClassHierarchy createForDesugaring(AppInfo appInfo) {
+ assert !appInfo.hasClassHierarchy();
+ return new AppInfoWithClassHierarchy(appInfo);
+ }
+
@Override
public boolean hasClassHierarchy() {
assert checkIfObsolete();
@@ -329,26 +352,34 @@
* <p>The result is the field that will be hit at runtime, if such field is known. A result of
* null indicates that the field is either undefined or not an instance field.
*/
- public DexEncodedField lookupInstanceTarget(DexType type, DexField field) {
+ public DexEncodedField lookupInstanceTargetOn(DexType type, DexField field) {
assert checkIfObsolete();
assert type.isClassType();
- DexEncodedField result = resolveFieldOn(type, field);
+ DexEncodedField result = resolveFieldOn(type, field).getResolvedField();
return result == null || result.accessFlags.isStatic() ? null : result;
}
+ public DexEncodedField lookupInstanceTarget(DexField field) {
+ return lookupInstanceTargetOn(field.holder, field);
+ }
+
/**
* Lookup static field starting in type and following the interface and super chain.
*
* <p>The result is the field that will be hit at runtime, if such field is known. A result of
* null indicates that the field is either undefined or not a static field.
*/
- public DexEncodedField lookupStaticTarget(DexType type, DexField field) {
+ public DexEncodedField lookupStaticTargetOn(DexType type, DexField field) {
assert checkIfObsolete();
assert type.isClassType();
- DexEncodedField result = resolveFieldOn(type, field);
+ DexEncodedField result = resolveFieldOn(type, field).getResolvedField();
return result == null || !result.accessFlags.isStatic() ? null : result;
}
+ public DexEncodedField lookupStaticTarget(DexField field) {
+ return lookupStaticTargetOn(field.holder, field);
+ }
+
/**
* Lookup static method following the super chain from the holder of {@code method}.
*
@@ -358,16 +389,15 @@
* @param method the method to lookup
* @return The actual target for {@code method} or {@code null} if none found.
*/
- @Deprecated // TODO(b/147578480): Remove
- public DexEncodedMethod lookupStaticTarget(DexMethod method, DexType invocationContext) {
+ // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
+ public DexEncodedMethod lookupStaticTarget(DexMethod method, DexProgramClass context) {
assert checkIfObsolete();
- return lookupStaticTarget(method, toProgramClass(invocationContext));
+ return unsafeResolveMethodDueToDexFormat(method).lookupInvokeStaticTarget(context, this);
}
- public final DexEncodedMethod lookupStaticTarget(
- DexMethod method, DexProgramClass invocationContext) {
- assert checkIfObsolete();
- return resolveMethod(method.holder, method).lookupInvokeStaticTarget(invocationContext, this);
+ // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
+ public DexEncodedMethod lookupStaticTarget(DexMethod method, ProgramMethod context) {
+ return lookupStaticTarget(method, context.getHolder());
}
/**
@@ -377,19 +407,18 @@
* non-null value if the result of resolution was an instance (i.e. non-static) method.
*
* @param method the method to lookup
- * @param invocationContext the class the invoke is contained in, i.e., the holder of the caller.
+ * @param context the class the invoke is contained in, i.e., the holder of the caller.
* @return The actual target for {@code method} or {@code null} if none found.
*/
- @Deprecated // TODO(b/147578480): Remove
- public DexEncodedMethod lookupSuperTarget(DexMethod method, DexType invocationContext) {
+ // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
+ public DexEncodedMethod lookupSuperTarget(DexMethod method, DexProgramClass context) {
assert checkIfObsolete();
- return lookupSuperTarget(method, toProgramClass(invocationContext));
+ return unsafeResolveMethodDueToDexFormat(method).lookupInvokeSuperTarget(context, this);
}
- public final DexEncodedMethod lookupSuperTarget(
- DexMethod method, DexProgramClass invocationContext) {
- assert checkIfObsolete();
- return resolveMethod(method.holder, method).lookupInvokeSuperTarget(invocationContext, this);
+ // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
+ public DexEncodedMethod lookupSuperTarget(DexMethod method, ProgramMethod context) {
+ return lookupSuperTarget(method, context.getHolder());
}
/**
@@ -400,14 +429,484 @@
* @param method the method to lookup
* @return The actual target for {@code method} or {@code null} if none found.
*/
- @Deprecated // TODO(b/147578480): Remove
- public DexEncodedMethod lookupDirectTarget(DexMethod method, DexType invocationContext) {
+ // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
+ public DexEncodedMethod lookupDirectTarget(DexMethod method, DexProgramClass context) {
assert checkIfObsolete();
- return lookupDirectTarget(method, toProgramClass(invocationContext));
+ return unsafeResolveMethodDueToDexFormat(method).lookupInvokeDirectTarget(context, this);
}
- public DexEncodedMethod lookupDirectTarget(DexMethod method, DexProgramClass invocationContext) {
+ // TODO(b/155968472): This should take a parameter `boolean isInterface` and use resolveMethod().
+ public DexEncodedMethod lookupDirectTarget(DexMethod method, ProgramMethod context) {
+ return lookupDirectTarget(method, context.getHolder());
+ }
+
+ /**
+ * Implements resolution of a method descriptor.
+ *
+ * <p>This method will query the definition of the holder to decide on which resolution to use. If
+ * the holder is an interface, it delegates to {@link #resolveMethodOnInterface(DexType,
+ * DexMethod)}, otherwise {@link #resolveMethodOnClass(DexMethod, DexType)} is used.
+ *
+ * <p>This is to overcome the shortcoming of the DEX file format that does not allow to encode the
+ * kind of a method reference.
+ */
+ public ResolutionResult unsafeResolveMethodDueToDexFormat(DexMethod method) {
assert checkIfObsolete();
- return resolveMethod(method.holder, method).lookupInvokeDirectTarget(invocationContext, this);
+ DexType holder = method.holder;
+ if (holder.isArrayType()) {
+ return resolveMethodOnArray(holder, method);
+ }
+ DexClass definition = definitionFor(holder);
+ if (definition == null) {
+ return ClassNotFoundResult.INSTANCE;
+ }
+ return resolveMethodOn(definition, method);
+ }
+
+ public ResolutionResult resolveMethod(DexMethod method, boolean isInterface) {
+ return isInterface
+ ? resolveMethodOnInterface(method.holder, method)
+ : resolveMethodOnClass(method, method.holder);
+ }
+
+ public ResolutionResult resolveMethodOn(DexClass holder, DexMethod method) {
+ return holder.isInterface()
+ ? resolveMethodOnInterface(holder, method)
+ : resolveMethodOnClass(method, holder);
+ }
+
+ /**
+ * Implements resolution of a method descriptor against a target type.
+ *
+ * <p>The boolean isInterface parameter denotes if the method reference is an interface method
+ * reference, and if so method resolution is done according to interface method resolution.
+ *
+ * @param holder Type at which to initiate the resolution.
+ * @param method Method descriptor for resolution (the field method.holder is ignored).
+ * @param isInterface Indicates if resolution is to be done according to class or interface.
+ * @return The result of resolution.
+ */
+ public ResolutionResult resolveMethodOn(DexType holder, DexMethod method, boolean isInterface) {
+ assert checkIfObsolete();
+ return isInterface
+ ? resolveMethodOnInterface(holder, method)
+ : resolveMethodOnClass(method, holder);
+ }
+
+ /**
+ * Implements resolution of a method descriptor against an array type.
+ *
+ * <p>See <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html#jls-10.7">Section
+ * 10.7 of the Java Language Specification</a>. All invokations will have target java.lang.Object
+ * except clone which has no target.
+ */
+ private ResolutionResult resolveMethodOnArray(DexType holder, DexMethod method) {
+ assert checkIfObsolete();
+ assert holder.isArrayType();
+ if (method.name == dexItemFactory().cloneMethodName) {
+ return ArrayCloneMethodResult.INSTANCE;
+ } else {
+ return resolveMethodOnClass(method, dexItemFactory().objectType);
+ }
+ }
+
+ public ResolutionResult resolveMethodOnClass(DexMethod method) {
+ return resolveMethodOnClass(method, method.holder);
+ }
+
+ /**
+ * Implements resolution of a method descriptor against a class type.
+ *
+ * <p>See <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">
+ * Section 5.4.3.3 of the JVM Spec</a>.
+ *
+ * <p>The resolved method is not the method that will actually be invoked. Which methods gets
+ * invoked depends on the invoke instruction used. However, it is always safe to rewrite any
+ * invoke on the given descriptor to a corresponding invoke on the resolved descriptor, as the
+ * resolved method is used as basis for dispatch.
+ */
+ public ResolutionResult resolveMethodOnClass(DexMethod method, DexType holder) {
+ assert checkIfObsolete();
+ if (holder.isArrayType()) {
+ return resolveMethodOnArray(holder, method);
+ }
+ DexClass clazz = definitionFor(holder);
+ if (clazz == null) {
+ return ClassNotFoundResult.INSTANCE;
+ }
+ // Step 1: If holder is an interface, resolution fails with an ICCE. We return null.
+ if (clazz.isInterface()) {
+ return IncompatibleClassResult.INSTANCE;
+ }
+ return resolveMethodOnClass(method, clazz);
+ }
+
+ public ResolutionResult resolveMethodOnClass(DexMethod method, DexClass clazz) {
+ assert checkIfObsolete();
+ assert !clazz.isInterface();
+ // Step 2:
+ ResolutionResult result = resolveMethodOnClassStep2(clazz, method, clazz);
+ if (result != null) {
+ return result;
+ }
+ // Finally Step 3:
+ return resolveMethodStep3(clazz, method);
+ }
+
+ /**
+ * Implements step 2 of method resolution on classes as per <a
+ * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">Section
+ * 5.4.3.3 of the JVM Spec</a>.
+ */
+ private ResolutionResult resolveMethodOnClassStep2(
+ DexClass clazz, DexMethod method, DexClass initialResolutionHolder) {
+ // Pt. 1: Signature polymorphic method check.
+ // See also <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.9">
+ // Section 2.9 of the JVM Spec</a>.
+ DexEncodedMethod result = clazz.lookupSignaturePolymorphicMethod(method.name, dexItemFactory());
+ if (result != null) {
+ return new SingleResolutionResult(initialResolutionHolder, clazz, result);
+ }
+ // Pt 2: Find a method that matches the descriptor.
+ result = clazz.lookupMethod(method);
+ if (result != null) {
+ // If the resolved method is private, then it can only be accessed if the symbolic reference
+ // that initiated the resolution was the type at which the method resolved on. If that is not
+ // the case, then the error is either an IllegalAccessError, or in the case where access is
+ // allowed because of nests, a NoSuchMethodError. Which error cannot be determined without
+ // knowing the calling context.
+ if (result.isPrivateMethod() && clazz != initialResolutionHolder) {
+ return new IllegalAccessOrNoSuchMethodResult(result);
+ }
+ return new SingleResolutionResult(initialResolutionHolder, clazz, result);
+ }
+ // Pt 3: Apply step two to direct superclass of holder.
+ if (clazz.superType != null) {
+ DexClass superClass = definitionFor(clazz.superType);
+ if (superClass != null) {
+ return resolveMethodOnClassStep2(superClass, method, initialResolutionHolder);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Implements step 3 of <a
+ * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">Section
+ * 5.4.3.3 of the JVM Spec</a>. As this is the same for interfaces and classes, we share one
+ * implementation.
+ */
+ private ResolutionResult resolveMethodStep3(DexClass clazz, DexMethod method) {
+ MaximallySpecificMethodsBuilder builder = new MaximallySpecificMethodsBuilder();
+ resolveMethodStep3Helper(method, clazz, builder);
+ return builder.resolve(clazz);
+ }
+
+ // Non-private lookup (ie, not resolution) to find interface targets.
+ DexClassAndMethod lookupMaximallySpecificTarget(DexClass clazz, DexMethod method) {
+ MaximallySpecificMethodsBuilder builder = new MaximallySpecificMethodsBuilder();
+ resolveMethodStep3Helper(method, clazz, builder);
+ return builder.lookup();
+ }
+
+ // Non-private lookup (ie, not resolution) to find interface targets.
+ DexClassAndMethod lookupMaximallySpecificTarget(LambdaDescriptor lambda, DexMethod method) {
+ MaximallySpecificMethodsBuilder builder = new MaximallySpecificMethodsBuilder();
+ resolveMethodStep3Helper(method, dexItemFactory().objectType, lambda.interfaces, builder);
+ return builder.lookup();
+ }
+
+ /** Helper method that builds the set of maximally specific methods. */
+ private void resolveMethodStep3Helper(
+ DexMethod method, DexClass clazz, MaximallySpecificMethodsBuilder builder) {
+ resolveMethodStep3Helper(
+ method, clazz.superType, Arrays.asList(clazz.interfaces.values), builder);
+ }
+
+ private void resolveMethodStep3Helper(
+ DexMethod method,
+ DexType superType,
+ List<DexType> interfaces,
+ MaximallySpecificMethodsBuilder builder) {
+ for (DexType iface : interfaces) {
+ DexClass definiton = definitionFor(iface);
+ if (definiton == null) {
+ // Ignore missing interface definitions.
+ continue;
+ }
+ assert definiton.isInterface();
+ DexEncodedMethod result = definiton.lookupMethod(method);
+ if (isMaximallySpecificCandidate(result)) {
+ // The candidate is added and doing so will prohibit shadowed methods from being in the set.
+ builder.addCandidate(definiton, result, this);
+ } else {
+ // Look at the super-interfaces of this class and keep searching.
+ resolveMethodStep3Helper(method, definiton, builder);
+ }
+ }
+ // Now look at indirect super interfaces.
+ if (superType != null) {
+ DexClass superClass = definitionFor(superType);
+ if (superClass != null) {
+ resolveMethodStep3Helper(method, superClass, builder);
+ }
+ }
+ }
+
+ /**
+ * A candidate for being a maximally specific method must have neither its private, nor its static
+ * flag set. A candidate may still not be maximally specific, which entails that no subinterfaces
+ * from also contribute with a candidate to the type. That is not determined by this method.
+ */
+ private boolean isMaximallySpecificCandidate(DexEncodedMethod method) {
+ return method != null && !method.accessFlags.isPrivate() && !method.accessFlags.isStatic();
+ }
+
+ public ResolutionResult resolveMethodOnInterface(DexMethod method) {
+ return resolveMethodOnInterface(method.holder, method);
+ }
+
+ /**
+ * Implements resolution of a method descriptor against an interface type.
+ *
+ * <p>See <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.3">
+ * Section 5.4.3.4 of the JVM Spec</a>.
+ *
+ * <p>The resolved method is not the method that will actually be invoked. Which methods gets
+ * invoked depends on the invoke instruction used. However, it is always save to rewrite any
+ * invoke on the given descriptor to a corresponding invoke on the resolved descriptor, as the
+ * resolved method is used as basis for dispatch.
+ */
+ public ResolutionResult resolveMethodOnInterface(DexType holder, DexMethod desc) {
+ assert checkIfObsolete();
+ if (holder.isArrayType()) {
+ return IncompatibleClassResult.INSTANCE;
+ }
+ // Step 1: Lookup interface.
+ DexClass definition = definitionFor(holder);
+ // If the definition is not an interface, resolution fails with an ICCE. We just return the
+ // empty result here.
+ if (definition == null) {
+ return ClassNotFoundResult.INSTANCE;
+ }
+ if (!definition.isInterface()) {
+ return IncompatibleClassResult.INSTANCE;
+ }
+ return resolveMethodOnInterface(definition, desc);
+ }
+
+ public ResolutionResult resolveMethodOnInterface(DexClass definition, DexMethod desc) {
+ assert checkIfObsolete();
+ assert definition.isInterface();
+ // Step 2: Look for exact method on interface.
+ DexEncodedMethod result = definition.lookupMethod(desc);
+ if (result != null) {
+ return new SingleResolutionResult(definition, definition, result);
+ }
+ // Step 3: Look for matching method on object class.
+ DexClass objectClass = definitionFor(dexItemFactory().objectType);
+ if (objectClass == null) {
+ return ClassNotFoundResult.INSTANCE;
+ }
+ result = objectClass.lookupMethod(desc);
+ if (result != null && result.accessFlags.isPublic() && !result.accessFlags.isAbstract()) {
+ return new SingleResolutionResult(definition, objectClass, result);
+ }
+ // Step 3: Look for maximally-specific superinterface methods or any interface definition.
+ // This is the same for classes and interfaces.
+ return resolveMethodStep3(definition, desc);
+ }
+
+ /**
+ * Implements resolution of a field descriptor against the holder of the field. See also {@link
+ * #resolveFieldOn}.
+ */
+ public FieldResolutionResult resolveField(DexField field) {
+ assert checkIfObsolete();
+ return resolveFieldOn(field.holder, field);
+ }
+
+ /** Intentionally drops {@param context} since this is only needed in D8. */
+ @Override
+ public FieldResolutionResult resolveFieldOn(DexType type, DexField field, ProgramMethod context) {
+ return resolveFieldOn(type, field);
+ }
+
+ /**
+ * Implements resolution of a field descriptor against a type.
+ *
+ * <p>See <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.2">
+ * Section 5.4.3.2 of the JVM Spec</a>.
+ */
+ public FieldResolutionResult resolveFieldOn(DexType type, DexField field) {
+ assert checkIfObsolete();
+ DexClass holder = definitionFor(type);
+ return holder != null ? resolveFieldOn(holder, field) : FieldResolutionResult.failure();
+ }
+
+ public FieldResolutionResult resolveFieldOn(DexClass holder, DexField field) {
+ assert checkIfObsolete();
+ assert holder != null;
+ return resolveFieldOn(holder, field, holder, SetUtils.newIdentityHashSet(8));
+ }
+
+ private FieldResolutionResult resolveFieldOn(
+ DexClass holder,
+ DexField field,
+ DexClass initialResolutionHolder,
+ Set<DexType> visitedInterfaces) {
+ assert checkIfObsolete();
+ assert holder != null;
+ // Step 1: Class declares the field.
+ DexEncodedField definition = holder.lookupField(field);
+ if (definition != null) {
+ return new SuccessfulFieldResolutionResult(initialResolutionHolder, holder, definition);
+ }
+ // Step 2: Apply recursively to direct superinterfaces. First match succeeds.
+ DexClassAndField result = resolveFieldOnDirectInterfaces(holder, field, visitedInterfaces);
+ if (result != null) {
+ return new SuccessfulFieldResolutionResult(
+ initialResolutionHolder, result.getHolder(), result.getDefinition());
+ }
+ // Step 3: Apply recursively to superclass.
+ if (holder.superType != null) {
+ DexClass superClass = definitionFor(holder.superType);
+ if (superClass != null) {
+ return resolveFieldOn(superClass, field, initialResolutionHolder, visitedInterfaces);
+ }
+ }
+ return FieldResolutionResult.failure();
+ }
+
+ private DexClassAndField resolveFieldOnDirectInterfaces(
+ DexClass clazz, DexField field, Set<DexType> visitedInterfaces) {
+ for (DexType interfaceType : clazz.interfaces.values) {
+ if (visitedInterfaces.add(interfaceType)) {
+ DexClass interfaceClass = definitionFor(interfaceType);
+ if (interfaceClass != null) {
+ DexClassAndField result =
+ resolveFieldOnInterface(interfaceClass, field, visitedInterfaces);
+ if (result != null) {
+ return result;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private DexClassAndField resolveFieldOnInterface(
+ DexClass interfaceClass, DexField field, Set<DexType> visitedInterfaces) {
+ // Step 1: Class declares the field.
+ DexEncodedField definition = interfaceClass.lookupField(field);
+ if (definition != null) {
+ return DexClassAndField.create(interfaceClass, definition);
+ }
+ // Step 2: Apply recursively to direct superinterfaces. First match succeeds.
+ return resolveFieldOnDirectInterfaces(interfaceClass, field, visitedInterfaces);
+ }
+
+ private static class MaximallySpecificMethodsBuilder {
+
+ // The set of actual maximally specific methods.
+ // This set is linked map so that in the case where a number of methods remain a deterministic
+ // choice can be made. The map is from definition classes to their maximally specific method, or
+ // in the case that a type has a candidate which is shadowed by a subinterface, the map will
+ // map the class to a null entry, thus any addition to the map must check for key containment
+ // prior to writing.
+ LinkedHashMap<DexClass, DexEncodedMethod> maximallySpecificMethods = new LinkedHashMap<>();
+
+ void addCandidate(DexClass holder, DexEncodedMethod method, AppInfo appInfo) {
+ // If this candidate is already a candidate or it is shadowed, then no need to continue.
+ if (maximallySpecificMethods.containsKey(holder)) {
+ return;
+ }
+ maximallySpecificMethods.put(holder, method);
+ // Prune exiting candidates and prohibit future candidates in the super hierarchy.
+ assert holder.isInterface();
+ assert holder.superType == appInfo.dexItemFactory().objectType;
+ for (DexType iface : holder.interfaces.values) {
+ markShadowed(iface, appInfo);
+ }
+ }
+
+ private void markShadowed(DexType type, AppInfo appInfo) {
+ if (type == null) {
+ return;
+ }
+ DexClass clazz = appInfo.definitionFor(type);
+ if (clazz == null) {
+ return;
+ }
+ assert clazz.isInterface();
+ assert clazz.superType == appInfo.dexItemFactory().objectType;
+ // A null entry signifies that the candidate is shadowed blocking future candidates.
+ // If the candidate is already shadowed at this type there is no need to shadow further up.
+ if (maximallySpecificMethods.containsKey(clazz)
+ && maximallySpecificMethods.get(clazz) == null) {
+ return;
+ }
+ maximallySpecificMethods.put(clazz, null);
+ for (DexType iface : clazz.interfaces.values) {
+ markShadowed(iface, appInfo);
+ }
+ }
+
+ DexClassAndMethod lookup() {
+ SingleResolutionResult result = internalResolve(null).asSingleResolution();
+ return result != null
+ ? DexClassAndMethod.create(result.getResolvedHolder(), result.getResolvedMethod())
+ : null;
+ }
+
+ ResolutionResult resolve(DexClass initialResolutionHolder) {
+ assert initialResolutionHolder != null;
+ return internalResolve(initialResolutionHolder);
+ }
+
+ private ResolutionResult internalResolve(DexClass initialResolutionHolder) {
+ if (maximallySpecificMethods.isEmpty()) {
+ return NoSuchMethodResult.INSTANCE;
+ }
+ // Fast path in the common case of a single method.
+ if (maximallySpecificMethods.size() == 1) {
+ return singleResultHelper(
+ initialResolutionHolder, maximallySpecificMethods.entrySet().iterator().next());
+ }
+ Entry<DexClass, DexEncodedMethod> firstMaximallySpecificMethod = null;
+ List<Entry<DexClass, DexEncodedMethod>> nonAbstractMethods =
+ new ArrayList<>(maximallySpecificMethods.size());
+ for (Entry<DexClass, DexEncodedMethod> entry : maximallySpecificMethods.entrySet()) {
+ DexEncodedMethod method = entry.getValue();
+ if (method == null) {
+ // Ignore shadowed candidates.
+ continue;
+ }
+ if (firstMaximallySpecificMethod == null) {
+ firstMaximallySpecificMethod = entry;
+ }
+ if (method.isNonAbstractVirtualMethod()) {
+ nonAbstractMethods.add(entry);
+ }
+ }
+ // If there are no non-abstract methods, then any candidate will suffice as a target.
+ // For deterministic resolution, we return the first mapped method (of the linked map).
+ if (nonAbstractMethods.isEmpty()) {
+ return singleResultHelper(initialResolutionHolder, firstMaximallySpecificMethod);
+ }
+ // If there is exactly one non-abstract method (a default method) it is the resolution target.
+ if (nonAbstractMethods.size() == 1) {
+ return singleResultHelper(initialResolutionHolder, nonAbstractMethods.get(0));
+ }
+ return IncompatibleClassResult.create(ListUtils.map(nonAbstractMethods, Entry::getValue));
+ }
+
+ private static SingleResolutionResult singleResultHelper(
+ DexClass initialResolutionResult, Entry<DexClass, DexEncodedMethod> entry) {
+ return new SingleResolutionResult(
+ initialResolutionResult != null ? initialResolutionResult : entry.getKey(),
+ entry.getKey(),
+ entry.getValue());
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 484c3e1..a7c1351 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -38,6 +38,7 @@
}
private T appInfo;
+ private AppInfoWithClassHierarchy appInfoForDesugaring;
private AppServices appServices;
private final DexItemFactory dexItemFactory;
private final WholeProgramOptimizations wholeProgramOptimizations;
@@ -144,13 +145,31 @@
}
public T appInfo() {
+ assert !appInfo.hasClassHierarchy() || enableWholeProgramOptimizations();
return appInfo;
}
+ public AppInfoWithClassHierarchy appInfoForDesugaring() {
+ if (enableWholeProgramOptimizations()) {
+ assert appInfo.hasClassHierarchy();
+ return appInfo.withClassHierarchy();
+ }
+ assert !appInfo.hasClassHierarchy();
+ if (appInfoForDesugaring == null) {
+ appInfoForDesugaring = AppInfoWithClassHierarchy.createForDesugaring(appInfo());
+ }
+ return appInfoForDesugaring;
+ }
+
+ private void unsetAppInfoForDesugaring() {
+ appInfoForDesugaring = null;
+ }
+
public <U extends T> AppView<U> setAppInfo(U appInfo) {
assert !appInfo.isObsolete();
AppInfo previous = this.appInfo;
this.appInfo = appInfo;
+ unsetAppInfoForDesugaring();
if (appInfo != previous) {
previous.markObsolete();
}
@@ -434,4 +453,9 @@
? OptionalBool.of(appInfo().withLiveness().isSubtype(subtype, supertype))
: OptionalBool.unknown();
}
+
+ public boolean isCfByteCodePassThrough(DexEncodedMethod method) {
+ return options.testing.cfByteCodePassThrough != null
+ && options.testing.cfByteCodePassThrough.test(method);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index b68b839..0b9b084 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -183,7 +183,7 @@
// Don't add parameter information if the code already has full debug information.
// Note: This fast path can cause a method to loose its parameter info, if the debug info turned
// out to be invalid during IR building.
- if (appView.options().debug) {
+ if (appView.options().debug || appView.isCfByteCodePassThrough(method)) {
return false;
}
assert localVariables.isEmpty();
@@ -395,23 +395,18 @@
@Override
public void registerCodeReferences(ProgramMethod method, UseRegistry registry) {
- internalRegisterCodeReferences(method, registry);
+ for (CfInstruction instruction : instructions) {
+ instruction.registerUse(registry, method);
+ }
+ tryCatchRanges.forEach(tryCatch -> tryCatch.guards.forEach(registry::registerTypeReference));
}
@Override
public void registerCodeReferencesForDesugaring(ClasspathMethod method, UseRegistry registry) {
- internalRegisterCodeReferences(method, registry);
- }
-
- private void internalRegisterCodeReferences(DexClassAndMethod method, UseRegistry registry) {
for (CfInstruction instruction : instructions) {
- instruction.registerUse(registry, method.getHolderType());
+ instruction.registerUseForDesugaring(registry, method);
}
- for (CfTryCatch tryCatch : tryCatchRanges) {
- for (DexType guard : tryCatch.guards) {
- registry.registerTypeReference(guard);
- }
- }
+ tryCatchRanges.forEach(tryCatch -> tryCatch.guards.forEach(registry::registerTypeReference));
}
@Override
@@ -513,8 +508,7 @@
ProgramMethod method,
AppView<AppInfoWithLiveness> appView,
GraphLense graphLense,
- DexType invocationContext) {
-
+ DexProgramClass context) {
InliningConstraints inliningConstraints = new InliningConstraints(appView, graphLense);
if (appView.options().isInterfaceMethodDesugaringEnabled()) {
// TODO(b/120130831): Conservatively need to say "no" at this point if there are invocations
@@ -536,9 +530,7 @@
for (CfInstruction insn : instructions) {
constraint =
ConstraintWithTarget.meet(
- constraint,
- insn.inliningConstraint(inliningConstraints, invocationContext),
- appView);
+ constraint, insn.inliningConstraint(inliningConstraints, context), appView);
if (constraint == ConstraintWithTarget.NEVER) {
return constraint;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClassAndField.java b/src/main/java/com/android/tools/r8/graph/DexClassAndField.java
new file mode 100644
index 0000000..7b11467
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/DexClassAndField.java
@@ -0,0 +1,78 @@
+// Copyright (c) 2020, 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.graph;
+
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.origin.Origin;
+
+public class DexClassAndField {
+
+ private final DexClass holder;
+ private final DexEncodedField field;
+
+ DexClassAndField(DexClass holder, DexEncodedField field) {
+ assert holder != null;
+ assert field != null;
+ assert holder.type == field.holder();
+ assert holder.isProgramClass() == (this instanceof ProgramField);
+ this.holder = holder;
+ this.field = field;
+ }
+
+ public static DexClassAndField create(DexClass holder, DexEncodedField field) {
+ if (holder.isProgramClass()) {
+ return new ProgramField(holder.asProgramClass(), field);
+ } else {
+ return new DexClassAndField(holder, field);
+ }
+ }
+
+ public DexClass getHolder() {
+ return holder;
+ }
+
+ public DexType getHolderType() {
+ return holder.type;
+ }
+
+ public DexEncodedField getDefinition() {
+ return field;
+ }
+
+ public DexField getReference() {
+ return field.field;
+ }
+
+ public Origin getOrigin() {
+ return holder.origin;
+ }
+
+ public boolean isProgramField() {
+ return false;
+ }
+
+ public ProgramField asProgramField() {
+ return null;
+ }
+
+ public String toSourceString() {
+ return getReference().toSourceString();
+ }
+
+ @Override
+ public String toString() {
+ return toSourceString();
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ throw new Unreachable("Unsupported attempt at comparing Class and DexClassAndField");
+ }
+
+ @Override
+ public int hashCode() {
+ throw new Unreachable("Unsupported attempt at computing the hashcode of DexClassAndField");
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index c589524..73395b2 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -231,7 +231,7 @@
}
public boolean mayTriggerClassInitializationSideEffects(
- AppView<AppInfoWithLiveness> appView, DexType context) {
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
// Only static field matters when it comes to class initialization side effects.
if (!isStatic()) {
return false;
@@ -244,7 +244,7 @@
appView,
// Types that are a super type of the current context are guaranteed to be initialized
// already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appView.appInfo().isSubtype(context.getHolderType(), type),
Sets.newIdentityHashSet())) {
// Ignore class initialization side-effects for dead proto extension fields to ensure that
// we force replace these field reads by null.
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index b81c877..c2390fb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -120,9 +120,6 @@
public static final DexEncodedMethod SENTINEL =
new DexEncodedMethod(
null, null, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null);
- public static final DexEncodedMethod ANNOTATION_REFERENCE =
- new DexEncodedMethod(
- null, null, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null);
public static final Int2ReferenceMap<DebugLocalInfo> NO_PARAMETER_INFO =
new Int2ReferenceArrayMap<>(0);
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index e27c7b4..900712b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -175,10 +175,21 @@
return toProgramMethodOrNull(getInitializer(types));
}
+ public ProgramField lookupProgramField(DexField reference) {
+ return toProgramFieldOrNull(lookupField(reference));
+ }
+
public ProgramMethod lookupProgramMethod(DexMethod reference) {
return toProgramMethodOrNull(getMethodCollection().getMethod(reference));
}
+ private ProgramField toProgramFieldOrNull(DexEncodedField field) {
+ if (field != null) {
+ return new ProgramField(this, field);
+ }
+ return null;
+ }
+
private ProgramMethod toProgramMethodOrNull(DexEncodedMethod method) {
if (method != null) {
return new ProgramMethod(this, method);
diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java b/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java
index 38d3a8e..35917f5 100644
--- a/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.graph;
-import java.util.Set;
+import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -20,15 +20,15 @@
int getNumberOfWriteContexts();
- DexEncodedMethod getUniqueReadContext();
+ ProgramMethod getUniqueReadContext();
void forEachIndirectAccess(Consumer<DexField> consumer);
- void forEachIndirectAccessWithContexts(BiConsumer<DexField, Set<DexEncodedMethod>> consumer);
+ void forEachIndirectAccessWithContexts(BiConsumer<DexField, ProgramMethodSet> consumer);
- void forEachReadContext(Consumer<DexEncodedMethod> consumer);
+ void forEachReadContext(Consumer<ProgramMethod> consumer);
- void forEachWriteContext(Consumer<DexEncodedMethod> consumer);
+ void forEachWriteContext(Consumer<ProgramMethod> consumer);
boolean hasReflectiveAccess();
@@ -38,17 +38,17 @@
boolean isRead();
- boolean isReadFromMethodHandle();
+ boolean isReadFromAnnotation();
- boolean isReadOnlyIn(DexEncodedMethod method);
+ boolean isReadFromMethodHandle();
boolean isWritten();
boolean isWrittenFromMethodHandle();
- boolean isWrittenInMethodSatisfying(Predicate<DexEncodedMethod> predicate);
+ boolean isWrittenInMethodSatisfying(Predicate<ProgramMethod> predicate);
- boolean isWrittenOnlyInMethodSatisfying(Predicate<DexEncodedMethod> predicate);
+ boolean isWrittenOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate);
boolean isWrittenOutside(DexEncodedMethod method);
}
diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java
index 5634d5b..9dd6c41 100644
--- a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java
+++ b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java
@@ -30,9 +30,10 @@
return infos.get(field);
}
- public void extend(DexField field, FieldAccessInfoImpl info) {
+ public FieldAccessInfoImpl extend(DexField field, FieldAccessInfoImpl info) {
assert !infos.containsKey(field);
infos.put(field, info);
+ return info;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java
index b15153b..383c6e2 100644
--- a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java
+++ b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.collect.Sets;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -22,9 +23,10 @@
public static final FieldAccessInfoImpl MISSING_FIELD_ACCESS_INFO = new FieldAccessInfoImpl(null);
- public static int FLAG_IS_READ_FROM_METHOD_HANDLE = 1 << 0;
- public static int FLAG_IS_WRITTEN_FROM_METHOD_HANDLE = 1 << 1;
- public static int FLAG_HAS_REFLECTIVE_ACCESS = 1 << 2;
+ public static int FLAG_IS_READ_FROM_ANNOTATION = 1 << 0;
+ public static int FLAG_IS_READ_FROM_METHOD_HANDLE = 1 << 1;
+ public static int FLAG_IS_WRITTEN_FROM_METHOD_HANDLE = 1 << 2;
+ public static int FLAG_HAS_REFLECTIVE_ACCESS = 1 << 3;
// A direct reference to the definition of the field.
private DexField field;
@@ -34,11 +36,11 @@
// Maps every direct and indirect reference in a read-context to the set of methods in which that
// reference appears.
- private Map<DexField, Set<DexEncodedMethod>> readsWithContexts;
+ private Map<DexField, ProgramMethodSet> readsWithContexts;
// Maps every direct and indirect reference in a write-context to the set of methods in which that
// reference appears.
- private Map<DexField, Set<DexEncodedMethod>> writesWithContexts;
+ private Map<DexField, ProgramMethodSet> writesWithContexts;
public FieldAccessInfoImpl(DexField field) {
this.field = field;
@@ -49,10 +51,10 @@
flattenAccessContexts(writesWithContexts);
}
- private void flattenAccessContexts(Map<DexField, Set<DexEncodedMethod>> accessesWithContexts) {
+ private void flattenAccessContexts(Map<DexField, ProgramMethodSet> accessesWithContexts) {
if (accessesWithContexts != null) {
- Set<DexEncodedMethod> flattenedAccessContexts =
- accessesWithContexts.computeIfAbsent(field, ignore -> Sets.newIdentityHashSet());
+ ProgramMethodSet flattenedAccessContexts =
+ accessesWithContexts.computeIfAbsent(field, ignore -> ProgramMethodSet.create());
accessesWithContexts.forEach(
(access, contexts) -> {
if (access != field) {
@@ -87,7 +89,7 @@
return getNumberOfAccessContexts(writesWithContexts);
}
- private int getNumberOfAccessContexts(Map<DexField, Set<DexEncodedMethod>> accessesWithContexts) {
+ private int getNumberOfAccessContexts(Map<DexField, ProgramMethodSet> accessesWithContexts) {
if (accessesWithContexts == null) {
return 0;
}
@@ -98,9 +100,9 @@
}
@Override
- public DexEncodedMethod getUniqueReadContext() {
+ public ProgramMethod getUniqueReadContext() {
if (readsWithContexts != null && readsWithContexts.size() == 1) {
- Set<DexEncodedMethod> contexts = readsWithContexts.values().iterator().next();
+ ProgramMethodSet contexts = readsWithContexts.values().iterator().next();
if (contexts.size() == 1) {
return contexts.iterator().next();
}
@@ -120,7 +122,7 @@
}
private static void forEachAccessInMap(
- Map<DexField, Set<DexEncodedMethod>> accessesWithContexts,
+ Map<DexField, ProgramMethodSet> accessesWithContexts,
Predicate<DexField> predicate,
Consumer<DexField> consumer) {
if (accessesWithContexts != null) {
@@ -134,9 +136,8 @@
}
@Override
- public void forEachIndirectAccessWithContexts(
- BiConsumer<DexField, Set<DexEncodedMethod>> consumer) {
- Map<DexField, Set<DexEncodedMethod>> indirectAccessesWithContexts = new IdentityHashMap<>();
+ public void forEachIndirectAccessWithContexts(BiConsumer<DexField, ProgramMethodSet> consumer) {
+ Map<DexField, ProgramMethodSet> indirectAccessesWithContexts = new IdentityHashMap<>();
extendAccessesWithContexts(
indirectAccessesWithContexts, access -> access != field, readsWithContexts);
extendAccessesWithContexts(
@@ -145,15 +146,15 @@
}
private void extendAccessesWithContexts(
- Map<DexField, Set<DexEncodedMethod>> accessesWithContexts,
+ Map<DexField, ProgramMethodSet> accessesWithContexts,
Predicate<DexField> predicate,
- Map<DexField, Set<DexEncodedMethod>> extension) {
+ Map<DexField, ProgramMethodSet> extension) {
if (extension != null) {
extension.forEach(
(access, contexts) -> {
if (predicate.test(access)) {
accessesWithContexts
- .computeIfAbsent(access, ignore -> Sets.newIdentityHashSet())
+ .computeIfAbsent(access, ignore -> ProgramMethodSet.create())
.addAll(contexts);
}
});
@@ -161,24 +162,23 @@
}
@Override
- public void forEachReadContext(Consumer<DexEncodedMethod> consumer) {
+ public void forEachReadContext(Consumer<ProgramMethod> consumer) {
forEachAccessContext(readsWithContexts, consumer);
}
@Override
- public void forEachWriteContext(Consumer<DexEncodedMethod> consumer) {
+ public void forEachWriteContext(Consumer<ProgramMethod> consumer) {
forEachAccessContext(writesWithContexts, consumer);
}
private void forEachAccessContext(
- Map<DexField, Set<DexEncodedMethod>> accessesWithContexts,
- Consumer<DexEncodedMethod> consumer) {
+ Map<DexField, ProgramMethodSet> accessesWithContexts, Consumer<ProgramMethod> consumer) {
// There can be indirect reads and writes of the same field reference, so we need to keep track
// of the previously-seen indirect accesses to avoid reporting duplicates.
- Set<DexEncodedMethod> visited = Sets.newIdentityHashSet();
+ ProgramMethodSet visited = ProgramMethodSet.create();
if (accessesWithContexts != null) {
- for (Set<DexEncodedMethod> encodedAccessContexts : accessesWithContexts.values()) {
- for (DexEncodedMethod encodedAccessContext : encodedAccessContexts) {
+ for (ProgramMethodSet encodedAccessContexts : accessesWithContexts.values()) {
+ for (ProgramMethod encodedAccessContext : encodedAccessContexts) {
if (visited.add(encodedAccessContext)) {
consumer.accept(encodedAccessContext);
}
@@ -199,7 +199,16 @@
/** Returns true if this field is read by the program. */
@Override
public boolean isRead() {
- return readsWithContexts != null && !readsWithContexts.isEmpty();
+ return (readsWithContexts != null && !readsWithContexts.isEmpty()) || isReadFromAnnotation();
+ }
+
+ @Override
+ public boolean isReadFromAnnotation() {
+ return (flags & FLAG_IS_READ_FROM_ANNOTATION) != 0;
+ }
+
+ public void setReadFromAnnotation() {
+ flags |= FLAG_IS_READ_FROM_ANNOTATION;
}
@Override
@@ -211,14 +220,6 @@
flags |= FLAG_IS_READ_FROM_METHOD_HANDLE;
}
- @Override
- public boolean isReadOnlyIn(DexEncodedMethod method) {
- assert isRead();
- assert method != null;
- DexEncodedMethod uniqueReadContext = getUniqueReadContext();
- return uniqueReadContext != null && uniqueReadContext == method;
- }
-
/** Returns true if this field is written by the program. */
@Override
public boolean isWritten() {
@@ -238,10 +239,10 @@
* Returns true if this field is written by a method for which {@param predicate} returns true.
*/
@Override
- public boolean isWrittenInMethodSatisfying(Predicate<DexEncodedMethod> predicate) {
+ public boolean isWrittenInMethodSatisfying(Predicate<ProgramMethod> predicate) {
if (writesWithContexts != null) {
- for (Set<DexEncodedMethod> encodedWriteContexts : writesWithContexts.values()) {
- for (DexEncodedMethod encodedWriteContext : encodedWriteContexts) {
+ for (ProgramMethodSet encodedWriteContexts : writesWithContexts.values()) {
+ for (ProgramMethod encodedWriteContext : encodedWriteContexts) {
if (predicate.test(encodedWriteContext)) {
return true;
}
@@ -256,10 +257,10 @@
* true.
*/
@Override
- public boolean isWrittenOnlyInMethodSatisfying(Predicate<DexEncodedMethod> predicate) {
+ public boolean isWrittenOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate) {
if (writesWithContexts != null) {
- for (Set<DexEncodedMethod> encodedWriteContexts : writesWithContexts.values()) {
- for (DexEncodedMethod encodedWriteContext : encodedWriteContexts) {
+ for (ProgramMethodSet encodedWriteContexts : writesWithContexts.values()) {
+ for (ProgramMethod encodedWriteContext : encodedWriteContexts) {
if (!predicate.test(encodedWriteContext)) {
return false;
}
@@ -275,9 +276,9 @@
@Override
public boolean isWrittenOutside(DexEncodedMethod method) {
if (writesWithContexts != null) {
- for (Set<DexEncodedMethod> encodedWriteContexts : writesWithContexts.values()) {
- for (DexEncodedMethod encodedWriteContext : encodedWriteContexts) {
- if (encodedWriteContext != method) {
+ for (ProgramMethodSet encodedWriteContexts : writesWithContexts.values()) {
+ for (ProgramMethod encodedWriteContext : encodedWriteContexts) {
+ if (encodedWriteContext.getDefinition() != method) {
return true;
}
}
@@ -286,21 +287,21 @@
return false;
}
- public boolean recordRead(DexField access, DexEncodedMethod context) {
+ public boolean recordRead(DexField access, ProgramMethod context) {
if (readsWithContexts == null) {
readsWithContexts = new IdentityHashMap<>();
}
return readsWithContexts
- .computeIfAbsent(access, ignore -> Sets.newIdentityHashSet())
+ .computeIfAbsent(access, ignore -> ProgramMethodSet.create())
.add(context);
}
- public boolean recordWrite(DexField access, DexEncodedMethod context) {
+ public boolean recordWrite(DexField access, ProgramMethod context) {
if (writesWithContexts == null) {
writesWithContexts = new IdentityHashMap<>();
}
return writesWithContexts
- .computeIfAbsent(access, ignore -> Sets.newIdentityHashSet())
+ .computeIfAbsent(access, ignore -> ProgramMethodSet.create())
.add(context);
}
@@ -319,11 +320,11 @@
rewritten.readsWithContexts = new IdentityHashMap<>();
readsWithContexts.forEach(
(access, contexts) -> {
- Set<DexEncodedMethod> newContexts =
+ ProgramMethodSet newContexts =
rewritten.readsWithContexts.computeIfAbsent(
- lens.lookupField(access), ignore -> Sets.newIdentityHashSet());
- for (DexEncodedMethod context : contexts) {
- newContexts.add(lens.mapDexEncodedMethod(context, definitions));
+ lens.lookupField(access), ignore -> ProgramMethodSet.create());
+ for (ProgramMethod context : contexts) {
+ newContexts.add(lens.mapProgramMethod(context, definitions));
}
});
}
@@ -331,11 +332,11 @@
rewritten.writesWithContexts = new IdentityHashMap<>();
writesWithContexts.forEach(
(access, contexts) -> {
- Set<DexEncodedMethod> newContexts =
+ ProgramMethodSet newContexts =
rewritten.writesWithContexts.computeIfAbsent(
- lens.lookupField(access), ignore -> Sets.newIdentityHashSet());
- for (DexEncodedMethod context : contexts) {
- newContexts.add(lens.mapDexEncodedMethod(context, definitions));
+ lens.lookupField(access), ignore -> ProgramMethodSet.create());
+ for (ProgramMethod context : contexts) {
+ newContexts.add(lens.mapProgramMethod(context, definitions));
}
});
}
diff --git a/src/main/java/com/android/tools/r8/graph/FieldResolutionResult.java b/src/main/java/com/android/tools/r8/graph/FieldResolutionResult.java
new file mode 100644
index 0000000..e5d7239
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/FieldResolutionResult.java
@@ -0,0 +1,115 @@
+// Copyright (c) 2020, 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.graph;
+
+import com.android.tools.r8.utils.OptionalBool;
+
+public abstract class FieldResolutionResult {
+
+ public static FailedFieldResolutionResult failure() {
+ return FailedFieldResolutionResult.INSTANCE;
+ }
+
+ public static UnknownFieldResolutionResult unknown() {
+ return UnknownFieldResolutionResult.INSTANCE;
+ }
+
+ public DexEncodedField getResolvedField() {
+ return null;
+ }
+
+ public abstract OptionalBool isAccessibleFrom(
+ ProgramMethod context, AppInfoWithClassHierarchy appInfo);
+
+ public boolean isSuccessfulResolution() {
+ return false;
+ }
+
+ public SuccessfulFieldResolutionResult asSuccessfulResolution() {
+ return null;
+ }
+
+ public boolean isFailedOrUnknownResolution() {
+ return false;
+ }
+
+ public static class SuccessfulFieldResolutionResult extends FieldResolutionResult {
+
+ private final DexClass initialResolutionHolder;
+ private final DexClass resolvedHolder;
+ private final DexEncodedField resolvedField;
+
+ SuccessfulFieldResolutionResult(
+ DexClass initialResolutionHolder, DexClass resolvedHolder, DexEncodedField resolvedField) {
+ assert resolvedHolder.type == resolvedField.holder();
+ this.initialResolutionHolder = initialResolutionHolder;
+ this.resolvedHolder = resolvedHolder;
+ this.resolvedField = resolvedField;
+ }
+
+ public DexClass getResolvedHolder() {
+ return resolvedHolder;
+ }
+
+ @Override
+ public DexEncodedField getResolvedField() {
+ return resolvedField;
+ }
+
+ public DexClassAndField getResolutionPair() {
+ return DexClassAndField.create(resolvedHolder, resolvedField);
+ }
+
+ @Override
+ public OptionalBool isAccessibleFrom(ProgramMethod context, AppInfoWithClassHierarchy appInfo) {
+ return AccessControl.isFieldAccessible(
+ resolvedField, initialResolutionHolder, context.getHolder(), appInfo);
+ }
+
+ @Override
+ public boolean isSuccessfulResolution() {
+ return true;
+ }
+
+ @Override
+ public SuccessfulFieldResolutionResult asSuccessfulResolution() {
+ return this;
+ }
+ }
+
+ public static class FailedFieldResolutionResult extends FieldResolutionResult {
+
+ private static final FailedFieldResolutionResult INSTANCE = new FailedFieldResolutionResult();
+
+ @Override
+ public OptionalBool isAccessibleFrom(ProgramMethod context, AppInfoWithClassHierarchy appInfo) {
+ return OptionalBool.FALSE;
+ }
+
+ @Override
+ public boolean isFailedOrUnknownResolution() {
+ return true;
+ }
+ }
+
+ /**
+ * Used in D8 when trying to resolve a field that is not declared on the enclosing class of the
+ * current method.
+ */
+ public static class UnknownFieldResolutionResult extends FieldResolutionResult {
+
+ private static final UnknownFieldResolutionResult INSTANCE = new UnknownFieldResolutionResult();
+
+ @Override
+ public OptionalBool isAccessibleFrom(ProgramMethod context, AppInfoWithClassHierarchy appInfo) {
+ return OptionalBool.FALSE;
+ }
+
+ @Override
+ public boolean isFailedOrUnknownResolution() {
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLense.java b/src/main/java/com/android/tools/r8/graph/GraphLense.java
index e5de7ff..2a5f317 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLense.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLense.java
@@ -145,9 +145,6 @@
public DexEncodedMethod mapDexEncodedMethod(
DexEncodedMethod originalEncodedMethod, DexDefinitionSupplier definitions) {
assert originalEncodedMethod != DexEncodedMethod.SENTINEL;
- if (originalEncodedMethod == DexEncodedMethod.ANNOTATION_REFERENCE) {
- return DexEncodedMethod.ANNOTATION_REFERENCE;
- }
DexMethod newMethod = getRenamedMethodSignature(originalEncodedMethod.method);
// Note that:
// * Even if `newMethod` is the same as `originalEncodedMethod.method`, we still need to look it
@@ -161,6 +158,13 @@
return newEncodedMethod;
}
+ public ProgramMethod mapProgramMethod(
+ ProgramMethod oldMethod, DexDefinitionSupplier definitions) {
+ DexMethod newMethod = getRenamedMethodSignature(oldMethod.getReference());
+ DexProgramClass holder = definitions.definitionForHolder(newMethod).asProgramClass();
+ return holder.lookupProgramMethod(newMethod);
+ }
+
public abstract DexType lookupType(DexType type);
// This overload can be used when the graph lense is known to be context insensitive.
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramField.java b/src/main/java/com/android/tools/r8/graph/ProgramField.java
new file mode 100644
index 0000000..29949d8
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ProgramField.java
@@ -0,0 +1,33 @@
+// Copyright (c) 2020, 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.graph;
+
+public class ProgramField extends DexClassAndField {
+
+ public ProgramField(DexProgramClass holder, DexEncodedField field) {
+ super(holder, field);
+ }
+
+ public boolean isStructurallyEqualTo(ProgramField other) {
+ return getDefinition() == other.getDefinition() && getHolder() == other.getHolder();
+ }
+
+ @Override
+ public boolean isProgramField() {
+ return true;
+ }
+
+ @Override
+ public ProgramField asProgramField() {
+ return this;
+ }
+
+ @Override
+ public DexProgramClass getHolder() {
+ DexClass holder = super.getHolder();
+ assert holder.isProgramClass();
+ return holder.asProgramClass();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
index fd1781d..fab752df 100644
--- a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
@@ -62,6 +62,11 @@
public abstract OptionalBool isAccessibleFrom(
DexProgramClass context, AppInfoWithClassHierarchy appInfo);
+ public final OptionalBool isAccessibleFrom(
+ ProgramMethod context, AppInfoWithClassHierarchy appInfo) {
+ return isAccessibleFrom(context.getHolder(), appInfo);
+ }
+
public abstract OptionalBool isAccessibleForVirtualDispatchFrom(
DexProgramClass context, AppInfoWithClassHierarchy appInfo);
@@ -228,12 +233,12 @@
* result of resolution was a static, non-abstract method.
*
* @param context Class the invoke is contained in, i.e., the holder of the caller.
- * * @param appInfo Application info.
+ * @param appInfo Application info.
* @return The actual target or {@code null} if none found.
*/
@Override
- public DexEncodedMethod lookupInvokeStaticTarget(DexProgramClass context,
- AppInfoWithClassHierarchy appInfo) {
+ public DexEncodedMethod lookupInvokeStaticTarget(
+ DexProgramClass context, AppInfoWithClassHierarchy appInfo) {
if (isAccessibleFrom(context, appInfo).isFalse()) {
return null;
}
@@ -265,7 +270,7 @@
}
private DexEncodedMethod internalInvokeSpecialOrSuper(
- DexClass context,
+ DexProgramClass context,
AppInfoWithClassHierarchy appInfo,
BiPredicate<DexClass, DexClass> isSuperclass) {
@@ -669,8 +674,8 @@
}
@Override
- public DexEncodedMethod lookupInvokeStaticTarget(DexProgramClass context,
- AppInfoWithClassHierarchy appInfo) {
+ public DexEncodedMethod lookupInvokeStaticTarget(
+ DexProgramClass context, AppInfoWithClassHierarchy appInfo) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
index 06f544d..049e211 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
@@ -4,8 +4,9 @@
package com.android.tools.r8.graph.analysis;
-import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.EnqueuerWorklist;
@@ -17,10 +18,11 @@
public void processNewlyInstantiatedClass(DexProgramClass clazz, ProgramMethod context) {}
/** Called when a class is found to be live. */
- public void processNewlyLiveClass(DexProgramClass clazz, EnqueuerWorklist worklist) {}
+ public void processNewlyLiveClass(
+ DexProgramClass clazz, EnqueuerWorklist worklist, DexDefinitionSupplier definitionSupplier) {}
/** Called when a field is found to be live. */
- public void processNewlyLiveField(DexEncodedField field) {}
+ public void processNewlyLiveField(ProgramField field) {}
/** Called when a method is found to be live. */
public void processNewlyLiveMethod(ProgramMethod method) {}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java
index 48518f5..59c37b8 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java
@@ -6,7 +6,6 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
@@ -28,25 +27,26 @@
this.mapping = mapping;
}
- public boolean isClassDefinitelyLoadedInInstanceMethodsOn(DexType subject, DexType context) {
+ public boolean isClassDefinitelyLoadedInInstanceMethod(
+ DexProgramClass subject, ProgramMethod context) {
+ assert !context.getDefinition().isStatic();
// If `subject` is kept, then it is instantiated by reflection, which means that the analysis
// has not seen all allocation sites. In that case, we conservatively return false.
AppInfoWithClassHierarchy appInfo = appView.appInfo();
- if (appInfo.hasLiveness() && appInfo.withLiveness().isPinned(subject)) {
+ if (appInfo.hasLiveness() && appInfo.withLiveness().isPinned(subject.type)) {
return false;
}
// Check that `subject` is guaranteed to be initialized in all instance methods of `context`.
DexType guaranteedToBeInitializedInContext =
- mapping.getOrDefault(context, appView.dexItemFactory().objectType);
- if (!appInfo.isSubtype(guaranteedToBeInitializedInContext, subject)) {
+ mapping.getOrDefault(context.getHolderType(), appView.dexItemFactory().objectType);
+ if (!appInfo.isSubtype(guaranteedToBeInitializedInContext, subject.type)) {
return false;
}
// Also check that `subject` is not an interface, since interfaces are not initialized
// transitively.
- DexClass clazz = appView.definitionFor(subject);
- return clazz != null && !clazz.isInterface();
+ return !subject.isInterface();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
index e825ba4..978646c 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
@@ -10,9 +10,9 @@
import com.android.tools.r8.graph.DexDefinition;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -74,7 +74,6 @@
private final AppView<AppInfoWithLiveness> appView;
private final IRCode code;
- private final DexItemFactory dexItemFactory;
private DominatorTree dominatorTree = null;
private int markingColor = -1;
@@ -82,13 +81,11 @@
private ClassInitializationAnalysis() {
this.appView = null;
this.code = null;
- this.dexItemFactory = null;
}
public ClassInitializationAnalysis(AppView<AppInfoWithLiveness> appView, IRCode code) {
this.appView = appView;
this.code = code;
- this.dexItemFactory = appView.dexItemFactory();
}
// Returns a trivial, conservative analysis that always returns false.
@@ -97,7 +94,7 @@
}
public boolean isClassDefinitelyLoadedBeforeInstruction(DexType type, Instruction instruction) {
- DexType context = code.method().holder();
+ ProgramMethod context = code.context();
BasicBlock block = instruction.getBlock();
// Visit the instructions in `block` prior to `instruction`.
@@ -237,7 +234,7 @@
public static boolean forInitClass(
InitClass instruction,
DexType type,
- AppView<?> appView,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -251,7 +248,7 @@
public static boolean forInstanceGet(
InstanceGet instruction,
DexType type,
- AppView<?> appView,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return forInstanceGetOrPut(instruction, type, appView, mode, assumption);
@@ -260,7 +257,7 @@
public static boolean forInstancePut(
InstancePut instruction,
DexType type,
- AppView<?> appView,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return forInstanceGetOrPut(instruction, type, appView, mode, assumption);
@@ -269,7 +266,7 @@
private static boolean forInstanceGetOrPut(
FieldInstruction instruction,
DexType type,
- AppView<?> appView,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
assert instruction.isInstanceGet() || instruction.isInstancePut();
@@ -283,14 +280,15 @@
return false;
}
}
- DexEncodedField field = appView.appInfo().resolveField(instruction.getField());
+ DexEncodedField field =
+ appView.appInfo().resolveField(instruction.getField()).getResolvedField();
return field != null && isTypeInitializedBy(instruction, type, field, appView, mode);
}
public static boolean forInvokeDirect(
InvokeDirect instruction,
DexType type,
- AppView<?> appView,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -306,8 +304,8 @@
public static boolean forInvokeInterface(
InvokeInterface instruction,
DexType type,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -342,8 +340,8 @@
public static boolean forInvokeStatic(
InvokeStatic instruction,
DexType type,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -357,8 +355,8 @@
public static boolean forInvokeSuper(
InvokeSuper instruction,
DexType type,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -390,7 +388,7 @@
return false;
}
ResolutionResult resolutionResult =
- appView.appInfo().resolveMethod(superType, method, instruction.itf);
+ appView.appInfo().resolveMethodOn(superType, method, instruction.itf);
if (!resolutionResult.isSingleResolution()) {
return false;
}
@@ -401,8 +399,8 @@
public static boolean forInvokeVirtual(
InvokeVirtual instruction,
DexType type,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -426,7 +424,7 @@
}
DexMethod method = instruction.getInvokedMethod();
ResolutionResult resolutionResult =
- appView.appInfo().resolveMethodOnClass(method.holder, method);
+ appView.appInfo().resolveMethodOnClass(method, method.holder);
if (!resolutionResult.isSingleResolution()) {
return false;
}
@@ -437,7 +435,7 @@
public static boolean forNewInstance(
NewInstance instruction,
DexType type,
- AppView<?> appView,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
@@ -451,7 +449,7 @@
public static boolean forStaticGet(
StaticGet instruction,
DexType type,
- AppView<?> appView,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return forStaticGetOrPut(instruction, type, appView, mode, assumption);
@@ -460,7 +458,7 @@
public static boolean forStaticPut(
StaticPut instruction,
DexType type,
- AppView<?> appView,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return forStaticGetOrPut(instruction, type, appView, mode, assumption);
@@ -469,7 +467,7 @@
private static boolean forStaticGetOrPut(
FieldInstruction instruction,
DexType type,
- AppView<?> appView,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
assert instruction.isStaticGet() || instruction.isStaticPut();
@@ -477,7 +475,8 @@
// Class initialization may fail with ExceptionInInitializerError.
return false;
}
- DexEncodedField field = appView.appInfo().resolveField(instruction.getField());
+ DexEncodedField field =
+ appView.appInfo().resolveField(instruction.getField()).getResolvedField();
return field != null && isTypeInitializedBy(instruction, type, field, appView, mode);
}
@@ -485,7 +484,7 @@
Instruction instruction,
DexType typeToBeInitialized,
DexDefinition definition,
- AppView<?> appView,
+ AppView<AppInfoWithLiveness> appView,
Query mode) {
if (mode == Query.DIRECTLY) {
if (definition.isDexClass()) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/DeterminismAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/DeterminismAnalysis.java
index 5452f50..32c1bb1 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/DeterminismAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/DeterminismAnalysis.java
@@ -37,7 +37,7 @@
}
if (instr.isInvokeMethod()) {
DexEncodedMethod target =
- instr.asInvokeMethod().lookupSingleTarget(appView, code.method().holder());
+ instr.asInvokeMethod().lookupSingleTarget(appView, code.context());
if (target != null && target.getOptimizationInfo().returnValueOnlyDependsOnArguments()) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/InitializedClassesOnNormalExitAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/InitializedClassesOnNormalExitAnalysis.java
index 215f2a1..b73a496 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/InitializedClassesOnNormalExitAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/InitializedClassesOnNormalExitAnalysis.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.DefaultInstructionVisitor;
import com.android.tools.r8.ir.code.DominatorTree;
@@ -36,7 +37,7 @@
public static Set<DexType> computeInitializedClassesOnNormalExit(
AppView<AppInfoWithLiveness> appView, IRCode code) {
DominatorTree dominatorTree = new DominatorTree(code, Assumption.MAY_HAVE_UNREACHABLE_BLOCKS);
- Visitor visitor = new Visitor(appView, code.method().holder());
+ Visitor visitor = new Visitor(appView, code.context());
for (BasicBlock dominator : dominatorTree.normalExitDominatorBlocks()) {
if (dominator.hasCatchHandlers()) {
// When determining which classes that are guaranteed to be initialized from a given
@@ -55,10 +56,10 @@
private static class Visitor extends DefaultInstructionVisitor<Void> {
private final AppView<AppInfoWithLiveness> appView;
- private final DexType context;
+ private final ProgramMethod context;
private final Set<DexType> initializedClassesOnNormalExit = Sets.newIdentityHashSet();
- Visitor(AppView<AppInfoWithLiveness> appView, DexType context) {
+ Visitor(AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
this.appView = appView;
this.context = context;
}
@@ -72,7 +73,7 @@
}
private void markInitializedOnNormalExit(DexType knownToBeInitialized) {
- if (knownToBeInitialized == context) {
+ if (knownToBeInitialized == context.getHolderType()) {
// Do not record that the given method causes its own holder to be initialized, since this
// is trivial.
return;
@@ -113,7 +114,8 @@
@Override
public Void handleFieldInstruction(FieldInstruction instruction) {
- DexEncodedField field = appView.appInfo().resolveField(instruction.getField());
+ DexEncodedField field =
+ appView.appInfo().resolveField(instruction.getField()).getResolvedField();
if (field != null) {
if (field.holder().isClassType()) {
markInitializedOnNormalExit(field.holder());
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java
index fbb6735..82e53b7 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.IRCode;
@@ -27,8 +27,6 @@
import com.android.tools.r8.utils.LongInterval;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
-import java.util.List;
-import java.util.Map;
import java.util.Set;
/**
@@ -69,19 +67,15 @@
private final AppView<?> appView;
private final IRCode code;
- private final DexType context;
+ private final ProgramMethod context;
private final Set<Value> knownNotToDependOnEnvironment = Sets.newIdentityHashSet();
private final Set<Value> visited = Sets.newIdentityHashSet();
- // Lazily computed mapping from final field definitions of the enclosing class to the static-put
- // instructions in the class initializer that assigns these final fields.
- private Map<DexEncodedField, List<StaticPut>> finalFieldPuts;
-
public ValueMayDependOnEnvironmentAnalysis(AppView<?> appView, IRCode code) {
this.appView = appView;
this.code = code;
- this.context = code.method().holder();
+ this.context = code.context();
}
public boolean valueMayDependOnEnvironment(Value value) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java b/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java
index 27c4e19..e4235e6 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java
@@ -8,7 +8,7 @@
import static com.google.common.base.Predicates.or;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstClass;
import com.android.tools.r8.ir.code.ConstNumber;
@@ -33,9 +33,9 @@
public class BasicBlockBehavioralSubsumption {
private final AppView<?> appView;
- private final DexType context;
+ private final ProgramMethod context;
- public BasicBlockBehavioralSubsumption(AppView<?> appView, DexType context) {
+ public BasicBlockBehavioralSubsumption(AppView<?> appView, ProgramMethod context) {
this.appView = appView;
this.context = context;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/escape/DefaultEscapeAnalysisConfiguration.java b/src/main/java/com/android/tools/r8/ir/analysis/escape/DefaultEscapeAnalysisConfiguration.java
index 6ec09bb..b65eda2 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/escape/DefaultEscapeAnalysisConfiguration.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/escape/DefaultEscapeAnalysisConfiguration.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.ir.analysis.escape;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.Instruction;
public class DefaultEscapeAnalysisConfiguration implements EscapeAnalysisConfiguration {
@@ -24,7 +24,7 @@
AppView<?> appView,
EscapeAnalysis escapeAnalysis,
Instruction escapeRoute,
- DexMethod context) {
+ ProgramMethod context) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysis.java
index b1cac80..b1821c3 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysis.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -137,8 +138,8 @@
}
}
}
- if (!configuration.isLegitimateEscapeRoute(appView, this, user, code.method().method)
- && isDirectlyEscaping(user, code.method().method, arguments)) {
+ if (!configuration.isLegitimateEscapeRoute(appView, this, user, code.context())
+ && isDirectlyEscaping(user, code.context(), arguments)) {
if (stoppingCriterion.test(user)) {
return true;
}
@@ -173,7 +174,8 @@
}
}
- private boolean isDirectlyEscaping(Instruction instr, DexMethod context, List<Value> arguments) {
+ private boolean isDirectlyEscaping(
+ Instruction instr, ProgramMethod context, List<Value> arguments) {
// As return value.
if (instr.isReturn()) {
return true;
@@ -190,7 +192,7 @@
if (instr.isInvokeMethod()) {
DexMethod invokedMethod = instr.asInvokeMethod().getInvokedMethod();
// Filter out the recursion with exactly same arguments.
- if (invokedMethod == context) {
+ if (invokedMethod == context.getReference()) {
return !instr.inValues().equals(arguments);
}
return true;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysisConfiguration.java b/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysisConfiguration.java
index ea3a7e3..e3e5f4b 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysisConfiguration.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysisConfiguration.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.ir.analysis.escape;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.Instruction;
public interface EscapeAnalysisConfiguration {
@@ -14,5 +14,5 @@
AppView<?> appView,
EscapeAnalysis escapeAnalysis,
Instruction escapeRoute,
- DexMethod context);
+ ProgramMethod context);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAccessAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAccessAnalysis.java
index 7c148a4..015b182 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAccessAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAccessAnalysis.java
@@ -6,9 +6,11 @@
import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.FieldResolutionResult;
+import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.ir.code.FieldInstruction;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -21,7 +23,7 @@
public class FieldAccessAnalysis {
- private final AppView<?> appView;
+ private final AppView<? extends AppInfoWithClassHierarchy> appView;
private final FieldAssignmentTracker fieldAssignmentTracker;
private final FieldBitAccessAnalysis fieldBitAccessAnalysis;
@@ -35,7 +37,7 @@
}
public FieldAccessAnalysis(
- AppView<?> appView,
+ AppView<? extends AppInfoWithClassHierarchy> appView,
FieldAssignmentTracker fieldAssignmentTracker,
FieldBitAccessAnalysis fieldBitAccessAnalysis) {
this.appView = appView;
@@ -71,13 +73,20 @@
for (Instruction instruction : code.instructions()) {
if (instruction.isFieldInstruction()) {
FieldInstruction fieldInstruction = instruction.asFieldInstruction();
- DexEncodedField encodedField = appView.appInfo().resolveField(fieldInstruction.getField());
- if (encodedField != null && encodedField.isProgramField(appView)) {
- if (fieldAssignmentTracker != null) {
- fieldAssignmentTracker.recordFieldAccess(fieldInstruction, encodedField, code.method());
- }
- if (fieldBitAccessAnalysis != null) {
- fieldBitAccessAnalysis.recordFieldAccess(fieldInstruction, encodedField, feedback);
+ FieldResolutionResult resolutionResult =
+ appView.appInfo().resolveField(fieldInstruction.getField());
+ if (resolutionResult.isSuccessfulResolution()) {
+ ProgramField field =
+ resolutionResult.asSuccessfulResolution().getResolutionPair().asProgramField();
+ if (field != null) {
+ if (fieldAssignmentTracker != null) {
+ fieldAssignmentTracker.recordFieldAccess(
+ fieldInstruction, field.getDefinition(), code.context());
+ }
+ if (fieldBitAccessAnalysis != null) {
+ fieldBitAccessAnalysis.recordFieldAccess(
+ fieldInstruction, field.getDefinition(), feedback);
+ }
}
}
} else if (instruction.isNewInstance()) {
@@ -85,7 +94,7 @@
DexProgramClass clazz = asProgramClassOrNull(appView.definitionFor(newInstance.clazz));
if (clazz != null) {
if (fieldAssignmentTracker != null) {
- fieldAssignmentTracker.recordAllocationSite(newInstance, clazz, code.method());
+ fieldAssignmentTracker.recordAllocationSite(newInstance, clazz, code.context());
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
index 5e29668..fbb6443 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
@@ -119,13 +119,13 @@
}
void recordFieldAccess(
- FieldInstruction instruction, DexEncodedField field, DexEncodedMethod context) {
+ FieldInstruction instruction, DexEncodedField field, ProgramMethod context) {
if (instruction.isFieldPut()) {
recordFieldPut(field, instruction.value(), context);
}
}
- private void recordFieldPut(DexEncodedField field, Value value, DexEncodedMethod context) {
+ private void recordFieldPut(DexEncodedField field, Value value, ProgramMethod context) {
assert verifyValueIsConsistentWithFieldOptimizationInfo(
value, field.getOptimizationInfo(), context);
if (!value.isZero()) {
@@ -133,8 +133,7 @@
}
}
- void recordAllocationSite(
- NewInstance instruction, DexProgramClass clazz, DexEncodedMethod context) {
+ void recordAllocationSite(NewInstance instruction, DexProgramClass clazz, ProgramMethod context) {
Map<DexEncodedField, AbstractValue> abstractInstanceFieldValuesForClass =
abstractInstanceFieldValues.get(clazz);
if (abstractInstanceFieldValuesForClass == null) {
@@ -149,7 +148,7 @@
return;
}
- DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, context.holder());
+ DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, context);
if (singleTarget == null) {
// We just lost track.
abstractInstanceFieldValues.remove(clazz);
@@ -174,7 +173,7 @@
initializationInfo.asArgumentInitializationInfo();
Value argument = invoke.arguments().get(argumentInitializationInfo.getArgumentIndex());
AbstractValue abstractValue =
- entry.getValue().join(argument.getAbstractValue(appView, context.holder()));
+ entry.getValue().join(argument.getAbstractValue(appView, context));
assert !abstractValue.isBottom();
if (!abstractValue.isUnknown()) {
entry.setValue(abstractValue);
@@ -290,12 +289,12 @@
}
private boolean verifyValueIsConsistentWithFieldOptimizationInfo(
- Value value, FieldOptimizationInfo optimizationInfo, DexEncodedMethod context) {
+ Value value, FieldOptimizationInfo optimizationInfo, ProgramMethod context) {
AbstractValue abstractValue = optimizationInfo.getAbstractValue();
if (abstractValue.isUnknown()) {
return true;
}
- assert abstractValue == value.getAbstractValue(appView, context.holder());
+ assert abstractValue == value.getAbstractValue(appView, context);
return true;
}
@@ -315,7 +314,8 @@
fieldAccessInfoCollection.flattenAccessContexts();
fieldAccessInfoCollection.forEach(
info -> {
- DexEncodedField field = appView.appInfo().resolveField(info.getField());
+ DexEncodedField field =
+ appView.appInfo().resolveField(info.getField()).getResolvedField();
if (field == null) {
assert false;
return;
@@ -323,7 +323,9 @@
if (!info.hasReflectiveAccess() && !info.isWrittenFromMethodHandle()) {
info.forEachWriteContext(
context ->
- fieldWrites.computeIfAbsent(context, ignore -> new ArrayList<>()).add(field));
+ fieldWrites
+ .computeIfAbsent(context.getDefinition(), ignore -> new ArrayList<>())
+ .add(field));
pendingFieldWrites.put(field, info.getNumberOfWriteContexts());
}
});
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java
index 1a6a707..b5bf1c4 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/TrivialFieldAccessReprocessor.java
@@ -162,7 +162,7 @@
}
private boolean registerFieldAccess(DexField field, boolean isStatic) {
- DexEncodedField encodedField = appView.appInfo().resolveField(field);
+ DexEncodedField encodedField = appView.appInfo().resolveField(field).getResolvedField();
if (encodedField != null) {
if (encodedField.isStatic() == isStatic) {
if (fieldsOfInterest.contains(encodedField)) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
index 08989c0..e4bf2a9 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
@@ -6,10 +6,8 @@
import com.android.tools.r8.graph.AppView;
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.DexProgramClass;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.DominatorTree;
import com.android.tools.r8.ir.code.DominatorTree.Assumption;
@@ -32,10 +30,9 @@
public abstract class FieldValueAnalysis {
final AppView<AppInfoWithLiveness> appView;
- final DexProgramClass clazz;
final IRCode code;
+ final ProgramMethod context;
final OptimizationFeedback feedback;
- final DexEncodedMethod method;
private DominatorTree dominatorTree;
private Map<BasicBlock, AbstractFieldSet> fieldsMaybeReadBeforeBlockInclusiveCache;
@@ -43,18 +40,11 @@
final Map<DexEncodedField, LinkedList<FieldInstruction>> putsPerField = new IdentityHashMap<>();
FieldValueAnalysis(
- AppView<AppInfoWithLiveness> appView,
- IRCode code,
- OptimizationFeedback feedback,
- DexProgramClass clazz,
- DexEncodedMethod method) {
- assert clazz != null;
- assert clazz.type == method.holder();
+ AppView<AppInfoWithLiveness> appView, IRCode code, OptimizationFeedback feedback) {
this.appView = appView;
- this.clazz = clazz;
this.code = code;
this.feedback = feedback;
- this.method = method;
+ this.context = code.context();
}
DominatorTree getOrCreateDominatorTree() {
@@ -88,7 +78,7 @@
if (instruction.isFieldPut()) {
FieldInstruction fieldPut = instruction.asFieldInstruction();
DexField field = fieldPut.getField();
- DexEncodedField encodedField = appInfo.resolveField(field);
+ DexEncodedField encodedField = appInfo.resolveField(field).getResolvedField();
if (encodedField != null && isSubjectToOptimization(encodedField)) {
putsPerField.computeIfAbsent(encodedField, ignore -> new LinkedList<>()).add(fieldPut);
}
@@ -129,7 +119,6 @@
// Then check if any of the instructions that precede the given instruction in the current block
// may read the field.
- DexType context = method.holder();
InstructionIterator instructionIterator = block.iterator();
while (instructionIterator.hasNext()) {
Instruction current = instructionIterator.next();
@@ -164,7 +153,6 @@
* and its transitive predecessors.
*/
private Map<BasicBlock, AbstractFieldSet> createFieldsMaybeReadBeforeBlockInclusive() {
- DexType context = method.holder();
Map<BasicBlock, AbstractFieldSet> result = new IdentityHashMap<>();
Deque<BasicBlock> worklist = DequeUtils.newArrayDeque(code.entryBlock());
while (!worklist.isEmpty()) {
@@ -249,7 +237,7 @@
}
private boolean verifyFieldSetContainsAllFieldReadsInBlock(
- KnownFieldSet readSet, BasicBlock block, DexType context) {
+ KnownFieldSet readSet, BasicBlock block, ProgramMethod context) {
for (Instruction instruction : block.getInstructions()) {
AbstractFieldSet instructionReadSet = instruction.readSet(appView, context);
assert !instructionReadSet.isTop();
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
index 58b4194..b818cc2 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -48,11 +47,9 @@
AppView<AppInfoWithLiveness> appView,
IRCode code,
OptimizationFeedback feedback,
- DexProgramClass clazz,
- DexEncodedMethod method,
DexEncodedMethod parentConstructor,
InvokeDirect parentConstructorCall) {
- super(appView, code, feedback, clazz, method);
+ super(appView, code, feedback);
this.factory = appView.instanceFieldInitializationInfoFactory();
this.parentConstructor = parentConstructor;
this.parentConstructorCall = parentConstructorCall;
@@ -67,11 +64,10 @@
IRCode code,
ClassInitializerDefaultsResult classInitializerDefaultsResult,
OptimizationFeedback feedback,
- DexEncodedMethod method,
Timing timing) {
timing.begin("Analyze instance initializer");
InstanceFieldInitializationInfoCollection result =
- run(appView, code, classInitializerDefaultsResult, feedback, method);
+ run(appView, code, classInitializerDefaultsResult, feedback);
timing.end();
return result;
}
@@ -80,16 +76,10 @@
AppView<?> appView,
IRCode code,
ClassInitializerDefaultsResult classInitializerDefaultsResult,
- OptimizationFeedback feedback,
- DexEncodedMethod method) {
+ OptimizationFeedback feedback) {
assert appView.appInfo().hasLiveness();
assert appView.enableWholeProgramOptimizations();
- assert method.isInstanceInitializer();
-
- DexProgramClass clazz = appView.definitionFor(method.holder()).asProgramClass();
- if (!appView.options().enableValuePropagationForInstanceFields) {
- return EmptyInstanceFieldInitializationInfoCollection.getInstance();
- }
+ assert code.context().getDefinition().isInstanceInitializer();
InvokeDirect parentConstructorCall =
IRCodeUtils.getUniqueConstructorInvoke(code.getThis(), appView.dexItemFactory());
@@ -98,7 +88,7 @@
}
DexEncodedMethod parentConstructor =
- parentConstructorCall.lookupSingleTarget(appView, clazz.type);
+ parentConstructorCall.lookupSingleTarget(appView, code.context());
if (parentConstructor == null) {
return EmptyInstanceFieldInitializationInfoCollection.getInstance();
}
@@ -108,8 +98,6 @@
appView.withLiveness(),
code,
feedback,
- clazz,
- method,
parentConstructor,
parentConstructorCall);
analysis.computeFieldOptimizationInfo(classInitializerDefaultsResult);
@@ -119,7 +107,7 @@
@Override
boolean isSubjectToOptimization(DexEncodedField field) {
- return !field.isStatic() && field.holder() == clazz.type;
+ return !field.isStatic() && field.holder() == context.getHolderType();
}
@Override
@@ -160,7 +148,7 @@
return;
}
- AbstractValue abstractValue = value.getAbstractValue(appView, clazz.type);
+ AbstractValue abstractValue = value.getAbstractValue(appView, context);
if (abstractValue.isSingleValue()) {
builder.recordInitializationInfo(field, abstractValue.asSingleValue());
return;
@@ -185,12 +173,12 @@
return true;
}
- if (appView.appInfo().isFieldOnlyWrittenInMethod(field, method)) {
+ if (appView.appInfo().isFieldOnlyWrittenInMethod(field, context.getDefinition())) {
return true;
}
if (appView.appInfo().isInstanceFieldWrittenOnlyInInstanceInitializers(field)) {
- if (parentConstructorCall.getInvokedMethod().holder != clazz.type) {
+ if (parentConstructorCall.getInvokedMethod().holder != context.getHolderType()) {
// The field is only written in instance initializers of the enclosing class, and the
// constructor call targets a constructor in the super class.
return true;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
index f488267..81df82a 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -38,12 +37,8 @@
public class StaticFieldValueAnalysis extends FieldValueAnalysis {
private StaticFieldValueAnalysis(
- AppView<AppInfoWithLiveness> appView,
- IRCode code,
- OptimizationFeedback feedback,
- DexProgramClass clazz,
- DexEncodedMethod method) {
- super(appView, code, feedback, clazz, method);
+ AppView<AppInfoWithLiveness> appView, IRCode code, OptimizationFeedback feedback) {
+ super(appView, code, feedback);
}
public static void run(
@@ -51,14 +46,12 @@
IRCode code,
ClassInitializerDefaultsResult classInitializerDefaultsResult,
OptimizationFeedback feedback,
- DexEncodedMethod method,
Timing timing) {
assert appView.appInfo().hasLiveness();
assert appView.enableWholeProgramOptimizations();
- assert method.isClassInitializer();
+ assert code.context().getDefinition().isClassInitializer();
timing.begin("Analyze class initializer");
- DexProgramClass clazz = appView.definitionFor(method.holder()).asProgramClass();
- new StaticFieldValueAnalysis(appView.withLiveness(), code, feedback, clazz, method)
+ new StaticFieldValueAnalysis(appView.withLiveness(), code, feedback)
.computeFieldOptimizationInfo(classInitializerDefaultsResult);
timing.end();
}
@@ -70,7 +63,7 @@
classInitializerDefaultsResult.forEachOptimizedField(
(field, value) -> {
if (putsPerField.containsKey(field)
- || !appView.appInfo().isFieldOnlyWrittenInMethod(field, method)) {
+ || !appView.appInfo().isFieldOnlyWrittenInMethod(field, context.getDefinition())) {
return;
}
@@ -96,15 +89,15 @@
@Override
boolean isSubjectToOptimization(DexEncodedField field) {
return field.isStatic()
- && field.holder() == clazz.type
- && appView.appInfo().isFieldOnlyWrittenInMethod(field, method);
+ && field.holder() == context.getHolderType()
+ && appView.appInfo().isFieldOnlyWrittenInMethod(field, context.getDefinition());
}
@Override
void updateFieldOptimizationInfo(DexEncodedField field, FieldInstruction fieldPut, Value value) {
// Abstract value.
Value root = value.getAliasedValue();
- AbstractValue abstractValue = root.getAbstractValue(appView, clazz.type);
+ AbstractValue abstractValue = root.getAbstractValue(appView, context);
if (abstractValue.isUnknown()) {
feedback.recordFieldHasAbstractValue(field, appView, computeSingleFieldValue(field, root));
} else {
@@ -149,12 +142,13 @@
*/
private SingleFieldValue computeSingleEnumFieldValue(Value value) {
assert !value.hasAliasedValue();
- if (!clazz.isEnum() || !value.isDefinedByInstructionSatisfying(Instruction::isNewInstance)) {
+ if (!context.getHolder().isEnum()
+ || !value.isDefinedByInstructionSatisfying(Instruction::isNewInstance)) {
return null;
}
NewInstance newInstance = value.definition.asNewInstance();
- if (newInstance.clazz != clazz.type) {
+ if (newInstance.clazz != context.getHolderType()) {
return null;
}
@@ -183,7 +177,8 @@
break;
case STATIC_PUT:
- DexEncodedField field = clazz.lookupStaticField(user.asStaticPut().getField());
+ DexEncodedField field =
+ context.getHolder().lookupStaticField(user.asStaticPut().getField());
if (field != null && field.accessFlags.isEnum()) {
if (enumField != null) {
return null;
@@ -219,7 +214,7 @@
return ObjectState.empty();
}
- DexEncodedMethod singleTarget = uniqueConstructorInvoke.lookupSingleTarget(appView, clazz.type);
+ DexEncodedMethod singleTarget = uniqueConstructorInvoke.lookupSingleTarget(appView, context);
if (singleTarget == null) {
return ObjectState.empty();
}
@@ -242,7 +237,7 @@
initializationInfo.asArgumentInitializationInfo();
Value argument =
uniqueConstructorInvoke.getArgument(argumentInitializationInfo.getArgumentIndex());
- builder.recordFieldHasValue(field, argument.getAbstractValue(appView, clazz.type));
+ builder.recordFieldHasValue(field, argument.getAbstractValue(appView, context));
} else if (initializationInfo.isSingleValue()) {
builder.recordFieldHasValue(field, initializationInfo.asSingleValue());
}
@@ -251,12 +246,12 @@
}
private boolean isEnumValuesArray(Value value) {
- assert clazz.isEnum();
+ assert context.getHolder().isEnum();
DexItemFactory dexItemFactory = appView.dexItemFactory();
DexField valuesField =
dexItemFactory.createField(
- clazz.type,
- clazz.type.toArrayType(1, dexItemFactory),
+ context.getHolderType(),
+ context.getHolderType().toArrayType(1, dexItemFactory),
dexItemFactory.enumValuesFieldName);
Value root = value.getAliasedValue();
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
index 4879783..400b509 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
@@ -6,7 +6,6 @@
import com.android.tools.r8.graph.AppView;
-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;
@@ -14,6 +13,8 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldAccessInfo;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
+import com.android.tools.r8.graph.FieldResolutionResult;
+import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.IRCodeUtils;
@@ -178,42 +179,39 @@
});
}
- public boolean isDeadProtoExtensionField(DexField field) {
+ public boolean isDeadProtoExtensionField(DexField fieldReference) {
AppInfoWithLiveness appInfo = appView.appInfo();
- DexEncodedField encodedField = appInfo.resolveField(field);
- if (encodedField != null) {
- return isDeadProtoExtensionField(
- encodedField, appInfo.getFieldAccessInfoCollection(), appInfo.getPinnedItems());
+ FieldResolutionResult resolutionResult = appInfo.resolveField(fieldReference);
+ if (resolutionResult.isSuccessfulResolution()) {
+ ProgramField field =
+ resolutionResult.asSuccessfulResolution().getResolutionPair().asProgramField();
+ return field != null
+ && isDeadProtoExtensionField(
+ field, appInfo.getFieldAccessInfoCollection(), appInfo.getPinnedItems());
}
return false;
}
public boolean isDeadProtoExtensionField(
- DexEncodedField encodedField,
+ ProgramField field,
FieldAccessInfoCollection<?> fieldAccessInfoCollection,
Set<DexReference> pinnedItems) {
- DexField field = encodedField.field;
- if (pinnedItems.contains(field)) {
+ if (pinnedItems.contains(field.getReference())) {
return false;
}
- if (field.type != references.generatedExtensionType) {
+ if (field.getReference().type != references.generatedExtensionType) {
return false;
}
- DexClass clazz = appView.definitionFor(encodedField.holder());
- if (clazz == null || !clazz.isProgramClass()) {
- return false;
- }
-
- FieldAccessInfo fieldAccessInfo = fieldAccessInfoCollection.get(encodedField.field);
+ FieldAccessInfo fieldAccessInfo = fieldAccessInfoCollection.get(field.getReference());
if (fieldAccessInfo == null) {
return false;
}
- DexEncodedMethod uniqueReadContext = fieldAccessInfo.getUniqueReadContext();
+ ProgramMethod uniqueReadContext = fieldAccessInfo.getUniqueReadContext();
return uniqueReadContext != null
- && references.isFindLiteExtensionByNumberMethod(uniqueReadContext.method);
+ && references.isFindLiteExtensionByNumberMethod(uniqueReadContext);
}
private void forEachDeadProtoExtensionField(Consumer<DexField> consumer) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java
index c2c9a50..861c0cd 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java
@@ -140,6 +140,10 @@
&& method.holder != extensionRegistryLiteType;
}
+ public boolean isFindLiteExtensionByNumberMethod(ProgramMethod method) {
+ return isFindLiteExtensionByNumberMethod(method.getReference());
+ }
+
public boolean isGeneratedMessageLiteBuilder(DexProgramClass clazz) {
return (clazz.superType == generatedMessageLiteBuilderType
|| clazz.superType == generatedMessageLiteExtendableBuilderType)
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
index 8001121..d1bf3d1 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
@@ -8,12 +8,15 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
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.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.FieldResolutionResult;
+import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.analysis.EnqueuerAnalysis;
import com.android.tools.r8.ir.analysis.proto.GeneratedMessageLiteShrinker;
@@ -56,7 +59,7 @@
// keep fields that could reach extensions to be conservative.
public class ProtoEnqueuerExtension extends EnqueuerAnalysis {
- private final AppView<?> appView;
+ private final AppView<? extends AppInfoWithClassHierarchy> appView;
private final RawMessageInfoDecoder decoder;
private final ProtoFieldTypeFactory factory;
private final ProtoReferences references;
@@ -85,7 +88,7 @@
// Mapping from extension container types to the extensions for that type.
private final Map<DexType, Set<DexType>> extensionGraph = new IdentityHashMap<>();
- public ProtoEnqueuerExtension(AppView<?> appView) {
+ public ProtoEnqueuerExtension(AppView<? extends AppInfoWithClassHierarchy> appView) {
ProtoShrinker protoShrinker = appView.protoShrinker();
this.appView = appView;
this.decoder = protoShrinker.decoder;
@@ -94,7 +97,8 @@
}
@Override
- public void processNewlyLiveClass(DexProgramClass clazz, EnqueuerWorklist worklist) {
+ public void processNewlyLiveClass(
+ DexProgramClass clazz, EnqueuerWorklist worklist, DexDefinitionSupplier definitionSupplier) {
assert appView.appInfo().hasClassHierarchy();
AppInfoWithClassHierarchy appInfo = appView.appInfo().withClassHierarchy();
if (appInfo.isStrictSubtypeOf(clazz.type, references.generatedMessageLiteType)) {
@@ -258,7 +262,8 @@
Instruction definition = returnValue.definition;
if (definition.isStaticGet()) {
StaticGet staticGet = definition.asStaticGet();
- DexEncodedField field = appView.appInfo().resolveField(staticGet.getField());
+ DexEncodedField field =
+ appView.appInfo().resolveField(staticGet.getField()).getResolvedField();
if (field == null) {
assert false;
continue;
@@ -355,7 +360,7 @@
ProgramMethod dynamicMethod = protoMessageInfo.getDynamicMethod();
for (ProtoFieldInfo protoFieldInfo : protoMessageInfo.getFields()) {
- DexEncodedField valueStorage = protoFieldInfo.getValueStorage(appView, protoMessageInfo);
+ ProgramField valueStorage = protoFieldInfo.getValueStorage(appView, protoMessageInfo);
if (valueStorage == null) {
continue;
}
@@ -369,21 +374,21 @@
// (i) optimize field reads into loading the default value of the field or (ii) remove
// field writes to proto fields that could be read using reflection by the proto
// library.
- enqueuer.registerReflectiveFieldAccess(valueStorage.field, dynamicMethod);
+ enqueuer.registerReflectiveFieldAccess(valueStorage.getReference(), dynamicMethod);
}
valueStorageIsLive = true;
} else if (reachesMapOrRequiredField(protoFieldInfo)) {
// Map/required fields cannot be removed. Therefore, we mark such fields as both read and
// written such that we cannot optimize any field reads or writes.
- enqueuer.registerReflectiveFieldAccess(valueStorage.field, dynamicMethod);
+ enqueuer.registerReflectiveFieldAccess(valueStorage.getReference(), dynamicMethod);
worklist.enqueueMarkReachableFieldAction(
- dynamicMethod.getHolder(), valueStorage, KeepReason.reflectiveUseIn(dynamicMethod));
+ valueStorage, KeepReason.reflectiveUseIn(dynamicMethod));
valueStorageIsLive = true;
} else {
valueStorageIsLive = false;
}
- DexEncodedField newlyLiveField = null;
+ ProgramField newlyLiveField = null;
if (valueStorageIsLive) {
// For one-of fields, mark the corresponding one-of-case field as live, and for proto2
// singular fields, mark the corresponding hazzer-bit field as live.
@@ -391,27 +396,28 @@
newlyLiveField = protoFieldInfo.getOneOfCaseField(appView, protoMessageInfo);
} else if (protoFieldInfo.hasHazzerBitField(protoMessageInfo)) {
newlyLiveField = protoFieldInfo.getHazzerBitField(appView, protoMessageInfo);
- enqueuer.registerReflectiveFieldAccess(valueStorage.field, dynamicMethod);
+ enqueuer.registerReflectiveFieldAccess(valueStorage.getReference(), dynamicMethod);
}
} else {
// For one-of fields, mark the one-of field as live if the one-of-case field is live, and
// for proto2 singular fields, mark the field as live if the corresponding hazzer-bit
// field is live.
if (protoFieldInfo.getType().isOneOf()) {
- DexEncodedField oneOfCaseField =
+ ProgramField oneOfCaseField =
protoFieldInfo.getOneOfCaseField(appView, protoMessageInfo);
if (oneOfCaseField != null && enqueuer.isFieldLive(oneOfCaseField)) {
newlyLiveField = valueStorage;
}
} else if (protoFieldInfo.hasHazzerBitField(protoMessageInfo)) {
- DexEncodedField hazzerBitField =
+ ProgramField hazzerBitField =
protoFieldInfo.getHazzerBitField(appView, protoMessageInfo);
if (hazzerBitField == null || !enqueuer.isFieldLive(hazzerBitField)) {
continue;
}
if (appView.options().enableFieldBitAccessAnalysis && appView.isAllCodeProcessed()) {
- FieldOptimizationInfo optimizationInfo = hazzerBitField.getOptimizationInfo();
+ FieldOptimizationInfo optimizationInfo =
+ hazzerBitField.getDefinition().getOptimizationInfo();
int hazzerBitIndex = protoFieldInfo.getHazzerBitFieldIndex(protoMessageInfo);
if (!BitUtils.isBitSet(optimizationInfo.getReadBits(), hazzerBitIndex)) {
continue;
@@ -428,20 +434,19 @@
ProgramMethod defaultInitializer =
dynamicMethod.getHolder().getProgramDefaultInitializer();
assert defaultInitializer != null;
- Predicate<DexEncodedMethod> neitherDefaultConstructorNorDynamicMethod =
+ Predicate<ProgramMethod> neitherDefaultConstructorNorDynamicMethod =
writer ->
- writer != defaultInitializer.getDefinition()
- && writer != dynamicMethod.getDefinition();
+ !writer.isStructurallyEqualTo(defaultInitializer)
+ && !writer.isStructurallyEqualTo(dynamicMethod);
if (enqueuer.isFieldWrittenInMethodSatisfying(
newlyLiveField, neitherDefaultConstructorNorDynamicMethod)) {
- enqueuer.registerReflectiveFieldRead(newlyLiveField.field, dynamicMethod);
+ enqueuer.registerReflectiveFieldRead(newlyLiveField.getReference(), dynamicMethod);
}
// Unconditionally register the hazzer and one-of proto fields as written from
// dynamicMethod().
- if (enqueuer.registerReflectiveFieldWrite(newlyLiveField.field, dynamicMethod)) {
+ if (enqueuer.registerReflectiveFieldWrite(newlyLiveField.getReference(), dynamicMethod)) {
worklist.enqueueMarkReachableFieldAction(
- dynamicMethod.getHolder(),
newlyLiveField,
KeepReason.reflectiveUseIn(dynamicMethod));
}
@@ -474,7 +479,7 @@
// NOTE: If `valueStorage` is not a live field, then code for it will not be emitted in the
// schema, and therefore we do need to trace the const-class instructions that will be
// emitted for it.
- DexEncodedField valueStorage = protoFieldInfo.getValueStorage(appView, protoMessageInfo);
+ ProgramField valueStorage = protoFieldInfo.getValueStorage(appView, protoMessageInfo);
if (valueStorage != null && enqueuer.isFieldLive(valueStorage)) {
for (ProtoObject object : objects) {
if (object.isProtoObjectFromStaticGet()) {
@@ -511,27 +516,32 @@
return;
}
- DexField oneOfCaseField = oneOfCaseObject.asLiveProtoFieldObject().getField();
- DexEncodedField encodedOneOfCaseField = appView.appInfo().resolveField(oneOfCaseField);
- if (encodedOneOfCaseField == null) {
+ DexField oneOfCaseFieldReference = oneOfCaseObject.asLiveProtoFieldObject().getField();
+ FieldResolutionResult oneOfCaseFieldResolutionResult =
+ appView.appInfo().resolveField(oneOfCaseFieldReference);
+ if (oneOfCaseFieldResolutionResult.isFailedOrUnknownResolution()) {
assert false;
return;
}
- DexProgramClass clazz =
- asProgramClassOrNull(appView.definitionFor(encodedOneOfCaseField.holder()));
- if (clazz == null) {
+ ProgramField oneOfCaseField =
+ oneOfCaseFieldResolutionResult
+ .asSuccessfulResolution()
+ .getResolutionPair()
+ .asProgramField();
+ if (oneOfCaseField == null) {
assert false;
return;
}
- ProgramMethod dynamicMethod = clazz.lookupProgramMethod(references.dynamicMethod);
+ ProgramMethod dynamicMethod =
+ oneOfCaseField.getHolder().lookupProgramMethod(references.dynamicMethod);
if (dynamicMethod == null) {
assert false;
return;
}
- if (!enqueuer.isFieldLive(encodedOneOfCaseField)) {
+ if (!enqueuer.isFieldLive(oneOfCaseField)) {
return;
}
@@ -541,21 +551,24 @@
return;
}
- DexField oneOfField = oneOfObject.asLiveProtoFieldObject().getField();
- DexEncodedField encodedOneOfField = appView.appInfo().resolveField(oneOfField);
- if (encodedOneOfField == null) {
+ DexField oneOfFieldReference = oneOfObject.asLiveProtoFieldObject().getField();
+ FieldResolutionResult oneOfFieldResolutionResult =
+ appView.appInfo().resolveField(oneOfFieldReference);
+ if (oneOfFieldResolutionResult.isFailedOrUnknownResolution()) {
assert false;
return;
}
- if (encodedOneOfField.holder() != encodedOneOfCaseField.holder()) {
+ ProgramField oneOfField =
+ oneOfFieldResolutionResult.asSuccessfulResolution().getResolutionPair().asProgramField();
+ if (oneOfField == null || oneOfField.getHolder() != oneOfCaseField.getHolder()) {
assert false;
return;
}
- if (enqueuer.registerReflectiveFieldWrite(encodedOneOfField.field, dynamicMethod)) {
+ if (enqueuer.registerReflectiveFieldWrite(oneOfField.getReference(), dynamicMethod)) {
worklist.enqueueMarkReachableFieldAction(
- clazz.asProgramClass(), encodedOneOfField, KeepReason.reflectiveUseIn(dynamicMethod));
+ oneOfField, KeepReason.reflectiveUseIn(dynamicMethod));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoFieldInfo.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoFieldInfo.java
index 944d069..6704f91 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoFieldInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoFieldInfo.java
@@ -6,9 +6,11 @@
import static com.android.tools.r8.ir.analysis.proto.schema.ProtoMessageInfo.BITS_PER_HAS_BITS_WORD;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.FieldResolutionResult;
+import com.android.tools.r8.graph.ProgramField;
import java.util.List;
import java.util.OptionalInt;
@@ -120,7 +122,8 @@
return protoMessageInfo.isProto2() && type.isSingular();
}
- public DexEncodedField getHazzerBitField(AppView<?> appView, ProtoMessageInfo protoMessageInfo) {
+ public ProgramField getHazzerBitField(
+ AppView<? extends AppInfoWithClassHierarchy> appView, ProtoMessageInfo protoMessageInfo) {
assert hasHazzerBitField(protoMessageInfo);
int hasBitsIndex = getAuxData() / BITS_PER_HAS_BITS_WORD;
@@ -128,7 +131,12 @@
ProtoObject object = protoMessageInfo.getHasBitsObjects().get(hasBitsIndex);
assert object.isLiveProtoFieldObject();
- return appView.appInfo().resolveField(object.asLiveProtoFieldObject().getField());
+ FieldResolutionResult resolutionResult =
+ appView.appInfo().resolveField(object.asLiveProtoFieldObject().getField());
+ if (resolutionResult.isSuccessfulResolution()) {
+ return resolutionResult.asSuccessfulResolution().getResolutionPair().asProgramField();
+ }
+ return null;
}
public int getHazzerBitFieldIndex(ProtoMessageInfo protoMessageInfo) {
@@ -162,12 +170,17 @@
* }
* </pre>
*/
- public DexEncodedField getOneOfCaseField(AppView<?> appView, ProtoMessageInfo protoMessageInfo) {
+ public ProgramField getOneOfCaseField(
+ AppView<? extends AppInfoWithClassHierarchy> appView, ProtoMessageInfo protoMessageInfo) {
assert type.isOneOf();
-
ProtoObject object = protoMessageInfo.getOneOfObjects().get(getAuxData()).getOneOfCaseObject();
assert object.isLiveProtoFieldObject();
- return appView.appInfo().resolveField(object.asLiveProtoFieldObject().getField());
+ FieldResolutionResult resolutionResult =
+ appView.appInfo().resolveField(object.asLiveProtoFieldObject().getField());
+ if (resolutionResult.isSuccessfulResolution()) {
+ return resolutionResult.asSuccessfulResolution().getResolutionPair().asProgramField();
+ }
+ return null;
}
/**
@@ -176,13 +189,19 @@
* <p>Java field into which the value is stored; constituents of a oneof all share the same
* storage.
*/
- public DexEncodedField getValueStorage(AppView<?> appView, ProtoMessageInfo protoMessageInfo) {
+ public ProgramField getValueStorage(
+ AppView<? extends AppInfoWithClassHierarchy> appView, ProtoMessageInfo protoMessageInfo) {
ProtoObject object =
type.isOneOf()
? protoMessageInfo.getOneOfObjects().get(getAuxData()).getOneOfObject()
: objects.get(0);
assert object.isLiveProtoFieldObject();
- return appView.appInfo().resolveField(object.asLiveProtoFieldObject().getField());
+ FieldResolutionResult resolutionResult =
+ appView.appInfo().resolveField(object.asLiveProtoFieldObject().getField());
+ if (resolutionResult.isSuccessfulResolution()) {
+ return resolutionResult.asSuccessfulResolution().getResolutionPair().asProgramField();
+ }
+ return null;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/sideeffect/ClassInitializerSideEffectAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/sideeffect/ClassInitializerSideEffectAnalysis.java
index b3aaf9c..f92edd0 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/sideeffect/ClassInitializerSideEffectAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/sideeffect/ClassInitializerSideEffectAnalysis.java
@@ -6,7 +6,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedField;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ValueMayDependOnEnvironmentAnalysis;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.IRCode;
@@ -15,6 +15,7 @@
import com.android.tools.r8.ir.code.NewArrayFilledData;
import com.android.tools.r8.ir.code.StaticPut;
import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.OptionalBool;
public class ClassInitializerSideEffectAnalysis {
@@ -38,8 +39,8 @@
* non-static-put instructions may have side effects.
*/
public static ClassInitializerSideEffect classInitializerCanBePostponed(
- AppView<?> appView, IRCode code) {
- DexType context = code.method().holder();
+ AppView<AppInfoWithLiveness> appView, IRCode code) {
+ ProgramMethod context = code.context();
OptionalBool controlFlowMayDependOnEnvironment = OptionalBool.unknown();
boolean mayHaveSideEffects = false;
@@ -111,9 +112,10 @@
if (instruction.isStaticPut()) {
StaticPut staticPut = instruction.asStaticPut();
- DexEncodedField field = appView.appInfo().resolveField(staticPut.getField());
+ DexEncodedField field =
+ appView.appInfo().resolveField(staticPut.getField()).getResolvedField();
if (field == null
- || field.holder() != context
+ || field.holder() != context.getHolderType()
|| environmentAnalysis.valueMayDependOnEnvironment(staticPut.value())
|| instruction.instructionInstanceCanThrow(appView, context).isThrowing()) {
return ClassInitializerSideEffect.SIDE_EFFECTS_THAT_CANNOT_BE_POSTPONED;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
index 76213c6..bcb5c0b 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
@@ -75,7 +75,7 @@
Value returnedValue =
code.createValue(classClassType(appView, definitelyNotNull()), debugLocalInfo);
ConstClass instruction = new ConstClass(returnedValue, type);
- assert !instruction.instructionMayHaveSideEffects(appView, code.method().holder());
+ assert !instruction.instructionMayHaveSideEffects(appView, code.context());
return instruction;
}
@@ -96,7 +96,7 @@
}
@Override
- public boolean isMaterializableInAllContexts(AppView<?> appView) {
+ public boolean isMaterializableInAllContexts(AppView<AppInfoWithLiveness> appView) {
DexType baseType = type.toBaseType(appView.dexItemFactory());
if (baseType.isClassType()) {
DexClass clazz = appView.definitionFor(type);
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
index 7bccd30..14dee6f 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
@@ -81,7 +81,7 @@
public boolean isMaterializableInContext(
AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
return AccessControl.isFieldAccessible(
- appView.appInfo().resolveField(field),
+ appView.appInfo().resolveField(field).getResolvedField(),
appView.definitionForHolder(field),
context.getHolder(),
appView.appInfo())
@@ -89,8 +89,8 @@
}
@Override
- public boolean isMaterializableInAllContexts(AppView<?> appView) {
- DexEncodedField encodedField = appView.appInfo().resolveField(field);
+ public boolean isMaterializableInAllContexts(AppView<AppInfoWithLiveness> appView) {
+ DexEncodedField encodedField = appView.appInfo().resolveField(field).getResolvedField();
if (encodedField == null) {
assert false;
return false;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
index 67a0858..e6b1ee6 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
@@ -86,7 +86,7 @@
}
@Override
- public boolean isMaterializableInAllContexts(AppView<?> appView) {
+ public boolean isMaterializableInAllContexts(AppView<AppInfoWithLiveness> appView) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
index 457d49b..ab7c218 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
@@ -87,7 +87,7 @@
}
@Override
- public boolean isMaterializableInAllContexts(AppView<?> appView) {
+ public boolean isMaterializableInAllContexts(AppView<AppInfoWithLiveness> appView) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java
index f0425b0..3ce27a0 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java
@@ -43,7 +43,7 @@
public abstract boolean isMaterializableInContext(
AppView<AppInfoWithLiveness> appView, ProgramMethod context);
- public abstract boolean isMaterializableInAllContexts(AppView<?> appView);
+ public abstract boolean isMaterializableInAllContexts(AppView<AppInfoWithLiveness> appView);
@Override
public abstract SingleValue rewrittenWithLens(
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
index 8cd1503..3cd25ea 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
@@ -7,7 +7,7 @@
import com.android.tools.r8.cf.code.CfNop;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -61,7 +61,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return ConstraintWithTarget.ALWAYS;
}
@@ -76,7 +76,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 2a32bb6..4b99975 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
@@ -6,7 +6,7 @@
import com.android.tools.r8.cf.LoadStoreHelper;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -62,7 +62,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forAlwaysMaterializingUser();
}
@@ -77,7 +77,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 2ace686..5b68bf5 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
@@ -9,6 +9,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -101,7 +102,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forArgument();
}
@@ -136,7 +137,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 432cf11..845cb26 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
@@ -19,6 +19,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -151,7 +152,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forArrayGet();
}
@@ -237,7 +238,7 @@
}
@Override
- public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, DexType context) {
+ public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, ProgramMethod context) {
return array() == value;
}
@@ -263,7 +264,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
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 a1ed1d7..fcea78c 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
@@ -8,7 +8,7 @@
import com.android.tools.r8.cf.code.CfArrayLength;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -74,7 +74,7 @@
}
@Override
- public AbstractError instructionInstanceCanThrow(AppView<?> appView, DexType context) {
+ public AbstractError instructionInstanceCanThrow(AppView<?> appView, ProgramMethod context) {
if (array().type.isNullable()) {
return AbstractError.specific(appView.dexItemFactory().npeType);
}
@@ -84,13 +84,13 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
return instructionInstanceCanThrow(appView, context).isThrowing();
}
@Override
public boolean canBeDeadCode(AppView<?> appView, IRCode code) {
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
@Override
@@ -114,7 +114,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forArrayLength();
}
@@ -140,7 +140,7 @@
}
@Override
- public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, DexType context) {
+ public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, ProgramMethod context) {
return array() == value;
}
@@ -155,7 +155,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 37daada..860473c 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
@@ -15,7 +15,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -134,7 +134,7 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
// In debug mode, ArrayPut has a side-effect on the locals.
if (appView.options().debug) {
return true;
@@ -192,7 +192,7 @@
@Override
public boolean canBeDeadCode(AppView<?> appView, IRCode code) {
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
@Override
@@ -220,7 +220,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forArrayPut();
}
@@ -240,7 +240,7 @@
}
@Override
- public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, DexType context) {
+ public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, ProgramMethod context) {
return array() == value;
}
@@ -260,7 +260,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Assume.java b/src/main/java/com/android/tools/r8/ir/code/Assume.java
index e5316e4..c6012bd 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Assume.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Assume.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Assume.Assumption;
@@ -238,7 +239,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forAssume();
}
@@ -270,7 +271,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
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 f0d4eff..613ff5b 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
@@ -9,7 +9,7 @@
import com.android.tools.r8.cf.LoadStoreHelper;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -123,7 +123,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forBinop();
}
@@ -144,7 +144,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 da952bd..cdbf6f0 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,6 +16,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -96,12 +97,12 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
return instructionInstanceCanThrow(appView, context).isThrowing();
}
@Override
- public AbstractError instructionInstanceCanThrow(AppView<?> appView, DexType context) {
+ public AbstractError instructionInstanceCanThrow(AppView<?> appView, ProgramMethod context) {
if (appView.options().debug || !appView.appInfo().hasLiveness()) {
return AbstractError.top();
}
@@ -154,8 +155,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forCheckCast(type, invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forCheckCast(type, context.getHolder());
}
@Override
@@ -225,7 +226,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 c2d5232..759e764 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
@@ -13,6 +13,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -22,6 +23,7 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
public class ConstClass extends ConstInstruction {
@@ -99,7 +101,7 @@
}
@Override
- public AbstractError instructionInstanceCanThrow(AppView<?> appView, DexType context) {
+ public AbstractError instructionInstanceCanThrow(AppView<?> appView, ProgramMethod context) {
DexType baseType = getValue().toBaseType(appView.dexItemFactory());
if (baseType.isPrimitiveType()) {
return AbstractError.bottom();
@@ -108,7 +110,7 @@
// Not applicable for D8.
if (!appView.enableWholeProgramOptimizations()) {
// Unless the type of interest is same as the context.
- if (baseType == context) {
+ if (baseType == context.getHolderType()) {
return AbstractError.bottom();
}
return AbstractError.top();
@@ -133,13 +135,13 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
return instructionInstanceCanThrow(appView, context).isThrowing();
}
@Override
public boolean canBeDeadCode(AppView<?> appView, IRCode code) {
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
@Override
@@ -164,8 +166,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forConstClass(clazz, invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forConstClass(clazz, context.getHolder());
}
@Override
@@ -189,7 +191,8 @@
}
@Override
- public AbstractValue getAbstractValue(AppView<?> appView, DexType context) {
+ public AbstractValue getAbstractValue(
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
if (!instructionMayHaveSideEffects(appView, context)) {
return appView.abstractValueFactory().createSingleConstClassValue(clazz);
}
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 8db125c..0e8ce5d 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.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
@@ -50,7 +50,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forConstInstruction();
}
@@ -60,7 +60,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java b/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
index a390b3f..3973d6e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -78,7 +79,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forConstMethodHandle();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java b/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
index 774475d..6f153a6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -124,7 +125,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forConstMethodType();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
index fcb0c1b..dc66e3c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.constant.Bottom;
import com.android.tools.r8.ir.analysis.constant.ConstLatticeElement;
import com.android.tools.r8.ir.analysis.constant.LatticeElement;
@@ -25,6 +26,7 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOutputMode;
import com.android.tools.r8.utils.NumberUtils;
import java.util.Set;
@@ -333,7 +335,8 @@
}
@Override
- public AbstractValue getAbstractValue(AppView<?> appView, DexType context) {
+ public AbstractValue getAbstractValue(
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
return appView.abstractValueFactory().createSingleNumberValue(value);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstString.java b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
index a90a67e..3bd1d56 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
@@ -17,6 +18,7 @@
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.io.UTFDataFormatException;
public class ConstString extends ConstInstruction {
@@ -156,12 +158,13 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
@Override
- public AbstractValue getAbstractValue(AppView<?> appView, DexType context) {
+ public AbstractValue getAbstractValue(
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
if (!instructionInstanceCanThrow()) {
return appView.abstractValueFactory().createSingleStringValue(value);
}
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 64e2c14..292d6b7 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
@@ -6,7 +6,7 @@
import com.android.tools.r8.cf.LoadStoreHelper;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -66,7 +66,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forDebugLocalRead();
}
@@ -88,7 +88,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
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 5b4c66b..842eaa4 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
@@ -7,7 +7,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DebugLocalInfo;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -99,7 +99,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forDebugLocalsChange();
}
@@ -135,7 +135,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
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 b9ab9cd..fd6f9a9 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
@@ -7,7 +7,7 @@
import com.android.tools.r8.cf.code.CfNop;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -62,7 +62,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forDebugPosition();
}
@@ -89,7 +89,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
index bc29749..959dbfc 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
@@ -157,12 +158,12 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forDexItemBasedConstString(item, invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forDexItemBasedConstString(item, context.getHolder());
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Dup.java b/src/main/java/com/android/tools/r8/ir/code/Dup.java
index cddc41e..070b8e9 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Dup.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Dup.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -94,7 +94,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forDup();
}
@@ -119,7 +119,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Dup2.java b/src/main/java/com/android/tools/r8/ir/code/Dup2.java
index 465c408..7053383 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Dup2.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Dup2.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -108,7 +108,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forDup2();
}
@@ -133,7 +133,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 888536f..436de09 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,15 +3,14 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.code;
-import static com.android.tools.r8.optimize.MemberRebindingAnalysis.isMemberVisibleFromOriginalContext;
-
import com.android.tools.r8.graph.AppView;
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.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.FieldResolutionResult.SuccessfulFieldResolutionResult;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.AbstractFieldSet;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.ConcreteMutableFieldSet;
@@ -61,56 +60,32 @@
}
@Override
- public AbstractError instructionInstanceCanThrow(AppView<?> appView, DexType context) {
+ public AbstractError instructionInstanceCanThrow(AppView<?> appView, ProgramMethod context) {
return instructionInstanceCanThrow(appView, context, SideEffectAssumption.NONE);
}
public AbstractError instructionInstanceCanThrow(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
- DexEncodedField resolvedField;
- if (appView.enableWholeProgramOptimizations()) {
- // TODO(b/123857022): Should be possible to use definitionFor().
- resolvedField = appView.appInfo().resolveField(field);
- } else {
- // In D8, only allow the field in the same context.
- if (field.holder != context) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
+ SuccessfulFieldResolutionResult resolutionResult =
+ appView.appInfo().resolveField(field, context).asSuccessfulResolution();
+ if (resolutionResult == null) {
+ return AbstractError.top();
+ }
+ DexEncodedField resolvedField = resolutionResult.getResolvedField();
+ // Check if the instruction may fail with an IncompatibleClassChangeError.
+ if (resolvedField.isStatic() != isStaticFieldInstruction()) {
+ return AbstractError.top();
+ }
+ // Check if the resolution target is accessible.
+ if (resolutionResult.getResolvedHolder() != context.getHolder()) {
+ if (resolutionResult
+ .isAccessibleFrom(context, appView.appInfo().withClassHierarchy())
+ .isPossiblyFalse()) {
return AbstractError.top();
}
- // Note that, in D8, we are not using AppInfo#resolveField to avoid traversing the hierarchy.
- DexClass holder = appView.definitionFor(field.holder);
- if (holder == null) {
- return AbstractError.top();
- }
- resolvedField = holder.lookupField(field);
- }
- // * NoSuchFieldError (resolution failure).
- if (resolvedField == null) {
- if (appView.enableWholeProgramOptimizations()) {
- return AbstractError.specific(appView.dexItemFactory().noSuchFieldErrorType);
- } else {
- // In D8, the field lookup can only consult the context definition. Nothing can be concluded
- // from a lookup failure. For example, it could be ICCE or IAE if the current field access
- // is referring to incompatible or invisible field in a super type, respectively.
- return AbstractError.top();
- }
- }
- // * IncompatibleClassChangeError (instance-* for static field and vice versa).
- if (resolvedField.isStaticMember()) {
- if (isInstanceGet() || isInstancePut()) {
- return AbstractError.specific(appView.dexItemFactory().icceType);
- }
- } else {
- if (isStaticGet() || isStaticPut()) {
- return AbstractError.specific(appView.dexItemFactory().icceType);
- }
- }
- // * IllegalAccessError (not visible from the access context).
- if (!isMemberVisibleFromOriginalContext(
- appView, context, field.holder, resolvedField.accessFlags)) {
- return AbstractError.specific(appView.dexItemFactory().illegalAccessErrorType);
}
// TODO(b/137168535): Without non-null tracking, only locally created receiver is allowed in D8.
- // * NullPointerException (null receiver).
+ // Check if the instruction may fail with a NullPointerException (null receiver).
if (isInstanceGet() || isInstancePut()) {
if (!assumption.canAssumeReceiverIsNotNull()) {
Value receiver = inValues.get(0);
@@ -138,7 +113,7 @@
if (field.holder.classInitializationMayHaveSideEffects(
appView,
// Types that are a super type of `context` are guaranteed to be initialized already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appView.isSubtype(context.getHolderType(), type).isTrue(),
Sets.newIdentityHashSet())) {
return AbstractError.top();
}
@@ -153,7 +128,7 @@
}
@Override
- public AbstractFieldSet readSet(AppView<?> appView, DexType context) {
+ public AbstractFieldSet readSet(AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
if (instructionMayTriggerMethodInvocation(appView, context)) {
// This may trigger class initialization, which could potentially read any field.
return UnknownFieldSet.getInstance();
@@ -163,7 +138,7 @@
DexField field = getField();
DexEncodedField encodedField = null;
if (appView.enableWholeProgramOptimizations()) {
- encodedField = appView.appInfo().resolveField(field);
+ encodedField = appView.appInfo().resolveField(field).getResolvedField();
} else {
DexClass clazz = appView.definitionFor(field.holder);
if (clazz != null) {
@@ -219,7 +194,7 @@
DexItemFactory dexItemFactory = appView.dexItemFactory();
DexEncodedMethod resolutionResult =
appInfo
- .resolveMethod(clazz.type, dexItemFactory.objectMembers.finalize)
+ .resolveMethodOnClass(dexItemFactory.objectMembers.finalize, clazz)
.getSingleTarget();
return resolutionResult != null && resolutionResult.isProgramMethod(appView);
}
@@ -228,9 +203,10 @@
}
@Override
- public AbstractValue getAbstractValue(AppView<?> appView, DexType context) {
+ public AbstractValue getAbstractValue(
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
assert isFieldGet();
- DexEncodedField field = appView.appInfo().resolveField(getField());
+ DexEncodedField field = appView.appInfo().resolveField(getField()).getResolvedField();
if (field != null) {
return field.getOptimizationInfo().getAbstractValue();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCodeUtils.java b/src/main/java/com/android/tools/r8/ir/code/IRCodeUtils.java
index 107e06e..e06cdbee 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCodeUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCodeUtils.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.code;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexItemFactory;
@@ -44,11 +45,14 @@
* does not guarantee that the assignments found dominate all the normal exits.
*/
public static Map<DexEncodedField, StaticPut> findUniqueStaticPuts(
- AppView<?> appView, IRCode code, Set<DexEncodedField> fields) {
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ IRCode code,
+ Set<DexEncodedField> fields) {
Set<DexEncodedField> writtenMoreThanOnce = Sets.newIdentityHashSet();
Map<DexEncodedField, StaticPut> uniqueStaticPuts = new IdentityHashMap<>();
for (StaticPut staticPut : code.<StaticPut>instructions(Instruction::isStaticPut)) {
- DexEncodedField field = appView.appInfo().resolveField(staticPut.getField());
+ DexEncodedField field =
+ appView.appInfo().resolveField(staticPut.getField()).getResolvedField();
if (field == null || !fields.contains(field) || writtenMoreThanOnce.contains(field)) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InitClass.java b/src/main/java/com/android/tools/r8/ir/code/InitClass.java
index 02ee0eb..3ff5c53 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InitClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InitClass.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
@@ -21,6 +22,7 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.Sets;
public class InitClass extends Instruction {
@@ -78,8 +80,8 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInitClass(
@@ -92,14 +94,14 @@
}
@Override
- public AbstractError instructionInstanceCanThrow(AppView<?> appView, DexType context) {
+ public AbstractError instructionInstanceCanThrow(AppView<?> appView, ProgramMethod context) {
if (!isTypeVisibleFromContext(appView, context, clazz)) {
return AbstractError.top();
}
if (clazz.classInitializationMayHaveSideEffects(
appView,
// Types that are a super type of `context` are guaranteed to be initialized already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appView.isSubtype(context.getHolderType(), type).isTrue(),
Sets.newIdentityHashSet())) {
return AbstractError.top();
}
@@ -108,24 +110,24 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
return instructionInstanceCanThrow(appView, context).isThrowing();
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
if (appView.enableWholeProgramOptimizations()) {
// In R8, check if the class initialization of `clazz` or any of its ancestor types may have
// side effects.
return clazz.classInitializationMayHaveSideEffects(
appView,
// Types that are a super type of `context` are guaranteed to be initialized already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appView.isSubtype(context.getHolderType(), type).isTrue(),
Sets.newIdentityHashSet());
} else {
// In D8, this instruction may trigger class initialization if `clazz` is different from the
// current context.
- return clazz != context;
+ return clazz != context.getHolderType();
}
}
@@ -146,8 +148,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInitClass(clazz, invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInitClass(clazz, context.getHolder());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceFieldInstruction.java b/src/main/java/com/android/tools/r8/ir/code/InstanceFieldInstruction.java
index e78d3a7..9077c97 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceFieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceFieldInstruction.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.ir.code;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.Instruction.SideEffectAssumption;
public interface InstanceFieldInstruction {
@@ -17,7 +17,7 @@
Value object();
boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption);
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption);
FieldInstruction asFieldInstruction();
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 3050da7..38c1813 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
@@ -19,6 +19,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
@@ -28,6 +29,7 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.Set;
public class InstanceGet extends FieldInstruction implements InstanceFieldInstruction {
@@ -116,7 +118,7 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
return instructionInstanceCanThrow(appView, context, assumption).isThrowing();
}
@@ -127,7 +129,7 @@
// * IncompatibleClassChangeError (instance-* instruction for static fields)
// * IllegalAccessError (not visible from the access context)
// * NullPointerException (null receiver)
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
@Override
@@ -151,8 +153,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInstanceGet(getField(), invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInstanceGet(getField(), context.getHolder());
}
@Override
@@ -204,7 +206,7 @@
}
@Override
- public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, DexType context) {
+ public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, ProgramMethod context) {
return object() == value;
}
@@ -221,8 +223,8 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInstanceGet(
@@ -230,7 +232,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 c18e3c5..3d7ae52 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
@@ -9,6 +9,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -86,8 +87,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInstanceOf(type, invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInstanceOf(type, context.getHolder());
}
@Override
@@ -117,7 +118,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 fd76ad3..d5aad2d 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
@@ -19,6 +19,7 @@
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.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
@@ -115,7 +116,7 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
if (appView.appInfo().hasLiveness()) {
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
AppInfoWithLiveness appInfoWithLiveness = appViewWithLiveness.appInfo();
@@ -124,7 +125,8 @@
return true;
}
- DexEncodedField encodedField = appInfoWithLiveness.resolveField(getField());
+ DexEncodedField encodedField =
+ appInfoWithLiveness.resolveField(getField()).getResolvedField();
assert encodedField != null : "NoSuchFieldError (resolution failure) should be caught.";
return appInfoWithLiveness.isFieldRead(encodedField)
|| isStoringObjectWithFinalizer(appViewWithLiveness, encodedField);
@@ -142,7 +144,7 @@
// * IllegalAccessError (not visible from the access context)
// * NullPointerException (null receiver)
// * not read at all
- boolean haveSideEffects = instructionMayHaveSideEffects(appView, code.method().holder());
+ boolean haveSideEffects = instructionMayHaveSideEffects(appView, code.context());
assert appView.enableWholeProgramOptimizations() || haveSideEffects
: "Expected instance-put instruction to have side effects in D8";
return !haveSideEffects;
@@ -190,8 +192,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInstancePut(getField(), invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInstancePut(getField(), context.getHolder());
}
@Override
@@ -232,7 +234,7 @@
}
@Override
- public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, DexType context) {
+ public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, ProgramMethod context) {
return object() == value;
}
@@ -249,8 +251,8 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInstancePut(
@@ -258,7 +260,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 b280728..5fa8d11 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
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
@@ -30,6 +31,7 @@
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
@@ -139,7 +141,8 @@
return oldOutValue;
}
- public AbstractValue getAbstractValue(AppView<?> appView, DexType context) {
+ public AbstractValue getAbstractValue(
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
assert hasOutValue();
return UnknownValue.getInstance();
}
@@ -532,7 +535,8 @@
return false;
}
- public boolean isBlockLocalInstructionWithoutSideEffects(AppView<?> appView, DexType context) {
+ public boolean isBlockLocalInstructionWithoutSideEffects(
+ AppView<?> appView, ProgramMethod context) {
return definesBlockLocalValue() && !instructionMayHaveSideEffects(appView, context);
}
@@ -570,12 +574,12 @@
return instructionTypeCanThrow();
}
- public boolean instructionMayHaveSideEffects(AppView<?> appView, DexType context) {
+ public boolean instructionMayHaveSideEffects(AppView<?> appView, ProgramMethod context) {
return instructionMayHaveSideEffects(appView, context, SideEffectAssumption.NONE);
}
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
return instructionInstanceCanThrow();
}
@@ -584,9 +588,9 @@
* indirectly (e.g., via class initialization).
*/
public abstract boolean instructionMayTriggerMethodInvocation(
- AppView<?> appView, DexType context);
+ AppView<?> appView, ProgramMethod context);
- public AbstractError instructionInstanceCanThrow(AppView<?> appView, DexType context) {
+ public AbstractError instructionInstanceCanThrow(AppView<?> appView, ProgramMethod context) {
return instructionInstanceCanThrow() ? AbstractError.top() : AbstractError.bottom();
}
@@ -601,7 +605,7 @@
* Returns an abstraction of the set of fields that may possibly be read as a result of executing
* this instruction.
*/
- public AbstractFieldSet readSet(AppView<?> appView, DexType context) {
+ public AbstractFieldSet readSet(AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
if (instructionMayTriggerMethodInvocation(appView, context)
&& instructionMayHaveSideEffects(appView, context)) {
return UnknownFieldSet.getInstance();
@@ -1378,7 +1382,7 @@
* <p>The type is used to judge visibility constraints and also for dispatch decisions.
*/
public abstract ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context);
public abstract void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper);
@@ -1432,7 +1436,7 @@
* @return true if the instruction throws NullPointerException if value is null at runtime, false
* otherwise.
*/
- public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, DexType context) {
+ public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, ProgramMethod context) {
return false;
}
@@ -1460,8 +1464,8 @@
*/
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return false;
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 c3fec64..29b8a3b 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
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -165,7 +166,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forInvokeCustom();
}
@@ -196,7 +197,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return true;
}
}
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 e492db1..095db29 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
@@ -13,6 +13,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
@@ -121,24 +122,25 @@
}
@Override
- public DexEncodedMethod lookupSingleTarget(AppView<?> appView, DexType invocationContext) {
+ public DexEncodedMethod lookupSingleTarget(
+ AppView<?> appView, ProgramMethod context, Value receiver) {
DexMethod invokedMethod = getInvokedMethod();
if (appView.appInfo().hasLiveness()) {
AppInfoWithLiveness appInfo = appView.appInfo().withLiveness();
- DexEncodedMethod result = appInfo.lookupDirectTarget(invokedMethod, invocationContext);
+ DexEncodedMethod result = appInfo.lookupDirectTarget(invokedMethod, context);
assert verifyD8LookupResult(
- result, appView.appInfo().lookupDirectTargetOnItself(invokedMethod, invocationContext));
+ result, appView.appInfo().lookupDirectTargetOnItself(invokedMethod, context));
return result;
}
// In D8, we can treat invoke-direct instructions as having a single target if the invoke is
// targeting a method in the enclosing class.
- return appView.appInfo().lookupDirectTargetOnItself(invokedMethod, invocationContext);
+ return appView.appInfo().lookupDirectTargetOnItself(invokedMethod, context);
}
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInvokeDirect(getInvokedMethod(), invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInvokeDirect(getInvokedMethod(), context.getHolder());
}
@Override
@@ -149,8 +151,8 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInvokeDirect(
@@ -159,7 +161,7 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
if (appView.options().debug) {
return true;
}
@@ -217,8 +219,8 @@
@Override
public boolean canBeDeadCode(AppView<?> appView, IRCode code) {
- DexEncodedMethod method = code.method();
- if (instructionMayHaveSideEffects(appView, method.holder())) {
+ ProgramMethod context = code.context();
+ if (instructionMayHaveSideEffects(appView, context)) {
return false;
}
@@ -236,7 +238,7 @@
if (appView.dexItemFactory().isConstructor(invoke.getInvokedMethod())
&& invoke.getReceiver() == getReceiver()) {
// If another constructor call than `this` is found, then it must not have side effects.
- if (invoke.instructionMayHaveSideEffects(appView, method.holder())) {
+ if (invoke.instructionMayHaveSideEffects(appView, context)) {
return false;
}
if (otherInitCalls == null) {
@@ -267,7 +269,7 @@
}
@Override
- public AbstractFieldSet readSet(AppView<?> appView, DexType context) {
+ public AbstractFieldSet readSet(AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
DexMethod invokedMethod = getInvokedMethod();
// Trivial instance initializers do not read any fields.
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 e9f3063..f998009 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
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
@@ -86,26 +87,28 @@
}
@Override
- public DexEncodedMethod lookupSingleTarget(AppView<?> appView, DexType invocationContext) {
+ public DexEncodedMethod lookupSingleTarget(
+ AppView<?> appView, ProgramMethod context, Value receiver) {
if (appView.appInfo().hasLiveness()) {
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
return appViewWithLiveness
.appInfo()
.lookupSingleVirtualTarget(
getInvokedMethod(),
- invocationContext,
+ context,
true,
appView,
- TypeAnalysis.getRefinedReceiverType(appViewWithLiveness, this),
- getReceiver().getDynamicLowerBoundType(appViewWithLiveness));
+ TypeAnalysis.getRefinedReceiverType(
+ appViewWithLiveness, getInvokedMethod(), receiver),
+ receiver.getDynamicLowerBoundType(appViewWithLiveness));
}
return null;
}
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInvokeInterface(getInvokedMethod(), invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInvokeInterface(getInvokedMethod(), context.getHolder());
}
@Override
@@ -116,8 +119,8 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInvokeInterface(
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 6c9fb6f..8c059d9 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
@@ -28,12 +28,9 @@
import com.android.tools.r8.ir.optimize.inliner.WhyAreYouNotInliningReporter;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.SetUtils;
-import com.google.common.collect.Sets;
+import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.BitSet;
-import java.util.Collection;
import java.util.List;
-import java.util.Set;
public abstract class InvokeMethod extends Invoke {
@@ -76,23 +73,22 @@
// In subclasses, e.g., invoke-virtual or invoke-super, use a narrower receiver type by using
// receiver type and calling context---the holder of the method where the current invocation is.
// TODO(b/140204899): Refactor lookup methods to be defined in a single place.
- public abstract DexEncodedMethod lookupSingleTarget(
- AppView<?> appView, DexType invocationContext);
+ public abstract DexEncodedMethod lookupSingleTarget(AppView<?> appView, ProgramMethod context);
public final ProgramMethod lookupSingleProgramTarget(AppView<?> appView, ProgramMethod context) {
- DexEncodedMethod singleTarget = lookupSingleTarget(appView, context.getHolderType());
+ DexEncodedMethod singleTarget = lookupSingleTarget(appView, context);
return singleTarget != null ? singleTarget.asProgramMethod(appView) : null;
}
// TODO(b/140204899): Refactor lookup methods to be defined in a single place.
- public Collection<DexEncodedMethod> lookupTargets(
- AppView<AppInfoWithLiveness> appView, DexType invocationContext) {
+ public ProgramMethodSet lookupProgramDispatchTargets(
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
if (!getInvokedMethod().holder.isClassType()) {
return null;
}
if (!isInvokeMethodWithDynamicDispatch()) {
- DexEncodedMethod singleTarget = lookupSingleTarget(appView, invocationContext);
- return singleTarget != null ? SetUtils.newIdentityHashSet(singleTarget) : null;
+ ProgramMethod singleTarget = lookupSingleProgramTarget(appView, context);
+ return singleTarget != null ? ProgramMethodSet.create(singleTarget) : null;
}
DexProgramClass refinedReceiverUpperBound =
asProgramClassOrNull(
@@ -113,27 +109,31 @@
refinedReceiverLowerBound = null;
}
}
- ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult =
+ appView.appInfo().resolveMethod(method, isInvokeInterface());
LookupResult lookupResult;
if (refinedReceiverUpperBound != null) {
lookupResult =
resolutionResult.lookupVirtualDispatchTargets(
- appView.definitionForProgramType(invocationContext),
+ context.getHolder(),
appView.withLiveness().appInfo(),
refinedReceiverUpperBound,
refinedReceiverLowerBound);
} else {
lookupResult =
resolutionResult.lookupVirtualDispatchTargets(
- appView.definitionForProgramType(invocationContext),
- appView.withLiveness().appInfo());
+ context.getHolder(), appView.withLiveness().appInfo());
}
if (lookupResult.isLookupResultFailure()) {
return null;
}
- Set<DexEncodedMethod> result = Sets.newIdentityHashSet();
+ ProgramMethodSet result = ProgramMethodSet.create();
lookupResult.forEach(
- methodTarget -> result.add(methodTarget.getDefinition()),
+ methodTarget -> {
+ if (methodTarget.isProgramMethod()) {
+ result.add(methodTarget.asProgramMethod());
+ }
+ },
lambda -> {
// TODO(b/150277553): Support lambda targets.
});
@@ -195,17 +195,18 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return true;
}
@Override
- public AbstractFieldSet readSet(AppView<?> appView, DexType context) {
+ public AbstractFieldSet readSet(AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
return LibraryMethodReadSetModeling.getModeledReadSetOrUnknown(this, appView.dexItemFactory());
}
@Override
- public AbstractValue getAbstractValue(AppView<?> appView, DexType context) {
+ public AbstractValue getAbstractValue(
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
assert hasOutValue();
DexEncodedMethod method = lookupSingleTarget(appView, context);
if (method != null) {
@@ -224,7 +225,7 @@
}
@Override
- public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, DexType context) {
+ public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, ProgramMethod context) {
DexEncodedMethod singleTarget = lookupSingleTarget(appView, context);
if (singleTarget != null) {
BitSet nonNullParamOrThrow = singleTarget.getOptimizationInfo().getNonNullParamOrThrow();
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
index 00ffbe1..dbee028 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
@@ -3,8 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.code;
+import static com.android.tools.r8.graph.DexEncodedMethod.asProgramMethodOrNull;
+
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
@@ -53,7 +56,20 @@
}
@Override
- public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, DexType context) {
+ public final DexEncodedMethod lookupSingleTarget(AppView<?> appView, ProgramMethod context) {
+ return lookupSingleTarget(appView, context, getReceiver());
+ }
+
+ public abstract DexEncodedMethod lookupSingleTarget(
+ AppView<?> appView, ProgramMethod context, Value receiver);
+
+ public final ProgramMethod lookupSingleProgramTarget(
+ AppView<?> appView, ProgramMethod context, Value receiver) {
+ return asProgramMethodOrNull(lookupSingleTarget(appView, context, receiver), appView);
+ }
+
+ @Override
+ public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, ProgramMethod context) {
return value == getReceiver() || super.throwsNpeIfValueIsNull(value, appView, context);
}
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 4006bd7..1e41503 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
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -77,8 +78,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInvokeMultiNewArray(type, invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInvokeMultiNewArray(type, context.getHolder());
}
@Override
@@ -113,7 +114,7 @@
}
@Override
- public AbstractError instructionInstanceCanThrow(AppView<?> appView, DexType context) {
+ public AbstractError instructionInstanceCanThrow(AppView<?> appView, ProgramMethod context) {
DexType baseType = type.isArrayType() ? type.toBaseType(appView.dexItemFactory()) : type;
if (baseType.isPrimitiveType()) {
// Primitives types are known to be present and accessible.
@@ -123,7 +124,7 @@
assert baseType.isReferenceType();
- if (baseType == context) {
+ if (baseType == context.getHolderType()) {
// The enclosing type is known to be present and accessible.
return instructionInstanceCanThrowNegativeArraySizeException();
}
@@ -172,7 +173,7 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
// Check if the instruction has a side effect on the locals environment.
if (hasOutValue() && outValue().hasLocalInfo()) {
assert appView.options().debug;
@@ -184,11 +185,11 @@
@Override
public boolean canBeDeadCode(AppView<?> appView, IRCode code) {
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 3f5a1ab..1d6547e 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
@@ -13,6 +13,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -106,8 +107,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInvokeNewArray(type, invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInvokeNewArray(type, context.getHolder());
}
@Override
@@ -140,7 +141,7 @@
}
@Override
- public AbstractError instructionInstanceCanThrow(AppView<?> appView, DexType context) {
+ public AbstractError instructionInstanceCanThrow(AppView<?> appView, ProgramMethod context) {
DexType baseType = type.isArrayType() ? type.toBaseType(appView.dexItemFactory()) : type;
if (baseType.isPrimitiveType()) {
// Primitives types are known to be present and accessible.
@@ -150,7 +151,7 @@
assert baseType.isReferenceType();
- if (baseType == context) {
+ if (baseType == context.getHolderType()) {
// The enclosing type is known to be present and accessible.
return AbstractError.bottom();
}
@@ -185,7 +186,7 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
// Check if the instruction has a side effect on the locals environment.
if (hasOutValue() && outValue().hasLocalInfo()) {
assert appView.options().debug;
@@ -197,11 +198,11 @@
@Override
public boolean canBeDeadCode(AppView<?> appView, IRCode code) {
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 8d46da1..6a1e8a2 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
@@ -23,7 +23,7 @@
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.optimize.inliner.WhyAreYouNotInliningReporter;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import java.util.Collection;
+import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.List;
public class InvokePolymorphic extends InvokeMethod {
@@ -120,22 +120,22 @@
}
@Override
- public DexEncodedMethod lookupSingleTarget(AppView<?> appView, DexType invocationContext) {
+ public DexEncodedMethod lookupSingleTarget(AppView<?> appView, ProgramMethod context) {
// TODO(herhut): Implement lookup target for invokePolymorphic.
return null;
}
@Override
- public Collection<DexEncodedMethod> lookupTargets(
- AppView<AppInfoWithLiveness> appView, DexType invocationContext) {
+ public ProgramMethodSet lookupProgramDispatchTargets(
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
// TODO(herhut): Implement lookup target for invokePolymorphic.
return null;
}
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInvokePolymorphic(getInvokedMethod(), invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInvokePolymorphic(getInvokedMethod(), context.getHolder());
}
@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 5ea6e46..2c5faaf 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,13 +103,13 @@
}
@Override
- public DexEncodedMethod lookupSingleTarget(AppView<?> appView, DexType invocationContext) {
+ public DexEncodedMethod lookupSingleTarget(AppView<?> appView, ProgramMethod context) {
DexMethod invokedMethod = getInvokedMethod();
if (appView.appInfo().hasLiveness()) {
AppInfoWithLiveness appInfo = appView.appInfo().withLiveness();
- DexEncodedMethod result = appInfo.lookupStaticTarget(invokedMethod, invocationContext);
+ DexEncodedMethod result = appInfo.lookupStaticTarget(invokedMethod, context);
assert verifyD8LookupResult(
- result, appView.appInfo().lookupStaticTargetOnItself(invokedMethod, invocationContext));
+ result, appView.appInfo().lookupStaticTargetOnItself(invokedMethod, context));
return result;
}
// Allow optimizing static library invokes in D8.
@@ -120,13 +120,13 @@
}
// In D8, we can treat invoke-static instructions as having a single target if the invoke is
// targeting a method in the enclosing class.
- return appView.appInfo().lookupStaticTargetOnItself(invokedMethod, invocationContext);
+ return appView.appInfo().lookupStaticTargetOnItself(invokedMethod, context);
}
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInvokeStatic(getInvokedMethod(), invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInvokeStatic(getInvokedMethod(), context.getHolder());
}
@Override
@@ -148,8 +148,8 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInvokeStatic(
@@ -158,7 +158,7 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
if (!appView.enableWholeProgramOptimizations()) {
return true;
}
@@ -207,7 +207,7 @@
appView,
// Types that are a super type of `context` are guaranteed to be initialized
// already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appView.isSubtype(context.getHolderType(), type).isTrue(),
Sets.newIdentityHashSet());
}
@@ -216,6 +216,6 @@
@Override
public boolean canBeDeadCode(AppView<?> appView, IRCode code) {
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
}
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 588a0f1..e2b2e3a 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
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
@@ -93,12 +94,13 @@
}
@Override
- public DexEncodedMethod lookupSingleTarget(AppView<?> appView, DexType invocationContext) {
- if (appView.appInfo().hasLiveness() && invocationContext != null) {
+ public DexEncodedMethod lookupSingleTarget(
+ AppView<?> appView, ProgramMethod context, Value receiver) {
+ if (appView.appInfo().hasLiveness() && context != null) {
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
AppInfoWithLiveness appInfo = appViewWithLiveness.appInfo();
- if (appInfo.isSubtype(invocationContext, getInvokedMethod().holder)) {
- return appInfo.lookupSuperTarget(getInvokedMethod(), invocationContext);
+ if (appInfo.isSubtype(context.getHolderType(), getInvokedMethod().holder)) {
+ return appInfo.lookupSuperTarget(getInvokedMethod(), context);
}
}
return null;
@@ -106,15 +108,15 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInvokeSuper(getInvokedMethod(), invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInvokeSuper(getInvokedMethod(), context.getHolder());
}
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInvokeSuper(
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 b9a0765..69111fc 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
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
@@ -90,19 +91,20 @@
}
@Override
- public DexEncodedMethod lookupSingleTarget(AppView<?> appView, DexType invocationContext) {
- return lookupSingleTarget(appView, invocationContext, getInvokedMethod(), getReceiver());
+ public DexEncodedMethod lookupSingleTarget(
+ AppView<?> appView, ProgramMethod context, Value receiver) {
+ return lookupSingleTarget(appView, context, receiver, getInvokedMethod());
}
public static DexEncodedMethod lookupSingleTarget(
- AppView<?> appView, DexType invocationContext, DexMethod method, Value receiver) {
+ AppView<?> appView, ProgramMethod context, Value receiver, DexMethod method) {
if (appView.appInfo().hasLiveness()) {
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
return appViewWithLiveness
.appInfo()
.lookupSingleVirtualTarget(
method,
- invocationContext,
+ context,
false,
appView,
TypeAnalysis.getRefinedReceiverType(appViewWithLiveness, method, receiver),
@@ -126,8 +128,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forInvokeVirtual(getInvokedMethod(), invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forInvokeVirtual(getInvokedMethod(), context.getHolder());
}
@Override
@@ -138,8 +140,8 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forInvokeVirtual(
@@ -148,7 +150,7 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
if (!appView.enableWholeProgramOptimizations()) {
return true;
}
@@ -205,6 +207,6 @@
@Override
public boolean canBeDeadCode(AppView<?> appView, IRCode code) {
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
}
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 8e1e347..9536919 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
@@ -4,7 +4,7 @@
package com.android.tools.r8.ir.code;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
import java.util.List;
@@ -48,7 +48,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forJumpInstruction();
}
@@ -58,7 +58,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 9886690..eee3bef 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
@@ -10,6 +10,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -63,7 +64,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forLoad();
}
@@ -99,7 +100,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 598bc6c..f779651 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
@@ -12,7 +12,7 @@
import com.android.tools.r8.code.MonitorExit;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -109,7 +109,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forMonitor();
}
@@ -141,7 +141,7 @@
}
@Override
- public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, DexType context) {
+ public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, ProgramMethod context) {
return object() == value;
}
@@ -156,7 +156,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 24e831c..f531071 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
@@ -8,7 +8,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -99,7 +99,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forMove();
}
@@ -119,7 +119,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
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 9f21f17..4c87b70 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
@@ -8,6 +8,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -87,7 +88,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forMoveException();
}
@@ -121,7 +122,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 bd5c34f..c730efc 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
@@ -10,6 +10,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -107,8 +108,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forNewArrayEmpty(type, invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forNewArrayEmpty(type, context.getHolder());
}
@Override
@@ -139,7 +140,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 fd6cf65..aaa27dd 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
@@ -9,7 +9,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -101,7 +101,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forNewArrayFilledData();
}
@@ -116,7 +116,7 @@
}
@Override
- public AbstractError instructionInstanceCanThrow(AppView<?> appView, DexType context) {
+ public AbstractError instructionInstanceCanThrow(AppView<?> appView, ProgramMethod context) {
if (appView.options().debug) {
return AbstractError.top();
}
@@ -130,7 +130,7 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
// Treat the instruction as possibly having side-effects if it may throw or the array is used.
if (instructionInstanceCanThrow(appView, context).isThrowing()
|| src().numberOfAllUsers() > 1) {
@@ -145,12 +145,12 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
@Override
public boolean canBeDeadCode(AppView<?> appView, IRCode code) {
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
}
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 e30cdf1..3e6c121 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
@@ -14,6 +14,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
@@ -24,6 +25,7 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.Sets;
public class NewInstance extends Instruction {
@@ -100,8 +102,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forNewInstance(clazz, invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forNewInstance(clazz, context.getHolder());
}
@Override
@@ -132,8 +134,8 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forNewInstance(
@@ -142,13 +144,16 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
DexItemFactory dexItemFactory = appView.dexItemFactory();
if (!appView.enableWholeProgramOptimizations()) {
return !(dexItemFactory.libraryTypesAssumedToBePresent.contains(clazz)
&& dexItemFactory.libraryClassesWithoutStaticInitialization.contains(clazz));
}
+ assert appView.appInfo().hasLiveness();
+ AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+
if (clazz.isPrimitiveType() || clazz.isArrayType()) {
assert false : "Unexpected new-instance instruction with primitive or array type";
return true;
@@ -165,9 +170,8 @@
}
// Verify that the instruction does not lead to an IllegalAccessError.
- if (appView.appInfo().hasLiveness()
- && !isMemberVisibleFromOriginalContext(
- appView, context, definition.type, definition.accessFlags)) {
+ if (!isMemberVisibleFromOriginalContext(
+ appView, context, definition.type, definition.accessFlags)) {
return true;
}
@@ -175,14 +179,16 @@
if (definition.classInitializationMayHaveSideEffects(
appView,
// Types that are a super type of `context` are guaranteed to be initialized already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appViewWithLiveness.appInfo().isSubtype(context.getHolderType(), type),
Sets.newIdentityHashSet())) {
return true;
}
// Verify that the object does not have a finalizer.
ResolutionResult finalizeResolutionResult =
- appView.appInfo().resolveMethod(clazz, dexItemFactory.objectMembers.finalize);
+ appViewWithLiveness
+ .appInfo()
+ .resolveMethodOnClass(dexItemFactory.objectMembers.finalize, clazz);
if (finalizeResolutionResult.isSingleResolution()) {
DexMethod finalizeMethod = finalizeResolutionResult.getSingleTarget().method;
if (finalizeMethod != dexItemFactory.enumMethods.finalize
@@ -196,7 +202,7 @@
@Override
public boolean canBeDeadCode(AppView<?> appView, IRCode code) {
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
public void markNoSpilling() {
@@ -208,19 +214,19 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
if (appView.enableWholeProgramOptimizations()) {
// In R8, check if the class initialization of the holder or any of its ancestor types may
// have side effects.
return clazz.classInitializationMayHaveSideEffects(
appView,
// Types that are a super type of `context` are guaranteed to be initialized already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appView.isSubtype(context.getHolderType(), type).isTrue(),
Sets.newIdentityHashSet());
} else {
// In D8, this instruction may trigger class initialization if the holder of the field is
// different from the current context.
- return clazz != context;
+ return clazz != context.getHolderType();
}
}
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 ab07480..0124c45 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
@@ -7,7 +7,7 @@
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -66,7 +66,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forPop();
}
@@ -97,7 +97,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 0adf292..19c9887 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
@@ -11,7 +11,7 @@
import com.android.tools.r8.code.ReturnWide;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -110,7 +110,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forReturn();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticFieldInstruction.java b/src/main/java/com/android/tools/r8/ir/code/StaticFieldInstruction.java
index 286b470..9b0e28a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticFieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticFieldInstruction.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.ir.code;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.Instruction.SideEffectAssumption;
public interface StaticFieldInstruction {
@@ -14,10 +14,10 @@
Value outValue();
- boolean instructionMayHaveSideEffects(AppView<?> appView, DexType context);
+ boolean instructionMayHaveSideEffects(AppView<?> appView, ProgramMethod context);
boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption);
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption);
FieldInstruction asFieldInstruction();
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 de66cba..e0e8b63 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
@@ -18,6 +18,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
@@ -27,6 +28,7 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.Sets;
import java.util.Set;
@@ -136,13 +138,13 @@
}
@Override
- public boolean instructionMayHaveSideEffects(AppView<?> appView, DexType context) {
+ public boolean instructionMayHaveSideEffects(AppView<?> appView, ProgramMethod context) {
return instructionMayHaveSideEffects(appView, context, SideEffectAssumption.NONE);
}
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
return instructionInstanceCanThrow(appView, context, assumption).isThrowing();
}
@@ -153,7 +155,7 @@
// * IncompatibleClassChangeError (static-* instruction for instance fields)
// * IllegalAccessError (not visible from the access context)
// * side-effects in <clinit>
- return !instructionMayHaveSideEffects(appView, code.method().holder());
+ return !instructionMayHaveSideEffects(appView, code.context());
}
@Override
@@ -177,8 +179,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forStaticGet(getField(), invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forStaticGet(getField(), context.getHolder());
}
@Override
@@ -226,8 +228,8 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forStaticGet(
@@ -240,7 +242,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
DexType holder = getField().holder;
if (appView.enableWholeProgramOptimizations()) {
// In R8, check if the class initialization of the holder or any of its ancestor types may
@@ -248,12 +250,12 @@
return holder.classInitializationMayHaveSideEffects(
appView,
// Types that are a super type of `context` are guaranteed to be initialized already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appView.isSubtype(context.getHolderType(), type).isTrue(),
Sets.newIdentityHashSet());
} else {
// In D8, this instruction may trigger class initialization if the holder of the field is
// different from the current context.
- return holder != context;
+ return holder != context.getHolderType();
}
}
}
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 78d4de9..11732a9 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
@@ -18,6 +18,7 @@
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.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
@@ -95,7 +96,7 @@
@Override
public boolean instructionMayHaveSideEffects(
- AppView<?> appView, DexType context, SideEffectAssumption assumption) {
+ AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
if (appView.appInfo().hasLiveness()) {
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
AppInfoWithLiveness appInfoWithLiveness = appViewWithLiveness.appInfo();
@@ -113,7 +114,8 @@
return true;
}
- DexEncodedField encodedField = appInfoWithLiveness.resolveField(getField());
+ DexEncodedField encodedField =
+ appInfoWithLiveness.resolveField(getField()).getResolvedField();
assert encodedField != null : "NoSuchFieldError (resolution failure) should be caught.";
boolean isDeadProtoExtensionField =
@@ -139,7 +141,7 @@
// * IllegalAccessError (not visible from the access context)
// * side-effects in <clinit>
// * not read _globally_
- boolean haveSideEffects = instructionMayHaveSideEffects(appView, code.method().holder());
+ boolean haveSideEffects = instructionMayHaveSideEffects(appView, code.context());
assert appView.enableWholeProgramOptimizations() || haveSideEffects
: "Expected static-put instruction to have side effects in D8";
return !haveSideEffects;
@@ -187,8 +189,8 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
- return inliningConstraints.forStaticPut(getField(), invocationContext);
+ InliningConstraints inliningConstraints, ProgramMethod context) {
+ return inliningConstraints.forStaticPut(getField(), context.getHolder());
}
@Override
@@ -226,8 +228,8 @@
@Override
public boolean definitelyTriggersClassInitialization(
DexType clazz,
- DexType context,
- AppView<?> appView,
+ ProgramMethod context,
+ AppView<AppInfoWithLiveness> appView,
Query mode,
AnalysisAssumption assumption) {
return ClassInitializationAnalysis.InstructionUtils.forStaticPut(
@@ -235,7 +237,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
DexType holder = getField().holder;
if (appView.enableWholeProgramOptimizations()) {
// In R8, check if the class initialization of the holder or any of its ancestor types may
@@ -243,12 +245,12 @@
return holder.classInitializationMayHaveSideEffects(
appView,
// Types that are a super type of `context` are guaranteed to be initialized already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appView.isSubtype(context.getHolderType(), type).isTrue(),
Sets.newIdentityHashSet());
} else {
// In D8, this instruction may trigger class initialization if the holder of the field is
// different from the current context.
- return holder != context;
+ return holder != context.getHolderType();
}
}
}
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 4fe63c0..ccd57ea 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
@@ -11,6 +11,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -64,7 +65,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forStore();
}
@@ -111,7 +112,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Swap.java b/src/main/java/com/android/tools/r8/ir/code/Swap.java
index 2515934..5dfa623 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Swap.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Swap.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -89,7 +89,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forSwap();
}
@@ -114,7 +114,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
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 2b6b80d..6f47788 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
@@ -7,7 +7,7 @@
import com.android.tools.r8.cf.code.CfThrow;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -72,7 +72,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forThrow();
}
@@ -87,7 +87,7 @@
}
@Override
- public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, DexType context) {
+ public boolean throwsNpeIfValueIsNull(Value value, AppView<?> appView, ProgramMethod context) {
if (exception() == value) {
return true;
}
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 1765626..9c65c4e 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
@@ -6,7 +6,7 @@
import com.android.tools.r8.cf.LoadStoreHelper;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
@@ -47,7 +47,7 @@
@Override
public ConstraintWithTarget inliningConstraint(
- InliningConstraints inliningConstraints, DexType invocationContext) {
+ InliningConstraints inliningConstraints, ProgramMethod context) {
return inliningConstraints.forUnop();
}
@@ -68,7 +68,7 @@
}
@Override
- public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
+ public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index bbe7f7f..02ab2d9 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
@@ -891,7 +892,7 @@
return definition.isOutConstant() && !hasLocalInfo();
}
- public AbstractValue getAbstractValue(AppView<?> appView, DexType context) {
+ public AbstractValue getAbstractValue(AppView<?> appView, ProgramMethod context) {
if (!appView.enableWholeProgramOptimizations()) {
return UnknownValue.getInstance();
}
@@ -901,7 +902,7 @@
return UnknownValue.getInstance();
}
- return root.definition.getAbstractValue(appView, context);
+ return root.definition.getAbstractValue(appView.withLiveness(), context);
}
public boolean isDefinedByInstructionSatisfying(Predicate<Instruction> predicate) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
index e6bd8bf..9f57ac1 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
@@ -165,25 +165,25 @@
}
private void processInvoke(Invoke.Type originalType, DexMethod originalMethod) {
- ProgramMethod source = currentMethod.getProgramMethod();
- DexMethod context = source.getReference();
+ ProgramMethod context = currentMethod.getProgramMethod();
GraphLenseLookupResult result =
- appView.graphLense().lookupMethod(originalMethod, context, originalType);
+ appView.graphLense().lookupMethod(originalMethod, context.getReference(), originalType);
DexMethod method = result.getMethod();
Invoke.Type type = result.getType();
if (type == Invoke.Type.INTERFACE || type == Invoke.Type.VIRTUAL) {
// For virtual and interface calls add all potential targets that could be called.
- ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult =
+ appView.appInfo().resolveMethod(method, type == Invoke.Type.INTERFACE);
DexEncodedMethod target = resolutionResult.getSingleTarget();
if (target != null) {
- processInvokeWithDynamicDispatch(type, target, context.holder);
+ processInvokeWithDynamicDispatch(type, target, context);
}
} else {
ProgramMethod singleTarget =
- appView.appInfo().lookupSingleProgramTarget(type, method, context.holder, appView);
+ appView.appInfo().lookupSingleProgramTarget(type, method, context, appView);
if (singleTarget != null) {
- assert !source.getDefinition().isBridge()
- || singleTarget.getDefinition() != source.getDefinition();
+ assert !context.getDefinition().isBridge()
+ || singleTarget.getDefinition() != context.getDefinition();
// For static invokes, the class could be initialized.
if (type == Invoke.Type.STATIC) {
addClassInitializerTarget(singleTarget.getHolder());
@@ -194,7 +194,7 @@
}
private void processInvokeWithDynamicDispatch(
- Invoke.Type type, DexEncodedMethod encodedTarget, DexType context) {
+ Invoke.Type type, DexEncodedMethod encodedTarget, ProgramMethod context) {
DexMethod target = encodedTarget.method;
DexClass clazz = appView.definitionFor(target.holder);
if (clazz == null) {
@@ -214,12 +214,11 @@
possibleProgramTargetsCache.computeIfAbsent(
target,
method -> {
- ResolutionResult resolution =
- appView.appInfo().resolveMethod(method.holder, method, isInterface);
+ ResolutionResult resolution = appView.appInfo().resolveMethod(method, isInterface);
if (resolution.isVirtualTarget()) {
LookupResult lookupResult =
resolution.lookupVirtualDispatchTargets(
- appView.definitionForProgramType(context), appView.appInfo());
+ context.getHolder(), appView.appInfo());
if (lookupResult.isLookupResultSuccess()) {
ProgramMethodSet targets = ProgramMethodSet.create();
lookupResult
@@ -258,7 +257,7 @@
return;
}
- DexEncodedField encodedField = appView.appInfo().resolveField(field);
+ DexEncodedField encodedField = appView.appInfo().resolveField(field).getResolvedField();
if (encodedField == null || appView.appInfo().isPinned(encodedField.field)) {
return;
}
@@ -283,7 +282,7 @@
private void processFieldWrite(DexField field) {
if (field.holder.isClassType()) {
- DexEncodedField encodedField = appView.appInfo().resolveField(field);
+ DexEncodedField encodedField = appView.appInfo().resolveField(field).getResolvedField();
if (encodedField != null && encodedField.isStatic()) {
// Each static field access implicitly triggers the class initializer.
addClassInitializerTarget(field.holder);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index 74f24c8..00eb737 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -183,7 +183,8 @@
}
public DexField resolveField(DexField field) {
- DexEncodedField resolvedField = appView.appInfo().resolveField(field);
+ DexEncodedField resolvedField =
+ appView.appInfoForDesugaring().resolveField(field).getResolvedField();
return resolvedField == null ? field : resolvedField.field;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 31fd3c0..14a936d 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -290,13 +290,13 @@
if (options.testing.forceAssumeNoneInsertion) {
assumers.add(new AliasIntroducer(appView));
}
- if (options.enableNonNullTracking) {
- assumers.add(new NonNullTracker(appView));
- }
if (appView.enableWholeProgramOptimizations()) {
assert appView.appInfo().hasLiveness();
assert appView.rootSet() != null;
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+ if (options.enableNonNullTracking) {
+ assumers.add(new NonNullTracker(appViewWithLiveness));
+ }
this.classInliner =
options.enableClassInlining && options.enableInlining ? new ClassInliner() : null;
this.classStaticizer =
@@ -1164,7 +1164,7 @@
} else {
if (lambdaRewriter != null) {
timing.begin("Desugar lambdas");
- lambdaRewriter.desugarLambdas(method, code);
+ lambdaRewriter.desugarLambdas(code);
timing.end();
assert code.isConsistentSSA();
}
@@ -1284,7 +1284,7 @@
if (devirtualizer != null) {
assert code.verifyTypes(appView);
timing.begin("Devirtualize invoke interface");
- devirtualizer.devirtualizeInvokeInterface(code, holder);
+ devirtualizer.devirtualizeInvokeInterface(code);
timing.end();
}
@@ -1372,7 +1372,7 @@
timing.begin("Optimize class initializers");
ClassInitializerDefaultsResult classInitializerDefaultsResult =
- classInitializerDefaultsOptimization.optimize(method, code, feedback);
+ classInitializerDefaultsOptimization.optimize(code, feedback);
timing.end();
if (Log.ENABLED) {
@@ -1585,6 +1585,11 @@
timing.end();
}
+ if (appView.isCfByteCodePassThrough(method)) {
+ // If the code is pass trough, do not finalize by overwriting the existing code.
+ return timing;
+ }
+
printMethod(code, "Optimized IR (SSA)", previous);
timing.begin("Finalize IR");
finalizeIR(code, feedback, timing);
@@ -1632,11 +1637,11 @@
if (method.isInitializer()) {
if (method.isClassInitializer()) {
StaticFieldValueAnalysis.run(
- appView, code, classInitializerDefaultsResult, feedback, code.method(), timing);
+ appView, code, classInitializerDefaultsResult, feedback, timing);
} else {
instanceFieldInitializationInfos =
InstanceFieldValueAnalysis.run(
- appView, code, classInitializerDefaultsResult, feedback, code.method(), timing);
+ appView, code, classInitializerDefaultsResult, feedback, timing);
}
}
methodOptimizationInfoCollector.collectMethodOptimizationInfo(
@@ -1711,7 +1716,7 @@
ProgramMethod method = code.context();
ConstraintWithTarget state =
shouldComputeInliningConstraint(method)
- ? inliner.computeInliningConstraint(code, method)
+ ? inliner.computeInliningConstraint(code)
: ConstraintWithTarget.NEVER;
feedback.markProcessed(method.getDefinition(), state);
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index e9aed7f..e059db8 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -10,7 +10,6 @@
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.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.Code;
@@ -108,7 +107,7 @@
if (androidApp != null) {
DexApplication app =
new ApplicationReader(androidApp, options, Timing.empty()).read(executor);
- appInfo = new AppInfoWithClassHierarchy(app);
+ appInfo = new AppInfo(app);
}
AppView<?> appView = AppView.createForD8(appInfo, options, rewritePrefix);
BackportedMethodRewriter.RewritableMethods rewritableMethods =
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index 47ee95f..72f630b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -171,7 +171,7 @@
}
}
- private final AppView<? extends AppInfoWithClassHierarchy> appView;
+ private final AppView<?> appView;
private final DexItemFactory dexItemFactory;
private final InterfaceMethodRewriter rewriter;
private final Consumer<ProgramMethod> newSynthesizedMethodConsumer;
@@ -192,7 +192,7 @@
new IdentityHashMap<>();
ClassProcessor(
- AppView<? extends AppInfoWithClassHierarchy> appView,
+ AppView<?> appView,
InterfaceMethodRewriter rewriter,
Consumer<ProgramMethod> newSynthesizedMethodConsumer) {
this.appView = appView;
@@ -283,14 +283,14 @@
// Doing so can cause an invalid invoke to become valid (at runtime resolution at a subtype
// might have failed which is hidden by the insertion of the forward method). However, not doing
// so could cause valid dispatches to become invalid by resolving to private overrides.
+ AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
DexClassAndMethod virtualDispatchTarget =
- appView
- .appInfo()
+ appInfo
.resolveMethodOnInterface(method.holder, method)
- .lookupVirtualDispatchTarget(clazz, appView.appInfo());
+ .lookupVirtualDispatchTarget(clazz, appInfo);
if (virtualDispatchTarget == null) {
// If no target is found due to multiple default method targets, preserve ICCE behavior.
- ResolutionResult resolutionFromSubclass = appView.appInfo().resolveMethod(clazz, method);
+ ResolutionResult resolutionFromSubclass = appInfo.resolveMethodOn(clazz, method);
if (resolutionFromSubclass.isIncompatibleClassChangeErrorResult()) {
addICCEThrowingMethod(method, clazz);
return;
@@ -327,8 +327,7 @@
// If target is a non-interface library class it may be an emulated interface.
if (!libraryHolder.isInterface()) {
// Here we use step-3 of resolution to find a maximally specific default interface method.
- DexClassAndMethod result =
- appView.appInfo().lookupMaximallySpecificMethod(libraryHolder, method);
+ DexClassAndMethod result = appInfo.lookupMaximallySpecificMethod(libraryHolder, method);
if (result != null && rewriter.isEmulatedInterface(result.getHolder().type)) {
addForward.accept(result.getHolder(), result.getDefinition());
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
index a640fb6..408b152 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.ir.desugar;
import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
@@ -49,7 +48,7 @@
public static final String DESUGAR_LIB_RETARGET_CLASS_NAME_PREFIX =
"$r8$retargetLibraryMember$virtualDispatch";
- private final AppView<AppInfoWithClassHierarchy> appView;
+ private final AppView<?> appView;
private final Map<DexMethod, DexMethod> retargetLibraryMember = new IdentityHashMap<>();
// Map virtualRewrites hold a methodName->method mapping for virtual methods which are
// rewritten while the holder is non final but no superclass implement the method. In this case
@@ -59,9 +58,7 @@
private final Set<DexMethod> emulatedDispatchMethods = Sets.newHashSet();
public DesugaredLibraryRetargeter(AppView<?> appView) {
- assert appView.appInfo().hasClassHierarchy()
- : "Class hierarchy required for desugared library.";
- this.appView = appView.withClassHierarchy();
+ this.appView = appView;
if (appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()) {
return;
}
@@ -116,8 +113,8 @@
// We need to force resolution, even on d8, to know if the invoke has to be rewritten.
ResolutionResult resolutionResult =
appView
- .appInfo()
- .resolveMethod(invoke.getInvokedMethod().holder, invoke.getInvokedMethod());
+ .appInfoForDesugaring()
+ .resolveMethod(invoke.getInvokedMethod(), invoke.isInvokeInterface());
if (resolutionResult.isFailedResolution()) {
continue;
}
@@ -134,9 +131,8 @@
if (invoke.isInvokeSuper() && matchesVirtualRewrite(invoke.getInvokedMethod())) {
DexEncodedMethod dexEncodedMethod =
appView
- .appInfo()
- .withClassHierarchy()
- .lookupSuperTarget(invoke.getInvokedMethod(), code.method().holder());
+ .appInfoForDesugaring()
+ .lookupSuperTarget(invoke.getInvokedMethod(), code.context());
// Final methods can be rewritten as a normal invoke.
if (dexEncodedMethod != null && !dexEncodedMethod.isFinal()) {
DexMethod retargetMethod =
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
index e3c15ae..5fbf3df 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
@@ -99,7 +99,8 @@
public static final String VIVIFIED_TYPE_WRAPPER_SUFFIX = "$-V-WRP";
private final AppView<?> appView;
- private final DexString dexWrapperPrefix;
+ private final String dexWrapperPrefixString;
+ private final DexString dexWrapperPrefixDexString;
private final Map<DexType, DexType> typeWrappers = new ConcurrentHashMap<>();
private final Map<DexType, DexType> vivifiedTypeWrappers = new ConcurrentHashMap<>();
// The invalidWrappers are wrappers with incorrect behavior because of final methods that could
@@ -114,13 +115,14 @@
DesugaredLibraryWrapperSynthesizer(AppView<?> appView, DesugaredLibraryAPIConverter converter) {
this.appView = appView;
this.factory = appView.dexItemFactory();
- this.dexWrapperPrefix = factory.createString("L" + WRAPPER_PREFIX);
+ dexWrapperPrefixString = "L" + appView.options().synthesizedClassPrefix + WRAPPER_PREFIX;
+ dexWrapperPrefixDexString = factory.createString(dexWrapperPrefixString);
this.converter = converter;
this.vivifiedSourceFile = appView.dexItemFactory().createString("vivified");
}
boolean hasSynthesized(DexType type) {
- return type.descriptor.startsWith(dexWrapperPrefix);
+ return type.descriptor.startsWith(dexWrapperPrefixDexString);
}
boolean canGenerateWrapper(DexType type) {
@@ -145,12 +147,7 @@
private DexType createWrapperType(DexType type, String suffix) {
return factory.createType(
- "L"
- + appView.options().synthesizedClassPrefix
- + WRAPPER_PREFIX
- + type.toString().replace('.', '$')
- + suffix
- + ";");
+ dexWrapperPrefixString + type.toString().replace('.', '$') + suffix + ";");
}
private DexType getWrapper(DexType type, String suffix, Map<DexType, DexType> wrappers) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 5d494bb..1f6af29 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
@@ -102,7 +101,7 @@
public static final String DEFAULT_METHOD_PREFIX = "$default$";
public static final String PRIVATE_METHOD_PREFIX = "$private$";
- private final AppView<? extends AppInfoWithClassHierarchy> appView;
+ private final AppView<?> appView;
private final IRConverter converter;
private final InternalOptions options;
final DexItemFactory factory;
@@ -137,9 +136,7 @@
public InterfaceMethodRewriter(AppView<?> appView, IRConverter converter) {
assert converter != null;
- assert appView.appInfo().hasClassHierarchy()
- : "Cannot desugar interfaces without class hierarchy";
- this.appView = appView.withClassHierarchy();
+ this.appView = appView;
this.converter = converter;
this.options = appView.options();
this.factory = appView.dexItemFactory();
@@ -316,8 +313,8 @@
// If it resolves to a program overrides, the invoke-super can remain.
DexEncodedMethod dexEncodedMethod =
appView
- .appInfo()
- .lookupSuperTarget(invokeSuper.getInvokedMethod(), code.method().holder());
+ .appInfoForDesugaring()
+ .lookupSuperTarget(invokeSuper.getInvokedMethod(), code.context());
if (dexEncodedMethod != null) {
DexClass dexClass = appView.definitionFor(dexEncodedMethod.holder());
if (dexClass != null && dexClass.isLibraryClass()) {
@@ -390,7 +387,7 @@
} else {
// The method can be a default method in the interface hierarchy.
DexClassAndMethod virtualTarget =
- appView.appInfo().lookupMaximallySpecificMethod(clazz, method);
+ appView.appInfoForDesugaring().lookupMaximallySpecificMethod(clazz, method);
if (virtualTarget != null) {
// This is a invoke-direct call to a virtual method.
instructions.replaceCurrentInstruction(
@@ -448,7 +445,7 @@
}
if (singleTarget == null) {
DexClassAndMethod result =
- appView.appInfo().lookupMaximallySpecificMethod(dexClass, invokedMethod);
+ appView.appInfoForDesugaring().lookupMaximallySpecificMethod(dexClass, invokedMethod);
if (result != null) {
singleTarget = result.getDefinition();
}
@@ -1123,7 +1120,7 @@
DexMethod method = appView.graphLense().getOriginalMethodSignature(referencedFrom);
Origin origin = getMethodOrigin(method);
MethodPosition position = new MethodPosition(method);
- options.warningMissingTypeForDesugar(origin, position, missing, method.holder);
+ options.warningMissingTypeForDesugar(origin, position, missing, method);
}
private Origin getMethodOrigin(DexMethod method) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 05c9c66..7ed2773 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
@@ -61,6 +62,7 @@
*/
public final class LambdaClass {
+ final AppView<?> appView;
final LambdaRewriter rewriter;
public final DexType type;
public LambdaDescriptor descriptor;
@@ -74,19 +76,21 @@
Suppliers.memoize(this::synthesizeLambdaClass); // NOTE: thread-safe.
LambdaClass(
+ AppView<?> appView,
LambdaRewriter rewriter,
- DexType accessedFrom,
+ ProgramMethod accessedFrom,
DexType lambdaClassType,
LambdaDescriptor descriptor) {
assert rewriter != null;
assert lambdaClassType != null;
assert descriptor != null;
+ this.appView = appView;
this.rewriter = rewriter;
this.type = lambdaClassType;
this.descriptor = descriptor;
- DexItemFactory factory = rewriter.getFactory();
+ DexItemFactory factory = appView.dexItemFactory();
DexProto constructorProto = factory.createProto(
factory.voidType, descriptor.captures.values);
this.constructor =
@@ -107,17 +111,12 @@
}
// Generate unique lambda class type for lambda descriptor and instantiation point context.
- static DexType createLambdaClassType(
- LambdaRewriter rewriter, DexType accessedFrom, LambdaDescriptor match) {
- return createLambdaClassType(rewriter.getFactory(), accessedFrom, match);
- }
-
public static DexType createLambdaClassType(
- DexItemFactory factory, DexType accessedFrom, LambdaDescriptor match) {
+ AppView<?> appView, ProgramMethod accessedFrom, LambdaDescriptor match) {
StringBuilder lambdaClassDescriptor = new StringBuilder("L");
// We always create lambda class in the same package where it is referenced.
- String packageDescriptor = accessedFrom.getPackageDescriptor();
+ String packageDescriptor = accessedFrom.getHolderType().getPackageDescriptor();
if (!packageDescriptor.isEmpty()) {
lambdaClassDescriptor.append(packageDescriptor).append('/');
}
@@ -129,12 +128,12 @@
// just add the name of this type to make lambda class name unique.
// It also helps link the class lambda originated from in some cases.
if (match.delegatesToLambdaImplMethod() || match.needsAccessor(accessedFrom)) {
- lambdaClassDescriptor.append(accessedFrom.getName()).append('$');
+ lambdaClassDescriptor.append(accessedFrom.getHolderType().getName()).append('$');
}
// Add unique lambda descriptor id
lambdaClassDescriptor.append(match.uniqueId).append(';');
- return factory.createType(lambdaClassDescriptor.toString());
+ return appView.dexItemFactory().createType(lambdaClassDescriptor.toString());
}
public final DexProgramClass getOrCreateLambdaClass() {
@@ -143,7 +142,7 @@
private DexProgramClass synthesizeLambdaClass() {
DexMethod mainMethod =
- rewriter.getFactory().createMethod(type, descriptor.erasedProto, descriptor.name);
+ appView.dexItemFactory().createMethod(type, descriptor.erasedProto, descriptor.name);
DexProgramClass clazz =
new DexProgramClass(
@@ -154,9 +153,9 @@
// classloader (package private access is not allowed across classloaders, b/72538146).
ClassAccessFlags.fromDexAccessFlags(
Constants.ACC_FINAL | Constants.ACC_SYNTHETIC | Constants.ACC_PUBLIC),
- rewriter.getFactory().objectType,
+ appView.dexItemFactory().objectType,
buildInterfaces(),
- rewriter.getFactory().createString("lambda"),
+ appView.dexItemFactory().createString("lambda"),
null,
Collections.emptyList(),
null,
@@ -166,9 +165,9 @@
synthesizeInstanceFields(),
synthesizeDirectMethods(),
synthesizeVirtualMethods(mainMethod),
- rewriter.getFactory().getSkipNameValidationForTesting(),
+ appView.dexItemFactory().getSkipNameValidationForTesting(),
LambdaClass::computeChecksumForSynthesizedClass);
- rewriter.getAppInfo().addSynthesizedClass(clazz);
+ appView.appInfo().addSynthesizedClass(clazz);
// The method addSynthesizedFrom() may be called concurrently. To avoid a Concurrent-
// ModificationException we must use synchronization.
@@ -197,12 +196,12 @@
}
final DexField getCaptureField(int index) {
- return rewriter
- .getFactory()
+ return appView
+ .dexItemFactory()
.createField(
this.type,
descriptor.captures.values[index],
- rewriter.getFactory().createString("f$" + index));
+ appView.dexItemFactory().createString("f$" + index));
}
public final boolean isStateless() {
@@ -239,7 +238,7 @@
// Synthesize bridge methods.
for (DexProto bridgeProto : descriptor.bridges) {
DexMethod bridgeMethod =
- rewriter.getFactory().createMethod(type, bridgeProto, descriptor.name);
+ appView.dexItemFactory().createMethod(type, bridgeProto, descriptor.name);
methods[index++] =
new DexEncodedMethod(
bridgeMethod,
@@ -337,7 +336,7 @@
// Creates a delegation target for this particular lambda class. Note that we
// should always be able to create targets for the lambdas we support.
- private Target createTarget(DexType accessedFrom) {
+ private Target createTarget(ProgramMethod accessedFrom) {
if (descriptor.delegatesToLambdaImplMethod()) {
return createLambdaImplMethodTarget(accessedFrom);
}
@@ -360,17 +359,20 @@
}
}
- private Target createLambdaImplMethodTarget(DexType accessedFrom) {
+ private Target createLambdaImplMethodTarget(ProgramMethod accessedFrom) {
DexMethodHandle implHandle = descriptor.implHandle;
assert implHandle != null;
DexMethod implMethod = implHandle.asMethod();
// Lambda$ method. We must always find it.
- assert implMethod.holder == accessedFrom;
- assert descriptor.verifyTargetFoundInClass(accessedFrom);
+ assert implMethod.holder == accessedFrom.getHolderType();
+ assert descriptor.verifyTargetFoundInClass(accessedFrom.getHolderType());
if (implHandle.type.isInvokeStatic()) {
SingleResolutionResult resolution =
- rewriter.getAppInfo().resolveMethod(implMethod.holder, implMethod).asSingleResolution();
+ appView
+ .appInfoForDesugaring()
+ .resolveMethod(implMethod, implHandle.isInterface)
+ .asSingleResolution();
assert resolution.getResolvedMethod().isStatic();
assert resolution.getResolvedHolder().isProgramClass();
return new StaticLambdaImplTarget(
@@ -383,28 +385,28 @@
// If the lambda$ method is an instance-private method on an interface we convert it into a
// public static method as it will be placed on the companion class.
if (implHandle.type.isInvokeDirect()
- && rewriter.getAppView().definitionFor(implMethod.holder).isInterface()) {
+ && appView.definitionFor(implMethod.holder).isInterface()) {
DexProto implProto = implMethod.proto;
DexType[] implParams = implProto.parameters.values;
DexType[] newParams = new DexType[implParams.length + 1];
newParams[0] = implMethod.holder;
System.arraycopy(implParams, 0, newParams, 1, implParams.length);
- DexProto newProto = rewriter.getFactory().createProto(implProto.returnType, newParams);
+ DexProto newProto = appView.dexItemFactory().createProto(implProto.returnType, newParams);
return new InterfaceLambdaImplTarget(
- rewriter.getFactory().createMethod(implMethod.holder, newProto, implMethod.name));
+ appView.dexItemFactory().createMethod(implMethod.holder, newProto, implMethod.name));
} else {
// Otherwise we need to ensure the method can be reached publicly by virtual dispatch.
// To avoid potential conflicts on the name of the lambda method once dispatch becomes virtual
// we add the method-holder name as suffix to the lambda-method name.
return new InstanceLambdaImplTarget(
- rewriter
- .getFactory()
+ appView
+ .dexItemFactory()
.createMethod(
implMethod.holder,
implMethod.proto,
- rewriter
- .getFactory()
+ appView
+ .dexItemFactory()
.createString(
implMethod.name.toString() + "$" + implMethod.holder.getName())));
}
@@ -412,7 +414,7 @@
// Create targets for instance method referenced directly without
// lambda$ methods. It may require creation of accessors in some cases.
- private Target createInstanceMethodTarget(DexType accessedFrom) {
+ private Target createInstanceMethodTarget(ProgramMethod accessedFrom) {
assert descriptor.implHandle.type.isInvokeInstance() ||
descriptor.implHandle.type.isInvokeDirect();
@@ -433,18 +435,19 @@
accessorParams[0] = descriptor.getImplReceiverType();
System.arraycopy(implParams, 0, accessorParams, 1, implParams.length);
DexProto accessorProto =
- rewriter.getFactory().createProto(implProto.returnType, accessorParams);
+ appView.dexItemFactory().createProto(implProto.returnType, accessorParams);
DexMethod accessorMethod =
- rewriter
- .getFactory()
- .createMethod(accessedFrom, accessorProto, generateUniqueLambdaMethodName());
+ appView
+ .dexItemFactory()
+ .createMethod(
+ accessedFrom.getHolderType(), accessorProto, generateUniqueLambdaMethodName());
return new ClassMethodWithAccessorTarget(accessorMethod);
}
// Create targets for static method referenced directly without
// lambda$ methods. It may require creation of accessors in some cases.
- private Target createStaticMethodTarget(DexType accessedFrom) {
+ private Target createStaticMethodTarget(ProgramMethod accessedFrom) {
assert descriptor.implHandle.type.isInvokeStatic();
if (!descriptor.needsAccessor(accessedFrom)) {
@@ -455,10 +458,10 @@
// for accessing the original static impl-method. The accessor method will be
// static, package private with exactly same signature and the original method.
DexMethod accessorMethod =
- rewriter
- .getFactory()
+ appView
+ .dexItemFactory()
.createMethod(
- accessedFrom,
+ accessedFrom.getHolderType(),
descriptor.implHandle.asMethod().proto,
generateUniqueLambdaMethodName());
return new ClassMethodWithAccessorTarget(accessorMethod);
@@ -466,7 +469,7 @@
// Create targets for constructor referenced directly without lambda$ methods.
// It may require creation of accessors in some cases.
- private Target createConstructorTarget(DexType accessedFrom) {
+ private Target createConstructorTarget(ProgramMethod accessedFrom) {
DexMethodHandle implHandle = descriptor.implHandle;
assert implHandle != null;
assert implHandle.type.isInvokeConstructor();
@@ -482,24 +485,25 @@
DexMethod implMethod = implHandle.asMethod();
DexType returnType = implMethod.holder;
DexProto accessorProto =
- rewriter.getFactory().createProto(returnType, implMethod.proto.parameters.values);
+ appView.dexItemFactory().createProto(returnType, implMethod.proto.parameters.values);
DexMethod accessorMethod =
- rewriter
- .getFactory()
- .createMethod(accessedFrom, accessorProto, generateUniqueLambdaMethodName());
+ appView
+ .dexItemFactory()
+ .createMethod(
+ accessedFrom.getHolderType(), accessorProto, generateUniqueLambdaMethodName());
return new ClassMethodWithAccessorTarget(accessorMethod);
}
// Create targets for interface methods.
- private Target createInterfaceMethodTarget(DexType accessedFrom) {
+ private Target createInterfaceMethodTarget(ProgramMethod accessedFrom) {
assert descriptor.implHandle.type.isInvokeInterface();
assert !descriptor.needsAccessor(accessedFrom);
return new NoAccessorMethodTarget(Invoke.Type.INTERFACE);
}
private DexString generateUniqueLambdaMethodName() {
- return rewriter
- .getFactory()
+ return appView
+ .dexItemFactory()
.createString(LambdaRewriter.EXPECTED_LAMBDA_METHOD_PREFIX + descriptor.uniqueId);
}
@@ -533,16 +537,8 @@
return accessibilityBridge;
}
- DexClass definitionFor(DexType type) {
- return rewriter.getAppInfo().app().definitionFor(type);
- }
-
- DexProgramClass programDefinitionFor(DexType type) {
- return rewriter.getAppInfo().app().programDefinitionFor(type);
- }
-
boolean holderIsInterface() {
- InternalOptions options = rewriter.getAppView().options();
+ InternalOptions options = appView.options();
if (!options.isGeneratingClassFiles()) {
// When generating dex the value of this flag on invokes does not matter (unused).
// We cannot know if definitionFor(implMethod.holder) is null or not in that case,
@@ -554,7 +550,7 @@
// implMethodHolder != null may fail, hence the assertion.
assert options.cfToCfDesugar;
DexMethod implMethod = descriptor.implHandle.asMethod();
- DexClass implMethodHolder = definitionFor(implMethod.holder);
+ DexClass implMethodHolder = appView.definitionFor(implMethod.holder);
if (implMethodHolder == null) {
assert options
.desugaredLibraryConfiguration
@@ -613,7 +609,7 @@
// For all instantiation points for which the compiler creates lambda$
// methods, it creates these methods in the same class/interface.
DexMethod implMethod = descriptor.implHandle.asMethod();
- DexProgramClass implMethodHolder = definitionFor(implMethod.holder).asProgramClass();
+ DexProgramClass implMethodHolder = appView.definitionFor(implMethod.holder).asProgramClass();
DexEncodedMethod replacement =
implMethodHolder
@@ -642,7 +638,7 @@
rewriter.originalMethodSignatures.put(callTarget, encodedMethod.method);
DexEncodedMethod.setDebugInfoWithFakeThisParameter(
- newMethod.getCode(), callTarget.getArity(), rewriter.getAppView());
+ newMethod.getCode(), callTarget.getArity(), appView);
return newMethod;
});
@@ -663,11 +659,11 @@
@Override
ProgramMethod ensureAccessibility(boolean allowMethodModification) {
// When compiling with whole program optimization, check that we are not inplace modifying.
- assert !(rewriter.getAppView().enableWholeProgramOptimizations() && allowMethodModification);
+ assert !(appView.enableWholeProgramOptimizations() && allowMethodModification);
// For all instantiation points for which the compiler creates lambda$
// methods, it creates these methods in the same class/interface.
DexMethod implMethod = descriptor.implHandle.asMethod();
- DexProgramClass implMethodHolder = definitionFor(implMethod.holder).asProgramClass();
+ DexProgramClass implMethodHolder = appView.definitionFor(implMethod.holder).asProgramClass();
return allowMethodModification
? modifyLambdaImplementationMethod(implMethod, implMethodHolder)
: createSyntheticAccessor(implMethod, implMethodHolder);
@@ -744,7 +740,7 @@
@Override
ProgramMethod ensureAccessibility(boolean allowMethodModification) {
// Create a static accessor with proper accessibility.
- DexProgramClass accessorClass = programDefinitionFor(callTarget.holder);
+ DexProgramClass accessorClass = appView.definitionForProgramType(callTarget.holder);
assert accessorClass != null;
// Always make the method public to provide access when r8 minification is allowed to move
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
index bfc9362..deb4579 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
@@ -11,13 +11,13 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
-import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.ProgramMethod;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.List;
@@ -67,7 +67,7 @@
private LambdaDescriptor(
AppInfoWithClassHierarchy appInfo,
- DexType invocationContext,
+ ProgramMethod context,
DexCallSite callSite,
DexString name,
DexProto erasedProto,
@@ -92,8 +92,7 @@
this.captures = captures;
this.interfaces.add(mainInterface);
- DexEncodedMethod targetMethod =
- invocationContext == null ? null : lookupTargetMethod(appInfo, invocationContext);
+ DexEncodedMethod targetMethod = context == null ? null : lookupTargetMethod(appInfo, context);
if (targetMethod != null) {
targetAccessFlags = targetMethod.accessFlags.copy();
targetHolder = targetMethod.holder();
@@ -113,17 +112,19 @@
}
private DexEncodedMethod lookupTargetMethod(
- AppInfoWithClassHierarchy appInfo, DexType invocationContext) {
- assert invocationContext != null;
+ AppInfoWithClassHierarchy appInfo, ProgramMethod context) {
+ assert context != null;
// Find the lambda's impl-method target.
DexMethod method = implHandle.asMethod();
switch (implHandle.type) {
case INVOKE_DIRECT:
case INVOKE_INSTANCE: {
DexEncodedMethod target =
- appInfo.resolveMethod(getImplReceiverType(), method).getSingleTarget();
+ appInfo
+ .resolveMethodOn(getImplReceiverType(), method, implHandle.isInterface)
+ .getSingleTarget();
if (target == null) {
- target = appInfo.lookupDirectTarget(method, invocationContext);
+ target = appInfo.lookupDirectTarget(method, context);
}
assert target == null
|| (implHandle.type.isInvokeInstance() && isInstanceMethod(target))
@@ -133,20 +134,20 @@
}
case INVOKE_STATIC: {
- DexEncodedMethod target = appInfo.lookupStaticTarget(method, invocationContext);
+ DexEncodedMethod target = appInfo.lookupStaticTarget(method, context);
assert target == null || target.accessFlags.isStatic();
return target;
}
case INVOKE_CONSTRUCTOR: {
- DexEncodedMethod target = appInfo.lookupDirectTarget(method, invocationContext);
+ DexEncodedMethod target = appInfo.lookupDirectTarget(method, context);
assert target == null || target.accessFlags.isConstructor();
return target;
}
case INVOKE_INTERFACE: {
DexEncodedMethod target =
- appInfo.resolveMethod(getImplReceiverType(), method).getSingleTarget();
+ appInfo.resolveMethodOnInterface(getImplReceiverType(), method).getSingleTarget();
assert target == null || isInstanceMethod(target);
return target;
}
@@ -187,7 +188,7 @@
}
/** Checks if call site needs a accessor when referenced from `accessedFrom`. */
- boolean needsAccessor(DexType accessedFrom) {
+ boolean needsAccessor(ProgramMethod accessedFrom) {
if (delegatesToLambdaImplMethod()) {
return false;
}
@@ -217,8 +218,10 @@
// because the method being called must be present in method holder,
// and not in one from its supertypes.
boolean accessedFromSamePackage =
- accessedFrom.getPackageDescriptor().equals(
- implHandle.asMethod().holder.getPackageDescriptor());
+ accessedFrom
+ .getHolderType()
+ .getPackageDescriptor()
+ .equals(implHandle.asMethod().holder.getPackageDescriptor());
return !accessedFromSamePackage;
}
@@ -238,7 +241,10 @@
}
boolean accessedFromSamePackage =
- accessedFrom.getPackageDescriptor().equals(targetHolder.getPackageDescriptor());
+ accessedFrom
+ .getHolderType()
+ .getPackageDescriptor()
+ .equals(targetHolder.getPackageDescriptor());
assert flags.isProtected() || accessedFromSamePackage;
return flags.isProtected() && !accessedFromSamePackage;
}
@@ -248,8 +254,8 @@
* information, or null if match failed.
*/
public static LambdaDescriptor tryInfer(
- DexCallSite callSite, AppInfoWithClassHierarchy appInfo, DexProgramClass invocationContext) {
- LambdaDescriptor descriptor = infer(callSite, appInfo, invocationContext.type);
+ DexCallSite callSite, AppInfoWithClassHierarchy appInfo, ProgramMethod context) {
+ LambdaDescriptor descriptor = infer(callSite, appInfo, context);
return descriptor == MATCH_FAILED ? null : descriptor;
}
@@ -265,7 +271,7 @@
* information, or MATCH_FAILED if match failed.
*/
static LambdaDescriptor infer(
- DexCallSite callSite, AppInfoWithClassHierarchy appInfo, DexType invocationContext) {
+ DexCallSite callSite, AppInfoWithClassHierarchy appInfo, ProgramMethod context) {
if (!isLambdaMetafactoryMethod(callSite, appInfo.dexItemFactory())) {
return LambdaDescriptor.MATCH_FAILED;
}
@@ -309,7 +315,7 @@
LambdaDescriptor match =
new LambdaDescriptor(
appInfo,
- invocationContext,
+ context,
callSite,
funcMethodName,
funcErasedSignature.value,
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index 6b41818..aa47bdc 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -4,13 +4,9 @@
package com.android.tools.r8.ir.desugar;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication.Builder;
import com.android.tools.r8.graph.DexCallSite;
-import com.android.tools.r8.graph.DexEncodedField;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
@@ -59,7 +55,7 @@
static final String EXPECTED_LAMBDA_METHOD_PREFIX = "lambda$";
private static final String LAMBDA_INSTANCE_FIELD_NAME = "INSTANCE";
- private final AppView<? extends AppInfoWithClassHierarchy> appView;
+ private final AppView<?> appView;
final DexString instanceFieldName;
@@ -76,42 +72,9 @@
// NOTE: synchronize concurrent access on `knownLambdaClasses`.
private final Map<DexType, LambdaClass> knownLambdaClasses = new IdentityHashMap<>();
- // Checks if the type starts with lambda-class prefix.
- public static boolean hasLambdaClassPrefix(DexType clazz) {
- return clazz.getName().startsWith(LAMBDA_CLASS_NAME_PREFIX);
- }
-
public LambdaRewriter(AppView<?> appView) {
- assert appView.appInfo().hasClassHierarchy()
- : "Lambda desugaring is not available without class hierarchy.";
- this.appView = appView.withClassHierarchy();
- this.instanceFieldName = getFactory().createString(LAMBDA_INSTANCE_FIELD_NAME);
- }
-
- public AppView<?> getAppView() {
- return appView;
- }
-
- public AppInfoWithClassHierarchy getAppInfo() {
- return appView.appInfo();
- }
-
- public DexItemFactory getFactory() {
- return getAppView().dexItemFactory();
- }
-
- public Map<DexEncodedField, Set<DexEncodedMethod>> getWritesWithContexts(
- DexProgramClass synthesizedLambdaClass) {
- // Record that the static fields on each lambda class are only written inside the static
- // initializer of the lambdas.
- Map<DexEncodedField, Set<DexEncodedMethod>> writesWithContexts = new IdentityHashMap<>();
- DexEncodedMethod clinit = synthesizedLambdaClass.getClassInitializer();
- if (clinit != null) {
- for (DexEncodedField field : synthesizedLambdaClass.staticFields()) {
- writesWithContexts.put(field, ImmutableSet.of(clinit));
- }
- }
- return writesWithContexts;
+ this.appView = appView;
+ this.instanceFieldName = appView.dexItemFactory().createString(LAMBDA_INSTANCE_FIELD_NAME);
}
private void synthesizeAccessibilityBridgesForLambdaClassesD8(
@@ -136,9 +99,9 @@
*
* <p>NOTE: this method can be called concurrently for several different methods.
*/
- public void desugarLambdas(DexEncodedMethod encodedMethod, IRCode code) {
+ public void desugarLambdas(IRCode code) {
Set<Value> affectedValues = Sets.newIdentityHashSet();
- DexType currentType = encodedMethod.holder();
+ ProgramMethod context = code.context();
ListIterator<BasicBlock> blocks = code.listIterator();
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
@@ -147,8 +110,7 @@
Instruction instruction = instructions.next();
if (instruction.isInvokeCustom()) {
InvokeCustom invoke = instruction.asInvokeCustom();
- LambdaDescriptor descriptor =
- inferLambdaDescriptor(invoke.getCallSite(), encodedMethod.holder());
+ LambdaDescriptor descriptor = inferLambdaDescriptor(invoke.getCallSite(), context);
if (descriptor == LambdaDescriptor.MATCH_FAILED) {
continue;
}
@@ -156,9 +118,9 @@
// We have a descriptor, get the lambda class. In D8, we synthesize the lambda classes
// during IR processing, and therefore we may need to create it now.
LambdaClass lambdaClass =
- getAppView().enableWholeProgramOptimizations()
- ? getKnownLambdaClass(descriptor, currentType)
- : getOrCreateLambdaClass(descriptor, currentType);
+ appView.enableWholeProgramOptimizations()
+ ? getKnownLambdaClass(descriptor, context)
+ : getOrCreateLambdaClass(descriptor, context);
assert lambdaClass != null;
// We rely on patch performing its work in a way which
@@ -169,7 +131,7 @@
}
}
if (!affectedValues.isEmpty()) {
- new TypeAnalysis(getAppView()).narrowing(affectedValues);
+ new TypeAnalysis(appView).narrowing(affectedValues);
}
assert code.isConsistentSSA();
}
@@ -177,7 +139,7 @@
/** Remove lambda deserialization methods. */
public void removeLambdaDeserializationMethods(Iterable<DexProgramClass> classes) {
for (DexProgramClass clazz : classes) {
- clazz.removeMethod(getFactory().deserializeLambdaMethod);
+ clazz.removeMethod(appView.dexItemFactory().deserializeLambdaMethod);
}
}
@@ -189,7 +151,7 @@
knownLambdaClasses.values(), converter, executorService);
for (LambdaClass lambdaClass : knownLambdaClasses.values()) {
DexProgramClass synthesizedClass = lambdaClass.getOrCreateLambdaClass();
- getAppInfo().addSynthesizedClass(synthesizedClass);
+ appView.appInfo().addSynthesizedClass(synthesizedClass);
builder.addSynthesizedClass(synthesizedClass, lambdaClass.addToMainDexList.get());
}
optimizeSynthesizedClasses(converter, executorService);
@@ -204,17 +166,11 @@
executorService);
}
- public Set<DexCallSite> getDesugaredCallSites() {
- synchronized (knownCallSites) {
- return knownCallSites.keySet();
- }
- }
-
// Matches invoke-custom instruction operands to infer lambda descriptor
// corresponding to this lambda invocation point.
//
// Returns the lambda descriptor or `MATCH_FAILED`.
- private LambdaDescriptor inferLambdaDescriptor(DexCallSite callSite, DexType invocationContext) {
+ private LambdaDescriptor inferLambdaDescriptor(DexCallSite callSite, ProgramMethod context) {
// We check the map before and after inferring lambda descriptor to minimize time
// spent in synchronized block. As a result we may throw away calculated descriptor
// in rare case when another thread has same call site processed concurrently,
@@ -225,17 +181,18 @@
: putIfAbsent(
knownCallSites,
callSite,
- LambdaDescriptor.infer(callSite, getAppInfo(), invocationContext));
+ LambdaDescriptor.infer(callSite, appView.appInfoForDesugaring(), context));
}
private boolean isInMainDexList(DexType type) {
- return getAppInfo().isInMainDexList(type);
+ return appView.appInfo().isInMainDexList(type);
}
// Returns a lambda class corresponding to the lambda descriptor and context,
// creates the class if it does not yet exist.
- public LambdaClass getOrCreateLambdaClass(LambdaDescriptor descriptor, DexType accessedFrom) {
- DexType lambdaClassType = LambdaClass.createLambdaClassType(this, accessedFrom, descriptor);
+ public LambdaClass getOrCreateLambdaClass(
+ LambdaDescriptor descriptor, ProgramMethod accessedFrom) {
+ DexType lambdaClassType = LambdaClass.createLambdaClassType(appView, accessedFrom, descriptor);
// We check the map twice to to minimize time spent in synchronized block.
LambdaClass lambdaClass = getKnown(knownLambdaClasses, lambdaClassType);
if (lambdaClass == null) {
@@ -243,50 +200,50 @@
putIfAbsent(
knownLambdaClasses,
lambdaClassType,
- new LambdaClass(this, accessedFrom, lambdaClassType, descriptor));
- if (getAppView().options().isDesugaredLibraryCompilation()) {
+ new LambdaClass(appView, this, accessedFrom, lambdaClassType, descriptor));
+ if (appView.options().isDesugaredLibraryCompilation()) {
DexType rewrittenType =
- getAppView().rewritePrefix.rewrittenType(accessedFrom, getAppView());
+ appView.rewritePrefix.rewrittenType(accessedFrom.getHolderType(), appView);
if (rewrittenType == null) {
rewrittenType =
- getAppView()
+ appView
.options()
.desugaredLibraryConfiguration
.getEmulateLibraryInterface()
- .get(accessedFrom);
+ .get(accessedFrom.getHolderType());
}
if (rewrittenType != null) {
addRewritingPrefix(accessedFrom, rewrittenType, lambdaClassType);
}
}
}
- lambdaClass.addSynthesizedFrom(getAppView().definitionFor(accessedFrom).asProgramClass());
- if (isInMainDexList(accessedFrom)) {
+ lambdaClass.addSynthesizedFrom(accessedFrom.getHolder());
+ if (isInMainDexList(accessedFrom.getHolderType())) {
lambdaClass.addToMainDexList.set(true);
}
return lambdaClass;
}
- private LambdaClass getKnownLambdaClass(LambdaDescriptor descriptor, DexType accessedFrom) {
- DexType lambdaClassType = LambdaClass.createLambdaClassType(this, accessedFrom, descriptor);
+ private LambdaClass getKnownLambdaClass(LambdaDescriptor descriptor, ProgramMethod accessedFrom) {
+ DexType lambdaClassType = LambdaClass.createLambdaClassType(appView, accessedFrom, descriptor);
return getKnown(knownLambdaClasses, lambdaClassType);
}
- private void addRewritingPrefix(DexType type, DexType rewritten, DexType lambdaClassType) {
+ private void addRewritingPrefix(
+ ProgramMethod context, DexType rewritten, DexType lambdaClassType) {
String javaName = lambdaClassType.toString();
- String typeString = type.toString();
+ String typeString = context.getHolderType().toString();
String actualPrefix = typeString.substring(0, typeString.lastIndexOf('.'));
String rewrittenString = rewritten.toString();
String actualRewrittenPrefix = rewrittenString.substring(0, rewrittenString.lastIndexOf('.'));
assert javaName.startsWith(actualPrefix);
- getAppView()
- .rewritePrefix
- .rewriteType(
- lambdaClassType,
- getFactory()
- .createType(
- DescriptorUtils.javaTypeToDescriptor(
- actualRewrittenPrefix + javaName.substring(actualPrefix.length()))));
+ appView.rewritePrefix.rewriteType(
+ lambdaClassType,
+ appView
+ .dexItemFactory()
+ .createType(
+ DescriptorUtils.javaTypeToDescriptor(
+ actualRewrittenPrefix + javaName.substring(actualPrefix.length()))));
}
private static <K, V> V getKnown(Map<K, V> map, K key) {
@@ -326,7 +283,7 @@
// The out value might be empty in case it was optimized out.
lambdaInstanceValue =
code.createValue(
- TypeElement.fromDexType(lambdaClass.type, Nullability.maybeNull(), getAppView()));
+ TypeElement.fromDexType(lambdaClass.type, Nullability.maybeNull(), appView));
} else {
affectedValues.add(lambdaInstanceValue);
}
@@ -379,7 +336,7 @@
BasicBlock currentBlock = newInstance.getBlock();
BasicBlock nextBlock = instructions.split(code, blocks);
assert !instructions.hasNext();
- nextBlock.copyCatchHandlers(code, blocks, currentBlock, getAppView().options());
+ nextBlock.copyCatchHandlers(code, blocks, currentBlock, appView.options());
}
public Map<DexType, LambdaClass> getKnownLambdaClasses() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaSynthesizedCode.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaSynthesizedCode.java
index 7e50b88..5643288 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaSynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaSynthesizedCode.java
@@ -21,7 +21,7 @@
}
final DexItemFactory dexItemFactory() {
- return lambda.rewriter.getFactory();
+ return lambda.appView.dexItemFactory();
}
final LambdaDescriptor descriptor() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/SynthesizedLambdaSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/SynthesizedLambdaSourceCode.java
index 7677cee..fc12713 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/SynthesizedLambdaSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/SynthesizedLambdaSourceCode.java
@@ -40,7 +40,7 @@
}
final DexItemFactory factory() {
- return lambda.rewriter.getFactory();
+ return lambda.appView.dexItemFactory();
}
final int enforceParameterType(int register, DexType paramType, DexType enforcedType) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java b/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
index 8d1124b..8912aeb 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.ir.optimize;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexProgramClass;
@@ -85,7 +84,7 @@
if (mode != Mode.COLLECT) {
return;
}
- DexEncodedMethod context = code.method();
+ ProgramMethod context = code.context();
for (Instruction instruction : code.instructions()) {
if (!instruction.isInvokeMethod() && !instruction.isInvokeCustom()) {
continue;
@@ -95,26 +94,28 @@
if (invoke.isInvokeMethodWithDynamicDispatch()) {
DexMethod invokedMethod = invoke.getInvokedMethod();
ResolutionResult resolutionResult =
- appView.appInfo().resolveMethod(invokedMethod.holder, invokedMethod);
+ appView.appInfo().resolveMethod(invokedMethod, invoke.isInvokeInterface());
// For virtual and interface calls, proceed on valid results only (since it's enforced).
- if (!resolutionResult.isVirtualTarget()) {
+ if (!resolutionResult.isSingleResolution() || !resolutionResult.isVirtualTarget()) {
continue;
}
// If the resolution ended up with a single target, check if it is a library override.
// And if so, bail out early (to avoid expensive target lookup).
- if (resolutionResult.isSingleResolution()
- && isLibraryMethodOrLibraryMethodOverride(resolutionResult.getSingleTarget())) {
+ ProgramMethod resolutionTarget =
+ resolutionResult.asSingleResolution().getResolutionPair().asProgramMethod();
+ if (resolutionTarget == null
+ || isLibraryMethodOrLibraryMethodOverride(resolutionTarget)) {
continue;
}
}
- Collection<DexEncodedMethod> targets = invoke.lookupTargets(appView, context.holder());
+ ProgramMethodSet targets = invoke.lookupProgramDispatchTargets(appView, context);
assert invoke.isInvokeMethodWithDynamicDispatch()
// For other invocation types, the size of targets should be at most one.
|| targets == null || targets.size() <= 1;
if (targets == null || targets.isEmpty() || hasLibraryOverrides(targets)) {
continue;
}
- for (DexEncodedMethod target : targets) {
+ for (ProgramMethod target : targets) {
recordArgumentsIfNecessary(target, invoke.inValues());
}
}
@@ -132,7 +133,6 @@
appView
.appInfo()
.resolveMethod(
- bootstrapMethod.asMethod().holder,
bootstrapMethod.asMethod(),
bootstrapMethod.isInterface)
.asSingleResolution();
@@ -147,8 +147,8 @@
// TODO(b/140204899): Instead of reprocessing here, pass stopping criteria to lookup?
// If any of target method is a library method override, bail out entirely/early.
- private boolean hasLibraryOverrides(Collection<DexEncodedMethod> targets) {
- for (DexEncodedMethod target : targets) {
+ private boolean hasLibraryOverrides(ProgramMethodSet targets) {
+ for (ProgramMethod target : targets) {
if (isLibraryMethodOrLibraryMethodOverride(target)) {
return true;
}
@@ -156,54 +156,42 @@
return false;
}
- private boolean isLibraryMethodOrLibraryMethodOverride(DexEncodedMethod target) {
- // Not a program method.
- if (!target.isProgramMethod(appView)) {
- return true;
- }
+ private boolean isLibraryMethodOrLibraryMethodOverride(ProgramMethod target) {
// If the method overrides a library method, it is unsure how the method would be invoked by
// that library.
- if (target.isLibraryMethodOverride().isTrue()) {
- return true;
- }
- return false;
+ return target.getDefinition().isLibraryMethodOverride().isTrue();
}
// Record arguments for the given method if necessary.
// At the same time, if it decides to bail out, make the corresponding info immutable so that we
// can avoid recording arguments for the same method accidentally.
- private void recordArgumentsIfNecessary(DexEncodedMethod target, List<Value> inValues) {
- assert !target.isObsolete();
- if (appView.appInfo().neverReprocess.contains(target.method)) {
+ private void recordArgumentsIfNecessary(ProgramMethod target, List<Value> inValues) {
+ assert !target.getDefinition().isObsolete();
+ if (appView.appInfo().neverReprocess.contains(target.getReference())) {
return;
}
- if (target.getCallSiteOptimizationInfo().isTop()) {
+ if (target.getDefinition().getCallSiteOptimizationInfo().isTop()) {
return;
}
- target.joinCallSiteOptimizationInfo(
- computeCallSiteOptimizationInfoFromArguments(target, inValues), appView);
+ target
+ .getDefinition()
+ .joinCallSiteOptimizationInfo(
+ computeCallSiteOptimizationInfoFromArguments(target, inValues), appView);
}
private CallSiteOptimizationInfo computeCallSiteOptimizationInfoFromArguments(
- DexEncodedMethod target, List<Value> inValues) {
+ ProgramMethod target, List<Value> inValues) {
// No method body or no argument at all.
- if (target.shouldNotHaveCode() || inValues.size() == 0) {
+ if (target.getDefinition().shouldNotHaveCode() || inValues.size() == 0) {
return CallSiteOptimizationInfo.TOP;
}
// If pinned, that method could be invoked via reflection.
- if (appView.appInfo().isPinned(target.method)) {
- return CallSiteOptimizationInfo.TOP;
- }
- // Not a program method.
- if (!target.isProgramMethod(appView)) {
- // But, should not be reachable, since we already bail out.
- assert false
- : "Trying to compute call site optimization info for " + target.toSourceString();
+ if (appView.appInfo().isPinned(target.getReference())) {
return CallSiteOptimizationInfo.TOP;
}
// If the method overrides a library method, it is unsure how the method would be invoked by
// that library.
- if (target.isLibraryMethodOverride().isTrue()) {
+ if (target.getDefinition().isLibraryMethodOverride().isTrue()) {
// But, should not be reachable, since we already bail out.
assert false
: "Trying to compute call site optimization info for " + target.toSourceString();
@@ -212,8 +200,8 @@
// If the program already has illegal accesses, method resolution results will reflect that too.
// We should avoid recording arguments in that case. E.g., b/139823850: static methods can be a
// result of virtual call targets, if that's the only method that matches name and signature.
- int argumentOffset = target.isStatic() ? 0 : 1;
- if (inValues.size() != argumentOffset + target.method.getArity()) {
+ int argumentOffset = target.getDefinition().isStatic() ? 0 : 1;
+ if (inValues.size() != argumentOffset + target.getReference().getArity()) {
return CallSiteOptimizationInfo.BOTTOM;
}
return ConcreteCallSiteOptimizationInfo.fromArguments(appView, target, inValues);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
index ce853a2..a7a24cc 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.graph.AppView;
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.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
@@ -29,6 +28,8 @@
import com.android.tools.r8.graph.DexValue.DexValueNull;
import com.android.tools.r8.graph.DexValue.DexValueShort;
import com.android.tools.r8.graph.DexValue.DexValueString;
+import com.android.tools.r8.graph.FieldResolutionResult;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ValueMayDependOnEnvironmentAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.ArrayPut;
@@ -53,7 +54,6 @@
import com.android.tools.r8.utils.IteratorUtils;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
-import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
@@ -123,18 +123,17 @@
this.dexItemFactory = appView.dexItemFactory();
}
- public ClassInitializerDefaultsResult optimize(
- DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
- if (appView.options().debug || method.getOptimizationInfo().isReachabilitySensitive()) {
+ public ClassInitializerDefaultsResult optimize(IRCode code, OptimizationFeedback feedback) {
+ if (appView.options().debug) {
return ClassInitializerDefaultsResult.empty();
}
- if (!method.isClassInitializer()) {
+ ProgramMethod context = code.context();
+ if (context.getDefinition().getOptimizationInfo().isReachabilitySensitive()) {
return ClassInitializerDefaultsResult.empty();
}
- DexClass clazz = appView.definitionFor(method.holder());
- if (clazz == null) {
+ if (!context.getDefinition().isClassInitializer()) {
return ClassInitializerDefaultsResult.empty();
}
@@ -142,8 +141,9 @@
// a static put on a field on this class with a value that can be hoisted to
// the field initial value.
Set<StaticPut> unnecessaryStaticPuts = Sets.newIdentityHashSet();
- Collection<StaticPut> finalFieldPuts =
- findFinalFieldPutsWhileCollectingUnnecessaryStaticPuts(code, clazz, unnecessaryStaticPuts);
+ Map<DexEncodedField, StaticPut> finalFieldPuts =
+ findFinalFieldPutsWhileCollectingUnnecessaryStaticPuts(
+ code, context, unnecessaryStaticPuts);
// Return eagerly if there is nothing to optimize.
if (finalFieldPuts.isEmpty()) {
@@ -154,43 +154,43 @@
Map<DexEncodedField, DexValue> fieldsWithStaticValues = new IdentityHashMap<>();
// Set initial values for static fields from the definitive static put instructions collected.
- for (StaticPut put : finalFieldPuts) {
- DexEncodedField field = appView.appInfo().resolveField(put.getField());
- DexType fieldType = field.field.type;
- Value value = put.value();
- if (unnecessaryStaticPuts.contains(put)) {
- if (fieldType == dexItemFactory.stringType) {
- fieldsWithStaticValues.put(field, getDexStringValue(value, method.holder()));
- } else if (fieldType.isClassType() || fieldType.isArrayType()) {
- if (value.isZero()) {
- fieldsWithStaticValues.put(field, DexValueNull.NULL);
- } else {
- throw new Unreachable("Unexpected default value for field type " + fieldType + ".");
+ finalFieldPuts.forEach(
+ (field, put) -> {
+ DexType fieldType = field.field.type;
+ Value value = put.value();
+ if (unnecessaryStaticPuts.contains(put)) {
+ if (fieldType == dexItemFactory.stringType) {
+ fieldsWithStaticValues.put(field, getDexStringValue(value, context.getHolderType()));
+ } else if (fieldType.isClassType() || fieldType.isArrayType()) {
+ if (value.isZero()) {
+ fieldsWithStaticValues.put(field, DexValueNull.NULL);
+ } else {
+ throw new Unreachable("Unexpected default value for field type " + fieldType + ".");
+ }
+ } else {
+ ConstNumber cnst = value.getConstInstruction().asConstNumber();
+ if (fieldType == dexItemFactory.booleanType) {
+ fieldsWithStaticValues.put(field, DexValueBoolean.create(cnst.getBooleanValue()));
+ } else if (fieldType == dexItemFactory.byteType) {
+ fieldsWithStaticValues.put(field, DexValueByte.create((byte) cnst.getIntValue()));
+ } else if (fieldType == dexItemFactory.shortType) {
+ fieldsWithStaticValues.put(field, DexValueShort.create((short) cnst.getIntValue()));
+ } else if (fieldType == dexItemFactory.intType) {
+ fieldsWithStaticValues.put(field, DexValueInt.create(cnst.getIntValue()));
+ } else if (fieldType == dexItemFactory.longType) {
+ fieldsWithStaticValues.put(field, DexValueLong.create(cnst.getLongValue()));
+ } else if (fieldType == dexItemFactory.floatType) {
+ fieldsWithStaticValues.put(field, DexValueFloat.create(cnst.getFloatValue()));
+ } else if (fieldType == dexItemFactory.doubleType) {
+ fieldsWithStaticValues.put(field, DexValueDouble.create(cnst.getDoubleValue()));
+ } else if (fieldType == dexItemFactory.charType) {
+ fieldsWithStaticValues.put(field, DexValueChar.create((char) cnst.getIntValue()));
+ } else {
+ throw new Unreachable("Unexpected field type " + fieldType + ".");
+ }
+ }
}
- } else {
- ConstNumber cnst = value.getConstInstruction().asConstNumber();
- if (fieldType == dexItemFactory.booleanType) {
- fieldsWithStaticValues.put(field, DexValueBoolean.create(cnst.getBooleanValue()));
- } else if (fieldType == dexItemFactory.byteType) {
- fieldsWithStaticValues.put(field, DexValueByte.create((byte) cnst.getIntValue()));
- } else if (fieldType == dexItemFactory.shortType) {
- fieldsWithStaticValues.put(field, DexValueShort.create((short) cnst.getIntValue()));
- } else if (fieldType == dexItemFactory.intType) {
- fieldsWithStaticValues.put(field, DexValueInt.create(cnst.getIntValue()));
- } else if (fieldType == dexItemFactory.longType) {
- fieldsWithStaticValues.put(field, DexValueLong.create(cnst.getLongValue()));
- } else if (fieldType == dexItemFactory.floatType) {
- fieldsWithStaticValues.put(field, DexValueFloat.create(cnst.getFloatValue()));
- } else if (fieldType == dexItemFactory.doubleType) {
- fieldsWithStaticValues.put(field, DexValueDouble.create(cnst.getDoubleValue()));
- } else if (fieldType == dexItemFactory.charType) {
- fieldsWithStaticValues.put(field, DexValueChar.create((char) cnst.getIntValue()));
- } else {
- throw new Unreachable("Unexpected field type " + fieldType + ".");
- }
- }
- }
- }
+ });
if (!unnecessaryStaticPuts.isEmpty()) {
// Remove the static put instructions now replaced by static field initial values.
@@ -239,10 +239,11 @@
// First collect all the candidate fields that are *potentially* no longer being written to.
Set<DexField> candidates =
- finalFieldPuts.stream()
+ finalFieldPuts.values().stream()
.filter(unnecessaryStaticPuts::contains)
.map(FieldInstruction::getField)
.map(appInfoWithLiveness::resolveField)
+ .map(FieldResolutionResult::getResolvedField)
.filter(appInfoWithLiveness::isStaticFieldWrittenOnlyInEnclosingStaticInitializer)
.map(field -> field.field)
.collect(Collectors.toSet());
@@ -252,7 +253,8 @@
if (instruction.isStaticPut()) {
StaticPut staticPutInstruction = instruction.asStaticPut();
DexField field = staticPutInstruction.getField();
- DexEncodedField encodedField = appInfoWithLiveness.resolveField(field);
+ DexEncodedField encodedField =
+ appInfoWithLiveness.resolveField(field).getResolvedField();
if (encodedField != null) {
candidates.remove(encodedField.field);
}
@@ -357,13 +359,13 @@
return null;
}
- private Collection<StaticPut> findFinalFieldPutsWhileCollectingUnnecessaryStaticPuts(
- IRCode code, DexClass clazz, Set<StaticPut> unnecessaryStaticPuts) {
+ private Map<DexEncodedField, StaticPut> findFinalFieldPutsWhileCollectingUnnecessaryStaticPuts(
+ IRCode code, ProgramMethod context, Set<StaticPut> unnecessaryStaticPuts) {
ValueMayDependOnEnvironmentAnalysis environmentAnalysis =
new ValueMayDependOnEnvironmentAnalysis(appView, code);
- Map<DexField, StaticPut> finalFieldPuts = Maps.newIdentityHashMap();
+ Map<DexEncodedField, StaticPut> finalFieldPuts = Maps.newIdentityHashMap();
Map<DexField, Set<StaticPut>> isWrittenBefore = Maps.newIdentityHashMap();
- Set<DexField> isReadBefore = Sets.newIdentityHashSet();
+ Set<DexEncodedField> isReadBefore = Sets.newIdentityHashSet();
final int color = code.reserveMarkingColor();
try {
BasicBlock block = code.entryBlock();
@@ -374,29 +376,30 @@
// Array stores do not impact our ability to move constants into the class definition,
// as long as the instructions do not throw.
ArrayPut arrayPut = instruction.asArrayPut();
- if (arrayPut.instructionInstanceCanThrow(appView, clazz.type).isThrowing()) {
+ if (arrayPut.instructionInstanceCanThrow(appView, context).isThrowing()) {
return validateFinalFieldPuts(finalFieldPuts, isWrittenBefore);
}
} else if (instruction.isStaticGet()) {
StaticGet get = instruction.asStaticGet();
- DexEncodedField field = appView.appInfo().resolveField(get.getField());
- if (field != null && field.holder() == clazz.type) {
- isReadBefore.add(field.field);
- } else if (instruction.instructionMayHaveSideEffects(appView, clazz.type)) {
+ DexEncodedField field = context.getHolder().lookupField(get.getField());
+ if (field != null) {
+ isReadBefore.add(field);
+ } else {
// Reading another field is only OK if the read does not have side-effects.
return validateFinalFieldPuts(finalFieldPuts, isWrittenBefore);
}
} else if (instruction.isStaticPut()) {
StaticPut put = instruction.asStaticPut();
- if (put.getField().holder != clazz.type) {
+ if (put.getField().holder != context.getHolderType()) {
// Can cause clinit on another class which can read uninitialized static fields
// of this class.
return validateFinalFieldPuts(finalFieldPuts, isWrittenBefore);
}
- DexField field = put.getField();
+ DexField fieldReference = put.getField();
+ DexEncodedField field = context.getHolder().lookupField(fieldReference);
Value value = put.value();
TypeElement valueType = value.getType();
- if (clazz.definesStaticField(field)) {
+ if (field != null) {
if (isReadBefore.contains(field)) {
// Promoting this put to a class constant would cause a previous static-get
// instruction to read a different value.
@@ -406,37 +409,37 @@
continue;
}
if (value.isConstant()) {
- if (field.type.isReferenceType() && value.isZero()) {
+ if (fieldReference.type.isReferenceType() && value.isZero()) {
finalFieldPuts.put(field, put);
unnecessaryStaticPuts.add(put);
// If this field has been written before, those static-put's up to this point are
// redundant. We should remove them all together; otherwise, remaining static-put
// that is not constant can change the program semantics. See b/138912149.
- if (isWrittenBefore.containsKey(field)) {
- unnecessaryStaticPuts.addAll(isWrittenBefore.get(field));
- isWrittenBefore.remove(field);
+ if (isWrittenBefore.containsKey(fieldReference)) {
+ unnecessaryStaticPuts.addAll(isWrittenBefore.get(fieldReference));
+ isWrittenBefore.remove(fieldReference);
}
continue;
- } else if (field.type.isPrimitiveType()
- || field.type == dexItemFactory.stringType) {
+ } else if (fieldReference.type.isPrimitiveType()
+ || fieldReference.type == dexItemFactory.stringType) {
finalFieldPuts.put(field, put);
unnecessaryStaticPuts.add(put);
- if (isWrittenBefore.containsKey(field)) {
- unnecessaryStaticPuts.addAll(isWrittenBefore.get(field));
- isWrittenBefore.remove(field);
+ if (isWrittenBefore.containsKey(fieldReference)) {
+ unnecessaryStaticPuts.addAll(isWrittenBefore.get(fieldReference));
+ isWrittenBefore.remove(fieldReference);
}
continue;
}
// Still constant, but not able to represent it as static encoded values, e.g.,
// const-class, const-method-handle, etc. This static-put can be redundant if the
// field is rewritten with another constant. Will fall through and track static-put.
- } else if (isClassNameConstantOf(clazz, put)) {
+ } else if (isClassNameConstantOf(context.getHolder(), put)) {
// Collect put of class name constant as a potential default value.
finalFieldPuts.put(field, put);
unnecessaryStaticPuts.add(put);
- if (isWrittenBefore.containsKey(field)) {
- unnecessaryStaticPuts.addAll(isWrittenBefore.get(field));
- isWrittenBefore.remove(field);
+ if (isWrittenBefore.containsKey(fieldReference)) {
+ unnecessaryStaticPuts.addAll(isWrittenBefore.get(fieldReference));
+ isWrittenBefore.remove(fieldReference);
}
continue;
} else if (valueType.isReferenceType() && valueType.isDefinitelyNotNull()) {
@@ -448,19 +451,19 @@
// However, if static-put is still remaining in `isWrittenBefore`, that indicates
// the previous candidate as final field put is no longer valid.
isWrittenBefore
- .computeIfAbsent(field, ignore -> Sets.newIdentityHashSet())
+ .computeIfAbsent(fieldReference, ignore -> Sets.newIdentityHashSet())
.add(put);
} else {
// Writing another field is not OK.
return validateFinalFieldPuts(finalFieldPuts, isWrittenBefore);
}
- } else if (instruction.instructionMayHaveSideEffects(appView, clazz.type)) {
+ } else if (instruction.instructionMayHaveSideEffects(appView, context)) {
// Some other instruction that has side-effects. Stop here.
return validateFinalFieldPuts(finalFieldPuts, isWrittenBefore);
} else {
// TODO(b/120138731): This check should be removed when the Class.get*Name()
// optimizations become enabled.
- if (isClassNameConstantOf(clazz, instruction)) {
+ if (isClassNameConstantOf(context.getHolder(), instruction)) {
// OK, this does not read one of the fields in the enclosing class.
continue;
}
@@ -489,8 +492,8 @@
return validateFinalFieldPuts(finalFieldPuts, isWrittenBefore);
}
- private Collection<StaticPut> validateFinalFieldPuts(
- Map<DexField, StaticPut> finalFieldPuts,
+ private Map<DexEncodedField, StaticPut> validateFinalFieldPuts(
+ Map<DexEncodedField, StaticPut> finalFieldPuts,
Map<DexField, Set<StaticPut>> isWrittenBefore) {
// If a field is rewritten again with other values that we can't represent as static encoded
// values, that would be recorded at `isWrittenBefore`, which is used to collect and remove
@@ -512,7 +515,7 @@
// values, leaving it can cause incorrect optimizations. Thus, we invalidate candidates of
// final field puts at all.
isWrittenBefore.keySet().forEach(finalFieldPuts::remove);
- return finalFieldPuts.values();
+ return finalFieldPuts;
}
// Check if the static put is a constant derived from the class holding the method.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 3dbe05d..29a0c32 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -24,6 +24,7 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.equivalence.BasicBlockBehavioralSubsumption;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -312,7 +313,7 @@
boolean canDetachValueIsNullTarget = true;
for (Instruction i : valueIsNullTarget.instructionsBefore(throwInstruction)) {
- if (!i.isBlockLocalInstructionWithoutSideEffects(appView, code.method().holder())) {
+ if (!i.isBlockLocalInstructionWithoutSideEffects(appView, code.context())) {
canDetachValueIsNullTarget = false;
break;
}
@@ -1133,7 +1134,7 @@
BasicBlock defaultTarget = theSwitch.fallthroughBlock();
SwitchCaseEliminator eliminator = null;
BasicBlockBehavioralSubsumption behavioralSubsumption =
- new BasicBlockBehavioralSubsumption(appView, code.method().holder());
+ new BasicBlockBehavioralSubsumption(appView, code.context());
// Compute the set of switch cases that can be removed.
int alwaysHitCase = -1;
@@ -1258,7 +1259,7 @@
}
// Check if the invoked method is known to return one of its arguments.
- DexEncodedMethod target = invoke.lookupSingleTarget(appView, code.method().holder());
+ DexEncodedMethod target = invoke.lookupSingleTarget(appView, code.context());
if (target != null && target.getOptimizationInfo().returnsArgument()) {
int argumentIndex = target.getOptimizationInfo().getReturnedArgument();
// Replace the out value of the invoke with the argument and ignore the out value.
@@ -1380,7 +1381,7 @@
// If the cast type is not accessible in the current context, we should not remove the cast
// in order to preserve IllegalAccessError. Note that JVM and ART behave differently: see
// {@link com.android.tools.r8.ir.optimize.checkcast.IllegalAccessErrorTest}.
- if (!isTypeVisibleFromContext(appView, code.method().holder(), castType)) {
+ if (!isTypeVisibleFromContext(appView, code.context(), castType)) {
return RemoveCheckCastInstructionIfTrivialResult.NO_REMOVALS;
}
@@ -1437,7 +1438,7 @@
InstanceOf instanceOf, InstructionListIterator it, IRCode code) {
// If the instance-of type is not accessible in the current context, we should not remove the
// instance-of instruction in order to preserve IllegalAccessError.
- if (!isTypeVisibleFromContext(appView, code.method().holder(), instanceOf.type())) {
+ if (!isTypeVisibleFromContext(appView, code.context(), instanceOf.type())) {
return false;
}
@@ -2505,7 +2506,7 @@
}
}
} else {
- DexType context = code.method().holder();
+ ProgramMethod context = code.context();
AbstractValue abstractValue = lhs.getAbstractValue(appView, context);
if (abstractValue.isSingleConstClassValue()) {
AbstractValue otherAbstractValue = rhs.getAbstractValue(appView, context);
@@ -2822,7 +2823,7 @@
InvokeMethod invoke = insn.asInvokeMethod();
DexEncodedMethod singleTarget =
- invoke.lookupSingleTarget(appView.withLiveness(), code.method().holder());
+ invoke.lookupSingleTarget(appView.withLiveness(), code.context());
if (singleTarget == null || !singleTarget.getOptimizationInfo().neverReturnsNormally()) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java b/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
index 691de34..36fba35 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
@@ -11,8 +11,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.SingleFieldValue;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -87,8 +86,7 @@
}
public void canonicalize(AppView<?> appView, IRCode code) {
- DexEncodedMethod method = code.method();
- DexType context = method.holder();
+ ProgramMethod context = code.context();
Object2ObjectLinkedOpenCustomHashMap<Instruction, List<Value>> valuesDefinedByConstant =
new Object2ObjectLinkedOpenCustomHashMap<>(
new Strategy<Instruction>() {
@@ -149,7 +147,8 @@
continue;
}
SingleFieldValue singleFieldValue = abstractValue.asSingleFieldValue();
- if (method.isClassInitializer() && method.holder() == singleFieldValue.getField().holder) {
+ if (context.getDefinition().isClassInitializer()
+ && context.getHolderType() == singleFieldValue.getField().holder) {
// Avoid that canonicalization inserts a read before the unique write in the class
// initializer, as that would change the program behavior.
continue;
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 e0066a7..4b8ee00 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
@@ -9,7 +9,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.Code;
-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;
@@ -328,11 +327,7 @@
ClassInitializationAnalysis classInitializationAnalysis,
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
InlineAction action = new InlineAction(singleTarget, invoke, reason);
- if (isTargetClassInitialized(
- invoke,
- method.getDefinition(),
- singleTarget.getDefinition(),
- classInitializationAnalysis)) {
+ if (isTargetClassInitialized(invoke, method, singleTarget, classInitializationAnalysis)) {
return action;
}
if (appView.canUseInitClass()
@@ -346,8 +341,8 @@
private boolean isTargetClassInitialized(
InvokeStatic invoke,
- DexEncodedMethod method,
- DexEncodedMethod target,
+ ProgramMethod context,
+ ProgramMethod target,
ClassInitializationAnalysis classInitializationAnalysis) {
// Only proceed with inlining a static invoke if:
// - the holder for the target is a subtype of the holder for the method,
@@ -356,28 +351,24 @@
// - the current method has already triggered the holder for the target method to be
// initialized, or
// - there is no non-trivial class initializer.
- DexType targetHolder = target.holder();
- if (appView.appInfo().isSubtype(method.holder(), targetHolder)) {
+ if (appView.appInfo().isSubtype(context.getHolderType(), target.getHolderType())) {
return true;
}
- DexClass clazz = appView.definitionFor(targetHolder);
- assert clazz != null;
- if (target.getOptimizationInfo().triggersClassInitBeforeAnySideEffect()) {
+ if (target.getDefinition().getOptimizationInfo().triggersClassInitBeforeAnySideEffect()) {
return true;
}
- if (!method.isStatic()) {
+ if (!context.getDefinition().isStatic()) {
boolean targetIsGuaranteedToBeInitialized =
appView.withInitializedClassesInInstanceMethods(
analysis ->
- analysis.isClassDefinitelyLoadedInInstanceMethodsOn(
- target.holder(), method.holder()),
+ analysis.isClassDefinitelyLoadedInInstanceMethod(target.getHolder(), context),
false);
if (targetIsGuaranteedToBeInitialized) {
return true;
}
}
if (classInitializationAnalysis.isClassDefinitelyLoadedBeforeInstruction(
- target.holder(), invoke)) {
+ target.getHolderType(), invoke)) {
return true;
}
// Check for class initializer side effects when loading this class, as inlining might remove
@@ -387,11 +378,11 @@
//
// For simplicity, we are conservative and consider all interfaces, not only the ones with
// default methods.
- if (!clazz.classInitializationMayHaveSideEffects(appView)) {
+ if (!target.getHolder().classInitializationMayHaveSideEffects(appView)) {
return true;
}
- if (appView.rootSet().bypassClinitForInlining.contains(target.method)) {
+ if (appView.rootSet().bypassClinitForInlining.contains(target.getReference())) {
return true;
}
@@ -488,7 +479,7 @@
// Final fields may not be initialized outside of a constructor in the enclosing class.
InstancePut instancePut = instruction.asInstancePut();
DexField field = instancePut.getField();
- DexEncodedField target = appView.appInfo().lookupInstanceTarget(field.holder, field);
+ DexEncodedField target = appView.appInfo().lookupInstanceTarget(field);
if (target == null || target.accessFlags.isFinal()) {
whyAreYouNotInliningReporter.reportUnsafeConstructorInliningDueToFinalFieldAssignment(
instancePut);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
index 0366798..8117d6c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
@@ -7,8 +7,8 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -52,8 +52,9 @@
this.appView = appView;
}
- public void devirtualizeInvokeInterface(IRCode code, DexProgramClass context) {
+ public void devirtualizeInvokeInterface(IRCode code) {
Set<Value> affectedValues = Sets.newIdentityHashSet();
+ ProgramMethod context = code.context();
Map<InvokeInterface, InvokeVirtual> devirtualizedCall = new IdentityHashMap<>();
DominatorTree dominatorTree = new DominatorTree(code);
Map<Value, Map<DexType, Value>> castedReceiverCache = new IdentityHashMap<>();
@@ -118,14 +119,14 @@
if (appView.options().testing.enableInvokeSuperToInvokeVirtualRewriting) {
if (current.isInvokeSuper()) {
InvokeSuper invoke = current.asInvokeSuper();
- DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, context.type);
+ DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, context);
if (singleTarget != null) {
DexClass holder = appView.definitionForHolder(singleTarget);
assert holder != null;
DexMethod invokedMethod = invoke.getInvokedMethod();
DexEncodedMethod newSingleTarget =
InvokeVirtual.lookupSingleTarget(
- appView, context.type, invokedMethod, invoke.getReceiver());
+ appView, context, invoke.getReceiver(), invokedMethod);
if (newSingleTarget == singleTarget) {
it.replaceCurrentInstruction(
new InvokeVirtual(invokedMethod, invoke.outValue(), invoke.arguments()));
@@ -139,7 +140,7 @@
InvokeVirtual invoke = current.asInvokeVirtual();
DexMethod invokedMethod = invoke.getInvokedMethod();
DexMethod reboundTarget =
- rebindVirtualInvokeToMostSpecific(invokedMethod, invoke.getReceiver(), context.type);
+ rebindVirtualInvokeToMostSpecific(invokedMethod, invoke.getReceiver(), context);
if (reboundTarget != invokedMethod) {
it.replaceCurrentInstruction(
new InvokeVirtual(reboundTarget, invoke.outValue(), invoke.arguments()));
@@ -151,7 +152,7 @@
continue;
}
InvokeInterface invoke = current.asInvokeInterface();
- DexEncodedMethod target = invoke.lookupSingleTarget(appView, context.type);
+ DexEncodedMethod target = invoke.lookupSingleTarget(appView, context);
if (target == null) {
continue;
}
@@ -163,7 +164,7 @@
}
// Due to the potential downcast below, make sure the new target holder is visible.
ConstraintWithTarget visibility =
- ConstraintWithTarget.classIsVisible(context.type, holderType, appView);
+ ConstraintWithTarget.classIsVisible(context.getHolder(), holderType, appView);
if (visibility == ConstraintWithTarget.NEVER) {
continue;
}
@@ -279,7 +280,7 @@
* entirely. Without this rewriting, we would have to keep A.foo() because the method is targeted.
*/
private DexMethod rebindVirtualInvokeToMostSpecific(
- DexMethod target, Value receiver, DexType context) {
+ DexMethod target, Value receiver, ProgramMethod context) {
if (!receiver.getType().isClassType()) {
return target;
}
@@ -296,7 +297,8 @@
// Virtual invoke is already as specific as it can get.
return target;
}
- ResolutionResult resolutionResult = appView.appInfo().resolveMethod(receiverType, target);
+ ResolutionResult resolutionResult =
+ appView.appInfo().resolveMethodOnClass(target, receiverType);
DexEncodedMethod newTarget =
resolutionResult.isVirtualTarget() ? resolutionResult.getSingleTarget() : null;
if (newTarget == null || newTarget.method == target) {
@@ -318,10 +320,11 @@
return target.isNonPrivateVirtualMethod() && appView.isInterface(target.holder()).isFalse();
}
- private boolean hasAccessToInvokeTargetFromContext(DexEncodedMethod target, DexType context) {
+ private boolean hasAccessToInvokeTargetFromContext(
+ DexEncodedMethod target, ProgramMethod context) {
assert !target.accessFlags.isPrivate();
DexType holder = target.holder();
- if (holder == context) {
+ if (holder == context.getHolderType()) {
// It is always safe to invoke a method from the same enclosing class.
return true;
}
@@ -330,7 +333,7 @@
// Conservatively report an illegal access.
return false;
}
- if (holder.isSamePackage(context)) {
+ if (holder.isSamePackage(context.getHolderType())) {
// The class must be accessible (note that we have already established that the method is not
// private).
return !clazz.accessFlags.isPrivate();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
index eac97c1..cbcbd2e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
@@ -78,8 +78,7 @@
TypeElement.fromDexType(invokedMethod.holder, definitelyNotNull(), appView);
dynamicLowerBoundType = null;
} else {
- DexEncodedMethod singleTarget =
- invoke.lookupSingleTarget(appView, code.method().holder());
+ DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, code.context());
if (singleTarget == null) {
continue;
}
@@ -96,7 +95,8 @@
}
} else if (current.isStaticGet()) {
StaticGet staticGet = current.asStaticGet();
- DexEncodedField encodedField = appView.appInfo().resolveField(staticGet.getField());
+ DexEncodedField encodedField =
+ appView.appInfo().resolveField(staticGet.getField()).getResolvedField();
if (encodedField == null) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java b/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
index 62b5ab3..b1af390 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -110,7 +110,7 @@
}
});
- DexType context = code.method().holder();
+ ProgramMethod context = code.context();
// Collect invocations along with arguments.
for (BasicBlock block : code.blocks) {
for (Instruction current : block.getInstructions()) {
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 6db2341..bb58ce1 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
@@ -147,22 +147,22 @@
}
private ConstraintWithTarget instructionAllowedForInlining(
- Instruction instruction, InliningConstraints inliningConstraints, DexType invocationContext) {
- ConstraintWithTarget result =
- instruction.inliningConstraint(inliningConstraints, invocationContext);
+ Instruction instruction, InliningConstraints inliningConstraints, ProgramMethod context) {
+ ConstraintWithTarget result = instruction.inliningConstraint(inliningConstraints, context);
if (result == ConstraintWithTarget.NEVER && instruction.isDebugInstruction()) {
return ConstraintWithTarget.ALWAYS;
}
return result;
}
- public ConstraintWithTarget computeInliningConstraint(IRCode code, ProgramMethod method) {
+ public ConstraintWithTarget computeInliningConstraint(IRCode code) {
if (containsPotentialCatchHandlerVerificationError(code)) {
return ConstraintWithTarget.NEVER;
}
+ ProgramMethod context = code.context();
if (appView.options().canHaveDalvikIntUsedAsNonIntPrimitiveTypeBug()
- && returnsIntAsBoolean(code, method)) {
+ && returnsIntAsBoolean(code, context)) {
return ConstraintWithTarget.NEVER;
}
@@ -171,7 +171,7 @@
new InliningConstraints(appView, GraphLense.getIdentityLense());
for (Instruction instruction : code.instructions()) {
ConstraintWithTarget state =
- instructionAllowedForInlining(instruction, inliningConstraints, method.getHolderType());
+ instructionAllowedForInlining(instruction, inliningConstraints, context);
if (state == ConstraintWithTarget.NEVER) {
result = state;
break;
@@ -198,28 +198,27 @@
return false;
}
- boolean hasInliningAccess(ProgramMethod method, ProgramMethod target) {
- if (!isVisibleWithFlags(
- target.getHolderType(), method.getHolderType(), target.getDefinition().accessFlags)) {
+ boolean hasInliningAccess(ProgramMethod context, ProgramMethod target) {
+ if (!isVisibleWithFlags(target.getHolderType(), context, target.getDefinition().accessFlags)) {
return false;
}
// The class needs also to be visible for us to have access.
- return isVisibleWithFlags(
- target.getHolderType(), method.getHolderType(), target.getHolder().accessFlags);
+ return isVisibleWithFlags(target.getHolderType(), context, target.getHolder().accessFlags);
}
- private boolean isVisibleWithFlags(DexType target, DexType context, AccessFlags<?> flags) {
+ private boolean isVisibleWithFlags(DexType target, ProgramMethod context, AccessFlags<?> flags) {
if (flags.isPublic()) {
return true;
}
if (flags.isPrivate()) {
- return NestUtils.sameNest(target, context, appView);
+ return NestUtils.sameNest(target, context.getHolderType(), appView);
}
if (flags.isProtected()) {
- return appView.appInfo().isSubtype(context, target) || target.isSamePackage(context);
+ return appView.appInfo().isSubtype(context.getHolderType(), target)
+ || target.isSamePackage(context.getHolderType());
}
// package-private
- return target.isSamePackage(context);
+ return target.isSamePackage(context.getHolderType());
}
public synchronized boolean isDoubleInlineSelectedTarget(ProgramMethod method) {
@@ -367,36 +366,36 @@
}
public static ConstraintWithTarget deriveConstraint(
- DexType contextHolder, DexType targetHolder, AccessFlags flags, AppView<?> appView) {
+ DexProgramClass context, DexType targetHolder, AccessFlags<?> flags, AppView<?> appView) {
if (flags.isPublic()) {
return ALWAYS;
} else if (flags.isPrivate()) {
- DexClass contextHolderClass = appView.definitionFor(contextHolder);
- assert contextHolderClass != null;
- if (contextHolderClass.isInANest()) {
- return NestUtils.sameNest(contextHolder, targetHolder, appView)
+ if (context.isInANest()) {
+ return NestUtils.sameNest(context.getType(), targetHolder, appView)
? new ConstraintWithTarget(Constraint.SAMENEST, targetHolder)
: NEVER;
}
- return targetHolder == contextHolder
- ? new ConstraintWithTarget(Constraint.SAMECLASS, targetHolder) : NEVER;
+ return targetHolder == context.type
+ ? new ConstraintWithTarget(Constraint.SAMECLASS, targetHolder)
+ : NEVER;
} else if (flags.isProtected()) {
- if (targetHolder.isSamePackage(contextHolder)) {
+ if (targetHolder.isSamePackage(context.type)) {
// Even though protected, this is visible via the same package from the context.
return new ConstraintWithTarget(Constraint.PACKAGE, targetHolder);
- } else if (appView.isSubtype(contextHolder, targetHolder).isTrue()) {
+ } else if (appView.isSubtype(context.type, targetHolder).isTrue()) {
return new ConstraintWithTarget(Constraint.SUBCLASS, targetHolder);
}
return NEVER;
} else {
/* package-private */
- return targetHolder.isSamePackage(contextHolder)
- ? new ConstraintWithTarget(Constraint.PACKAGE, targetHolder) : NEVER;
+ return targetHolder.isSamePackage(context.type)
+ ? new ConstraintWithTarget(Constraint.PACKAGE, targetHolder)
+ : NEVER;
}
}
public static ConstraintWithTarget classIsVisible(
- DexType context, DexType clazz, AppView<?> appView) {
+ DexProgramClass context, DexType clazz, AppView<?> appView) {
if (clazz.isArrayType()) {
return classIsVisible(context, clazz.toArrayElementType(appView.dexItemFactory()), appView);
}
@@ -966,8 +965,7 @@
// TODO(b/142116551): This should be equivalent to invoke.lookupSingleTarget()!
ProgramMethod singleTarget = oracle.lookupSingleTarget(invoke, context);
if (singleTarget == null) {
- WhyAreYouNotInliningReporter.handleInvokeWithUnknownTarget(
- invoke, appView, context.getDefinition());
+ WhyAreYouNotInliningReporter.handleInvokeWithUnknownTarget(invoke, appView, context);
continue;
}
@@ -975,8 +973,7 @@
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter =
oracle.isForcedInliningOracle()
? NopWhyAreYouNotInliningReporter.getInstance()
- : WhyAreYouNotInliningReporter.createFor(
- singleTargetMethod, appView, context.getDefinition());
+ : WhyAreYouNotInliningReporter.createFor(singleTarget, appView, context);
InlineAction action =
oracle.computeInlining(
invoke,
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 ea77caf..890a23e 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
@@ -90,16 +90,16 @@
}
public ConstraintWithTarget forDexItemBasedConstString(
- DexReference type, DexType invocationContext) {
+ DexReference type, DexProgramClass context) {
return ConstraintWithTarget.ALWAYS;
}
- public ConstraintWithTarget forCheckCast(DexType type, DexType invocationContext) {
- return ConstraintWithTarget.classIsVisible(invocationContext, type, appView);
+ public ConstraintWithTarget forCheckCast(DexType type, DexProgramClass context) {
+ return ConstraintWithTarget.classIsVisible(context, type, appView);
}
- public ConstraintWithTarget forConstClass(DexType type, DexType invocationContext) {
- return ConstraintWithTarget.classIsVisible(invocationContext, type, appView);
+ public ConstraintWithTarget forConstClass(DexType type, DexProgramClass context) {
+ return ConstraintWithTarget.classIsVisible(context, type, appView);
}
public ConstraintWithTarget forConstInstruction() {
@@ -126,42 +126,40 @@
return ConstraintWithTarget.ALWAYS;
}
- public ConstraintWithTarget forInitClass(DexType clazz, DexType context) {
+ public ConstraintWithTarget forInitClass(DexType clazz, DexProgramClass context) {
return ConstraintWithTarget.classIsVisible(context, clazz, appView);
}
- public ConstraintWithTarget forInstanceGet(DexField field, DexType invocationContext) {
+ public ConstraintWithTarget forInstanceGet(DexField field, DexProgramClass context) {
DexField lookup = graphLense.lookupField(field);
- return forFieldInstruction(
- lookup, appView.appInfo().lookupInstanceTarget(lookup.holder, lookup), invocationContext);
+ return forFieldInstruction(lookup, appView.appInfo().lookupInstanceTarget(lookup), context);
}
- public ConstraintWithTarget forInstanceOf(DexType type, DexType invocationContext) {
- return ConstraintWithTarget.classIsVisible(invocationContext, type, appView);
+ public ConstraintWithTarget forInstanceOf(DexType type, DexProgramClass context) {
+ return ConstraintWithTarget.classIsVisible(context, type, appView);
}
- public ConstraintWithTarget forInstancePut(DexField field, DexType invocationContext) {
+ public ConstraintWithTarget forInstancePut(DexField field, DexProgramClass context) {
DexField lookup = graphLense.lookupField(field);
- return forFieldInstruction(
- lookup, appView.appInfo().lookupInstanceTarget(lookup.holder, lookup), invocationContext);
+ return forFieldInstruction(lookup, appView.appInfo().lookupInstanceTarget(lookup), context);
}
- public ConstraintWithTarget forInvoke(DexMethod method, Type type, DexType invocationContext) {
+ public ConstraintWithTarget forInvoke(DexMethod method, Type type, DexProgramClass context) {
switch (type) {
case DIRECT:
- return forInvokeDirect(method, invocationContext);
+ return forInvokeDirect(method, context);
case INTERFACE:
- return forInvokeInterface(method, invocationContext);
+ return forInvokeInterface(method, context);
case STATIC:
- return forInvokeStatic(method, invocationContext);
+ return forInvokeStatic(method, context);
case SUPER:
- return forInvokeSuper(method, invocationContext);
+ return forInvokeSuper(method, context);
case VIRTUAL:
- return forInvokeVirtual(method, invocationContext);
+ return forInvokeVirtual(method, context);
case CUSTOM:
return forInvokeCustom();
case POLYMORPHIC:
- return forInvokePolymorphic(method, invocationContext);
+ return forInvokePolymorphic(method, context);
default:
throw new Unreachable("Unexpected type: " + type);
}
@@ -174,17 +172,13 @@
private DexEncodedMethod lookupWhileVerticalClassMerging(
DexMethod method,
- DexType invocationContext,
+ DexProgramClass context,
BiFunction<SingleResolutionResult, DexProgramClass, DexEncodedMethod> lookupFunction) {
SingleResolutionResult singleResolutionResult =
- appView.appInfo().resolveMethod(method.holder, method).asSingleResolution();
+ appView.appInfo().unsafeResolveMethodDueToDexFormat(method).asSingleResolution();
if (singleResolutionResult == null) {
return null;
}
- DexProgramClass context = appView.definitionForProgramType(invocationContext);
- if (context == null) {
- return null;
- }
DexEncodedMethod dexEncodedMethod = lookupFunction.apply(singleResolutionResult, context);
if (dexEncodedMethod != null) {
return dexEncodedMethod;
@@ -203,61 +197,55 @@
return null;
}
- public ConstraintWithTarget forInvokeDirect(DexMethod method, DexType invocationContext) {
+ public ConstraintWithTarget forInvokeDirect(DexMethod method, DexProgramClass context) {
DexMethod lookup = graphLense.lookupMethod(method);
DexEncodedMethod target =
isVerticalClassMerging()
? lookupWhileVerticalClassMerging(
lookup,
- invocationContext,
+ context,
(res, ctxt) -> res.lookupInvokeDirectTarget(ctxt, appView.appInfo()))
- : appView.appInfo().lookupDirectTarget(lookup, invocationContext);
- return forSingleTargetInvoke(lookup, target, invocationContext);
+ : appView.appInfo().lookupDirectTarget(lookup, context);
+ return forSingleTargetInvoke(lookup, target, context);
}
- public ConstraintWithTarget forInvokeInterface(DexMethod method, DexType invocationContext) {
+ public ConstraintWithTarget forInvokeInterface(DexMethod method, DexProgramClass context) {
DexMethod lookup = graphLense.lookupMethod(method);
- return forVirtualInvoke(
- lookup,
- invocationContext,
- true);
+ return forVirtualInvoke(lookup, context, true);
}
- public ConstraintWithTarget forInvokeMultiNewArray(DexType type, DexType invocationContext) {
- return ConstraintWithTarget.classIsVisible(invocationContext, type, appView);
+ public ConstraintWithTarget forInvokeMultiNewArray(DexType type, DexProgramClass context) {
+ return ConstraintWithTarget.classIsVisible(context, type, appView);
}
- public ConstraintWithTarget forInvokeNewArray(DexType type, DexType invocationContext) {
- return ConstraintWithTarget.classIsVisible(invocationContext, type, appView);
+ public ConstraintWithTarget forInvokeNewArray(DexType type, DexProgramClass context) {
+ return ConstraintWithTarget.classIsVisible(context, type, appView);
}
- public ConstraintWithTarget forInvokePolymorphic(DexMethod method, DexType invocationContext) {
+ public ConstraintWithTarget forInvokePolymorphic(DexMethod method, DexProgramClass context) {
return ConstraintWithTarget.NEVER;
}
- public ConstraintWithTarget forInvokeStatic(DexMethod method, DexType invocationContext) {
+ public ConstraintWithTarget forInvokeStatic(DexMethod method, DexProgramClass context) {
DexMethod lookup = graphLense.lookupMethod(method);
DexEncodedMethod target =
isVerticalClassMerging()
? lookupWhileVerticalClassMerging(
lookup,
- invocationContext,
+ context,
(res, ctxt) -> res.lookupInvokeStaticTarget(ctxt, appView.appInfo()))
- : appView.appInfo().lookupStaticTarget(lookup, invocationContext);
- return forSingleTargetInvoke(lookup, target, invocationContext);
+ : appView.appInfo().lookupStaticTarget(lookup, context);
+ return forSingleTargetInvoke(lookup, target, context);
}
- public ConstraintWithTarget forInvokeSuper(DexMethod method, DexType invocationContext) {
+ public ConstraintWithTarget forInvokeSuper(DexMethod method, DexProgramClass context) {
// The semantics of invoke super depend on the context.
- return new ConstraintWithTarget(Constraint.SAMECLASS, invocationContext);
+ return new ConstraintWithTarget(Constraint.SAMECLASS, context.type);
}
- public ConstraintWithTarget forInvokeVirtual(DexMethod method, DexType invocationContext) {
+ public ConstraintWithTarget forInvokeVirtual(DexMethod method, DexProgramClass context) {
DexMethod lookup = graphLense.lookupMethod(method);
- return forVirtualInvoke(
- lookup,
- invocationContext,
- false);
+ return forVirtualInvoke(lookup, context, false);
}
public ConstraintWithTarget forJumpInstruction() {
@@ -280,16 +268,16 @@
return ConstraintWithTarget.ALWAYS;
}
- public ConstraintWithTarget forNewArrayEmpty(DexType type, DexType invocationContext) {
- return ConstraintWithTarget.classIsVisible(invocationContext, type, appView);
+ public ConstraintWithTarget forNewArrayEmpty(DexType type, DexProgramClass context) {
+ return ConstraintWithTarget.classIsVisible(context, type, appView);
}
public ConstraintWithTarget forNewArrayFilledData() {
return ConstraintWithTarget.ALWAYS;
}
- public ConstraintWithTarget forNewInstance(DexType type, DexType invocationContext) {
- return ConstraintWithTarget.classIsVisible(invocationContext, type, appView);
+ public ConstraintWithTarget forNewInstance(DexType type, DexProgramClass context) {
+ return ConstraintWithTarget.classIsVisible(context, type, appView);
}
public ConstraintWithTarget forAssume() {
@@ -304,16 +292,14 @@
return ConstraintWithTarget.ALWAYS;
}
- public ConstraintWithTarget forStaticGet(DexField field, DexType invocationContext) {
+ public ConstraintWithTarget forStaticGet(DexField field, DexProgramClass context) {
DexField lookup = graphLense.lookupField(field);
- return forFieldInstruction(
- lookup, appView.appInfo().lookupStaticTarget(lookup.holder, lookup), invocationContext);
+ return forFieldInstruction(lookup, appView.appInfo().lookupStaticTarget(lookup), context);
}
- public ConstraintWithTarget forStaticPut(DexField field, DexType invocationContext) {
+ public ConstraintWithTarget forStaticPut(DexField field, DexProgramClass context) {
DexField lookup = graphLense.lookupField(field);
- return forFieldInstruction(
- lookup, appView.appInfo().lookupStaticTarget(lookup.holder, lookup), invocationContext);
+ return forFieldInstruction(lookup, appView.appInfo().lookupStaticTarget(lookup), context);
}
public ConstraintWithTarget forStore() {
@@ -341,17 +327,16 @@
}
private ConstraintWithTarget forFieldInstruction(
- DexField field, DexEncodedField target, DexType invocationContext) {
+ DexField field, DexEncodedField target, DexProgramClass context) {
// Resolve the field if possible and decide whether the instruction can inlined.
DexType fieldHolder = graphLense.lookupType(field.holder);
DexClass fieldClass = appView.definitionFor(fieldHolder);
if (target != null && fieldClass != null) {
ConstraintWithTarget fieldConstraintWithTarget =
- ConstraintWithTarget.deriveConstraint(
- invocationContext, fieldHolder, target.accessFlags, appView);
+ ConstraintWithTarget.deriveConstraint(context, fieldHolder, target.accessFlags, appView);
// If the field has not been member-rebound, then we also need to make sure that the
- // `invocationContext` has access to the definition of the field.
+ // `context` has access to the definition of the field.
//
// See, for example, InlineNonReboundFieldTest (b/128604123).
if (field.holder != target.holder()) {
@@ -360,13 +345,13 @@
ConstraintWithTarget.meet(
fieldConstraintWithTarget,
ConstraintWithTarget.deriveConstraint(
- invocationContext, actualFieldHolder, target.accessFlags, appView),
+ context, actualFieldHolder, target.accessFlags, appView),
appView);
}
ConstraintWithTarget classConstraintWithTarget =
ConstraintWithTarget.deriveConstraint(
- invocationContext, fieldHolder, fieldClass.accessFlags, appView);
+ context, fieldHolder, fieldClass.accessFlags, appView);
return ConstraintWithTarget.meet(
fieldConstraintWithTarget, classConstraintWithTarget, appView);
}
@@ -374,7 +359,7 @@
}
private ConstraintWithTarget forSingleTargetInvoke(
- DexMethod method, DexEncodedMethod target, DexType invocationContext) {
+ DexMethod method, DexEncodedMethod target, DexProgramClass context) {
if (method.holder.isArrayType()) {
return ConstraintWithTarget.ALWAYS;
}
@@ -389,11 +374,11 @@
ConstraintWithTarget methodConstraintWithTarget =
ConstraintWithTarget.deriveConstraint(
- invocationContext, methodHolder, target.accessFlags, appView);
+ context, methodHolder, target.accessFlags, appView);
// We also have to take the constraint of the enclosing class into account.
ConstraintWithTarget classConstraintWithTarget =
ConstraintWithTarget.deriveConstraint(
- invocationContext, methodHolder, methodClass.accessFlags, appView);
+ context, methodHolder, methodClass.accessFlags, appView);
return ConstraintWithTarget.meet(
methodConstraintWithTarget, classConstraintWithTarget, appView);
}
@@ -402,17 +387,14 @@
}
private ConstraintWithTarget forVirtualInvoke(
- DexMethod method,
- DexType invocationContext,
- boolean isInterface) {
+ DexMethod method, DexProgramClass context, boolean isInterface) {
if (method.holder.isArrayType()) {
return ConstraintWithTarget.ALWAYS;
}
// Perform resolution and derive inlining constraints based on the accessibility of the
// resolution result.
- ResolutionResult resolutionResult =
- appView.appInfo().resolveMethod(method.holder, method, isInterface);
+ ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method, isInterface);
if (!resolutionResult.isVirtualTarget()) {
return ConstraintWithTarget.NEVER;
}
@@ -428,7 +410,7 @@
assert methodClass != null;
ConstraintWithTarget methodConstraintWithTarget =
ConstraintWithTarget.deriveConstraint(
- invocationContext, methodHolder, resolutionTarget.accessFlags, appView);
+ context, methodHolder, resolutionTarget.accessFlags, appView);
// We also have to take the constraint of the enclosing class of the resolution result
// into account. We do not allow inlining this method if it is calling something that
// is inaccessible. Inlining in that case could move the code to another package making a
@@ -436,7 +418,7 @@
// we have to make sure that inlining cannot make it inaccessible.
ConstraintWithTarget classConstraintWithTarget =
ConstraintWithTarget.deriveConstraint(
- invocationContext, methodHolder, methodClass.accessFlags, appView);
+ context, methodHolder, methodClass.accessFlags, appView);
return ConstraintWithTarget.meet(
methodConstraintWithTarget, classConstraintWithTarget, appView);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
index 458f4b1..8222958 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
@@ -146,7 +146,7 @@
DexField field = returnValueRule.getField();
assert instruction.getOutType() == TypeElement.fromDexType(field.type, maybeNull(), appView);
- DexEncodedField staticField = appView.appInfo().lookupStaticTarget(field.holder, field);
+ DexEncodedField staticField = appView.appInfo().lookupStaticTarget(field);
if (staticField == null) {
if (warnedFields.add(field)) {
reporter.warning(
@@ -212,7 +212,7 @@
if (current.isStaticGet()) {
StaticGet staticGet = current.asStaticGet();
replaceInstructionByInitClassIfPossible(
- staticGet, staticGet.getField().holder, code, iterator, code.method().holder());
+ staticGet, staticGet.getField().holder, code, iterator, code.context());
}
replacement.setPosition(position);
if (block.hasCatchHandlers()) {
@@ -236,7 +236,7 @@
if (!invokedHolder.isClassType()) {
return;
}
- DexEncodedMethod target = current.lookupSingleTarget(appView, context.getHolderType());
+ DexEncodedMethod target = current.lookupSingleTarget(appView, context);
if (target != null && target.isInstanceInitializer()) {
// Member value propagation does not apply to constructors. Removing a call to a constructor
// that is marked as having no side effects could lead to verification errors, due to
@@ -250,7 +250,7 @@
// references that have actual definitions are marked by the root set builder. So, here, we
// try again with a resolved target, not the direct definition, which may not exist.
DexEncodedMethod resolutionTarget =
- appView.appInfo().resolveMethod(invokedHolder, invokedMethod).getSingleTarget();
+ appView.appInfo().unsafeResolveMethodDueToDexFormat(invokedMethod).getSingleTarget();
lookup = lookupMemberRule(resolutionTarget);
}
boolean invokeReplaced = false;
@@ -303,10 +303,10 @@
current.setOutValue(null);
if (current.isInvokeMethodWithReceiver()) {
- replaceInstructionByNullCheckIfPossible(current, iterator, context.getHolderType());
+ replaceInstructionByNullCheckIfPossible(current, iterator, context);
} else if (current.isInvokeStatic()) {
replaceInstructionByInitClassIfPossible(
- current, target.holder(), code, iterator, context.getHolderType());
+ current, target.holder(), code, iterator, context);
}
// Insert the definition of the replacement.
@@ -330,7 +330,7 @@
DexField field = current.getField();
// TODO(b/123857022): Should be able to use definitionFor().
- DexEncodedField target = appView.appInfo().resolveField(field);
+ DexEncodedField target = appView.appInfo().resolveField(field).getResolvedField();
if (target == null) {
boolean replaceCurrentInstructionWithConstNull =
appView.withGeneratedExtensionRegistryShrinker(
@@ -367,7 +367,7 @@
abstractValue = target.getOptimizationInfo().getAbstractValue();
if (abstractValue.isUnknown() && !target.isStatic()) {
AbstractValue abstractReceiverValue =
- current.asInstanceGet().object().getAbstractValue(appView, code.method().holder());
+ current.asInstanceGet().object().getAbstractValue(appView, code.context());
if (abstractReceiverValue.isSingleFieldValue()) {
abstractValue =
abstractReceiverValue.asSingleFieldValue().getState().getAbstractFieldValue(target);
@@ -393,7 +393,7 @@
}
if (singleValue.isMaterializableInContext(appView, code.context())) {
BasicBlock block = current.getBlock();
- DexType context = code.method().holder();
+ ProgramMethod context = code.context();
Position position = current.getPosition();
// All usages are replaced by the replacement value.
@@ -425,7 +425,7 @@
}
private void replaceInstructionByNullCheckIfPossible(
- Instruction instruction, InstructionListIterator iterator, DexType context) {
+ Instruction instruction, InstructionListIterator iterator, ProgramMethod context) {
assert instruction.isInstanceFieldInstruction() || instruction.isInvokeMethodWithReceiver();
assert !instruction.hasOutValue() || !instruction.outValue().hasAnyUsers();
if (instruction.instructionMayHaveSideEffects(
@@ -456,7 +456,7 @@
DexType holder,
IRCode code,
InstructionListIterator iterator,
- DexType context) {
+ ProgramMethod context) {
assert instruction.isStaticFieldInstruction() || instruction.isInvokeStatic();
if (instruction.instructionMayHaveSideEffects(
appView, context, Instruction.SideEffectAssumption.CLASS_ALREADY_INITIALIZED)) {
@@ -467,7 +467,7 @@
appView,
// Types that are a super type of `context` are guaranteed to be initialized
// already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appView.appInfo().isSubtype(context.getHolderType(), type),
Sets.newIdentityHashSet());
if (!classInitializationMayHaveSideEffects) {
iterator.removeOrReplaceByDebugLocalRead();
@@ -485,7 +485,7 @@
private void replaceInstancePutByNullCheckIfNeverRead(
IRCode code, InstructionListIterator iterator, InstancePut current) {
- DexEncodedField target = appView.appInfo().resolveField(current.getField());
+ DexEncodedField target = appView.appInfo().resolveField(current.getField()).getResolvedField();
if (target == null || appView.appInfo().isFieldRead(target)) {
return;
}
@@ -494,12 +494,12 @@
return;
}
- replaceInstructionByNullCheckIfPossible(current, iterator, code.method().holder());
+ replaceInstructionByNullCheckIfPossible(current, iterator, code.context());
}
private void replaceStaticPutByInitClassIfNeverRead(
IRCode code, InstructionListIterator iterator, StaticPut current) {
- DexEncodedField field = appView.appInfo().resolveField(current.getField());
+ DexEncodedField field = appView.appInfo().resolveField(current.getField()).getResolvedField();
if (field == null || appView.appInfo().isFieldRead(field)) {
return;
}
@@ -509,7 +509,7 @@
}
replaceInstructionByInitClassIfPossible(
- current, field.holder(), code, iterator, code.method().holder());
+ current, field.holder(), code, iterator, code.context());
}
/**
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java b/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
index 662eb39..406c09c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
@@ -5,11 +5,11 @@
import static com.android.tools.r8.ir.code.DominatorTree.Assumption.MAY_HAVE_UNREACHABLE_BLOCKS;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
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.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -43,17 +43,17 @@
public class NonNullTracker implements Assumer {
- private final AppView<?> appView;
- private final DexItemFactory dexItemFactory;
+ private final AppView<? extends AppInfoWithClassHierarchy> appView;
private final Consumer<BasicBlock> splitBlockConsumer;
- public NonNullTracker(AppView<?> appView) {
+ public NonNullTracker(AppView<? extends AppInfoWithClassHierarchy> appView) {
this(appView, null);
}
- public NonNullTracker(AppView<?> appView, Consumer<BasicBlock> splitBlockConsumer) {
+ public NonNullTracker(
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ Consumer<BasicBlock> splitBlockConsumer) {
this.appView = appView;
- this.dexItemFactory = appView.dexItemFactory();
this.splitBlockConsumer = splitBlockConsumer;
}
@@ -89,8 +89,7 @@
InvokeMethod invoke = current.asInvokeMethod();
DexMethod invokedMethod = invoke.getInvokedMethod();
- DexEncodedMethod singleTarget =
- invoke.lookupSingleTarget(appView, code.method().holder());
+ DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, code.context());
if (singleTarget != null) {
MethodOptimizationInfo optimizationInfo = singleTarget.getOptimizationInfo();
@@ -119,7 +118,7 @@
FieldInstruction fieldInstruction = current.asFieldInstruction();
DexField field = fieldInstruction.getField();
if (field.type.isReferenceType() && isNullableReferenceTypeWithUsers(outValue)) {
- DexEncodedField encodedField = appView.appInfo().resolveField(field);
+ DexEncodedField encodedField = appView.appInfo().resolveField(field).getResolvedField();
if (encodedField != null) {
FieldOptimizationInfo optimizationInfo = encodedField.getOptimizationInfo();
if (optimizationInfo.getDynamicUpperBoundType() != null
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 2b9456a..5c4197c 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
@@ -66,10 +66,14 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.ProgramMethodEquivalence;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
import com.android.tools.r8.utils.collections.LongLivedProgramMethodSetBuilder;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
+import com.google.common.base.Equivalence.Wrapper;
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -108,7 +112,7 @@
public class Outliner {
/** Result of first step (see {@link Outliner#createOutlineMethodIdentifierGenerator()}. */
- private final List<List<ProgramMethod>> candidateMethodLists = new ArrayList<>();
+ private final List<Multiset<Wrapper<ProgramMethod>>> candidateMethodLists = new ArrayList<>();
/** Result of second step (see {@link Outliner#selectMethodsForOutlining()}. */
private final LongLivedProgramMethodSetBuilder methodsSelectedForOutlining =
new LongLivedProgramMethodSetBuilder();
@@ -863,8 +867,7 @@
// See whether we could move this invoke somewhere else. We reuse the logic from inlining
// here, as the constraints are the same.
- ConstraintWithTarget constraint =
- invoke.inliningConstraint(inliningConstraints, method.getHolderType());
+ ConstraintWithTarget constraint = invoke.inliningConstraint(inliningConstraints, method);
if (constraint != ConstraintWithTarget.ALWAYS) {
return false;
}
@@ -1135,10 +1138,12 @@
// TODO(sgjesse): This does not take several usages in the same method into account.
private class OutlineMethodIdentifier extends OutlineSpotter {
- private final Map<Outline, List<ProgramMethod>> candidateMap;
+ private final Map<Outline, Multiset<Wrapper<ProgramMethod>>> candidateMap;
OutlineMethodIdentifier(
- ProgramMethod method, BasicBlock block, Map<Outline, List<ProgramMethod>> candidateMap) {
+ ProgramMethod method,
+ BasicBlock block,
+ Map<Outline, Multiset<Wrapper<ProgramMethod>>> candidateMap) {
super(method, block);
this.candidateMap = candidateMap;
}
@@ -1146,12 +1151,14 @@
@Override
protected void handle(int start, int end, Outline outline) {
synchronized (candidateMap) {
- candidateMap.computeIfAbsent(outline, this::addOutlineMethodList).add(method);
+ candidateMap
+ .computeIfAbsent(outline, this::addOutlineMethodList)
+ .add(ProgramMethodEquivalence.get().wrap(method));
}
}
- private List<ProgramMethod> addOutlineMethodList(Outline outline) {
- List<ProgramMethod> result = new ArrayList<>();
+ private Multiset<Wrapper<ProgramMethod>> addOutlineMethodList(Outline outline) {
+ Multiset<Wrapper<ProgramMethod>> result = HashMultiset.create();
candidateMethodLists.add(result);
return result;
}
@@ -1277,7 +1284,7 @@
// out-value of invokes to null), this map must not be used except for identifying methods
// potentially relevant to outlining. OutlineMethodIdentifier will add method lists to
// candidateMethodLists whenever it adds an entry to candidateMap.
- Map<Outline, List<ProgramMethod>> candidateMap = new HashMap<>();
+ Map<Outline, Multiset<Wrapper<ProgramMethod>>> candidateMap = new HashMap<>();
assert candidateMethodLists.isEmpty();
assert outlineMethodIdentifierGenerator == null;
outlineMethodIdentifierGenerator =
@@ -1311,9 +1318,9 @@
public boolean selectMethodsForOutlining() {
assert methodsSelectedForOutlining.isEmpty();
assert outlineSites.isEmpty();
- for (List<ProgramMethod> outlineMethods : candidateMethodLists) {
+ for (Multiset<Wrapper<ProgramMethod>> outlineMethods : candidateMethodLists) {
if (outlineMethods.size() >= appView.options().outline.threshold) {
- methodsSelectedForOutlining.addAll(outlineMethods);
+ outlineMethods.forEach(wrapper -> methodsSelectedForOutlining.add(wrapper.get()));
}
}
candidateMethodLists.clear();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
index 1ba460e..ef81097 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
@@ -152,7 +152,7 @@
private DexEncodedField resolveField(DexField field) {
if (appView.enableWholeProgramOptimizations()) {
- return appView.appInfo().resolveField(field);
+ return appView.appInfo().withLiveness().resolveField(field).getResolvedField();
}
if (field.holder == method.getHolderType()) {
return appView.definitionFor(field);
@@ -161,7 +161,6 @@
}
public void run() {
- DexType context = method.getHolderType();
Reference2IntMap<BasicBlock> pendingNormalSuccessors = new Reference2IntOpenHashMap<>();
for (BasicBlock block : code.blocks) {
if (!block.hasUniqueNormalSuccessor()) {
@@ -274,14 +273,14 @@
appView,
// Types that are a super type of `context` are guaranteed to be initialized
// already.
- type -> appView.isSubtype(context, type).isTrue(),
+ type -> appView.isSubtype(method.getHolderType(), type).isTrue(),
Sets.newIdentityHashSet())) {
killAllNonFinalActiveFields();
}
} else {
// If the current instruction could trigger a method invocation, it could also cause
// field values to change. In that case, it must be handled above.
- assert !instruction.instructionMayTriggerMethodInvocation(appView, context);
+ assert !instruction.instructionMayTriggerMethodInvocation(appView, method);
// If this assertion fails for a new instruction we need to determine if that
// instruction has side-effects that can change the value of fields. If so, it must be
@@ -348,7 +347,7 @@
return;
}
- DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, method.getHolderType());
+ DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, method);
if (singleTarget == null || !singleTarget.isInstanceInitializer()) {
killAllNonFinalActiveFields();
return;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
index 1f410ef..fd270a4 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -39,7 +40,7 @@
return;
}
Set<Value> affectedValues = Sets.newIdentityHashSet();
- DexType context = code.method().holder();
+ ProgramMethod context = code.context();
ClassInitializationAnalysis classInitializationAnalysis =
new ClassInitializationAnalysis(appView, code);
for (BasicBlock block : code.blocks) {
@@ -84,9 +85,7 @@
}
private static DexType getTypeForGetClass(
- AppView<AppInfoWithLiveness> appView,
- DexType context,
- InvokeVirtual invoke) {
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context, InvokeVirtual invoke) {
DexItemFactory dexItemFactory = appView.dexItemFactory();
DexMethod invokedMethod = invoke.getInvokedMethod();
// Class<?> Object#getClass() is final and cannot be overridden.
@@ -126,7 +125,7 @@
}
// Make sure the target (base) type is visible.
ConstraintWithTarget constraints =
- ConstraintWithTarget.classIsVisible(context, baseType, appView);
+ ConstraintWithTarget.classIsVisible(context.getHolder(), baseType, appView);
if (constraints == ConstraintWithTarget.NEVER) {
return null;
}
@@ -136,7 +135,7 @@
private static DexType getTypeForClassForName(
AppView<AppInfoWithLiveness> appView,
ClassInitializationAnalysis classInitializationAnalysis,
- DexType context,
+ ProgramMethod context,
InvokeStatic invoke) {
DexItemFactory dexItemFactory = appView.dexItemFactory();
DexMethod invokedMethod = invoke.getInvokedMethod();
@@ -203,7 +202,7 @@
}
// Make sure the (base) type is visible.
ConstraintWithTarget constraints =
- ConstraintWithTarget.classIsVisible(context, baseType, appView);
+ ConstraintWithTarget.classIsVisible(context.getHolder(), baseType, appView);
if (constraints == ConstraintWithTarget.NEVER) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
index 055f575..32bea32 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense.NestedGraphLense;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.RewrittenPrototypeDescription;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.ArgumentInfoCollection;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.RemovedArgumentInfo;
@@ -351,8 +352,7 @@
Instruction instruction = instructionIterator.next();
if (instruction.throwsOnNullInput()) {
Value couldBeNullValue = instruction.getNonNullInput();
- if (isThrowNullCandidate(
- couldBeNullValue, instruction, appView, code.method().holder())) {
+ if (isThrowNullCandidate(couldBeNullValue, instruction, appView, code.context())) {
if (instruction.isInstanceGet() || instruction.isInstancePut()) {
++numberOfInstanceGetOrInstancePutWithNullReceiver;
} else if (instruction.isInvokeMethodWithReceiver()) {
@@ -405,7 +405,7 @@
Value couldBeNullValue,
Instruction current,
AppView<? extends AppInfoWithClassHierarchy> appView,
- DexType context) {
+ ProgramMethod context) {
if (!couldBeNullValue.isAlwaysNull(appView)) {
return false;
}
@@ -451,12 +451,12 @@
IRCode code,
AssumeDynamicTypeRemover assumeDynamicTypeRemover,
Set<Value> affectedValues) {
- DexType context = code.method().holder();
+ ProgramMethod context = code.context();
DexField field = instruction.getField();
DexType fieldType = field.type;
if (fieldType.isAlwaysNull(appView)) {
// TODO(b/123857022): Should be possible to use definitionFor().
- DexEncodedField encodedField = appView.appInfo().resolveField(field);
+ DexEncodedField encodedField = appView.appInfo().resolveField(field).getResolvedField();
if (encodedField == null) {
return;
}
@@ -507,7 +507,7 @@
AssumeDynamicTypeRemover assumeDynamicTypeRemover,
Set<BasicBlock> blocksToBeRemoved,
Set<Value> affectedValues) {
- DexEncodedMethod target = invoke.lookupSingleTarget(appView, code.method().holder());
+ DexEncodedMethod target = invoke.lookupSingleTarget(appView, code.context());
if (target == null) {
return;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
index 59e9a94..9318acb 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
@@ -172,10 +172,10 @@
assert root.isStaticGet();
StaticGet staticGet = root.asStaticGet();
- if (staticGet.instructionMayHaveSideEffects(appView, method.getHolderType())) {
+ if (staticGet.instructionMayHaveSideEffects(appView, method)) {
return EligibilityStatus.RETRIEVAL_MAY_HAVE_SIDE_EFFECTS;
}
- DexEncodedField field = appView.appInfo().resolveField(staticGet.getField());
+ DexEncodedField field = appView.appInfo().resolveField(staticGet.getField()).getResolvedField();
FieldOptimizationInfo optimizationInfo = field.getOptimizationInfo();
ClassTypeElement dynamicLowerBoundType = optimizationInfo.getDynamicLowerBoundType();
if (dynamicLowerBoundType == null
@@ -221,7 +221,14 @@
while (!currentUsers.isEmpty()) {
Set<Instruction> indirectUsers = Sets.newIdentityHashSet();
for (Instruction user : currentUsers) {
- if (user.isAssume()) {
+ if (user.isAssume() || user.isCheckCast()) {
+ if (user.isCheckCast()) {
+ boolean isCheckCastUnsafe =
+ !appView.appInfo().isSubtype(eligibleClass.type, user.asCheckCast().getType());
+ if (isCheckCastUnsafe) {
+ return user; // Not eligible.
+ }
+ }
Value alias = user.outValue();
if (receivers.isReceiverAlias(alias)) {
continue; // Already processed.
@@ -242,7 +249,10 @@
return user; // Not eligible.
}
DexEncodedField field =
- appView.appInfo().resolveField(user.asFieldInstruction().getField());
+ appView
+ .appInfo()
+ .resolveField(user.asFieldInstruction().getField())
+ .getResolvedField();
if (field == null || field.isStatic()) {
return user; // Not eligible.
}
@@ -258,7 +268,10 @@
return user; // Not eligible.
}
DexEncodedField field =
- appView.appInfo().resolveField(user.asFieldInstruction().getField());
+ appView
+ .appInfo()
+ .resolveField(user.asFieldInstruction().getField())
+ .getResolvedField();
if (field == null || field.isStatic()) {
return user; // Not eligible.
}
@@ -267,8 +280,7 @@
if (user.isInvokeMethod()) {
InvokeMethod invokeMethod = user.asInvokeMethod();
- DexEncodedMethod singleTargetMethod =
- invokeMethod.lookupSingleTarget(appView, method.getHolderType());
+ DexEncodedMethod singleTargetMethod = invokeMethod.lookupSingleTarget(appView, method);
if (singleTargetMethod == null) {
return user; // Not eligible.
}
@@ -513,7 +525,8 @@
continue;
}
- ProgramMethod singleTarget = invoke.lookupSingleProgramTarget(appView, method);
+ ProgramMethod singleTarget =
+ invoke.lookupSingleProgramTarget(appView, method, eligibleInstance);
if (singleTarget == null || !indirectMethodCallsOnInstance.contains(singleTarget)) {
throw new IllegalClassInlinerStateException();
}
@@ -574,7 +587,7 @@
continue;
}
- DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, method.getHolderType());
+ DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, method);
if (singleTarget != null) {
Predicate<InvokeMethod> noSideEffectsPredicate =
dexItemFactory.libraryMethodsWithoutSideEffects.getOrDefault(
@@ -701,7 +714,10 @@
}
InstancePut instancePut = user.asInstancePut();
DexEncodedField field =
- appView.appInfo().resolveFieldOn(eligibleClass, instancePut.getField());
+ appView
+ .appInfo()
+ .resolveFieldOn(eligibleClass, instancePut.getField())
+ .getResolvedField();
if (field == null) {
throw new Unreachable(
"Unexpected field write left in method `"
@@ -880,8 +896,8 @@
invoke,
invoke.getInvokedMethod(),
singleTarget,
- eligibility ->
- isEligibleInvokeWithAllUsersAsReceivers(eligibility, invoke, indirectUsers))) {
+ eligibility -> isEligibleInvokeWithAllUsersAsReceivers(eligibility, invoke, indirectUsers),
+ invoke.getType())) {
return null;
}
@@ -892,15 +908,18 @@
}
if (!eligibility.callsReceiver.isEmpty()) {
assert eligibility.callsReceiver.get(0).getFirst() == Invoke.Type.VIRTUAL;
- DexMethod indirectlyInvokedMethod = eligibility.callsReceiver.get(0).getSecond();
+ Pair<Type, DexMethod> invokeInfo = eligibility.callsReceiver.get(0);
+ Type invokeType = invokeInfo.getFirst();
+ DexMethod indirectlyInvokedMethod = invokeInfo.getSecond();
ResolutionResult resolutionResult =
- appView.appInfo().resolveMethod(eligibleClass, indirectlyInvokedMethod);
+ appView.appInfo().resolveMethodOn(eligibleClass, indirectlyInvokedMethod);
if (!resolutionResult.isSingleResolution()) {
return null;
}
ProgramMethod indirectSingleTarget =
resolutionResult.asSingleResolution().getResolutionPair().asProgramMethod();
- if (!isEligibleIndirectVirtualMethodCall(indirectlyInvokedMethod, indirectSingleTarget)) {
+ if (!isEligibleIndirectVirtualMethodCall(
+ indirectlyInvokedMethod, invokeType, indirectSingleTarget)) {
return null;
}
indirectMethodCallsOnInstance.add(indirectSingleTarget);
@@ -909,16 +928,16 @@
return new InliningInfo(singleTarget, eligibleClass.type);
}
- private boolean isEligibleIndirectVirtualMethodCall(DexMethod invokedMethod) {
+ private boolean isEligibleIndirectVirtualMethodCall(DexMethod invokedMethod, Type type) {
ProgramMethod singleTarget =
asProgramMethodOrNull(
- appView.appInfo().resolveMethod(eligibleClass, invokedMethod).getSingleTarget(),
+ appView.appInfo().resolveMethodOn(eligibleClass, invokedMethod).getSingleTarget(),
appView);
- return isEligibleIndirectVirtualMethodCall(invokedMethod, singleTarget);
+ return isEligibleIndirectVirtualMethodCall(invokedMethod, type, singleTarget);
}
private boolean isEligibleIndirectVirtualMethodCall(
- DexMethod invokedMethod, ProgramMethod singleTarget) {
+ DexMethod invokedMethod, Type type, ProgramMethod singleTarget) {
if (!isEligibleSingleTarget(singleTarget)) {
return false;
}
@@ -929,21 +948,23 @@
null,
invokedMethod,
singleTarget,
- eligibility ->
- eligibility.callsReceiver.isEmpty() && eligibility.returnsReceiver.isFalse());
+ eligibility -> eligibility.callsReceiver.isEmpty() && eligibility.returnsReceiver.isFalse(),
+ type);
}
private boolean isEligibleVirtualMethodCall(
InvokeMethodWithReceiver invoke,
DexMethod callee,
ProgramMethod singleTarget,
- Predicate<ClassInlinerEligibilityInfo> eligibilityAcceptanceCheck) {
+ Predicate<ClassInlinerEligibilityInfo> eligibilityAcceptanceCheck,
+ Type type) {
assert isEligibleSingleTarget(singleTarget);
// We should not inline a method if the invocation has type interface or virtual and the
// signature of the invocation resolves to a private or static method.
// TODO(b/147212189): Why not inline private methods? If access is permitted it is valid.
- ResolutionResult resolutionResult = appView.appInfo().resolveMethod(callee.holder, callee);
+ ResolutionResult resolutionResult =
+ appView.appInfo().resolveMethod(callee, type == Type.INTERFACE);
if (resolutionResult.isSingleResolution()
&& !resolutionResult.getSingleTarget().isNonPrivateVirtualMethod()) {
return false;
@@ -1152,7 +1173,7 @@
if (type == Type.VIRTUAL || type == Type.INTERFACE) {
// Is the method called indirectly still eligible?
- if (!isEligibleIndirectVirtualMethodCall(target)) {
+ if (!isEligibleIndirectVirtualMethodCall(target, type)) {
return false;
}
} else if (type == Type.DIRECT) {
@@ -1166,7 +1187,7 @@
}
// Check if the method is inline-able by standard inliner.
- DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, method.getHolderType());
+ DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, method);
if (singleTarget == null) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index 06c2894..b601000 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -394,7 +394,7 @@
return Reason.INVALID_INVOKE_ON_ARRAY;
}
DexEncodedMethod encodedSingleTarget =
- invokeMethod.lookupSingleTarget(appView, code.method().holder());
+ invokeMethod.lookupSingleTarget(appView, code.context());
if (encodedSingleTarget == null) {
return Reason.INVALID_INVOKE;
}
@@ -459,7 +459,8 @@
// have identical enum type.
if (instruction.isFieldPut()) {
FieldInstruction fieldInstruction = instruction.asFieldInstruction();
- DexEncodedField field = appView.appInfo().resolveField(fieldInstruction.getField());
+ DexEncodedField field =
+ appView.appInfo().resolveField(fieldInstruction.getField()).getResolvedField();
if (field == null) {
return Reason.INVALID_FIELD_PUT;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
index 97d0029..1d6668c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
@@ -114,7 +114,7 @@
DexEncodedMethod singleTarget =
appView
.appInfo()
- .resolveMethodOnClass(valueInfo.type, factory.objectMembers.toString)
+ .resolveMethodOnClass(factory.objectMembers.toString, valueInfo.type)
.getSingleTarget();
if (singleTarget != null && singleTarget.method != factory.enumMethods.toString) {
continue;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java
index f4d341b..86d107a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java
@@ -6,15 +6,16 @@
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import java.util.List;
@@ -153,12 +154,10 @@
}
public static CallSiteOptimizationInfo fromArguments(
- AppView<? extends AppInfoWithClassHierarchy> appView,
- DexEncodedMethod method,
- List<Value> inValues) {
+ AppView<AppInfoWithLiveness> appView, ProgramMethod target, List<Value> inValues) {
boolean allowConstantPropagation = appView.options().enablePropagationOfConstantsAtCallSites;
ConcreteCallSiteOptimizationInfo newCallSiteInfo =
- new ConcreteCallSiteOptimizationInfo(method, allowConstantPropagation);
+ new ConcreteCallSiteOptimizationInfo(target.getDefinition(), allowConstantPropagation);
assert newCallSiteInfo.size == inValues.size();
assert newCallSiteInfo.dynamicUpperBoundTypes != null;
for (int i = 0; i < newCallSiteInfo.size; i++) {
@@ -167,8 +166,7 @@
assert newCallSiteInfo.constants != null;
Value aliasedValue = arg.getAliasedValue();
if (!aliasedValue.isPhi()) {
- AbstractValue abstractValue =
- aliasedValue.definition.getAbstractValue(appView, method.holder());
+ AbstractValue abstractValue = aliasedValue.definition.getAbstractValue(appView, target);
if (abstractValue.isNonTrivial()) {
newCallSiteInfo.constants.put(i, abstractValue);
}
@@ -181,7 +179,7 @@
assert arg.getType().isReferenceType();
newCallSiteInfo.dynamicUpperBoundTypes.put(i, arg.getDynamicUpperBoundType(appView));
}
- if (newCallSiteInfo.hasUsefulOptimizationInfo(appView, method)) {
+ if (newCallSiteInfo.hasUsefulOptimizationInfo(appView, target.getDefinition())) {
return newCallSiteInfo;
}
// As soon as we know the current call site does not have any useful optimization info,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
index 23b74b1..8bb40e0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
@@ -44,13 +44,14 @@
import static com.android.tools.r8.ir.code.Opcodes.XOR;
import com.android.tools.r8.graph.AppView;
-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.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.DeterminismAnalysis;
@@ -128,9 +129,9 @@
InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos,
Timing timing) {
identifyBridgeInfo(method, code, feedback, timing);
- identifyClassInlinerEligibility(method, code, feedback, timing);
+ identifyClassInlinerEligibility(code, feedback, timing);
identifyParameterUsages(method, code, feedback, timing);
- identifyReturnsArgument(method, code, feedback, timing);
+ identifyReturnsArgument(code, feedback, timing);
if (options.enableInlining) {
identifyInvokeSemanticsForInlining(method, code, feedback, timing);
}
@@ -152,14 +153,13 @@
}
private void identifyClassInlinerEligibility(
- DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
+ IRCode code, OptimizationFeedback feedback, Timing timing) {
timing.begin("Identify class inliner eligibility");
- identifyClassInlinerEligibility(method, code, feedback);
+ identifyClassInlinerEligibility(code, feedback);
timing.end();
}
- private void identifyClassInlinerEligibility(
- DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
+ private void identifyClassInlinerEligibility(IRCode code, OptimizationFeedback feedback) {
// Method eligibility is calculated in similar way for regular method
// and for the constructor. To be eligible method should only be using its
// receiver in the following ways:
@@ -173,24 +173,21 @@
//
// Note that (4) can safely be removed as the receiver is guaranteed not to escape when we class
// inline it, and hence any monitor instructions are no-ops.
- boolean instanceInitializer = method.isInstanceInitializer();
- if (method.accessFlags.isNative()
- || (!method.isNonAbstractVirtualMethod() && !instanceInitializer)) {
+ ProgramMethod context = code.context();
+ DexEncodedMethod definition = context.getDefinition();
+ boolean instanceInitializer = definition.isInstanceInitializer();
+ if (definition.isNative()
+ || (!definition.isNonAbstractVirtualMethod() && !instanceInitializer)) {
return;
}
- feedback.setClassInlinerEligibility(method, null); // To allow returns below.
+ feedback.setClassInlinerEligibility(definition, null); // To allow returns below.
Value receiver = code.getThis();
if (receiver.numberOfPhiUsers() > 0) {
return;
}
- DexClass clazz = appView.definitionFor(method.holder());
- if (clazz == null) {
- return;
- }
-
List<Pair<Invoke.Type, DexMethod>> callsReceiver = new ArrayList<>();
boolean seenSuperInitCall = false;
boolean seenMonitor = false;
@@ -224,11 +221,10 @@
}
}
DexField field = insn.asFieldInstruction().getField();
- if (appView.appInfo().resolveFieldOn(clazz, field) != null) {
- // Require only accessing direct or indirect instance fields of the current class.
- break;
+ if (appView.appInfo().resolveField(field).isFailedOrUnknownResolution()) {
+ return;
}
- return;
+ break;
}
case INVOKE_DIRECT:
@@ -236,7 +232,7 @@
InvokeDirect invoke = insn.asInvokeDirect();
DexMethod invokedMethod = invoke.getInvokedMethod();
if (dexItemFactory.isConstructor(invokedMethod)
- && invokedMethod.holder == clazz.superType
+ && invokedMethod.holder == context.getHolder().superType
&& ListUtils.lastIndexMatching(invoke.arguments(), isReceiverAlias) == 0
&& !seenSuperInitCall
&& instanceInitializer) {
@@ -250,7 +246,7 @@
case INVOKE_STATIC:
{
InvokeStatic invoke = insn.asInvokeStatic();
- DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, method.holder());
+ DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, context);
if (singleTarget == null) {
return; // Not allowed.
}
@@ -271,7 +267,7 @@
DexMethod invokedMethod = invoke.getInvokedMethod();
DexType returnType = invokedMethod.proto.returnType;
if (returnType.isClassType()
- && appView.appInfo().inSameHierarchy(returnType, method.holder())) {
+ && appView.appInfo().inSameHierarchy(returnType, context.getHolderType())) {
return; // Not allowed, could introduce an alias of the receiver.
}
callsReceiver.add(new Pair<>(Invoke.Type.VIRTUAL, invokedMethod));
@@ -289,13 +285,13 @@
return;
}
- boolean synchronizedVirtualMethod = method.isSynchronized() && method.isVirtualMethod();
+ boolean synchronizedVirtualMethod = definition.isSynchronized() && definition.isVirtualMethod();
feedback.setClassInlinerEligibility(
- method,
+ definition,
new ClassInlinerEligibilityInfo(
callsReceiver,
- new ClassInlinerReceiverAnalysis(appView, method, code).computeReturnsReceiver(),
+ new ClassInlinerReceiverAnalysis(appView, definition, code).computeReturnsReceiver(),
seenMonitor || synchronizedVirtualMethod));
}
@@ -345,15 +341,15 @@
return builder.build();
}
- private void identifyReturnsArgument(
- DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
+ private void identifyReturnsArgument(IRCode code, OptimizationFeedback feedback, Timing timing) {
timing.begin("Identify returns argument");
- identifyReturnsArgument(method, code, feedback);
+ identifyReturnsArgument(code, feedback);
timing.end();
}
- private void identifyReturnsArgument(
- DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
+ private void identifyReturnsArgument(IRCode code, OptimizationFeedback feedback) {
+ ProgramMethod context = code.context();
+ DexEncodedMethod method = context.getDefinition();
List<BasicBlock> normalExits = code.computeNormalExitBlocks();
if (normalExits.isEmpty()) {
feedback.methodNeverReturnsNormally(method);
@@ -380,7 +376,6 @@
if (definition.isArgument()) {
feedback.methodReturnsArgument(method, definition.asArgument().getIndex());
}
- DexType context = method.holder();
AbstractValue abstractReturnValue = definition.getAbstractValue(appView, context);
if (abstractReturnValue.isNonTrivial()) {
feedback.methodReturnsAbstractValue(method, appView, abstractReturnValue);
@@ -424,16 +419,9 @@
return;
}
- DexClass clazz = appView.appInfo().definitionFor(method.holder());
- if (clazz == null) {
- assert false;
- return;
- }
-
NonTrivialInstanceInitializerInfo.Builder builder =
NonTrivialInstanceInitializerInfo.builder(instanceFieldInitializationInfos);
- InstanceInitializerInfo instanceInitializerInfo =
- analyzeInstanceInitializer(code, clazz, builder);
+ InstanceInitializerInfo instanceInitializerInfo = analyzeInstanceInitializer(code, builder);
feedback.setInstanceInitializerInfo(
method,
instanceInitializerInfo != null
@@ -457,8 +445,9 @@
//
// (Note that this initializer does not have to have zero arguments.)
private InstanceInitializerInfo analyzeInstanceInitializer(
- IRCode code, DexClass clazz, NonTrivialInstanceInitializerInfo.Builder builder) {
- if (clazz.definesFinalizer(options.itemFactory)) {
+ IRCode code, NonTrivialInstanceInitializerInfo.Builder builder) {
+ ProgramMethod context = code.context();
+ if (context.getHolder().definesFinalizer(options.itemFactory)) {
// Defining a finalize method can observe the side-effect of Object.<init> GC registration.
return null;
}
@@ -510,7 +499,7 @@
// instructions can trigger class initialization side effects, hence it is not necessary
// to mark all fields as potentially being read. Also, none of the instruction types
// can cause the receiver to escape.
- if (instruction.instructionMayHaveSideEffects(appView, clazz.type)) {
+ if (instruction.instructionMayHaveSideEffects(appView, context)) {
builder.setMayHaveOtherSideEffectsThanInstanceFieldAssignments();
}
break;
@@ -519,12 +508,13 @@
case STATIC_GET:
{
FieldInstruction fieldGet = instruction.asFieldInstruction();
- DexEncodedField field = appView.appInfo().resolveField(fieldGet.getField());
+ DexEncodedField field =
+ appView.appInfo().resolveField(fieldGet.getField()).getResolvedField();
if (field == null) {
return null;
}
builder.markFieldAsRead(field);
- if (fieldGet.instructionMayHaveSideEffects(appView, clazz.type)) {
+ if (fieldGet.instructionMayHaveSideEffects(appView, context)) {
builder.setMayHaveOtherSideEffectsThanInstanceFieldAssignments();
if (fieldGet.isStaticGet()) {
// It could trigger a class initializer.
@@ -537,14 +527,15 @@
case INSTANCE_PUT:
{
InstancePut instancePut = instruction.asInstancePut();
- DexEncodedField field = appView.appInfo().resolveField(instancePut.getField());
+ DexEncodedField field =
+ appView.appInfo().resolveField(instancePut.getField()).getResolvedField();
if (field == null) {
return null;
}
Value object =
instancePut.object().getAliasedValue(aliasesThroughAssumeAndCheckCasts);
if (object != receiver
- || instancePut.instructionInstanceCanThrow(appView, clazz.type).isThrowing()) {
+ || instancePut.instructionInstanceCanThrow(appView, context).isThrowing()) {
builder.setMayHaveOtherSideEffectsThanInstanceFieldAssignments();
}
@@ -612,7 +603,7 @@
case INVOKE_NEW_ARRAY:
{
InvokeNewArray invoke = instruction.asInvokeNewArray();
- if (invoke.instructionMayHaveSideEffects(appView, clazz.type)) {
+ if (invoke.instructionMayHaveSideEffects(appView, context)) {
builder.setMayHaveOtherSideEffectsThanInstanceFieldAssignments();
}
for (Value argument : invoke.arguments()) {
@@ -644,7 +635,7 @@
case NEW_INSTANCE:
{
NewInstance newInstance = instruction.asNewInstance();
- if (newInstance.instructionMayHaveSideEffects(appView, clazz.type)) {
+ if (newInstance.instructionMayHaveSideEffects(appView, context)) {
// It could trigger a class initializer.
builder
.markAllFieldsAsRead()
@@ -694,12 +685,12 @@
if (method.isStatic()) {
// Identifies if the method preserves class initialization after inlining.
feedback.markTriggerClassInitBeforeAnySideEffect(
- method, triggersClassInitializationBeforeSideEffect(method.holder(), code, appView));
+ method, triggersClassInitializationBeforeSideEffect(code));
} else {
// Identifies if the method preserves null check of the receiver after inlining.
final Value receiver = code.getThis();
feedback.markCheckNullReceiverBeforeAnySideEffect(
- method, receiver.isUsed() && checksNullBeforeSideEffect(code, receiver, appView));
+ method, receiver.isUsed() && checksNullBeforeSideEffect(code, receiver));
}
}
@@ -709,14 +700,17 @@
*
* <p>Note: we do not track phis so we may return false negative. This is a conservative approach.
*/
- private static boolean triggersClassInitializationBeforeSideEffect(
- DexType clazz, IRCode code, AppView<?> appView) {
+ private boolean triggersClassInitializationBeforeSideEffect(IRCode code) {
return alwaysTriggerExpectedEffectBeforeAnythingElse(
code,
(instruction, it) -> {
- DexType context = code.method().holder();
+ ProgramMethod context = code.context();
if (instruction.definitelyTriggersClassInitialization(
- clazz, context, appView, DIRECTLY, AnalysisAssumption.INSTRUCTION_DOES_NOT_THROW)) {
+ context.getHolderType(),
+ context,
+ appView,
+ DIRECTLY,
+ AnalysisAssumption.INSTRUCTION_DOES_NOT_THROW)) {
// In order to preserve class initialization semantic, the exception must not be caught
// by any handler. Therefore, we must ignore this instruction if it is covered by a
// catch handler.
@@ -726,7 +720,7 @@
// We found an instruction that preserves initialization of the class.
return InstructionEffect.DESIRED_EFFECT;
}
- } else if (instruction.instructionMayHaveSideEffects(appView, clazz)) {
+ } else if (instruction.instructionMayHaveSideEffects(appView, context)) {
// We found a side effect before class initialization.
return InstructionEffect.OTHER_EFFECT;
}
@@ -810,7 +804,7 @@
*
* <p>Note: we do not track phis so we may return false negative. This is a conservative approach.
*/
- private static boolean checksNullBeforeSideEffect(IRCode code, Value value, AppView<?> appView) {
+ private boolean checksNullBeforeSideEffect(IRCode code, Value value) {
return alwaysTriggerExpectedEffectBeforeAnythingElse(
code,
(instr, it) -> {
@@ -847,7 +841,7 @@
if (isInstantiationOfNullPointerException(instr, it, appView.dexItemFactory())) {
it.next(); // Skip call to NullPointerException.<init>.
return InstructionEffect.NO_EFFECT;
- } else if (instr.throwsNpeIfValueIsNull(value, appView, code.method().holder())) {
+ } else if (instr.throwsNpeIfValueIsNull(value, appView, code.context())) {
// In order to preserve NPE semantic, the exception must not be caught by any handler.
// Therefore, we must ignore this instruction if it is covered by a catch handler.
// Note: this is a conservative approach where we consider that any catch handler could
@@ -856,7 +850,7 @@
// We found a NPE check on the value.
return InstructionEffect.DESIRED_EFFECT;
}
- } else if (instr.instructionMayHaveSideEffects(appView, code.method().holder())) {
+ } else if (instr.instructionMayHaveSideEffects(appView, code.context())) {
// If the current instruction is const-string, this could load the parameter name.
// Just make sure it is indeed not throwing.
if (instr.isConstString() && !instr.instructionInstanceCanThrow()) {
@@ -1021,7 +1015,7 @@
if (appView.appInfo().mayHaveSideEffects.containsKey(method.method)) {
return;
}
- DexType context = method.holder();
+ ProgramMethod context = code.context();
if (method.isClassInitializer()) {
// For class initializers, we also wish to compute if the class initializer has observable
// side effects.
@@ -1033,9 +1027,9 @@
} else if (classInitializerSideEffect.canBePostponed()) {
feedback.classInitializerMayBePostponed(method);
} else {
- assert !context.isD8R8SynthesizedLambdaClassType()
+ assert !context.getHolderType().isD8R8SynthesizedLambdaClassType()
|| options.debug
- || appView.appInfo().hasPinnedInstanceInitializer(context)
+ || appView.appInfo().hasPinnedInstanceInitializer(context.getHolderType())
: "Unexpected observable side effects from lambda `" + context.toSourceString() + "`";
}
return;
@@ -1044,7 +1038,7 @@
if (method.isSynchronized()) {
// If the method is synchronized then it acquires a lock.
mayHaveSideEffects = true;
- } else if (method.isInstanceInitializer() && hasNonTrivialFinalizeMethod(context)) {
+ } else if (method.isInstanceInitializer() && hasNonTrivialFinalizeMethod(context.getHolder())) {
// If a class T overrides java.lang.Object.finalize(), then treat the constructor as having
// side effects. This ensures that we won't remove instructions on the form `new-instance
// {v0}, T`.
@@ -1064,31 +1058,20 @@
}
}
- // Returns true if `method` is an initializer and the enclosing class overrides the method
- // `void java.lang.Object.finalize()`.
- private boolean hasNonTrivialFinalizeMethod(DexType type) {
- DexClass clazz = appView.definitionFor(type);
- if (clazz != null) {
- if (clazz.isProgramClass() && !clazz.isInterface()) {
- DexItemFactory dexItemFactory = appView.dexItemFactory();
- ResolutionResult resolutionResult =
- appView
- .appInfo()
- .resolveMethodOnClass(clazz, appView.dexItemFactory().objectMembers.finalize);
-
- DexEncodedMethod target = resolutionResult.getSingleTarget();
- if (target != null
- && target.method != dexItemFactory.enumMethods.finalize
- && target.method != dexItemFactory.objectMembers.finalize) {
- return true;
- }
- return false;
- } else {
- // Conservatively report that the library class could implement finalize().
- return true;
- }
+ // Returns true if the given class overrides the method `void java.lang.Object.finalize()`.
+ private boolean hasNonTrivialFinalizeMethod(DexProgramClass clazz) {
+ if (clazz.isInterface()) {
+ return false;
}
- return false;
+ DexItemFactory dexItemFactory = appView.dexItemFactory();
+ ResolutionResult resolutionResult =
+ appView
+ .appInfo()
+ .resolveMethodOnClass(appView.dexItemFactory().objectMembers.finalize, clazz);
+ DexEncodedMethod target = resolutionResult.getSingleTarget();
+ return target != null
+ && target.method != dexItemFactory.enumMethods.finalize
+ && target.method != dexItemFactory.objectMembers.finalize;
}
private void computeReturnValueOnlyDependsOnArguments(
@@ -1137,7 +1120,7 @@
// invoke-static throwParameterIsNullException(msg)
//
// or some other variants, e.g., throw null or NPE after the direct null check.
- if (argument.isUsed() && checksNullBeforeSideEffect(code, argument, appView)) {
+ if (argument.isUsed() && checksNullBeforeSideEffect(code, argument)) {
paramsCheckedForNull.set(index);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java
index 091a5e5..05d9b49 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporter.java
@@ -5,21 +5,21 @@
package com.android.tools.r8.ir.optimize.inliner;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.InstancePut;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.optimize.Inliner.Reason;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import java.util.Collection;
+import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.Set;
public abstract class WhyAreYouNotInliningReporter {
public static WhyAreYouNotInliningReporter createFor(
- DexEncodedMethod callee, AppView<AppInfoWithLiveness> appView, DexEncodedMethod context) {
- if (appView.appInfo().whyAreYouNotInlining.contains(callee.method)) {
+ ProgramMethod callee, AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+ if (appView.appInfo().whyAreYouNotInlining.contains(callee.getReference())) {
return new WhyAreYouNotInliningReporterImpl(
callee, context, appView.options().testing.whyAreYouNotInliningConsumer);
}
@@ -27,20 +27,20 @@
}
public static void handleInvokeWithUnknownTarget(
- InvokeMethod invoke, AppView<AppInfoWithLiveness> appView, DexEncodedMethod context) {
+ InvokeMethod invoke, AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
if (appView.appInfo().whyAreYouNotInlining.isEmpty()) {
return;
}
- Collection<DexEncodedMethod> possibleTargets = invoke.lookupTargets(appView, context.holder());
- if (possibleTargets == null) {
+ ProgramMethodSet possibleProgramTargets = invoke.lookupProgramDispatchTargets(appView, context);
+ if (possibleProgramTargets == null) {
// In principle, this invoke might target any method in the program, but we do not want to
// report a message for each of the methods in `AppInfoWithLiveness#whyAreYouNotInlining`,
// since that would almost never be useful.
return;
}
- for (DexEncodedMethod possibleTarget : possibleTargets) {
+ for (ProgramMethod possibleTarget : possibleProgramTargets) {
createFor(possibleTarget, appView, context).reportUnknownTarget();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
index b141817..934651c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/inliner/WhyAreYouNotInliningReporterImpl.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.ir.optimize.inliner;
-import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.InstancePut;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeDirect;
@@ -15,14 +15,14 @@
class WhyAreYouNotInliningReporterImpl extends WhyAreYouNotInliningReporter {
- private final DexEncodedMethod callee;
- private final DexEncodedMethod context;
+ private final ProgramMethod callee;
+ private final ProgramMethod context;
private final PrintStream output;
private boolean reasonHasBeenReported = false;
WhyAreYouNotInliningReporterImpl(
- DexEncodedMethod callee, DexEncodedMethod context, PrintStream output) {
+ ProgramMethod callee, ProgramMethod context, PrintStream output) {
this.callee = callee;
this.context = context;
this.output = output;
@@ -30,9 +30,9 @@
private void print(String reason) {
output.print("Method `");
- output.print(callee.method.toSourceString());
+ output.print(callee.toSourceString());
output.print("` was not inlined into `");
- output.print(context.method.toSourceString());
+ output.print(context.toSourceString());
if (reason != null) {
output.print("`: ");
output.println(reason);
@@ -220,7 +220,7 @@
"final field `"
+ instancePut.getField()
+ "` must be initialized in a constructor of `"
- + callee.holder().toSourceString()
+ + callee.getHolderType().toSourceString()
+ "`.");
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index 2a5e9cd..7a81f73 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -157,8 +157,7 @@
DexType holder = invokedMethod.holder;
if (lambdaGroup.containsLambda(holder)) {
// TODO(b/150685763): Check if we can use simpler lookup.
- ResolutionResult resolution =
- appView.appInfo().resolveMethod(holder, invokedMethod, false);
+ ResolutionResult resolution = appView.appInfo().resolveMethodOnClass(invokedMethod);
assert resolution.isSingleResolution();
ProgramMethod singleTarget =
resolution.asSingleResolution().getResolutionPair().asProgramMethod();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/BooleanMethodOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/BooleanMethodOptimizer.java
index 76e81ac..a560844 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/BooleanMethodOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/BooleanMethodOptimizer.java
@@ -70,7 +70,7 @@
InvokeMethod invoke,
Set<Value> affectedValues) {
Value argument = invoke.arguments().get(0);
- AbstractValue abstractValue = argument.getAbstractValue(appView, code.method().holder());
+ AbstractValue abstractValue = argument.getAbstractValue(appView, code.context());
if (abstractValue.isSingleNumberValue()) {
instructionIterator.replaceCurrentInstructionWithStaticGet(
appView,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMemberOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMemberOptimizer.java
index 6566187..0c7393b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMemberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMemberOptimizer.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory.LibraryMembers;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -86,12 +87,12 @@
*
* <p>In order for library modeling to work in D8, we return a definition for invoke instructions
* that are guaranteed to dispatch to a library method in {@link
- * InvokeMethod#lookupSingleTarget(AppView, DexType)}. As part of that, we bail-out if the holder
- * of the targeted method is not a library class. However, what is usually on the library path
- * will be on the program path when compiling the framework itself. To ensure that our library
- * modeling works also for the framework compilation, we maintain the set of types that we model,
- * and treat these types as library types in {@link InvokeMethod#lookupSingleTarget(AppView,
- * DexType)} although they are on the program path.
+ * InvokeMethod#lookupSingleTarget(AppView, ProgramMethod)}. As part of that, we bail-out if the
+ * holder of the targeted method is not a library class. However, what is usually on the library
+ * path will be on the program path when compiling the framework itself. To ensure that our
+ * library modeling works also for the framework compilation, we maintain the set of types that we
+ * model, and treat these types as library types in {@link
+ * InvokeMethod#lookupSingleTarget(AppView, ProgramMethod)} although they are on the program path.
*/
public boolean isModeled(DexType type) {
return modeledLibraryTypes.contains(type);
@@ -114,7 +115,7 @@
Instruction instruction = instructionIterator.next();
if (instruction.isInvokeMethod()) {
InvokeMethod invoke = instruction.asInvokeMethod();
- DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, code.method().holder());
+ DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, code.context());
if (singleTarget != null) {
optimizeInvoke(code, instructionIterator, invoke, singleTarget, affectedValues);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/StringMethodOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/StringMethodOptimizer.java
index 1283bf4..64dce88 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/StringMethodOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/StringMethodOptimizer.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.DexItemBasedConstString;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -47,7 +48,7 @@
private void optimizeEquals(
IRCode code, InstructionListIterator instructionIterator, InvokeMethod invoke) {
if (appView.appInfo().hasLiveness()) {
- DexType context = code.method().holder();
+ ProgramMethod context = code.context();
Value first = invoke.arguments().get(0).getAliasedValue();
Value second = invoke.arguments().get(1).getAliasedValue();
if (isPrunedClassNameComparison(first, second, context)
@@ -63,7 +64,7 @@
* has been pruned by the {@link com.android.tools.r8.shaking.Enqueuer}.
*/
private boolean isPrunedClassNameComparison(
- Value classNameValue, Value constStringValue, DexType context) {
+ Value classNameValue, Value constStringValue, ProgramMethod context) {
if (classNameValue.isPhi() || constStringValue.isPhi()) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
index 041cf09..acba57f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
@@ -82,8 +82,8 @@
candidates.put(candidate.type, this);
}
- boolean isHostClassInitializer(DexEncodedMethod method) {
- return factory.isClassConstructor(method.method) && method.holder() == hostType();
+ boolean isHostClassInitializer(ProgramMethod method) {
+ return method.getDefinition().isClassInitializer() && method.getHolderType() == hostType();
}
DexType hostType() {
@@ -217,10 +217,10 @@
//
// NOTE: can be called concurrently.
public final void examineMethodCode(IRCode code) {
- ProgramMethod method = code.context();
+ ProgramMethod context = code.context();
Set<Instruction> alreadyProcessed = Sets.newIdentityHashSet();
- CandidateInfo receiverClassCandidateInfo = candidates.get(method.getHolderType());
+ CandidateInfo receiverClassCandidateInfo = candidates.get(context.getHolderType());
Value receiverValue = code.getThis(); // NOTE: is null for static methods.
if (receiverClassCandidateInfo != null) {
if (receiverValue != null) {
@@ -230,26 +230,26 @@
analyzeAllValueUsers(
receiverClassCandidateInfo,
receiverValue,
- factory.isConstructor(method.getReference()));
+ factory.isConstructor(context.getReference()));
// If the candidate is still valid, ignore all instructions
// we treat as valid usages on receiver.
- if (candidates.get(method.getHolderType()) != null) {
+ if (candidates.get(context.getHolderType()) != null) {
alreadyProcessed.addAll(receiverValue.uniqueUsers());
}
} else {
// We are inside a static method of candidate class.
// Check if this is a valid getter of the singleton field.
- if (method.getDefinition().returnType() == method.getHolderType()) {
+ if (context.getDefinition().returnType() == context.getHolderType()) {
List<Instruction> examined = isValidGetter(receiverClassCandidateInfo, code);
if (examined != null) {
DexEncodedMethod getter = receiverClassCandidateInfo.getter.get();
if (getter == null) {
- receiverClassCandidateInfo.getter.set(method.getDefinition());
+ receiverClassCandidateInfo.getter.set(context.getDefinition());
// Except for static-get and return, iterate other remaining instructions if any.
alreadyProcessed.addAll(examined);
} else {
- assert getter != method.getDefinition();
+ assert getter != context.getDefinition();
// Not sure how to deal with many getters.
receiverClassCandidateInfo.invalidate();
}
@@ -275,8 +275,7 @@
if (instruction.isNewInstance()) {
// Check the class being initialized against valid staticizing candidates.
NewInstance newInstance = instruction.asNewInstance();
- CandidateInfo candidateInfo =
- processInstantiation(method.getDefinition(), iterator, newInstance);
+ CandidateInfo candidateInfo = processInstantiation(context, iterator, newInstance);
if (candidateInfo != null) {
alreadyProcessed.addAll(newInstance.outValue().aliasedUsers());
// For host class initializers having eligible instantiation we also want to
@@ -284,7 +283,7 @@
// This must guarantee that removing field access will not result in missing side
// effects, otherwise we can still staticize, but cannot remove singleton reads.
while (iterator.hasNext()) {
- if (!isAllowedInHostClassInitializer(method.getHolderType(), iterator.next(), code)) {
+ if (!isAllowedInHostClassInitializer(context.getHolderType(), iterator.next(), code)) {
candidateInfo.preserveRead.set(true);
iterator.previous();
break;
@@ -293,7 +292,7 @@
}
referencedFrom
.computeIfAbsent(candidateInfo, ignore -> new LongLivedProgramMethodSetBuilder())
- .add(method);
+ .add(context);
}
continue;
}
@@ -315,7 +314,7 @@
if (info != null) {
referencedFrom
.computeIfAbsent(info, ignore -> new LongLivedProgramMethodSetBuilder())
- .add(method);
+ .add(context);
// If the candidate is still valid, ignore all usages in further analysis.
Value value = instruction.outValue();
if (value != null) {
@@ -331,7 +330,7 @@
if (info != null) {
referencedFrom
.computeIfAbsent(info, ignore -> new LongLivedProgramMethodSetBuilder())
- .add(method);
+ .add(context);
// If the candidate is still valid, ignore all usages in further analysis.
Value value = instruction.outValue();
if (value != null) {
@@ -380,8 +379,7 @@
}
private CandidateInfo processInstantiation(
- DexEncodedMethod method, ListIterator<Instruction> iterator, NewInstance newInstance) {
-
+ ProgramMethod context, ListIterator<Instruction> iterator, NewInstance newInstance) {
DexType candidateType = newInstance.clazz;
CandidateInfo candidateInfo = candidates.get(candidateType);
if (candidateInfo == null) {
@@ -393,7 +391,7 @@
return candidateInfo.invalidate();
}
- if (!candidateInfo.isHostClassInitializer(method)) {
+ if (!candidateInfo.isHostClassInitializer(context)) {
// A valid candidate must only have one instantiation which is
// done in the static initializer of the host class.
return candidateInfo.invalidate();
@@ -445,7 +443,7 @@
}
Set<Instruction> users = SetUtils.newIdentityHashSet(candidateValue.uniqueUsers());
Instruction constructorCall = iterator.next();
- if (!isValidInitCall(candidateInfo, constructorCall, candidateValue, candidateType)) {
+ if (!isValidInitCall(candidateInfo, constructorCall, candidateValue, context)) {
iterator.previous();
return candidateInfo.invalidate();
}
@@ -475,7 +473,7 @@
}
private boolean isValidInitCall(
- CandidateInfo info, Instruction instruction, Value candidateValue, DexType candidateType) {
+ CandidateInfo info, Instruction instruction, Value candidateValue, ProgramMethod context) {
if (!instruction.isInvokeDirect()) {
return false;
}
@@ -483,12 +481,12 @@
// Check constructor.
InvokeDirect invoke = instruction.asInvokeDirect();
DexEncodedMethod methodInvoked =
- appView.appInfo().lookupDirectTarget(invoke.getInvokedMethod(), info.candidate);
+ appView.appInfo().lookupDirectTarget(invoke.getInvokedMethod(), context);
List<Value> values = invoke.inValues();
if (ListUtils.lastIndexMatching(values, v -> v.getAliasedValue() == candidateValue) != 0
|| methodInvoked == null
- || methodInvoked.holder() != candidateType) {
+ || methodInvoked.holder() != info.candidate.type) {
return false;
}
@@ -511,8 +509,7 @@
}
// Allow single assignment to a singleton field.
StaticPut staticPut = instruction.asStaticPut();
- DexEncodedField fieldAccessed =
- appView.appInfo().lookupStaticTarget(staticPut.getField().holder, staticPut.getField());
+ DexEncodedField fieldAccessed = appView.appInfo().lookupStaticTarget(staticPut.getField());
return fieldAccessed == info.singletonField;
}
@@ -529,8 +526,7 @@
for (Instruction instr : code.instructions()) {
if (instr.isStaticGet()) {
staticGet = instr.asStaticGet();
- DexEncodedField fieldAccessed =
- appView.appInfo().lookupStaticTarget(staticGet.getField().holder, staticGet.getField());
+ DexEncodedField fieldAccessed = appView.appInfo().lookupStaticTarget(staticGet.getField());
if (fieldAccessed != info.singletonField) {
return null;
}
@@ -562,7 +558,7 @@
return null;
}
- assert candidateInfo.singletonField == appView.appInfo().lookupStaticTarget(field.holder, field)
+ assert candidateInfo.singletonField == appView.appInfo().lookupStaticTarget(field)
: "Added reference after collectCandidates(...)?";
Value singletonValue = staticGet.dest();
@@ -651,7 +647,7 @@
}
AppInfoWithLiveness appInfo = appView.appInfo();
ResolutionResult resolutionResult =
- appInfo.resolveMethod(methodReferenced.holder, methodReferenced);
+ appInfo.unsafeResolveMethodDueToDexFormat(methodReferenced);
DexEncodedMethod methodInvoked =
user.isInvokeDirect()
? resolutionResult.lookupInvokeDirectTarget(candidateInfo.candidate, appInfo)
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
index 07d330b..53122b0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.escape.EscapeAnalysis;
import com.android.tools.r8.ir.analysis.escape.EscapeAnalysisConfiguration;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
@@ -882,7 +883,7 @@
AppView<?> appView,
EscapeAnalysis escapeAnalysis,
Instruction escapeRoute,
- DexMethod context) {
+ ProgramMethod context) {
if (escapeRoute.isReturn() || escapeRoute.isThrow() || escapeRoute.isStaticPut()) {
logEscapingRoute(false);
return false;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
index ae94194..d00100a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.escape.EscapeAnalysis;
import com.android.tools.r8.ir.analysis.escape.EscapeAnalysisConfiguration;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
@@ -589,7 +590,7 @@
AppView<?> appView,
EscapeAnalysis escapeAnalysis,
Instruction escapeRoute,
- DexMethod context) {
+ ProgramMethod context) {
if (escapeRoute.isReturn() || escapeRoute.isThrow() || escapeRoute.isStaticPut()) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/Kotlin.java b/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
index 18b3533..b225440 100644
--- a/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
+++ b/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
@@ -4,8 +4,6 @@
package com.android.tools.r8.kotlin;
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
@@ -192,9 +190,4 @@
public final DexMethod throwNpe = factory.createMethod(
type, factory.createProto(factory.voidType), "throwNpe");
}
-
- // Calculates kotlin info for a class.
- public KotlinClassLevelInfo getKotlinInfo(DexClass clazz, AppView<?> appView) {
- return KotlinClassMetadataReader.getKotlinInfo(this, clazz, appView);
- }
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
index 47ed582..a4bc5b0 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
@@ -4,7 +4,10 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.referenceTypeFromBinaryName;
+
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.NamingLens;
@@ -31,19 +34,21 @@
this.arguments = arguments;
}
- private static KotlinAnnotationInfo create(KmAnnotation annotation, AppView<?> appView) {
- String descriptor = DescriptorUtils.getDescriptorFromClassBinaryName(annotation.getClassName());
- DexType type = appView.dexItemFactory().createType(descriptor);
- return new KotlinAnnotationInfo(type, annotation.getArguments());
+ private static KotlinAnnotationInfo create(
+ KmAnnotation annotation, DexDefinitionSupplier definitionSupplier) {
+ return new KotlinAnnotationInfo(
+ referenceTypeFromBinaryName(annotation.getClassName(), definitionSupplier),
+ annotation.getArguments());
}
- static List<KotlinAnnotationInfo> create(List<KmAnnotation> annotations, AppView<?> appView) {
+ static List<KotlinAnnotationInfo> create(
+ List<KmAnnotation> annotations, DexDefinitionSupplier definitionSupplier) {
if (annotations.isEmpty()) {
return EMPTY_ANNOTATIONS;
}
ImmutableList.Builder<KotlinAnnotationInfo> builder = ImmutableList.builder();
for (KmAnnotation annotation : annotations) {
- builder.add(create(annotation, appView));
+ builder.add(create(annotation, definitionSupplier));
}
return builder.build();
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
index b2f71cb..2cb8fe4 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
@@ -4,11 +4,13 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.referenceTypeFromBinaryName;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toJvmFieldSignature;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toJvmMethodSignature;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexString;
@@ -16,6 +18,7 @@
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.HashMap;
import java.util.List;
@@ -68,7 +71,11 @@
this.anonymousObjectOrigin = anonymousObjectOrigin;
}
- public static KotlinClassInfo create(KmClass kmClass, DexClass hostClass, AppView<?> appView) {
+ public static KotlinClassInfo create(
+ KmClass kmClass,
+ DexClass hostClass,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
Map<String, DexEncodedField> fieldMap = new HashMap<>();
for (DexEncodedField field : hostClass.fields()) {
fieldMap.put(toJvmFieldSignature(field.field).asString(), field);
@@ -79,7 +86,8 @@
}
ImmutableList.Builder<KotlinConstructorInfo> notBackedConstructors = ImmutableList.builder();
for (KmConstructor kmConstructor : kmClass.getConstructors()) {
- KotlinConstructorInfo constructorInfo = KotlinConstructorInfo.create(kmConstructor, appView);
+ KotlinConstructorInfo constructorInfo =
+ KotlinConstructorInfo.create(kmConstructor, definitionSupplier, reporter);
JvmMethodSignature signature = JvmExtensionsKt.getSignature(kmConstructor);
if (signature != null) {
DexEncodedMethod method = methodMap.get(signature.asString());
@@ -92,72 +100,65 @@
notBackedConstructors.add(constructorInfo);
}
KotlinDeclarationContainerInfo container =
- KotlinDeclarationContainerInfo.create(kmClass, methodMap, fieldMap, appView);
- setCompanionObject(kmClass, hostClass, appView);
+ KotlinDeclarationContainerInfo.create(
+ kmClass, methodMap, fieldMap, definitionSupplier, reporter);
+ setCompanionObject(kmClass, hostClass, reporter);
return new KotlinClassInfo(
kmClass.getFlags(),
kmClass.name,
JvmExtensionsKt.getModuleName(kmClass),
container,
- KotlinTypeParameterInfo.create(kmClass.getTypeParameters(), appView),
+ KotlinTypeParameterInfo.create(kmClass.getTypeParameters(), definitionSupplier, reporter),
notBackedConstructors.build(),
- getSuperTypes(kmClass.getSupertypes(), appView),
- getSealedSubClasses(hostClass, kmClass.getSealedSubclasses(), appView),
- getNestedClasses(hostClass, kmClass.getNestedClasses(), appView),
+ getSuperTypes(kmClass.getSupertypes(), definitionSupplier, reporter),
+ getSealedSubClasses(hostClass, kmClass.getSealedSubclasses(), definitionSupplier),
+ getNestedClasses(hostClass, kmClass.getNestedClasses(), definitionSupplier),
kmClass.getEnumEntries(),
- getAnonymousObjectOrigin(kmClass, appView));
+ getAnonymousObjectOrigin(kmClass, definitionSupplier));
}
- private static DexType getAnonymousObjectOrigin(KmClass kmClass, AppView<?> appView) {
+ private static DexType getAnonymousObjectOrigin(
+ KmClass kmClass, DexDefinitionSupplier definitionSupplier) {
String anonymousObjectOriginName = JvmExtensionsKt.getAnonymousObjectOriginName(kmClass);
if (anonymousObjectOriginName != null) {
- return appView
- .dexItemFactory()
- .createType(DescriptorUtils.getDescriptorFromClassBinaryName(anonymousObjectOriginName));
+ return referenceTypeFromBinaryName(anonymousObjectOriginName, definitionSupplier);
}
return null;
}
private static List<DexType> getNestedClasses(
- DexClass clazz, List<String> nestedClasses, AppView<?> appView) {
+ DexClass clazz, List<String> nestedClasses, DexDefinitionSupplier definitionSupplier) {
ImmutableList.Builder<DexType> nestedTypes = ImmutableList.builder();
for (String nestedClass : nestedClasses) {
String binaryName =
clazz.type.toBinaryName() + DescriptorUtils.INNER_CLASS_SEPARATOR + nestedClass;
- DexType nestedType =
- appView
- .dexItemFactory()
- .createType(DescriptorUtils.getDescriptorFromClassBinaryName(binaryName));
- nestedTypes.add(nestedType);
+ nestedTypes.add(referenceTypeFromBinaryName(binaryName, definitionSupplier));
}
return nestedTypes.build();
}
private static List<DexType> getSealedSubClasses(
- DexClass clazz, List<String> sealedSubclasses, AppView<?> appView) {
+ DexClass clazz, List<String> sealedSubclasses, DexDefinitionSupplier definitionSupplier) {
ImmutableList.Builder<DexType> sealedTypes = ImmutableList.builder();
for (String sealedSubClass : sealedSubclasses) {
String binaryName =
sealedSubClass.replace(
DescriptorUtils.JAVA_PACKAGE_SEPARATOR, DescriptorUtils.INNER_CLASS_SEPARATOR);
- DexType sealedType =
- appView
- .dexItemFactory()
- .createType(DescriptorUtils.getDescriptorFromClassBinaryName(binaryName));
- sealedTypes.add(sealedType);
+ sealedTypes.add(referenceTypeFromBinaryName(binaryName, definitionSupplier));
}
return sealedTypes.build();
}
- private static List<KotlinTypeInfo> getSuperTypes(List<KmType> superTypes, AppView<?> appView) {
+ private static List<KotlinTypeInfo> getSuperTypes(
+ List<KmType> superTypes, DexDefinitionSupplier definitionSupplier, Reporter reporter) {
ImmutableList.Builder<KotlinTypeInfo> superTypeInfos = ImmutableList.builder();
for (KmType superType : superTypes) {
- superTypeInfos.add(KotlinTypeInfo.create(superType, appView));
+ superTypeInfos.add(KotlinTypeInfo.create(superType, definitionSupplier, reporter));
}
return superTypeInfos.build();
}
- private static void setCompanionObject(KmClass kmClass, DexClass hostClass, AppView<?> appView) {
+ private static void setCompanionObject(KmClass kmClass, DexClass hostClass, Reporter reporter) {
String companionObjectName = kmClass.getCompanionObject();
if (companionObjectName == null) {
return;
@@ -168,10 +169,8 @@
return;
}
}
- appView
- .options()
- .reporter
- .warning(KotlinMetadataDiagnostic.missingCompanionObject(hostClass, companionObjectName));
+ reporter.warning(
+ KotlinMetadataDiagnostic.missingCompanionObject(hostClass, companionObjectName));
}
@Override
@@ -235,7 +234,7 @@
}
// Rewrite nested classes.
for (DexType nestedClass : nestedClasses) {
- if (appView.definitionFor(nestedClass) != null) {
+ if (appView.appInfo().isNonProgramTypeOrLiveProgramType(nestedClass)) {
String descriptor =
KotlinMetadataUtils.kotlinNameFromDescriptor(namingLens.lookupDescriptor(nestedClass));
// If the class is a nested class, it should be on the form Foo.Bar$Baz, where Baz is the
@@ -246,7 +245,7 @@
}
// Rewrite sealed sub classes.
for (DexType sealedSubClass : sealedSubClasses) {
- if (appView.definitionFor(sealedSubClass) != null) {
+ if (appView.appInfo().isNonProgramTypeOrLiveProgramType(sealedSubClass)) {
String descriptor =
KotlinMetadataUtils.kotlinNameFromDescriptor(
namingLens.lookupDescriptor(sealedSubClass));
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
index 13ae5f5..f52f65e 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
@@ -5,14 +5,15 @@
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.NO_KOTLIN_INFO;
-import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedAnnotation;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueArray;
+import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -23,31 +24,25 @@
public final class KotlinClassMetadataReader {
public static KotlinClassLevelInfo getKotlinInfo(
- Kotlin kotlin, DexClass clazz, AppView<?> appView) {
+ Kotlin kotlin, DexClass clazz, DexDefinitionSupplier definitionSupplier, Reporter reporter) {
DexAnnotation meta = clazz.annotations().getFirstMatching(kotlin.metadata.kotlinMetadataType);
if (meta != null) {
try {
- return createKotlinInfo(kotlin, clazz, meta.annotation, appView);
+ return createKotlinInfo(kotlin, clazz, meta.annotation, definitionSupplier, reporter);
} catch (ClassCastException | InconsistentKotlinMetadataException | MetadataError e) {
- appView
- .options()
- .reporter
- .info(
- new StringDiagnostic(
- "Class "
- + clazz.type.toSourceString()
- + " has malformed kotlin.Metadata: "
- + e.getMessage()));
+ reporter.info(
+ new StringDiagnostic(
+ "Class "
+ + clazz.type.toSourceString()
+ + " has malformed kotlin.Metadata: "
+ + e.getMessage()));
} catch (Throwable e) {
- appView
- .options()
- .reporter
- .info(
- new StringDiagnostic(
- "Unexpected error while reading "
- + clazz.type.toSourceString()
- + "'s kotlin.Metadata: "
- + e.getMessage()));
+ reporter.info(
+ new StringDiagnostic(
+ "Unexpected error while reading "
+ + clazz.type.toSourceString()
+ + "'s kotlin.Metadata: "
+ + e.getMessage()));
}
}
return NO_KOTLIN_INFO;
@@ -85,27 +80,35 @@
}
public static KotlinClassLevelInfo createKotlinInfo(
- Kotlin kotlin, DexClass clazz, DexEncodedAnnotation metadataAnnotation, AppView<?> appView) {
+ Kotlin kotlin,
+ DexClass clazz,
+ DexEncodedAnnotation metadataAnnotation,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
KotlinClassMetadata kMetadata = toKotlinClassMetadata(kotlin, metadataAnnotation);
if (kMetadata instanceof KotlinClassMetadata.Class) {
return KotlinClassInfo.create(
- ((KotlinClassMetadata.Class) kMetadata).toKmClass(), clazz, appView);
+ ((KotlinClassMetadata.Class) kMetadata).toKmClass(), clazz, definitionSupplier, reporter);
} else if (kMetadata instanceof KotlinClassMetadata.FileFacade) {
// e.g., B.kt becomes class `BKt`
return KotlinFileFacadeInfo.create(
- (KotlinClassMetadata.FileFacade) kMetadata, clazz, appView);
+ (KotlinClassMetadata.FileFacade) kMetadata, clazz, definitionSupplier, reporter);
} else if (kMetadata instanceof KotlinClassMetadata.MultiFileClassFacade) {
// multi-file class with the same @JvmName.
return KotlinMultiFileClassFacadeInfo.create(
- (KotlinClassMetadata.MultiFileClassFacade) kMetadata, appView);
+ (KotlinClassMetadata.MultiFileClassFacade) kMetadata, definitionSupplier);
} else if (kMetadata instanceof KotlinClassMetadata.MultiFileClassPart) {
// A single file, which is part of multi-file class.
return KotlinMultiFileClassPartInfo.create(
- (KotlinClassMetadata.MultiFileClassPart) kMetadata, clazz, appView);
+ (KotlinClassMetadata.MultiFileClassPart) kMetadata, clazz, definitionSupplier, reporter);
} else if (kMetadata instanceof KotlinClassMetadata.SyntheticClass) {
return KotlinSyntheticClassInfo.create(
- (KotlinClassMetadata.SyntheticClass) kMetadata, clazz, kotlin, appView);
+ (KotlinClassMetadata.SyntheticClass) kMetadata,
+ clazz,
+ kotlin,
+ definitionSupplier,
+ reporter);
} else {
throw new MetadataError("unsupported 'k' value: " + kMetadata.getHeader().getKind());
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java
index 86db718..60851e2 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java
@@ -4,13 +4,17 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.referenceTypeFromDescriptor;
+
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.kotlin.Kotlin.ClassClassifiers;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.Reporter;
import kotlinx.metadata.KmClassifier;
import kotlinx.metadata.KmClassifier.TypeAlias;
import kotlinx.metadata.KmClassifier.TypeParameter;
@@ -18,7 +22,8 @@
public abstract class KotlinClassifierInfo {
- public static KotlinClassifierInfo create(KmClassifier classifier, AppView<?> appView) {
+ public static KotlinClassifierInfo create(
+ KmClassifier classifier, DexDefinitionSupplier definitionSupplier, Reporter reporter) {
if (classifier instanceof KmClassifier.Class) {
String typeName = ((KmClassifier.Class) classifier).getName();
// If this name starts with '.', it represents a local class or an anonymous object. This is
@@ -29,8 +34,8 @@
}
String descriptor = DescriptorUtils.getDescriptorFromKotlinClassifier(typeName);
if (DescriptorUtils.isClassDescriptor(descriptor)) {
- DexType type = appView.dexItemFactory().createType(descriptor);
- return new KotlinClassClassifierInfo(type);
+ return new KotlinClassClassifierInfo(
+ referenceTypeFromDescriptor(descriptor, definitionSupplier));
} else {
return new KotlinUnknownClassClassifierInfo(typeName);
}
@@ -39,10 +44,7 @@
} else if (classifier instanceof KmClassifier.TypeParameter) {
return new KotlinTypeParameterClassifierInfo(((TypeParameter) classifier).getId());
} else {
- appView
- .options()
- .reporter
- .warning(KotlinMetadataDiagnostic.unknownClassifier(classifier.toString()));
+ reporter.warning(KotlinMetadataDiagnostic.unknownClassifier(classifier.toString()));
return new KotlinUnknownClassifierInfo(classifier.toString());
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
index 3e9ee04..6f9f366 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
@@ -5,9 +5,11 @@
package com.android.tools.r8.kotlin;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import java.util.List;
import kotlinx.metadata.KmClass;
import kotlinx.metadata.KmConstructor;
@@ -32,11 +34,14 @@
this.signature = signature;
}
- public static KotlinConstructorInfo create(KmConstructor kmConstructor, AppView<?> appView) {
+ public static KotlinConstructorInfo create(
+ KmConstructor kmConstructor, DexDefinitionSupplier definitionSupplier, Reporter reporter) {
return new KotlinConstructorInfo(
kmConstructor.getFlags(),
- KotlinValueParameterInfo.create(kmConstructor.getValueParameters(), appView),
- KotlinJvmMethodSignatureInfo.create(JvmExtensionsKt.getSignature(kmConstructor), appView));
+ KotlinValueParameterInfo.create(
+ kmConstructor.getValueParameters(), definitionSupplier, reporter),
+ KotlinJvmMethodSignatureInfo.create(
+ JvmExtensionsKt.getSignature(kmConstructor), definitionSupplier));
}
public void rewrite(
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
index d1b2913..6dc4d4a 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
@@ -8,11 +8,13 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.kotlin.KotlinMetadataUtils.KmPropertyProcessor;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.IdentityHashMap;
import java.util.List;
@@ -47,7 +49,8 @@
KmDeclarationContainer container,
Map<String, DexEncodedMethod> methodSignatureMap,
Map<String, DexEncodedField> fieldSignatureMap,
- AppView<?> appView) {
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
ImmutableList.Builder<KotlinFunctionInfo> notBackedFunctions = ImmutableList.builder();
for (KmFunction kmFunction : container.getFunctions()) {
JvmMethodSignature signature = JvmExtensionsKt.getSignature(kmFunction);
@@ -55,7 +58,8 @@
assert false;
continue;
}
- KotlinFunctionInfo kotlinFunctionInfo = KotlinFunctionInfo.create(kmFunction, appView);
+ KotlinFunctionInfo kotlinFunctionInfo =
+ KotlinFunctionInfo.create(kmFunction, definitionSupplier, reporter);
DexEncodedMethod method = methodSignatureMap.get(signature.asString());
if (method == null) {
notBackedFunctions.add(kotlinFunctionInfo);
@@ -76,7 +80,8 @@
ImmutableList.Builder<KotlinPropertyInfo> notBackedProperties = ImmutableList.builder();
for (KmProperty kmProperty : container.getProperties()) {
- KotlinPropertyInfo kotlinPropertyInfo = KotlinPropertyInfo.create(kmProperty, appView);
+ KotlinPropertyInfo kotlinPropertyInfo =
+ KotlinPropertyInfo.create(kmProperty, definitionSupplier, reporter);
KmPropertyProcessor propertyProcessor = new KmPropertyProcessor(kmProperty);
boolean hasBacking = false;
if (propertyProcessor.fieldSignature() != null) {
@@ -108,16 +113,16 @@
}
}
return new KotlinDeclarationContainerInfo(
- getTypeAliases(container.getTypeAliases(), appView),
+ getTypeAliases(container.getTypeAliases(), definitionSupplier, reporter),
notBackedFunctions.build(),
notBackedProperties.build());
}
private static List<KotlinTypeAliasInfo> getTypeAliases(
- List<KmTypeAlias> aliases, AppView<?> appView) {
+ List<KmTypeAlias> aliases, DexDefinitionSupplier definitionSupplier, Reporter reporter) {
ImmutableList.Builder<KotlinTypeAliasInfo> builder = ImmutableList.builder();
for (KmTypeAlias alias : aliases) {
- builder.add(KotlinTypeAliasInfo.create(alias, appView));
+ builder.add(KotlinTypeAliasInfo.create(alias, definitionSupplier, reporter));
}
return builder.build();
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
index ee2f81d..ccd957a 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
@@ -6,8 +6,10 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import kotlinx.metadata.KmPackage;
import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
@@ -23,9 +25,12 @@
}
public static KotlinFileFacadeInfo create(
- FileFacade kmFileFacade, DexClass clazz, AppView<?> appView) {
+ FileFacade kmFileFacade,
+ DexClass clazz,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
return new KotlinFileFacadeInfo(
- KotlinPackageInfo.create(kmFileFacade.toKmPackage(), clazz, appView));
+ KotlinPackageInfo.create(kmFileFacade.toKmPackage(), clazz, definitionSupplier, reporter));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
index c1170a1..58b07cb 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
@@ -4,12 +4,15 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.referenceTypeFromBinaryName;
+
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.Reporter;
import java.util.List;
import kotlinx.metadata.KmFunction;
import kotlinx.metadata.KmFunctionVisitor;
@@ -54,24 +57,27 @@
this.lambdaClassOrigin = lambdaClassOrigin;
}
- static KotlinFunctionInfo create(KmFunction kmFunction, AppView<?> appView) {
+ static KotlinFunctionInfo create(
+ KmFunction kmFunction, DexDefinitionSupplier definitionSupplier, Reporter reporter) {
return new KotlinFunctionInfo(
kmFunction.getFlags(),
kmFunction.getName(),
- KotlinTypeInfo.create(kmFunction.getReturnType(), appView),
- KotlinTypeInfo.create(kmFunction.getReceiverParameterType(), appView),
- KotlinValueParameterInfo.create(kmFunction.getValueParameters(), appView),
- KotlinTypeParameterInfo.create(kmFunction.getTypeParameters(), appView),
- KotlinJvmMethodSignatureInfo.create(JvmExtensionsKt.getSignature(kmFunction), appView),
- getlambdaClassOrigin(kmFunction, appView));
+ KotlinTypeInfo.create(kmFunction.getReturnType(), definitionSupplier, reporter),
+ KotlinTypeInfo.create(kmFunction.getReceiverParameterType(), definitionSupplier, reporter),
+ KotlinValueParameterInfo.create(
+ kmFunction.getValueParameters(), definitionSupplier, reporter),
+ KotlinTypeParameterInfo.create(
+ kmFunction.getTypeParameters(), definitionSupplier, reporter),
+ KotlinJvmMethodSignatureInfo.create(
+ JvmExtensionsKt.getSignature(kmFunction), definitionSupplier),
+ getlambdaClassOrigin(kmFunction, definitionSupplier));
}
- private static DexType getlambdaClassOrigin(KmFunction kmFunction, AppView<?> appView) {
+ private static DexType getlambdaClassOrigin(
+ KmFunction kmFunction, DexDefinitionSupplier definitionSupplier) {
String lambdaClassOriginName = JvmExtensionsKt.getLambdaClassOriginName(kmFunction);
if (lambdaClassOriginName != null) {
- return appView
- .dexItemFactory()
- .createType(DescriptorUtils.getDescriptorFromClassBinaryName(lambdaClassOriginName));
+ return referenceTypeFromBinaryName(lambdaClassOriginName, definitionSupplier);
}
return null;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinInfoCollector.java b/src/main/java/com/android/tools/r8/kotlin/KotlinInfoCollector.java
deleted file mode 100644
index 94f9b12..0000000
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinInfoCollector.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2020, 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.kotlin;
-
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.utils.ThreadUtils;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-
-public class KotlinInfoCollector {
- public static void computeKotlinInfoForProgramClasses(
- DexApplication application, AppView<?> appView, ExecutorService executorService)
- throws ExecutionException {
- if (appView.options().kotlinOptimizationOptions().disableKotlinSpecificOptimizations) {
- return;
- }
- Kotlin kotlin = appView.dexItemFactory().kotlin;
- ThreadUtils.processItems(
- application.classes(),
- programClass -> {
- programClass.setKotlinInfo(kotlin.getKotlinInfo(programClass, appView));
- },
- executorService);
- }
-}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
index 0dae9cf..69c0442 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
@@ -4,9 +4,11 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.referenceTypeFromDescriptor;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toRenamedDescriptorOrDefault;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.NamingLens;
@@ -28,12 +30,13 @@
}
public static KotlinJvmFieldSignatureInfo create(
- JvmFieldSignature fieldSignature, AppView<?> appView) {
+ JvmFieldSignature fieldSignature, DexDefinitionSupplier definitionSupplier) {
if (fieldSignature == null) {
return null;
}
return new KotlinJvmFieldSignatureInfo(
- fieldSignature.getName(), appView.dexItemFactory().createType(fieldSignature.getDesc()));
+ fieldSignature.getName(),
+ referenceTypeFromDescriptor(fieldSignature.getDesc(), definitionSupplier));
}
public JvmFieldSignature rewrite(
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
index 354364a..d9d5c9d 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
@@ -4,11 +4,12 @@
package com.android.tools.r8.kotlin;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.referenceTypeFromDescriptor;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toRenamedDescriptorOrDefault;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -36,14 +37,13 @@
}
public static KotlinJvmMethodSignatureInfo create(
- JvmMethodSignature methodSignature, AppView<?> appView) {
+ JvmMethodSignature methodSignature, DexDefinitionSupplier definitionSupplier) {
if (methodSignature == null) {
return null;
}
String kotlinDescriptor = methodSignature.getDesc();
String returnTypeDescriptor = DescriptorUtils.getReturnTypeDescriptor(kotlinDescriptor);
- DexItemFactory factory = appView.dexItemFactory();
- DexType returnType = factory.createType(returnTypeDescriptor);
+ DexType returnType = referenceTypeFromDescriptor(returnTypeDescriptor, definitionSupplier);
String[] descriptors = DescriptorUtils.getArgumentTypeDescriptors(kotlinDescriptor);
if (descriptors.length == 0) {
return new KotlinJvmMethodSignatureInfo(
@@ -51,7 +51,7 @@
}
ImmutableList.Builder<DexType> parameters = ImmutableList.builder();
for (String descriptor : descriptors) {
- parameters.add(factory.createType(descriptor));
+ parameters.add(referenceTypeFromDescriptor(descriptor, definitionSupplier));
}
return new KotlinJvmMethodSignatureInfo(
methodSignature.getName(), returnType, parameters.build());
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
index 107d197..d25f105 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
@@ -8,9 +8,11 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import kotlinx.metadata.KmLambda;
import kotlinx.metadata.KmLambdaVisitor;
import kotlinx.metadata.jvm.JvmExtensionsKt;
@@ -25,7 +27,11 @@
this.function = function;
}
- static KotlinLambdaInfo create(DexClass clazz, KmLambda lambda, AppView<?> appView) {
+ static KotlinLambdaInfo create(
+ DexClass clazz,
+ KmLambda lambda,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
if (lambda == null) {
assert false;
return null;
@@ -37,7 +43,8 @@
}
for (DexEncodedMethod method : clazz.methods()) {
if (toJvmMethodSignature(method.method).asString().equals(signature.asString())) {
- KotlinFunctionInfo kotlinFunctionInfo = KotlinFunctionInfo.create(lambda.function, appView);
+ KotlinFunctionInfo kotlinFunctionInfo =
+ KotlinFunctionInfo.create(lambda.function, definitionSupplier, reporter);
method.setKotlinMemberInfo(kotlinFunctionInfo);
return new KotlinLambdaInfo(kotlinFunctionInfo);
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataEnqueuerExtension.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataEnqueuerExtension.java
new file mode 100644
index 0000000..d280d134
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataEnqueuerExtension.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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.kotlin;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.analysis.EnqueuerAnalysis;
+import com.android.tools.r8.shaking.EnqueuerWorklist;
+
+public class KotlinMetadataEnqueuerExtension extends EnqueuerAnalysis {
+
+ private final AppView<?> appView;
+
+ public KotlinMetadataEnqueuerExtension(AppView<?> appView) {
+ this.appView = appView;
+ }
+
+ @Override
+ public void processNewlyLiveClass(
+ DexProgramClass clazz, EnqueuerWorklist worklist, DexDefinitionSupplier definitionSupplier) {
+ Kotlin kotlin = appView.dexItemFactory().kotlin;
+ clazz.setKotlinInfo(
+ KotlinClassMetadataReader.getKotlinInfo(
+ kotlin, clazz, definitionSupplier, appView.options().reporter));
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
index b3e0eb4..b3c167f 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
@@ -67,8 +67,6 @@
}
public void run(ExecutorService executorService) throws ExecutionException {
- // TODO(b/152283077): Don't disable the assert.
- appView.appInfo().disableDefinitionForAssert();
ThreadUtils.processItems(
appView.appInfo().classes(),
clazz -> {
@@ -95,7 +93,6 @@
}
},
executorService);
- appView.appInfo().enableDefinitionForAssert();
}
private DexAnnotation createKotlinMetadataAnnotation(KotlinClassHeader header) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
index 277201c..fb173a2 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
@@ -132,4 +133,20 @@
static String kotlinNameFromDescriptor(DexString descriptor) {
return DescriptorUtils.getBinaryNameFromDescriptor(descriptor.toString());
}
+
+ static DexType referenceTypeFromBinaryName(
+ String binaryName, DexDefinitionSupplier definitionSupplier) {
+ return referenceTypeFromDescriptor(
+ DescriptorUtils.getDescriptorFromClassBinaryName(binaryName), definitionSupplier);
+ }
+
+ static DexType referenceTypeFromDescriptor(
+ String descriptor, DexDefinitionSupplier definitionSupplier) {
+ DexType type = definitionSupplier.dexItemFactory().createType(descriptor);
+ // Lookup the definition, ignoring the result. This populates the sets in the Enqueuer.
+ if (type.isClassType()) {
+ definitionSupplier.definitionFor(type);
+ }
+ return type;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
index 02efea2..7eaa6b8 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.NamingLens;
@@ -28,7 +29,7 @@
}
static KotlinMultiFileClassFacadeInfo create(
- MultiFileClassFacade kmMultiFileClassFacade, AppView<?> appView) {
+ MultiFileClassFacade kmMultiFileClassFacade, DexDefinitionSupplier appView) {
ImmutableList.Builder<DexType> builder = ImmutableList.builder();
for (String partClassName : kmMultiFileClassFacade.getPartClassNames()) {
String descriptor = DescriptorUtils.getDescriptorFromClassBinaryName(partClassName);
@@ -55,7 +56,7 @@
new KotlinClassMetadata.MultiFileClassFacade.Writer();
List<String> partClassNameStrings = new ArrayList<>(partClassNames.size());
for (DexType partClassName : partClassNames) {
- if (appView.definitionFor(partClassName) != null) {
+ if (appView.appInfo().isNonProgramTypeOrLiveProgramType(partClassName)) {
DexString descriptor = namingLens.lookupDescriptor(partClassName);
String classifier = DescriptorUtils.descriptorToKotlinClassifier(descriptor.toString());
partClassNameStrings.add(classifier);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
index 69ea8e4..6a06b7d 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
@@ -6,8 +6,10 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import kotlinx.metadata.KmPackage;
import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
@@ -25,10 +27,13 @@
}
static KotlinMultiFileClassPartInfo create(
- MultiFileClassPart classPart, DexClass clazz, AppView<?> appView) {
+ MultiFileClassPart classPart,
+ DexClass clazz,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
return new KotlinMultiFileClassPartInfo(
classPart.getFacadeClassName(),
- KotlinPackageInfo.create(classPart.toKmPackage(), clazz, appView));
+ KotlinPackageInfo.create(classPart.toKmPackage(), clazz, definitionSupplier, reporter));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
index c90d673..7a667e6 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
@@ -9,10 +9,12 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import java.util.HashMap;
import java.util.Map;
import kotlinx.metadata.KmPackage;
@@ -29,7 +31,11 @@
this.containerInfo = containerInfo;
}
- public static KotlinPackageInfo create(KmPackage kmPackage, DexClass clazz, AppView<?> appView) {
+ public static KotlinPackageInfo create(
+ KmPackage kmPackage,
+ DexClass clazz,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
Map<String, DexEncodedField> fieldMap = new HashMap<>();
for (DexEncodedField field : clazz.fields()) {
fieldMap.put(toJvmFieldSignature(field.field).asString(), field);
@@ -40,7 +46,8 @@
}
return new KotlinPackageInfo(
JvmExtensionsKt.getModuleName(kmPackage),
- KotlinDeclarationContainerInfo.create(kmPackage, methodMap, fieldMap, appView));
+ KotlinDeclarationContainerInfo.create(
+ kmPackage, methodMap, fieldMap, definitionSupplier, reporter));
}
public void rewrite(
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
index a94b6fc..802428a 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
@@ -5,10 +5,12 @@
package com.android.tools.r8.kotlin;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import java.util.List;
import kotlinx.metadata.KmProperty;
import kotlinx.metadata.KmPropertyVisitor;
@@ -19,35 +21,35 @@
public class KotlinPropertyInfo implements KotlinFieldLevelInfo, KotlinMethodLevelInfo {
// Original flags.
- final int flags;
+ private final int flags;
// Original getter flags. E.g., for property getter.
- final int getterFlags;
+ private final int getterFlags;
// Original setter flags. E.g., for property setter.
- final int setterFlags;
+ private final int setterFlags;
// Original property name for (extension) property. Otherwise, null.
- final String name;
+ private final String name;
// Original return type information. This should never be NULL (even for setters without field).
- final KotlinTypeInfo returnType;
+ private final KotlinTypeInfo returnType;
- final KotlinTypeInfo receiverParameterType;
+ private final KotlinTypeInfo receiverParameterType;
- final KotlinValueParameterInfo setterParameter;
+ private final KotlinValueParameterInfo setterParameter;
- final List<KotlinTypeParameterInfo> typeParameters;
+ private final List<KotlinTypeParameterInfo> typeParameters;
- final int jvmFlags;
+ private final int jvmFlags;
- final KotlinJvmFieldSignatureInfo fieldSignature;
+ private final KotlinJvmFieldSignatureInfo fieldSignature;
- final KotlinJvmMethodSignatureInfo getterSignature;
+ private final KotlinJvmMethodSignatureInfo getterSignature;
- final KotlinJvmMethodSignatureInfo setterSignature;
+ private final KotlinJvmMethodSignatureInfo setterSignature;
- final KotlinJvmMethodSignatureInfo syntheticMethodForAnnotations;
+ private final KotlinJvmMethodSignatureInfo syntheticMethodForAnnotations;
private KotlinPropertyInfo(
int flags,
@@ -78,24 +80,28 @@
this.syntheticMethodForAnnotations = syntheticMethodForAnnotations;
}
- public static KotlinPropertyInfo create(KmProperty kmProperty, AppView<?> appView) {
+ public static KotlinPropertyInfo create(
+ KmProperty kmProperty, DexDefinitionSupplier definitionSupplier, Reporter reporter) {
return new KotlinPropertyInfo(
kmProperty.getFlags(),
kmProperty.getGetterFlags(),
kmProperty.getSetterFlags(),
kmProperty.getName(),
- KotlinTypeInfo.create(kmProperty.getReturnType(), appView),
- KotlinTypeInfo.create(kmProperty.getReceiverParameterType(), appView),
- KotlinValueParameterInfo.create(kmProperty.getSetterParameter(), appView),
- KotlinTypeParameterInfo.create(kmProperty.getTypeParameters(), appView),
+ KotlinTypeInfo.create(kmProperty.getReturnType(), definitionSupplier, reporter),
+ KotlinTypeInfo.create(kmProperty.getReceiverParameterType(), definitionSupplier, reporter),
+ KotlinValueParameterInfo.create(
+ kmProperty.getSetterParameter(), definitionSupplier, reporter),
+ KotlinTypeParameterInfo.create(
+ kmProperty.getTypeParameters(), definitionSupplier, reporter),
JvmExtensionsKt.getJvmFlags(kmProperty),
- KotlinJvmFieldSignatureInfo.create(JvmExtensionsKt.getFieldSignature(kmProperty), appView),
+ KotlinJvmFieldSignatureInfo.create(
+ JvmExtensionsKt.getFieldSignature(kmProperty), definitionSupplier),
KotlinJvmMethodSignatureInfo.create(
- JvmExtensionsKt.getGetterSignature(kmProperty), appView),
+ JvmExtensionsKt.getGetterSignature(kmProperty), definitionSupplier),
KotlinJvmMethodSignatureInfo.create(
- JvmExtensionsKt.getSetterSignature(kmProperty), appView),
+ JvmExtensionsKt.getSetterSignature(kmProperty), definitionSupplier),
KotlinJvmMethodSignatureInfo.create(
- JvmExtensionsKt.getSyntheticMethodForAnnotations(kmProperty), appView));
+ JvmExtensionsKt.getSyntheticMethodForAnnotations(kmProperty), definitionSupplier));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
index 8dfe761..cc11647 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
@@ -6,8 +6,10 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import kotlinx.metadata.InconsistentKotlinMetadataException;
import kotlinx.metadata.KmLambda;
import kotlinx.metadata.jvm.KotlinClassHeader;
@@ -34,7 +36,11 @@
}
static KotlinSyntheticClassInfo create(
- SyntheticClass syntheticClass, DexClass clazz, Kotlin kotlin, AppView<?> appView) {
+ SyntheticClass syntheticClass,
+ DexClass clazz,
+ Kotlin kotlin,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
KmLambda lambda = null;
if (syntheticClass.isLambda()) {
try {
@@ -45,7 +51,9 @@
}
}
return new KotlinSyntheticClassInfo(
- lambda != null ? KotlinLambdaInfo.create(clazz, lambda, appView) : null,
+ lambda != null
+ ? KotlinLambdaInfo.create(clazz, lambda, definitionSupplier, reporter)
+ : null,
getFlavour(syntheticClass, clazz, kotlin));
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
index 974469c..b4b5354 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
@@ -5,8 +5,10 @@
package com.android.tools.r8.kotlin;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import java.util.List;
import kotlinx.metadata.KmTypeAlias;
import kotlinx.metadata.KmTypeAliasVisitor;
@@ -38,14 +40,15 @@
this.annotations = annotations;
}
- public static KotlinTypeAliasInfo create(KmTypeAlias alias, AppView<?> appView) {
+ public static KotlinTypeAliasInfo create(
+ KmTypeAlias alias, DexDefinitionSupplier definitionSupplier, Reporter reporter) {
return new KotlinTypeAliasInfo(
alias.getFlags(),
alias.getName(),
- KotlinTypeInfo.create(alias.underlyingType, appView),
- KotlinTypeInfo.create(alias.expandedType, appView),
- KotlinTypeParameterInfo.create(alias.getTypeParameters(), appView),
- KotlinAnnotationInfo.create(alias.getAnnotations(), appView));
+ KotlinTypeInfo.create(alias.underlyingType, definitionSupplier, reporter),
+ KotlinTypeInfo.create(alias.expandedType, definitionSupplier, reporter),
+ KotlinTypeParameterInfo.create(alias.getTypeParameters(), definitionSupplier, reporter),
+ KotlinAnnotationInfo.create(alias.getAnnotations(), definitionSupplier));
}
void rewrite(
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
index f00a544..204bcbb 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
@@ -5,8 +5,10 @@
package com.android.tools.r8.kotlin;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.List;
import kotlinx.metadata.KmType;
@@ -47,27 +49,30 @@
return arguments;
}
- static KotlinTypeInfo create(KmType kmType, AppView<?> appView) {
+ static KotlinTypeInfo create(
+ KmType kmType, DexDefinitionSupplier definitionSupplier, Reporter reporter) {
if (kmType == null) {
return null;
}
return new KotlinTypeInfo(
kmType.getFlags(),
- KotlinClassifierInfo.create(kmType.classifier, appView),
- KotlinTypeInfo.create(kmType.getAbbreviatedType(), appView),
- KotlinTypeInfo.create(kmType.getOuterType(), appView),
- getArguments(kmType.getArguments(), appView),
- KotlinAnnotationInfo.create(JvmExtensionsKt.getAnnotations(kmType), appView));
+ KotlinClassifierInfo.create(kmType.classifier, definitionSupplier, reporter),
+ KotlinTypeInfo.create(kmType.getAbbreviatedType(), definitionSupplier, reporter),
+ KotlinTypeInfo.create(kmType.getOuterType(), definitionSupplier, reporter),
+ getArguments(kmType.getArguments(), definitionSupplier, reporter),
+ KotlinAnnotationInfo.create(JvmExtensionsKt.getAnnotations(kmType), definitionSupplier));
}
private static List<KotlinTypeProjectionInfo> getArguments(
- List<KmTypeProjection> projections, AppView<?> appView) {
+ List<KmTypeProjection> projections,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
if (projections.isEmpty()) {
return EMPTY_ARGUMENTS;
}
ImmutableList.Builder<KotlinTypeProjectionInfo> arguments = ImmutableList.builder();
for (KmTypeProjection projection : projections) {
- arguments.add(KotlinTypeProjectionInfo.create(projection, appView));
+ arguments.add(KotlinTypeProjectionInfo.create(projection, definitionSupplier, reporter));
}
return arguments.build();
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
index e79ea83..fd11c11 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
@@ -5,8 +5,10 @@
package com.android.tools.r8.kotlin;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.List;
import kotlinx.metadata.KmType;
@@ -45,35 +47,41 @@
}
private static KotlinTypeParameterInfo create(
- KmTypeParameter kmTypeParameter, AppView<?> appView) {
+ KmTypeParameter kmTypeParameter,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
return new KotlinTypeParameterInfo(
kmTypeParameter.getFlags(),
kmTypeParameter.getId(),
kmTypeParameter.getName(),
kmTypeParameter.getVariance(),
- getUpperBounds(kmTypeParameter.getUpperBounds(), appView),
- KotlinAnnotationInfo.create(JvmExtensionsKt.getAnnotations(kmTypeParameter), appView));
+ getUpperBounds(kmTypeParameter.getUpperBounds(), definitionSupplier, reporter),
+ KotlinAnnotationInfo.create(
+ JvmExtensionsKt.getAnnotations(kmTypeParameter), definitionSupplier));
}
static List<KotlinTypeParameterInfo> create(
- List<KmTypeParameter> kmTypeParameters, AppView<?> appView) {
+ List<KmTypeParameter> kmTypeParameters,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
if (kmTypeParameters.isEmpty()) {
return EMPTY_TYPE_PARAMETERS;
}
ImmutableList.Builder<KotlinTypeParameterInfo> builder = ImmutableList.builder();
for (KmTypeParameter kmTypeParameter : kmTypeParameters) {
- builder.add(create(kmTypeParameter, appView));
+ builder.add(create(kmTypeParameter, definitionSupplier, reporter));
}
return builder.build();
}
- private static List<KotlinTypeInfo> getUpperBounds(List<KmType> upperBounds, AppView<?> appView) {
+ private static List<KotlinTypeInfo> getUpperBounds(
+ List<KmType> upperBounds, DexDefinitionSupplier definitionSupplier, Reporter reporter) {
if (upperBounds.isEmpty()) {
return EMPTY_UPPER_BOUNDS;
}
ImmutableList.Builder<KotlinTypeInfo> builder = ImmutableList.builder();
for (KmType upperBound : upperBounds) {
- builder.add(KotlinTypeInfo.create(upperBound, appView));
+ builder.add(KotlinTypeInfo.create(upperBound, definitionSupplier, reporter));
}
return builder.build();
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
index 9ab8adc..68da5db 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
@@ -5,8 +5,10 @@
package com.android.tools.r8.kotlin;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import kotlinx.metadata.KmTypeProjection;
import kotlinx.metadata.KmVariance;
@@ -21,9 +23,13 @@
this.typeInfo = typeInfo;
}
- static KotlinTypeProjectionInfo create(KmTypeProjection kmTypeProjection, AppView<?> appView) {
+ static KotlinTypeProjectionInfo create(
+ KmTypeProjection kmTypeProjection,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
return new KotlinTypeProjectionInfo(
- kmTypeProjection.getVariance(), KotlinTypeInfo.create(kmTypeProjection.getType(), appView));
+ kmTypeProjection.getVariance(),
+ KotlinTypeInfo.create(kmTypeProjection.getType(), definitionSupplier, reporter));
}
private boolean isStarProjection() {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
index d092495..ee2f99b 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
@@ -5,8 +5,10 @@
package com.android.tools.r8.kotlin;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.List;
import kotlinx.metadata.KmType;
@@ -33,7 +35,10 @@
this.varargElementType = varargElementType;
}
- static KotlinValueParameterInfo create(KmValueParameter kmValueParameter, AppView<?> appView) {
+ static KotlinValueParameterInfo create(
+ KmValueParameter kmValueParameter,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
if (kmValueParameter == null) {
return null;
}
@@ -41,18 +46,21 @@
return new KotlinValueParameterInfo(
kmValueParameter.getFlags(),
kmValueParameter.getName(),
- KotlinTypeInfo.create(kmType, appView),
- KotlinTypeInfo.create(kmValueParameter.getVarargElementType(), appView));
+ KotlinTypeInfo.create(kmType, definitionSupplier, reporter),
+ KotlinTypeInfo.create(
+ kmValueParameter.getVarargElementType(), definitionSupplier, reporter));
}
static List<KotlinValueParameterInfo> create(
- List<KmValueParameter> parameters, AppView<?> appView) {
+ List<KmValueParameter> parameters,
+ DexDefinitionSupplier definitionSupplier,
+ Reporter reporter) {
if (parameters.isEmpty()) {
return EMPTY_VALUE_PARAMETERS;
}
ImmutableList.Builder<KotlinValueParameterInfo> builder = ImmutableList.builder();
for (KmValueParameter parameter : parameters) {
- builder.add(create(parameter, appView));
+ builder.add(create(parameter, definitionSupplier, reporter));
}
return builder.build();
}
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index c57a91a..8cffa05 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -271,7 +271,7 @@
if (holder == null || holder.isNotProgramClass()) {
return;
}
- definition = appView.appInfo().resolveField(field);
+ definition = appView.appInfo().resolveField(field).getResolvedField();
if (definition == null) {
// The program is already broken in the sense that it has an unresolvable field reference.
// Leave it as-is.
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNamingState.java b/src/main/java/com/android/tools/r8/naming/FieldNamingState.java
index 6652d4a..f8d80cb 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNamingState.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNamingState.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.naming;
-
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
@@ -22,17 +22,20 @@
private final MemberNamingStrategy strategy;
private final BiPredicate<DexString, DexField> isAvailable;
- public FieldNamingState(AppView<?> appView, MemberNamingStrategy strategy) {
+ public FieldNamingState(
+ AppView<? extends AppInfoWithClassHierarchy> appView, MemberNamingStrategy strategy) {
this(appView, strategy, new ReservedFieldNamingState(appView));
}
public FieldNamingState(
- AppView<?> appView, MemberNamingStrategy strategy, ReservedFieldNamingState reservedNames) {
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ MemberNamingStrategy strategy,
+ ReservedFieldNamingState reservedNames) {
this(appView, strategy, reservedNames, new IdentityHashMap<>());
}
private FieldNamingState(
- AppView<?> appView,
+ AppView<? extends AppInfoWithClassHierarchy> appView,
MemberNamingStrategy strategy,
ReservedFieldNamingState reservedNames,
Map<DexType, InternalState> internalStates) {
@@ -50,7 +53,7 @@
}
public DexString getOrCreateNameFor(DexField field) {
- DexEncodedField encodedField = appView.appInfo().resolveField(field);
+ DexEncodedField encodedField = appView.appInfo().resolveField(field).getResolvedField();
if (encodedField != null) {
DexClass clazz = appView.definitionFor(encodedField.holder());
if (clazz == null) {
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNamingStateBase.java b/src/main/java/com/android/tools/r8/naming/FieldNamingStateBase.java
index 8fbcfcd..693f373 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNamingStateBase.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNamingStateBase.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.naming;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
@@ -12,10 +13,11 @@
abstract class FieldNamingStateBase<T> {
- final AppView<?> appView;
+ final AppView<? extends AppInfoWithClassHierarchy> appView;
final Map<DexType, T> internalStates;
- FieldNamingStateBase(AppView<?> appView, Map<DexType, T> internalStates) {
+ FieldNamingStateBase(
+ AppView<? extends AppInfoWithClassHierarchy> appView, Map<DexType, T> internalStates) {
this.appView = appView;
this.internalStates = internalStates;
}
diff --git a/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java b/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
index f789fe4..d133c3f 100644
--- a/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
+++ b/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.naming;
-
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -32,12 +32,12 @@
class MinifiedRenaming extends NamingLens {
- final AppView<?> appView;
+ final AppView<? extends AppInfoWithClassHierarchy> appView;
private final Map<String, String> packageRenaming;
private final Map<DexItem, DexString> renaming = new IdentityHashMap<>();
MinifiedRenaming(
- AppView<?> appView,
+ AppView<? extends AppInfoWithClassHierarchy> appView,
ClassRenaming classRenaming,
MethodRenaming methodRenaming,
FieldRenaming fieldRenaming) {
@@ -99,7 +99,7 @@
return renamed;
}
// If the method does not have a direct renaming, return the resolutions mapping.
- ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appView.appInfo().unsafeResolveMethodDueToDexFormat(method);
if (resolutionResult.isSingleResolution()) {
return renaming.getOrDefault(resolutionResult.getSingleTarget().method, method.name);
}
@@ -166,7 +166,7 @@
return true;
}
- ResolutionResult resolution = appView.appInfo().resolveMethod(method.holder, method);
+ ResolutionResult resolution = appView.appInfo().unsafeResolveMethodDueToDexFormat(method);
assert resolution != null;
if (resolution.isSingleResolution()) {
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
index 5e23d98..ab735ca 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.naming;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinition;
@@ -583,7 +584,7 @@
private final Map<DexString, DexType> classRenamingsMappingToDifferentName;
ProguardMapMinifiedRenaming(
- AppView<?> appView,
+ AppView<? extends AppInfoWithClassHierarchy> appView,
ClassRenaming classRenaming,
MethodRenaming methodRenaming,
FieldRenaming fieldRenaming,
diff --git a/src/main/java/com/android/tools/r8/naming/ReservedFieldNamingState.java b/src/main/java/com/android/tools/r8/naming/ReservedFieldNamingState.java
index 9a0051b..4e3e98c 100644
--- a/src/main/java/com/android/tools/r8/naming/ReservedFieldNamingState.java
+++ b/src/main/java/com/android/tools/r8/naming/ReservedFieldNamingState.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.naming;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
@@ -13,7 +14,7 @@
class ReservedFieldNamingState extends FieldNamingStateBase<InternalState> {
- ReservedFieldNamingState(AppView<?> appView) {
+ ReservedFieldNamingState(AppView<? extends AppInfoWithClassHierarchy> appView) {
super(appView, new IdentityHashMap<>());
}
diff --git a/src/main/java/com/android/tools/r8/optimize/BridgeHoisting.java b/src/main/java/com/android/tools/r8/optimize/BridgeHoisting.java
index 8e5c3c3..1cdeec3 100644
--- a/src/main/java/com/android/tools/r8/optimize/BridgeHoisting.java
+++ b/src/main/java/com/android/tools/r8/optimize/BridgeHoisting.java
@@ -157,7 +157,7 @@
DexEncodedMethod definition = subclass.lookupVirtualMethod(method);
if (definition == null) {
DexEncodedMethod resolutionTarget =
- appView.appInfo().resolveMethodOnClass(subclass, method).getSingleTarget();
+ appView.appInfo().resolveMethodOnClass(method, subclass).getSingleTarget();
if (resolutionTarget == null || resolutionTarget.isAbstract()) {
// The fact that this class does not declare the bridge (or the bridge is abstract) should
// not prevent us from hoisting the bridge.
diff --git a/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java b/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java
index 8315925..5da8e5f 100644
--- a/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/ClassAndMemberPublicizer.java
@@ -6,11 +6,13 @@
import static com.android.tools.r8.dex.Constants.ACC_PRIVATE;
import static com.android.tools.r8.dex.Constants.ACC_PROTECTED;
import static com.android.tools.r8.dex.Constants.ACC_PUBLIC;
+import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.InnerClassAttribute;
@@ -82,43 +84,69 @@
}
private void publicizeType(DexType type) {
- DexClass clazz = application.definitionFor(type);
- if (clazz != null && clazz.isProgramClass()) {
- clazz.accessFlags.promoteToPublic();
-
- // Publicize fields.
- clazz.forEachField(field -> field.accessFlags.promoteToPublic());
-
- // Publicize methods.
- Set<DexEncodedMethod> privateInstanceEncodedMethods = new LinkedHashSet<>();
- clazz.forEachMethod(encodedMethod -> {
- if (publicizeMethod(clazz, encodedMethod)) {
- privateInstanceEncodedMethods.add(encodedMethod);
- }
- });
- if (!privateInstanceEncodedMethods.isEmpty()) {
- clazz.virtualizeMethods(privateInstanceEncodedMethods);
- }
-
- // Publicize inner class attribute.
- InnerClassAttribute attr = clazz.getInnerClassAttributeForThisClass();
- if (attr != null) {
- int accessFlags = ((attr.getAccess() | ACC_PUBLIC) & ~ACC_PRIVATE) & ~ACC_PROTECTED;
- clazz.replaceInnerClassAttributeForThisClass(
- new InnerClassAttribute(
- accessFlags, attr.getInner(), attr.getOuter(), attr.getInnerName()));
- }
+ DexProgramClass clazz = asProgramClassOrNull(application.definitionFor(type));
+ if (clazz != null) {
+ publicizeClass(clazz);
}
-
subtypingInfo.forAllImmediateExtendsSubtypes(type, this::publicizeType);
}
- private boolean publicizeMethod(DexClass holder, DexEncodedMethod encodedMethod) {
- MethodAccessFlags accessFlags = encodedMethod.accessFlags;
+ private void publicizeClass(DexProgramClass clazz) {
+ clazz.accessFlags.promoteToPublic();
+
+ // Publicize fields.
+ clazz.forEachField(
+ field -> {
+ if (field.isPublic()) {
+ return;
+ }
+ if (appView.appInfo().isPinned(field.field)) {
+ // TODO(b/131130038): Also do not publicize package-private and protected fields that
+ // are kept.
+ if (field.isPrivate()) {
+ return;
+ }
+ }
+ field.accessFlags.promoteToPublic();
+ });
+
+ // Publicize methods.
+ Set<DexEncodedMethod> privateInstanceMethods = new LinkedHashSet<>();
+ clazz.forEachMethod(
+ method -> {
+ if (publicizeMethod(clazz, method)) {
+ privateInstanceMethods.add(method);
+ }
+ });
+ if (!privateInstanceMethods.isEmpty()) {
+ clazz.virtualizeMethods(privateInstanceMethods);
+ }
+
+ // Publicize inner class attribute.
+ InnerClassAttribute attr = clazz.getInnerClassAttributeForThisClass();
+ if (attr != null) {
+ int accessFlags = ((attr.getAccess() | ACC_PUBLIC) & ~ACC_PRIVATE) & ~ACC_PROTECTED;
+ clazz.replaceInnerClassAttributeForThisClass(
+ new InnerClassAttribute(
+ accessFlags, attr.getInner(), attr.getOuter(), attr.getInnerName()));
+ }
+ }
+
+ private boolean publicizeMethod(DexProgramClass holder, DexEncodedMethod method) {
+ MethodAccessFlags accessFlags = method.accessFlags;
if (accessFlags.isPublic()) {
return false;
}
- if (!accessFlags.isPrivate() || appView.dexItemFactory().isConstructor(encodedMethod.method)) {
+ // If this method is mentioned in keep rules, do not transform (rule applications changed).
+ if (appView.appInfo().isPinned(method.method)) {
+ // TODO(b/131130038): Also do not publicize package-private and protected methods that are
+ // kept.
+ if (method.isPrivate()) {
+ return false;
+ }
+ }
+
+ if (!accessFlags.isPrivate() || appView.dexItemFactory().isConstructor(method.method)) {
// TODO(b/150589374): This should check for dispatch targets or just abandon in
// package-private.
accessFlags.promoteToPublic();
@@ -126,10 +154,6 @@
}
if (!accessFlags.isStatic()) {
- // If this method is mentioned in keep rules, do not transform (rule applications changed).
- if (appView.appInfo().isPinned(encodedMethod.method)) {
- return false;
- }
// We can't publicize private instance methods in interfaces or methods that are copied from
// interfaces to lambda-desugared classes because this will be added as a new default method.
@@ -138,20 +162,20 @@
return false;
}
- boolean wasSeen = methodPoolCollection.markIfNotSeen(holder, encodedMethod.method);
+ boolean wasSeen = methodPoolCollection.markIfNotSeen(holder, method.method);
if (wasSeen) {
// We can't do anything further because even renaming is not allowed due to the keep rule.
- if (appView.rootSet().mayNotBeMinified(encodedMethod.method, appView)) {
+ if (appView.rootSet().mayNotBeMinified(method.method, appView)) {
return false;
}
// TODO(b/111118390): Renaming will enable more private instance methods to be publicized.
return false;
}
- lenseBuilder.add(encodedMethod.method);
+ lenseBuilder.add(method.method);
accessFlags.promoteToFinal();
accessFlags.promoteToPublic();
// The method just became public and is therefore not a library override.
- encodedMethod.setLibraryMethodOverride(OptionalBool.FALSE);
+ method.setLibraryMethodOverride(OptionalBool.FALSE);
return true;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 42e03e0..a3e4666 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -15,12 +15,13 @@
import com.android.tools.r8.graph.FieldAccessInfo;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.Map;
-import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
@@ -114,7 +115,7 @@
}
private DexEncodedMethod classLookup(DexMethod method) {
- return appView.appInfo().resolveMethodOnClass(method.holder, method).getSingleTarget();
+ return appView.appInfo().resolveMethodOnClass(method, method.holder).getSingleTarget();
}
private DexEncodedMethod interfaceLookup(DexMethod method) {
@@ -122,11 +123,11 @@
}
private DexEncodedMethod anyLookup(DexMethod method) {
- return appView.appInfo().resolveMethod(method.holder, method).getSingleTarget();
+ return appView.appInfo().unsafeResolveMethodDueToDexFormat(method).getSingleTarget();
}
private void computeMethodRebinding(
- Map<DexMethod, Set<DexEncodedMethod>> methodsWithContexts,
+ Map<DexMethod, ProgramMethodSet> methodsWithContexts,
Function<DexMethod, DexEncodedMethod> lookupTarget,
Type invokeType) {
for (DexMethod method : methodsWithContexts.keySet()) {
@@ -158,9 +159,9 @@
// If the target class is not public but the targeted method is, we might run into
// visibility problems when rebinding.
final DexEncodedMethod finalTarget = target;
- Set<DexEncodedMethod> contexts = methodsWithContexts.get(method);
+ ProgramMethodSet contexts = methodsWithContexts.get(method);
if (contexts.stream()
- .anyMatch(context -> mayNeedBridgeForVisibility(context.holder(), finalTarget))) {
+ .anyMatch(context -> mayNeedBridgeForVisibility(context, finalTarget))) {
target =
insertBridgeForVisibilityIfNeeded(
method, target, originalClass, targetClass, lookupTarget);
@@ -216,16 +217,18 @@
return findHolderForInterfaceMethodBridge(superClass.asProgramClass(), iface);
}
- private boolean mayNeedBridgeForVisibility(DexType context, DexEncodedMethod method) {
+ private boolean mayNeedBridgeForVisibility(ProgramMethod context, DexEncodedMethod method) {
DexType holderType = method.holder();
DexClass holder = appView.definitionFor(holderType);
if (holder == null) {
return false;
}
ConstraintWithTarget classVisibility =
- ConstraintWithTarget.deriveConstraint(context, holderType, holder.accessFlags, appView);
+ ConstraintWithTarget.deriveConstraint(
+ context.getHolder(), holderType, holder.accessFlags, appView);
ConstraintWithTarget methodVisibility =
- ConstraintWithTarget.deriveConstraint(context, holderType, method.accessFlags, appView);
+ ConstraintWithTarget.deriveConstraint(
+ context.getHolder(), holderType, method.accessFlags, appView);
// We may need bridge for visibility if the target class is not visible while the target method
// is visible from the calling context.
return classVisibility == ConstraintWithTarget.NEVER
@@ -297,8 +300,8 @@
}
private void computeFieldRebindingForIndirectAccessWithContexts(
- DexField field, Set<DexEncodedMethod> contexts) {
- DexEncodedField target = appView.appInfo().resolveField(field);
+ DexField field, ProgramMethodSet contexts) {
+ DexEncodedField target = appView.appInfo().resolveField(field).getResolvedField();
if (target == null) {
assert false;
return;
@@ -315,14 +318,14 @@
.allMatch(
context ->
isMemberVisibleFromOriginalContext(
- appView, context.holder(), target.holder(), target.accessFlags))) {
+ appView, context, target.holder(), target.accessFlags))) {
builder.map(
field, lense.lookupField(validTargetFor(target.field, field, DexClass::lookupField)));
}
}
public static boolean isTypeVisibleFromContext(
- AppView<?> appView, DexType context, DexType type) {
+ AppView<?> appView, ProgramMethod context, DexType type) {
DexType baseType = type.toBaseType(appView.dexItemFactory());
if (baseType.isPrimitiveType()) {
return true;
@@ -331,26 +334,28 @@
}
public static boolean isClassTypeVisibleFromContext(
- AppView<?> appView, DexType context, DexType type) {
+ AppView<?> appView, ProgramMethod context, DexType type) {
assert type.isClassType();
DexClass clazz = appView.definitionFor(type);
return clazz != null && isClassTypeVisibleFromContext(appView, context, clazz);
}
public static boolean isClassTypeVisibleFromContext(
- AppView<?> appView, DexType context, DexClass clazz) {
+ AppView<?> appView, ProgramMethod context, DexClass clazz) {
ConstraintWithTarget classVisibility =
- ConstraintWithTarget.deriveConstraint(context, clazz.type, clazz.accessFlags, appView);
+ ConstraintWithTarget.deriveConstraint(
+ context.getHolder(), clazz.type, clazz.accessFlags, appView);
return classVisibility != ConstraintWithTarget.NEVER;
}
public static boolean isMemberVisibleFromOriginalContext(
- AppView<?> appView, DexType context, DexType holder, AccessFlags<?> memberAccessFlags) {
+ AppView<?> appView, ProgramMethod context, DexType holder, AccessFlags<?> memberAccessFlags) {
if (!isClassTypeVisibleFromContext(appView, context, holder)) {
return false;
}
ConstraintWithTarget memberVisibility =
- ConstraintWithTarget.deriveConstraint(context, holder, memberAccessFlags, appView);
+ ConstraintWithTarget.deriveConstraint(
+ context.getHolder(), holder, memberAccessFlags, appView);
return memberVisibility != ConstraintWithTarget.NEVER;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
index 45892a2..96dd07b 100644
--- a/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/VisibilityBridgeRemover.java
@@ -83,7 +83,7 @@
if (kind == InvokeKind.SUPER) {
// This is a visibility forward, so check for the direct target.
DexEncodedMethod targetMethod =
- appView.appInfo().resolveMethod(target.holder, target).getSingleTarget();
+ appView.appInfo().unsafeResolveMethodDueToDexFormat(target).getSingleTarget();
if (targetMethod != null && targetMethod.accessFlags.isPublic()) {
if (Log.ENABLED) {
Log.info(
diff --git a/src/main/java/com/android/tools/r8/relocator/Relocator.java b/src/main/java/com/android/tools/r8/relocator/Relocator.java
index a4caad6..aaf83b1 100644
--- a/src/main/java/com/android/tools/r8/relocator/Relocator.java
+++ b/src/main/java/com/android/tools/r8/relocator/Relocator.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppServices;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
@@ -81,7 +80,7 @@
try {
DexApplication app = new ApplicationReader(inputApp, options, timing).read(executor);
- AppInfo appInfo = new AppInfoWithClassHierarchy(app);
+ AppInfo appInfo = new AppInfo(app);
AppView<?> appView = AppView.createForRelocator(appInfo, options);
appView.setAppServices(AppServices.builder(appView).build());
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 77edcc6..308cf69 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -50,6 +50,7 @@
import com.android.tools.r8.utils.PredicateSet;
import com.android.tools.r8.utils.TraversalContinuation;
import com.android.tools.r8.utils.Visibility;
+import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.ImmutableSortedSet.Builder;
@@ -121,15 +122,15 @@
/** Information about instantiated classes and their allocation sites. */
private final ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection;
/** Set of all methods referenced in virtual invokes, along with calling context. */
- public final SortedMap<DexMethod, Set<DexEncodedMethod>> virtualInvokes;
+ public final SortedMap<DexMethod, ProgramMethodSet> virtualInvokes;
/** Set of all methods referenced in interface invokes, along with calling context. */
- public final SortedMap<DexMethod, Set<DexEncodedMethod>> interfaceInvokes;
+ public final SortedMap<DexMethod, ProgramMethodSet> interfaceInvokes;
/** Set of all methods referenced in super invokes, along with calling context. */
- public final SortedMap<DexMethod, Set<DexEncodedMethod>> superInvokes;
+ public final SortedMap<DexMethod, ProgramMethodSet> superInvokes;
/** Set of all methods referenced in direct invokes, along with calling context. */
- public final SortedMap<DexMethod, Set<DexEncodedMethod>> directInvokes;
+ public final SortedMap<DexMethod, ProgramMethodSet> directInvokes;
/** Set of all methods referenced in static invokes, along with calling context. */
- public final SortedMap<DexMethod, Set<DexEncodedMethod>> staticInvokes;
+ public final SortedMap<DexMethod, ProgramMethodSet> staticInvokes;
/**
* Set of live call sites in the code. Note that if desugaring has taken place call site objects
* will have been removed from the code.
@@ -208,11 +209,11 @@
SortedSet<DexMethod> liveMethods,
FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection,
- SortedMap<DexMethod, Set<DexEncodedMethod>> virtualInvokes,
- SortedMap<DexMethod, Set<DexEncodedMethod>> interfaceInvokes,
- SortedMap<DexMethod, Set<DexEncodedMethod>> superInvokes,
- SortedMap<DexMethod, Set<DexEncodedMethod>> directInvokes,
- SortedMap<DexMethod, Set<DexEncodedMethod>> staticInvokes,
+ SortedMap<DexMethod, ProgramMethodSet> virtualInvokes,
+ SortedMap<DexMethod, ProgramMethodSet> interfaceInvokes,
+ SortedMap<DexMethod, ProgramMethodSet> superInvokes,
+ SortedMap<DexMethod, ProgramMethodSet> directInvokes,
+ SortedMap<DexMethod, ProgramMethodSet> staticInvokes,
Set<DexCallSite> callSites,
Set<DexReference> pinnedItems,
Map<DexReference, ProguardMemberRule> mayHaveSideEffects,
@@ -280,7 +281,7 @@
}
public AppInfoWithLiveness(
- AppInfoWithClassHierarchy appInfoWithSubtyping,
+ AppInfoWithClassHierarchy appInfoWithClassHierarchy,
Set<DexType> deadProtoTypes,
Set<DexType> missingTypes,
Set<DexType> liveTypes,
@@ -293,11 +294,11 @@
SortedSet<DexMethod> liveMethods,
FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection,
- SortedMap<DexMethod, Set<DexEncodedMethod>> virtualInvokes,
- SortedMap<DexMethod, Set<DexEncodedMethod>> interfaceInvokes,
- SortedMap<DexMethod, Set<DexEncodedMethod>> superInvokes,
- SortedMap<DexMethod, Set<DexEncodedMethod>> directInvokes,
- SortedMap<DexMethod, Set<DexEncodedMethod>> staticInvokes,
+ SortedMap<DexMethod, ProgramMethodSet> virtualInvokes,
+ SortedMap<DexMethod, ProgramMethodSet> interfaceInvokes,
+ SortedMap<DexMethod, ProgramMethodSet> superInvokes,
+ SortedMap<DexMethod, ProgramMethodSet> directInvokes,
+ SortedMap<DexMethod, ProgramMethodSet> staticInvokes,
Set<DexCallSite> callSites,
Set<DexReference> pinnedItems,
Map<DexReference, ProguardMemberRule> mayHaveSideEffects,
@@ -321,7 +322,7 @@
EnumValueInfoMapCollection enumValueInfoMaps,
Set<DexType> constClassReferences,
Map<DexType, Visibility> initClassReferences) {
- super(appInfoWithSubtyping);
+ super(appInfoWithClassHierarchy);
this.deadProtoTypes = deadProtoTypes;
this.missingTypes = missingTypes;
this.liveTypes = liveTypes;
@@ -853,7 +854,8 @@
}
DexType holder = field.holder();
return fieldAccessInfo.isWrittenOnlyInMethodSatisfying(
- method -> method.isInstanceInitializer() && method.holder() == holder);
+ method ->
+ method.getDefinition().isInstanceInitializer() && method.getHolderType() == holder);
}
public boolean isStaticFieldWrittenOnlyInEnclosingStaticInitializer(DexEncodedField field) {
@@ -885,15 +887,15 @@
return builder.build();
}
- private static <T extends PresortedComparable<T>, S>
- SortedMap<T, Set<S>> rewriteKeysConservativelyWhileMergingValues(
- Map<T, Set<S>> original, Function<T, Set<T>> rewrite) {
- SortedMap<T, Set<S>> result = new TreeMap<>(PresortedComparable::slowCompare);
+ private static <T extends PresortedComparable<T>>
+ SortedMap<T, ProgramMethodSet> rewriteKeysConservativelyWhileMergingValues(
+ Map<T, ProgramMethodSet> original, Function<T, Set<T>> rewrite) {
+ SortedMap<T, ProgramMethodSet> result = new TreeMap<>(PresortedComparable::slowCompare);
for (T item : original.keySet()) {
Set<T> rewrittenKeys = rewrite.apply(item);
for (T rewrittenKey : rewrittenKeys) {
result
- .computeIfAbsent(rewrittenKey, k -> Sets.newIdentityHashSet())
+ .computeIfAbsent(rewrittenKey, k -> ProgramMethodSet.create())
.addAll(original.get(item));
}
}
@@ -1053,7 +1055,7 @@
public DexEncodedMethod lookupSingleTarget(
Type type,
DexMethod target,
- DexType invocationContext,
+ ProgramMethod context,
LibraryModeledPredicate modeledPredicate) {
assert checkIfObsolete();
DexType holder = target.holder;
@@ -1062,15 +1064,15 @@
}
switch (type) {
case VIRTUAL:
- return lookupSingleVirtualTarget(target, invocationContext, false, modeledPredicate);
+ return lookupSingleVirtualTarget(target, context, false, modeledPredicate);
case INTERFACE:
- return lookupSingleVirtualTarget(target, invocationContext, true, modeledPredicate);
+ return lookupSingleVirtualTarget(target, context, true, modeledPredicate);
case DIRECT:
- return lookupDirectTarget(target, invocationContext);
+ return lookupDirectTarget(target, context);
case STATIC:
- return lookupStaticTarget(target, invocationContext);
+ return lookupStaticTarget(target, context);
case SUPER:
- return lookupSuperTarget(target, invocationContext);
+ return lookupSuperTarget(target, context);
default:
return null;
}
@@ -1079,44 +1081,39 @@
public ProgramMethod lookupSingleProgramTarget(
Type type,
DexMethod target,
- DexType invocationContext,
+ ProgramMethod context,
LibraryModeledPredicate modeledPredicate) {
- return asProgramMethodOrNull(
- lookupSingleTarget(type, target, invocationContext, modeledPredicate), this);
+ return asProgramMethodOrNull(lookupSingleTarget(type, target, context, modeledPredicate), this);
}
/** For mapping invoke virtual instruction to single target method. */
public DexEncodedMethod lookupSingleVirtualTarget(
- DexMethod method, DexType invocationContext, boolean isInterface) {
+ DexMethod method, ProgramMethod context, boolean isInterface) {
assert checkIfObsolete();
return lookupSingleVirtualTarget(
- method, invocationContext, isInterface, type -> false, method.holder, null);
+ method, context, isInterface, type -> false, method.holder, null);
}
/** For mapping invoke virtual instruction to single target method. */
public DexEncodedMethod lookupSingleVirtualTarget(
DexMethod method,
- DexType invocationContext,
+ ProgramMethod context,
boolean isInterface,
LibraryModeledPredicate modeledPredicate) {
assert checkIfObsolete();
return lookupSingleVirtualTarget(
- method, invocationContext, isInterface, modeledPredicate, method.holder, null);
+ method, context, isInterface, modeledPredicate, method.holder, null);
}
public DexEncodedMethod lookupSingleVirtualTarget(
DexMethod method,
- DexType invocationContext,
+ ProgramMethod context,
boolean isInterface,
LibraryModeledPredicate modeledPredicate,
DexType refinedReceiverType,
ClassTypeElement receiverLowerBoundType) {
assert checkIfObsolete();
assert refinedReceiverType != null;
-
- DexProgramClass invocationClass = asProgramClassOrNull(definitionFor(invocationContext));
- assert invocationClass != null;
-
if (!refinedReceiverType.isClassType()) {
// The refined receiver is not of class type and we will not be able to find a single target
// (it is either primitive or array).
@@ -1138,9 +1135,9 @@
return cachedItem;
}
SingleResolutionResult resolution =
- resolveMethod(initialResolutionHolder, method).asSingleResolution();
+ resolveMethodOn(initialResolutionHolder, method).asSingleResolution();
if (resolution == null
- || resolution.isAccessibleForVirtualDispatchFrom(invocationClass, this).isFalse()) {
+ || resolution.isAccessibleForVirtualDispatchFrom(context.getHolder(), this).isFalse()) {
return null;
}
// If the method is modeled, return the resolution.
@@ -1189,7 +1186,7 @@
LookupResultSuccess lookupResult =
resolution
.lookupVirtualDispatchTargets(
- invocationClass, this, refinedReceiverClass.asProgramClass(), refinedLowerBound)
+ context.getHolder(), this, refinedReceiverClass.asProgramClass(), refinedLowerBound)
.asLookupResultSuccess();
if (lookupResult != null && !lookupResult.isIncomplete()) {
LookupTarget singleTarget = lookupResult.getSingleLookupTarget();
@@ -1394,7 +1391,7 @@
return TraversalContinuation.BREAK;
} else {
SingleResolutionResult resolution =
- resolveMethod(clazz, dexItemFactory().objectMembers.finalize)
+ resolveMethodOn(clazz, dexItemFactory().objectMembers.finalize)
.asSingleResolution();
if (resolution != null && resolution.getResolvedHolder().isProgramClass()) {
return TraversalContinuation.BREAK;
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 9604389..f2dddae 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -34,6 +34,7 @@
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexDefinition;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -55,11 +56,13 @@
import com.android.tools.r8.graph.EnumValueInfoMapCollection;
import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
import com.android.tools.r8.graph.FieldAccessInfoImpl;
+import com.android.tools.r8.graph.FieldResolutionResult;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.LookupLambdaTarget;
import com.android.tools.r8.graph.LookupTarget;
import com.android.tools.r8.graph.ObjectAllocationInfoCollectionImpl;
import com.android.tools.r8.graph.PresortedComparable;
+import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.graph.ResolutionResult.FailedResolutionResult;
@@ -84,6 +87,7 @@
import com.android.tools.r8.ir.desugar.LambdaClass;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.ir.desugar.LambdaRewriter;
+import com.android.tools.r8.kotlin.KotlinMetadataEnqueuerExtension;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.shaking.DelayedRootSetActionItem.InterfaceMethodSyntheticBridgeAction;
import com.android.tools.r8.shaking.EnqueuerWorklist.EnqueuerAction;
@@ -103,6 +107,7 @@
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.Visibility;
import com.android.tools.r8.utils.WorkList;
+import com.android.tools.r8.utils.collections.ProgramFieldSet;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.ImmutableSet;
@@ -184,12 +189,13 @@
private ProguardClassFilter dontWarnPatterns;
private final EnqueuerUseRegistryFactory useRegistryFactory;
private AnnotationRemover.Builder annotationRemoverBuilder;
+ private final DexDefinitionSupplier enqueuerDefinitionSupplier;
- private final Map<DexMethod, Set<DexEncodedMethod>> virtualInvokes = new IdentityHashMap<>();
- private final Map<DexMethod, Set<DexEncodedMethod>> interfaceInvokes = new IdentityHashMap<>();
- private final Map<DexMethod, Set<DexEncodedMethod>> superInvokes = new IdentityHashMap<>();
- private final Map<DexMethod, Set<DexEncodedMethod>> directInvokes = new IdentityHashMap<>();
- private final Map<DexMethod, Set<DexEncodedMethod>> staticInvokes = new IdentityHashMap<>();
+ private final Map<DexMethod, ProgramMethodSet> virtualInvokes = new IdentityHashMap<>();
+ private final Map<DexMethod, ProgramMethodSet> interfaceInvokes = new IdentityHashMap<>();
+ private final Map<DexMethod, ProgramMethodSet> superInvokes = new IdentityHashMap<>();
+ private final Map<DexMethod, ProgramMethodSet> directInvokes = new IdentityHashMap<>();
+ private final Map<DexMethod, ProgramMethodSet> staticInvokes = new IdentityHashMap<>();
private final FieldAccessInfoCollectionImpl fieldAccessInfoCollection =
new FieldAccessInfoCollectionImpl();
private final ObjectAllocationInfoCollectionImpl.Builder objectAllocationInfoCollection;
@@ -204,7 +210,7 @@
private final Map<DexEncodedMethod, ProgramMethodSet> superInvokeDependencies =
Maps.newIdentityHashMap();
/** Set of instance fields that can be reached by read/write operations. */
- private final Map<DexProgramClass, SetWithReason<DexEncodedField>> reachableInstanceFields =
+ private final Map<DexProgramClass, ProgramFieldSet> reachableInstanceFields =
Maps.newIdentityHashMap();
/**
@@ -272,7 +278,7 @@
/**
* Set of fields that belong to live classes and can be reached by invokes. These need to be kept.
*/
- private final SetWithReason<DexEncodedField> liveFields;
+ private final LiveFieldsSet liveFields;
/**
* Set of service types (from META-INF/services/) that may have been instantiated reflectively via
@@ -361,7 +367,6 @@
&& mode.isInitialOrFinalTreeShaking()) {
registerAnalysis(new ProtoEnqueuerExtension(appView));
}
-
liveTypes = new SetWithReportedReason<>();
initializedTypes = new SetWithReportedReason<>();
targetedMethods = new SetWithReason<>(graphReporter::registerMethod);
@@ -370,7 +375,7 @@
// likely contain two methods. Thus the default capacity of 2.
failedResolutionTargets = SetUtils.newIdentityHashSet(2);
liveMethods = new LiveMethodsSet(graphReporter::registerMethod);
- liveFields = new SetWithReason<>(graphReporter::registerField);
+ liveFields = new LiveFieldsSet(graphReporter::registerField);
lambdaRewriter = options.desugarState == DesugarState.ON ? new LambdaRewriter(appView) : null;
objectAllocationInfoCollection =
@@ -383,6 +388,8 @@
} else {
desugaredLibraryWrapperAnalysis = null;
}
+
+ enqueuerDefinitionSupplier = new EnqueuerDefinitionSupplier(appView, this);
}
private AppInfoWithClassHierarchy appInfo() {
@@ -484,6 +491,33 @@
recordTypeReference(field.type);
}
+ public DexDefinition definitionFor(DexReference reference) {
+ if (reference.isDexType()) {
+ return definitionFor(reference.asDexType());
+ } else if (reference.isDexMethod()) {
+ return definitionFor(reference.asDexMethod());
+ } else {
+ assert reference.isDexField();
+ return definitionFor(reference.asDexField());
+ }
+ }
+
+ public DexEncodedField definitionFor(DexField field) {
+ DexClass clazz = definitionFor(field.holder);
+ if (clazz == null) {
+ return null;
+ }
+ return clazz.lookupField(field);
+ }
+
+ public DexEncodedMethod definitionFor(DexMethod method) {
+ DexClass clazz = definitionFor(method.holder);
+ if (clazz == null) {
+ return null;
+ }
+ return clazz.lookupMethod(method);
+ }
+
private DexClass definitionFor(DexType type) {
DexClass clazz = appView.definitionFor(type);
if (clazz == null) {
@@ -610,13 +644,12 @@
}
}
} else if (item.isDexEncodedField()) {
- DexEncodedField dexEncodedField = item.asDexEncodedField();
- DexProgramClass holder = getProgramClassOrNull(dexEncodedField.holder());
+ DexEncodedField field = item.asDexEncodedField();
+ DexProgramClass holder = getProgramClassOrNull(field.holder());
if (holder != null) {
workList.enqueueMarkFieldKeptAction(
- holder,
- dexEncodedField,
- graphReporter.reportKeepField(precondition, rules, dexEncodedField));
+ new ProgramField(holder, field),
+ graphReporter.reportKeepField(precondition, rules, field));
}
} else if (item.isDexEncodedMethod()) {
DexEncodedMethod encodedMethod = item.asDexEncodedMethod();
@@ -672,47 +705,42 @@
//
private boolean registerMethodWithTargetAndContext(
- Map<DexMethod, Set<DexEncodedMethod>> seen, DexMethod method, ProgramMethod context) {
+ Map<DexMethod, ProgramMethodSet> seen, DexMethod method, ProgramMethod context) {
DexType baseHolder = method.holder.toBaseType(appView.dexItemFactory());
if (baseHolder.isClassType()) {
markTypeAsLive(baseHolder, clazz -> graphReporter.reportClassReferencedFrom(clazz, context));
- return seen.computeIfAbsent(method, ignore -> Sets.newIdentityHashSet())
- .add(context.getDefinition());
+ return seen.computeIfAbsent(method, ignore -> ProgramMethodSet.create()).add(context);
}
return false;
}
public boolean registerFieldRead(DexField field, ProgramMethod context) {
- return registerFieldAccess(field, context.getDefinition(), true, false);
- }
-
- public boolean registerFieldReadFromAnnotation(DexField field) {
- return registerFieldAccess(field, DexEncodedMethod.ANNOTATION_REFERENCE, true, false);
+ return registerFieldAccess(field, context, true, false);
}
public boolean registerReflectiveFieldRead(DexField field, ProgramMethod context) {
- return registerFieldAccess(field, context.getDefinition(), true, true);
+ return registerFieldAccess(field, context, true, true);
}
public boolean registerFieldWrite(DexField field, ProgramMethod context) {
- return registerFieldAccess(field, context.getDefinition(), false, false);
+ return registerFieldAccess(field, context, false, false);
}
public boolean registerReflectiveFieldWrite(DexField field, ProgramMethod context) {
- return registerFieldAccess(field, context.getDefinition(), false, true);
+ return registerFieldAccess(field, context, false, true);
}
public boolean registerReflectiveFieldAccess(DexField field, ProgramMethod context) {
- boolean changed = registerFieldAccess(field, context.getDefinition(), true, true);
- changed |= registerFieldAccess(field, context.getDefinition(), false, true);
+ boolean changed = registerFieldAccess(field, context, true, true);
+ changed |= registerFieldAccess(field, context, false, true);
return changed;
}
private boolean registerFieldAccess(
- DexField field, DexEncodedMethod context, boolean isRead, boolean isReflective) {
+ DexField field, ProgramMethod context, boolean isRead, boolean isReflective) {
FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field);
if (info == null) {
- DexEncodedField encodedField = resolveField(field);
+ DexEncodedField encodedField = resolveField(field).getResolvedField();
// If the field does not exist, then record this in the mapping, such that we don't have to
// resolve the field the next time.
@@ -751,8 +779,7 @@
bootstrapMethods.add(callSite.bootstrapMethod.asMethod());
}
- DexProgramClass contextHolder = context.getHolder();
- LambdaDescriptor descriptor = LambdaDescriptor.tryInfer(callSite, appInfo, contextHolder);
+ LambdaDescriptor descriptor = LambdaDescriptor.tryInfer(callSite, appInfo, context);
if (descriptor == null) {
return;
}
@@ -762,14 +789,13 @@
assert contextMethod.getCode().isCfCode() : "Unexpected input type with lambdas";
CfCode code = contextMethod.getCode().asCfCode();
if (code != null) {
- LambdaClass lambdaClass =
- lambdaRewriter.getOrCreateLambdaClass(descriptor, contextMethod.holder());
+ LambdaClass lambdaClass = lambdaRewriter.getOrCreateLambdaClass(descriptor, context);
lambdaClasses.put(lambdaClass.type, new Pair<>(lambdaClass, context));
lambdaCallSites
.computeIfAbsent(contextMethod, k -> new IdentityHashMap<>())
.put(callSite, lambdaClass);
if (lambdaClass.descriptor.interfaces.contains(appView.dexItemFactory().serializableType)) {
- classesWithSerializableLambdas.add(contextHolder);
+ classesWithSerializableLambdas.add(context.getHolder());
}
}
if (descriptor.delegatesToLambdaImplMethod()) {
@@ -1137,43 +1163,45 @@
}
private boolean traceInstanceFieldRead(
- DexField field, ProgramMethod currentMethod, boolean fromMethodHandle) {
- if (!registerFieldRead(field, currentMethod)) {
+ DexField fieldReference, ProgramMethod currentMethod, boolean fromMethodHandle) {
+ if (!registerFieldRead(fieldReference, currentMethod)) {
return false;
}
// Must mark the field as targeted even if it does not exist.
- markFieldAsTargeted(field, currentMethod);
+ markFieldAsTargeted(fieldReference, currentMethod);
- DexEncodedField encodedField = resolveField(field);
- if (encodedField == null) {
+ FieldResolutionResult resolutionResult = resolveField(fieldReference);
+ if (resolutionResult.isFailedOrUnknownResolution()) {
+ return false;
+ }
+
+ ProgramField field =
+ resolutionResult.asSuccessfulResolution().getResolutionPair().asProgramField();
+ if (field == null) {
+ // No need to trace into the non-program code.
return false;
}
if (fromMethodHandle) {
- fieldAccessInfoCollection.get(encodedField.field).setReadFromMethodHandle();
- }
-
- DexProgramClass clazz = getProgramClassOrNull(encodedField.holder());
- if (clazz == null) {
- return false;
+ fieldAccessInfoCollection.get(field.getReference()).setReadFromMethodHandle();
}
if (Log.ENABLED) {
- Log.verbose(getClass(), "Register Iget `%s`.", field);
+ Log.verbose(getClass(), "Register Iget `%s`.", fieldReference);
}
// If unused interface removal is enabled, then we won't necessarily mark the actual holder of
// the field as live, if the holder is an interface.
if (appView.options().enableUnusedInterfaceRemoval) {
- if (encodedField.field != field) {
- markTypeAsLive(clazz, graphReporter.reportClassReferencedFrom(clazz, currentMethod));
- markTypeAsLive(encodedField.field.type, classReferencedFromReporter(currentMethod));
+ if (field.getReference() != fieldReference) {
+ markTypeAsLive(
+ field.getHolder(),
+ graphReporter.reportClassReferencedFrom(field.getHolder(), currentMethod));
}
}
- workList.enqueueMarkReachableFieldAction(
- clazz, encodedField, KeepReason.fieldReferencedIn(currentMethod));
+ workList.enqueueMarkReachableFieldAction(field, KeepReason.fieldReferencedIn(currentMethod));
return true;
}
@@ -1186,43 +1214,46 @@
}
private boolean traceInstanceFieldWrite(
- DexField field, ProgramMethod currentMethod, boolean fromMethodHandle) {
- if (!registerFieldWrite(field, currentMethod)) {
+ DexField fieldReference, ProgramMethod currentMethod, boolean fromMethodHandle) {
+ if (!registerFieldWrite(fieldReference, currentMethod)) {
return false;
}
// Must mark the field as targeted even if it does not exist.
- markFieldAsTargeted(field, currentMethod);
+ markFieldAsTargeted(fieldReference, currentMethod);
- DexEncodedField encodedField = resolveField(field);
- if (encodedField == null) {
+ FieldResolutionResult resolutionResult = resolveField(fieldReference);
+ if (resolutionResult.isFailedOrUnknownResolution()) {
+ return false;
+ }
+
+ ProgramField field =
+ resolutionResult.asSuccessfulResolution().getResolutionPair().asProgramField();
+ if (field == null) {
+ // No need to trace into the non-program code.
return false;
}
if (fromMethodHandle) {
- fieldAccessInfoCollection.get(encodedField.field).setWrittenFromMethodHandle();
- }
-
- DexProgramClass clazz = getProgramClassOrNull(encodedField.holder());
- if (clazz == null) {
- return false;
+ fieldAccessInfoCollection.get(field.getReference()).setWrittenFromMethodHandle();
}
if (Log.ENABLED) {
- Log.verbose(getClass(), "Register Iput `%s`.", field);
+ Log.verbose(getClass(), "Register Iput `%s`.", fieldReference);
}
// If unused interface removal is enabled, then we won't necessarily mark the actual holder of
// the field as live, if the holder is an interface.
if (appView.options().enableUnusedInterfaceRemoval) {
- if (encodedField.field != field) {
- markTypeAsLive(clazz, graphReporter.reportClassReferencedFrom(clazz, currentMethod));
- markTypeAsLive(encodedField.field.type, classReferencedFromReporter(currentMethod));
+ if (field.getReference() != fieldReference) {
+ markTypeAsLive(
+ field.getHolder(),
+ graphReporter.reportClassReferencedFrom(field.getHolder(), currentMethod));
}
}
KeepReason reason = KeepReason.fieldReferencedIn(currentMethod);
- workList.enqueueMarkReachableFieldAction(clazz, encodedField, reason);
+ workList.enqueueMarkReachableFieldAction(field, reason);
return true;
}
@@ -1235,30 +1266,31 @@
}
private boolean traceStaticFieldRead(
- DexField field, ProgramMethod currentMethod, boolean fromMethodHandle) {
- if (!registerFieldRead(field, currentMethod)) {
+ DexField fieldReference, ProgramMethod currentMethod, boolean fromMethodHandle) {
+ if (!registerFieldRead(fieldReference, currentMethod)) {
return false;
}
- DexEncodedField encodedField = resolveField(field);
- if (encodedField == null) {
+ FieldResolutionResult resolutionResult = resolveField(fieldReference);
+ if (resolutionResult.isFailedOrUnknownResolution()) {
// Must mark the field as targeted even if it does not exist.
- markFieldAsTargeted(field, currentMethod);
+ markFieldAsTargeted(fieldReference, currentMethod);
return false;
}
- if (fromMethodHandle) {
- fieldAccessInfoCollection.get(encodedField.field).setReadFromMethodHandle();
- }
-
- DexProgramClass holder = getProgramClassOrNull(encodedField.holder());
- if (holder == null) {
+ ProgramField field =
+ resolutionResult.asSuccessfulResolution().getResolutionPair().asProgramField();
+ if (field == null) {
// No need to trace into the non-program code.
return false;
}
+ if (fromMethodHandle) {
+ fieldAccessInfoCollection.get(field.getReference()).setReadFromMethodHandle();
+ }
+
if (Log.ENABLED) {
- Log.verbose(getClass(), "Register Sget `%s`.", field);
+ Log.verbose(getClass(), "Register Sget `%s`.", fieldReference);
}
if (appView.options().protoShrinking().enableGeneratedExtensionRegistryShrinking) {
@@ -1266,22 +1298,21 @@
boolean skipTracing =
appView.withGeneratedExtensionRegistryShrinker(
shrinker ->
- shrinker.isDeadProtoExtensionField(
- encodedField, fieldAccessInfoCollection, pinnedItems),
+ shrinker.isDeadProtoExtensionField(field, fieldAccessInfoCollection, pinnedItems),
false);
if (skipTracing) {
- addDeadProtoTypeCandidate(holder);
+ addDeadProtoTypeCandidate(field.getHolder());
return false;
}
}
- if (encodedField.field != field) {
+ if (field.getReference() != fieldReference) {
// Mark the non-rebound field access as targeted. Note that this should only be done if the
// field is not a dead proto field (in which case we bail-out above).
- markFieldAsTargeted(field, currentMethod);
+ markFieldAsTargeted(fieldReference, currentMethod);
}
- markStaticFieldAsLive(encodedField, KeepReason.fieldReferencedIn(currentMethod));
+ markStaticFieldAsLive(field, KeepReason.fieldReferencedIn(currentMethod));
return true;
}
@@ -1294,30 +1325,31 @@
}
private boolean traceStaticFieldWrite(
- DexField field, ProgramMethod currentMethod, boolean fromMethodHandle) {
- if (!registerFieldWrite(field, currentMethod)) {
+ DexField fieldReference, ProgramMethod currentMethod, boolean fromMethodHandle) {
+ if (!registerFieldWrite(fieldReference, currentMethod)) {
return false;
}
- DexEncodedField encodedField = resolveField(field);
- if (encodedField == null) {
+ FieldResolutionResult resolutionResult = resolveField(fieldReference);
+ if (resolutionResult.isFailedOrUnknownResolution()) {
// Must mark the field as targeted even if it does not exist.
- markFieldAsTargeted(field, currentMethod);
+ markFieldAsTargeted(fieldReference, currentMethod);
return false;
}
- if (fromMethodHandle) {
- fieldAccessInfoCollection.get(encodedField.field).setWrittenFromMethodHandle();
- }
-
- DexProgramClass holder = getProgramClassOrNull(encodedField.holder());
- if (holder == null) {
+ ProgramField field =
+ resolutionResult.asSuccessfulResolution().getResolutionPair().asProgramField();
+ if (field == null) {
// No need to trace into the non-program code.
return false;
}
+ if (fromMethodHandle) {
+ fieldAccessInfoCollection.get(field.getReference()).setWrittenFromMethodHandle();
+ }
+
if (Log.ENABLED) {
- Log.verbose(getClass(), "Register Sput `%s`.", field);
+ Log.verbose(getClass(), "Register Sput `%s`.", fieldReference);
}
if (appView.options().protoShrinking().enableGeneratedExtensionRegistryShrinking) {
@@ -1325,22 +1357,21 @@
boolean skipTracing =
appView.withGeneratedExtensionRegistryShrinker(
shrinker ->
- shrinker.isDeadProtoExtensionField(
- encodedField, fieldAccessInfoCollection, pinnedItems),
+ shrinker.isDeadProtoExtensionField(field, fieldAccessInfoCollection, pinnedItems),
false);
if (skipTracing) {
- addDeadProtoTypeCandidate(holder);
+ addDeadProtoTypeCandidate(field.getHolder());
return false;
}
}
- if (encodedField.field != field) {
+ if (field.getReference() != fieldReference) {
// Mark the non-rebound field access as targeted. Note that this should only be done if the
// field is not a dead proto field (in which case we bail-out above).
- markFieldAsTargeted(field, currentMethod);
+ markFieldAsTargeted(fieldReference, currentMethod);
}
- markStaticFieldAsLive(encodedField, KeepReason.fieldReferencedIn(currentMethod));
+ markStaticFieldAsLive(field, KeepReason.fieldReferencedIn(currentMethod));
return true;
}
@@ -1505,7 +1536,8 @@
compatEnqueueHolderIfDependentNonStaticMember(
holder, rootSet.getDependentKeepClassCompatRule(holder.getType()));
- analyses.forEach(analysis -> analysis.processNewlyLiveClass(holder, workList));
+ analyses.forEach(
+ analysis -> analysis.processNewlyLiveClass(holder, workList, enqueuerDefinitionSupplier));
}
private void ensureMethodsContinueToWidenAccess(DexClass clazz) {
@@ -1616,22 +1648,21 @@
annotation.annotation.collectIndexedItems(referenceMarker);
}
- private DexEncodedField resolveField(DexField field) {
+ private FieldResolutionResult resolveField(DexField field) {
// Record the references in case they are not program types.
recordTypeReference(field.holder);
recordTypeReference(field.type);
- DexEncodedField encodedField = appInfo.resolveField(field);
- if (encodedField == null) {
+ FieldResolutionResult resolutionResult = appInfo.resolveField(field);
+ if (resolutionResult.isFailedOrUnknownResolution()) {
reportMissingField(field);
- return null;
}
- return encodedField;
+ return resolutionResult;
}
private SingleResolutionResult resolveMethod(DexMethod method, KeepReason reason) {
// Record the references in case they are not program types.
recordMethodReference(method);
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.unsafeResolveMethodDueToDexFormat(method);
if (resolutionResult.isFailedResolution()) {
reportMissingMethod(method);
markFailedResolutionTargets(method, resolutionResult.asFailedResolution(), reason);
@@ -1643,8 +1674,7 @@
DexMethod method, KeepReason reason, boolean interfaceInvoke) {
// Record the references in case they are not program types.
recordMethodReference(method);
- ResolutionResult resolutionResult =
- appInfo.resolveMethod(method.holder, method, interfaceInvoke);
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method, interfaceInvoke);
if (resolutionResult.isFailedResolution()) {
reportMissingMethod(method);
markFailedResolutionTargets(method, resolutionResult.asFailedResolution(), reason);
@@ -1998,7 +2028,7 @@
assert method.holder == superClass.type;
if (seenMethods.add(MethodSignatureEquivalence.get().wrap(method))) {
SingleResolutionResult resolution =
- appInfo.resolveMethod(superClass, method).asSingleResolution();
+ appInfo.resolveMethodOn(superClass, method).asSingleResolution();
assert resolution != null;
assert resolution.getResolvedHolder().isProgramClass();
if (resolution != null && resolution.getResolvedHolder().isProgramClass()) {
@@ -2052,7 +2082,7 @@
// Note: It would be reasonable to not process methods already seen during the marking of
// program usages, but that would cause the methods to not be marked as library overrides.
markLibraryOrClasspathOverrideLive(
- instantiation, libraryClass, appInfo.resolveMethod(libraryClass, method.method));
+ instantiation, libraryClass, appInfo.resolveMethodOn(libraryClass, method.method));
// Due to API conversion, some overrides can be hidden since they will be rewritten. See
// class comment of DesugaredLibraryAPIConverter and vivifiedType logic.
@@ -2068,7 +2098,7 @@
markLibraryOrClasspathOverrideLive(
instantiation,
libraryClass,
- appInfo.resolveMethod(instantiation.asClass(), methodToResolve));
+ appInfo.resolveMethodOn(instantiation.asClass(), methodToResolve));
}
}
}
@@ -2123,12 +2153,11 @@
*/
private void transitionFieldsForInstantiatedClass(DexProgramClass clazz) {
do {
- SetWithReason<DexEncodedField> reachableFields = reachableInstanceFields.get(clazz);
+ ProgramFieldSet reachableFields = reachableInstanceFields.get(clazz);
if (reachableFields != null) {
- for (DexEncodedField field : reachableFields.getItems()) {
- // TODO(b/120959039): Should the reason this field is reachable come from the set?
- markInstanceFieldAsLive(clazz, field, KeepReason.reachableFromLiveType(clazz.type));
- }
+ // TODO(b/120959039): Should the reason this field is reachable come from the set?
+ KeepReason reason = KeepReason.reachableFromLiveType(clazz.type);
+ reachableFields.forEach(field -> markInstanceFieldAsLive(field, reason));
}
clazz = getProgramClassOrNull(clazz.superType);
} while (clazz != null && !objectAllocationInfoCollection.isInstantiatedDirectly(clazz));
@@ -2176,58 +2205,48 @@
markTypeAsLive(field.holder, clazz -> graphReporter.reportClassReferencedFrom(clazz, context));
}
- private void markStaticFieldAsLive(DexEncodedField encodedField, KeepReason reason) {
+ private void markStaticFieldAsLive(ProgramField field, KeepReason reason) {
// Mark the type live here, so that the class exists at runtime.
- DexField field = encodedField.field;
markTypeAsLive(
- field.holder, clazz -> graphReporter.reportClassReferencedFrom(clazz, encodedField));
+ field.getHolder(), graphReporter.reportClassReferencedFrom(field.getHolder(), field));
markTypeAsLive(
- field.type, clazz -> graphReporter.reportClassReferencedFrom(clazz, encodedField));
+ field.getReference().type, clazz -> graphReporter.reportClassReferencedFrom(clazz, field));
- DexProgramClass clazz = getProgramClassOrNull(field.holder);
- if (clazz == null) {
- return;
- }
-
- markDirectAndIndirectClassInitializersAsLive(clazz);
+ markDirectAndIndirectClassInitializersAsLive(field.getHolder());
// This field might be an instance field reachable from a static context, e.g. a getStatic that
// resolves to an instance field. We have to keep the instance field nonetheless, as otherwise
// we might unmask a shadowed static field and hence change semantics.
- if (encodedField.accessFlags.isStatic()) {
+ if (field.getDefinition().isStatic()) {
if (Log.ENABLED) {
- Log.verbose(getClass(), "Adding static field `%s` to live set.", encodedField.field);
+ Log.verbose(getClass(), "Adding static field `%s` to live set.", field);
}
} else {
if (Log.ENABLED) {
- Log.verbose(getClass(), "Adding instance field `%s` to live set (static context).",
- encodedField.field);
+ Log.verbose(getClass(), "Adding instance field `%s` to live set (static context).", field);
}
}
- processAnnotations(clazz, encodedField);
- liveFields.add(encodedField, reason);
-
- // Add all dependent members to the workqueue.
- enqueueRootItems(rootSet.getDependentItems(encodedField));
-
- // Notify analyses.
- analyses.forEach(analysis -> analysis.processNewlyLiveField(encodedField));
- }
-
- private void markInstanceFieldAsLive(
- DexProgramClass holder, DexEncodedField field, KeepReason reason) {
- assert field != null;
- assert field.isProgramField(appView);
- markTypeAsLive(field.holder(), reason);
- markTypeAsLive(field.field.type, reason);
- if (Log.ENABLED) {
- Log.verbose(getClass(), "Adding instance field `%s` to live set.", field.field);
- }
- processAnnotations(holder, field);
+ processAnnotations(field.getHolder(), field.getDefinition());
liveFields.add(field, reason);
// Add all dependent members to the workqueue.
- enqueueRootItems(rootSet.getDependentItems(field));
+ enqueueRootItems(rootSet.getDependentItems(field.getDefinition()));
+
+ // Notify analyses.
+ analyses.forEach(analysis -> analysis.processNewlyLiveField(field));
+ }
+
+ private void markInstanceFieldAsLive(ProgramField field, KeepReason reason) {
+ markTypeAsLive(field.getHolder(), graphReporter.registerClass(field.getHolder(), reason));
+ markTypeAsLive(field.getReference().type, reason);
+ if (Log.ENABLED) {
+ Log.verbose(getClass(), "Adding instance field `%s` to live set.", field);
+ }
+ processAnnotations(field.getHolder(), field.getDefinition());
+ liveFields.add(field, reason);
+
+ // Add all dependent members to the workqueue.
+ enqueueRootItems(rootSet.getDependentItems(field.getDefinition()));
// Notify analyses.
analyses.forEach(analysis -> analysis.processNewlyLiveField(field));
@@ -2264,28 +2283,27 @@
return info != null;
}
- public boolean isFieldLive(DexEncodedField field) {
+ public boolean isFieldLive(ProgramField field) {
return liveFields.contains(field);
}
- public boolean isFieldRead(DexEncodedField field) {
- FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field.field);
+ public boolean isFieldRead(ProgramField field) {
+ FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field.getReference());
return info != null && info.isRead();
}
public boolean isFieldWrittenInMethodSatisfying(
- DexEncodedField field, Predicate<DexEncodedMethod> predicate) {
- FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field.field);
+ ProgramField field, Predicate<ProgramMethod> predicate) {
+ FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field.getReference());
return info != null && info.isWrittenInMethodSatisfying(predicate);
}
- public boolean isFieldWrittenOutsideDefaultConstructor(DexEncodedField field) {
- FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field.field);
+ public boolean isFieldWrittenOutsideDefaultConstructor(ProgramField field) {
+ FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field.getReference());
if (info == null) {
return false;
}
- DexClass clazz = appView.definitionFor(field.holder());
- DexEncodedMethod defaultInitializer = clazz.getDefaultInitializer();
+ DexEncodedMethod defaultInitializer = field.getHolder().getDefaultInitializer();
return defaultInitializer != null
? info.isWrittenOutside(defaultInitializer)
: info.isWritten();
@@ -2322,37 +2340,30 @@
}
// Package protected due to entry point from worklist.
- void markInstanceFieldAsReachable(DexEncodedField encodedField, KeepReason reason) {
- DexField field = encodedField.field;
+ void markInstanceFieldAsReachable(ProgramField field, KeepReason reason) {
if (Log.ENABLED) {
Log.verbose(getClass(), "Marking instance field `%s` as reachable.", field);
}
markTypeAsLive(
- field.holder, clazz -> graphReporter.reportClassReferencedFrom(clazz, encodedField));
+ field.getHolder(), graphReporter.reportClassReferencedFrom(field.getHolder(), field));
markTypeAsLive(
- field.type, clazz -> graphReporter.reportClassReferencedFrom(clazz, encodedField));
-
- DexProgramClass clazz = getProgramClassOrNull(field.holder);
- if (clazz == null) {
- return;
- }
+ field.getReference().type, clazz -> graphReporter.reportClassReferencedFrom(clazz, field));
// We might have a instance field access that is dispatched to a static field. In such case,
// we have to keep the static field, so that the dispatch fails at runtime in the same way that
// it did before. We have to keep the field even if the receiver has no live inhabitants, as
// field resolution happens before the receiver is inspected.
- if (encodedField.accessFlags.isStatic()) {
- markStaticFieldAsLive(encodedField, reason);
+ if (field.getDefinition().isStatic()) {
+ markStaticFieldAsLive(field, reason);
+ } else if (objectAllocationInfoCollection.isInstantiatedDirectlyOrHasInstantiatedSubtype(
+ field.getHolder())) {
+ markInstanceFieldAsLive(field, reason);
} else {
- if (objectAllocationInfoCollection.isInstantiatedDirectlyOrHasInstantiatedSubtype(clazz)) {
- markInstanceFieldAsLive(clazz, encodedField, reason);
- } else {
- // Add the field to the reachable set if the type later becomes instantiated.
- reachableInstanceFields
- .computeIfAbsent(clazz, ignore -> newSetWithoutReasonReporter())
- .add(encodedField, reason);
- }
+ // Add the field to the reachable set if the type later becomes instantiated.
+ reachableInstanceFields
+ .computeIfAbsent(field.getHolder(), ignore -> ProgramFieldSet.create())
+ .add(field);
}
}
@@ -2407,9 +2418,9 @@
DexEncodedMethod resolvedMethod = resolution.getResolvedMethod();
markMethodAsTargeted(new ProgramMethod(resolvedHolder, resolvedMethod), reason);
- DexProgramClass context = contextOrNull == null ? null : contextOrNull.getHolder();
+ DexProgramClass contextHolder = contextOrNull != null ? contextOrNull.getHolder() : null;
if (contextOrNull != null
- && resolution.isAccessibleForVirtualDispatchFrom(context, appInfo).isFalse()) {
+ && resolution.isAccessibleForVirtualDispatchFrom(contextHolder, appInfo).isFalse()) {
// Not accessible from this context, so this call will cause a runtime exception.
return;
}
@@ -2417,7 +2428,7 @@
// If the resolved method is not a virtual target, eg, is static, dispatch will fail too.
if (!resolvedMethod.isVirtualMethod()) {
// This can only happen when context is null, otherwise the access check above will fail.
- assert context == null;
+ assert contextOrNull == null;
return;
}
@@ -2426,7 +2437,7 @@
resolution
.lookupVirtualDispatchTargets(
- context,
+ contextHolder,
appInfo,
(type, subTypeConsumer, lambdaConsumer) ->
objectAllocationInfoCollection.forEachInstantiatedSubType(
@@ -2567,6 +2578,10 @@
throws ExecutionException {
this.rootSet = rootSet;
this.dontWarnPatterns = dontWarnPatterns;
+ if (!options.kotlinOptimizationOptions().disableKotlinSpecificOptimizations
+ && mode.isInitialTreeShaking()) {
+ registerAnalysis(new KotlinMetadataEnqueuerExtension(appView));
+ }
// Translate the result of root-set computation into enqueuer actions.
if (appView.options().isShrinking() || appView.options().getProguardConfiguration() == null) {
enqueueRootItems(rootSet.noShrinking);
@@ -2820,7 +2835,11 @@
new AppInfoWithLiveness(
app,
SetUtils.mapIdentityHashSet(deadProtoTypeCandidates, DexProgramClass::getType),
- missingTypes,
+ // TODO(b/155959821): We should be able to assert that missing types is a subset of
+ // initialMissingTypes + synthesized types.
+ mode.isFinalTreeShaking()
+ ? Sets.union(initialMissingTypes, missingTypes)
+ : missingTypes,
SetUtils.mapIdentityHashSet(liveTypes.getItems(), DexProgramClass::getType),
Collections.unmodifiableSet(instantiatedAppServices),
Enqueuer.toSortedDescriptorSet(targetedMethods.getItems()),
@@ -3143,7 +3162,7 @@
private long getNumberOfLiveItems() {
long result = liveTypes.items.size();
result += liveMethods.items.size();
- result += liveFields.items.size();
+ result += liveFields.fields.size();
return result;
}
@@ -3281,12 +3300,11 @@
}
// Package protected due to entry point from worklist.
- void markFieldAsKept(DexProgramClass holder, DexEncodedField target, KeepReason reason) {
- assert holder.type == target.holder();
- if (target.accessFlags.isStatic()) {
- markStaticFieldAsLive(target, reason);
+ void markFieldAsKept(ProgramField field, KeepReason reason) {
+ if (field.getDefinition().isStatic()) {
+ markStaticFieldAsLive(field, reason);
} else {
- markInstanceFieldAsReachable(target, reason);
+ markInstanceFieldAsReachable(field, reason);
}
}
@@ -3504,7 +3522,7 @@
if (clazz == null) {
return;
}
- DexEncodedField encodedField = appView.definitionFor(field);
+ DexEncodedField encodedField = clazz.lookupField(field);
if (encodedField == null) {
return;
}
@@ -3514,14 +3532,14 @@
// fields since the creation of a field updater throws a NoSuchFieldException if the field
// is not present.
boolean keepClass =
- !encodedField.accessFlags.isStatic()
+ !encodedField.isStatic()
&& dexItemFactory.atomicFieldUpdaterMethods.isFieldUpdater(invokedMethod);
if (keepClass) {
workList.enqueueMarkInstantiatedAction(
clazz, null, InstantiationReason.REFLECTION, KeepReason.reflectiveUseIn(method));
}
if (pinnedItems.add(encodedField.field)) {
- markFieldAsKept(clazz, encodedField, KeepReason.reflectiveUseIn(method));
+ markFieldAsKept(new ProgramField(clazz, encodedField), KeepReason.reflectiveUseIn(method));
}
} else {
assert identifierItem.isDexMethod();
@@ -3817,6 +3835,32 @@
}
}
+ private class LiveFieldsSet {
+
+ private final Set<DexEncodedField> fields = Sets.newIdentityHashSet();
+
+ private final BiConsumer<DexEncodedField, KeepReason> register;
+
+ LiveFieldsSet(BiConsumer<DexEncodedField, KeepReason> register) {
+ this.register = register;
+ }
+
+ boolean add(ProgramField field, KeepReason reason) {
+ DexEncodedField definition = field.getDefinition();
+ register.accept(definition, reason);
+ transitionUnusedInterfaceToLive(field.getHolder());
+ return fields.add(definition);
+ }
+
+ boolean contains(DexEncodedField field) {
+ return fields.contains(field);
+ }
+
+ boolean contains(ProgramField field) {
+ return contains(field.getDefinition());
+ }
+ }
+
private class LiveMethodsSet {
private final Set<DexEncodedMethod> items = Sets.newIdentityHashSet();
@@ -3890,37 +3934,40 @@
}
@Override
- public boolean addField(DexField field) {
- recordTypeReference(field.holder);
- recordTypeReference(field.type);
- DexClass holder = appView.definitionFor(field.holder);
+ public boolean addField(DexField fieldReference) {
+ recordFieldReference(fieldReference);
+ DexProgramClass holder = getProgramClassOrNull(fieldReference.holder);
if (holder == null) {
return false;
}
- DexEncodedField target = holder.lookupStaticField(field);
- if (target != null) {
- // There is no dispatch on annotations, so only keep what is directly referenced.
- if (target.field == field) {
- if (!registerFieldReadFromAnnotation(field)) {
- return false;
- }
- markStaticFieldAsLive(target, KeepReason.referencedInAnnotation(annotationHolder));
- // When an annotation has a field of an enum type with a default value then Java VM
- // will use the values() method on that enum class.
- if (options.isGeneratingClassFiles()
- && annotationHolder == dexItemFactory.annotationDefault) {
- DexProgramClass clazz = getProgramClassOrNull(field.type);
- if (clazz != null && clazz.accessFlags.isEnum()) {
- markEnumValuesAsReachable(clazz, KeepReason.referencedInAnnotation(annotationHolder));
- }
+ ProgramField field = holder.lookupProgramField(fieldReference);
+ if (field == null) {
+ return false;
+ }
+ // There is no dispatch on annotations, so only keep what is directly referenced.
+ if (field.getReference() != fieldReference) {
+ return false;
+ }
+ if (field.getDefinition().isStatic()) {
+ FieldAccessInfoImpl fieldAccessInfo =
+ fieldAccessInfoCollection.contains(fieldReference)
+ ? fieldAccessInfoCollection.get(fieldReference)
+ : fieldAccessInfoCollection.extend(
+ fieldReference, new FieldAccessInfoImpl(fieldReference));
+ fieldAccessInfo.setReadFromAnnotation();
+ markStaticFieldAsLive(field, KeepReason.referencedInAnnotation(annotationHolder));
+ // When an annotation has a field of an enum type with a default value then Java VM
+ // will use the values() method on that enum class.
+ if (options.isGeneratingClassFiles()
+ && annotationHolder == dexItemFactory.annotationDefault) {
+ if (field.getHolder().isEnum()) {
+ markEnumValuesAsReachable(
+ field.getHolder(), KeepReason.referencedInAnnotation(annotationHolder));
}
}
} else {
- target = holder.lookupInstanceField(field);
// There is no dispatch on annotations, so only keep what is directly referenced.
- if (target != null && target.field != field) {
- markInstanceFieldAsReachable(target, KeepReason.referencedInAnnotation(annotationHolder));
- }
+ markInstanceFieldAsReachable(field, KeepReason.referencedInAnnotation(annotationHolder));
}
return false;
}
@@ -3984,4 +4031,44 @@
}
}
+ public static class EnqueuerDefinitionSupplier implements DexDefinitionSupplier {
+
+ private final Enqueuer enqueuer;
+ private final AppView<?> appView;
+
+ private EnqueuerDefinitionSupplier(AppView<?> appView, Enqueuer enqueuer) {
+ this.appView = appView;
+ this.enqueuer = enqueuer;
+ }
+
+ @Override
+ public DexDefinition definitionFor(DexReference reference) {
+ return enqueuer.definitionFor(reference);
+ }
+
+ @Override
+ public DexEncodedField definitionFor(DexField field) {
+ return enqueuer.definitionFor(field);
+ }
+
+ @Override
+ public DexEncodedMethod definitionFor(DexMethod method) {
+ return enqueuer.definitionFor(method);
+ }
+
+ @Override
+ public DexClass definitionFor(DexType type) {
+ return enqueuer.definitionFor(type);
+ }
+
+ @Override
+ public DexProgramClass definitionForProgramType(DexType type) {
+ return enqueuer.getProgramClassOrNull(type);
+ }
+
+ @Override
+ public DexItemFactory dexItemFactory() {
+ return appView.dexItemFactory();
+ }
+ }
}
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
index f5ffc75..3c9649d 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
@@ -5,11 +5,11 @@
package com.android.tools.r8.shaking;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.GraphReporter.KeepReasonWitness;
import java.util.ArrayDeque;
@@ -52,17 +52,17 @@
}
static class MarkReachableFieldAction extends EnqueuerAction {
- final DexEncodedField target;
+ final ProgramField field;
final KeepReason reason;
- public MarkReachableFieldAction(DexEncodedField target, KeepReason reason) {
- this.target = target;
+ public MarkReachableFieldAction(ProgramField field, KeepReason reason) {
+ this.field = field;
this.reason = reason;
}
@Override
public void run(Enqueuer enqueuer) {
- enqueuer.markInstanceFieldAsReachable(target, reason);
+ enqueuer.markInstanceFieldAsReachable(field, reason);
}
}
@@ -151,20 +151,17 @@
}
static class MarkFieldKeptAction extends EnqueuerAction {
- final DexProgramClass holder;
- final DexEncodedField target;
+ final ProgramField field;
final KeepReasonWitness witness;
- public MarkFieldKeptAction(
- DexProgramClass holder, DexEncodedField target, KeepReasonWitness witness) {
- this.holder = holder;
- this.target = target;
+ public MarkFieldKeptAction(ProgramField field, KeepReasonWitness witness) {
+ this.field = field;
this.witness = witness;
}
@Override
public void run(Enqueuer enqueuer) {
- enqueuer.markFieldAsKept(holder, target, witness);
+ enqueuer.markFieldAsKept(field, witness);
}
}
@@ -255,9 +252,7 @@
queue.add(new MarkReachableSuperAction(method, from));
}
- public void enqueueMarkReachableFieldAction(
- DexProgramClass clazz, DexEncodedField field, KeepReason reason) {
- assert field.holder() == clazz.type;
+ public void enqueueMarkReachableFieldAction(ProgramField field, KeepReason reason) {
queue.add(new MarkReachableFieldAction(field, reason));
}
@@ -293,10 +288,8 @@
queue.add(new MarkMethodKeptAction(method, reason));
}
- void enqueueMarkFieldKeptAction(
- DexProgramClass holder, DexEncodedField field, KeepReasonWitness witness) {
- assert field.isProgramField(appView);
- queue.add(new MarkFieldKeptAction(holder, field, witness));
+ void enqueueMarkFieldKeptAction(ProgramField field, KeepReasonWitness witness) {
+ queue.add(new MarkFieldKeptAction(field, witness));
}
public void enqueueTraceConstClassAction(DexType type, ProgramMethod context) {
diff --git a/src/main/java/com/android/tools/r8/shaking/GraphReporter.java b/src/main/java/com/android/tools/r8/shaking/GraphReporter.java
index 0e39b4c..2ab539d 100644
--- a/src/main/java/com/android/tools/r8/shaking/GraphReporter.java
+++ b/src/main/java/com/android/tools/r8/shaking/GraphReporter.java
@@ -26,6 +26,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
import com.android.tools.r8.references.Reference;
@@ -219,9 +220,9 @@
return KeepReasonWitness.INSTANCE;
}
- public KeepReasonWitness reportClassReferencedFrom(DexProgramClass clazz, DexEncodedField field) {
+ public KeepReasonWitness reportClassReferencedFrom(DexProgramClass clazz, ProgramField field) {
if (keptGraphConsumer != null) {
- FieldGraphNode source = getFieldGraphNode(field.field);
+ FieldGraphNode source = getFieldGraphNode(field.getReference());
ClassGraphNode target = getClassGraphNode(clazz.type);
return reportEdge(source, target, EdgeKind.ReferencedFrom);
}
diff --git a/src/main/java/com/android/tools/r8/shaking/LibraryMethodOverrideAnalysis.java b/src/main/java/com/android/tools/r8/shaking/LibraryMethodOverrideAnalysis.java
index f73139d..0979ef9 100644
--- a/src/main/java/com/android/tools/r8/shaking/LibraryMethodOverrideAnalysis.java
+++ b/src/main/java/com/android/tools/r8/shaking/LibraryMethodOverrideAnalysis.java
@@ -7,10 +7,10 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.TopDownClassHierarchyTraversal;
import com.android.tools.r8.ir.analysis.escape.EscapeAnalysis;
import com.android.tools.r8.ir.analysis.escape.EscapeAnalysisConfiguration;
@@ -193,7 +193,7 @@
AppView<?> appView,
EscapeAnalysis escapeAnalysis,
Instruction escapeRoute,
- DexMethod context) {
+ ProgramMethod context) {
if (appView.appInfo().hasLiveness()) {
return isLegitimateConstructorInvocation(
appView.withLiveness(), escapeAnalysis, escapeRoute, context);
@@ -205,7 +205,7 @@
AppView<AppInfoWithLiveness> appView,
EscapeAnalysis escapeAnalysis,
Instruction instruction,
- DexMethod context) {
+ ProgramMethod context) {
if (!instruction.isInvokeDirect()) {
return false;
}
@@ -221,7 +221,7 @@
}
}
- DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, context.holder);
+ DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, context);
if (singleTarget == null) {
return false;
}
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 e105350..ffb940a 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -378,7 +378,7 @@
// is due to the lack of the definition or it indeed means no matching rules. Similar to how
// we apply those assume rules, here we use a resolved target.
DexEncodedMethod target =
- appView.appInfo().resolveMethod(subType, referenceInSubType).getSingleTarget();
+ appView.appInfo().unsafeResolveMethodDueToDexFormat(referenceInSubType).getSingleTarget();
// But, the resolution should not be landed on the current type we are visiting.
if (target == null || target.holder() == type) {
continue;
@@ -555,7 +555,7 @@
private void tryAndKeepMethodOnClass(DexEncodedMethod method, ProguardMemberRule rule) {
SingleResolutionResult resolutionResult =
- appView.appInfo().resolveMethod(originalClazz, method.method).asSingleResolution();
+ appView.appInfo().resolveMethodOn(originalClazz, method.method).asSingleResolution();
if (resolutionResult == null || !resolutionResult.isVirtualTarget()) {
return;
}
@@ -1286,6 +1286,10 @@
this.delayedRootSetActionItems = delayedRootSetActionItems;
}
+ public boolean noShrinking(DexReference reference) {
+ return noShrinking.containsKey(reference);
+ }
+
public void forEachClassWithDependentItems(
DexDefinitionSupplier definitions, Consumer<DexProgramClass> consumer) {
for (DexReference reference : dependentNoShrinking.keySet()) {
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 31d8074..a540236 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -382,7 +382,7 @@
TraversalContinuation result =
sourceClass.traverseProgramInstanceInitializers(
method -> {
- AbortReason reason = disallowInlining(method, targetClass.type);
+ AbortReason reason = disallowInlining(method, targetClass);
if (reason != null) {
// Cannot guarantee that markForceInline() will work.
if (Log.ENABLED) {
@@ -1182,7 +1182,7 @@
// Resolution would have succeeded if the method used to be in [type], or if one of
// its super classes declared the method.
boolean resolutionSucceededBeforeMerge =
- renamedMembersLense.hasMappingForSignatureInContext(holder.type, signatureInType)
+ renamedMembersLense.hasMappingForSignatureInContext(holder, signatureInType)
|| appInfo.lookupSuperTarget(signatureInHolder, holder) != null;
if (resolutionSucceededBeforeMerge) {
deferredRenamings.mapVirtualMethodToDirectInType(
@@ -1261,7 +1261,7 @@
// Returns the method that shadows the given method, or null if method is not shadowed.
private DexEncodedMethod findMethodInTarget(DexEncodedMethod method) {
- ResolutionResult resolutionResult = appInfo.resolveMethod(target, method.method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOn(target, method.method);
if (!resolutionResult.isSingleResolution()) {
// May happen in case of missing classes, or if multiple implementations were found.
abortMerge = true;
@@ -1655,7 +1655,7 @@
}
}
- private AbortReason disallowInlining(ProgramMethod method, DexType invocationContext) {
+ private AbortReason disallowInlining(ProgramMethod method, DexProgramClass context) {
if (appView.options().enableInlining) {
Code code = method.getDefinition().getCode();
if (code.isCfCode()) {
@@ -1664,14 +1664,14 @@
cfCode.computeInliningConstraint(
method,
appView,
- new SingleTypeMapperGraphLense(method.getHolderType(), invocationContext),
- invocationContext);
+ new SingleTypeMapperGraphLense(method.getHolderType(), context),
+ context);
if (constraint == ConstraintWithTarget.NEVER) {
return AbortReason.UNSAFE_INLINING;
}
// Constructors can have references beyond the root main dex classes. This can increase the
// size of the main dex dependent classes and we should bail out.
- if (mainDexClasses.getRoots().contains(invocationContext)
+ if (mainDexClasses.getRoots().contains(context.type)
&& MainDexDirectReferenceTracer.hasReferencesOutsideFromCode(
appView.appInfo(), method, mainDexClasses.getRoots())) {
return AbortReason.MAIN_DEX_ROOT_OUTSIDE_REFERENCE;
@@ -1686,9 +1686,9 @@
private class SingleTypeMapperGraphLense extends GraphLense {
private final DexType source;
- private final DexType target;
+ private final DexProgramClass target;
- public SingleTypeMapperGraphLense(DexType source, DexType target) {
+ public SingleTypeMapperGraphLense(DexType source, DexProgramClass target) {
this.source = source;
this.target = target;
}
@@ -1720,7 +1720,7 @@
@Override
public DexType lookupType(DexType type) {
- return type == source ? target : mergedClasses.getOrDefault(type, type);
+ return type == source ? target.type : mergedClasses.getOrDefault(type, type);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLense.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLense.java
index 1013539..1202384 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLense.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLense.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
@@ -303,9 +304,9 @@
return mergedClasses.getOrDefault(type, type);
}
- public boolean hasMappingForSignatureInContext(DexType context, DexMethod signature) {
+ public boolean hasMappingForSignatureInContext(DexProgramClass context, DexMethod signature) {
Map<DexMethod, GraphLenseLookupResult> virtualToDirectMethodMap =
- contextualVirtualToDirectMethodMaps.get(context);
+ contextualVirtualToDirectMethodMaps.get(context.type);
if (virtualToDirectMethodMap != null) {
return virtualToDirectMethodMap.containsKey(signature);
}
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
index 60b6f7d..f15c049 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
@@ -41,9 +41,9 @@
O_MR1(27),
P(28),
Q(29),
- R(30); // Speculative, this can change.
+ R(30);
- public static final AndroidApiLevel LATEST = Q;
+ public static final AndroidApiLevel LATEST = R;
public static final int magicApiLevelUsedByAndroidPlatformBuild = 10000;
diff --git a/src/main/java/com/android/tools/r8/utils/BooleanBox.java b/src/main/java/com/android/tools/r8/utils/BooleanBox.java
index d31e352..f46ac1c 100644
--- a/src/main/java/com/android/tools/r8/utils/BooleanBox.java
+++ b/src/main/java/com/android/tools/r8/utils/BooleanBox.java
@@ -18,7 +18,15 @@
return value;
}
+ public void set() {
+ set(true);
+ }
+
public void set(boolean value) {
this.value = value;
}
+
+ public void unset() {
+ set(false);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/utils/DexVersion.java b/src/main/java/com/android/tools/r8/utils/DexVersion.java
index 99098d8..e9557fa 100644
--- a/src/main/java/com/android/tools/r8/utils/DexVersion.java
+++ b/src/main/java/com/android/tools/r8/utils/DexVersion.java
@@ -38,6 +38,7 @@
public static DexVersion getDexVersion(AndroidApiLevel androidApiLevel) {
switch (androidApiLevel) {
+ case R:
case Q:
case P:
return DexVersion.V39;
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 62aa29a..e92effc 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -73,6 +73,7 @@
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.objectweb.asm.Opcodes;
@@ -838,14 +839,14 @@
}
public void warningMissingTypeForDesugar(
- Origin origin, Position position, DexType missingType, DexType contextType) {
+ Origin origin, Position position, DexType missingType, DexMethod context) {
if (reportedMissingForDesugaring.add(missingType)) {
reporter.warning(
new InterfaceDesugarMissingTypeDiagnostic(
origin,
position,
Reference.classFromDescriptor(missingType.toDescriptorString()),
- Reference.classFromDescriptor(contextType.toDescriptorString()),
+ Reference.classFromDescriptor(context.holder.toDescriptorString()),
null));
}
}
@@ -1186,6 +1187,8 @@
}
public Consumer<ProgramMethod> callSiteOptimizationInfoInspector = null;
+
+ public Predicate<DexEncodedMethod> cfByteCodePassThrough = null;
}
@VisibleForTesting
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 8cdce08..d62402b 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -338,7 +338,9 @@
optimizeDexCodePositions(
method, appView, kotlinRemapper, mappedPositions, identityMapping);
}
- } else if (code.isCfCode() && doesContainPositions(code.asCfCode())) {
+ } else if (code.isCfCode()
+ && doesContainPositions(code.asCfCode())
+ && !appView.isCfByteCodePassThrough(method)) {
optimizeCfCodePositions(method, kotlinRemapper, mappedPositions, appView);
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/ProgramMethodEquivalence.java b/src/main/java/com/android/tools/r8/utils/ProgramMethodEquivalence.java
new file mode 100644
index 0000000..91553b8
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/ProgramMethodEquivalence.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, 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.utils;
+
+import com.android.tools.r8.graph.ProgramMethod;
+import com.google.common.base.Equivalence;
+
+public class ProgramMethodEquivalence extends Equivalence<ProgramMethod> {
+
+ private static final ProgramMethodEquivalence INSTANCE = new ProgramMethodEquivalence();
+
+ private ProgramMethodEquivalence() {}
+
+ public static ProgramMethodEquivalence get() {
+ return INSTANCE;
+ }
+
+ @Override
+ protected boolean doEquivalent(ProgramMethod method, ProgramMethod other) {
+ return method.getDefinition() == other.getDefinition();
+ }
+
+ @Override
+ protected int doHash(ProgramMethod method) {
+ return method.getReference().hashCode();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/ProgramFieldSet.java b/src/main/java/com/android/tools/r8/utils/collections/ProgramFieldSet.java
new file mode 100644
index 0000000..5a9e280
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/collections/ProgramFieldSet.java
@@ -0,0 +1,99 @@
+// Copyright (c) 2020, 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.utils.collections;
+
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.ProgramField;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+
+public class ProgramFieldSet implements Iterable<ProgramField> {
+
+ private static final ProgramFieldSet EMPTY = new ProgramFieldSet(ImmutableMap.of());
+
+ private Map<DexField, ProgramField> backing;
+
+ private ProgramFieldSet(Map<DexField, ProgramField> backing) {
+ this.backing = backing;
+ }
+
+ public static ProgramFieldSet create() {
+ return new ProgramFieldSet(new IdentityHashMap<>());
+ }
+
+ public static ProgramFieldSet empty() {
+ return EMPTY;
+ }
+
+ public boolean add(ProgramField field) {
+ ProgramField existing = backing.put(field.getReference(), field);
+ assert existing == null || existing.isStructurallyEqualTo(field);
+ return existing == null;
+ }
+
+ public void addAll(Iterable<ProgramField> fields) {
+ fields.forEach(this::add);
+ }
+
+ public void addAll(ProgramFieldSet fields) {
+ backing.putAll(fields.backing);
+ }
+
+ public boolean createAndAdd(DexProgramClass clazz, DexEncodedField definition) {
+ return add(new ProgramField(clazz, definition));
+ }
+
+ public boolean contains(DexEncodedField field) {
+ return backing.containsKey(field.toReference());
+ }
+
+ public boolean contains(ProgramField field) {
+ return backing.containsKey(field.getReference());
+ }
+
+ public void clear() {
+ backing.clear();
+ }
+
+ public boolean isEmpty() {
+ return backing.isEmpty();
+ }
+
+ @Override
+ public Iterator<ProgramField> iterator() {
+ return backing.values().iterator();
+ }
+
+ public boolean remove(DexField field) {
+ ProgramField existing = backing.remove(field);
+ return existing != null;
+ }
+
+ public boolean remove(DexEncodedField field) {
+ return remove(field.toReference());
+ }
+
+ public int size() {
+ return backing.size();
+ }
+
+ public Stream<ProgramField> stream() {
+ return backing.values().stream();
+ }
+
+ public Set<DexEncodedField> toDefinitionSet() {
+ assert backing instanceof IdentityHashMap;
+ Set<DexEncodedField> definitions = Sets.newIdentityHashSet();
+ forEach(field -> definitions.add(field.getDefinition()));
+ return definitions;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/CfFrontendExamplesTest.java b/src/test/java/com/android/tools/r8/CfFrontendExamplesTest.java
index d881974..2ae20c9 100644
--- a/src/test/java/com/android/tools/r8/CfFrontendExamplesTest.java
+++ b/src/test/java/com/android/tools/r8/CfFrontendExamplesTest.java
@@ -352,18 +352,18 @@
return descriptorList;
}
- private static byte[] getClassAsBytes(ArchiveClassFileProvider inputJar, String descriptor)
+ public static byte[] getClassAsBytes(ClassFileResourceProvider inputJar, String descriptor)
throws Exception {
return toByteArray(inputJar.getProgramResource(descriptor).getByteStream());
}
- private static String asmToString(byte[] clazz) {
+ public static String asmToString(byte[] clazz) {
StringWriter stringWriter = new StringWriter();
printAsm(new PrintWriter(stringWriter), clazz);
return stringWriter.toString();
}
- private static void printAsm(PrintWriter pw, byte[] clazz) {
+ public static void printAsm(PrintWriter pw, byte[] clazz) {
new ClassReader(clazz).accept(new TraceClassVisitor(null, new ASMifierSorted(), pw), 0);
}
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 7938666..000ffbc 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -33,6 +33,7 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.SmaliWriter;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.jasmin.JasminBuilder;
@@ -1294,13 +1295,14 @@
return getMethodSubject(application, className, returnType, methodName, parameters).getMethod();
}
- protected DexEncodedMethod getMethod(
+ protected ProgramMethod getMethod(
CodeInspector inspector,
String className,
String returnType,
String methodName,
List<String> parameters) {
- return getMethodSubject(inspector, className, returnType, methodName, parameters).getMethod();
+ return getMethodSubject(inspector, className, returnType, methodName, parameters)
+ .getProgramMethod();
}
protected static void checkInstructions(
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/AccessRelaxationProguardCompatTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/AccessRelaxationProguardCompatTest.java
index 7ea2765..3efb9b1 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/AccessRelaxationProguardCompatTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/AccessRelaxationProguardCompatTest.java
@@ -15,10 +15,7 @@
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import org.junit.Test;
-/**
- * Tests that both R8 and Proguard may change the visibility of a field or method that is explicitly
- * kept.
- */
+/** Tests that Proguard may change the visibility of a field or method that is explicitly kept. */
public class AccessRelaxationProguardCompatTest extends TestBase {
private static Class<?> clazz = AccessRelaxationProguardCompatTestClass.class;
@@ -35,7 +32,7 @@
"}")
.allowAccessModification()
.compile()
- .inspect(AccessRelaxationProguardCompatTest::inspect);
+ .inspect(inspector -> inspect(inspector, true));
}
@Test
@@ -49,10 +46,10 @@
"}")
.allowAccessModification()
.compile()
- .inspect(AccessRelaxationProguardCompatTest::inspect);
+ .inspect(inspector -> inspect(inspector, false));
}
- private static void inspect(CodeInspector inspector) {
+ private static void inspect(CodeInspector inspector, boolean isR8) {
ClassSubject classSubject = inspector.clazz(clazzWithGetter);
assertThat(classSubject, isPresent());
@@ -60,7 +57,11 @@
assertThat(fieldSubject, isPresent());
// Although this field was explicitly kept, it is no longer private.
- assertThat(fieldSubject, not(isPrivate()));
+ if (isR8) {
+ assertThat(fieldSubject, isPrivate());
+ } else {
+ assertThat(fieldSubject, not(isPrivate()));
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/PrivateKeptMembersPublicizerTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/PrivateKeptMembersPublicizerTest.java
new file mode 100644
index 0000000..940479a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/PrivateKeptMembersPublicizerTest.java
@@ -0,0 +1,67 @@
+// Copyright (c) 2020, 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.accessrelaxation;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class PrivateKeptMembersPublicizerTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public PrivateKeptMembersPublicizerTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(PrivateKeptMembersPublicizerTest.class)
+ .addKeepClassAndMembersRules(TestClass.class)
+ .allowAccessModification()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello world!");
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject classSubject = inspector.clazz(TestClass.class);
+ assertThat(classSubject, isPresent());
+ assertTrue(classSubject.uniqueFieldWithName("greeting").isPrivate());
+ assertTrue(classSubject.uniqueMethodWithName("greet").isPrivate());
+ }
+
+ static class TestClass {
+
+ private static String greeting = "Hello world!";
+
+ public static void main(String[] args) {
+ greet(greeting);
+ }
+
+ private static void greet(String message) {
+ System.out.println(message);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/classmerging/KeptTargetsIncompleteDiamondTest.java b/src/test/java/com/android/tools/r8/classmerging/KeptTargetsIncompleteDiamondTest.java
index de3afb5..c27b55b 100644
--- a/src/test/java/com/android/tools/r8/classmerging/KeptTargetsIncompleteDiamondTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/KeptTargetsIncompleteDiamondTest.java
@@ -73,7 +73,7 @@
// }
AppView<AppInfoWithLiveness> appView = computeAppViewWithLiveness(I.class, I.class);
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appView.dexItemFactory());
- ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appView.appInfo().resolveMethodOnInterface(method);
DexType typeI = buildType(I.class, appView.dexItemFactory());
DexType typeL = buildType(L.class, appView.dexItemFactory());
DexType typeA = buildType(A.class, appView.dexItemFactory());
@@ -114,7 +114,7 @@
// }
AppView<AppInfoWithLiveness> appView = computeAppViewWithLiveness(I.class, I.class);
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appView.dexItemFactory());
- ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appView.appInfo().resolveMethodOnInterface(method);
DexType typeI = buildType(I.class, appView.dexItemFactory());
DexType typeL = buildType(L.class, appView.dexItemFactory());
DexType typeA = buildType(A.class, appView.dexItemFactory());
@@ -154,7 +154,7 @@
// }
AppView<AppInfoWithLiveness> appView = computeAppViewWithLiveness(J.class, J.class);
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appView.dexItemFactory());
- ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appView.appInfo().resolveMethodOnInterface(method);
DexType typeI = buildType(I.class, appView.dexItemFactory());
DexType typeB = buildType(A.class, appView.dexItemFactory());
DexProgramClass classI = appView.definitionForProgramType(typeI);
@@ -191,7 +191,7 @@
// }
AppView<AppInfoWithLiveness> appView = computeAppViewWithLiveness(J.class, A.class);
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appView.dexItemFactory());
- ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appView.appInfo().resolveMethodOnInterface(method);
DexType typeI = buildType(I.class, appView.dexItemFactory());
DexType typeB = buildType(A.class, appView.dexItemFactory());
DexProgramClass classI = appView.definitionForProgramType(typeI);
@@ -230,7 +230,7 @@
// }
AppView<AppInfoWithLiveness> appView = computeAppViewWithLiveness(I.class, I.class);
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appView.dexItemFactory());
- ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appView.appInfo().resolveMethodOnInterface(method);
DexType typeI = buildType(I.class, appView.dexItemFactory());
DexType typeB = buildType(A.class, appView.dexItemFactory());
DexProgramClass classI = appView.definitionForProgramType(typeI);
diff --git a/src/test/java/com/android/tools/r8/code/PassThroughTest.java b/src/test/java/com/android/tools/r8/code/PassThroughTest.java
new file mode 100644
index 0000000..b1a9f2f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/code/PassThroughTest.java
@@ -0,0 +1,160 @@
+// Copyright (c) 2020, 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.code;
+
+import static junit.framework.Assert.assertSame;
+
+import com.android.tools.r8.ArchiveClassFileProvider;
+import com.android.tools.r8.CfFrontendExamplesTest;
+import com.android.tools.r8.ClassFileResourceProvider;
+import com.android.tools.r8.DirectoryClassFileProvider;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestShrinkerBuilder;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class PassThroughTest extends TestBase {
+
+ private final String EXPECTED = StringUtils.lines("0", "foo", "0");
+
+ private final TestParameters parameters;
+ private final boolean keepDebug;
+
+ @Parameters(name = "{0}, keep-debug: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(getTestParameters().withCfRuntimes().build(), BooleanUtils.values());
+ }
+
+ public PassThroughTest(TestParameters parameters, boolean keepDebug) {
+ this.parameters = parameters;
+ this.keepDebug = keepDebug;
+ }
+
+ @Test
+ public void testJmv() throws Exception {
+ CodeInspector inspector =
+ testForJvm()
+ .addProgramClasses(Main.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED)
+ .inspector();
+ // Check that reading the same input is actual matches.
+ ClassFileResourceProvider original =
+ DirectoryClassFileProvider.fromDirectory(ToolHelper.getClassPathForTests());
+ verifyInstructionsForMainMatchingExpectation(original, true, true);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ Path outputJar = temp.newFile("output.jar").toPath();
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Main.class)
+ .addKeepMainRule(Main.class)
+ .ifTrue(keepDebug, TestShrinkerBuilder::addKeepAllAttributes)
+ .compile()
+ .writeToZip(outputJar)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED);
+ verifyInstructionsForMainMatchingExpectation(
+ new ArchiveClassFileProvider(outputJar), keepDebug, false);
+ }
+
+ @Test
+ public void testR8ByteCodePassThrough() throws Exception {
+ Path outputJar = temp.newFile("output.jar").toPath();
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Main.class)
+ .addKeepMainRule(Main.class)
+ .ifTrue(keepDebug, TestShrinkerBuilder::addKeepAllAttributes)
+ .addOptionsModification(
+ internalOptions ->
+ internalOptions.testing.cfByteCodePassThrough =
+ method -> method.method.name.toString().equals("main"))
+ .compile()
+ .writeToZip(outputJar)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED);
+ verifyInstructionsForMainMatchingExpectation(
+ new ArchiveClassFileProvider(outputJar), keepDebug, true);
+ }
+
+ private void verifyInstructionsForMainMatchingExpectation(
+ ClassFileResourceProvider actual, boolean checkDebug, boolean expectation) throws Exception {
+ ClassFileResourceProvider original =
+ DirectoryClassFileProvider.fromDirectory(ToolHelper.getClassPathForTests());
+ String descriptor = DescriptorUtils.javaTypeToDescriptor(Main.class.getTypeName());
+ byte[] expectedBytes = CfFrontendExamplesTest.getClassAsBytes(original, descriptor);
+ byte[] actualBytes = CfFrontendExamplesTest.getClassAsBytes(actual, descriptor);
+ if (!Arrays.equals(expectedBytes, actualBytes)) {
+ String expectedString = CfFrontendExamplesTest.asmToString(expectedBytes);
+ String actualString = CfFrontendExamplesTest.asmToString(actualBytes);
+ verifyInstructionsForMainMatchingExpectation(
+ getMethodInstructions(expectedString),
+ getMethodInstructions(actualString),
+ checkDebug,
+ expectation);
+ }
+ }
+
+ private String getMethodInstructions(String asm) {
+ int methodIndexStart =
+ asm.indexOf(
+ "methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, \"main\","
+ + " \"([Ljava/lang/String;)V\", null, null);");
+ int methodIndexEnd = asm.indexOf("}", methodIndexStart);
+ return asm.substring(methodIndexStart, methodIndexEnd);
+ }
+
+ private void verifyInstructionsForMainMatchingExpectation(
+ String originalInstructions,
+ String actualInstructions,
+ boolean checkDebug,
+ boolean expectation) {
+ if (!checkDebug) {
+ originalInstructions =
+ StringUtils.splitLines(originalInstructions).stream()
+ .filter(this::isNotDebugInstruction)
+ .map(instr -> instr + "\n")
+ .collect(Collectors.joining());
+ }
+ assertSame(expectation, actualInstructions.equals(originalInstructions));
+ }
+
+ private boolean isNotDebugInstruction(String instruction) {
+ return !(instruction.startsWith("methodVisitor.visitLocalVariable")
+ || instruction.startsWith("methodVisitor.visitLabel")
+ || instruction.startsWith("Label")
+ || instruction.startsWith("methodVisitor.visitLineNumber"));
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ int i = 0;
+ System.out.println(i);
+ int j = 0;
+ String foo = "foo";
+ // Keep the false to have R8 remove it.
+ if (false) {
+ System.out.println(foo);
+ }
+ System.out.println(foo);
+ System.out.println(j);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java b/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java
index 5dac547..e9d9d79 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java
@@ -6,18 +6,16 @@
import static org.hamcrest.core.StringContains.containsString;
+import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.utils.AndroidApiLevel;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
@RunWith(Parameterized.class)
public class ApiLevelBackportsTest extends TestBase {
@@ -26,6 +24,8 @@
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
+ // NOTE: Most of the 'run' invocations below work only because the static configured APIs do not
+ // give rise to DEX file versions larger than what can be accepted by VM 9.0.0.
return getTestParameters().withDexRuntimesStartingFromIncluding(Version.V9_0_0).build();
}
@@ -36,22 +36,49 @@
@Test
public void backportSucceedsOnSupportedApiLevel() throws Exception {
testForD8()
- .addProgramClassFileData(Dump.mainWithMathMultiplyExactLongInt())
+ .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
.setMinApi(AndroidApiLevel.B)
- .run(parameters.getRuntime(), "Test")
+ .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
.assertSuccessWithOutputLines("4");
}
@Test
- public void warningForNonPlatformBuild() throws Exception {
+ public void backportOfNonPresentMethodOnLatest() throws Exception {
testForD8()
- .addProgramClassFileData(Dump.mainWithMathMultiplyExactLongInt())
- .setMinApi(30)
+ .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
+ .setMinApi(AndroidApiLevel.LATEST)
+ .compile()
+ .assertNoMessages()
+ .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
+ .assertSuccessWithOutputLines("4");
+ }
+
+ @Test
+ public void backportOfPresentMethodOnLatest() throws Exception {
+ D8TestRunResult result =
+ testForD8()
+ .addProgramClassFileData(transformTestListOf())
+ .setMinApi(AndroidApiLevel.LATEST)
+ .compile()
+ .assertNoMessages()
+ .run(parameters.getRuntime(), TestListOf.class);
+ if (runtimeHasListOf()) {
+ result.assertSuccessWithOutputLines("0");
+ } else {
+ result.assertFailureWithErrorThatMatches(
+ containsString("java.lang.NoSuchMethodError: No static method of()Ljava/util/List;"));
+ }
+ }
+
+ @Test
+ public void warningForFutureNonPlatformBuild() throws Exception {
+ testForD8()
+ .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
+ .setMinApi(AndroidApiLevel.LATEST.getLevel() + 1)
.compile()
.assertOnlyWarnings()
- .assertWarningMessageThatMatches(
- containsString("An API level of 30 is not supported by this compiler"))
- .run(parameters.getRuntime(), "Test")
+ .assertWarningMessageThatMatches(containsString("is not supported by this compiler"))
+ .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
.assertFailureWithErrorThatMatches(
containsString("java.lang.NoSuchMethodError: No static method multiplyExact(JI)J"));
}
@@ -59,70 +86,78 @@
@Test
public void noWarningForPlatformBuild() throws Exception {
testForD8()
- .addProgramClassFileData(Dump.mainWithMathMultiplyExactLongInt())
+ .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
.setMinApi(AndroidApiLevel.magicApiLevelUsedByAndroidPlatformBuild)
- .run(parameters.getRuntime(), "Test")
+ .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
.assertFailureWithErrorThatMatches(
containsString("java.lang.NoSuchMethodError: No static method multiplyExact(JI)J"));
}
- static class Dump implements Opcodes {
+ // Test class for using: List List.of()
+ // Introduced in Android R.
- // Code for:
- //
- // class Test {
- // public static void main(String[] args) {
- // // Call Math.multiplyExact(long, int), which is not in Android Q.
- // System.out.println(Math.multiplyExact(2L, 2));
- // }
- // }
- //
- static byte[] mainWithMathMultiplyExactLongInt() {
+ boolean runtimeHasListOf() {
+ return parameters
+ .getRuntime()
+ .asDex()
+ .getMinApiLevel()
+ .isGreaterThanOrEqualTo(AndroidApiLevel.R);
+ }
- ClassWriter classWriter = new ClassWriter(0);
- MethodVisitor methodVisitor;
+ byte[] transformTestListOf() throws Exception {
+ return transformer(TestListOf.class)
+ .transformMethodInsnInMethod(
+ "main",
+ (opcode, owner, name, descriptor, isInterface, visitor) -> {
+ if (name.equals("List_of")) {
+ visitor.visitMethodInsn(opcode, "java/util/List", "of", descriptor, isInterface);
+ } else {
+ visitor.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+ })
+ .transform();
+ }
- classWriter.visit(V1_8, ACC_SUPER, "Test", null, "java/lang/Object", null);
+ static class TestListOf {
+ public static List List_of() {
+ throw null;
+ }
- classWriter.visitSource("Test.java", null);
+ public static void main(String[] args) {
+ System.out.println(List_of().size());
+ }
+ }
- {
- methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
- methodVisitor.visitCode();
- Label label0 = new Label();
- methodVisitor.visitLabel(label0);
- methodVisitor.visitLineNumber(1, label0);
- methodVisitor.visitVarInsn(ALOAD, 0);
- methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
- methodVisitor.visitInsn(RETURN);
- methodVisitor.visitMaxs(1, 1);
- methodVisitor.visitEnd();
- }
- {
- methodVisitor =
- classWriter.visitMethod(
- ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
- methodVisitor.visitCode();
- Label label0 = new Label();
- methodVisitor.visitLabel(label0);
- methodVisitor.visitLineNumber(3, label0);
- methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
- methodVisitor.visitLdcInsn(Long.valueOf(2L));
- methodVisitor.visitLdcInsn(Integer.valueOf(2));
- methodVisitor.visitMethodInsn(
- INVOKESTATIC, "java/lang/Math", "multiplyExact", "(JI)J", false);
- methodVisitor.visitMethodInsn(
- INVOKEVIRTUAL, "java/io/PrintStream", "println", "(J)V", false);
- Label label1 = new Label();
- methodVisitor.visitLabel(label1);
- methodVisitor.visitLineNumber(4, label1);
- methodVisitor.visitInsn(RETURN);
- methodVisitor.visitMaxs(5, 1);
- methodVisitor.visitEnd();
- }
- classWriter.visitEnd();
+ // Test class for the method: long Math.multiplyExact(long, int)
+ // Not present on any currently known Android platforms.
- return classWriter.toByteArray();
+ boolean runtimeHasMathMultiplyExactLongInt() {
+ // NOTE: This may change with a future release.
+ return false;
+ }
+
+ byte[] transformTestMathMultiplyExactLongInt() throws Exception {
+ return transformer(TestMathMultiplyExactLongInt.class)
+ .transformMethodInsnInMethod(
+ "main",
+ (opcode, owner, name, descriptor, isInterface, visitor) -> {
+ if (name.equals("Math_multiplyExact")) {
+ visitor.visitMethodInsn(
+ opcode, "java/lang/Math", "multiplyExact", descriptor, isInterface);
+ } else {
+ visitor.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ }
+ })
+ .transform();
+ }
+
+ static class TestMathMultiplyExactLongInt {
+ public static long Math_multiplyExact(long l, int i) {
+ throw null;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(Math_multiplyExact(2L, 2));
}
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java
new file mode 100644
index 0000000..8dd0d27
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryWarningTest.java
@@ -0,0 +1,71 @@
+// Copyright (c) 2020, 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.desugar.desugaredlibrary;
+
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.L8Command;
+import com.android.tools.r8.OutputMode;
+import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanUtils;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DesugaredLibraryWarningTest extends DesugaredLibraryTestBase {
+
+ private static final String FUNCTION_KEEP =
+ "-keep class j$.util.function.Function$-CC {\n"
+ + " j$.util.function.Function $default$compose(j$.util.function.Function,"
+ + " j$.util.function.Function);\n"
+ + " j$.util.function.Function $default$andThen(j$.util.function.Function,"
+ + " j$.util.function.Function);\n"
+ + "}\n"
+ + "-keep class j$.util.function.Function { *; }";
+
+ private final TestParameters parameters;
+ private final boolean shrinkDesugaredLibrary;
+
+ @Parameterized.Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ BooleanUtils.values(), getTestParameters().withDexRuntimes().withAllApiLevels().build());
+ }
+
+ public DesugaredLibraryWarningTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
+ this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testDesugaredLibraryContent() throws Exception {
+ TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
+ Path desugaredLib = temp.newFolder().toPath().resolve("desugar_jdk_libs_dex.zip");
+ L8Command.Builder l8Builder =
+ L8Command.builder(diagnosticsHandler)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .addProgramFiles(ToolHelper.getDesugarJDKLibs())
+ .addProgramFiles(ToolHelper.DESUGAR_LIB_CONVERSIONS)
+ .setMode(shrinkDesugaredLibrary ? CompilationMode.RELEASE : CompilationMode.DEBUG)
+ .addDesugaredLibraryConfiguration(
+ StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
+ .setMinApiLevel(parameters.getApiLevel().getLevel())
+ .setOutput(desugaredLib, OutputMode.DexIndexed);
+ if (shrinkDesugaredLibrary) {
+ l8Builder.addProguardConfiguration(
+ Arrays.asList(FUNCTION_KEEP.split(System.lineSeparator())), Origin.unknown());
+ }
+ ToolHelper.runL8(l8Builder.build(), options -> {});
+ diagnosticsHandler.assertNoMessages();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
index 945f3c2..71d5ffb 100644
--- a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
+++ b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
@@ -25,6 +25,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -127,13 +128,15 @@
.addDexProgramData(Files.toByteArray(originalDexFile.toFile()), Origin.unknown())
.build();
CodeInspector inspector = new CodeInspector(application);
- DexEncodedMethod method = getMethod(
- inspector,
- "android.databinding.DataBinderMapperImpl",
- "android.databinding.ViewDataBinding",
- "getDataBinder",
- ImmutableList.of("android.databinding.DataBindingComponent", "android.view.View", "int"));
- Instruction[] instructions = method.getCode().asDexCode().instructions;
+ ProgramMethod method =
+ getMethod(
+ inspector,
+ "android.databinding.DataBinderMapperImpl",
+ "android.databinding.ViewDataBinding",
+ "getDataBinder",
+ ImmutableList.of(
+ "android.databinding.DataBindingComponent", "android.view.View", "int"));
+ Instruction[] instructions = method.getDefinition().getCode().asDexCode().instructions;
assertEquals(0, countJumboStrings(instructions));
assertEquals(1, countSimpleNops(instructions));
diff --git a/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java b/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
index 8524677..9c86160 100644
--- a/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/graph/TargetLookupTest.java
@@ -80,12 +80,11 @@
AndroidApp application = buildApplication(builder);
AppInfoWithClassHierarchy appInfo = computeAppInfoWithClassHierarchy(application);
CodeInspector inspector = new CodeInspector(appInfo.app());
- DexEncodedMethod method = getMethod(inspector, DEFAULT_CLASS_NAME, "int", "x",
- ImmutableList.of());
+ ProgramMethod method = getMethod(inspector, DEFAULT_CLASS_NAME, "int", "x", ImmutableList.of());
assertFalse(
- appInfo.resolveMethod(method.holder(), method.method).getSingleTarget().isVirtualMethod());
- assertNull(appInfo.lookupDirectTarget(method.method, method.holder()));
- assertNotNull(appInfo.lookupStaticTarget(method.method, method.holder()));
+ appInfo.resolveMethodOnClass(method.getReference()).getSingleTarget().isVirtualMethod());
+ assertNull(appInfo.lookupDirectTarget(method.getReference(), method));
+ assertNotNull(appInfo.lookupStaticTarget(method.getReference(), method));
if (ToolHelper.getDexVm().getVersion().isOlderThanOrEqual(DexVm.Version.V4_4_4)) {
// Dalvik rejects at verification time instead of producing the
@@ -152,32 +151,35 @@
AppInfoWithClassHierarchy appInfo = computeAppInfoWithClassHierarchy(application);
CodeInspector inspector = new CodeInspector(appInfo.app());
- DexMethod methodXOnTestSuper =
- getMethod(inspector, "TestSuper", "int", "x", ImmutableList.of()).method;
- DexMethod methodYOnTest =
- getMethod(inspector, "Test", "int", "y", ImmutableList.of()).method;
+ ProgramMethod methodXOnTestSuper =
+ getMethod(inspector, "TestSuper", "int", "x", ImmutableList.of());
+ ProgramMethod methodYOnTest = getMethod(inspector, "Test", "int", "y", ImmutableList.of());
- DexType classTestSuper = methodXOnTestSuper.holder;
- DexType classTest = methodYOnTest.holder;
- DexProto methodXProto = methodXOnTestSuper.proto;
- DexString methodXName = methodXOnTestSuper.name;
- DexMethod methodXOnTest =
+ DexType classTestSuper = methodXOnTestSuper.getHolderType();
+ DexType classTest = methodYOnTest.getHolderType();
+ DexProto methodXProto = methodXOnTestSuper.getReference().proto;
+ DexString methodXName = methodXOnTestSuper.getReference().name;
+ DexMethod methodXOnTestReference =
appInfo.dexItemFactory().createMethod(classTest, methodXProto, methodXName);
assertFalse(
appInfo
- .resolveMethod(classTestSuper, methodXOnTestSuper)
+ .resolveMethodOnClass(methodXOnTestSuper.getReference(), classTestSuper)
.getSingleTarget()
.isVirtualMethod());
- assertNull(appInfo.resolveMethod(classTest, methodXOnTestSuper).getSingleTarget());
- assertNull(appInfo.resolveMethod(classTest, methodXOnTest).getSingleTarget());
+ assertNull(
+ appInfo
+ .resolveMethodOnClass(methodXOnTestSuper.getReference(), classTest)
+ .getSingleTarget());
+ assertNull(appInfo.resolveMethodOnClass(methodXOnTestReference, classTest).getSingleTarget());
- assertNull(appInfo.lookupDirectTarget(methodXOnTestSuper, methodXOnTestSuper.holder));
- assertNull(appInfo.lookupDirectTarget(methodXOnTest, methodXOnTest.holder));
+ assertNull(appInfo.lookupDirectTarget(methodXOnTestSuper.getReference(), methodXOnTestSuper));
+ assertNull(appInfo.lookupDirectTarget(methodXOnTestReference, methodYOnTest));
- assertNotNull(appInfo.lookupStaticTarget(methodXOnTestSuper, methodXOnTestSuper.holder));
+ assertNotNull(
+ appInfo.lookupStaticTarget(methodXOnTestSuper.getReference(), methodXOnTestSuper));
// Accessing a private target on a different type will fail resolution outright.
- assertNull(appInfo.lookupStaticTarget(methodXOnTest, methodXOnTest.holder));
+ assertNull(appInfo.lookupStaticTarget(methodXOnTestReference, methodYOnTest));
assertEquals("OK", runArt(application));
}
@@ -211,8 +213,7 @@
DexField aFieldOnInterface = factory
.createField(factory.createType("LInterface;"), factory.intType, "aField");
- assertEquals(aFieldOnInterface,
- appInfo.lookupStaticTarget(aFieldOnSubClass.holder, aFieldOnSubClass).field);
+ assertEquals(aFieldOnInterface, appInfo.lookupStaticTarget(aFieldOnSubClass).field);
assertEquals("42", runArt(application));
@@ -244,13 +245,13 @@
DexType i3 = factory.createType("L" + pkg + "/I3;");
DexType i4 = factory.createType("L" + pkg + "/I4;");
DexType c0 = factory.createType("L" + pkg + "/C0;");
- DexType c1 = factory.createType("L" + pkg + "/C1;");
- DexType c2 = factory.createType("L" + pkg + "/C2;");
+ DexProgramClass c1 = appInfo.definitionForProgramType(factory.createType("L" + pkg + "/C1;"));
+ DexProgramClass c2 = appInfo.definitionForProgramType(factory.createType("L" + pkg + "/C2;"));
DexProto mProto = factory.createProto(factory.intType);
DexString m = factory.createString("m");
DexMethod mOnC0 = factory.createMethod(c0, mProto, m);
- DexMethod mOnC1 = factory.createMethod(c1, mProto, m);
+ DexMethod mOnC1 = factory.createMethod(c1.type, mProto, m);
DexMethod mOnI0 = factory.createMethod(i0, mProto, m);
DexMethod mOnI1 = factory.createMethod(i1, mProto, m);
DexMethod mOnI2 = factory.createMethod(i2, mProto, m);
diff --git a/src/test/java/com/android/tools/r8/internal/NestTreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/NestTreeShakeJarVerificationTest.java
index 2c06bd8..64b3fc0 100644
--- a/src/test/java/com/android/tools/r8/internal/NestTreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/NestTreeShakeJarVerificationTest.java
@@ -27,7 +27,7 @@
ImmutableList.of(BASE + DEPLOY_JAR));
assertEquals(0, filterKotlinMetadata(handler.warnings).count());
// TODO(b/155536535): We find bad descriptors. See if we can still resolve them.
- assertEquals(2, filterKotlinMetadata(handler.infos).count());
+ assertEquals(0, filterKotlinMetadata(handler.infos).count());
}
private Stream<Diagnostic> filterKotlinMetadata(List<Diagnostic> warnings) {
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
index ccbfd3a..5048226 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
@@ -72,10 +72,11 @@
private void testVirtualLookup(DexProgramClass clazz, DexEncodedMethod method) {
// Check lookup will produce the same result.
DexMethod id = method.method;
- assertEquals(appInfo().resolveMethod(id.holder, method.method).getSingleTarget(), method);
+ assertEquals(
+ appInfo().resolveMethodOnClass(method.method, id.holder).getSingleTarget(), method);
// Check lookup targets with include method.
- ResolutionResult resolutionResult = appInfo().resolveMethodOnClass(clazz, method.method);
+ ResolutionResult resolutionResult = appInfo().resolveMethodOnClass(method.method, clazz);
AppInfoWithLiveness appInfo = null; // TODO(b/154881041): Remove or compute liveness.
LookupResult lookupResult =
resolutionResult.lookupVirtualDispatchTargets(
diff --git a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
index 2b3e44d..7104c9a 100644
--- a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
+++ b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
@@ -8,7 +8,7 @@
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -61,8 +61,7 @@
InternalOptions options = new InternalOptions();
DexApplication application = buildApplication(builder, options);
- AppView<AppInfoWithClassHierarchy> appView =
- AppView.createForD8(new AppInfoWithClassHierarchy(application), options);
+ AppView<?> appView = AppView.createForD8(new AppInfo(application), options);
// Return the processed method for inspection.
MethodSubject methodSubject = getMethodSubject(application, signature);
@@ -178,8 +177,7 @@
InternalOptions options = new InternalOptions();
DexApplication application = buildApplication(builder, options);
- AppView<AppInfoWithClassHierarchy> appView =
- AppView.createForD8(new AppInfoWithClassHierarchy(application), options);
+ AppView<?> appView = AppView.createForD8(new AppInfo(application), options);
// Return the processed method for inspection.
MethodSubject methodSubject = getMethodSubject(application, signature);
@@ -303,8 +301,7 @@
InternalOptions options = new InternalOptions();
DexApplication application = buildApplication(builder, options);
- AppView<AppInfoWithClassHierarchy> appView =
- AppView.createForD8(new AppInfoWithClassHierarchy(application), options);
+ AppView<?> appView = AppView.createForD8(new AppInfo(application), options);
// Return the processed method for inspection.
MethodSubject methodSubject = getMethodSubject(application, signature);
@@ -427,8 +424,7 @@
InternalOptions options = new InternalOptions();
DexApplication application = buildApplication(builder, options);
- AppView<AppInfoWithClassHierarchy> appView =
- AppView.createForD8(new AppInfoWithClassHierarchy(application), options);
+ AppView<?> appView = AppView.createForD8(new AppInfo(application), options);
// Return the processed method for inspection.
MethodSubject methodSubject = getMethodSubject(application, signature);
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysisForNameReflectionTest.java b/src/test/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysisForNameReflectionTest.java
index c337379..9362432 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysisForNameReflectionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysisForNameReflectionTest.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.AnalysisTestBase;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -176,14 +177,14 @@
AppView<?> appView,
EscapeAnalysis escapeAnalysis,
Instruction escapeRoute,
- DexMethod context) {
+ ProgramMethod context) {
if (escapeRoute.isReturn() || escapeRoute.isThrow() || escapeRoute.isStaticPut()) {
return false;
}
if (escapeRoute.isInvokeMethod()) {
DexMethod invokedMethod = escapeRoute.asInvokeMethod().getInvokedMethod();
// Heuristic: if the call target has the same method name, it could be still local.
- if (invokedMethod.name == context.name) {
+ if (invokedMethod.name == context.getReference().name) {
return true;
}
// It's not legitimate during testing, except for recursion calls.
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java b/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
index 6177bf3..5a53fb5 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldBitAccessInfoTest.java
@@ -80,7 +80,7 @@
@Test
public void testOptimizationInfo() throws Exception {
- AppView<AppInfoWithClassHierarchy> appView = buildApp();
+ AppView<? extends AppInfoWithClassHierarchy> appView = buildApp();
OptimizationFeedbackMock feedback = new OptimizationFeedbackMock();
FieldBitAccessAnalysis fieldBitAccessAnalysis = new FieldBitAccessAnalysis();
FieldAccessAnalysis fieldAccessAnalysis =
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
index 2590f1b..1bee09a 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
@@ -11,6 +11,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.Argument;
@@ -45,7 +46,7 @@
boolean npeCaught,
BiConsumer<AppView<?>, IRCode> inspector)
throws Exception {
- AppView<?> appView = build(mainClass);
+ AppView<? extends AppInfoWithClassHierarchy> appView = build(mainClass);
CodeInspector codeInspector = new CodeInspector(appView.appInfo().app());
MethodSubject fooSubject = codeInspector.clazz(mainClass.getName()).method(signature);
IRCode irCode = fooSubject.buildIR();
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java
index 50742b5..3d28b08 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java
@@ -7,6 +7,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.InstancePut;
@@ -32,7 +33,7 @@
int expectedNumberOfNonNull,
Consumer<IRCode> testAugmentedIRCode)
throws Exception {
- AppView<?> appView = build(testClass);
+ AppView<? extends AppInfoWithClassHierarchy> appView = build(testClass);
CodeInspector codeInspector = new CodeInspector(appView.appInfo().app());
MethodSubject fooSubject = codeInspector.clazz(testClass.getName()).method(signature);
IRCode code = fooSubject.buildIR();
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
index 28ab813..4820221 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
@@ -16,14 +16,15 @@
public abstract class NonNullTrackerTestBase extends TestBase {
- protected AppView<?> build(Class<?> mainClass) throws Exception {
+ protected AppView<? extends AppInfoWithClassHierarchy> build(Class<?> mainClass)
+ throws Exception {
Timing timing = Timing.empty();
AndroidApp app = buildAndroidApp(ToolHelper.getClassAsBytes(mainClass));
InternalOptions options = new InternalOptions();
DirectMappedDexApplication dexApplication =
new ApplicationReader(app, options, timing).read().toDirect();
- AppView<?> appView =
- AppView.createForD8(new AppInfoWithClassHierarchy(dexApplication), options);
+ AppView<? extends AppInfoWithClassHierarchy> appView =
+ AppView.createForR8(new AppInfoWithClassHierarchy(dexApplication), options);
appView.setAppServices(AppServices.builder(appView).build());
return appView;
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/SimplifyIfNotNullTest.java b/src/test/java/com/android/tools/r8/ir/optimize/SimplifyIfNotNullTest.java
index 466b6fd..14d7e6b 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/SimplifyIfNotNullTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/SimplifyIfNotNullTest.java
@@ -31,16 +31,6 @@
}
}
- private void testD8(Class<?> testClass, List<MethodSignature> signatures) throws Exception {
- CodeInspector codeInspector =
- testForD8()
- .addProgramClasses(testClass)
- .addOptionsModification(options -> options.enableNonNullTracking = true)
- .compile()
- .inspector();
- verifyAbsenceOfIf(codeInspector, testClass, signatures);
- }
-
private void testR8(Class<?> testClass, List<MethodSignature> signatures) throws Exception {
CodeInspector codeInspector =
testForR8(Backend.DEX)
@@ -57,7 +47,6 @@
new MethodSignature("foo", "int", new String[]{"java.lang.String"});
MethodSignature bar =
new MethodSignature("bar", "int", new String[]{"java.lang.String"});
- testD8(NonNullAfterInvoke.class, ImmutableList.of(foo, bar));
testR8(NonNullAfterInvoke.class, ImmutableList.of(foo, bar));
}
@@ -67,7 +56,6 @@
new MethodSignature("foo", "int", new String[]{"java.lang.String[]"});
MethodSignature bar =
new MethodSignature("bar", "int", new String[]{"java.lang.String[]"});
- testD8(NonNullAfterArrayAccess.class, ImmutableList.of(foo, bar));
testR8(NonNullAfterArrayAccess.class, ImmutableList.of(foo, bar));
}
@@ -79,7 +67,6 @@
new String[]{FieldAccessTest.class.getCanonicalName()});
MethodSignature foo2 = new MethodSignature("foo2", "int",
new String[]{FieldAccessTest.class.getCanonicalName()});
- testD8(NonNullAfterFieldAccess.class, ImmutableList.of(foo, bar, foo2));
testR8(NonNullAfterFieldAccess.class, ImmutableList.of(foo, bar, foo2));
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliningWithImpreciseReceiverTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliningWithImpreciseReceiverTypeTest.java
new file mode 100644
index 0000000..cfdfcda
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliningWithImpreciseReceiverTypeTest.java
@@ -0,0 +1,87 @@
+// Copyright (c) 2020, 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.ir.optimize.classinliner;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ClassInliningWithImpreciseReceiverTypeTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public ClassInliningWithImpreciseReceiverTypeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(ClassInliningWithImpreciseReceiverTypeTest.class)
+ .addKeepMainRule(TestClass.class)
+ .enableInliningAnnotations()
+ .enableMergeAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("C1", "C2");
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ // After force inlining asB() and build(), the class inliner will attempt to force inline
+ // internalBuild(), but the receiver of that invoke is defined by a check-cast instruction
+ // that casts the receiver to B.
+ System.out.println(new C1().asB().build());
+ System.out.println(new C2().asB().build());
+ }
+ }
+
+ @NeverMerge
+ abstract static class A {
+
+ @NeverInline
+ B asB() {
+ return (B) this;
+ }
+
+ @NeverInline
+ String build() {
+ return internalBuild();
+ }
+
+ abstract String internalBuild();
+ }
+
+ abstract static class B extends A {}
+
+ static class C1 extends B {
+
+ @NeverInline
+ String internalBuild() {
+ return System.currentTimeMillis() > 0 ? "C1" : null;
+ }
+ }
+
+ static class C2 extends B {
+
+ @NeverInline
+ String internalBuild() {
+ return System.currentTimeMillis() > 0 ? "C2" : null;
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java
index f743bf2..c4dbbc4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java
@@ -106,31 +106,6 @@
}
@Test
- public void testD8() throws Exception {
- assumeTrue("Only run D8 for Dex backend", parameters.isDexRuntime());
-
- TestRunResult result =
- testForD8()
- .debug()
- .addProgramClassesAndInnerClasses(MAIN)
- .setMinApi(parameters.getRuntime())
- .addOptionsModification(options -> options.enableNonNullTracking = true)
- .run(parameters.getRuntime(), MAIN)
- .assertSuccessWithOutput(JAVA_OUTPUT);
- test(result, false, false);
-
- result =
- testForD8()
- .release()
- .addProgramClassesAndInnerClasses(MAIN)
- .setMinApi(parameters.getRuntime())
- .addOptionsModification(options -> options.enableNonNullTracking = true)
- .run(parameters.getRuntime(), MAIN)
- .assertSuccessWithOutput(JAVA_OUTPUT);
- test(result, false, true);
- }
-
- @Test
public void testR8() throws Exception {
TestRunResult result =
testForR8(parameters.getBackend())
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteBoxedTypesTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteBoxedTypesTest.java
new file mode 100644
index 0000000..bc0f2a4
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteBoxedTypesTest.java
@@ -0,0 +1,184 @@
+// Copyright (c) 2020, 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.kotlin.metadata;
+
+import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotNull;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertNull;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.kotlin.KotlinMetadataWriter;
+import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import kotlinx.metadata.jvm.KotlinClassHeader;
+import kotlinx.metadata.jvm.KotlinClassMetadata;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MetadataRewriteBoxedTypesTest extends KotlinMetadataTestBase {
+
+ private final String EXPECTED =
+ StringUtils.lines("false", "0", "a", "0.042", "0.42", "42", "442", "1", "2", "42", "42");
+
+ @Parameterized.Parameters(name = "{0} target: {1}")
+ public static Collection<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withCfRuntimes().build(), KotlinTargetVersion.values());
+ }
+
+ public MetadataRewriteBoxedTypesTest(
+ TestParameters parameters, KotlinTargetVersion targetVersion) {
+ super(targetVersion);
+ this.parameters = parameters;
+ }
+
+ private static Map<KotlinTargetVersion, Path> libJars = new HashMap<>();
+ private final TestParameters parameters;
+
+ @BeforeClass
+ public static void createLibJar() throws Exception {
+ String baseLibFolder = PKG_PREFIX + "/box_primitives_lib";
+ for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
+ Path baseLibJar =
+ kotlinc(KOTLINC, targetVersion)
+ .addSourceFiles(getKotlinFileInTest(baseLibFolder, "lib"))
+ .compile();
+ libJars.put(targetVersion, baseLibJar);
+ }
+ }
+
+ @Test
+ public void smokeTest() throws Exception {
+ Path libJar = libJars.get(targetVersion);
+ Path output =
+ kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
+ .addClasspathFiles(libJar)
+ .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/box_primitives_app", "main"))
+ .setOutputPath(temp.newFolder().toPath())
+ .compile();
+ testForJvm()
+ .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar(), libJar)
+ .addClasspath(output)
+ .run(parameters.getRuntime(), PKG + ".box_primitives_app.MainKt")
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void smokeTestReflection() throws Exception {
+ Path libJar = libJars.get(targetVersion);
+ Path output =
+ kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
+ .addClasspathFiles(libJar)
+ .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/box_primitives_app", "main_reflect"))
+ .setOutputPath(temp.newFolder().toPath())
+ .compile();
+ testForJvm()
+ .addVmArguments("-ea")
+ .addRunClasspathFiles(
+ ToolHelper.getKotlinStdlibJar(), ToolHelper.getKotlinReflectJar(), libJar)
+ .addClasspath(output)
+ .run(parameters.getRuntime(), PKG + ".box_primitives_app.Main_reflectKt")
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testMetadataForLib() throws Exception {
+ Path libJar =
+ testForR8(parameters.getBackend())
+ .addProgramFiles(libJars.get(targetVersion))
+ .addKeepAllClassesRule()
+ .addKeepAttributes(
+ ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS,
+ ProguardKeepAttributes.SIGNATURE,
+ ProguardKeepAttributes.INNER_CLASSES,
+ ProguardKeepAttributes.ENCLOSING_METHOD)
+ .compile()
+ .inspect(this::inspect)
+ .writeToZip();
+ Path main =
+ kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
+ .addClasspathFiles(libJar)
+ .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/box_primitives_app", "main"))
+ .setOutputPath(temp.newFolder().toPath())
+ .compile();
+ testForJvm()
+ .addRunClasspathFiles(
+ ToolHelper.getKotlinStdlibJar(), ToolHelper.getKotlinReflectJar(), libJar)
+ .addClasspath(main)
+ .run(parameters.getRuntime(), PKG + ".box_primitives_app.MainKt")
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ private void inspect(CodeInspector inspector) throws IOException, ExecutionException {
+ // Since this has a keep-all classes rule, we should just assert that the meta-data is equal to
+ // the original one.
+ CodeInspector stdLibInspector = new CodeInspector(libJars.get(targetVersion));
+ for (FoundClassSubject clazzSubject : stdLibInspector.allClasses()) {
+ ClassSubject r8Clazz = inspector.clazz(clazzSubject.getOriginalName());
+ assertThat(r8Clazz, isPresent());
+ KotlinClassMetadata originalMetadata = clazzSubject.getKotlinClassMetadata();
+ KotlinClassMetadata rewrittenMetadata = r8Clazz.getKotlinClassMetadata();
+ if (originalMetadata == null) {
+ assertNull(rewrittenMetadata);
+ continue;
+ }
+ assertNotNull(rewrittenMetadata);
+ KotlinClassHeader originalHeader = originalMetadata.getHeader();
+ KotlinClassHeader rewrittenHeader = rewrittenMetadata.getHeader();
+ assertEquals(originalHeader.getKind(), rewrittenHeader.getKind());
+ assertEquals(originalHeader.getPackageName(), rewrittenHeader.getPackageName());
+ // We cannot assert equality of the data since it may be ordered differently. Instead we use
+ // the KotlinMetadataWriter.
+ String expected = KotlinMetadataWriter.kotlinMetadataToString("", originalMetadata);
+ String actual = KotlinMetadataWriter.kotlinMetadataToString("", rewrittenMetadata);
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void testMetadataForReflect() throws Exception {
+ Path libJar =
+ testForR8(parameters.getBackend())
+ .addProgramFiles(libJars.get(targetVersion))
+ .addKeepAllClassesRule()
+ .addKeepAttributes(
+ ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS,
+ ProguardKeepAttributes.SIGNATURE,
+ ProguardKeepAttributes.INNER_CLASSES,
+ ProguardKeepAttributes.ENCLOSING_METHOD)
+ .compile()
+ .writeToZip();
+ Path main =
+ kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
+ .addClasspathFiles(libJar)
+ .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/box_primitives_app", "main_reflect"))
+ .setOutputPath(temp.newFolder().toPath())
+ .compile();
+ testForJvm()
+ .addVmArguments("-ea")
+ .addRunClasspathFiles(
+ ToolHelper.getKotlinStdlibJar(), ToolHelper.getKotlinReflectJar(), libJar)
+ .addClasspath(main)
+ .run(parameters.getRuntime(), PKG + ".box_primitives_app.Main_reflectKt")
+ .assertSuccessWithOutput(EXPECTED);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/box_primitives_app/main.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/box_primitives_app/main.kt
new file mode 100644
index 0000000..2a7cb0c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/box_primitives_app/main.kt
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, 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.kotlin.metadata.box_primitives_app
+
+import com.android.tools.r8.kotlin.metadata.box_primitives_lib.Test
+
+fun main() {
+ var test = Test()
+ test.testBoolean.add(test.boolean)
+ println(test.getFirstBoolean(test.testBoolean))
+ test.testByte.add(test.byte)
+ println(test.getFirstByte(test.testByte))
+ test.testChar.add(test.char)
+ println(test.getFirstChar(test.testChar))
+ test.testDouble.add(test.double)
+ println(test.getFirstDouble(test.testDouble))
+ test.testFloat.add(test.float)
+ println(test.getFirstFloat(test.testFloat))
+ test.testInt.add(test.int)
+ println(test.getFirstInt(test.testInt))
+ test.testLong.add(test.long)
+ println(test.getFirstLong(test.testLong))
+ test.testShort.add(test.short)
+ println(test.getFirstShort(test.testShort))
+ test.testNumber.add(test.number)
+ println(test.getFirstNumber(test.testNumber))
+ test.functionWithUnit { println(it) }
+ test.functionWithVoid { println(it); null }
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/box_primitives_app/main_reflect.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/box_primitives_app/main_reflect.kt
new file mode 100644
index 0000000..be89c90
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/box_primitives_app/main_reflect.kt
@@ -0,0 +1,72 @@
+// Copyright (c) 2020, 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.kotlin.metadata.box_primitives_app
+
+import com.android.tools.r8.kotlin.metadata.box_primitives_lib.Test
+
+fun trivialTypeAssertionsForProperties() {
+ val test = Test()
+ assert(test::boolean.returnType.classifier.toString().equals("class kotlin.Boolean"))
+ assert(test::byte.returnType.classifier.toString().equals("class kotlin.Byte"))
+ assert(test::char.returnType.classifier.toString().equals("class kotlin.Char"))
+ assert(test::double.returnType.classifier.toString().equals("class kotlin.Double"))
+ assert(test::float.returnType.classifier.toString().equals("class kotlin.Float"))
+ assert(test::int.returnType.classifier.toString().equals("class kotlin.Int"))
+ assert(test::long.returnType.classifier.toString().equals("class kotlin.Long"))
+ assert(test::short.returnType.classifier.toString().equals("class kotlin.Short"))
+ assert(test::number.returnType.classifier.toString().equals("class kotlin.Number"))
+}
+
+fun trivialTypeAssertionsForFunctions() {
+ val test = Test()
+ assert(test::getFirstBoolean.parameters.size == 1)
+ assert(test::getFirstBoolean.parameters.get(0).name == "l")
+ assert(test::getFirstBoolean
+ .parameters.get(0).type.classifier.toString() == "class kotlin.collections.List")
+ assert(test::getFirstBoolean.parameters.get(0).type.arguments.size == 1)
+ assert(test::getFirstBoolean
+ .parameters.get(0).type.arguments.get(0).type!!.classifier.toString().equals(
+ test::boolean.returnType.classifier.toString()))
+}
+
+fun runReflective() {
+ val test = Test()
+ // Test boxed types
+ test::boolean.set(false)
+ test::testBoolean.get().add(test::boolean.get())
+ println(test::getFirstBoolean.call(test::testBoolean.get()))
+ test::byte.set(0)
+ test::testByte.get().add(test::byte.get())
+ println(test::getFirstByte.call(test::testByte.get()))
+ test::char.set('a')
+ test::testChar.get().add(test::char.get())
+ println(test::getFirstChar.call(test::testChar.get()))
+ test::double.set(0.042)
+ test::testDouble.get().add(test::double.get())
+ println(test::getFirstDouble.call(test::testDouble.get()))
+ test::float.set(0.42F)
+ test::testFloat.get().add(test::float.get())
+ println(test::getFirstFloat.call(test::testFloat.get()))
+ test::int.set(42)
+ test::testInt.get().add(test::int.get())
+ println(test::getFirstInt.call(test::testInt.get()))
+ test::long.set(442)
+ test::testLong.get().add(test::long.get())
+ println(test::getFirstLong.call(test::testLong.get()))
+ test::short.set(1)
+ test::testShort.get().add(test::short.get())
+ println(test::getFirstShort.call(test::testShort.get()))
+ test::number.set(2)
+ test::testNumber.get().add(test::number.get())
+ println(test::getFirstNumber.call(test::testNumber.get()))
+ test::functionWithUnit.call({ i: Int -> println(i) })
+ test::functionWithVoid.call({ i: Int -> println(i); null })
+}
+
+fun main() {
+ trivialTypeAssertionsForProperties()
+ trivialTypeAssertionsForFunctions()
+ runReflective()
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/box_primitives_lib/lib.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/box_primitives_lib/lib.kt
new file mode 100644
index 0000000..7193b62
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/box_primitives_lib/lib.kt
@@ -0,0 +1,41 @@
+// Copyright (c) 2020, 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.kotlin.metadata.box_primitives_lib
+
+class Test {
+
+ val testReadOnly : List<Boolean> = listOf()
+
+ var boolean : Boolean = false
+ var testBoolean : MutableList<Boolean> = mutableListOf()
+ var byte : Byte = 0
+ var testByte : MutableList<Byte> = mutableListOf()
+ var char : Char = 'a'
+ var testChar : MutableList<Char> = mutableListOf()
+ var double : Double = 0.042
+ var testDouble : MutableList<Double> = mutableListOf()
+ var float : Float = 0.42F
+ var testFloat : MutableList<Float> = mutableListOf()
+ var int : Int = 42
+ var testInt : MutableList<Int> = mutableListOf()
+ var long : Long = 442
+ var testLong : MutableList<Long> = mutableListOf()
+ var short : Short = 1
+ var testShort : MutableList<Short> = mutableListOf()
+ var number : Number = 2
+ var testNumber : MutableList<Number> = mutableListOf()
+
+ fun getFirstBoolean(l : List<Boolean>) : Boolean = l.get(0)
+ fun getFirstByte(l : List<Byte>) : Byte = l.get(0)
+ fun getFirstChar(l : List<Char>) : Char = l.get(0)
+ fun getFirstDouble(l : List<Double>) : Double = l.get(0)
+ fun getFirstFloat(l : List<Float>) : Float = l.get(0)
+ fun getFirstInt(l : List<Int>) : Int = l.get(0)
+ fun getFirstLong(l : List<Long>) : Long = l.get(0)
+ fun getFirstShort(l : List<Short>) : Short = l.get(0)
+ fun getFirstNumber(l : List<Number>) : Number = l.get(0)
+ fun functionWithUnit(consumer : (Int) -> Unit) = consumer(42)
+ fun functionWithVoid(consumer : (Int) -> Void?) = consumer(42)
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java b/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java
index 02cb64e..4ad2bed 100644
--- a/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java
@@ -51,20 +51,18 @@
};
DexEncodedMethod langObjectNotifyMethod =
appInfo
- .resolveMethod(
- fooType,
+ .resolveMethodOnClass(
factory.createMethod(fooType, factory.createProto(factory.voidType), "notify"))
.getSingleTarget();
for (DexType arrType : arrayTypes) {
assertNull(
appInfo
- .resolveMethod(
- arrType, factory.createMethod(arrType, factory.createProto(arrType), "clone"))
+ .resolveMethodOnClass(
+ factory.createMethod(arrType, factory.createProto(arrType), "clone"))
.getSingleTarget());
DexEncodedMethod target =
appInfo
- .resolveMethod(
- arrType,
+ .resolveMethodOnClass(
factory.createMethod(arrType, factory.createProto(factory.voidType), "notify"))
.getSingleTarget();
assertEquals(langObjectNotifyMethod, target);
diff --git a/src/test/java/com/android/tools/r8/resolution/InvokeSuperCallInStaticTest.java b/src/test/java/com/android/tools/r8/resolution/InvokeSuperCallInStaticTest.java
index bade483..8f4ec7b 100644
--- a/src/test/java/com/android/tools/r8/resolution/InvokeSuperCallInStaticTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/InvokeSuperCallInStaticTest.java
@@ -58,7 +58,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(Base.class, "collect", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
assertTrue(resolutionResult.isSingleResolution());
DexProgramClass context =
appView.definitionForProgramType(buildType(A.class, appInfo.dexItemFactory()));
diff --git a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
index 7bd9cc9..c119db0 100644
--- a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.resolution.singletarget.Main;
import com.android.tools.r8.resolution.singletarget.one.AbstractSubClass;
@@ -32,9 +33,8 @@
import com.android.tools.r8.resolution.singletarget.two.OtherSubSubClassTwo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableList;
-import java.io.IOException;
+import com.google.common.collect.Sets;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.Assert;
@@ -76,9 +76,9 @@
public SingleTargetLookupTest(
String methodName,
- Class invokeReceiver,
- Class singleTargetHolderOrNull,
- List<Class> virtualTargetHolders) {
+ Class<?> invokeReceiver,
+ Class<?> singleTargetHolderOrNull,
+ List<Class<?>> virtualTargetHolders) {
this.methodName = methodName;
this.invokeReceiver = invokeReceiver;
this.singleTargetHolderOrNull = singleTargetHolderOrNull;
@@ -166,22 +166,24 @@
});
}
- private static DexType toType(Class clazz, AppInfo appInfo) {
+ private static DexType toType(Class<?> clazz, AppInfo appInfo) {
return buildType(clazz, appInfo.dexItemFactory());
}
private final String methodName;
- private final Class invokeReceiver;
- private final Class singleTargetHolderOrNull;
- private final List<Class> virtualTargetHolders;
+ private final Class<?> invokeReceiver;
+ private final Class<?> singleTargetHolderOrNull;
+ private final List<Class<?>> virtualTargetHolders;
@Test
public void lookupSingleTarget() {
- DexMethod method = buildNullaryVoidMethod(invokeReceiver, methodName, appInfo.dexItemFactory());
- Assert.assertNotNull(
- appInfo.resolveMethod(toType(invokeReceiver, appInfo), method).getSingleTarget());
+ DexMethod reference =
+ buildNullaryVoidMethod(invokeReceiver, methodName, appInfo.dexItemFactory());
+ ProgramMethod context =
+ appInfo.definitionForProgramType(reference.holder).getProgramDefaultInitializer();
+ Assert.assertNotNull(appInfo.resolveMethodOnClass(reference).getSingleTarget());
DexEncodedMethod singleVirtualTarget =
- appInfo.lookupSingleVirtualTarget(method, method.holder, false);
+ appInfo.lookupSingleVirtualTarget(reference, context, false);
if (singleTargetHolderOrNull == null) {
Assert.assertNull(singleVirtualTarget);
} else {
@@ -191,11 +193,10 @@
}
@Test
- public void lookupVirtualTargets() throws IOException {
+ public void lookupVirtualTargets() {
DexMethod method = buildNullaryVoidMethod(invokeReceiver, methodName, appInfo.dexItemFactory());
- Assert.assertNotNull(
- appInfo.resolveMethod(toType(invokeReceiver, appInfo), method).getSingleTarget());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ Assert.assertNotNull(appInfo.resolveMethodOnClass(method).getSingleTarget());
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
if (resolutionResult.isVirtualTarget()) {
LookupResult lookupResult =
resolutionResult.lookupVirtualDispatchTargets(
@@ -203,7 +204,7 @@
appInfo);
assertTrue(lookupResult.isLookupResultSuccess());
assertFalse(lookupResult.asLookupResultSuccess().hasLambdaTargets());
- Set<DexType> targetHolders = new HashSet<>();
+ Set<DexType> targetHolders = Sets.newIdentityHashSet();
lookupResult
.asLookupResultSuccess()
.forEach(
diff --git a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodTest.java b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodTest.java
index 28b468e..c0996fe 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodTest.java
@@ -80,7 +80,7 @@
@Test
public void resolveTarget() {
- ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB.holder, methodOnB);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB, methodOnB.holder);
assertTrue(resolutionResult instanceof IllegalAccessOrNoSuchMethodResult);
}
diff --git a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodWithVirtualParentTest.java b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodWithVirtualParentTest.java
index 1da4ff7..5da5b2d 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodWithVirtualParentTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfPrivateStaticMethodWithVirtualParentTest.java
@@ -101,7 +101,7 @@
@Test
public void testResolution() {
- ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB.holder, methodOnB);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB, methodOnB.holder);
assertTrue(resolutionResult.isFailedResolution());
}
diff --git a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
index eb40786..5b08461 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
@@ -14,6 +14,8 @@
import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -108,9 +110,9 @@
}
private final TestParameters parameters;
- private final DexMethod methodOnA = buildMethod(A.class, "f");
- private final DexMethod methodOnB = buildMethod(B.class, "f");
- private final DexMethod methodOnC = buildMethod(C.class, "f");
+ private final DexMethod methodOnAReference = buildMethod(A.class, "f");
+ private final DexMethod methodOnBReference = buildMethod(B.class, "f");
+ private final DexMethod methodOnCReference = buildMethod(C.class, "f");
public VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest(TestParameters parameters) {
this.parameters = parameters;
@@ -118,21 +120,24 @@
@Test
public void lookupSingleTarget() {
+ DexProgramClass bClass = appInfo.definitionForProgramType(methodOnBReference.holder);
+ ProgramMethod methodOnB = bClass.lookupProgramMethod(methodOnBReference);
ResolutionResult resolutionResult =
- appInfo.resolveMethodOnInterface(methodOnB.holder, methodOnB);
+ appInfo.resolveMethodOnInterface(methodOnBReference.holder, methodOnBReference);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
- assertEquals(methodOnB, resolved.method);
+ assertEquals(methodOnBReference, resolved.method);
assertFalse(resolutionResult.isVirtualTarget());
DexEncodedMethod singleVirtualTarget =
- appInfo.lookupSingleVirtualTarget(methodOnB, methodOnB.holder, false);
+ appInfo.lookupSingleVirtualTarget(methodOnBReference, methodOnB, false);
Assert.assertNull(singleVirtualTarget);
}
@Test
public void lookupVirtualTargets() {
- ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(methodOnB.holder, methodOnB);
+ ResolutionResult resolutionResult =
+ appInfo.resolveMethodOnInterface(methodOnBReference.holder, methodOnBReference);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
- assertEquals(methodOnB, resolved.method);
+ assertEquals(methodOnBReference, resolved.method);
assertFalse(resolutionResult.isVirtualTarget());
}
diff --git a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
index 1f24983..fe66478 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableList;
@@ -165,18 +166,19 @@
@Test
public void lookupSingleTarget() {
- ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB.holder, methodOnB);
+ DexProgramClass bClass = appInfo.definitionForProgramType(methodOnB.holder);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB, methodOnB.holder);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
assertEquals(methodOnA, resolved.method);
assertFalse(resolutionResult.isVirtualTarget());
DexEncodedMethod singleVirtualTarget =
- appInfo.lookupSingleVirtualTarget(methodOnB, methodOnB.holder, false);
+ appInfo.lookupSingleVirtualTarget(methodOnB, bClass.getProgramDefaultInitializer(), false);
Assert.assertNull(singleVirtualTarget);
}
@Test
public void lookupVirtualTargets() {
- ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB.holder, methodOnB);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB, methodOnB.holder);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
assertEquals(methodOnA, resolved.method);
assertFalse(resolutionResult.isVirtualTarget());
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java
index 67bf3e3..65e2ed5 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java
@@ -120,7 +120,7 @@
// Resolve the method from the point of the declared holder.
assertEquals(method.holder, declaredClassDefinition.type);
- ResolutionResult resolutionResult = appInfo.resolveMethod(declaredClassDefinition, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOn(declaredClassDefinition, method);
if (!symbolicReferenceIsDefiningType) {
// The targeted method is a private interface method and thus not a maximally specific method.
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessWithIntermediateTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessWithIntermediateTest.java
index a25f3c6..364014c 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessWithIntermediateTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessWithIntermediateTest.java
@@ -120,7 +120,7 @@
// Resolve the method from the point of the declared holder.
assertEquals(method.holder, declaredClassDefinition.type);
- ResolutionResult resolutionResult = appInfo.resolveMethod(declaredClassDefinition, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOn(declaredClassDefinition, method);
// The targeted method is a private interface method and thus not a maximally specific method.
assertTrue(resolutionResult instanceof NoSuchMethodResult);
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessTest.java
index 026055c..25a5d9e 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessTest.java
@@ -95,7 +95,7 @@
// Resolve the method from the point of the declared holder.
assertEquals(method.holder, declaredClassDefinition.type);
- ResolutionResult resolutionResult = appInfo.resolveMethod(declaredClassDefinition, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOn(declaredClassDefinition, method);
// Verify that the resolved method is on the defining class.
assertEquals(
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
index f1e182a..4453f58 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
@@ -121,7 +121,7 @@
// Resolve the method from the point of the declared holder.
assertEquals(method.holder, declaredClassDefinition.type);
- ResolutionResult resolutionResult = appInfo.resolveMethod(declaredClassDefinition, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOn(declaredClassDefinition, method);
// Resolution fails when there is a mismatch between the symbolic reference and the definition.
if (!symbolicReferenceIsDefiningType) {
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodPublicAccessWithIntermediateTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodPublicAccessWithIntermediateTest.java
index 4f013bb..aced457 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodPublicAccessWithIntermediateTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodPublicAccessWithIntermediateTest.java
@@ -97,7 +97,7 @@
// Resolve the method from the point of the declared holder.
assertEquals(method.holder, declaredClassDefinition.type);
- ResolutionResult resolutionResult = appInfo.resolveMethod(declaredClassDefinition, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOn(declaredClassDefinition, method);
// Verify that the resolved method is on the defining class.
assertEquals(
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestStaticMethodAccessTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestStaticMethodAccessTest.java
index 15f7edc..2000456 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestStaticMethodAccessTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestStaticMethodAccessTest.java
@@ -70,7 +70,7 @@
DexProgramClass bClass =
appInfo.definitionFor(buildType(B.class, appInfo.dexItemFactory())).asProgramClass();
DexMethod bar = buildMethod(A.class.getDeclaredMethod("bar"), appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(bar.holder, bar);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(bar);
assertEquals(OptionalBool.of(inSameNest), resolutionResult.isAccessibleFrom(bClass, appInfo));
}
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestStaticMethodAccessWithIntermediateClassTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestStaticMethodAccessWithIntermediateClassTest.java
index 4041e47..0460ce5 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestStaticMethodAccessWithIntermediateClassTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestStaticMethodAccessWithIntermediateClassTest.java
@@ -72,7 +72,7 @@
DexProgramClass bClass =
appInfo.definitionFor(buildType(B.class, appInfo.dexItemFactory())).asProgramClass();
DexMethod bar = buildMethod(A.class.getDeclaredMethod("bar"), appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(bar.holder, bar);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(bar);
assertEquals(OptionalBool.of(inSameNest), resolutionResult.isAccessibleFrom(bClass, appInfo));
}
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessTest.java
index 8dc4191..5e2743c 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessTest.java
@@ -72,7 +72,7 @@
DexProgramClass bClass =
appInfo.definitionFor(buildType(B.class, appInfo.dexItemFactory())).asProgramClass();
DexMethod bar = buildMethod(A.class.getDeclaredMethod("bar"), appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(bar.holder, bar);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(bar);
assertEquals(OptionalBool.of(inSameNest), resolutionResult.isAccessibleFrom(bClass, appInfo));
}
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessWithIntermediateClassTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessWithIntermediateClassTest.java
index d6e6ab9..4aff595 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessWithIntermediateClassTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessWithIntermediateClassTest.java
@@ -71,7 +71,7 @@
DexProgramClass bClass =
appInfo.definitionFor(buildType(B.class, appInfo.dexItemFactory())).asProgramClass();
DexMethod bar = buildMethod(A.class.getDeclaredMethod("bar"), appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(bar.holder, bar);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(bar);
assertEquals(OptionalBool.of(inSameNest), resolutionResult.isAccessibleFrom(bClass, appInfo));
}
diff --git a/src/test/java/com/android/tools/r8/resolution/access/SelfVirtualMethodAccessTest.java b/src/test/java/com/android/tools/r8/resolution/access/SelfVirtualMethodAccessTest.java
index 020ec02..f2d4c5c 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/SelfVirtualMethodAccessTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/SelfVirtualMethodAccessTest.java
@@ -56,7 +56,7 @@
DexProgramClass aClass =
appInfo.definitionFor(buildType(A.class, appInfo.dexItemFactory())).asProgramClass();
DexMethod bar = buildMethod(A.class.getDeclaredMethod("bar"), appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(bar.holder, bar);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(bar);
assertEquals(OptionalBool.TRUE, resolutionResult.isAccessibleFrom(aClass, appInfo));
}
diff --git a/src/test/java/com/android/tools/r8/resolution/access/indirectfield/IndirectFieldAccessTest.java b/src/test/java/com/android/tools/r8/resolution/access/indirectfield/IndirectFieldAccessTest.java
index 4616af8..4d0f445 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/indirectfield/IndirectFieldAccessTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/indirectfield/IndirectFieldAccessTest.java
@@ -4,17 +4,17 @@
package com.android.tools.r8.resolution.access.indirectfield;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRunResult;
-import com.android.tools.r8.graph.AccessControl;
import com.android.tools.r8.graph.AppView;
-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.DexProgramClass;
+import com.android.tools.r8.graph.FieldResolutionResult;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.resolution.access.indirectfield.pkg.C;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -53,18 +53,17 @@
AppInfoWithLiveness appInfo = appView.appInfo();
DexProgramClass cClass =
appInfo.definitionFor(buildType(C.class, appInfo.dexItemFactory())).asProgramClass();
+ ProgramMethod barMethod =
+ cClass.lookupProgramMethod(
+ buildMethod(C.class.getDeclaredMethod("bar"), appInfo.dexItemFactory()));
DexField f =
buildField(
// Reflecting on B.class.getField("f") will give A.f, so manually create the reference.
Reference.field(Reference.classFromClass(B.class), "f", Reference.INT),
appInfo.dexItemFactory());
- DexClass initialResolutionHolder = appInfo.definitionFor(f.holder);
- DexEncodedField resolutionTarget = appInfo.resolveField(f);
- // TODO(b/145723539): Test access via the resolution result once possible.
- assertEquals(
- OptionalBool.TRUE,
- AccessControl.isFieldAccessible(
- resolutionTarget, initialResolutionHolder, cClass, appInfo));
+ FieldResolutionResult resolutionResult = appInfo.resolveField(f);
+ assertTrue(resolutionResult.isSuccessfulResolution());
+ assertEquals(OptionalBool.TRUE, resolutionResult.isAccessibleFrom(barMethod, appInfo));
}
@Test
diff --git a/src/test/java/com/android/tools/r8/resolution/access/indirectmethod/IndirectMethodAccessTest.java b/src/test/java/com/android/tools/r8/resolution/access/indirectmethod/IndirectMethodAccessTest.java
index bdd8484..6e51158 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/indirectmethod/IndirectMethodAccessTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/indirectmethod/IndirectMethodAccessTest.java
@@ -61,7 +61,7 @@
DexProgramClass cClass =
appInfo.definitionFor(buildType(C.class, appInfo.dexItemFactory())).asProgramClass();
DexMethod bar = buildMethod(B.class.getMethod("foo"), appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(bar.holder, bar);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(bar);
assertEquals(
OptionalBool.TRUE, resolutionResult.isAccessibleForVirtualDispatchFrom(cClass, appInfo));
}
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/AbstractAllTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/AbstractAllTest.java
index b6023ce..b031eca 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/AbstractAllTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/AbstractAllTest.java
@@ -44,7 +44,7 @@
AndroidApp app = readClasses(CLASSES);
AppInfoWithLiveness appInfo = computeAppViewWithLiveness(app, Main.class).appInfo();
DexMethod method = buildNullaryVoidMethod(B.class, "f", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexEncodedMethod resolutionTarget = resolutionResult.getSingleTarget();
// Currently R8 will resolve to L::f as that is the first in the topological search.
// Resolution may return any of the matches, so it is valid if this expectation changes.
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultLeftAbstractRightTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultLeftAbstractRightTest.java
index 2068ef1..429b8d9 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultLeftAbstractRightTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultLeftAbstractRightTest.java
@@ -49,7 +49,7 @@
Main.class)
.appInfo();
DexMethod method = buildNullaryVoidMethod(B.class, "f", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexEncodedMethod resolutionTarget = resolutionResult.getSingleTarget();
assertEquals(L.class.getTypeName(), resolutionTarget.holder().toSourceString());
}
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultRightAbstractLeftTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultRightAbstractLeftTest.java
index 64908c4..a1e3185 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultRightAbstractLeftTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultRightAbstractLeftTest.java
@@ -49,7 +49,7 @@
Main.class)
.appInfo();
DexMethod method = buildNullaryVoidMethod(B.class, "f", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexEncodedMethod resolutionTarget = resolutionResult.getSingleTarget();
assertEquals(R.class.getTypeName(), resolutionTarget.holder().toSourceString());
}
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractLeftTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractLeftTest.java
index 4841f77..44c41eb 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractLeftTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractLeftTest.java
@@ -52,7 +52,7 @@
Main.class)
.appInfo();
DexMethod method = buildNullaryVoidMethod(B.class, "f", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexEncodedMethod resolutionTarget = resolutionResult.getSingleTarget();
assertEquals(L.class.getTypeName(), resolutionTarget.holder().toSourceString());
}
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractRightTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractRightTest.java
index 6059ea1..7683037 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractRightTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractRightTest.java
@@ -52,7 +52,7 @@
Main.class)
.appInfo();
DexMethod method = buildNullaryVoidMethod(B.class, "f", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexEncodedMethod resolutionTarget = resolutionResult.getSingleTarget();
assertEquals(R.class.getTypeName(), resolutionTarget.holder().toSourceString());
}
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndBothTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndBothTest.java
index 433575f..6fa3216 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndBothTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndBothTest.java
@@ -51,7 +51,7 @@
Main.class)
.appInfo();
DexMethod method = buildNullaryVoidMethod(B.class, "f", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
Set<String> holders = new HashSet<>();
resolutionResult
.asFailedResolution()
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndLeftTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndLeftTest.java
index e04908b..ccac0ed 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndLeftTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndLeftTest.java
@@ -43,7 +43,7 @@
AppInfoWithLiveness appInfo =
computeAppViewWithLiveness(readClasses(CLASSES), Main.class).appInfo();
DexMethod method = buildNullaryVoidMethod(B.class, "f", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexEncodedMethod resolutionTarget = resolutionResult.getSingleTarget();
assertEquals(L.class.getTypeName(), resolutionTarget.holder().toSourceString());
}
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndRightTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndRightTest.java
index 7472e89..54a9b59 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndRightTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAndRightTest.java
@@ -43,7 +43,7 @@
AppInfoWithLiveness appInfo =
computeAppViewWithLiveness(readClasses(CLASSES), Main.class).appInfo();
DexMethod method = buildNullaryVoidMethod(B.class, "f", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexEncodedMethod resolutionTarget = resolutionResult.getSingleTarget();
assertEquals(R.class.getTypeName(), resolutionTarget.holder().toSourceString());
}
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/TwoDefaultMethodsWithoutTopTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/TwoDefaultMethodsWithoutTopTest.java
index 5966b9d..a311b5a 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/TwoDefaultMethodsWithoutTopTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/TwoDefaultMethodsWithoutTopTest.java
@@ -52,7 +52,7 @@
Main.class)
.appInfo();
DexMethod method = buildNullaryVoidMethod(B.class, "f", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
Set<String> holders = new HashSet<>();
resolutionResult
.asFailedResolution()
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java
index e59009e..8d2a599 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java
@@ -59,7 +59,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Main.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
@@ -102,7 +102,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Main.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DuplicateImportsTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DuplicateImportsTest.java
index cb44081..ef5656d 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DuplicateImportsTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DuplicateImportsTest.java
@@ -57,7 +57,7 @@
buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Main.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
index 9a17065..e29f3fc 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
@@ -65,7 +65,7 @@
AssertionError.class,
() ->
appInfo
- .resolveMethod(method.holder, method)
+ .resolveMethodOnInterface(method)
.lookupVirtualDispatchTargets(context, appInfo));
}
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
index 81ed494..b4009fb 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
@@ -56,7 +56,7 @@
AssertionError.class,
() ->
appInfo
- .resolveMethod(method.holder, method)
+ .resolveMethodOnInterface(method)
.lookupVirtualDispatchTargets(context, appInfo));
}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateClasspathWidenTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateClasspathWidenTest.java
index f0b55f2..1033136 100644
--- a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateClasspathWidenTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateClasspathWidenTest.java
@@ -68,7 +68,7 @@
buildClasses(C.class, Main.class).addClasspathFiles(classPathJar).build(), Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(Abstract.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Abstract.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryTest.java
index 01d5afb..3a20a43 100644
--- a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryTest.java
@@ -56,7 +56,7 @@
buildClasses(A.class, B.class, C.class, D.class, Main.class).build(), Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "bar", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(A.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryWithNarrowingTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryWithNarrowingTest.java
index 37d915a..81920cb 100644
--- a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryWithNarrowingTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryWithNarrowingTest.java
@@ -60,7 +60,7 @@
buildClasses(A.class, B.class, C.class, D.class, Main.class).build(), Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "bar", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(A.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethod2Test.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethod2Test.java
index e8c34d1..a964f73 100644
--- a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethod2Test.java
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethod2Test.java
@@ -72,7 +72,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(A.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethodTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethodTest.java
index 338d00a..ed64145 100644
--- a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethodTest.java
@@ -71,7 +71,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(A.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/WidenAccessOutsidePackageTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/WidenAccessOutsidePackageTest.java
index e7d36e9..d86de60 100644
--- a/src/test/java/com/android/tools/r8/resolution/packageprivate/WidenAccessOutsidePackageTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/WidenAccessOutsidePackageTest.java
@@ -57,7 +57,7 @@
buildClasses(A.class, B.class, C.class, Main.class).build(), Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "bar", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(A.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java b/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
index c15c379..abd4956 100644
--- a/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
@@ -52,11 +53,15 @@
DexType typeA = buildType(A.class, appInfo.dexItemFactory());
DexType typeB = buildType(B.class, appInfo.dexItemFactory());
DexType typeMain = buildType(Main.class, appInfo.dexItemFactory());
+ DexMethod mainMethodReference =
+ buildMethod(Main.class.getDeclaredMethod("main", String[].class), appInfo.dexItemFactory());
+ ProgramMethod mainMethod =
+ appInfo.definitionForProgramType(typeMain).lookupProgramMethod(mainMethodReference);
DexMethod fooA = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
ClassTypeElement latticeB =
ClassTypeElement.create(typeB, Nullability.definitelyNotNull(), appView);
DexEncodedMethod singleTarget =
- appInfo.lookupSingleVirtualTarget(fooA, typeMain, false, t -> false, typeA, latticeB);
+ appInfo.lookupSingleVirtualTarget(fooA, mainMethod, false, t -> false, typeA, latticeB);
assertNotNull(singleTarget);
DexMethod fooB = buildNullaryVoidMethod(B.class, "foo", appInfo.dexItemFactory());
assertEquals(fooB, singleTarget.method);
@@ -72,11 +77,15 @@
DexType typeA = buildType(A.class, appInfo.dexItemFactory());
DexType typeB = buildType(B.class, appInfo.dexItemFactory());
DexType typeMain = buildType(Main.class, appInfo.dexItemFactory());
+ DexMethod mainMethodReference =
+ buildMethod(Main.class.getDeclaredMethod("main", String[].class), appInfo.dexItemFactory());
+ ProgramMethod mainMethod =
+ appInfo.definitionForProgramType(typeMain).lookupProgramMethod(mainMethodReference);
DexMethod fooA = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
ClassTypeElement latticeB =
ClassTypeElement.create(typeB, Nullability.definitelyNotNull(), appView);
DexEncodedMethod singleTarget =
- appInfo.lookupSingleVirtualTarget(fooA, typeMain, false, t -> false, typeA, latticeB);
+ appInfo.lookupSingleVirtualTarget(fooA, mainMethod, false, t -> false, typeA, latticeB);
assertNotNull(singleTarget);
DexMethod fooB = buildNullaryVoidMethod(B.class, "foo", appInfo.dexItemFactory());
assertEquals(fooB, singleTarget.method);
@@ -94,10 +103,14 @@
DexType typeA = buildType(A.class, appInfo.dexItemFactory());
DexType typeC = buildType(C.class, appInfo.dexItemFactory());
DexType typeMain = buildType(MainAllInstantiated.class, appInfo.dexItemFactory());
+ DexMethod mainMethodReference =
+ buildMethod(Main.class.getDeclaredMethod("main", String[].class), appInfo.dexItemFactory());
+ ProgramMethod mainMethod =
+ appInfo.definitionForProgramType(typeMain).lookupProgramMethod(mainMethodReference);
DexMethod fooA = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
DexMethod fooB = buildNullaryVoidMethod(B.class, "foo", appInfo.dexItemFactory());
DexMethod fooC = buildNullaryVoidMethod(C.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolution = appInfo.resolveMethod(typeA, fooA);
+ ResolutionResult resolution = appInfo.resolveMethodOnClass(fooA);
DexProgramClass context = appView.definitionForProgramType(typeMain);
DexProgramClass upperBound = appView.definitionForProgramType(typeA);
DexProgramClass lowerBound = appView.definitionForProgramType(typeC);
@@ -120,7 +133,7 @@
ClassTypeElement latticeC =
ClassTypeElement.create(typeC, Nullability.definitelyNotNull(), appView);
DexEncodedMethod singleTarget =
- appInfo.lookupSingleVirtualTarget(fooA, typeMain, false, t -> false, typeA, latticeC);
+ appInfo.lookupSingleVirtualTarget(fooA, mainMethod, false, t -> false, typeA, latticeC);
assertNull(singleTarget);
}
diff --git a/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java b/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java
index 870c9cc..9489060 100644
--- a/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/singletarget/SuccessAndInvalidLookupTest.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.ArrayList;
import org.junit.Test;
@@ -42,14 +43,18 @@
factory -> new ArrayList<>(buildKeepRuleForClassAndMethods(Main.class, factory)));
AppInfoWithLiveness appInfo = appView.appInfo();
DexType typeMain = buildType(Main.class, appInfo.dexItemFactory());
+ DexMethod mainMethodReference =
+ buildMethod(Main.class.getDeclaredMethod("main", String[].class), appInfo.dexItemFactory());
+ ProgramMethod mainMethod =
+ appInfo.definitionForProgramType(typeMain).lookupProgramMethod(mainMethodReference);
DexType typeA = buildType(A.class, appInfo.dexItemFactory());
DexMethod fooA = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
DexEncodedMethod singleTarget =
- appInfo.lookupSingleVirtualTarget(fooA, typeMain, false, t -> false, typeA, null);
+ appInfo.lookupSingleVirtualTarget(fooA, mainMethod, false, t -> false, typeA, null);
assertNotNull(singleTarget);
assertEquals(fooA, singleTarget.method);
DexEncodedMethod invalidSingleTarget =
- appInfo.lookupSingleVirtualTarget(fooA, typeMain, true, t -> false, typeA, null);
+ appInfo.lookupSingleVirtualTarget(fooA, mainMethod, true, t -> false, typeA, null);
assertNull(invalidSingleTarget);
}
@@ -61,15 +66,19 @@
factory -> new ArrayList<>(buildKeepRuleForClassAndMethods(Main.class, factory)));
AppInfoWithLiveness appInfo = appView.appInfo();
DexType typeMain = buildType(Main.class, appInfo.dexItemFactory());
+ DexMethod mainMethodReference =
+ buildMethod(Main.class.getDeclaredMethod("main", String[].class), appInfo.dexItemFactory());
+ ProgramMethod mainMethod =
+ appInfo.definitionForProgramType(typeMain).lookupProgramMethod(mainMethodReference);
DexType typeA = buildType(I.class, appInfo.dexItemFactory());
DexMethod fooI = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
DexMethod fooA = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
DexEncodedMethod singleTarget =
- appInfo.lookupSingleVirtualTarget(fooI, typeMain, true, t -> false, typeA, null);
+ appInfo.lookupSingleVirtualTarget(fooI, mainMethod, true, t -> false, typeA, null);
assertNotNull(singleTarget);
assertEquals(fooA, singleTarget.method);
DexEncodedMethod invalidSingleTarget =
- appInfo.lookupSingleVirtualTarget(fooI, typeMain, false, t -> false, typeA, null);
+ appInfo.lookupSingleVirtualTarget(fooI, mainMethod, false, t -> false, typeA, null);
assertNull(invalidSingleTarget);
}
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java
index 750c642..7f52044 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java
@@ -56,7 +56,7 @@
buildClasses(A.class, B.class, C.class, Main.class).build(), Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Main.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java
index 8bc102b..6264f35 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java
@@ -56,7 +56,7 @@
buildClasses(I.class, J.class, A.class, B.class, Main.class).build(), Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Main.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java
index 469c0ad..8f818b2 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java
@@ -56,7 +56,7 @@
buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Main.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java
index f025e17..2b236b5 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java
@@ -59,7 +59,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Main.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvalidResolutionToThisTarget.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvalidResolutionToThisTarget.java
index d8f8c4a..b75b7ac 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvalidResolutionToThisTarget.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvalidResolutionToThisTarget.java
@@ -58,7 +58,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
assertTrue(resolutionResult.isSingleResolution());
DexType mainType = buildType(Main.class, appInfo.dexItemFactory());
DexProgramClass main = appView.definitionForProgramType(mainType);
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java
index 472f7a1..9c7245c 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java
@@ -55,7 +55,7 @@
computeAppViewWithLiveness(buildClasses(A.class, I.class, Main.class).build(), Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Main.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java
index d3c1b7a..745ff4b 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/KeptTargetsIncompleteLookupTest.java
@@ -86,7 +86,7 @@
});
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(initial, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Unrelated.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
@@ -233,7 +233,7 @@
.build());
AppInfoWithClassHierarchy appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(B.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexType typeA = buildType(A.class, appInfo.dexItemFactory());
DexType typeB = buildType(B.class, appInfo.dexItemFactory());
DexProgramClass classB = appInfo.definitionForProgramType(typeB);
@@ -266,7 +266,7 @@
computeAppViewWithLiveness(buildClasses(Unrelated.class).build(), Unrelated.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(Unrelated.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Unrelated.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateChainTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateChainTest.java
index 477bed8..c74b196 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateChainTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateChainTest.java
@@ -61,7 +61,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(Top.class, "clear", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(TopRunner.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideTest.java
index b9f8c90..e5904db 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideTest.java
@@ -68,7 +68,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(ViewModel.class, "clear", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(
buildType(ViewModelRunner.class, appInfo.dexItemFactory()));
@@ -116,7 +116,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(ViewModel.class, "clear", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Main.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
@@ -162,7 +162,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(ViewModel.class, "clear", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(
buildType(ViewModelRunnerWithCast.class, appInfo.dexItemFactory()));
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PrivateOverrideOfVirtualTargetTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PrivateOverrideOfVirtualTargetTest.java
index c4fb6d2..e7319cd 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PrivateOverrideOfVirtualTargetTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PrivateOverrideOfVirtualTargetTest.java
@@ -60,7 +60,7 @@
Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "bar", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(B.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java
index b6f838b..fbf8ac5 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java
@@ -57,7 +57,7 @@
buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class);
AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
- ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method);
DexProgramClass context =
appView.definitionForProgramType(buildType(Main.class, appInfo.dexItemFactory()));
LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);