Version 1.0.31 Merge: Fix an infinite loop in CodeRewriter#simplifyArrayConstruction. CL: https://r8-review.googlesource.com/c/r8/+/21880 Bug: 87341268 Change-Id: Ibccf02e65171eec8c4aa1c513fe0f65f11f23311
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java index fb1837e..5c7bd78 100644 --- a/src/main/java/com/android/tools/r8/Version.java +++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@ // This field is accessed from release scripts using simple pattern matching. // Therefore, changing this field could break our release scripts. - public static final String LABEL = "v1.0.30"; + public static final String LABEL = "v1.0.31"; private Version() { }
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 61cd3e7..4d745b4 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
@@ -1376,10 +1376,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; @@ -1470,7 +1468,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(); @@ -1492,7 +1492,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..f197f46 --- /dev/null +++ b/src/test/java/com/android/tools/r8/ir/optimize/B87341268.java
@@ -0,0 +1,38 @@ +// 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 org.junit.Assert.assertTrue; + +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); + assertTrue(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; + } +}