aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMorten Krogh-Jespersen <mkroghj@google.com>2021-03-11 14:52:48 +0100
committerMorten Krogh-Jespersen <mkroghj@google.com>2021-03-11 14:52:48 +0100
commitff3be41f81842f39328d9043e2a3e81d6e5bd1b2 (patch)
tree0301ceffe7bb80818cb6dc9cca4ae4652e52ec22
parentfc8ff4a3007244a6277c99de794e5d445f4bfe4d (diff)
downloadr8-ff3be41f81842f39328d9043e2a3e81d6e5bd1b2.tar.gz
Check if methods are overriding if they are seen when marking live
Bug: 182456011 Bug: 182458496 Bug: 182444403 Change-Id: I26a6a30cd7d42f05e9121876417ebf3ba2892ba1
-rw-r--r--src/main/java/com/android/tools/r8/shaking/Enqueuer.java34
-rw-r--r--src/main/java/com/android/tools/r8/utils/FunctionUtils.java5
-rw-r--r--src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java3
3 files changed, 30 insertions, 12 deletions
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 331466be2..8c7060583 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -5,11 +5,13 @@ package com.android.tools.r8.shaking;
import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import static com.android.tools.r8.graph.FieldAccessInfoImpl.MISSING_FIELD_ACCESS_INFO;
+import static com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult.isOverriding;
import static com.android.tools.r8.ir.desugar.LambdaDescriptor.isLambdaMetafactoryMethod;
import static com.android.tools.r8.ir.optimize.enums.UnboxedEnumMemberRelocator.ENUM_UNBOXING_UTILITY_CLASS_SUFFIX;
import static com.android.tools.r8.naming.IdentifierNameStringUtils.identifyIdentifier;
import static com.android.tools.r8.naming.IdentifierNameStringUtils.isReflectionMethod;
import static com.android.tools.r8.shaking.AnnotationRemover.shouldKeepAnnotation;
+import static com.android.tools.r8.utils.FunctionUtils.ignoreArgument;
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.cf.code.CfInstruction;
@@ -140,7 +142,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -2363,11 +2364,13 @@ public class Enqueuer {
*/
private void transitionMethodsForInstantiatedObject(
InstantiatedObject instantiation, DexClass clazz, List<DexType> interfaces) {
- Set<Wrapper<DexMethod>> seen = new HashSet<>();
+ Map<Wrapper<DexMethod>, List<DexEncodedMethod>> seen = new HashMap<>();
WorkList<DexType> worklist = WorkList.newIdentityWorkList();
worklist.addIfNotSeen(interfaces);
// First we lookup and mark all targets on the instantiated class for each reachable method in
// the super chain (inclusive).
+ // TODO(b/182458496): Consider changing this algorithm to a version that collects all reachable
+ // methods and then does lookup.
DexClass initialClass = clazz;
while (clazz != null) {
if (clazz.isProgramClass()) {
@@ -2405,14 +2408,25 @@ public class Enqueuer {
private void markProgramMethodOverridesAsLive(
InstantiatedObject instantiation,
DexClass initialClass,
- DexProgramClass superClass,
- Set<Wrapper<DexMethod>> seenMethods) {
- for (DexMethod method : getReachableVirtualTargets(superClass)) {
- assert method.holder == superClass.type;
+ DexProgramClass currentClass,
+ Map<Wrapper<DexMethod>, List<DexEncodedMethod>> seenMethods) {
+ for (DexMethod method : getReachableVirtualTargets(currentClass)) {
+ assert method.holder == currentClass.type;
Wrapper<DexMethod> signature = MethodSignatureEquivalence.get().wrap(method);
- if (!seenMethods.contains(signature)) {
+ // TODO(b/182456011): Could reachableVirtalTarget be dex encoded methods.
+ DexEncodedMethod currentTarget = definitionFor(method, currentClass);
+ List<DexEncodedMethod> potentialOverrides =
+ seenMethods.computeIfAbsent(signature, ignoreArgument(ArrayList::new));
+ boolean notOverridingCurrentTarget = potentialOverrides.isEmpty();
+ for (DexEncodedMethod potentialOverride : potentialOverrides) {
+ if (!isOverriding(currentTarget, potentialOverride)) {
+ notOverridingCurrentTarget = true;
+ break;
+ }
+ }
+ if (notOverridingCurrentTarget) {
SingleResolutionResult resolution =
- appInfo.resolveMethodOn(superClass, method).asSingleResolution();
+ appInfo.resolveMethodOn(currentClass, method).asSingleResolution();
assert resolution != null;
assert resolution.getResolvedHolder().isProgramClass();
if (resolution != null) {
@@ -2420,11 +2434,11 @@ public class Enqueuer {
|| resolution
.isAccessibleForVirtualDispatchFrom(initialClass.asProgramClass(), appInfo)
.isTrue()) {
- seenMethods.add(signature);
+ potentialOverrides.add(currentTarget);
}
if (resolution.getResolvedHolder().isProgramClass()) {
markLiveOverrides(
- instantiation, superClass, resolution.getResolutionPair().asProgramMethod());
+ instantiation, currentClass, resolution.getResolutionPair().asProgramMethod());
}
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/FunctionUtils.java b/src/main/java/com/android/tools/r8/utils/FunctionUtils.java
index 3338dde56..acd5cb3c2 100644
--- a/src/main/java/com/android/tools/r8/utils/FunctionUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/FunctionUtils.java
@@ -7,6 +7,7 @@ package com.android.tools.r8.utils;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
+import java.util.function.Supplier;
public class FunctionUtils {
@@ -28,4 +29,8 @@ public class FunctionUtils {
func.apply(t).accept(argument);
}
}
+
+ public static <T, R> Function<T, R> ignoreArgument(Supplier<R> supplier) {
+ return ignore -> supplier.get();
+ }
}
diff --git a/src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java b/src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java
index 8cdd48ea6..f9583f768 100644
--- a/src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/AbstractSuperClassLiveMethodTest.java
@@ -69,8 +69,7 @@ public class AbstractSuperClassLiveMethodTest extends TestBase {
.applyIf(
parameters.isDexRuntime() && parameters.getDexRuntimeVersion().isDalvik(),
r -> r.assertSuccessWithOutputLines(EXPECTED_DALVIK),
- // TODO(b/182444403): Should succeed with EXPECTED.
- r -> r.assertFailureWithErrorThatThrows(AbstractMethodError.class));
+ r -> r.assertSuccessWithOutputLines(EXPECTED));
}
@NoVerticalClassMerging