Merge "Allow inlining of methods that throw"
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
index 5f62c6c..8e91a62 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
@@ -192,8 +192,6 @@
private boolean inPrelude;
private Int2ObjectMap<DebugLocalInfo> incomingLocals;
private Int2ObjectMap<DebugLocalInfo> outgoingLocals;
- private Int2ReferenceMap<Int2ObjectMap<DebugLocalInfo>> definitelyLiveIncomingLocals =
- new Int2ReferenceOpenHashMap<>();
private Int2ReferenceMap<CfState.Snapshot> incomingState = new Int2ReferenceOpenHashMap<>();
private final CanonicalPositions canonicalPositions;
@@ -371,38 +369,21 @@
if (predecessorOffset == IRBuilder.INITIAL_BLOCK_OFFSET) {
return;
}
- if (currentInstructionIndex != predecessorOffset) {
- // If transfer is not still in the same block, then update the state to that of the successor.
- // The builder's lookup of local variables relies on this state for starting locals.
- currentInstructionIndex = successorOffset;
- state.reset(incomingState.get(currentInstructionIndex), false);
- setLocalVariableLists();
- // The transfer has not yet taken place, so the current position is that of the predecessor.
- int positionOffset = predecessorOffset;
- List<CfInstruction> instructions = code.getInstructions();
- CfInstruction instruction = instructions.get(positionOffset);
- while (0 < positionOffset && !(instruction instanceof CfPosition)) {
- instruction = instructions.get(--positionOffset);
- }
- if (instruction instanceof CfPosition) {
- CfPosition position = (CfPosition) instruction;
- state.setPosition(getCanonicalPosition(position.getPosition()));
- } else {
- state.setPosition(canonicalPositions.getPreamblePosition());
- }
- }
+ // The transfer has not yet taken place, so the current position is that of the predecessor.
+ state.setPosition(getCanonicalDebugPositionAtOffset(predecessorOffset));
+
// Manually compute the local variable change for the block transfer.
- LocalVariableList atSource = getLocalVariables(predecessorOffset);
- LocalVariableList atTarget = getLocalVariables(successorOffset);
+ Int2ObjectMap<DebugLocalInfo> atSource = getLocalVariables(predecessorOffset).locals;
+ Int2ObjectMap<DebugLocalInfo> atTarget = getLocalVariables(successorOffset).locals;
if (!isExceptional) {
- for (Entry<DebugLocalInfo> entry : atSource.locals.int2ObjectEntrySet()) {
- if (atTarget.locals.get(entry.getIntKey()) != entry.getValue()) {
+ for (Entry<DebugLocalInfo> entry : atSource.int2ObjectEntrySet()) {
+ if (atTarget.get(entry.getIntKey()) != entry.getValue()) {
builder.addDebugLocalEnd(entry.getIntKey(), entry.getValue());
}
}
}
- for (Entry<DebugLocalInfo> entry : atTarget.locals.int2ObjectEntrySet()) {
- if (atSource.locals.get(entry.getIntKey()) != entry.getValue()) {
+ for (Entry<DebugLocalInfo> entry : atTarget.int2ObjectEntrySet()) {
+ if (atSource.get(entry.getIntKey()) != entry.getValue()) {
builder.addDebugLocalStart(entry.getIntKey(), entry.getValue());
}
}
@@ -562,33 +543,15 @@
private void setLocalVariableLists() {
incomingLocals = getLocalVariables(currentInstructionIndex).locals;
- CfInstruction currentInstruction = code.getInstructions().get(currentInstructionIndex);
if (inPrelude) {
outgoingLocals = incomingLocals;
return;
}
- if (currentInstruction.isReturn() || currentInstruction instanceof CfThrow) {
- outgoingLocals = emptyMap();
- return;
- }
- if (isControlFlow(currentInstruction)) {
- // We need to read all locals that are not live on all successors to ensure liveness.
- // Determine outgoingLocals as the intersection of all successors' locals.
- outgoingLocals = null;
- int[] targets = getTargets(currentInstructionIndex);
- for (int target : targets) {
- Int2ObjectMap<DebugLocalInfo> locals = getLocalVariables(target).locals;
- outgoingLocals = intersectMaps(outgoingLocals, locals);
- }
- assert outgoingLocals != null;
- // Pass outgoingLocals to all successors.
- for (int target : targets) {
- Int2ObjectMap<DebugLocalInfo> existing = definitelyLiveIncomingLocals.get(target);
- definitelyLiveIncomingLocals.put(target, intersectMaps(existing, outgoingLocals));
- }
- } else {
- outgoingLocals = getLocalVariables(currentInstructionIndex + 1).locals;
- }
+ CfInstruction currentInstruction = code.getInstructions().get(currentInstructionIndex);
+ outgoingLocals =
+ !isControlFlow(currentInstruction)
+ ? getLocalVariables(currentInstructionIndex + 1).locals
+ : emptyMap();
}
private boolean localsChanged() {
@@ -613,27 +576,6 @@
}
}
- private Int2ObjectMap<DebugLocalInfo> intersectMaps(
- Int2ObjectMap<DebugLocalInfo> existing, Int2ObjectMap<DebugLocalInfo> update) {
- assert update != null;
- if (existing == null) {
- return update;
- }
- if (existing.size() > update.size()) {
- return intersectMaps(update, existing);
- }
- if (existing.equals(update)) {
- return existing;
- }
- Int2ObjectOpenHashMap<DebugLocalInfo> result = new Int2ObjectOpenHashMap<>();
- for (Entry<DebugLocalInfo> local : existing.int2ObjectEntrySet()) {
- if (local.getValue().equals(update.get(local.getIntKey()))) {
- result.put(local.getIntKey(), local.getValue());
- }
- }
- return result;
- }
-
private boolean isControlFlow(CfInstruction currentInstruction) {
return currentInstruction.isReturn()
|| currentInstruction.getTarget() != null
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 5c4d581..8fe972b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -706,14 +706,6 @@
addInstruction(new Argument(value));
}
- private void addDebugLocalWrite(ValueType type, int dest, Value in) {
- assert options.debug;
- Value out = writeRegister(dest, type, ThrowingInfo.NO_THROW);
- DebugLocalWrite write = new DebugLocalWrite(out, in);
- assert !write.instructionTypeCanThrow();
- addInstruction(write);
- }
-
private Value getIncomingLocalValue(int register, DebugLocalInfo local) {
assert options.debug;
assert local != null;
@@ -729,26 +721,26 @@
}
public void addDebugLocalStart(int register, DebugLocalInfo local) {
+ assert local != null;
if (!options.debug) {
return;
}
- assert local != null;
- assert local == getOutgoingLocal(register) :
- "local-start mismatch: " + local + " != " + getOutgoingLocal(register)
- + " at " + currentInstructionOffset
- + " for source\n" + source.toString();
- // TODO(b/111251032): Here we lookup a value with type based on debug info. That's just wrong!
- ValueType valueType = ValueType.fromDexType(local.type);
- Value incomingValue = readRegisterIgnoreLocal(register, valueType, local);
// If the local was not introduced by the previous instruction, start it here.
+ Value incomingValue = getIncomingLocalValue(register, local);
if (incomingValue.getLocalInfo() != local
|| currentBlock.isEmpty()
|| currentBlock.getInstructions().getLast().outValue() != incomingValue) {
- addDebugLocalWrite(ValueType.fromDexType(local.type), register, incomingValue);
+ // Note that the write register must not lookup outgoing local information and the local is
+ // never considered clobbered by a start (if the in value has local info it must have been
+ // marked ended elsewhere).
+ Value out = writeRegister(register, incomingValue.outType(), ThrowingInfo.NO_THROW, local);
+ DebugLocalWrite write = new DebugLocalWrite(out, incomingValue);
+ addInstruction(write);
}
}
public void addDebugLocalEnd(int register, DebugLocalInfo local) {
+ assert local != null;
if (!options.debug) {
return;
}
@@ -951,7 +943,8 @@
// If the move is writing to a different local we must construct a new value.
DebugLocalInfo destLocal = getOutgoingLocal(dest);
if (destLocal != null && destLocal != in.getLocalInfo()) {
- addDebugLocalWrite(type, dest, in);
+ Value out = writeRegister(dest, type, ThrowingInfo.NO_THROW);
+ addInstruction(new DebugLocalWrite(out, in));
return;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index e528a90..1039817 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -476,6 +476,7 @@
|| successorOffset == EXCEPTIONAL_SYNC_EXIT_OFFSET) {
return;
}
+ // The transfer has not yet taken place, so the current position is that of the predecessor.
currentPosition = getCanonicalDebugPositionAtOffset(predecessorOffset);
LocalChangeAtOffset localChange = state.getLocalChange(predecessorOffset, successorOffset);
@@ -484,12 +485,8 @@
builder.addDebugLocalEnd(toClose.slot.register, toClose.info);
}
}
- List<Local> localsToOpen = localChange.getLocalsToOpen();
- if (!localsToOpen.isEmpty()) {
- state.restoreState(successorOffset);
- for (Local toOpen : localsToOpen) {
- builder.addDebugLocalStart(toOpen.slot.register, toOpen.info);
- }
+ for (Local toOpen : localChange.getLocalsToOpen()) {
+ builder.addDebugLocalStart(toOpen.slot.register, toOpen.info);
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index c6729e8..97f1228 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
+import com.android.tools.r8.utils.MethodSignatureRelaxedEquivalence;
import com.android.tools.r8.utils.Timing;
import com.google.common.base.Equivalence;
import com.google.common.base.Equivalence.Wrapper;
@@ -90,11 +91,15 @@
*/
class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
- private final Equivalence<DexMethod> equivalence = MethodSignatureEquivalence.get();
+ private final Equivalence<DexMethod> equivalence;
private final Map<DexCallSite, DexString> callSiteRenaming = new IdentityHashMap<>();
MethodNameMinifier(AppInfoWithSubtyping appInfo, RootSet rootSet, InternalOptions options) {
super(appInfo, rootSet, options);
+ equivalence =
+ overloadAggressively
+ ? MethodSignatureEquivalence.get()
+ : new MethodSignatureRelaxedEquivalence(appInfo);
}
@Override
@@ -337,10 +342,12 @@
}
private void addStatesToGlobalMapForMethod(
- DexEncodedMethod method, Set<NamingState<DexProto, ?>> collectedStates,
+ DexEncodedMethod method,
+ Set<NamingState<DexProto, ?>> collectedStates,
Map<Wrapper<DexMethod>, Set<NamingState<DexProto, ?>>> globalStateMap,
Map<Wrapper<DexMethod>, Set<DexMethod>> sourceMethodsMap,
- Map<Wrapper<DexMethod>, NamingState<DexProto, ?>> originStates, DexType originInterface) {
+ Map<Wrapper<DexMethod>, NamingState<DexProto, ?>> originStates,
+ DexType originInterface) {
Wrapper<DexMethod> key = equivalence.wrap(method.method);
Set<NamingState<DexProto, ?>> stateSet =
globalStateMap.computeIfAbsent(key, k -> new HashSet<>());
diff --git a/src/main/java/com/android/tools/r8/utils/MethodSignatureRelaxedEquivalence.java b/src/main/java/com/android/tools/r8/utils/MethodSignatureRelaxedEquivalence.java
new file mode 100644
index 0000000..74d2d98
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/MethodSignatureRelaxedEquivalence.java
@@ -0,0 +1,36 @@
+// Copyright (c) 2018, 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.utils;
+
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.DexMethod;
+import com.google.common.base.Equivalence;
+
+/**
+ * Implements an equivalence on {@link DexMethod} that does not take the holder into account but
+ * allow covariant return type: a method in a sub type can return a narrower type.
+ */
+public class MethodSignatureRelaxedEquivalence extends Equivalence<DexMethod> {
+
+ private final AppInfo appInfo;
+
+ public MethodSignatureRelaxedEquivalence(AppInfo appInfo) {
+ this.appInfo = appInfo;
+ }
+
+ @Override
+ protected boolean doEquivalent(DexMethod a, DexMethod b) {
+ return a.name.equals(b.name) && a.proto.parameters.equals(b.proto.parameters)
+ && (a.proto.returnType.equals(b.proto.returnType)
+ || (a.proto.returnType.isStrictSubtypeOf(b.proto.returnType, appInfo)
+ && a.getHolder().isStrictSubtypeOf(b.getHolder(), appInfo))
+ || (b.proto.returnType.isStrictSubtypeOf(a.proto.returnType, appInfo)
+ && b.getHolder().isStrictSubtypeOf(a.getHolder(), appInfo)));
+ }
+
+ @Override
+ protected int doHash(DexMethod method) {
+ return method.name.hashCode() * 31 + method.proto.parameters.hashCode();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesKotlinTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesKotlinTest.java
index dc94a71..4451910 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesKotlinTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesKotlinTest.java
@@ -25,10 +25,16 @@
List<String[]> fullTestList = new ArrayList<>(tests.length * 2);
for (String test : tests) {
- fullTestList.add(makeTest(Input.JAVAC, CompilerUnderTest.D8, CompilationMode.DEBUG, test));
- fullTestList.add(makeTest(Input.JAVAC, CompilerUnderTest.D8, CompilationMode.RELEASE, test));
+ fullTestList.add(
+ makeTest(Input.JAVAC, CompilerUnderTest.D8, CompilationMode.DEBUG, test, Output.DEX));
+ fullTestList.add(
+ makeTest(Input.JAVAC, CompilerUnderTest.D8, CompilationMode.RELEASE, test, Output.DEX));
fullTestList.add(makeTest(Input.DX, CompilerUnderTest.R8, CompilationMode.DEBUG, test));
fullTestList.add(makeTest(Input.DX, CompilerUnderTest.R8, CompilationMode.RELEASE, test));
+ fullTestList.add(
+ makeTest(Input.JAVAC, CompilerUnderTest.R8, CompilationMode.DEBUG, test, Output.CF));
+ fullTestList.add(
+ makeTest(Input.JAVAC, CompilerUnderTest.R8, CompilationMode.RELEASE, test, Output.CF));
}
return fullTestList;
}
diff --git a/src/test/java/com/android/tools/r8/debug/PostIncrementTestRunner.java b/src/test/java/com/android/tools/r8/debug/PostIncrementTestRunner.java
index 4cfb71a..6ddc9db 100644
--- a/src/test/java/com/android/tools/r8/debug/PostIncrementTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debug/PostIncrementTestRunner.java
@@ -5,18 +5,24 @@
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.VmTestRunner;
+import com.android.tools.r8.VmTestRunner.IgnoreIfVmOlderOrEqualThan;
import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.DebuggeeState;
import java.util.stream.Stream;
import org.junit.Assume;
import org.junit.Test;
+import org.junit.runner.RunWith;
// See b/80385846
+@RunWith(VmTestRunner.class)
public class PostIncrementTestRunner extends DebugTestBase {
private static final Class CLASS = PostIncrementTest.class;
private static final String NAME = CLASS.getCanonicalName();
@Test
+ @IgnoreIfVmOlderOrEqualThan(Version.V5_1_1)
public void test() throws Exception {
Assume.assumeTrue("Older runtimes cause some kind of debug streaming issues",
ToolHelper.getDexVm().isNewerThan(DexVm.ART_5_1_1_HOST));
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/CompositionalLenseTest.java b/src/test/java/com/android/tools/r8/memberrebinding/CompositionalLenseTest.java
index 6c6e69d..4903304 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/CompositionalLenseTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/CompositionalLenseTest.java
@@ -11,19 +11,24 @@
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.code.InvokeVirtual;
-import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.InvokeInstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
// Base -> X:
class Base {
@@ -47,10 +52,22 @@
}
}
+@RunWith(Parameterized.class)
public class CompositionalLenseTest extends TestBase {
private final static List<Class> CLASSES =
ImmutableList.of(Base.class, Sub.class, TestMain.class);
+ private Backend backend;
+
+ @Parameterized.Parameters(name = "Backend: {0}")
+ public static Collection<Backend> data() {
+ return Arrays.asList(Backend.values());
+ }
+
+ public CompositionalLenseTest(Backend backend) {
+ this.backend = backend;
+ }
+
@Test
public void test() throws Exception {
Path mapPath = temp.newFile("test-mapping.txt").toPath();
@@ -63,26 +80,38 @@
FileUtils.writeTextFile(mapPath, pgMap);
AndroidApp app = readClasses(CLASSES);
- R8Command.Builder builder = ToolHelper.prepareR8CommandBuilder(app);
- builder.addProguardConfiguration(
- ImmutableList.of(
- keepMainProguardConfiguration(TestMain.class),
- "-applymapping " + mapPath,
- "-dontobfuscate"), // to use the renamed names in test-mapping.txt
- Origin.unknown());
+ R8Command.Builder builder = ToolHelper.prepareR8CommandBuilder(app, emptyConsumer(backend));
+ builder
+ .addProguardConfiguration(
+ ImmutableList.of(
+ keepMainProguardConfiguration(TestMain.class),
+ "-applymapping " + mapPath,
+ "-dontobfuscate"), // to use the renamed names in test-mapping.txt
+ Origin.unknown())
+ .addLibraryFiles(runtimeJar(backend));
AndroidApp processedApp = ToolHelper.runR8(builder.build(), options -> {
options.enableInlining = false;
options.enableClassMerging = false;
});
- CodeInspector codeInspector = new CodeInspector(processedApp);
+ CodeInspector codeInspector = new CodeInspector(processedApp, o -> o.enableCfFrontend = true);
ClassSubject classSubject = codeInspector.clazz(TestMain.class);
assertThat(classSubject, isPresent());
MethodSubject methodSubject = classSubject.method(CodeInspector.MAIN);
assertThat(methodSubject, isPresent());
- DexCode dexCode = methodSubject.getMethod().getCode().asDexCode();
- assertTrue(dexCode.instructions[2] instanceof InvokeVirtual);
- InvokeVirtual invoke = (InvokeVirtual) dexCode.instructions[2];
- DexMethod invokedMethod = invoke.getMethod();
+ Iterator<InstructionSubject> iterator = methodSubject.iterateInstructions();
+
+ InstructionSubject instruction = null;
+ boolean found = false;
+ while (iterator.hasNext()) {
+ instruction = iterator.next();
+ if (instruction.isInvokeVirtual()) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue(found);
+
+ DexMethod invokedMethod = ((InvokeInstructionSubject) instruction).invokedMethod();
assertEquals("bar", invokedMethod.name.toString());
assertEquals("X", invokedMethod.getHolder().getName());
}
diff --git a/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeInSubInterfaceTest.java b/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeInSubInterfaceTest.java
index 6602d0c..20f46b4 100644
--- a/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeInSubInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/naming/CovariantReturnTypeInSubInterfaceTest.java
@@ -7,15 +7,20 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
+import com.android.tools.r8.OutputMode;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
import java.util.List;
-import org.junit.Ignore;
import org.junit.Test;
+import org.junit.runner.RunWith;
interface SuperInterface {
Super foo();
@@ -42,14 +47,14 @@
class SuperImplementer implements SuperInterface {
@Override
public Super foo() {
- return new Super();
+ return new Sub();
}
}
-class SubImplementer implements SubInterface {
+class SubImplementer extends SuperImplementer implements SubInterface {
@Override
public Sub foo() {
- return new Sub();
+ return (Sub) super.foo();
}
}
@@ -57,19 +62,22 @@
public static void main(String[] args) {
SubImplementer subImplementer = new SubImplementer();
Super sup = subImplementer.foo();
- System.out.println(sup.bar());
+ System.out.print(sup.bar());
}
}
+@RunWith(VmTestRunner.class)
public class CovariantReturnTypeInSubInterfaceTest extends TestBase {
- @Ignore("b/112185748")
- @Test
- public void test() throws Exception {
+ private void test(boolean overloadAggressively) throws Exception {
+ String mainName = TestMain.class.getCanonicalName();
+ String aggressive =
+ overloadAggressively ? "-overloadaggressively" : "# Not overload aggressively";
List<String> config = ImmutableList.of(
"-printmapping",
"-useuniqueclassmembernames",
- "-keep class " + TestMain.class.getCanonicalName() + " {",
+ aggressive,
+ "-keep class " + mainName + " {",
" public void main(...);",
"}",
"-keep,allowobfuscation class **.Super* {",
@@ -88,7 +96,10 @@
SubImplementer.class,
TestMain.class
);
- AndroidApp processedApp = compileWithR8(app, String.join(System.lineSeparator(), config));
+ AndroidApp processedApp =
+ compileWithR8(app, String.join(System.lineSeparator(), config), options -> {
+ options.enableInlining = false;
+ });
CodeInspector inspector = new CodeInspector(processedApp);
ClassSubject superInterface = inspector.clazz(SuperInterface.class);
assertThat(superInterface, isRenamed());
@@ -101,6 +112,24 @@
Sub.class.getCanonicalName(), "foo", ImmutableList.of());
assertThat(foo2, isRenamed());
assertEquals(foo1.getFinalName(), foo2.getFinalName());
+
+ ProcessResult javaResult = ToolHelper.runJava(ToolHelper.getClassPathForTests(), mainName);
+ assertEquals(0, javaResult.exitCode);
+ Path outDex = temp.getRoot().toPath().resolve("dex.zip");
+ processedApp.writeToZip(outDex, OutputMode.DexIndexed);
+ ProcessResult artResult = ToolHelper.runArtNoVerificationErrorsRaw(outDex.toString(), mainName);
+ assertEquals(0, artResult.exitCode);
+ assertEquals(javaResult.stdout, artResult.stdout);
+ }
+
+ @Test
+ public void test_notAggressively() throws Exception {
+ test(false);
+ }
+
+ @Test
+ public void test_aggressively() throws Exception {
+ test(true);
}
}
diff --git a/src/test/java/com/android/tools/r8/naming/InterfaceRenamingTestRunner.java b/src/test/java/com/android/tools/r8/naming/InterfaceRenamingTestRunner.java
index e1fa3d0..ef6e0c8 100644
--- a/src/test/java/com/android/tools/r8/naming/InterfaceRenamingTestRunner.java
+++ b/src/test/java/com/android/tools/r8/naming/InterfaceRenamingTestRunner.java
@@ -14,12 +14,15 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.origin.Origin;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
+import org.junit.runner.RunWith;
+@RunWith(VmTestRunner.class)
public class InterfaceRenamingTestRunner extends TestBase {
static final Class CLASS = InterfaceRenamingTest.class;
static final Class[] CLASSES = InterfaceRenamingTest.CLASSES;
diff --git a/src/test/java/com/android/tools/r8/naming/LambdaRenamingTestRunner.java b/src/test/java/com/android/tools/r8/naming/LambdaRenamingTestRunner.java
index 02bca3a..56dce3a 100644
--- a/src/test/java/com/android/tools/r8/naming/LambdaRenamingTestRunner.java
+++ b/src/test/java/com/android/tools/r8/naming/LambdaRenamingTestRunner.java
@@ -16,13 +16,16 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
import java.io.IOException;
import java.nio.file.Path;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+@RunWith(VmTestRunner.class)
public class LambdaRenamingTestRunner extends TestBase {
static final Class CLASS = LambdaRenamingTest.class;
static final Class[] CLASSES = LambdaRenamingTest.CLASSES;
diff --git a/src/test/java/com/android/tools/r8/regress/b63935662/Regress63935662.java b/src/test/java/com/android/tools/r8/regress/b63935662/Regress63935662.java
index 01b0a17..86852ef 100644
--- a/src/test/java/com/android/tools/r8/regress/b63935662/Regress63935662.java
+++ b/src/test/java/com/android/tools/r8/regress/b63935662/Regress63935662.java
@@ -7,28 +7,53 @@
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.OffOrAuto;
import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+@RunWith(Parameterized.class)
public class Regress63935662 extends TestBase {
+ private Backend backend;
+
+ @Parameterized.Parameters(name = "Backend: {0}")
+ public static Collection<Backend> data() {
+ return Arrays.asList(Backend.values());
+ }
+
+ public Regress63935662(Backend backend) {
+ this.backend = backend;
+ }
+
void run(AndroidApp app, Class mainClass) throws Exception {
Path proguardConfig =
writeTextToTempFile(keepMainProguardConfiguration(mainClass, true, false));
- R8Command command =
- ToolHelper.prepareR8CommandBuilder(app)
- .addProguardConfigurationFiles(proguardConfig)
- .setMinApiLevel(AndroidApiLevel.L.getLevel())
- .build();
+ R8Command.Builder builder =
+ ToolHelper.prepareR8CommandBuilder(app, emptyConsumer(backend))
+ .addLibraryFiles(runtimeJar(backend))
+ .addProguardConfigurationFiles(proguardConfig);
+ if (backend == Backend.DEX) {
+ builder.setMinApiLevel(AndroidApiLevel.L.getLevel());
+ }
String resultFromJava = runOnJava(mainClass);
- app = ToolHelper.runR8(command, options -> options.interfaceMethodDesugaring = OffOrAuto.Auto);
- String resultFromArt = runOnArt(app, mainClass);
- Assert.assertEquals(resultFromJava, resultFromArt);
+ app =
+ ToolHelper.runR8(
+ builder.build(), options -> options.interfaceMethodDesugaring = OffOrAuto.Auto);
+ String result;
+ if (backend == Backend.DEX) {
+ result = runOnArt(app, mainClass);
+ } else {
+ assert backend == Backend.CF;
+ result = runOnJava(app, mainClass);
+ }
+ Assert.assertEquals(resultFromJava, result);
}
@Test
diff --git a/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java b/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java
index b2bcb4e..ee99b38 100644
--- a/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.rewrite.switchmaps;
import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
@@ -13,12 +12,28 @@
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+@RunWith(Parameterized.class)
public class RewriteSwitchMapsTest extends TestBase {
+ private Backend backend;
+
+ @Parameterized.Parameters(name = "Backend: {0}")
+ public static Collection<Backend> data() {
+ return Arrays.asList(Backend.values());
+ }
+
+ public RewriteSwitchMapsTest(Backend backend) {
+ this.backend = backend;
+ }
+
private static final String JAR_FILE = "switchmaps.jar";
private static final String SWITCHMAP_CLASS_NAME = "switchmaps.Switches$1";
private static final List<String> PG_CONFIG = ImmutableList.of(
@@ -37,15 +52,16 @@
}
private void run(CompilationMode compilationMode) throws Exception {
- R8Command command = R8Command.builder()
- .addProgramFiles(Paths.get(ToolHelper.EXAMPLES_BUILD_DIR).resolve(JAR_FILE))
- .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
- .addProguardConfiguration(PG_CONFIG, Origin.unknown())
- .setMode(compilationMode)
- .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
- .build();
+ R8Command command =
+ R8Command.builder()
+ .addProgramFiles(Paths.get(ToolHelper.EXAMPLES_BUILD_DIR).resolve(JAR_FILE))
+ .addLibraryFiles(runtimeJar(backend))
+ .addProguardConfiguration(PG_CONFIG, Origin.unknown())
+ .setMode(compilationMode)
+ .setProgramConsumer(emptyConsumer(backend))
+ .build();
AndroidApp result = ToolHelper.runR8(command);
- CodeInspector inspector = new CodeInspector(result);
+ CodeInspector inspector = new CodeInspector(result, o -> o.enableCfFrontend = true);
Assert.assertFalse(inspector.clazz(SWITCHMAP_CLASS_NAME).isPresent());
}
}