Version 1.6.46
Cherry-pick: Don't run the outliner when compiling to classfiles.
CL: https://r8-review.googlesource.com/c/r8/+/45007
Resolved conflict by adding
src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlinesWithNonNullTest.java
which was not on the branch.
Bug: 143550696
Change-Id: Ica63d398d8ecfe6c645332231e2dea5998dece73
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 235882e..a568336 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -859,6 +859,13 @@
internal.assertionProcessing = AssertionProcessing.LEAVE;
}
+ // When generating class files the build is "intermediate" and we cannot pollute the namespace
+ // with the a hard-coded outline class. Doing so would prohibit subsequent merging of two
+ // R8 produced libraries.
+ if (internal.isGeneratingClassFiles()) {
+ internal.outline.enabled = false;
+ }
+
// EXPERIMENTAL flags.
assert !internal.forceProguardCompatibility;
internal.forceProguardCompatibility = forceProguardCompatibility;
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 05e7e22..091b934 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "1.6.45";
+ public static final String LABEL = "1.6.46";
private Version() {
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/NoOutliningForClassFileBuildsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/NoOutliningForClassFileBuildsTest.java
new file mode 100644
index 0000000..4af2593
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/NoOutliningForClassFileBuildsTest.java
@@ -0,0 +1,102 @@
+// 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.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class NoOutliningForClassFileBuildsTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("foobarbaz");
+
+ private final TestParameters parameters;
+ private final boolean forceOutline;
+
+ @Parameterized.Parameters(name = "{0}, force-outline: {1}")
+ public static Collection<Object[]> data() {
+ List<Object[]> args = new ArrayList<>();
+ for (TestParameters parameter : getTestParameters().withAllRuntimesAndApiLevels().build()) {
+ args.add(new Object[] {parameter, false});
+ if (parameter.isCfRuntime()) {
+ args.add(new Object[] {parameter, true});
+ }
+ }
+ return args;
+ }
+
+ public NoOutliningForClassFileBuildsTest(TestParameters parameters, boolean forceOutline) {
+ this.parameters = parameters;
+ this.forceOutline = forceOutline;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .noMinification()
+ .addProgramClasses(TestClass.class)
+ .addKeepClassAndMembersRules(TestClass.class)
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(
+ o -> {
+ if (forceOutline) {
+ o.outline.enabled = true;
+ }
+ o.outline.minSize = 2;
+ o.outline.maxSize = 20;
+ o.outline.threshold = 2;
+ })
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED)
+ .inspect(this::checkOutlining);
+ }
+
+ private void checkOutlining(CodeInspector inspector) {
+ ClassSubject classSubject = inspector.clazz(TestClass.class);
+ assertThat(classSubject, isPresent());
+ assertThat(classSubject.uniqueMethodWithName("foo"), isPresent());
+ assertThat(classSubject.uniqueMethodWithName("bar"), isPresent());
+ boolean hasOutlineClass =
+ inspector.allClasses().stream()
+ .anyMatch(c -> c.getFinalName().equals(OutlineOptions.CLASS_NAME));
+ assertEquals(forceOutline || parameters.isDexRuntime(), hasOutlineClass);
+ }
+
+ static class TestClass {
+
+ public void foo(String arg) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("foo");
+ builder.append(arg);
+ builder.append("baz");
+ System.out.println(builder.toString());
+ }
+
+ public void bar(String arg) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("foo");
+ builder.append(arg);
+ builder.append("baz");
+ System.out.println(builder.toString());
+ }
+
+ public static void main(String[] args) {
+ new TestClass().foo("bar");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlinesWithNonNullTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlinesWithNonNullTest.java
new file mode 100644
index 0000000..bea51f6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlinesWithNonNullTest.java
@@ -0,0 +1,194 @@
+// 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.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+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.utils.InternalOptions.OutlineOptions;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.CodeMatchers;
+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 OutlinesWithNonNullTest extends TestBase {
+ private static final String JVM_OUTPUT = StringUtils.lines(
+ "42",
+ "arg",
+ "42",
+ "arg"
+ );
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().build();
+ }
+
+ public OutlinesWithNonNullTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testNonNullOnOneSide() throws Exception {
+ testForR8(parameters.getBackend())
+ .enableClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .addProgramClasses(TestArg.class, TestClassWithNonNullOnOneSide.class)
+ .addKeepMainRule(TestClassWithNonNullOnOneSide.class)
+ .setMinApi(parameters.getRuntime())
+ .allowAccessModification()
+ .noMinification()
+ .addOptionsModification(
+ options -> {
+ if (parameters.isCfRuntime()) {
+ assert !options.outline.enabled;
+ options.outline.enabled = true;
+ }
+ options.outline.threshold = 2;
+ options.outline.minSize = 2;
+ })
+ .compile()
+ .inspect(inspector -> validateOutlining(inspector, TestClassWithNonNullOnOneSide.class))
+ .run(parameters.getRuntime(), TestClassWithNonNullOnOneSide.class)
+ .assertSuccessWithOutput(JVM_OUTPUT);
+ }
+
+ @Test
+ public void testNonNullOnBothSides() throws Exception {
+ testForR8(parameters.getBackend())
+ .enableClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .addProgramClasses(TestArg.class, TestClassWithNonNullOnBothSides.class)
+ .addKeepMainRule(TestClassWithNonNullOnBothSides.class)
+ .setMinApi(parameters.getRuntime())
+ .allowAccessModification()
+ .noMinification()
+ .addOptionsModification(
+ options -> {
+ if (parameters.isCfRuntime()) {
+ assert !options.outline.enabled;
+ options.outline.enabled = true;
+ }
+ options.outline.threshold = 2;
+ options.outline.minSize = 2;
+ })
+ .compile()
+ .inspect(inspector -> validateOutlining(inspector, TestClassWithNonNullOnBothSides.class))
+ .run(parameters.getRuntime(), TestClassWithNonNullOnBothSides.class)
+ .assertSuccessWithOutput(JVM_OUTPUT);
+ }
+
+ private void validateOutlining(CodeInspector inspector, Class<?> main) {
+ ClassSubject outlineClass = inspector.clazz(OutlineOptions.CLASS_NAME);
+ assertThat(outlineClass, isPresent());
+ MethodSubject outlineMethod = outlineClass.uniqueMethodWithName("outline0");
+ assertThat(outlineMethod, isPresent());
+
+ ClassSubject argClass = inspector.clazz(TestArg.class);
+ assertThat(argClass, isPresent());
+ MethodSubject printHash = argClass.uniqueMethodWithName("printHash");
+ assertThat(printHash, isPresent());
+ MethodSubject printArg= argClass.uniqueMethodWithName("printArg");
+ assertThat(printArg, isPresent());
+
+ ClassSubject classSubject = inspector.clazz(main);
+ assertThat(classSubject, isPresent());
+ MethodSubject method1 = classSubject.uniqueMethodWithName("method1");
+ assertThat(method1, isPresent());
+ assertThat(method1, CodeMatchers.invokesMethod(outlineMethod));
+ assertThat(method1, not(CodeMatchers.invokesMethod(printHash)));
+ assertThat(method1, not(CodeMatchers.invokesMethod(printArg)));
+ MethodSubject method2 = classSubject.uniqueMethodWithName("method2");
+ assertThat(method2, isPresent());
+ assertThat(method2, CodeMatchers.invokesMethod(outlineMethod));
+ assertThat(method2, not(CodeMatchers.invokesMethod(printHash)));
+ assertThat(method2, not(CodeMatchers.invokesMethod(printArg)));
+ }
+
+ @NeverClassInline
+ public static class TestArg {
+ @Override
+ public int hashCode() {
+ return 42;
+ }
+
+ @Override
+ public String toString() {
+ return "arg";
+ }
+
+ @NeverInline
+ static void printHash(Object arg) {
+ if (arg == null) {
+ throw new NullPointerException();
+ }
+ System.out.println(arg.hashCode());
+ // This method guarantees that, at the normal exit, argument is not null.
+ }
+
+ @NeverInline
+ static void printArg(Object arg) {
+ System.out.println(arg);
+ }
+ }
+
+ static class TestClassWithNonNullOnOneSide {
+ @NeverInline
+ static void method1(Object arg) {
+ TestArg.printHash(arg);
+ // We will have non-null aliasing here.
+ TestArg.printArg(arg);
+ }
+
+ @NeverInline
+ static void method2(Object arg) {
+ if (arg != null) {
+ // We will have non-null aliasing here.
+ TestArg.printHash(arg);
+ TestArg.printArg(arg);
+ }
+ }
+
+ public static void main(String... args) {
+ TestArg arg = new TestArg();
+ method1(arg);
+ method2(arg);
+ }
+ }
+
+ static class TestClassWithNonNullOnBothSides {
+ @NeverInline
+ static void method1(Object arg) {
+ TestArg.printHash(arg);
+ // We will have non-null aliasing here.
+ TestArg.printArg(arg);
+ }
+
+ @NeverInline
+ static void method2(Object arg) {
+ TestArg.printHash(arg);
+ // We will have non-null aliasing here.
+ TestArg.printArg(arg);
+ }
+
+ public static void main(String... args) {
+ TestArg arg = new TestArg();
+ method1(arg);
+ method2(arg);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithClassArrayTypeArguments.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithClassArrayTypeArguments.java
index 604e3fe..099afa8 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithClassArrayTypeArguments.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithClassArrayTypeArguments.java
@@ -63,6 +63,10 @@
.noMinification()
.addOptionsModification(
options -> {
+ if (parameters.isCfRuntime()) {
+ assert !options.outline.enabled;
+ options.outline.enabled = true;
+ }
options.outline.threshold = 2;
options.outline.minSize = 2;
})
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithInterfaceArrayTypeArguments.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithInterfaceArrayTypeArguments.java
index 33e5f96..fb4417f9 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithInterfaceArrayTypeArguments.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithInterfaceArrayTypeArguments.java
@@ -74,6 +74,10 @@
.noMinification()
.addOptionsModification(
options -> {
+ if (parameters.isCfRuntime()) {
+ assert !options.outline.enabled;
+ options.outline.enabled = true;
+ }
options.outline.threshold = 2;
options.outline.minSize = 2;
options.testing.allowOutlinerInterfaceArrayArguments =
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithPrimitiveArrayTypeArguments.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithPrimitiveArrayTypeArguments.java
index 8a78d77..7a69926 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithPrimitiveArrayTypeArguments.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithPrimitiveArrayTypeArguments.java
@@ -59,6 +59,10 @@
.noMinification()
.addOptionsModification(
options -> {
+ if (parameters.isCfRuntime()) {
+ assert !options.outline.enabled;
+ options.outline.enabled = true;
+ }
options.outline.threshold = 2;
options.outline.minSize = 2;
})
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b112247415/B112247415.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b112247415/B112247415.java
index ef9e4f3..9fcc6b7 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b112247415/B112247415.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b112247415/B112247415.java
@@ -85,6 +85,10 @@
.addProgramClassesAndInnerClasses(TestClass.class)
.addKeepMainRule(TestClass.class)
.addOptionsModification(options -> {
+ if (parameters.isCfRuntime()) {
+ assert !options.outline.enabled;
+ options.outline.enabled = true;
+ }
// To trigger outliner, set # of expected outline candidate as threshold.
options.outline.threshold = 2;
options.enableInlining = false;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b133215941/B133215941.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b133215941/B133215941.java
index c7d5cf0..b380f62 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b133215941/B133215941.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b133215941/B133215941.java
@@ -70,7 +70,13 @@
.addKeepClassAndMembersRules(ClassWithStaticMethod.class)
.setMinApi(parameters.getRuntime())
.noMinification()
- .addOptionsModification(options -> options.outline.threshold = 2)
+ .addOptionsModification(options -> {
+ if (parameters.isCfRuntime()) {
+ assert !options.outline.enabled;
+ options.outline.enabled = true;
+ }
+ options.outline.threshold = 2;
+ })
.compile()
.inspect(this::validateOutlining)
.run(parameters.getRuntime(), TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java
index 177bc91..eab6811 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java
@@ -67,6 +67,10 @@
.noMinification()
.addOptionsModification(
options -> {
+ if (parameters.isCfRuntime()) {
+ assert !options.outline.enabled;
+ options.outline.enabled = true;
+ }
options.outline.threshold = 2;
options.outline.minSize = 2;
})
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java
index aba1f31..f6e72b2 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java
@@ -62,6 +62,10 @@
.noMinification()
.addOptionsModification(
options -> {
+ if (parameters.isCfRuntime()) {
+ assert !options.outline.enabled;
+ options.outline.enabled = true;
+ }
options.outline.threshold = 2;
options.outline.minSize = 2;
})