Harden assertion configuration analysis to allow input stack maps
Change-Id: I871a48c1474cd083e5939f080a1ca55affe92efe
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
index 72f5be9..f1058d6 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
@@ -76,6 +76,16 @@
private FrameType() {}
}
+ @Override
+ public boolean isFrame() {
+ return true;
+ }
+
+ @Override
+ public CfFrame asFrame() {
+ return this;
+ }
+
private static class InitializedType extends FrameType {
private final DexType type;
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
index 05f1181..041409b 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
@@ -87,6 +87,14 @@
return false;
}
+ public CfFrame asFrame() {
+ return null;
+ }
+
+ public boolean isFrame() {
+ return false;
+ }
+
public CfPosition asPosition() {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java
index 6b03d33..c57a3da 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java
@@ -167,8 +167,8 @@
i < code.instructions.size() && nextExpectedInstructionIndex < sequence.size();
i++) {
instruction = code.instructions.get(i);
- if (instruction.isLabel()) {
- // Just ignore labels.
+ if (instruction.isLabel() || instruction.isFrame()) {
+ // Just ignore labels and frames.
continue;
}
if (instruction.getClass() != sequence.get(nextExpectedInstructionIndex)) {
diff --git a/src/test/java/com/android/tools/r8/TestBuilder.java b/src/test/java/com/android/tools/r8/TestBuilder.java
index e9ac10d..21ab2b1 100644
--- a/src/test/java/com/android/tools/r8/TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestBuilder.java
@@ -12,7 +12,6 @@
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutionException;
-import java.util.function.Consumer;
public abstract class TestBuilder<RR extends TestRunResult, T extends TestBuilder<RR, T>> {
@@ -39,10 +38,21 @@
return self();
}
- public T ifTrue(boolean value, Consumer<T> consumer) {
+ public T applyIf(boolean value, ThrowableConsumer<T> consumer) {
T self = self();
if (value) {
- consumer.accept(self);
+ consumer.acceptWithRuntimeException(self);
+ }
+ return self;
+ }
+
+ public T applyIf(
+ boolean value, ThrowableConsumer<T> trueConsumer, ThrowableConsumer<T> falseConsumer) {
+ T self = self();
+ if (value) {
+ trueConsumer.acceptWithRuntimeException(self);
+ } else {
+ falseConsumer.acceptWithRuntimeException(self);
}
return self;
}
diff --git a/src/test/java/com/android/tools/r8/code/PassThroughTest.java b/src/test/java/com/android/tools/r8/code/PassThroughTest.java
index 30b8b6e..673f3a2 100644
--- a/src/test/java/com/android/tools/r8/code/PassThroughTest.java
+++ b/src/test/java/com/android/tools/r8/code/PassThroughTest.java
@@ -69,7 +69,7 @@
.addProgramClasses(Main.class)
.addKeepAllClassesRule()
.enableInliningAnnotations()
- .ifTrue(keepDebug, TestShrinkerBuilder::addKeepAllAttributes)
+ .applyIf(keepDebug, TestShrinkerBuilder::addKeepAllAttributes)
.compile()
.writeToZip(outputJar)
.run(parameters.getRuntime(), Main.class)
@@ -86,7 +86,7 @@
.addProgramClasses(Main.class)
.addKeepAllClassesRule()
.enableInliningAnnotations()
- .ifTrue(keepDebug, TestShrinkerBuilder::addKeepAllAttributes)
+ .applyIf(keepDebug, TestShrinkerBuilder::addKeepAllAttributes)
.addOptionsModification(
internalOptions -> {
internalOptions.testing.cfByteCodePassThrough =
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteKeepPathTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteKeepPathTest.java
index b8c4186..600ff8e 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteKeepPathTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteKeepPathTest.java
@@ -67,7 +67,7 @@
.addProgramFiles(libJars.get(targetVersion))
.addProgramFiles(ToolHelper.getKotlinStdlibJar())
.addKeepRules("-keep class " + LIB_CLASS_NAME)
- .ifTrue(keepMetadata, TestShrinkerBuilder::addKeepKotlinMetadata)
+ .applyIf(keepMetadata, TestShrinkerBuilder::addKeepKotlinMetadata)
.addKeepRuntimeVisibleAnnotations()
.allowDiagnosticWarningMessages()
.compile()
@@ -81,7 +81,7 @@
.addProgramFiles(libJars.get(targetVersion))
.addClasspathFiles(ToolHelper.getKotlinStdlibJar())
.addKeepRules("-keep class " + LIB_CLASS_NAME)
- .ifTrue(keepMetadata, TestShrinkerBuilder::addKeepKotlinMetadata)
+ .applyIf(keepMetadata, TestShrinkerBuilder::addKeepKotlinMetadata)
.addKeepRuntimeVisibleAnnotations()
.compile()
.inspect(inspector -> inspect(inspector, keepMetadata));
@@ -94,7 +94,7 @@
.addLibraryFiles(ToolHelper.getKotlinStdlibJar())
.addLibraryFiles(ToolHelper.getJava8RuntimeJar())
.addKeepRules("-keep class " + LIB_CLASS_NAME)
- .ifTrue(keepMetadata, TestShrinkerBuilder::addKeepKotlinMetadata)
+ .applyIf(keepMetadata, TestShrinkerBuilder::addKeepKotlinMetadata)
.addKeepRuntimeVisibleAnnotations()
.compile()
.inspect(inspector -> inspect(inspector, keepMetadata));
diff --git a/src/test/java/com/android/tools/r8/naming/DontUseMixedCaseClassNamesExistingClassTest.java b/src/test/java/com/android/tools/r8/naming/DontUseMixedCaseClassNamesExistingClassTest.java
index b16347d..6804b54 100644
--- a/src/test/java/com/android/tools/r8/naming/DontUseMixedCaseClassNamesExistingClassTest.java
+++ b/src/test/java/com/android/tools/r8/naming/DontUseMixedCaseClassNamesExistingClassTest.java
@@ -51,7 +51,7 @@
.addKeepClassRulesWithAllowObfuscation(A.class)
.addKeepMainRule(Main.class)
.addKeepRules("-classobfuscationdictionary " + dictionary.toString())
- .ifTrue(dontUseMixedCase, b -> b.addKeepRules("-dontusemixedcaseclassnames"))
+ .applyIf(dontUseMixedCase, b -> b.addKeepRules("-dontusemixedcaseclassnames"))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines(EXPECTED)
.inspect(
diff --git a/src/test/java/com/android/tools/r8/naming/b155249069/DontUseMixedCaseClassNamesExistingClassPackageTest.java b/src/test/java/com/android/tools/r8/naming/b155249069/DontUseMixedCaseClassNamesExistingClassPackageTest.java
index a55ef4b..f662aa6 100644
--- a/src/test/java/com/android/tools/r8/naming/b155249069/DontUseMixedCaseClassNamesExistingClassPackageTest.java
+++ b/src/test/java/com/android/tools/r8/naming/b155249069/DontUseMixedCaseClassNamesExistingClassPackageTest.java
@@ -54,7 +54,7 @@
.addKeepClassRulesWithAllowObfuscation(A.class)
.addKeepMainRule(Main.class)
.addKeepRules("-packageobfuscationdictionary " + packageDictionary.toString())
- .ifTrue(dontUseMixedCase, b -> b.addKeepRules("-dontusemixedcaseclassnames"))
+ .applyIf(dontUseMixedCase, b -> b.addKeepRules("-dontusemixedcaseclassnames"))
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("A.A.foo()", "package_b.B.foo()")
.inspect(
diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationKotlinTest.java b/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationKotlinTest.java
index 873788c..a0049f4 100644
--- a/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationKotlinTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/assertions/AssertionConfigurationKotlinTest.java
@@ -183,38 +183,27 @@
boolean enableJvmAssertions)
throws Exception {
- if (kotlinStdlibAsLibrary) {
- testForR8(parameters.getBackend())
- .addClasspathFiles(ToolHelper.getKotlinStdlibJar())
- .addProgramFiles(kotlinClasses.get(kotlinCompilationKey))
- .addKeepMainRule(testClassKt)
- .addKeepClassAndMembersRules(class1, class2)
- .setMinApi(parameters.getApiLevel())
- .apply(builderConsumer)
- .noMinification()
- .addRunClasspathFiles(kotlinStdlibLibraryForRuntime())
- .compile()
- .enableRuntimeAssertions(enableJvmAssertions)
- .run(parameters.getRuntime(), testClassKt)
- .inspect(inspector)
- .assertSuccessWithOutputLines(outputLines);
- } else {
- testForR8(parameters.getBackend())
- .addProgramFiles(ToolHelper.getKotlinStdlibJar())
- .addProgramFiles(kotlinClasses.get(kotlinCompilationKey))
- .addKeepMainRule(testClassKt)
- .addKeepClassAndMembersRules(class1, class2)
- .setMinApi(parameters.getApiLevel())
- .apply(builderConsumer)
- .noMinification()
- .allowDiagnosticWarningMessages()
- .compile()
- .assertAllWarningMessagesMatch(equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
- .enableRuntimeAssertions(enableJvmAssertions)
- .run(parameters.getRuntime(), testClassKt)
- .inspect(inspector)
- .assertSuccessWithOutputLines(outputLines);
- }
+ testForR8(parameters.getBackend())
+ .applyIf(
+ kotlinStdlibAsLibrary,
+ b -> {
+ b.addClasspathFiles(ToolHelper.getKotlinStdlibJar());
+ b.addRunClasspathFiles(kotlinStdlibLibraryForRuntime());
+ },
+ b -> b.addProgramFiles(ToolHelper.getKotlinStdlibJar()))
+ .addProgramFiles(kotlinClasses.get(kotlinCompilationKey))
+ .addKeepMainRule(testClassKt)
+ .addKeepClassAndMembersRules(class1, class2)
+ .setMinApi(parameters.getApiLevel())
+ .apply(builderConsumer)
+ .allowDiagnosticWarningMessages(!kotlinStdlibAsLibrary)
+ .addRunClasspathFiles(kotlinStdlibLibraryForRuntime())
+ .compile()
+ .assertAllWarningMessagesMatch(equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
+ .enableRuntimeAssertions(enableJvmAssertions)
+ .run(parameters.getRuntime(), testClassKt)
+ .inspect(inspector)
+ .assertSuccessWithOutputLines(outputLines);
}
private List<String> allAssertionsExpectedLines() {
@@ -484,7 +473,30 @@
}
@Test
- public void testAssertionsForCf() throws Exception {
+ public void testAssertionsForCfEnableWithStackMap() throws Exception {
+ Assume.assumeTrue(parameters.isCfRuntime());
+ Assume.assumeTrue(useJvmAssertions);
+ Assume.assumeTrue(kotlinCompilationKey.targetVersion == KotlinTargetVersion.JAVA_8);
+ // Compile time enabling or disabling assertions means the -ea flag has no effect.
+ runR8Test(
+ builder -> {
+ builder.addAssertionsConfiguration(AssertionsConfiguration.Builder::enableAllAssertions);
+ builder.addOptionsModification(options -> options.testing.readInputStackMaps = true);
+ },
+ inspector -> checkAssertionCodeEnabled(inspector, true),
+ allAssertionsExpectedLines());
+ runR8Test(
+ builder -> {
+ builder.addAssertionsConfiguration(AssertionsConfiguration.Builder::enableAllAssertions);
+ builder.addOptionsModification(options -> options.testing.readInputStackMaps = true);
+ },
+ inspector -> checkAssertionCodeEnabled(inspector, true),
+ allAssertionsExpectedLines(),
+ true);
+ }
+
+ @Test
+ public void testAssertionsForCfPassThrough() throws Exception {
Assume.assumeTrue(parameters.isCfRuntime());
// Leaving assertion code means assertions are controlled by the -ea flag.
runR8Test(
@@ -500,6 +512,11 @@
inspector -> checkAssertionCodeLeft(inspector, true),
allAssertionsExpectedLines(),
true);
+ }
+
+ @Test
+ public void testAssertionsForCfEnable() throws Exception {
+ Assume.assumeTrue(parameters.isCfRuntime());
// Compile time enabling or disabling assertions means the -ea flag has no effect.
runR8Test(
builder ->
@@ -514,6 +531,11 @@
inspector -> checkAssertionCodeEnabled(inspector, true),
allAssertionsExpectedLines(),
true);
+ }
+
+ @Test
+ public void testAssertionsForCfDisable() throws Exception {
+ Assume.assumeTrue(parameters.isCfRuntime());
runR8Test(
builder ->
builder.addAssertionsConfiguration(