Merge "Add benchmarking ability to the sample app tool"
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 cb5aad0..3d30b23 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
@@ -138,13 +138,10 @@
if (predecessors.size() <= 1) {
continue;
}
- // If any of the edges to the block are critical, we need to insert new blocks on each
- // containing the move-exception instruction which must remain the first instruction.
- if (block.entry() instanceof MoveException) {
- nextBlockNumber = block.splitCriticalExceptionEdges(
- nextBlockNumber, valueNumberGenerator, newBlocks::add);
- continue;
- }
+
+ // Exceptional edges are given unique header blocks and can have at most one predecessor.
+ assert !block.entry().isMoveException();
+
for (int predIndex = 0; predIndex < predecessors.size(); predIndex++) {
BasicBlock pred = predecessors.get(predIndex);
if (!pred.hasOneNormalExit()) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
index 309e1d0..4cbebcf 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfSourceCode.java
@@ -586,7 +586,7 @@
}
@Override
- public int getMoveExceptionRegister() {
+ public int getMoveExceptionRegister(int instructionIndex) {
return CfState.Slot.STACK_OFFSET;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
index 31ee706..b59794b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
@@ -21,12 +21,12 @@
import com.android.tools.r8.code.InvokeSuperRange;
import com.android.tools.r8.code.InvokeVirtual;
import com.android.tools.r8.code.InvokeVirtualRange;
+import com.android.tools.r8.code.MoveException;
import com.android.tools.r8.code.MoveResult;
import com.android.tools.r8.code.MoveResultObject;
import com.android.tools.r8.code.MoveResultWide;
import com.android.tools.r8.code.SwitchPayload;
import com.android.tools.r8.code.Throw;
-import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexCode.Try;
@@ -185,14 +185,19 @@
}
@Override
- public int getMoveExceptionRegister() {
- // No register, move-exception is manually entered during construction.
+ public int getMoveExceptionRegister(int instructionIndex) {
+ Instruction instruction = code.instructions[instructionIndex];
+ if (instruction instanceof MoveException) {
+ MoveException moveException = (MoveException) instruction;
+ return moveException.AA;
+ }
return -1;
}
@Override
public Position getDebugPositionAtOffset(int offset) {
- throw new Unreachable();
+ DexDebugEntry entry = getDebugEntryAtOffset(offset);
+ return entry == null ? preamblePosition : getCanonicalPositionAppendCaller(entry);
}
@Override
@@ -225,23 +230,30 @@
}
}
+ private DexDebugEntry getDebugEntryAtOffset(int offset) {
+ DexDebugEntry current = null;
+ if (debugEntries != null) {
+ for (DexDebugEntry entry : debugEntries) {
+ if (entry.address > offset) {
+ break;
+ }
+ current = entry;
+ }
+ }
+ return current;
+ }
+
private void updateDebugPosition(int instructionIndex, IRBuilder builder) {
if (debugEntries == null || debugEntries.isEmpty()) {
return;
}
- DexDebugEntry current = null;
int offset = instructionOffset(instructionIndex);
- for (DexDebugEntry entry : debugEntries) {
- if (entry.address > offset) {
- break;
- }
- current = entry;
- }
- if (current == null) {
+ DexDebugEntry entry = getDebugEntryAtOffset(offset);
+ if (entry == null) {
currentPosition = preamblePosition;
} else {
- currentPosition = getCanonicalPositionAppendCaller(current);
- if (current.lineEntry && current.address == offset) {
+ currentPosition = getCanonicalPositionAppendCaller(entry);
+ if (entry.lineEntry && entry.address == offset) {
builder.addDebugPosition(currentPosition);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 5be54f5..6735863 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -296,7 +296,6 @@
private final LinkedList<BasicBlock> blocks = new LinkedList<>();
private BasicBlock currentBlock = null;
- private final List<BasicBlock.Pair> needGotoToCatchBlocks = new ArrayList<>();
final private ValueNumberGenerator valueNumberGenerator;
private final DexEncodedMethod method;
private final AppInfo appInfo;
@@ -411,9 +410,6 @@
// Check that the last block is closed and does not fall off the end.
assert currentBlock == null;
- // Handle where a catch handler hits the same block as the fallthrough.
- handleFallthroughToCatchBlock();
-
// Verify that we have properly filled all blocks
// Must be after handle-catch (which has delayed edges),
// but before handle-exit (which does not maintain predecessor counts).
@@ -571,14 +567,15 @@
private void processMoveExceptionItem(MoveExceptionWorklistItem moveExceptionItem) {
// TODO(zerny): Link with outer try-block handlers, if any. b/65203529
- int moveExceptionDest = source.getMoveExceptionRegister();
- assert moveExceptionDest >= 0;
int targetIndex = source.instructionIndex(moveExceptionItem.targetOffset);
- Value out = writeRegister(moveExceptionDest, ValueType.OBJECT, ThrowingInfo.NO_THROW, null);
- Position position = source.getDebugPositionAtOffset(moveExceptionItem.targetOffset);
- MoveException moveException = new MoveException(out);
- moveException.setPosition(position);
- currentBlock.add(moveException);
+ int moveExceptionDest = source.getMoveExceptionRegister(targetIndex);
+ if (moveExceptionDest >= 0) {
+ Value out = writeRegister(moveExceptionDest, ValueType.OBJECT, ThrowingInfo.NO_THROW, null);
+ Position position = source.getDebugPositionAtOffset(moveExceptionItem.targetOffset);
+ MoveException moveException = new MoveException(out);
+ moveException.setPosition(position);
+ currentBlock.add(moveException);
+ }
Goto exit = new Goto();
currentBlock.add(exit);
BasicBlock targetBlock = getTarget(moveExceptionItem.targetOffset);
@@ -976,11 +973,8 @@
public void addGoto(int targetOffset) {
addInstruction(new Goto());
BasicBlock targetBlock = getTarget(targetOffset);
- if (currentBlock.hasCatchSuccessor(targetBlock)) {
- needGotoToCatchBlocks.add(new BasicBlock.Pair(currentBlock, targetBlock));
- } else {
- currentBlock.link(targetBlock);
- }
+ assert !currentBlock.hasCatchSuccessor(targetBlock);
+ currentBlock.link(targetBlock);
addToWorklist(targetBlock, source.instructionIndex(targetOffset));
closeCurrentBlock();
}
@@ -1292,25 +1286,20 @@
}
public void addMoveException(int dest) {
- Value out = writeRegister(dest, ValueType.OBJECT, ThrowingInfo.NO_THROW);
- assert !out.hasLocalInfo();
- MoveException instruction = new MoveException(out);
- assert !instruction.instructionTypeCanThrow();
- if (currentBlock.getInstructions().size() == 1 && currentBlock.entry().isDebugPosition()) {
- InstructionListIterator it = currentBlock.listIterator();
- Instruction entry = it.next();
- assert entry.getPosition().equals(source.getCurrentPosition());
- attachLocalValues(instruction);
- it.replaceCurrentInstruction(instruction);
- return;
+ assert !currentBlock.getPredecessors().isEmpty();
+ assert currentBlock.getPredecessors().stream().allMatch(b -> b.entry().isMoveException());
+ assert verifyValueIsMoveException(readRegister(dest, ValueType.OBJECT));
+ }
+
+ private static boolean verifyValueIsMoveException(Value value) {
+ if (value.isPhi()) {
+ for (Value operand : value.asPhi().getOperands()) {
+ assert operand.definition.isMoveException();
+ }
+ } else {
+ assert value.definition.isMoveException();
}
- if (!currentBlock.getInstructions().isEmpty()) {
- throw new CompilationError("Invalid MoveException instruction encountered. "
- + "The MoveException instruction is not the first instruction in the block in "
- + method.qualifiedName()
- + ".");
- }
- addInstruction(instruction);
+ return true;
}
public void addMoveResult(int dest) {
@@ -1843,29 +1832,19 @@
assert !throwingInstructionInCurrentBlock;
throwingInstructionInCurrentBlock = true;
List<BasicBlock> targets = new ArrayList<>(catchHandlers.getAllTargets().size());
- int moveExceptionDest = source.getMoveExceptionRegister();
- if (moveExceptionDest < 0) {
- for (int targetOffset : catchHandlers.getAllTargets()) {
- BasicBlock target = getTarget(targetOffset);
- addToWorklist(target, source.instructionIndex(targetOffset));
- targets.add(target);
+ // Construct unique move-exception header blocks for each unique target.
+ Map<BasicBlock, BasicBlock> moveExceptionHeaders =
+ new IdentityHashMap<>(catchHandlers.getUniqueTargets().size());
+ for (int targetOffset : catchHandlers.getAllTargets()) {
+ BasicBlock target = getTarget(targetOffset);
+ BasicBlock header = moveExceptionHeaders.get(target);
+ if (header == null) {
+ header = new BasicBlock();
+ header.incrementUnfilledPredecessorCount();
+ moveExceptionHeaders.put(target, header);
+ ssaWorklist.add(new MoveExceptionWorklistItem(header, targetOffset));
}
- } else {
- // If there is a well-defined move-exception destination register (eg, compiling from
- // Java-bytecode) then we construct move-exception header blocks for each unique target.
- Map<BasicBlock, BasicBlock> moveExceptionHeaders =
- new IdentityHashMap<>(catchHandlers.getUniqueTargets().size());
- for (int targetOffset : catchHandlers.getAllTargets()) {
- BasicBlock target = getTarget(targetOffset);
- BasicBlock header = moveExceptionHeaders.get(target);
- if (header == null) {
- header = new BasicBlock();
- header.incrementUnfilledPredecessorCount();
- moveExceptionHeaders.put(target, header);
- ssaWorklist.add(new MoveExceptionWorklistItem(header, targetOffset));
- }
- targets.add(header);
- }
+ targets.add(header);
}
currentBlock.linkCatchSuccessors(catchHandlers.getGuards(), targets);
}
@@ -1997,45 +1976,11 @@
private void closeCurrentBlockWithFallThrough(BasicBlock nextBlock) {
assert currentBlock != null;
addInstruction(new Goto());
- if (currentBlock.hasCatchSuccessor(nextBlock)) {
- needGotoToCatchBlocks.add(new BasicBlock.Pair(currentBlock, nextBlock));
- } else {
- currentBlock.link(nextBlock);
- }
+ assert !currentBlock.hasCatchSuccessor(nextBlock);
+ currentBlock.link(nextBlock);
closeCurrentBlock();
}
- private void handleFallthroughToCatchBlock() {
- // When a catch handler for a block goes to the same block as the fallthrough for that
- // block the graph only has one edge there. In these cases we add an additional block so the
- // catch edge goes through that and then make the fallthrough go through a new direct edge.
- for (BasicBlock.Pair pair : needGotoToCatchBlocks) {
- BasicBlock source = pair.first;
- BasicBlock target = pair.second;
-
- // New block with one unfilled predecessor.
- BasicBlock newBlock = BasicBlock.createGotoBlock(nextBlockNumber++, target);
- blocks.add(newBlock);
- newBlock.incrementUnfilledPredecessorCount();
-
- // Link blocks.
- source.replaceSuccessor(target, newBlock);
- newBlock.getPredecessors().add(source);
- source.getSuccessors().add(target);
- target.getPredecessors().add(newBlock);
-
- // Check that the successor indexes are correct.
- assert source.hasCatchSuccessor(newBlock);
- assert !source.hasCatchSuccessor(target);
-
- // Mark the filled predecessors to the blocks.
- if (source.isFilled()) {
- newBlock.filledPredecessor(this);
- }
- target.filledPredecessor(this);
- }
- }
-
/**
* Change to control-flow graph to avoid repeated phi operands when all the same values
* flow in from multiple predecessors.
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index 5c25fba..53bbb7e 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -594,7 +594,12 @@
}
@Override
- public int getMoveExceptionRegister() {
+ public int getMoveExceptionRegister(int instructionIndex) {
+ return getMoveExceptionRegister();
+ }
+
+ // In classfiles the register is always on top of stack.
+ private int getMoveExceptionRegister() {
return state.startOfStack;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java
index e95790a..bf2b51f 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/SourceCode.java
@@ -59,7 +59,8 @@
void resolveAndBuildNewArrayFilledData(int arrayRef, int payloadOffset, IRBuilder builder);
CatchHandlers<Integer> getCurrentCatchHandlers();
- int getMoveExceptionRegister();
+
+ int getMoveExceptionRegister(int instructionIndex);
// For debugging/verification purpose.
boolean verifyRegister(int register);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 6cb8f6e..e749479 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -1099,7 +1099,7 @@
}
@Override
- public int getMoveExceptionRegister() {
+ public int getMoveExceptionRegister(int instructionIndex) {
throw new Unreachable();
}
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
index 80a439a..c64d8ed 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
@@ -209,7 +209,7 @@
}
@Override
- public int getMoveExceptionRegister() {
+ public int getMoveExceptionRegister(int instructionIndex) {
throw new Unreachable();
}
diff --git a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
index e7344a4..0cf2f53 100644
--- a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
+++ b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
@@ -196,7 +196,7 @@
public void runCatchHandlerTest(boolean codeThrows, boolean twoGuards) throws Exception {
final int secondBlockInstructions = 4;
- final int initialBlockCount = 5;
+ final int initialBlockCount = 6;
// Try split between all instructions in second block.
for (int i = 1; i < secondBlockInstructions; i++) {
TestApplication test = codeWithCatchHandlers(codeThrows, twoGuards);
@@ -235,7 +235,7 @@
public void runCatchHandlerSplitThreeTest(boolean codeThrows, boolean twoGuards)
throws Exception {
final int secondBlockInstructions = 4;
- final int initialBlockCount = 5;
+ final int initialBlockCount = 6;
// Try split out all instructions in second block.
for (int i = 1; i < secondBlockInstructions - 1; i++) {
TestApplication test = codeWithCatchHandlers(codeThrows, twoGuards);
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 4214a67..101bf06 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -766,7 +766,7 @@
}
@Override
- public int getMoveExceptionRegister() {
+ public int getMoveExceptionRegister(int instructionIndex) {
throw new Unreachable();
}