ART: Add regression test for obsolete crash.
Add a regression test for a `StringBuilderAppend` pattern
recognition crash in debug mode that we had while we were
inlining the `StringBuilder` constructor. As we no longer
inline this constructor, we do not encounter the bug.
Test: testrunner.py --target -t 639-checker-code-sinking
Test: Repeat on an older tree to see the crash - before
https://android-review.googlesource.com/2230607 .
Bug: 252799691
Change-Id: I8eaf9294f8b90fe7cedbe79ffd99394f79d43943
diff --git a/test/639-checker-code-sinking/src/Main.java b/test/639-checker-code-sinking/src/Main.java
index 5e465f2..27df41f 100644
--- a/test/639-checker-code-sinking/src/Main.java
+++ b/test/639-checker-code-sinking/src/Main.java
@@ -27,6 +27,7 @@
testPhiInput();
testVolatileStore();
testCatchBlock();
+ $noinline$testTwoThrowingPathsAndStringBuilderAppend();
doThrow = true;
try {
testInstanceSideEffects();
@@ -687,12 +688,65 @@
return x;
}
+ private static void $noinline$testTwoThrowingPathsAndStringBuilderAppend() {
+ try {
+ $noinline$twoThrowingPathsAndStringBuilderAppend(null);
+ throw new Error("Unreachable");
+ } catch (Error expected) {
+ assertEquals("Object is null", expected.getMessage());
+ }
+ try {
+ $noinline$twoThrowingPathsAndStringBuilderAppend(new Object());
+ throw new Error("Unreachable");
+ } catch (Error expected) {
+ assertEquals("s1s2", expected.getMessage());
+ }
+ }
+
+ // We currently do not inline the `StringBuilder` constructor.
+ // When we did, the `StringBuilderAppend` pattern recognition was looking for
+ // the inlined `NewArray` (and its associated `LoadClass`) and checked in
+ // debug build that the `StringBuilder` has an environment use from this
+ // `NewArray` (and maybe from `LoadClass`). However, code sinking was pruning
+ // the environment of the `NewArray`, leading to a crash when compiling the
+ // code below on the device (we do not inline `core-oj` on host). b/252799691
+ private static void $noinline$twoThrowingPathsAndStringBuilderAppend(Object o) {
+ String s1 = "s1";
+ String s2 = "s2";
+ StringBuilder sb = new StringBuilder();
+
+ // Before inlining, the environment use from this invoke prevents the
+ // `StringBuilderAppend` pattern recognition. After inlining, we end up
+ // with two paths ending with a `Throw` and we could sink the `sb`
+ // instructions from above down to those below, enabling the
+ // `StringBuilderAppend` pattern recognition.
+ // (But that does not happen when the `StringBuilder` constructor is
+ // not inlined, see above.)
+ $inline$requireNonNull(o);
+
+ String s1s2 = sb.append(s1).append(s2).toString();
+ sb = null;
+ throw new Error(s1s2);
+ }
+
+ private static void $inline$requireNonNull(Object o) {
+ if (o == null) {
+ throw new Error("Object is null");
+ }
+ }
+
private static void assertEquals(int expected, int actual) {
if (expected != actual) {
throw new AssertionError("Expected: " + expected + ", Actual: " + actual);
}
}
+ private static void assertEquals(String expected, String actual) {
+ if (!expected.equals(actual)) {
+ throw new AssertionError("Expected: " + expected + ", Actual: " + actual);
+ }
+ }
+
volatile int volatileField;
int intField;
int intField2;