Extend remaining outliner tests to R8
Change-Id: I0c2d9733352b65ee200153986c2b3744463dbe44
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
index 8d98060..65a5c1a 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
@@ -17,7 +17,6 @@
import static com.android.tools.r8.ir.code.Opcodes.RETURN;
import static com.android.tools.r8.ir.code.Opcodes.STATIC_PUT;
-import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
@@ -71,24 +70,15 @@
* value must have in order for the program to type check.
*/
public static TypeElement computeUseType(AppView<?> appView, DexType returnType, Value value) {
- if (appView.hasClassHierarchy()) {
- return computeUseType(appView, returnType, value, (s, t) -> s.join(t, appView));
- } else {
- AppView<AppInfo> appViewWithoutClassHierarchy = appView.withoutClassHierarchy();
- AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
- return computeUseType(
- appView,
- returnType,
- value,
- (s, t) -> joinWithoutClassHierarchy(s, t, appViewWithoutClassHierarchy, appInfo));
- }
+ AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
+ return computeUseType(appView, returnType, value, (s, t) -> meet(s, t, appView, appInfo));
}
private static TypeElement computeUseType(
AppView<?> appView,
DexType returnType,
Value value,
- BiFunction<TypeElement, TypeElement, TypeElement> joiner) {
+ BiFunction<TypeElement, TypeElement, TypeElement> meet) {
TypeElement staticType = value.getType();
TypeElement useType = TypeElement.getBottom();
WorkList<UserAndValuePair> users = WorkList.newEqualityWorkList();
@@ -101,9 +91,8 @@
} else {
Instruction instruction = user.asInstruction();
TypeElement instructionUseType =
- computeUseTypeForInstruction(
- appView, returnType, instruction, item.value, joiner, users);
- useType = joiner.apply(useType, instructionUseType);
+ computeUseTypeForInstruction(appView, returnType, instruction, item.value, meet, users);
+ useType = meet.apply(useType, instructionUseType);
if (useType.isTop() || useType.equalUpToNullability(staticType)) {
// Bail-out.
return staticType;
@@ -127,7 +116,7 @@
DexType returnType,
Instruction instruction,
Value value,
- BiFunction<TypeElement, TypeElement, TypeElement> joiner,
+ BiFunction<TypeElement, TypeElement, TypeElement> meet,
WorkList<UserAndValuePair> users) {
switch (instruction.opcode()) {
case ASSUME:
@@ -138,13 +127,13 @@
case INSTANCE_GET:
return computeUseTypeForInstanceGet(appView, instruction.asInstanceGet());
case INSTANCE_PUT:
- return computeUseTypeForInstancePut(appView, instruction.asInstancePut(), value, joiner);
+ return computeUseTypeForInstancePut(appView, instruction.asInstancePut(), value, meet);
case INVOKE_DIRECT:
case INVOKE_INTERFACE:
case INVOKE_STATIC:
case INVOKE_SUPER:
case INVOKE_VIRTUAL:
- return computeUseTypeForInvoke(appView, instruction.asInvokeMethod(), value, joiner);
+ return computeUseTypeForInvoke(appView, instruction.asInvokeMethod(), value, meet);
case RETURN:
return computeUseTypeForReturn(appView, returnType);
case STATIC_PUT:
@@ -170,14 +159,14 @@
AppView<?> appView,
InstancePut instancePut,
Value value,
- BiFunction<TypeElement, TypeElement, TypeElement> joiner) {
+ BiFunction<TypeElement, TypeElement, TypeElement> meet) {
DexField field = instancePut.getField();
TypeElement useType = TypeElement.getBottom();
if (instancePut.object() == value) {
- useType = joiner.apply(useType, field.getHolderType().toTypeElement(appView));
+ useType = meet.apply(useType, field.getHolderType().toTypeElement(appView));
}
if (instancePut.value() == value) {
- useType = joiner.apply(useType, field.getType().toTypeElement(appView));
+ useType = meet.apply(useType, field.getType().toTypeElement(appView));
}
return useType;
}
@@ -186,7 +175,7 @@
AppView<?> appView,
InvokeMethod invoke,
Value value,
- BiFunction<TypeElement, TypeElement, TypeElement> joiner) {
+ BiFunction<TypeElement, TypeElement, TypeElement> meet) {
TypeElement useType = TypeElement.getBottom();
for (int argumentIndex = 0; argumentIndex < invoke.arguments().size(); argumentIndex++) {
Value argument = invoke.getArgument(argumentIndex);
@@ -198,7 +187,7 @@
.getInvokedMethod()
.getArgumentType(argumentIndex, invoke.isInvokeStatic())
.toTypeElement(appView);
- useType = joiner.apply(useType, useTypeForArgument);
+ useType = meet.apply(useType, useTypeForArgument);
}
assert !useType.isBottom();
return useType;
@@ -212,19 +201,24 @@
return staticPut.getField().getType().toTypeElement(appView);
}
- private static TypeElement joinWithoutClassHierarchy(
- TypeElement type,
- TypeElement other,
- AppView<AppInfo> appView,
- AppInfoWithClassHierarchy appInfo) {
- assert !other.isBottom();
+ private static TypeElement meet(
+ TypeElement type, TypeElement other, AppView<?> appView, AppInfoWithClassHierarchy appInfo) {
+ if (other.isBottom()) {
+ return type;
+ }
if (type.isBottom()) {
return other;
}
if (type.isTop() || other.isTop()) {
return TypeElement.getTop();
}
- if (type.equals(other)) {
+ if (type.equalUpToNullability(other)) {
+ if (type.isReferenceType()) {
+ if (!type.nullability().equals(other.nullability())) {
+ return type.asReferenceType()
+ .getOrCreateVariant(type.nullability().meet(other.nullability()));
+ }
+ }
return type;
}
if (type.isPrimitiveType()) {
@@ -242,11 +236,16 @@
DexType classType = type.asClassType().getClassType();
DexType otherClassType = other.asClassType().getClassType();
if (appInfo.isSubtype(classType, otherClassType)) {
- return ClassTypeElement.createForD8(classType, type.nullability().join(other.nullability()));
+ if (type.nullability().equals(other.nullability())) {
+ return type;
+ }
+ return type.asClassType().getOrCreateVariant(type.nullability().meet(other.nullability()));
}
if (appInfo.isSubtype(otherClassType, classType)) {
- return ClassTypeElement.createForD8(
- otherClassType, type.nullability().join(other.nullability()));
+ if (type.nullability().equals(other.nullability())) {
+ return other;
+ }
+ return other.asClassType().getOrCreateVariant(type.nullability().meet(other.nullability()));
}
return TypeElement.getTop();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java
index 004e148..e9de503 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlineMarkerRewriter.java
@@ -75,7 +75,9 @@
appView,
callerPosition,
outline.getProtoChanges(),
- MethodConversionOptions.forD8(appView, method));
+ appView.enableWholeProgramOptimizations()
+ ? MethodConversionOptions.forLirPhase(appView)
+ : MethodConversionOptions.forD8(appView, method));
}
private void finalizeCode(ProgramMethod method, IRCode code) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java
index 0ee7d9b..d07c1e6 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerArrayUseTypeTest.java
@@ -3,22 +3,46 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize.outliner.exceptions;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.KeepUnusedArguments;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.SingleTestRunResult;
+import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
import java.util.Collection;
import org.junit.Test;
public class ThrowBlockOutlinerArrayUseTypeTest extends ThrowBlockOutlinerTestBase {
@Test
- public void test() throws Exception {
- testForD8(parameters)
- .addInnerClasses(getClass())
- .apply(this::configure)
- .compile()
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(
+ testForR8(parameters)
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .enableUnusedArgumentAnnotations());
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
+ TestCompileResult<?, ?> compileResult =
+ testBuilder.addInnerClasses(getClass()).apply(this::configure).compile();
+
+ ClassSubject exceptionClassSubject = compileResult.inspector().clazz(MyException.class);
+ compileResult
.run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatThrows(MyException.class);
+ .assertFailureWithErrorThatMatches(containsString(exceptionClassSubject.getFinalName()));
}
@Override
@@ -46,6 +70,8 @@
static class MyException extends RuntimeException {
+ @KeepUnusedArguments
+ @NeverInline
MyException(String msg, Main[] main) {}
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java
index cd6c533..2badee6 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerConstArgumentTest.java
@@ -10,8 +10,11 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.optimize.outliner.exceptions.ThrowBlockOutlinerArrayUseTypeTest.Main;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -24,9 +27,21 @@
public class ThrowBlockOutlinerConstArgumentTest extends ThrowBlockOutlinerTestBase {
@Test
- public void test() throws Exception {
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(testForR8(parameters).addKeepMainRule(Main.class));
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
TestCompileResult<?, ?> compileResult =
- testForD8(parameters)
+ testBuilder
.addInnerClasses(getClass())
.apply(this::configure)
.compile()
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java
index 3b9a6e4..d0c21e3 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerInterfaceMethodDesugaringTest.java
@@ -6,8 +6,11 @@
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.optimize.outliner.exceptions.ThrowBlockOutlinerArrayUseTypeTest.Main;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.Collection;
import org.junit.Test;
@@ -15,9 +18,21 @@
public class ThrowBlockOutlinerInterfaceMethodDesugaringTest extends ThrowBlockOutlinerTestBase {
@Test
- public void test() throws Exception {
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(testForR8(parameters).addKeepMainRule(Main.class));
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
TestCompileResult<?, ?> compileResult =
- testForD8(parameters)
+ testBuilder
.addProgramClasses(Main.class, A.class)
.addProgramClassFileData(
transformer(I.class)
@@ -25,7 +40,7 @@
.transform())
.apply(this::configure)
.compile()
- .inspect(this::inspectOutput);
+ .inspect(inspector -> inspectOutput(inspector, testBuilder));
compileResult
.run(parameters.getRuntime(), Main.class, "default")
.assertFailureWithErrorThatThrows(RuntimeException.class)
@@ -49,7 +64,12 @@
assertEquals(3, outline.getNumberOfUsers());
}
- private void inspectOutput(CodeInspector inspector) {
+ private void inspectOutput(
+ CodeInspector inspector,
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder) {
+ if (testBuilder.isR8TestBuilder()) {
+ return;
+ }
// Main, I, I$-CC, A and the synthetic outline class.
assertEquals(
parameters.canUseDefaultAndStaticInterfaceMethods() ? 4 : 5, inspector.allClasses().size());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java
index 174b194..cfb6c30 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerNoArgumentsTest.java
@@ -47,6 +47,7 @@
@Test
public void testR8() throws Exception {
+ assumeRelease();
runTest(testForR8(parameters).addKeepMainRule(Main.class));
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java
index bebc31b..51d44e7 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSharedStringBuilderTest.java
@@ -10,9 +10,12 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
+import com.android.tools.r8.ir.optimize.outliner.exceptions.ThrowBlockOutlinerArrayUseTypeTest.Main;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -25,9 +28,21 @@
public class ThrowBlockOutlinerSharedStringBuilderTest extends ThrowBlockOutlinerTestBase {
@Test
- public void test() throws Exception {
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(testForR8(parameters).addKeepMainRule(Main.class));
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
TestCompileResult<?, ?> compileResult =
- testForD8(parameters)
+ testBuilder
.addInnerClasses(getClass())
.apply(this::configure)
.compile()
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java
index f507e28..a3edcff 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerTestBase.java
@@ -5,6 +5,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.SingleTestRunResult;
@@ -49,6 +50,13 @@
assertTrue(receivedCallback.isTrue());
}
+ public void assumeRelease() {
+ if (mode.isDebug()) {
+ receivedCallback.set();
+ }
+ assumeTrue(mode.isRelease());
+ }
+
public void configure(
TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder) {
testBuilder
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java
index d48861d..5a3fcdb 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerUseTypeTest.java
@@ -3,22 +3,46 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize.outliner.exceptions;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.KeepUnusedArguments;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.SingleTestRunResult;
+import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
import java.util.Collection;
import org.junit.Test;
public class ThrowBlockOutlinerUseTypeTest extends ThrowBlockOutlinerTestBase {
@Test
- public void test() throws Exception {
- testForD8(parameters)
- .addInnerClasses(getClass())
- .apply(this::configure)
- .compile()
+ public void testD8() throws Exception {
+ runTest(testForD8(parameters));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeRelease();
+ runTest(
+ testForR8(parameters)
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .enableUnusedArgumentAnnotations());
+ }
+
+ private void runTest(
+ TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> testBuilder)
+ throws Exception {
+ TestCompileResult<?, ?> compileResult =
+ testBuilder.addInnerClasses(getClass()).apply(this::configure).compile();
+
+ ClassSubject exceptionClassSubject = compileResult.inspector().clazz(MyException.class);
+ compileResult
.run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatThrows(MyException.class);
+ .assertFailureWithErrorThatMatches(containsString(exceptionClassSubject.getFinalName()));
}
@Override
@@ -46,6 +70,8 @@
static class MyException extends RuntimeException {
+ @KeepUnusedArguments
+ @NeverInline
MyException(String msg, Main main) {}
}
}