Merge "Test for "R8/CF does not merge identical catch handlers""
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 68d87c1..0a4416a 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -793,12 +793,22 @@
}
public static R8Command.Builder prepareR8CommandBuilder(AndroidApp app) {
- return R8Command.builder(app).setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+ return prepareR8CommandBuilder(app, DexIndexedConsumer.emptyConsumer());
+ }
+
+ public static R8Command.Builder prepareR8CommandBuilder(
+ AndroidApp app, ProgramConsumer programConsumer) {
+ return R8Command.builder(app).setProgramConsumer(programConsumer);
}
public static AndroidApp runR8(AndroidApp app) throws IOException {
+ return runR8WithProgramConsumer(app, DexIndexedConsumer.emptyConsumer());
+ }
+
+ public static AndroidApp runR8WithProgramConsumer(AndroidApp app, ProgramConsumer programConsumer)
+ throws IOException {
try {
- return runR8(prepareR8CommandBuilder(app).build());
+ return runR8(prepareR8CommandBuilder(app, programConsumer).build());
} catch (CompilationFailedException e) {
throw new RuntimeException(e);
}
diff --git a/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java b/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java
new file mode 100644
index 0000000..fd696bc
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java
@@ -0,0 +1,88 @@
+// 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.cf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.cf.code.CfLabel;
+import com.android.tools.r8.cf.code.CfTryCatch;
+import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.Code;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexCode;
+import com.android.tools.r8.graph.DexCode.Try;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.DexInspector;
+import com.google.common.collect.Sets;
+import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
+import it.unimi.dsi.fastutil.ints.IntSet;
+import java.nio.file.Paths;
+import java.util.Set;
+import org.junit.Test;
+
+public class IdenticalCatchHandlerTest extends TestBase {
+
+ private static class TestClass {
+ public void foo(Object a, Object b, Object c) {
+ if (a == null) {
+ try {
+ System.out.println(b.toString());
+ } catch (RuntimeException e) {
+ }
+ } else {
+ try {
+ System.out.println(c.toString());
+ } catch (RuntimeException e) {
+ }
+ }
+ System.out.println("Hello");
+ }
+ }
+
+ @Test
+ public void test() throws Exception {
+ byte[] inputBytes = ToolHelper.getClassAsBytes(TestClass.class);
+ AndroidApp inputApp =
+ AndroidApp.builder()
+ .addClassProgramData(inputBytes, Origin.unknown())
+ .addLibraryFiles(Paths.get(ToolHelper.JAVA_8_RUNTIME))
+ .build();
+ assertEquals(2, countCatchHandlers(inputApp));
+ AndroidApp outputDexApp = ToolHelper.runR8(inputApp);
+ assertEquals(1, countCatchHandlers(outputDexApp));
+ AndroidApp outputCfApp =
+ ToolHelper.runR8WithProgramConsumer(inputApp, ClassFileConsumer.emptyConsumer());
+ // TODO(b/80514966): Change to assertEquals when fixed.
+ assertNotEquals(1, countCatchHandlers(outputCfApp));
+ }
+
+ private int countCatchHandlers(AndroidApp inputApp) throws Exception {
+ DexInspector inspector = new DexInspector(inputApp, o -> o.enableCfFrontend = true);
+ DexClass dexClass = inspector.clazz(TestClass.class).getDexClass();
+ Code code = dexClass.virtualMethods()[0].getCode();
+ if (code.isCfCode()) {
+ CfCode cfCode = code.asCfCode();
+ Set<CfLabel> targets = Sets.newIdentityHashSet();
+ for (CfTryCatch tryCatch : cfCode.getTryCatchRanges()) {
+ targets.addAll(tryCatch.targets);
+ }
+ return targets.size();
+ } else if (code.isDexCode()) {
+ DexCode dexCode = code.asDexCode();
+ IntSet targets = new IntOpenHashSet();
+ for (Try aTry : dexCode.tries) {
+ targets.add(aTry.handlerOffset);
+ }
+ return targets.size();
+ } else {
+ throw new Unimplemented(code.getClass().getName());
+ }
+ }
+}