Supply guard type to exceptional control flow transfer
Change-Id: I9d6f6abd6f8a1c4b0246c5e9cf397cea8f8e303c
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfTryCatch.java b/src/main/java/com/android/tools/r8/cf/code/CfTryCatch.java
index 22aac9a..67f452d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfTryCatch.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfTryCatch.java
@@ -12,7 +12,9 @@
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.utils.structural.CompareToVisitor;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class CfTryCatch {
@@ -29,6 +31,15 @@
assert verifyAllNonNull(guards);
}
+ public void forEach(BiConsumer<DexType, CfLabel> consumer) {
+ Iterator<DexType> guardIterator = guards.iterator();
+ Iterator<CfLabel> targetIterator = targets.iterator();
+ while (guardIterator.hasNext()) {
+ consumer.accept(guardIterator.next(), targetIterator.next());
+ }
+ assert !targetIterator.hasNext();
+ }
+
public void forEachTarget(Consumer<CfLabel> consumer) {
targets.forEach(consumer);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/AbstractTransferFunction.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/AbstractTransferFunction.java
index 57e5b6b..ad58a5c 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/AbstractTransferFunction.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/AbstractTransferFunction.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.ir.analysis.framework.intraprocedural;
+import com.android.tools.r8.graph.DexType;
+
/**
* A transfer function that defines the abstract semantics of the instructions in the program
* according to some abstract state {@link StateType}.
@@ -48,7 +50,11 @@
* true.
*/
default StateType computeExceptionalBlockEntryState(
- Block block, Block throwBlock, Instruction throwInstruction, StateType throwState) {
+ Block block,
+ DexType guard,
+ Block throwBlock,
+ Instruction throwInstruction,
+ StateType throwState) {
return throwState;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/ControlFlowGraph.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/ControlFlowGraph.java
index ecf6287..a0a7ba0 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/ControlFlowGraph.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/ControlFlowGraph.java
@@ -4,8 +4,11 @@
package com.android.tools.r8.ir.analysis.framework.intraprocedural;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.TraversalContinuation;
import com.android.tools.r8.utils.TraversalUtils;
+import com.android.tools.r8.utils.TriFunction;
+import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -29,7 +32,10 @@
}
default boolean hasExceptionalSuccessors(Block block) {
- return TraversalUtils.hasNext(counter -> traverseExceptionalSuccessors(block, counter));
+ return TraversalUtils.hasNext(
+ counter ->
+ traverseExceptionalSuccessors(
+ block, (exceptionalSuccessor, guard) -> counter.apply(exceptionalSuccessor)));
}
default boolean hasUniquePredecessor(Block block) {
@@ -77,8 +83,9 @@
}
default <BT, CT> TraversalContinuation<BT, CT> traverseExceptionalSuccessors(
- Block block, Function<? super Block, TraversalContinuation<BT, CT>> fn) {
- return traverseExceptionalSuccessors(block, (successor, ignore) -> fn.apply(successor), null);
+ Block block, BiFunction<? super Block, DexType, TraversalContinuation<BT, CT>> fn) {
+ return traverseExceptionalSuccessors(
+ block, (successor, guard, ignore) -> fn.apply(successor, guard), null);
}
// Block traversal with result.
@@ -110,7 +117,10 @@
return traverseNormalSuccessors(block, fn, initialValue)
.ifContinueThen(
continuation ->
- traverseExceptionalSuccessors(block, fn, continuation.getValueOrDefault(null)));
+ traverseExceptionalSuccessors(
+ block,
+ (exceptionalSuccessor, guard, value) -> fn.apply(exceptionalSuccessor, value),
+ continuation.getValueOrDefault(null)));
}
<BT, CT> TraversalContinuation<BT, CT> traverseNormalSuccessors(
@@ -120,7 +130,7 @@
<BT, CT> TraversalContinuation<BT, CT> traverseExceptionalSuccessors(
Block block,
- BiFunction<? super Block, ? super CT, TraversalContinuation<BT, CT>> fn,
+ TriFunction<? super Block, DexType, ? super CT, TraversalContinuation<BT, CT>> fn,
CT initialValue);
// Block iteration.
@@ -150,7 +160,8 @@
default void forEachSuccessor(Block block, Consumer<Block> consumer) {
forEachNormalSuccessor(block, consumer);
- forEachExceptionalSuccessor(block, consumer);
+ forEachExceptionalSuccessor(
+ block, (exceptionalSuccessor, guard) -> consumer.accept(exceptionalSuccessor));
}
default void forEachNormalSuccessor(Block block, Consumer<Block> consumer) {
@@ -162,11 +173,11 @@
});
}
- default void forEachExceptionalSuccessor(Block block, Consumer<Block> consumer) {
+ default void forEachExceptionalSuccessor(Block block, BiConsumer<Block, DexType> consumer) {
traverseExceptionalSuccessors(
block,
- exceptionalSuccessor -> {
- consumer.accept(exceptionalSuccessor);
+ (exceptionalSuccessor, guard) -> {
+ consumer.accept(exceptionalSuccessor, guard);
return TraversalContinuation.doContinue();
});
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraProceduralDataflowAnalysisBase.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraProceduralDataflowAnalysisBase.java
index dbd2a45..d7dbeb3 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraProceduralDataflowAnalysisBase.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/IntraProceduralDataflowAnalysisBase.java
@@ -190,10 +190,10 @@
Block block, Instruction instruction, StateType state) {
cfg.forEachExceptionalSuccessor(
block,
- exceptionalSuccessor -> {
+ (exceptionalSuccessor, guard) -> {
StateType edgeState =
transfer.computeExceptionalBlockEntryState(
- exceptionalSuccessor, block, instruction, state);
+ exceptionalSuccessor, guard, block, instruction, state);
updateBlockEntryStateForBlock(
exceptionalSuccessor, edgeState, exceptionalBlockEntryStates);
});
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfBlock.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfBlock.java
index 942cb97..7986623 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfBlock.java
@@ -6,10 +6,12 @@
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.SetUtils;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -31,7 +33,7 @@
final List<CfBlock> exceptionalPredecessors = new ArrayList<>();
// The exceptional successors of the block (i.e., the catch handlers of the block).
- final List<CfBlock> exceptionalSuccessors = new ArrayList<>();
+ final LinkedHashMap<DexType, CfBlock> exceptionalSuccessors = new LinkedHashMap<>();
public CfInstruction getFallthroughInstruction(CfCode code) {
int fallthroughInstructionIndex = getLastInstructionIndex() + 1;
@@ -56,15 +58,11 @@
return predecessors;
}
- // TODO(b/214496607): This currently only encodes the graph, but we likely need to include the
- // guard types here.
public List<CfBlock> getExceptionalPredecessors() {
return exceptionalPredecessors;
}
- // TODO(b/214496607): This currently only encodes the graph, but we likely need to include the
- // guard types here.
- public List<CfBlock> getExceptionalSuccessors() {
+ public LinkedHashMap<DexType, CfBlock> getExceptionalSuccessors() {
return exceptionalSuccessors;
}
@@ -79,8 +77,9 @@
exceptionalPredecessors.add(block);
}
- void addExceptionalSuccessor(CfBlock block) {
- exceptionalSuccessors.add(block);
+ void addExceptionalSuccessor(CfBlock block, DexType guard) {
+ assert !exceptionalSuccessors.containsKey(guard);
+ exceptionalSuccessors.put(guard, block);
}
void setFirstInstructionIndex(int firstInstructionIndex) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfControlFlowGraph.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfControlFlowGraph.java
index 4fe4724..2b58157 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfControlFlowGraph.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfControlFlowGraph.java
@@ -10,12 +10,14 @@
import com.android.tools.r8.cf.code.CfLabel;
import com.android.tools.r8.cf.code.CfTryCatch;
import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.ControlFlowGraph;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.cf.CfBlock.MutableCfBlock;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.TraversalContinuation;
import com.android.tools.r8.utils.TraversalUtils;
+import com.android.tools.r8.utils.TriFunction;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.util.ArrayDeque;
@@ -23,10 +25,9 @@
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.Iterator;
-import java.util.LinkedHashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.function.BiFunction;
/**
@@ -64,7 +65,7 @@
@Override
public CfBlock getEntryBlock() {
- return getBlock(code.getInstructions().get(0));
+ return getBlock(code.getInstruction(0));
}
@Override
@@ -97,9 +98,12 @@
@Override
public <BT, CT> TraversalContinuation<BT, CT> traverseExceptionalSuccessors(
CfBlock block,
- BiFunction<? super CfBlock, ? super CT, TraversalContinuation<BT, CT>> fn,
+ TriFunction<? super CfBlock, DexType, ? super CT, TraversalContinuation<BT, CT>> fn,
CT initialValue) {
- return TraversalUtils.traverseIterable(block.getExceptionalSuccessors(), fn, initialValue);
+ return TraversalUtils.traverseMap(
+ block.getExceptionalSuccessors(),
+ (guard, exceptionalSuccessor, value) -> fn.apply(exceptionalSuccessor, guard, value),
+ initialValue);
}
@Override
@@ -112,7 +116,7 @@
for (int instructionIndex = block.getFirstInstructionIndex();
instructionIndex <= block.getLastInstructionIndex();
instructionIndex++) {
- CfInstruction instruction = code.getInstructions().get(instructionIndex);
+ CfInstruction instruction = code.getInstruction(instructionIndex);
traversalContinuation = fn.apply(instruction, traversalContinuation.asContinue().getValue());
if (traversalContinuation.shouldBreak()) {
break;
@@ -255,11 +259,11 @@
}
// Visit each instruction belonging to the current block.
- Set<CfLabel> exceptionalSuccessors = new LinkedHashSet<>();
+ Map<DexType, CfLabel> exceptionalSuccessors = new LinkedHashMap<>();
Iterator<CfTryCatch> activeCatchHandlerIterator = activeCatchHandlers.descendingIterator();
while (activeCatchHandlerIterator.hasNext()) {
CfTryCatch activeCatchHandler = activeCatchHandlerIterator.next();
- activeCatchHandler.forEachTarget(exceptionalSuccessors::add);
+ activeCatchHandler.forEach(exceptionalSuccessors::putIfAbsent);
}
do {
@@ -269,7 +273,7 @@
if (isBlockExit(instructionIndex)) {
break;
}
- instruction = code.getInstructions().get(++instructionIndex);
+ instruction = code.getInstruction(++instructionIndex);
} while (true);
// Record the index of the last instruction of the block.
@@ -282,9 +286,9 @@
// Add the current block as an exceptional predecessor of the exceptional successor blocks.
exceptionalSuccessors.forEach(
- exceptionalSuccessor -> {
+ (guard, exceptionalSuccessor) -> {
MutableCfBlock exceptionalSuccessorBlock = getBlock(exceptionalSuccessor);
- block.addExceptionalSuccessor(exceptionalSuccessorBlock);
+ block.addExceptionalSuccessor(exceptionalSuccessorBlock, guard);
exceptionalSuccessorBlock.addExceptionalPredecessor(block);
});
@@ -307,7 +311,7 @@
if (instructionIndex == lastInstructionIndex) {
return true;
}
- CfInstruction nextInstruction = code.getInstructions().get(instructionIndex + 1);
+ CfInstruction nextInstruction = code.getInstruction(instructionIndex + 1);
return isBlockEntry(nextInstruction);
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
index 0d1bf75..432311b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -26,6 +26,7 @@
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
import com.android.tools.r8.utils.TraversalContinuation;
+import com.android.tools.r8.utils.TriFunction;
import com.google.common.base.Equivalence;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.ImmutableList;
@@ -243,14 +244,17 @@
}
public <BT, CT> TraversalContinuation<BT, CT> traverseExceptionalSuccessors(
- BiFunction<? super BasicBlock, ? super CT, TraversalContinuation<BT, CT>> fn,
+ TriFunction<? super BasicBlock, DexType, ? super CT, TraversalContinuation<BT, CT>> fn,
CT initialValue) {
int numberOfExceptionalSuccessors = numberOfExceptionalSuccessors();
TraversalContinuation<BT, CT> traversalContinuation =
TraversalContinuation.doContinue(initialValue);
for (int i = 0; i < numberOfExceptionalSuccessors; i++) {
traversalContinuation =
- fn.apply(successors.get(i), traversalContinuation.asContinue().getValueOrDefault(null));
+ fn.apply(
+ successors.get(i),
+ catchHandlers.getGuard(i),
+ traversalContinuation.asContinue().getValueOrDefault(null));
if (traversalContinuation.isBreak()) {
break;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/CatchHandlers.java b/src/main/java/com/android/tools/r8/ir/code/CatchHandlers.java
index 6005e1f..03771cd 100644
--- a/src/main/java/com/android/tools/r8/ir/code/CatchHandlers.java
+++ b/src/main/java/com/android/tools/r8/ir/code/CatchHandlers.java
@@ -64,6 +64,10 @@
return guards;
}
+ public DexType getGuard(int index) {
+ return guards.get(index);
+ }
+
public List<T> getAllTargets() {
return targets;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index 8f310c8..409d050 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -35,6 +35,7 @@
import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.TraversalContinuation;
+import com.android.tools.r8.utils.TriFunction;
import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -1402,7 +1403,7 @@
@Override
public <BT, CT> TraversalContinuation<BT, CT> traverseExceptionalSuccessors(
BasicBlock block,
- BiFunction<? super BasicBlock, ? super CT, TraversalContinuation<BT, CT>> fn,
+ TriFunction<? super BasicBlock, DexType, ? super CT, TraversalContinuation<BT, CT>> fn,
CT initialValue) {
return block.traverseExceptionalSuccessors(fn, initialValue);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/TransferFunction.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/TransferFunction.java
index a955882..f6bc6e6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/TransferFunction.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/TransferFunction.java
@@ -152,6 +152,7 @@
@Override
public ParameterUsages computeExceptionalBlockEntryState(
BasicBlock block,
+ DexType guard,
BasicBlock throwBlock,
Instruction throwInstruction,
ParameterUsages throwState) {
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
index 121b5ab..049a279 100644
--- a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
@@ -102,6 +102,7 @@
@Override
public CfFrameState computeExceptionalBlockEntryState(
CfBlock block,
+ DexType guard,
CfBlock throwBlock,
CfInstruction throwInstruction,
CfFrameState throwState) {
diff --git a/src/main/java/com/android/tools/r8/utils/TraversalUtils.java b/src/main/java/com/android/tools/r8/utils/TraversalUtils.java
index b705d02..627ee79 100644
--- a/src/main/java/com/android/tools/r8/utils/TraversalUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/TraversalUtils.java
@@ -6,6 +6,8 @@
import static com.android.tools.r8.utils.FunctionUtils.ignoreArgument;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -64,4 +66,23 @@
}
return traversalContinuation;
}
+
+ public static <S, T, BT, CT> TraversalContinuation<BT, CT> traverseMap(
+ Map<S, T> map,
+ TriFunction<? super S, ? super T, ? super CT, TraversalContinuation<BT, CT>> fn,
+ CT initialValue) {
+ TraversalContinuation<BT, CT> traversalContinuation =
+ TraversalContinuation.doContinue(initialValue);
+ for (Entry<S, T> entry : map.entrySet()) {
+ traversalContinuation =
+ fn.apply(
+ entry.getKey(),
+ entry.getValue(),
+ traversalContinuation.asContinue().getValueOrDefault(null));
+ if (traversalContinuation.isBreak()) {
+ break;
+ }
+ }
+ return traversalContinuation;
+ }
}