Merge "Reproduce b/122819537: kotlinc-generated synthetic methods are not traced."
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 46d3a68..898d06c 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -885,6 +885,8 @@
if (context instanceof ProguardKeepRule) {
if (item.isDexEncodedMethod() && item.asDexEncodedMethod().accessFlags.isSynthetic()) {
// Don't keep synthetic methods (see b/120971047 for additional details).
+ // TODO(b/122819537): need to distinguish lambda desugared synthetic methods v.s. kotlinc
+ // synthetic methods?
return;
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java b/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java
index 767e818..700e2d4 100644
--- a/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java
@@ -25,32 +25,42 @@
return buildParameters(Backend.values(), KotlinTargetVersion.values());
}
- @Test
- public void testDontShrinkAndDontObfuscate() throws Exception {
+ private void test(String... rules) throws Exception {
testForR8(backend)
.addLibraryFiles(ToolHelper.getDefaultAndroidJar(), ToolHelper.getKotlinStdlibJar())
.addProgramFiles(ToolHelper.getKotlinReflectJar())
- .addKeepRules("-dontshrink")
- .addKeepRules("-dontobfuscate")
+ .addKeepRules(rules)
.compile();
}
@Test
+ public void testAsIs() throws Exception {
+ test("-dontshrink", "-dontoptimize", "-dontobfuscate");
+ }
+
+ @Test
+ public void testDontShrinkAndDontOptimize() throws Exception {
+ test("-dontshrink", "-dontoptimize");
+ }
+
+ @Test
+ public void testDontShrinkAndDontObfuscate() throws Exception {
+ test("-dontshrink", "-dontobfuscate");
+ }
+
+ @Test
public void testDontShrink() throws Exception {
- testForR8(backend)
- .addLibraryFiles(ToolHelper.getDefaultAndroidJar(), ToolHelper.getKotlinStdlibJar())
- .addProgramFiles(ToolHelper.getKotlinReflectJar())
- .addKeepRules("-dontshrink")
- .compile();
+ test("-dontshrink");
+ }
+
+ @Test
+ public void testDontOptimize() throws Exception {
+ test("-dontoptimize");
}
@Test
public void testDontObfuscate() throws Exception {
- testForR8(backend)
- .addLibraryFiles(ToolHelper.getDefaultAndroidJar(), ToolHelper.getKotlinStdlibJar())
- .addProgramFiles(ToolHelper.getKotlinReflectJar())
- .addKeepRules("-dontobfuscate")
- .compile();
+ test("-dontobfuscate");
}
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinStdlibTest.java b/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinStdlibTest.java
index 44047d9..f19b089 100644
--- a/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinStdlibTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinStdlibTest.java
@@ -25,33 +25,49 @@
return buildParameters(Backend.values(), KotlinTargetVersion.values());
}
- @Test
- public void testDontShrinkAndDontObfuscate() throws Exception {
+ private void test(String... rules) throws Exception {
testForR8(backend)
.addProgramFiles(ToolHelper.getKotlinStdlibJar())
- .addKeepRules("-dontshrink")
- .addKeepRules("-dontobfuscate")
+ .addKeepRules(rules)
.compile();
}
@Test
+ public void testAsIs() throws Exception {
+ test("-dontshrink", "-dontoptimize", "-dontobfuscate");
+ }
+
+ @Test
+ public void testDontShrinkAndDontOptimize() throws Exception {
+ // TODO(b/122819537): need to trace kotlinc-generated synthetic methods.
+ if (backend == Backend.DEX) {
+ return;
+ }
+ test("-dontshrink", "-dontoptimize");
+ }
+
+ @Test
+ public void testDontShrinkAndDontObfuscate() throws Exception {
+ test("-dontshrink", "-dontobfuscate");
+ }
+
+ @Test
public void testDontShrink() throws Exception {
- // TODO(b/122819537)
+ // TODO(b/122819537): need to trace kotlinc-generated synthetic methods.
if (backend == Backend.DEX) {
return;
}
- testForR8(backend)
- .addProgramFiles(ToolHelper.getKotlinStdlibJar())
- .addKeepRules("-dontshrink")
- .compile();
+ test("-dontshrink");
+ }
+
+ @Test
+ public void testDontOptimize() throws Exception {
+ test("-dontoptimize");
}
@Test
public void testDontObfuscate() throws Exception {
- testForR8(backend)
- .addProgramFiles(ToolHelper.getKotlinStdlibJar())
- .addKeepRules("-dontobfuscate")
- .compile();
+ test("-dontobfuscate");
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/synthetic/KotlinCollectionDump.java b/src/test/java/com/android/tools/r8/shaking/synthetic/KotlinCollectionDump.java
new file mode 100644
index 0000000..d104272
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/synthetic/KotlinCollectionDump.java
@@ -0,0 +1,113 @@
+// 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.shaking.synthetic;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+// Generated by running tools/asmifier.py on the following code snippet:
+//
+// class Base {
+// public static void foo() {
+// System.out.println("Base::foo");
+// }
+// static void bar() {
+// Sub.foo();
+// }
+// }
+//
+// then make bar _synthetic_ as `kotlinc` does.
+class Base implements Opcodes {
+
+ public static byte[] dump () throws Exception {
+
+ ClassWriter classWriter = new ClassWriter(0);
+ MethodVisitor methodVisitor;
+
+ classWriter.visit(V1_8, ACC_SUPER, "Base", null, "java/lang/Object", null);
+
+ classWriter.visitSource("Arrays.kt", null);
+
+ {
+ methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(3, label0);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ methodVisitor.visitInsn(RETURN);
+ methodVisitor.visitMaxs(1, 1);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, "foo", "()V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(5, label0);
+ methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ methodVisitor.visitLdcInsn("Base::foo");
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLineNumber(6, label1);
+ methodVisitor.visitInsn(RETURN);
+ methodVisitor.visitMaxs(2, 0);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor = classWriter.visitMethod(ACC_STATIC | ACC_SYNTHETIC, "bar", "()V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(9, label0);
+ methodVisitor.visitMethodInsn(INVOKESTATIC, "Sub", "foo", "()V", false);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLineNumber(10, label1);
+ methodVisitor.visitInsn(RETURN);
+ methodVisitor.visitMaxs(0, 0);
+ methodVisitor.visitEnd();
+ }
+ classWriter.visitEnd();
+
+ return classWriter.toByteArray();
+ }
+}
+
+// Generated by running tools/asmifier.py on the following code snippet:
+// class Sub extends Base {}
+class Sub implements Opcodes {
+
+ public static byte[] dump () throws Exception {
+
+ ClassWriter classWriter = new ClassWriter(0);
+ MethodVisitor methodVisitor;
+
+ classWriter.visit(V1_8, ACC_SUPER, "Sub", null, "Base", null);
+
+ classWriter.visitSource("Arrays.kt", null);
+
+ {
+ methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(13, label0);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitMethodInsn(INVOKESPECIAL, "Base", "<init>", "()V", false);
+ methodVisitor.visitInsn(RETURN);
+ methodVisitor.visitMaxs(1, 1);
+ methodVisitor.visitEnd();
+ }
+ classWriter.visitEnd();
+
+ return classWriter.toByteArray();
+ }
+}
+
diff --git a/src/test/java/com/android/tools/r8/shaking/synthetic/StaticCallInSyntheticMethodAsmTest.java b/src/test/java/com/android/tools/r8/shaking/synthetic/StaticCallInSyntheticMethodAsmTest.java
new file mode 100644
index 0000000..cad2410
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/synthetic/StaticCallInSyntheticMethodAsmTest.java
@@ -0,0 +1,46 @@
+// 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.shaking.synthetic;
+
+import com.android.tools.r8.AsmTestBase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class StaticCallInSyntheticMethodAsmTest extends AsmTestBase {
+ private final Backend backend;
+
+ @Parameterized.Parameters(name = "backend: {0}")
+ public static Backend[] data() {
+ return Backend.values();
+ }
+
+ public StaticCallInSyntheticMethodAsmTest(Backend backend) {
+ this.backend = backend;
+ }
+
+ // class Base {
+ // static void foo() { ... }
+ // static synthetic void bar() { Sub.foo(); }
+ // }
+ // class Sub extends Base {}
+ //
+ // As per b/120971047, we do not add synthetic methods to the root set.
+ // When running the above example with -dontshrink, the static call in the synthetic method is not
+ // traced, so no chance to rebind that call to Base#foo. Then, at the end of dex writing, it hits
+ // assertion error in the naming lense that checks if call targets are eligible for renaming.
+ @Test
+ public void test() throws Exception {
+ // TODO(b/122819537): need to trace kotlinc-generated synthetic methods.
+ if (backend == Backend.DEX) {
+ return;
+ }
+ testForR8(backend)
+ .addProgramClassFileData(Base.dump(), Sub.dump())
+ .addKeepRules("-dontshrink")
+ .compile();
+ }
+
+}