Fix an infinite loop in CodeRewriter#simplifyArrayConstruction.
Bug: 87341268
Change-Id: Ibccf02e65171eec8c4aa1c513fe0f65f11f23311
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index bd3442c..ae57f48 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -1707,10 +1707,8 @@
return values;
}
}
- block =
- block.exit().isGoto() && !visitedBlocks.contains(block.exit().asGoto().getTarget())
- ? block.exit().asGoto().getTarget()
- : null;
+ BasicBlock nextBlock = block.exit().isGoto() ? block.exit().asGoto().getTarget() : null;
+ block = nextBlock != null && !visitedBlocks.contains(nextBlock) ? nextBlock : null;
it = block != null ? block.listIterator() : null;
} while (it != null);
return null;
@@ -1801,7 +1799,9 @@
// Second pass: remove all the array put instructions for the array for which we have
// inserted a fill array data instruction instead.
if (!storesToRemoveForArray.isEmpty()) {
+ Set<BasicBlock> visitedBlocks = Sets.newIdentityHashSet();
do {
+ visitedBlocks.add(block);
it = block.listIterator();
while (it.hasNext()) {
Instruction instruction = it.next();
@@ -1823,7 +1823,8 @@
}
}
}
- block = block.exit().isGoto() ? block.exit().asGoto().getTarget() : null;
+ BasicBlock nextBlock = block.exit().isGoto() ? block.exit().asGoto().getTarget() : null;
+ block = nextBlock != null && !visitedBlocks.contains(nextBlock) ? nextBlock : null;
} while (block != null);
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/B87341268.java b/src/test/java/com/android/tools/r8/ir/optimize/B87341268.java
new file mode 100644
index 0000000..3f7bcfb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/B87341268.java
@@ -0,0 +1,39 @@
+// Copyright (c) 2018, 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;
+
+import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
+import org.junit.Test;
+
+public class B87341268 extends TestBase {
+ @Test
+ public void test() throws Exception {
+ AndroidApp app = compileWithD8(readClasses(TestClass.class));
+ DexInspector inspector = new DexInspector(app);
+ ClassSubject clazz = inspector.clazz(TestClass.class);
+ assertThat(clazz, isPresent());
+ }
+}
+
+class TestClass {
+ int loop(String arg) {
+ long[] array = { 0L, 1L, 2L };
+ int length = -1;
+ while (true) {
+ try {
+ length = arg.length();
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ break;
+ }
+ }
+ return length;
+ }
+}