Add a test to shrink Kotlin compiler.
Bug: 144859533
Change-Id: Ib9cecc211854a1383c7fd091069e172350a93947
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index 55cabed..fb96a96 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -174,6 +174,7 @@
CfInvoke invoke = (CfInvoke) instruction;
if (invoke.getMethod().holder.isClassType()) {
DexClass holder = appView.definitionFor(invoke.getMethod().holder);
+ // TODO(b/144861100): static method in interface?
assert holder == null || holder.isInterface() == invoke.isInterface();
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNamingState.java b/src/main/java/com/android/tools/r8/naming/MethodNamingState.java
index ccac2d6..c6b7ee0 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNamingState.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNamingState.java
@@ -185,6 +185,7 @@
if (isDirectMethodCall) {
return virtualNameCount + directNameCount++;
} else {
+ // TODO(b/144877828): is it guaranteed?
assert directNameCount == 0;
return virtualNameCount++;
}
diff --git a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
index 4109295..268709d 100644
--- a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
+++ b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
@@ -28,21 +28,27 @@
private final CfRuntime jdk;
private final TestState state;
+ private final String kotlincJar;
private final List<Path> sources = new ArrayList<>();
private final List<Path> classpath = new ArrayList<>();
private Path output = null;
- private KotlinCompilerTool(CfRuntime jdk, TestState state) {
+ private KotlinCompilerTool(CfRuntime jdk, TestState state, Path kotlincJar) {
this.jdk = jdk;
this.state = state;
+ this.kotlincJar = kotlincJar == null ? KT_COMPILER : kotlincJar.toString();
}
public static KotlinCompilerTool create(CfRuntime jdk, TemporaryFolder temp) {
- return create(jdk, new TestState(temp));
+ return create(jdk, new TestState(temp), null);
}
- public static KotlinCompilerTool create(CfRuntime jdk, TestState state) {
- return new KotlinCompilerTool(jdk, state);
+ public static KotlinCompilerTool create (CfRuntime jdk, TemporaryFolder temp, Path kotlincJar) {
+ return create(jdk, new TestState(temp), kotlincJar);
+ }
+
+ public static KotlinCompilerTool create(CfRuntime jdk, TestState state, Path kotlincJar) {
+ return new KotlinCompilerTool(jdk, state, kotlincJar);
}
public KotlinCompilerTool addSourceFiles(Path files) {
@@ -99,8 +105,8 @@
cmdline.add(KT_PRELOADER);
cmdline.add("org.jetbrains.kotlin.preloading.Preloader");
cmdline.add("-cp");
- cmdline.add(KT_COMPILER);
- cmdline.add("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler");
+ cmdline.add(kotlincJar);
+ cmdline.add(ToolHelper.K2JVMCompiler);
for (Path source : sources) {
cmdline.add(source.toString());
}
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 2eb2d42..b90b40c 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -186,6 +186,10 @@
return KotlinCompilerTool.create(jdk, temp);
}
+ public KotlinCompilerTool kotlinc(CfRuntime jdk, Path kotlincJar) {
+ return KotlinCompilerTool.create(jdk, temp, kotlincJar);
+ }
+
public static KotlinCompilerTool kotlinc(CfRuntime jdk, TemporaryFolder temp) {
return KotlinCompilerTool.create(jdk, temp);
}
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 6b224e3..43d08bc 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -129,9 +129,12 @@
"third_party/rhino-android-1.1.1/rhino-android-1.1.1.jar";
public static final String RHINO_JAR = "third_party/rhino-1.7.10/rhino-1.7.10.jar";
static final String KT_PRELOADER = "third_party/kotlin/kotlinc/lib/kotlin-preloader.jar";
- static final String KT_COMPILER = "third_party/kotlin/kotlinc/lib/kotlin-compiler.jar";
+ public static final String KT_COMPILER = "third_party/kotlin/kotlinc/lib/kotlin-compiler.jar";
+ public static final String K2JVMCompiler = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler";
public static final String KT_STDLIB = "third_party/kotlin/kotlinc/lib/kotlin-stdlib.jar";
public static final String KT_REFLECT = "third_party/kotlin/kotlinc/lib/kotlin-reflect.jar";
+ public static final String KT_SCRIPT_RT =
+ "third_party/kotlin/kotlinc/lib/kotlin-script-runtime.jar";
private static final String ANDROID_JAR_PATTERN = "third_party/android_jar/lib-v%d/android.jar";
private static final AndroidApiLevel DEFAULT_MIN_SDK = AndroidApiLevel.I;
@@ -1284,7 +1287,7 @@
cmdline.add("org.jetbrains.kotlin.preloading.Preloader");
cmdline.add("-cp");
cmdline.add(KT_COMPILER);
- cmdline.add("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler");
+ cmdline.add(K2JVMCompiler);
String[] strings = Arrays.stream(filesToCompile).map(Path::toString).toArray(String[]::new);
Collections.addAll(cmdline, strings);
cmdline.add("-d");
diff --git a/src/test/java/com/android/tools/r8/cf/BootstrapCurrentEqualityTest.java b/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java
similarity index 99%
rename from src/test/java/com/android/tools/r8/cf/BootstrapCurrentEqualityTest.java
rename to src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java
index cafb01b..a19cfec 100644
--- a/src/test/java/com/android/tools/r8/cf/BootstrapCurrentEqualityTest.java
+++ b/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java
@@ -1,7 +1,7 @@
// 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.cf;
+package com.android.tools.r8.cf.bootstrap;
import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
import static com.google.common.io.ByteStreams.toByteArray;
diff --git a/src/test/java/com/android/tools/r8/cf/BootstrapTest.java b/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapTest.java
similarity index 99%
rename from src/test/java/com/android/tools/r8/cf/BootstrapTest.java
rename to src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapTest.java
index addc3ec..722e4f6 100644
--- a/src/test/java/com/android/tools/r8/cf/BootstrapTest.java
+++ b/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapTest.java
@@ -1,7 +1,7 @@
// 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.cf;
+package com.android.tools.r8.cf.bootstrap;
import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
import static com.google.common.io.ByteStreams.toByteArray;
diff --git a/src/test/java/com/android/tools/r8/cf/bootstrap/Hello.kt b/src/test/java/com/android/tools/r8/cf/bootstrap/Hello.kt
new file mode 100644
index 0000000..fdfc655
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/bootstrap/Hello.kt
@@ -0,0 +1,8 @@
+// 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.cf.bootstrap
+
+fun main(args : Array<String>) {
+ println("I'm Woody. Howdy, howdy, howdy.")
+}
diff --git a/src/test/java/com/android/tools/r8/cf/bootstrap/KotlinCompilerTreeShakingTest.java b/src/test/java/com/android/tools/r8/cf/bootstrap/KotlinCompilerTreeShakingTest.java
new file mode 100644
index 0000000..cef8fce
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/bootstrap/KotlinCompilerTreeShakingTest.java
@@ -0,0 +1,133 @@
+// 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.cf.bootstrap;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.internal.CompilationTestBase;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class KotlinCompilerTreeShakingTest extends CompilationTestBase {
+
+ private static final String PKG_NAME = KotlinCompilerTreeShakingTest.class.getPackage().getName();
+ private static final Path HELLO_KT =
+ Paths.get(
+ ToolHelper.TESTS_DIR,
+ "java",
+ DescriptorUtils.getBinaryNameFromJavaType(PKG_NAME),
+ "Hello.kt");
+ private static final int MAX_SIZE = (int) (31361268 * 0.4);
+
+ private TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withCfRuntimes().build();
+ }
+
+ public KotlinCompilerTreeShakingTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testForRuntime() throws Exception {
+ // Compile Hello.kt and make sure it works as expected.
+ Path classPathBefore =
+ kotlinc(parameters.getRuntime().asCf())
+ .addSourceFiles(HELLO_KT)
+ .setOutputPath(temp.newFolder().toPath())
+ .compile();
+ testForJvm()
+ .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar())
+ .addClasspath(classPathBefore)
+ .run(parameters.getRuntime(), PKG_NAME + ".HelloKt")
+ .assertSuccessWithOutputLines("I'm Woody. Howdy, howdy, howdy.");
+ }
+
+ @Ignore(
+ "b/136457753: assertion error in static class merger; "
+ + "b/144861100: assertion error in CfBuilder; "
+ + "b/144861881: force-inlining of non-inlineable constructors in vertical class merger; "
+ + "b/144877828: assertion error in method naming state during interface method renaming; "
+ + "b/144859533: umbrella"
+ )
+ @Test
+ public void test() throws Exception {
+ List<Path> libs =
+ ImmutableList.of(
+ ToolHelper.getKotlinStdlibJar(),
+ ToolHelper.getKotlinReflectJar(),
+ Paths.get(ToolHelper.KT_SCRIPT_RT));
+ // Process kotlin-compiler.jar.
+ Path r8ProcessedKotlinc =
+ testForR8(parameters.getBackend())
+ .addLibraryFiles(libs)
+ .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
+ .addProgramFiles(Paths.get(ToolHelper.KT_COMPILER))
+ .addKeepAttributes("*Annotation*")
+ .addKeepClassAndMembersRules(ToolHelper.K2JVMCompiler)
+ .addKeepClassAndMembersRules("**.K2JVMCompilerArguments")
+ .addKeepClassAndMembersRules("**.*Argument*")
+ .addKeepClassAndMembersRules("**.Freezable")
+ .addKeepRules(
+ "-keepclassmembers class * {",
+ " *** parseCommandLineArguments(...);",
+ "}"
+ )
+ .addKeepRules(
+ "-keepclassmembers,allowoptimization enum * {",
+ " public static **[] values();",
+ " public static ** valueOf(java.lang.String);",
+ "}")
+ .addOptionsModification(o -> {
+ // Ignore com.sun.tools.javac.main.JavaCompiler and others
+ // Resulting jar may not be able to deal with .java source files, though.
+ o.ignoreMissingClasses = true;
+ // TODO(b/144861881): force-inlining of non-inlineable constructors.
+ o.enableVerticalClassMerging = false;
+ })
+ .compile()
+ .writeToZip();
+
+ // Copy libraries used by kotlin-compiler.jar so that Preloader can load them.
+ Path dir = r8ProcessedKotlinc.getParent();
+ for (Path lib : libs) {
+ Path newLib = dir.resolve(lib.getFileName());
+ Files.copy(lib, newLib, REPLACE_EXISTING);
+ }
+
+ // TODO(b/144859533): passing `dir` as -kotlin-home.
+ // Compile Hello.kt again with r8-processed kotlin-compiler.jar
+ Path classPathAfter =
+ kotlinc(parameters.getRuntime().asCf(), r8ProcessedKotlinc)
+ .addSourceFiles(HELLO_KT)
+ .setOutputPath(temp.newFolder().toPath())
+ .compile();
+ testForJvm()
+ .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar())
+ .addClasspath(classPathAfter)
+ .run(parameters.getRuntime(), PKG_NAME + ".HelloKt")
+ .assertSuccessWithOutputLines("I'm Woody. Howdy, howdy, howdy.");
+
+ int size = applicationSize(AndroidApp.builder().addProgramFile(r8ProcessedKotlinc).build());
+ assertTrue(size <= MAX_SIZE);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/R8CompiledThroughDexTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/R8CompiledThroughDexTest.java
index 148f165..2533619 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/R8CompiledThroughDexTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/R8CompiledThroughDexTest.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.cf.BootstrapCurrentEqualityTest;
+import com.android.tools.r8.cf.bootstrap.BootstrapCurrentEqualityTest;
import com.android.tools.r8.desugar.desugaredlibrary.CoreLibDesugarTestBase;
import java.io.File;
import java.nio.file.Path;
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8BootstrapTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8BootstrapTest.java
index 8af167c..1f6832c 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8BootstrapTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8BootstrapTest.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.TestRuntime;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.cf.BootstrapCurrentEqualityTest;
+import com.android.tools.r8.cf.bootstrap.BootstrapCurrentEqualityTest;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;