Reland "Fix inability to map static interface method during outlining"
This reverts commit ee37ab87e10a9ba7ff16bfd2f3b4f6047e3d7016.
Change-Id: Iefb1f8417d729dae180fc4b2347fe10b7d55dbf3
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLens.java b/src/main/java/com/android/tools/r8/graph/GraphLens.java
index 7681f24..f2de6db 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLens.java
@@ -950,10 +950,7 @@
@Override
public DexMethod getOriginalMethodSignature(DexMethod method) {
- DexMethod originalMethod =
- originalMethodSignatures != null
- ? originalMethodSignatures.getOrDefault(method, method)
- : method;
+ DexMethod originalMethod = internalGetPreviousMethodSignature(method);
return getPrevious().getOriginalMethodSignature(originalMethod);
}
@@ -971,9 +968,7 @@
return originalMethod;
}
DexMethod renamedMethod = getPrevious().getRenamedMethodSignature(originalMethod, applied);
- return originalMethodSignatures != null
- ? originalMethodSignatures.inverse().getOrDefault(renamedMethod, renamedMethod)
- : renamedMethod;
+ return internalGetNextMethodSignature(renamedMethod);
}
@Override
@@ -1064,6 +1059,12 @@
: method;
}
+ protected DexMethod internalGetNextMethodSignature(DexMethod method) {
+ return originalMethodSignatures != null
+ ? originalMethodSignatures.inverse().getOrDefault(method, method)
+ : method;
+ }
+
@Override
public DexMethod lookupGetFieldForMethod(DexField field, DexMethod context) {
return getPrevious().lookupGetFieldForMethod(field, context);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index fd1bfe1..99230aa 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -108,7 +108,7 @@
implMethod.copyMetadata(virtual);
virtual.setDefaultInterfaceMethodImplementation(implMethod);
companionMethods.add(implMethod);
- graphLensBuilder.recordOrigin(implMethod.method, virtual.method);
+ graphLensBuilder.recordCodeMovedToCompanionClass(virtual.method, implMethod.method);
}
// Remove bridge methods.
@@ -453,15 +453,17 @@
}
@Override
- public DexMethod getOriginalMethodSignature(DexMethod method) {
- DexMethod originalMethod = extraOriginalMethodSignatures.get(method);
- if (originalMethod == null) {
- originalMethod =
- originalMethodSignatures != null
- ? originalMethodSignatures.getOrDefault(method, method)
- : method;
- }
- return getPrevious().getOriginalMethodSignature(originalMethod);
+ protected DexMethod internalGetPreviousMethodSignature(DexMethod method) {
+ return extraOriginalMethodSignatures.getOrDefault(
+ method, originalMethodSignatures.getOrDefault(method, method));
+ }
+
+ @Override
+ protected DexMethod internalGetNextMethodSignature(DexMethod method) {
+ return originalMethodSignatures
+ .inverse()
+ .getOrDefault(
+ method, extraOriginalMethodSignatures.inverse().getOrDefault(method, method));
}
@Override
@@ -477,11 +479,10 @@
private final BiMap<DexMethod, DexMethod> extraOriginalMethodSignatures = HashBiMap.create();
- public void recordOrigin(DexMethod method, DexMethod origin) {
- if (method == origin) {
- return;
- }
- extraOriginalMethodSignatures.put(method, origin);
+ public void recordCodeMovedToCompanionClass(DexMethod from, DexMethod to) {
+ assert from != to;
+ originalMethodSignatures.put(from, from);
+ extraOriginalMethodSignatures.put(to, from);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineFromStaticInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineFromStaticInterfaceMethodTest.java
new file mode 100644
index 0000000..ec4c859
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlineFromStaticInterfaceMethodTest.java
@@ -0,0 +1,114 @@
+// 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.ir.optimize.outliner;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
+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.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class OutlineFromStaticInterfaceMethodTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public OutlineFromStaticInterfaceMethodTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(TestClass.class)
+ .addOptionsModification(
+ options -> {
+ if (parameters.isCfRuntime()) {
+ assert !options.outline.enabled;
+ options.outline.enabled = true;
+ }
+ options.outline.threshold = 2;
+ options.outline.minSize = 2;
+ })
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello world!", "Hello world!");
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject interfaceSubject =
+ parameters.isCfRuntime()
+ || parameters
+ .getApiLevel()
+ .isGreaterThanOrEqualTo(apiLevelWithStaticInterfaceMethodsSupport())
+ ? inspector.clazz(I.class)
+ : inspector.clazz(
+ I.class.getTypeName() + InterfaceMethodRewriter.COMPANION_CLASS_NAME_SUFFIX);
+ assertThat(interfaceSubject, isPresent());
+
+ MethodSubject greetMethodSubject = interfaceSubject.uniqueMethodWithName("greet");
+ assertThat(greetMethodSubject, isPresent());
+ assertEquals(
+ 1,
+ greetMethodSubject.streamInstructions().filter(InstructionSubject::isInvokeStatic).count());
+ }
+
+ static class TestClass {
+
+ public static void main(String... args) {
+ greet();
+ I.greet();
+ }
+
+ @NeverInline
+ static void greet() {
+ Greeter.hello();
+ Greeter.world();
+ }
+ }
+
+ interface I {
+
+ @NeverInline
+ static void greet() {
+ Greeter.hello();
+ Greeter.world();
+ }
+ }
+
+ @NeverClassInline
+ public static class Greeter {
+
+ @NeverInline
+ public static void hello() {
+ System.out.print("Hello");
+ }
+
+ @NeverInline
+ public static void world() {
+ System.out.println(" world!");
+ }
+ }
+}