Reland "Remove invalid nest check from isValidVirtualTarget predicate."
Bug: 146620831
Bug: 145187573
Bug: 145187969
This reverts commit ef8e73e75d2be92fb87f171d68dbf36a2cea333d.
Change-Id: Ic3c5c9423fa66026f5a88cc204f6e82cc010dcb5
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 3080960..2c60a43 100644
--- a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
@@ -6,7 +6,6 @@
import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.SetUtils;
import com.google.common.collect.Sets;
import java.util.Collection;
@@ -57,8 +56,12 @@
public abstract boolean isAccessibleForVirtualDispatchFrom(
DexProgramClass context, AppInfoWithSubtyping appInfo);
- public abstract boolean isValidVirtualTarget(InternalOptions options);
+ // TODO(b/145187573): Remove this and use proper access checks.
+ @Deprecated
+ public abstract boolean isValidVirtualTarget();
+ // TODO(b/145187573): Remove this and use proper access checks.
+ @Deprecated
public abstract boolean isValidVirtualTargetForDynamicDispatch();
/** Lookup the single target of an invoke-special on this resolution result if possible. */
@@ -87,10 +90,10 @@
private final DexClass resolvedHolder;
private final DexEncodedMethod resolvedMethod;
- public static boolean isValidVirtualTarget(InternalOptions options, DexEncodedMethod target) {
- return options.canUseNestBasedAccess()
- ? (!target.accessFlags.isStatic() && !target.accessFlags.isConstructor())
- : target.isVirtualMethod();
+ // TODO(b/145187573): Remove this and use proper access checks.
+ @Deprecated
+ public static boolean isValidVirtualTarget(DexEncodedMethod target) {
+ return !target.accessFlags.isStatic() && !target.accessFlags.isConstructor();
}
public SingleResolutionResult(
@@ -141,8 +144,8 @@
}
@Override
- public boolean isValidVirtualTarget(InternalOptions options) {
- return isValidVirtualTarget(options, resolvedMethod);
+ public boolean isValidVirtualTarget() {
+ return isValidVirtualTarget(resolvedMethod);
}
@Override
@@ -301,7 +304,7 @@
@Override
// TODO(b/140204899): Leverage refined receiver type if available.
public Set<DexEncodedMethod> lookupVirtualTargets(AppInfoWithSubtyping appInfo) {
- assert isValidVirtualTarget(appInfo.app().options);
+ assert isValidVirtualTarget();
// First add the target for receiver type method.type.
DexEncodedMethod encodedMethod = getSingleTarget();
Set<DexEncodedMethod> result = SetUtils.newIdentityHashSet(encodedMethod);
@@ -325,7 +328,7 @@
@Override
// TODO(b/140204899): Leverage refined receiver type if available.
public Set<DexEncodedMethod> lookupInterfaceTargets(AppInfoWithSubtyping appInfo) {
- assert isValidVirtualTarget(appInfo.app().options);
+ assert isValidVirtualTarget();
Set<DexEncodedMethod> result = Sets.newIdentityHashSet();
if (isSingleResolution()) {
// Add default interface methods to the list of targets.
@@ -451,7 +454,7 @@
}
@Override
- public boolean isValidVirtualTarget(InternalOptions options) {
+ public boolean isValidVirtualTarget() {
return true;
}
@@ -490,7 +493,7 @@
}
@Override
- public boolean isValidVirtualTarget(InternalOptions options) {
+ public boolean isValidVirtualTarget() {
return false;
}
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 c7939b5..0e6d2a3 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
@@ -180,7 +180,7 @@
method -> {
ResolutionResult resolution =
appView.appInfo().resolveMethod(method.holder, method, isInterface);
- if (resolution.isValidVirtualTarget(appView.options())) {
+ if (resolution.isValidVirtualTarget()) {
return resolution.lookupVirtualDispatchTargets(isInterface, appView.appInfo());
}
return null;
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 e83a17a..133eff3 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
@@ -88,7 +88,7 @@
ResolutionResult resolutionResult =
appView.appInfo().resolveMethod(invokedMethod.holder, invokedMethod);
// For virtual and interface calls, proceed on valid results only (since it's enforced).
- if (!resolutionResult.isValidVirtualTarget(appView.options())) {
+ if (!resolutionResult.isValidVirtualTarget()) {
continue;
}
// If the resolution ended up with a single target, check if it is a library override.
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 4977d4c..e0219c5 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
@@ -352,7 +352,7 @@
// resolution result.
ResolutionResult resolutionResult =
appView.appInfo().resolveMethod(method.holder, method, isInterface);
- if (!resolutionResult.isValidVirtualTarget(appView.options())) {
+ if (!resolutionResult.isValidVirtualTarget()) {
return ConstraintWithTarget.NEVER;
}
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 25a7b15..4e248d9 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -979,7 +979,7 @@
private DexEncodedMethod validateSingleVirtualTarget(
DexEncodedMethod singleTarget, DexEncodedMethod resolutionResult) {
- assert SingleResolutionResult.isValidVirtualTarget(options(), resolutionResult);
+ assert SingleResolutionResult.isValidVirtualTarget(resolutionResult);
if (singleTarget == null || singleTarget == DexEncodedMethod.SENTINEL) {
return null;
@@ -996,7 +996,7 @@
private boolean isInvalidSingleVirtualTarget(
DexEncodedMethod singleTarget, DexEncodedMethod resolutionResult) {
- assert SingleResolutionResult.isValidVirtualTarget(options(), resolutionResult);
+ assert SingleResolutionResult.isValidVirtualTarget(resolutionResult);
// Art978_virtual_interfaceTest correctly expects an IncompatibleClassChangeError exception
// at runtime.
return !singleTarget.accessFlags.isAtLeastAsVisibleAs(resolutionResult.accessFlags);
@@ -1081,7 +1081,7 @@
// First get the target for the holder type.
ResolutionResult topMethod = resolveMethodOnClass(holder, method);
// We might hit none or multiple targets. Both make this fail at runtime.
- if (!topMethod.isSingleResolution() || !topMethod.isValidVirtualTarget(options())) {
+ if (!topMethod.isSingleResolution() || !topMethod.isValidVirtualTarget()) {
method.setSingleVirtualMethodCache(refinedReceiverType, null);
return null;
}
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 4b412cf..1fa2300 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1658,7 +1658,7 @@
}
private void markResolutionAsLive(DexClass libraryClass, ResolutionResult resolution) {
- if (resolution.isValidVirtualTarget(options)) {
+ if (resolution.isValidVirtualTarget()) {
DexEncodedMethod target = resolution.getSingleTarget();
DexProgramClass targetHolder = getProgramClassOrNull(target.method.holder);
if (targetHolder != null
@@ -2004,7 +2004,7 @@
resolution = findAndMarkResolutionTarget(method, interfaceInvoke, reason);
virtualTargetsMarkedAsReachable.put(method, resolution);
if (resolution.isUnresolved()
- || !SingleResolutionResult.isValidVirtualTarget(options, resolution.method)) {
+ || !SingleResolutionResult.isValidVirtualTarget(resolution.method)) {
// There is no valid resolution, so any call will lead to a runtime exception.
return;
}
@@ -2035,7 +2035,7 @@
MarkedResolutionTarget reason,
BiPredicate<DexProgramClass, DexEncodedMethod> possibleTargetsFilter,
DexEncodedMethod encodedPossibleTarget) {
- assert encodedPossibleTarget.isVirtualMethod() || options.canUseNestBasedAccess();
+ assert encodedPossibleTarget.isVirtualMethod() || encodedPossibleTarget.isPrivateMethod();
assert !encodedPossibleTarget.isAbstract();
DexMethod possibleTarget = encodedPossibleTarget.method;
DexProgramClass clazz = getProgramClassOrNull(possibleTarget.holder);
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 b86857a..bd05dc3 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -533,8 +533,7 @@
}
ResolutionResult resolutionResult =
appView.appInfo().resolveMethod(originalClazz, method.method);
- if (!resolutionResult.isValidVirtualTarget(appView.options())
- || !resolutionResult.isSingleResolution()) {
+ if (!resolutionResult.isValidVirtualTarget() || !resolutionResult.isSingleResolution()) {
return;
}
DexEncodedMethod methodToKeep = resolutionResult.getSingleTarget();
diff --git a/src/test/java/com/android/tools/r8/resolution/PrivateInvokeVirtualTest.java b/src/test/java/com/android/tools/r8/resolution/PrivateInvokeVirtualTest.java
new file mode 100644
index 0000000..543ecad
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/PrivateInvokeVirtualTest.java
@@ -0,0 +1,95 @@
+// Copyright (c) 2019, 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.resolution;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class PrivateInvokeVirtualTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public PrivateInvokeVirtualTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ public static class UInt implements Comparable<UInt> {
+
+ private final int val;
+
+ public UInt(int val) {
+ this.val = val;
+ }
+
+ private int compareToHelper(int i) {
+ return Integer.compare(val, i);
+ }
+
+ @Override
+ public int compareTo(UInt o) {
+ return compareToHelper(o.val);
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ System.out.println(new UInt(3).compareTo(new UInt(args.length)));
+ }
+ }
+
+ @Test
+ public void testRuntime() throws IOException, CompilationFailedException, ExecutionException {
+ testForRuntime(parameters)
+ .addProgramClassFileData(getUIntWithTransformedInvoke())
+ .addProgramClasses(Main.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("1");
+ }
+
+ @Test
+ public void testPrivateInvokeVirtual()
+ throws IOException, CompilationFailedException, ExecutionException {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Main.class)
+ .addProgramClassFileData(getUIntWithTransformedInvoke())
+ .addKeepMainRule(Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("1");
+ }
+
+ private byte[] getUIntWithTransformedInvoke() throws IOException {
+ return transformer(UInt.class)
+ .transformMethodInsnInMethod(
+ "compareTo",
+ (opcode, owner, name, descriptor, isInterface, continuation) -> {
+ if (name.contains("compareToHelper")) {
+ assertEquals(Opcodes.INVOKESPECIAL, opcode);
+ continuation.apply(Opcodes.INVOKEVIRTUAL, owner, name, descriptor, isInterface);
+ } else {
+ continuation.apply(opcode, owner, name, descriptor, isInterface);
+ }
+ })
+ .transform();
+ }
+}
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 b1bcb52..27c7724 100644
--- a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
@@ -228,7 +228,7 @@
Assert.assertNotNull(
appInfo.resolveMethod(toType(invokeReceiver, appInfo), method).getSingleTarget());
ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
- if (resolutionResult.isValidVirtualTarget(appInfo.app().options)) {
+ if (resolutionResult.isValidVirtualTarget()) {
Set<DexEncodedMethod> targets = resolutionResult.lookupVirtualTargets(appInfo);
Set<DexType> targetHolders =
targets.stream().map(m -> m.method.holder).collect(Collectors.toSet());
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 63aa76f..82452a8 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
@@ -122,7 +122,7 @@
appInfo.resolveMethodOnInterface(methodOnB.holder, methodOnB);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
assertEquals(methodOnB, resolved.method);
- assertFalse(resolutionResult.isValidVirtualTarget(appInfo.app().options));
+ assertFalse(resolutionResult.isValidVirtualTarget());
DexEncodedMethod singleVirtualTarget =
appInfo.lookupSingleInterfaceTarget(methodOnB, methodOnB.holder);
Assert.assertNull(singleVirtualTarget);
@@ -133,7 +133,7 @@
ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(methodOnB.holder, methodOnB);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
assertEquals(methodOnB, resolved.method);
- assertFalse(resolutionResult.isValidVirtualTarget(appInfo.app().options));
+ assertFalse(resolutionResult.isValidVirtualTarget());
}
@Test
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 22a12f2..702eca9 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
@@ -168,7 +168,7 @@
ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB.holder, methodOnB);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
assertEquals(methodOnA, resolved.method);
- assertFalse(resolutionResult.isValidVirtualTarget(appInfo.app().options));
+ assertFalse(resolutionResult.isValidVirtualTarget());
DexEncodedMethod singleVirtualTarget =
appInfo.lookupSingleVirtualTarget(methodOnB, methodOnB.holder);
Assert.assertNull(singleVirtualTarget);
@@ -179,7 +179,7 @@
ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB.holder, methodOnB);
DexEncodedMethod resolved = resolutionResult.getSingleTarget();
assertEquals(methodOnA, resolved.method);
- assertFalse(resolutionResult.isValidVirtualTarget(appInfo.app().options));
+ assertFalse(resolutionResult.isValidVirtualTarget());
}
@Test
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 69cdad5..f1c5fa1 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
@@ -92,16 +92,7 @@
.setMinApi(parameters.getApiLevel())
.addKeepMainRule(Main.class)
.run(parameters.getRuntime(), Main.class)
- .apply(
- result -> {
- if (parameters.isDexRuntime() && inSameNest) {
- // TODO(b/145187969): R8 incorrectly compiles the nest based access away.
- result.assertFailureWithErrorThatMatches(
- containsString(NullPointerException.class.getName()));
- } else {
- checkExpectedResult(result);
- }
- });
+ .apply(this::checkExpectedResult);
}
private void checkExpectedResult(TestRunResult<?> result) {
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 a997622..f2f3309 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
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.resolution.access;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestBase;
@@ -77,16 +76,7 @@
.setMinApi(parameters.getApiLevel())
.addKeepMainRule(Main.class)
.run(parameters.getRuntime(), Main.class)
- .apply(
- result -> {
- if (parameters.isCfRuntime()) {
- result.assertSuccessWithOutput(EXPECTED);
- } else {
- // TODO(b/145187969): R8 compiles an incorrect program.
- result.assertFailureWithErrorThatMatches(
- containsString(NullPointerException.class.getName()));
- }
- });
+ .assertSuccessWithOutput(EXPECTED);
}
static class A {