Return a single dispatch target for final methods
Change-Id: I9ddbd7e8db63063bd90f86519570a3ff97b3565a
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 56c1ea4..b7f9c4f 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -1361,8 +1361,8 @@
.isDefinitelyInstanceOfStaticType(appView, () -> dynamicReceiverType, staticReceiverType)) {
return null;
}
- DexClass initialResolutionHolder = definitionFor(method.holder);
- if (initialResolutionHolder == null || initialResolutionHolder.isInterface() != isInterface) {
+ DexClass initialResolutionHolder = resolutionResult.getInitialResolutionHolder();
+ if (initialResolutionHolder.isInterface() != isInterface) {
return null;
}
DexType refinedReceiverType =
@@ -1372,27 +1372,24 @@
// The refined receiver is not defined in the program and we cannot determine the target.
return null;
}
- if (!dynamicReceiverType.hasDynamicLowerBoundType()) {
- if (singleTargetLookupCache.hasPositiveCacheHit(refinedReceiverType, method)) {
- return singleTargetLookupCache.getPositiveCacheHit(refinedReceiverType, method);
- }
- if (singleTargetLookupCache.hasNegativeCacheHit(refinedReceiverType, method)) {
- return null;
- }
+ if (singleTargetLookupCache.hasPositiveCacheHit(refinedReceiverType, method)) {
+ return singleTargetLookupCache.getPositiveCacheHit(refinedReceiverType, method);
+ }
+ if (!dynamicReceiverType.hasDynamicLowerBoundType()
+ && singleTargetLookupCache.hasNegativeCacheHit(refinedReceiverType, method)) {
+ return null;
}
if (resolutionResult
.isAccessibleForVirtualDispatchFrom(context.getHolder(), appView)
.isFalse()) {
return null;
}
- // If the method is modeled, return the resolution.
+ // If the resolved method is final, return the resolution.
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);
- return resolvedMethod;
+ if (resolvedMethod.getHolder().isFinal() || resolvedMethod.getAccessFlags().isFinal()) {
+ if (!resolvedMethod.isLibraryMethod()
+ || modeledPredicate.isModeled(resolvedMethod.getHolderType())) {
+ return singleTargetLookupCache.addToCache(refinedReceiverType, method, resolvedMethod);
}
}
DispatchTargetLookupResult exactTarget =
diff --git a/src/main/java/com/android/tools/r8/shaking/SingleTargetLookupCache.java b/src/main/java/com/android/tools/r8/shaking/SingleTargetLookupCache.java
index 0c576e0..fbe53c8 100644
--- a/src/main/java/com/android/tools/r8/shaking/SingleTargetLookupCache.java
+++ b/src/main/java/com/android/tools/r8/shaking/SingleTargetLookupCache.java
@@ -31,10 +31,11 @@
.add(method);
}
- public void addToCache(DexType refinedReceiverType, DexMethod method, DexClassAndMethod target) {
+ public DexClassAndMethod addToCache(
+ DexType refinedReceiverType, DexMethod method, DexClassAndMethod target) {
if (target == null) {
addNoSingleTargetToCache(refinedReceiverType, method);
- return;
+ return null;
}
assert !ObjectUtils.identical(target.getDefinition(), DexEncodedMethod.SENTINEL);
assert !hasNegativeCacheHit(refinedReceiverType, method);
@@ -43,6 +44,7 @@
positiveCache
.computeIfAbsent(refinedReceiverType, ignoreKey(ConcurrentHashMap::new))
.put(method, target);
+ return target;
}
public void removeInstantiatedType(DexType instantiatedType, AppInfoWithLiveness appInfo) {