Rename merged exception classes in DeadCodeRemover
This CL renames the guards in catch handlers in the DeadCodeRemover, and removes catch handlers that are clearly not needed after renaming.
Example:
try { ... }
catch (ExceptionB e) { ... }
catch (ExceptionA e) {
// If ExceptionA gets merged into ExceptionB, then this handler is clearly dead
...
}
Bug: 73958515
Change-Id: I85613f28ee45fe1f6edad2644252fb3ba14a747a
diff --git a/src/test/examples/classmerging/ExceptionTest.java b/src/test/examples/classmerging/ExceptionTest.java
index b365b2a..28442f3 100644
--- a/src/test/examples/classmerging/ExceptionTest.java
+++ b/src/test/examples/classmerging/ExceptionTest.java
@@ -8,12 +8,27 @@
public static void main(String[] args) {
// The following will lead to a catch handler for ExceptionA, which is merged into ExceptionB.
try {
- throw new ExceptionB("Ouch!");
+ doSomethingThatMightThrowExceptionB();
+ doSomethingThatMightThrowException2();
+ } catch (ExceptionB exception) {
+ System.out.println("Caught exception: " + exception.getMessage());
} catch (ExceptionA exception) {
System.out.println("Caught exception: " + exception.getMessage());
+ } catch (Exception2 exception) {
+ System.out.println("Caught exception: " + exception.getMessage());
+ } catch (Exception1 exception) {
+ System.out.println("Caught exception: " + exception.getMessage());
}
}
+ private static void doSomethingThatMightThrowExceptionB() throws ExceptionB {
+ throw new ExceptionB("Ouch!");
+ }
+
+ private static void doSomethingThatMightThrowException2() throws Exception2 {
+ throw new Exception2("Ouch!");
+ }
+
// Will be merged into ExceptionB when class merging is enabled.
public static class ExceptionA extends Exception {
public ExceptionA(String message) {
@@ -26,4 +41,16 @@
super(message);
}
}
+
+ public static class Exception1 extends Exception {
+ public Exception1(String message) {
+ super(message);
+ }
+ }
+
+ public static class Exception2 extends Exception1 {
+ public Exception2(String message) {
+ super(message);
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
index 69f925c..d2643cb 100644
--- a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
@@ -3,8 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.classmerging;
+import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -12,9 +14,14 @@
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.code.Instruction;
+import com.android.tools.r8.code.MoveException;
+import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
import com.android.tools.r8.utils.DexInspector.FoundClassSubject;
+import com.android.tools.r8.utils.DexInspector.MethodSubject;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -110,14 +117,36 @@
new Path[] {
CF_DIR.resolve("ExceptionTest.class"),
CF_DIR.resolve("ExceptionTest$ExceptionA.class"),
- CF_DIR.resolve("ExceptionTest$ExceptionB.class")
+ CF_DIR.resolve("ExceptionTest$ExceptionB.class"),
+ CF_DIR.resolve("ExceptionTest$Exception1.class"),
+ CF_DIR.resolve("ExceptionTest$Exception2.class")
};
Set<String> preservedClassNames =
- ImmutableSet.of("classmerging.ExceptionTest", "classmerging.ExceptionTest$ExceptionB");
- runTest(main, programFiles, preservedClassNames);
+ ImmutableSet.of(
+ "classmerging.ExceptionTest",
+ "classmerging.ExceptionTest$ExceptionB",
+ "classmerging.ExceptionTest$Exception2");
+ DexInspector inspector = runTest(main, programFiles, preservedClassNames);
+
+ ClassSubject mainClass = inspector.clazz(main);
+ assertThat(mainClass, isPresent());
+
+ MethodSubject mainMethod =
+ mainClass.method("void", "main", ImmutableList.of("java.lang.String[]"));
+ assertThat(mainMethod, isPresent());
+
+ // Check that the second catch handler has been removed.
+ DexCode code = mainMethod.getMethod().getCode().asDexCode();
+ int numberOfMoveExceptionInstructions = 0;
+ for (Instruction instruction : code.instructions) {
+ if (instruction instanceof MoveException) {
+ numberOfMoveExceptionInstructions++;
+ }
+ }
+ assertEquals(2, numberOfMoveExceptionInstructions);
}
- private void runTest(String main, Path[] programFiles, Set<String> preservedClassNames)
+ private DexInspector runTest(String main, Path[] programFiles, Set<String> preservedClassNames)
throws Exception {
AndroidApp input = readProgramFiles(programFiles);
AndroidApp output = compileWithR8(input, EXAMPLE_KEEP, this::configure);
@@ -135,5 +164,6 @@
}
// Check that the R8-generated code produces the same result as D8-generated code.
assertEquals(runOnArt(compileWithD8(input), main), runOnArt(output, main));
+ return inspector;
}
}
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index d6e3612..4214a67 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -38,7 +38,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DirectMappedDexApplication;
-import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.code.CatchHandlers;
@@ -653,7 +652,7 @@
code);
IRCode ir = code.buildIR(method, null, options, Origin.unknown());
RegisterAllocator allocator = new LinearScanRegisterAllocator(ir, options);
- method.setCode(ir, GraphLense.getIdentityLense(), allocator, options);
+ method.setCode(ir, allocator, options);
directMethods[i] = method;
}
builder.addProgramClass(