Test limiting exception range before throwing instruction
Bug: 122445224
Change-Id: I1c841a41efef5142ab87ef8ff8b93fe66fea3151
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index 6e5e5d7..4dcc839 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -149,7 +149,9 @@
computeInitializers();
typeVerificationHelper = new TypeVerificationHelper(code, factory, appInfo);
typeVerificationHelper.computeVerificationTypes();
- splitExceptionalBlocks();
+ if (!options.testing.noSplittingExceptionalEdges) {
+ splitExceptionalBlocks();
+ }
rewriter.converter.deadCodeRemover.run(code);
rewriteNots();
LoadStoreHelper loadStoreHelper = new LoadStoreHelper(code, typeVerificationHelper, appInfo);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index e96acfb..b1ea3f9 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -879,6 +879,10 @@
printC1VisualizerHeader(method);
String previous = printMethod(code, "Initial IR (SSA)", null);
+ if (options.testing.irModifier != null) {
+ options.testing.irModifier.accept(code);
+ }
+
if (options.canHaveArtStringNewInitBug()) {
CodeRewriter.ensureDirectStringNewToInit(code);
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 4921c79..f34e059 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -19,6 +19,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.optimize.Inliner;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.ProguardConfiguration;
@@ -532,6 +533,8 @@
public boolean noLocalsTableOnInput = false;
public boolean forceNameReflectionOptimization = false;
public boolean disallowLoadStoreOptimization = false;
+ public Consumer<IRCode> irModifier = null;
+ public boolean noSplittingExceptionalEdges = false;
}
private boolean hasMinApi(AndroidApiLevel level) {
diff --git a/src/test/java/com/android/tools/r8/cf/TryRangeTestLimitRange.java b/src/test/java/com/android/tools/r8/cf/TryRangeTestLimitRange.java
new file mode 100644
index 0000000..5e97ab0
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/TryRangeTestLimitRange.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2019, 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.cf;
+
+import com.android.tools.r8.NeverInline;
+
+public class TryRangeTestLimitRange {
+
+ @NeverInline
+ public static float doSomething(int x) throws Exception {
+ if (x == 42) {
+ throw new Exception("is 42");
+ } else {
+ return 1;
+ }
+ }
+
+ public static void main(String[] args) {
+ int x = args.length;
+ int y = x + 1;
+ try {
+ doSomething(y);
+ } catch (Exception ex) {
+ System.out.println(x + ": " + y);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java b/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java
index 98542ff..e4c7098 100644
--- a/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java
+++ b/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java
@@ -4,8 +4,14 @@
package com.android.tools.r8.cf;
+import static org.junit.Assert.assertTrue;
+
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ir.code.BasicBlock;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Instruction;
+import java.util.ListIterator;
import org.junit.Test;
/**
@@ -18,7 +24,7 @@
public class TryRangeTestRunner extends TestBase {
@Test
- public void test() throws Exception {
+ public void testRegisterAllocationLimitTrailingRange() throws Exception {
testForR8(Backend.CF)
.addProgramClasses(TryRangeTest.class)
.addKeepMainRule(TryRangeTest.class)
@@ -26,8 +32,55 @@
.minification(false)
.noTreeShaking()
.enableInliningAnnotations()
- .addOptionsModification(o -> o.testing.disallowLoadStoreOptimization = true)
+ .addOptionsModification(
+ o -> {
+ o.testing.disallowLoadStoreOptimization = true;
+ })
.run(TryRangeTest.class)
.assertSuccess();
}
+
+ @Test
+ public void testRegisterAllocationLimitLeadingRange() throws Exception {
+ testForR8(Backend.CF)
+ .addProgramClasses(TryRangeTestLimitRange.class)
+ .addKeepMainRule(TryRangeTestLimitRange.class)
+ .setMode(CompilationMode.RELEASE)
+ .minification(false)
+ .noTreeShaking()
+ .enableInliningAnnotations()
+ .addOptionsModification(
+ o -> {
+ o.testing.disallowLoadStoreOptimization = true;
+ o.testing.irModifier = this::processIR;
+ // TODO(mkroghj) Remove this option entirely when splittingExceptionalEdges is moved.
+ o.testing.noSplittingExceptionalEdges = true;
+ })
+ .run(TryRangeTestLimitRange.class)
+ .assertFailure();
+ }
+
+ private void processIR(IRCode code) {
+ if (!code.method.qualifiedName().equals(TryRangeTestLimitRange.class.getName() + ".main")) {
+ return;
+ }
+ BasicBlock entryBlock = code.blocks.get(0);
+ BasicBlock tryBlock = code.blocks.get(1);
+ assertTrue(tryBlock.hasCatchHandlers());
+ ListIterator<Instruction> it = entryBlock.getInstructions().listIterator();
+ Instruction constNumber = it.next();
+ while (!constNumber.isConstNumber()) {
+ constNumber = it.next();
+ }
+ it.remove();
+ Instruction add = it.next();
+ while (!add.isAdd()) {
+ add = it.next();
+ }
+ it.remove();
+ constNumber.setBlock(tryBlock);
+ add.setBlock(tryBlock);
+ tryBlock.getInstructions().add(0, add);
+ tryBlock.getInstructions().add(0, constNumber);
+ }
}