Merge "Add a method for dumping disassembly in tests"
diff --git a/build.gradle b/build.gradle
index 2e70b1e..e469e03 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1199,10 +1199,10 @@
kotlin.Kotlinc.KotlinTargetVersion.values().each { kotlinTargetVersion ->
def name = dir.getName()
def taskName = "jar_kotlinR8TestResources_${name}_${kotlinTargetVersion}"
- def outputFile = "build/test/r8KotlinTestResources/${kotlinTargetVersion}/${name}.jar"
- def javaOutput = "build/test/r8KotlinTestResources/${kotlinTargetVersion}/${name}/java"
+ def outputFile = "build/test/kotlinR8TestResources/${kotlinTargetVersion}/${name}.jar"
+ def javaOutput = "build/test/kotlinR8TestResources/${kotlinTargetVersion}/${name}/java"
def javaOutputJarName = "${name}.java.jar"
- def javaOutputJarDir = "build/test/r8KotlinTestResources/${kotlinTargetVersion}"
+ def javaOutputJarDir = "build/test/kotlinR8TestResources/${kotlinTargetVersion}"
task "${taskName}Kotlin"(type: kotlin.Kotlinc) {
source = fileTree(dir: file("${examplesDir}/${name}"),
include: ['**/*.kt', '**/*.java'])
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 737ab05..72e2887 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -943,10 +943,16 @@
if (options.disableAssertions) {
codeRewriter.disableAssertions(appInfo, method, code, feedback);
}
+
+ previous = printMethod(code, "IR after disable assertions (SSA)", previous);
+
if (options.enableNonNullTracking && nonNullTracker != null) {
nonNullTracker.addNonNull(code);
assert code.isConsistentSSA();
}
+
+ previous = printMethod(code, "IR after null tracking (SSA)", previous);
+
if (!isDebugMode && options.enableInlining && inliner != null) {
// TODO(zerny): Should we support inlining in debug mode? b/62937285
inliner.performInlining(method, code, isProcessedConcurrently, callSiteInformation);
@@ -1000,7 +1006,7 @@
if (options.enableNonNullTracking && nonNullTracker != null) {
// Computation of non-null parameters on normal exits rely on the existence of non-null IRs.
- nonNullTracker.computeNonNullParamOnNormalExits(feedback, code);
+ nonNullTracker.computeNonNullParamOnNormalExits(feedback, method, code);
nonNullTracker.cleanupNonNull(code);
assert code.isConsistentSSA();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java b/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
index 463b7fc..2094584 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
@@ -119,7 +119,7 @@
knownToBeNonNullValues.add(knownToBeNonNullValue);
}
}
- if (current.isInvokeMethod()) {
+ if (current.isInvokeMethod() && !current.isInvokePolymorphic()) {
DexEncodedMethod singleTarget =
current.asInvokeMethod().lookupSingleTarget(appInfo, code.method.method.getHolder());
if (singleTarget != null
@@ -350,11 +350,12 @@
&& typeLattice.isReference();
}
- public void computeNonNullParamOnNormalExits(OptimizationFeedback feedback, IRCode code) {
+ public void computeNonNullParamOnNormalExits(
+ OptimizationFeedback feedback, DexEncodedMethod method, IRCode code) {
Set<BasicBlock> normalExits = Sets.newIdentityHashSet();
normalExits.addAll(code.computeNormalExitBlocks());
DominatorTree dominatorTree = new DominatorTree(code, MAY_HAVE_UNREACHABLE_BLOCKS);
- List<Value> arguments = code.collectArguments(true);
+ List<Value> arguments = code.collectArguments();
BitSet facts = new BitSet();
Set<BasicBlock> nullCheckedBlocks = Sets.newIdentityHashSet();
for (int index = 0; index < arguments.size(); index++) {
@@ -363,6 +364,10 @@
if (!argument.getTypeLattice().isReference()) {
continue;
}
+ if (index == 0 && !method.accessFlags.isStatic()) {
+ // The receiver is always non-null after an invocation;
+ facts.set(index);
+ }
// Collect basic blocks that check nullability of the parameter.
nullCheckedBlocks.clear();
for (Instruction user : argument.uniqueUsers()) {
diff --git a/src/test/java/com/android/tools/r8/KotlinTestBase.java b/src/test/java/com/android/tools/r8/KotlinTestBase.java
index 63dd265..9139583 100644
--- a/src/test/java/com/android/tools/r8/KotlinTestBase.java
+++ b/src/test/java/com/android/tools/r8/KotlinTestBase.java
@@ -9,9 +9,7 @@
import java.nio.file.Paths;
public abstract class KotlinTestBase extends TestBase {
- // It is important that Kotlin is capitalized, otherwise the string will be relocated when
- // building tests for r8lib with relocated dependencies.
- private static final String RSRC = "r8KotlinTestResources";
+ private static final String RSRC = "kotlinR8TestResources";
protected final KotlinTargetVersion targetVersion;
@@ -19,21 +17,18 @@
this.targetVersion = targetVersion;
}
- protected static Path getKotlinJarFile(String folder, KotlinTargetVersion targetVersion) {
+ protected Path getKotlinJarFile(String folder) {
return Paths.get(ToolHelper.TESTS_BUILD_DIR, RSRC,
targetVersion.getFolderName(), folder + FileUtils.JAR_EXTENSION);
}
- protected Path getKotlinJarFile(String folder) {
- return getKotlinJarFile(folder, targetVersion);
- }
-
- protected static Path getJavaJarFile(String folder, KotlinTargetVersion targetVersion) {
+ protected Path getJavaJarFile(String folder) {
return Paths.get(ToolHelper.TESTS_BUILD_DIR, RSRC,
targetVersion.getFolderName(), folder + ".java" + FileUtils.JAR_EXTENSION);
}
- protected Path getJavaJarFile(String folder) {
- return getJavaJarFile(folder, targetVersion);
+ protected Path getMappingfile(String folder, String mappingFileName) {
+ return Paths.get(ToolHelper.TESTS_DIR, RSRC, folder, mappingFileName);
}
+
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/NonNullParamTest.java b/src/test/java/com/android/tools/r8/ir/optimize/NonNullParamTest.java
index 5692a55..10b9a63 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/NonNullParamTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/NonNullParamTest.java
@@ -10,7 +10,16 @@
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ir.optimize.nonnull.IntrinsicsDeputy;
-import com.android.tools.r8.ir.optimize.nonnull.NonNullParamAfterInvoke;
+import com.android.tools.r8.ir.optimize.nonnull.NonNullParamAfterInvokeDirect;
+import com.android.tools.r8.ir.optimize.nonnull.NonNullParamAfterInvokeInterface;
+import com.android.tools.r8.ir.optimize.nonnull.NonNullParamAfterInvokeInterfaceMain;
+import com.android.tools.r8.ir.optimize.nonnull.NonNullParamAfterInvokeStatic;
+import com.android.tools.r8.ir.optimize.nonnull.NonNullParamAfterInvokeVirtual;
+import com.android.tools.r8.ir.optimize.nonnull.NonNullParamAfterInvokeVirtualMain;
+import com.android.tools.r8.ir.optimize.nonnull.NonNullParamInterface;
+import com.android.tools.r8.ir.optimize.nonnull.NonNullParamInterfaceImpl;
+import com.android.tools.r8.ir.optimize.nonnull.NotPinnedClass;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -18,6 +27,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import java.util.Collection;
+import java.util.function.Consumer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -36,22 +46,35 @@
this.backend = backend;
}
- CodeInspector buildAndRun(Class<?> mainClass, Collection<Class<?>> classes) throws Exception {
+ private void noModification(InternalOptions options) {}
+
+ private void disableDevirtualization(InternalOptions options) {
+ options.enableDevirtualization = false;
+ }
+
+ CodeInspector buildAndRun(
+ Class<?> mainClass,
+ Collection<Class<?>> classes,
+ Consumer<InternalOptions> optionsModification)
+ throws Exception {
String javaOutput = runOnJava(mainClass);
return testForR8(backend)
.addProgramClasses(classes)
.enableProguardTestOptions()
.enableInliningAnnotations()
+ .enableClassInliningAnnotations()
+ .enableMergeAnnotations()
.addKeepMainRule(mainClass)
.addKeepRules(
ImmutableList.of(
- "-keepattributes InnerClasses,Signature,EnclosingMethod",
- "-dontobfuscate"))
- .addOptionsModification(options -> {
- // Need to increase a little bit to inline System.out.println
- options.inliningInstructionLimit = 4;
- })
+ "-keepattributes InnerClasses,Signature,EnclosingMethod", "-dontobfuscate"))
+ .addOptionsModification(
+ options -> {
+ // Need to increase a little bit to inline System.out.println
+ options.inliningInstructionLimit = 4;
+ })
+ .addOptionsModification(optionsModification)
.run(mainClass)
.assertSuccessWithOutput(javaOutput)
.inspector();
@@ -60,8 +83,9 @@
@Test
public void testIntrinsics() throws Exception {
Class mainClass = IntrinsicsDeputy.class;
- CodeInspector inspector = buildAndRun(mainClass,
- ImmutableList.of(NeverInline.class, mainClass));
+ CodeInspector inspector =
+ buildAndRun(
+ mainClass, ImmutableList.of(NeverInline.class, mainClass), this::noModification);
ClassSubject mainSubject = inspector.clazz(mainClass);
assertThat(mainSubject, isPresent());
@@ -92,21 +116,23 @@
}
@Test
- public void testNonNullParamAfterInvoke() throws Exception {
- Class mainClass = NonNullParamAfterInvoke.class;
- CodeInspector inspector = buildAndRun(mainClass, ImmutableList.of(
- NeverInline.class,
- IntrinsicsDeputy.class,
- NonNullParamAfterInvoke.NotPinnedClass.class,
- mainClass));
+ public void testNonNullParamAfterInvokeStatic() throws Exception {
+ Class<?> mainClass = NonNullParamAfterInvokeStatic.class;
+ CodeInspector inspector =
+ buildAndRun(
+ mainClass,
+ ImmutableList.of(
+ NeverInline.class, IntrinsicsDeputy.class, NotPinnedClass.class, mainClass),
+ this::noModification);
ClassSubject mainSubject = inspector.clazz(mainClass);
assertThat(mainSubject, isPresent());
- String argTypeName = NonNullParamAfterInvoke.NotPinnedClass.class.getName();
+ String argTypeName = NotPinnedClass.class.getName();
MethodSubject checkViaCall =
mainSubject.method("void", "checkViaCall", ImmutableList.of(argTypeName, argTypeName));
assertThat(checkViaCall, isPresent());
+ assertEquals(0, countActCall(checkViaCall));
assertEquals(2, countPrintCall(checkViaCall));
MethodSubject checkViaIntrinsic =
@@ -122,6 +148,107 @@
assertEquals(0, countThrow(checkAtOneLevelHigher));
}
+ @Test
+ public void testNonNullParamAfterInvokeDirect() throws Exception {
+ Class<?> mainClass = NonNullParamAfterInvokeDirect.class;
+ CodeInspector inspector =
+ buildAndRun(
+ mainClass,
+ ImmutableList.of(
+ NeverInline.class, IntrinsicsDeputy.class, NotPinnedClass.class, mainClass),
+ this::noModification);
+
+ ClassSubject mainSubject = inspector.clazz(mainClass);
+ assertThat(mainSubject, isPresent());
+
+ String argTypeName = NotPinnedClass.class.getName();
+ MethodSubject checkViaCall =
+ mainSubject.method("void", "checkViaCall", ImmutableList.of(argTypeName, argTypeName));
+ assertThat(checkViaCall, isPresent());
+ assertEquals(0, countActCall(checkViaCall));
+ assertEquals(2, countPrintCall(checkViaCall));
+
+ MethodSubject checkViaIntrinsic =
+ mainSubject.method("void", "checkViaIntrinsic", ImmutableList.of(argTypeName));
+ assertThat(checkViaIntrinsic, isPresent());
+ assertEquals(0, countCallToParamNullCheck(checkViaIntrinsic));
+ assertEquals(1, countPrintCall(checkViaIntrinsic));
+
+ MethodSubject checkAtOneLevelHigher =
+ mainSubject.method("void", "checkAtOneLevelHigher", ImmutableList.of(argTypeName));
+ assertThat(checkAtOneLevelHigher, isPresent());
+ assertEquals(1, countPrintCall(checkAtOneLevelHigher));
+ assertEquals(0, countThrow(checkAtOneLevelHigher));
+ }
+
+ @Test
+ public void testNonNullParamAfterInvokeVirtual() throws Exception {
+ Class<?> mainClass = NonNullParamAfterInvokeVirtualMain.class;
+ CodeInspector inspector =
+ buildAndRun(
+ mainClass,
+ ImmutableList.of(
+ NeverInline.class,
+ IntrinsicsDeputy.class,
+ NonNullParamAfterInvokeVirtual.class,
+ NotPinnedClass.class,
+ mainClass),
+ this::noModification);
+
+ ClassSubject mainSubject = inspector.clazz(NonNullParamAfterInvokeVirtual.class);
+ assertThat(mainSubject, isPresent());
+
+ String argTypeName = NotPinnedClass.class.getName();
+ MethodSubject checkViaCall =
+ mainSubject.method("void", "checkViaCall", ImmutableList.of(argTypeName, argTypeName));
+ assertThat(checkViaCall, isPresent());
+ assertEquals(0, countActCall(checkViaCall));
+ assertEquals(2, countPrintCall(checkViaCall));
+
+ MethodSubject checkViaIntrinsic =
+ mainSubject.method("void", "checkViaIntrinsic", ImmutableList.of(argTypeName));
+ assertThat(checkViaIntrinsic, isPresent());
+ assertEquals(0, countCallToParamNullCheck(checkViaIntrinsic));
+ assertEquals(1, countPrintCall(checkViaIntrinsic));
+
+ MethodSubject checkAtOneLevelHigher =
+ mainSubject.method("void", "checkAtOneLevelHigher", ImmutableList.of(argTypeName));
+ assertThat(checkAtOneLevelHigher, isPresent());
+ assertEquals(1, countPrintCall(checkAtOneLevelHigher));
+ assertEquals(0, countThrow(checkAtOneLevelHigher));
+ }
+
+ @Test
+ public void testNonNullParamAfterInvokeInterface() throws Exception {
+ Class<?> mainClass = NonNullParamAfterInvokeInterfaceMain.class;
+ CodeInspector inspector =
+ buildAndRun(
+ mainClass,
+ ImmutableList.of(
+ NeverInline.class,
+ IntrinsicsDeputy.class,
+ NonNullParamInterface.class,
+ NonNullParamInterfaceImpl.class,
+ NonNullParamAfterInvokeInterface.class,
+ NotPinnedClass.class,
+ mainClass),
+ this::disableDevirtualization);
+
+ ClassSubject mainSubject = inspector.clazz(NonNullParamAfterInvokeInterface.class);
+ assertThat(mainSubject, isPresent());
+
+ String argTypeName = NotPinnedClass.class.getName();
+ MethodSubject checkViaCall =
+ mainSubject.method(
+ "void",
+ "checkViaCall",
+ ImmutableList.of(NonNullParamInterface.class.getName(), argTypeName, argTypeName));
+ assertThat(checkViaCall, isPresent());
+ assertEquals(0, countActCall(checkViaCall));
+ // The DEX backend reuses the System.out.println invoke.
+ assertEquals(backend == Backend.CF ? 2 : 1, countPrintCall(checkViaCall));
+ }
+
private long countCallToParamNullCheck(MethodSubject method) {
return countCall(method, IntrinsicsDeputy.class.getSimpleName(), "checkParameterIsNotNull");
}
@@ -130,6 +257,10 @@
return countCall(method, "PrintStream", "print");
}
+ private long countActCall(MethodSubject method) {
+ return countCall(method, NotPinnedClass.class.getSimpleName(), "act");
+ }
+
private long countThrow(MethodSubject method) {
return Streams.stream(method.iterateInstructions(InstructionSubject::isThrow)).count();
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvoke.java b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeDirect.java
similarity index 61%
copy from src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvoke.java
copy to src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeDirect.java
index bac33ad..ae94a6d 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvoke.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeDirect.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// 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.nonnull;
@@ -7,25 +7,15 @@
import com.android.tools.r8.NeverInline;
-public class NonNullParamAfterInvoke {
-
- public static class NotPinnedClass {
- final int field;
- NotPinnedClass(int field) {
- this.field = field;
- }
- void act() {
- System.out.println(field);
- }
- }
+public class NonNullParamAfterInvokeDirect {
@NeverInline
- static int sum(NotPinnedClass arg1, NotPinnedClass arg2) {
+ private int sum(NotPinnedClass arg1, NotPinnedClass arg2) {
return arg1.field + arg2.field;
}
@NeverInline
- static void checkViaCall(NotPinnedClass arg1, NotPinnedClass arg2) {
+ private void checkViaCall(NotPinnedClass arg1, NotPinnedClass arg2) {
// After the call to sum(...), we can know parameters arg1 and arg2 are not null.
if (sum(arg1, arg2) > 0) {
// Hence, inlineable.
@@ -37,14 +27,14 @@
}
@NeverInline
- static void checkViaIntrinsic(NotPinnedClass arg) {
+ private void checkViaIntrinsic(NotPinnedClass arg) {
checkParameterIsNotNull(arg, "arg");
// Parameter arg is not null.
arg.act();
}
@NeverInline
- static void checkAtOneLevelHigher(NotPinnedClass arg) {
+ private void checkAtOneLevelHigher(NotPinnedClass arg) {
checkViaIntrinsic(arg);
// Parameter arg is not null.
arg.act();
@@ -53,9 +43,9 @@
public static void main(String[] args) {
NotPinnedClass arg1 = new NotPinnedClass(1);
NotPinnedClass arg2 = new NotPinnedClass(2);
- checkViaCall(arg1, arg2);
- checkViaIntrinsic(arg1);
- checkAtOneLevelHigher(arg2);
+ NonNullParamAfterInvokeDirect instance = new NonNullParamAfterInvokeDirect();
+ instance.checkViaCall(arg1, arg2);
+ instance.checkViaIntrinsic(arg1);
+ instance.checkAtOneLevelHigher(arg2);
}
-
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeInterface.java b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeInterface.java
new file mode 100644
index 0000000..5da26c3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeInterface.java
@@ -0,0 +1,23 @@
+// 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.nonnull;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+
+@NeverClassInline
+public class NonNullParamAfterInvokeInterface {
+
+ @NeverInline
+ void checkViaCall(NonNullParamInterface receiver, NotPinnedClass arg1, NotPinnedClass arg2) {
+ // After the call to sum(...), we can know parameters arg1 and arg2 are not null.
+ if (receiver.sum(arg1, arg2) > 0) {
+ // Hence, inlineable.
+ arg1.act();
+ } else {
+ // Ditto.
+ arg2.act();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeInterfaceMain.java b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeInterfaceMain.java
new file mode 100644
index 0000000..b2c322c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeInterfaceMain.java
@@ -0,0 +1,15 @@
+// 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.nonnull;
+
+public class NonNullParamAfterInvokeInterfaceMain {
+
+ public static void main(String[] args) {
+ NotPinnedClass arg1 = new NotPinnedClass(1);
+ NotPinnedClass arg2 = new NotPinnedClass(2);
+ NonNullParamAfterInvokeInterface instance = new NonNullParamAfterInvokeInterface();
+ NonNullParamInterfaceImpl receiver = new NonNullParamInterfaceImpl();
+ instance.checkViaCall(receiver, arg1, arg2);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvoke.java b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeStatic.java
similarity index 81%
rename from src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvoke.java
rename to src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeStatic.java
index bac33ad..944c024 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvoke.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeStatic.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// 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.nonnull;
@@ -7,17 +7,7 @@
import com.android.tools.r8.NeverInline;
-public class NonNullParamAfterInvoke {
-
- public static class NotPinnedClass {
- final int field;
- NotPinnedClass(int field) {
- this.field = field;
- }
- void act() {
- System.out.println(field);
- }
- }
+public class NonNullParamAfterInvokeStatic {
@NeverInline
static int sum(NotPinnedClass arg1, NotPinnedClass arg2) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeVirtual.java b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeVirtual.java
new file mode 100644
index 0000000..994c87a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeVirtual.java
@@ -0,0 +1,42 @@
+// 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.nonnull;
+
+import static com.android.tools.r8.ir.optimize.nonnull.IntrinsicsDeputy.checkParameterIsNotNull;
+
+import com.android.tools.r8.NeverInline;
+
+public class NonNullParamAfterInvokeVirtual {
+
+ @NeverInline
+ int sum(NotPinnedClass arg1, NotPinnedClass arg2) {
+ return arg1.field + arg2.field;
+ }
+
+ @NeverInline
+ void checkViaCall(NotPinnedClass arg1, NotPinnedClass arg2) {
+ // After the call to sum(...), we can know parameters arg1 and arg2 are not null.
+ if (sum(arg1, arg2) > 0) {
+ // Hence, inlineable.
+ arg1.act();
+ } else {
+ // Ditto.
+ arg2.act();
+ }
+ }
+
+ @NeverInline
+ void checkViaIntrinsic(NotPinnedClass arg) {
+ checkParameterIsNotNull(arg, "arg");
+ // Parameter arg is not null.
+ arg.act();
+ }
+
+ @NeverInline
+ void checkAtOneLevelHigher(NotPinnedClass arg) {
+ checkViaIntrinsic(arg);
+ // Parameter arg is not null.
+ arg.act();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeVirtualMain.java b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeVirtualMain.java
new file mode 100644
index 0000000..8fac6cb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamAfterInvokeVirtualMain.java
@@ -0,0 +1,16 @@
+// 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.nonnull;
+
+public class NonNullParamAfterInvokeVirtualMain {
+
+ public static void main(String[] args) {
+ NotPinnedClass arg1 = new NotPinnedClass(1);
+ NotPinnedClass arg2 = new NotPinnedClass(2);
+ NonNullParamAfterInvokeVirtual instance = new NonNullParamAfterInvokeVirtual();
+ instance.checkViaCall(arg1, arg2);
+ instance.checkViaIntrinsic(arg1);
+ instance.checkAtOneLevelHigher(arg2);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamInterface.java b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamInterface.java
new file mode 100644
index 0000000..e20992e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamInterface.java
@@ -0,0 +1,11 @@
+// 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.nonnull;
+
+import com.android.tools.r8.NeverMerge;
+
+@NeverMerge
+public interface NonNullParamInterface {
+ int sum(NotPinnedClass arg1, NotPinnedClass arg2);
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamInterfaceImpl.java b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamInterfaceImpl.java
new file mode 100644
index 0000000..4f1dc5f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NonNullParamInterfaceImpl.java
@@ -0,0 +1,13 @@
+// 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.nonnull;
+
+import com.android.tools.r8.NeverInline;
+
+public class NonNullParamInterfaceImpl implements NonNullParamInterface {
+ @NeverInline
+ public int sum(NotPinnedClass arg1, NotPinnedClass arg2) {
+ return arg1.field + arg2.field;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NotPinnedClass.java b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NotPinnedClass.java
new file mode 100644
index 0000000..b9f368d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/nonnull/NotPinnedClass.java
@@ -0,0 +1,16 @@
+// 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.nonnull;
+
+public class NotPinnedClass {
+ final int field;
+
+ NotPinnedClass(int field) {
+ this.field = field;
+ }
+
+ void act() {
+ System.out.println(field);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
index 4229213..9380115 100644
--- a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
+++ b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
@@ -10,9 +10,9 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import com.android.tools.r8.KotlinTestBase;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8Command;
+import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
import com.android.tools.r8.graph.Code;
@@ -24,6 +24,7 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -31,6 +32,7 @@
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -44,7 +46,7 @@
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
-public abstract class AbstractR8KotlinTestBase extends KotlinTestBase {
+public abstract class AbstractR8KotlinTestBase extends TestBase {
// This is the name of the Jasmin-generated class which contains the "main" method which will
// invoke the tested method.
@@ -61,10 +63,6 @@
return buildParameters(BooleanUtils.values(), KotlinTargetVersion.values());
}
- public AbstractR8KotlinTestBase() {
- super(KotlinTargetVersion.JAVA_6);
- }
-
protected void addExtraClasspath(Path path) {
extraClasspath.add(path);
}
@@ -232,8 +230,8 @@
// Build classpath for compilation (and java execution)
classpath.clear();
- classpath.add(getKotlinJarFile(folder, targetVersion));
- classpath.add(getJavaJarFile(folder, targetVersion));
+ classpath.add(getKotlinJarFile(folder));
+ classpath.add(getJavaJarFile(folder));
classpath.addAll(extraClasspath);
// Build with R8
@@ -298,6 +296,16 @@
}
}
+ private Path getKotlinJarFile(String folder) {
+ return Paths.get(ToolHelper.TESTS_BUILD_DIR, "kotlinR8TestResources",
+ targetVersion.getFolderName(), folder + FileUtils.JAR_EXTENSION);
+ }
+
+ private Path getJavaJarFile(String folder) {
+ return Paths.get(ToolHelper.TESTS_BUILD_DIR, "kotlinR8TestResources",
+ targetVersion.getFolderName(), folder + ".java" + FileUtils.JAR_EXTENSION);
+ }
+
@FunctionalInterface
interface AndroidAppInspector {