Make ThrowCatchOptimizer a CodeRewriterPass
Bug: b/284304606
Change-Id: I231eb42accbb2310b3eec0bd6c096d0b54117b74
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 8941176..327c74c 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
@@ -760,9 +760,7 @@
new StringBuilderAppendOptimizer(appView).run(code, timing);
}
new SparseConditionalConstantPropagation(appView, code).run(code, timing);
- timing.begin("Rewrite always throwing instructions");
- new ThrowCatchOptimizer(appView).optimizeAlwaysThrowingInstructions(code);
- timing.end();
+ new ThrowCatchOptimizer(appView, isDebugMode).run(code, timing);
timing.begin("Simplify control flow");
if (new BranchSimplifier(appView).simplifyBranches(code)) {
new TrivialCheckCastAndInstanceOfRemover(appView)
@@ -788,13 +786,6 @@
invertConditionalsForTesting(code);
}
- if (!isDebugMode) {
- timing.begin("Rewrite throw NPE");
- new ThrowCatchOptimizer(appView).rewriteThrowNullPointerException(code);
- timing.end();
- previous = printMethod(code, "IR after rewrite throw null (SSA)", previous);
- }
-
timing.begin("Optimize class initializers");
ClassInitializerDefaultsResult classInitializerDefaultsResult =
classInitializerDefaultsOptimization.optimize(code, feedback);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/ThrowCatchOptimizer.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/ThrowCatchOptimizer.java
index f34a6bd..f5a6841 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/ThrowCatchOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/ThrowCatchOptimizer.java
@@ -5,10 +5,10 @@
package com.android.tools.r8.ir.conversion.passes;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClassAndMethod;
-import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
@@ -32,6 +32,7 @@
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Throw;
import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.ir.conversion.passes.result.CodeRewriterResult;
import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
@@ -40,18 +41,41 @@
import java.util.ListIterator;
import java.util.Set;
-public class ThrowCatchOptimizer {
+public class ThrowCatchOptimizer extends CodeRewriterPass<AppInfo> {
- private final AppView<?> appView;
- private final DexItemFactory dexItemFactory;
+ private final boolean rewriteThrowNull;
+
+ public ThrowCatchOptimizer(AppView<?> appView, boolean isDebug) {
+ super(appView);
+ this.rewriteThrowNull = !isDebug;
+ }
public ThrowCatchOptimizer(AppView<?> appView) {
- this.appView = appView;
- this.dexItemFactory = appView.dexItemFactory();
+ super(appView);
+ this.rewriteThrowNull = false;
+ }
+
+ @Override
+ protected String getTimingId() {
+ return "ThrowCatchOptimizer";
+ }
+
+ @Override
+ protected boolean shouldRewriteCode(IRCode code) {
+ return true;
+ }
+
+ @Override
+ protected CodeRewriterResult rewriteCode(IRCode code) {
+ optimizeAlwaysThrowingInstructions(code);
+ if (rewriteThrowNull) {
+ rewriteThrowNullPointerException(code);
+ }
+ return CodeRewriterResult.NONE;
}
// Rewrite 'throw new NullPointerException()' to 'throw null'.
- public void rewriteThrowNullPointerException(IRCode code) {
+ private void rewriteThrowNullPointerException(IRCode code) {
boolean shouldRemoveUnreachableBlocks = false;
for (BasicBlock block : code.blocks) {
InstructionListIterator it = block.listIterator(code);
@@ -64,7 +88,7 @@
if (appView
.dexItemFactory()
.objectsMethods
- .isRequireNonNullMethod(code.method().getReference())) {
+ .isRequireNonNullMethod(code.context().getReference())) {
continue;
}
@@ -192,7 +216,7 @@
// Find all instructions that always throw, split the block after each such instruction and follow
// it with a block throwing a null value (which should result in NPE). Note that this throw is not
// expected to be ever reached, but is intended to satisfy verifier.
- public void optimizeAlwaysThrowingInstructions(IRCode code) {
+ private void optimizeAlwaysThrowingInstructions(IRCode code) {
Set<Value> affectedValues = Sets.newIdentityHashSet();
Set<BasicBlock> blocksToRemove = Sets.newIdentityHashSet();
ListIterator<BasicBlock> blockIterator = code.listIterator();
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
index 1c0d3de..f7cf0b5 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
@@ -270,7 +270,7 @@
rewriter.rewriteCode(ir, initializedClassesWithContexts, prunedFields);
// Run dead code elimination.
- new ThrowCatchOptimizer(appView).optimizeAlwaysThrowingInstructions(ir);
+ new ThrowCatchOptimizer(appView).run(ir, Timing.empty());
rewriter.getDeadCodeRemover().run(ir, Timing.empty());
// Finalize to class files or dex.