Recognize reflective instantiation in the presence of debug local write
This would trigger us to correctly see the instantiation in release
mode but not in debug mode.
Bug: 241478253
Change-Id: I851fb9364824b760cb6a1350be4d32ae8e99ccb5
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstantValueUtils.java b/src/main/java/com/android/tools/r8/ir/code/ConstantValueUtils.java
index 86d04e5..9855ee6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstantValueUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstantValueUtils.java
@@ -13,11 +13,12 @@
/**
* If the given value is a constant class, then returns the corresponding {@link DexType}.
- * Otherwise returns null.
+ * Otherwise returns null. This should only be used for tracing.
*/
- public static DexType getDexTypeRepresentedByValue(
+ public static DexType getDexTypeRepresentedByValueForTracing(
Value value, DexDefinitionSupplier definitions) {
- Value alias = value.getAliasedValue();
+ Value alias =
+ value.getAliasedValue(IgnoreDebugLocalWriteAliasedValueConfiguration.getInstance());
if (alias.isPhi()) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/IgnoreDebugLocalWriteAliasedValueConfiguration.java b/src/main/java/com/android/tools/r8/ir/code/IgnoreDebugLocalWriteAliasedValueConfiguration.java
new file mode 100644
index 0000000..c9dcfa2
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/code/IgnoreDebugLocalWriteAliasedValueConfiguration.java
@@ -0,0 +1,31 @@
+// Copyright (c) 2022, 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.code;
+
+public class IgnoreDebugLocalWriteAliasedValueConfiguration implements AliasedValueConfiguration {
+
+ private static final IgnoreDebugLocalWriteAliasedValueConfiguration INSTANCE =
+ new IgnoreDebugLocalWriteAliasedValueConfiguration();
+
+ private IgnoreDebugLocalWriteAliasedValueConfiguration() {}
+
+ public static IgnoreDebugLocalWriteAliasedValueConfiguration getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean isIntroducingAnAlias(Instruction instruction) {
+ return instruction.isAssume() || instruction.isDebugLocalWrite();
+ }
+
+ @Override
+ public Value getAliasForOutValue(Instruction instruction) {
+ assert instruction.isAssume() || instruction.isDebugLocalWrite();
+
+ return instruction.isAssume()
+ ? instruction.asAssume().src()
+ : instruction.asDebugLocalWrite().src();
+ }
+}
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 4d9598e..1008d80 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -4981,7 +4981,7 @@
}
DexType instantiatedType =
- ConstantValueUtils.getDexTypeRepresentedByValue(
+ ConstantValueUtils.getDexTypeRepresentedByValueForTracing(
invoke.asInvokeVirtual().getReceiver(), appView);
if (instantiatedType == null || !instantiatedType.isClassType()) {
// Give up, we can't tell which class is being instantiated, or the type is not a class type.
@@ -5027,7 +5027,7 @@
}
DexType instantiatedType =
- ConstantValueUtils.getDexTypeRepresentedByValue(
+ ConstantValueUtils.getDexTypeRepresentedByValueForTracing(
constructorDefinition.getReceiver(), appView);
if (instantiatedType == null || !instantiatedType.isClassType()) {
// Give up, we can't tell which constructor is being invoked, or the type is not a class type.
@@ -5076,7 +5076,8 @@
}
DexType type =
- ConstantValueUtils.getDexTypeRepresentedByValue(arrayPutInstruction.value(), appView);
+ ConstantValueUtils.getDexTypeRepresentedByValueForTracing(
+ arrayPutInstruction.value(), appView);
if (type == null) {
return;
}
@@ -5131,7 +5132,8 @@
}
ArrayPut arrayPut = user.asArrayPut();
- DexType type = ConstantValueUtils.getDexTypeRepresentedByValue(arrayPut.value(), appView);
+ DexType type =
+ ConstantValueUtils.getDexTypeRepresentedByValueForTracing(arrayPut.value(), appView);
if (type == null || !type.isClassType()) {
continue;
}
diff --git a/src/test/java/com/android/tools/r8/regress/Regress241478253.java b/src/test/java/com/android/tools/r8/regress/Regress241478253.java
index e22e8f5..ceacdf5 100644
--- a/src/test/java/com/android/tools/r8/regress/Regress241478253.java
+++ b/src/test/java/com/android/tools/r8/regress/Regress241478253.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.regress;
-import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
@@ -29,22 +28,19 @@
@Test
public void testR8() throws Exception {
- R8TestRunResult r8Release =
- testForR8(parameters.getBackend())
- .addProgramClasses(Foo.class, Bar.class)
- .addKeepMainRule(Foo.class)
- .setMinApi(parameters.getApiLevel())
- .run(parameters.getRuntime(), Foo.class)
- .assertSuccessWithOutputLines(EXPECTED);
- R8TestRunResult r8Debug =
- testForR8(parameters.getBackend())
- .debug()
- .addProgramClasses(Foo.class, Bar.class)
- .addKeepMainRule(Foo.class)
- .setMinApi(parameters.getApiLevel())
- .run(parameters.getRuntime(), Foo.class)
- // TODO(b/241478253): Should succeed
- .assertFailureWithErrorThatThrows(NoSuchMethodException.class);
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Foo.class, Bar.class)
+ .addKeepMainRule(Foo.class)
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Foo.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ testForR8(parameters.getBackend())
+ .debug()
+ .addProgramClasses(Foo.class, Bar.class)
+ .addKeepMainRule(Foo.class)
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Foo.class)
+ .assertSuccessWithOutputLines(EXPECTED);
}
public static class Foo {