Do not duplicate resolution in lookupDispatchTarget
Change-Id: I2efc657c7e65715747b3c780566b22a275db7f35
diff --git a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
index e8290ab..6dbdc35 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
@@ -411,6 +411,7 @@
.lookupSingleVirtualTarget(
appViewWithLiveness,
invokedMethod,
+ this,
context,
invoke.getInterfaceBit(),
appView,
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/callgraph/InvokeExtractor.java b/src/main/java/com/android/tools/r8/ir/conversion/callgraph/InvokeExtractor.java
index 1f0e197..eb09ac7 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/callgraph/InvokeExtractor.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/callgraph/InvokeExtractor.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.ir.conversion.callgraph;
+import static com.android.tools.r8.graph.DexClassAndMethod.asProgramMethodOrNull;
+
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
@@ -77,20 +79,28 @@
.lookupMethod(originalMethod, context.getReference(), originalType, getCodeLens());
DexMethod method = result.getReference();
InvokeType type = result.getType();
- if (type == InvokeType.INTERFACE || type == InvokeType.VIRTUAL) {
+ MethodResolutionResult resolutionResult =
+ type.isInterface() || type.isVirtual()
+ ? appViewWithLiveness.appInfo().resolveMethodLegacy(method, type.isInterface())
+ : appViewWithLiveness.appInfo().unsafeResolveMethodDueToDexFormatLegacy(method);
+ if (!resolutionResult.isSingleResolution()) {
+ return;
+ }
+ if (type.isInterface() || type.isVirtual()) {
// For virtual and interface calls add all potential targets that could be called.
- MethodResolutionResult resolutionResult =
- appViewWithLiveness.appInfo().resolveMethodLegacy(method, type == InvokeType.INTERFACE);
- DexClassAndMethod target = resolutionResult.getResolutionPair();
- if (target != null) {
- processInvokeWithDynamicDispatch(type, target, context);
- }
+ processInvokeWithDynamicDispatch(type, resolutionResult.getResolutionPair(), context);
} else {
ProgramMethod singleTarget =
- appViewWithLiveness
- .appInfo()
- .lookupSingleProgramTarget(
- appViewWithLiveness, type, method, context, appViewWithLiveness);
+ asProgramMethodOrNull(
+ appViewWithLiveness
+ .appInfo()
+ .lookupSingleTarget(
+ appViewWithLiveness,
+ type,
+ method,
+ resolutionResult.asSingleResolution(),
+ context,
+ appViewWithLiveness));
if (singleTarget != null) {
processSingleTarget(singleTarget, context);
}
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 3bdf1c0..56c1ea4 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -1289,18 +1289,24 @@
AppView<AppInfoWithLiveness> appView,
InvokeType type,
DexMethod target,
+ SingleResolutionResult<?> resolutionResult,
ProgramMethod context,
LibraryModeledPredicate modeledPredicate) {
assert checkIfObsolete();
- DexType holder = target.holder;
- if (!holder.isClassType()) {
+ if (!target.getHolderType().isClassType()) {
return null;
}
switch (type) {
- case VIRTUAL:
- return lookupSingleVirtualTarget(appView, target, context, false, modeledPredicate);
case INTERFACE:
- return lookupSingleVirtualTarget(appView, target, context, true, modeledPredicate);
+ case VIRTUAL:
+ return lookupSingleVirtualTarget(
+ appView,
+ target,
+ resolutionResult,
+ context,
+ type.isInterface(),
+ modeledPredicate,
+ DynamicType.unknown());
case DIRECT:
return lookupDirectTarget(target, context, appView);
case STATIC:
@@ -1312,42 +1318,34 @@
}
}
- public ProgramMethod lookupSingleProgramTarget(
- AppView<AppInfoWithLiveness> appView,
- InvokeType type,
- DexMethod target,
- ProgramMethod context,
- LibraryModeledPredicate modeledPredicate) {
- return DexClassAndMethod.asProgramMethodOrNull(
- lookupSingleTarget(appView, type, target, context, modeledPredicate));
- }
-
/** For mapping invoke virtual instruction to single target method. */
- public DexClassAndMethod lookupSingleVirtualTarget(
- AppView<AppInfoWithLiveness> appView,
- DexMethod method,
- ProgramMethod context,
- boolean isInterface) {
- assert checkIfObsolete();
- return lookupSingleVirtualTarget(appView, method, context, isInterface, type -> false);
- }
-
- /** For mapping invoke virtual instruction to single target method. */
- public DexClassAndMethod lookupSingleVirtualTarget(
+ public DexClassAndMethod lookupSingleVirtualTargetForTesting(
AppView<AppInfoWithLiveness> appView,
DexMethod method,
ProgramMethod context,
boolean isInterface,
- LibraryModeledPredicate modeledPredicate) {
+ LibraryModeledPredicate modeledPredicate,
+ DynamicType dynamicReceiverType) {
assert checkIfObsolete();
- return lookupSingleVirtualTarget(
- appView, method, context, isInterface, modeledPredicate, DynamicType.unknown());
+ SingleResolutionResult<?> resolutionResult =
+ appView.appInfo().resolveMethodLegacy(method, isInterface).asSingleResolution();
+ if (resolutionResult != null) {
+ return lookupSingleVirtualTarget(
+ appView,
+ method,
+ resolutionResult,
+ context,
+ isInterface,
+ modeledPredicate,
+ dynamicReceiverType);
+ }
+ return null;
}
- @SuppressWarnings("ReferenceEquality")
public DexClassAndMethod lookupSingleVirtualTarget(
AppView<AppInfoWithLiveness> appView,
DexMethod method,
+ SingleResolutionResult<?> resolutionResult,
ProgramMethod context,
boolean isInterface,
LibraryModeledPredicate modeledPredicate,
@@ -1382,16 +1380,15 @@
return null;
}
}
- SingleResolutionResult<?> resolution =
- resolveMethodOnLegacy(initialResolutionHolder, method).asSingleResolution();
- if (resolution == null
- || resolution.isAccessibleForVirtualDispatchFrom(context.getHolder(), appView).isFalse()) {
+ if (resolutionResult
+ .isAccessibleForVirtualDispatchFrom(context.getHolder(), appView)
+ .isFalse()) {
return null;
}
// If the method is modeled, return the resolution.
- DexClassAndMethod resolvedMethod = resolution.getResolutionPair();
- if (modeledPredicate.isModeled(resolution.getResolvedHolder().getType())) {
- if (resolution.getResolvedHolder().isFinal()
+ DexClassAndMethod resolvedMethod = resolutionResult.getResolutionPair();
+ if (modeledPredicate.isModeled(resolutionResult.getResolvedHolder().getType())) {
+ if (resolutionResult.getResolvedHolder().isFinal()
|| (resolvedMethod.getAccessFlags().isFinal()
&& resolvedMethod.getAccessFlags().isPublic())) {
singleTargetLookupCache.addToCache(refinedReceiverType, method, resolvedMethod);
@@ -1402,7 +1399,7 @@
getMethodTargetFromExactRuntimeInformation(
refinedReceiverType,
dynamicReceiverType.getDynamicLowerBoundType(),
- resolution,
+ resolutionResult,
refinedReceiverClass);
if (exactTarget != null) {
// We are not caching single targets here because the cache does not include the
@@ -1416,7 +1413,7 @@
singleTargetLookupCache.addNoSingleTargetToCache(refinedReceiverType, method);
return null;
}
- DexClass resolvedHolder = resolution.getResolvedHolder();
+ DexClass resolvedHolder = resolutionResult.getResolvedHolder();
// TODO(b/148769279): Disable lookup single target on lambda's for now.
if (resolvedHolder.isInterface()
&& resolvedHolder.isProgramClass()
@@ -1439,7 +1436,7 @@
}
}
LookupResultSuccess lookupResult =
- resolution
+ resolutionResult
.lookupVirtualDispatchTargets(
context.getHolder(),
appView,
diff --git a/src/main/java/com/android/tools/r8/shaking/LibraryModeledPredicate.java b/src/main/java/com/android/tools/r8/shaking/LibraryModeledPredicate.java
index 39ee67c..00be009 100644
--- a/src/main/java/com/android/tools/r8/shaking/LibraryModeledPredicate.java
+++ b/src/main/java/com/android/tools/r8/shaking/LibraryModeledPredicate.java
@@ -10,4 +10,8 @@
public interface LibraryModeledPredicate {
boolean isModeled(DexType type);
+
+ static LibraryModeledPredicate alwaysFalse() {
+ return type -> false;
+ }
}
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 d32849b..afe93c0 100644
--- a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.analysis.type.DynamicType;
import com.android.tools.r8.resolution.singletarget.Main;
import com.android.tools.r8.resolution.singletarget.one.AbstractSubClass;
import com.android.tools.r8.resolution.singletarget.one.AbstractTopClass;
@@ -34,6 +35,7 @@
import com.android.tools.r8.resolution.singletarget.two.OtherSubSubClassOne;
import com.android.tools.r8.resolution.singletarget.two.OtherSubSubClassTwo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.LibraryModeledPredicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import java.util.Collections;
@@ -196,7 +198,13 @@
appInfo.definitionForProgramType(reference.holder).getProgramDefaultInitializer();
Assert.assertNotNull(appInfo.resolveMethodOnClassHolderLegacy(reference).getSingleTarget());
DexClassAndMethod singleVirtualTarget =
- appInfo.lookupSingleVirtualTarget(appView, reference, context, false);
+ appInfo.lookupSingleVirtualTargetForTesting(
+ appView,
+ reference,
+ context,
+ false,
+ LibraryModeledPredicate.alwaysFalse(),
+ DynamicType.unknown());
if (singleTargetHolderOrNull == null) {
Assert.assertNull(singleVirtualTarget);
} else {
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 e15e664..3cbd047 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
@@ -17,7 +17,9 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.analysis.type.DynamicType;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.LibraryModeledPredicate;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Assert;
@@ -134,7 +136,13 @@
assertEquals(methodOnBReference, resolved.getReference());
assertFalse(resolutionResult.isVirtualTarget());
DexClassAndMethod singleVirtualTarget =
- appInfo.lookupSingleVirtualTarget(appView, methodOnBReference, methodOnB, false);
+ appInfo.lookupSingleVirtualTargetForTesting(
+ appView,
+ methodOnBReference,
+ methodOnB,
+ false,
+ LibraryModeledPredicate.alwaysFalse(),
+ DynamicType.unknown());
Assert.assertNull(singleVirtualTarget);
}
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 d166b97..15aa8e9 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
@@ -19,7 +19,9 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.MethodResolutionResult;
+import com.android.tools.r8.ir.analysis.type.DynamicType;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.LibraryModeledPredicate;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Assert;
@@ -181,8 +183,13 @@
assertEquals(methodOnA, resolved.getReference());
assertFalse(resolutionResult.isVirtualTarget());
DexClassAndMethod singleVirtualTarget =
- appInfo.lookupSingleVirtualTarget(
- appView, methodOnB, bClass.getProgramDefaultInitializer(), false);
+ appInfo.lookupSingleVirtualTargetForTesting(
+ appView,
+ methodOnB,
+ bClass.getProgramDefaultInitializer(),
+ false,
+ LibraryModeledPredicate.alwaysFalse(),
+ DynamicType.unknown());
Assert.assertNull(singleVirtualTarget);
}
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 7b9b80c..4c11c91 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
@@ -25,6 +25,7 @@
import com.android.tools.r8.ir.analysis.type.DynamicTypeWithLowerBound;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.LibraryModeledPredicate;
import com.google.common.collect.Sets;
import java.util.Set;
import org.junit.Test;
@@ -65,12 +66,12 @@
TypeElement latticeA = typeA.toTypeElement(appView);
ClassTypeElement latticeB = typeB.toTypeElement(appView).asClassType();
DexClassAndMethod singleTarget =
- appInfo.lookupSingleVirtualTarget(
+ appInfo.lookupSingleVirtualTargetForTesting(
appView,
fooA,
mainMethod,
false,
- t -> false,
+ LibraryModeledPredicate.alwaysFalse(),
DynamicTypeWithLowerBound.create(appView, latticeA, latticeB));
assertNotNull(singleTarget);
DexMethod fooB = buildNullaryVoidMethod(B.class, "foo", appInfo.dexItemFactory());
@@ -98,12 +99,12 @@
TypeElement latticeA = typeA.toTypeElement(appView);
ClassTypeElement latticeB = typeB.toTypeElement(appView).asClassType();
DexClassAndMethod singleTarget =
- appInfo.lookupSingleVirtualTarget(
+ appInfo.lookupSingleVirtualTargetForTesting(
appView,
fooA,
mainMethod,
false,
- t -> false,
+ LibraryModeledPredicate.alwaysFalse(),
DynamicTypeWithLowerBound.create(appView, latticeA, latticeB));
assertNotNull(singleTarget);
DexMethod fooB = buildNullaryVoidMethod(B.class, "foo", appInfo.dexItemFactory());
@@ -154,12 +155,12 @@
TypeElement latticeA = typeA.toTypeElement(appView);
ClassTypeElement latticeC = typeC.toTypeElement(appView).asClassType();
DexClassAndMethod singleTarget =
- appInfo.lookupSingleVirtualTarget(
+ appInfo.lookupSingleVirtualTargetForTesting(
appView,
fooA,
mainMethod,
false,
- t -> false,
+ LibraryModeledPredicate.alwaysFalse(),
DynamicTypeWithLowerBound.create(appView, latticeA, 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 ec3815d..0a94601 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
@@ -21,6 +21,7 @@
import com.android.tools.r8.ir.analysis.type.DynamicTypeWithUpperBound;
import com.android.tools.r8.optimize.interfaces.collection.NonEmptyOpenClosedInterfacesCollection;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.LibraryModeledPredicate;
import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -59,13 +60,13 @@
DynamicTypeWithUpperBound.create(appView, typeA.toTypeElement(appView));
DexMethod fooA = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
DexClassAndMethod singleTarget =
- appInfo.lookupSingleVirtualTarget(
- appView, fooA, mainMethod, false, t -> false, dynamicTypeA);
+ appInfo.lookupSingleVirtualTargetForTesting(
+ appView, fooA, mainMethod, false, LibraryModeledPredicate.alwaysFalse(), dynamicTypeA);
assertNotNull(singleTarget);
assertEquals(fooA, singleTarget.getReference());
DexClassAndMethod invalidSingleTarget =
- appInfo.lookupSingleVirtualTarget(
- appView, fooA, mainMethod, true, t -> false, dynamicTypeA);
+ appInfo.lookupSingleVirtualTargetForTesting(
+ appView, fooA, mainMethod, true, LibraryModeledPredicate.alwaysFalse(), dynamicTypeA);
assertNull(invalidSingleTarget);
}
@@ -92,13 +93,13 @@
DexMethod fooI = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
DexMethod fooA = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
DexClassAndMethod singleTarget =
- appInfo.lookupSingleVirtualTarget(
- appView, fooI, mainMethod, true, t -> false, dynamicTypeA);
+ appInfo.lookupSingleVirtualTargetForTesting(
+ appView, fooI, mainMethod, true, LibraryModeledPredicate.alwaysFalse(), dynamicTypeA);
assertNotNull(singleTarget);
assertEquals(fooA, singleTarget.getReference());
DexClassAndMethod invalidSingleTarget =
- appInfo.lookupSingleVirtualTarget(
- appView, fooI, mainMethod, false, t -> false, dynamicTypeA);
+ appInfo.lookupSingleVirtualTargetForTesting(
+ appView, fooI, mainMethod, false, LibraryModeledPredicate.alwaysFalse(), dynamicTypeA);
assertNull(invalidSingleTarget);
}