--- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java 2019-05-06 15:58:53.447333196 +0200
+++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java 2019-05-06 15:58:53.047330635 +0200
@@ -93,6 +93,7 @@
import static org.graalvm.compiler.bytecode.Bytecodes.TABLESWITCH;
import static org.graalvm.compiler.core.common.GraalOptions.SupportJsrBytecodes;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -117,7 +118,7 @@
/**
* Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph
- * (CFG). It makes one linear passes over the bytecodes to build the CFG where it detects block
+ * (CFG). It makes one linear pass over the bytecodes to build the CFG where it detects block
* headers and connects them.
*
* It also creates exception dispatch blocks for exception handling. These blocks are between a
@@ -477,6 +478,18 @@
}
}
+ private static final class TraversalStep {
+ private BciBlock block;
+ private int currentSuccessorIndex;
+ private long loops;
+
+ private TraversalStep(BciBlock block) {
+ this.block = block;
+ this.currentSuccessorIndex = 0;
+ this.loops = 0;
+ }
+ }
+
/**
* The blocks found in this method, in reverse postorder.
*/
@@ -857,7 +870,7 @@
b.visited = false;
}
- long loop = fixLoopBits(blockMap, blockMap[0]);
+ long loop = fixLoopBits(blockMap[0]);
if (loop != 0) {
// There is a path from a loop end to the method entry that does not pass the loop
@@ -1029,78 +1042,107 @@
}
/**
- * Depth-first traversal of the control flow graph. The flag {@linkplain BciBlock#visited} is
- * used to visit every block only once. The flag {@linkplain BciBlock#active} is used to detect
- * cycles (backward edges).
+ * Non-recursive depth-first traversal of the control flow graph. The flag
+ * {@linkplain BciBlock#visited} is used to visit every block only once. The flag
+ * {@linkplain BciBlock#active} is used to detect cycles (backward edges)
*/
- private long computeBlockOrder(BciBlock block) {
- if (block.visited) {
- if (block.active) {
- // Reached block via backward branch.
- makeLoopHeader(block);
- // Return cached loop information for this block.
- return block.loops;
- } else if (block.isLoopHeader) {
- return block.loops & ~(1L << block.loopId);
+ private long computeBlockOrder(BciBlock initialBlock) {
+ ArrayDeque workStack = new ArrayDeque<>();
+ workStack.push(new TraversalStep(initialBlock));
+ while (true) {
+ TraversalStep step = workStack.peek();
+ BciBlock block = step.block;
+ if (step.currentSuccessorIndex == 0) {
+ block.visited = true;
+ block.active = true;
} else {
- return block.loops;
+ BciBlock successor = block.getSuccessor(step.currentSuccessorIndex - 1);
+ if (successor.active) {
+ // Reached block via backward branch.
+ step.loops |= (1L << successor.loopId);
+ }
}
- }
-
- block.visited = true;
- block.active = true;
+ if (step.currentSuccessorIndex < block.successors.size()) {
+ BciBlock successor = block.getSuccessors().get(step.currentSuccessorIndex);
+ if (successor.visited) {
+ if (successor.active) {
+ // Reached block via backward branch.
+ makeLoopHeader(successor);
+ step.loops |= successor.loops;
+ } else if (successor.isLoopHeader) {
+ step.loops |= successor.loops & ~(1L << successor.loopId);
+ } else {
+ step.loops |= successor.loops;
+ }
+ } else {
+ workStack.push(new TraversalStep(successor));
+ }
+ step.currentSuccessorIndex++;
+ } else {
+ // We processed all the successors of this block.
+ block.loops = step.loops;
+ debug.log("computeBlockOrder(%s) -> %x", block, block.loops);
- long loops = 0;
- for (BciBlock successor : block.getSuccessors()) {
- // Recursively process successors.
- loops |= computeBlockOrder(successor);
- if (successor.active) {
- // Reached block via backward branch.
- loops |= (1L << successor.loopId);
- }
- }
+ if (block.isLoopHeader) {
+ step.loops &= ~(1L << block.loopId);
+ }
- block.loops = loops;
- debug.log("computeBlockOrder(%s) -> %x", block, block.loops);
+ block.active = false;
+ blocksNotYetAssignedId--;
+ blocks[blocksNotYetAssignedId] = block;
- if (block.isLoopHeader) {
- loops &= ~(1L << block.loopId);
+ workStack.pop();
+ if (!workStack.isEmpty()) {
+ workStack.peek().loops |= step.loops;
+ } else {
+ return step.loops;
+ }
+ }
}
-
- block.active = false;
- blocksNotYetAssignedId--;
- blocks[blocksNotYetAssignedId] = block;
-
- return loops;
}
- private long fixLoopBits(BciBlock[] blockMap, BciBlock block) {
- if (block.visited) {
- // Return cached loop information for this block.
- if (block.isLoopHeader) {
- return block.loops & ~(1L << block.loopId);
- } else {
- return block.loops;
+ private long fixLoopBits(BciBlock initialBlock) {
+ ArrayDeque workStack = new ArrayDeque<>();
+ workStack.push(new TraversalStep(initialBlock));
+ while (true) {
+ TraversalStep step = workStack.peek();
+ BciBlock block = step.block;
+ if (step.currentSuccessorIndex == 0) {
+ block.visited = true;
+ step.loops = block.loops;
}
- }
+ if (step.currentSuccessorIndex < block.getSuccessors().size()) {
+ BciBlock successor = block.getSuccessors().get(step.currentSuccessorIndex);
+ if (successor.visited) {
+ // Return cached loop information for this block.
+ if (successor.isLoopHeader) {
+ step.loops |= successor.loops & ~(1L << successor.loopId);
+ } else {
+ step.loops |= successor.loops;
+ }
+ } else {
+ workStack.push(new TraversalStep(successor));
+ }
+ step.currentSuccessorIndex++;
+ } else {
+ if (block.loops != step.loops) {
+ loopChanges = true;
+ block.loops = step.loops;
+ debug.log("fixLoopBits0(%s) -> %x", block, block.loops);
+ }
- block.visited = true;
- long loops = block.loops;
- for (BciBlock successor : block.getSuccessors()) {
- // Recursively process successors.
- loops |= fixLoopBits(blockMap, successor);
- }
- if (block.loops != loops) {
- loopChanges = true;
- block.loops = loops;
- debug.log("fixLoopBits0(%s) -> %x", block, block.loops);
- }
+ if (block.isLoopHeader) {
+ step.loops &= ~(1L << block.loopId);
+ }
- if (block.isLoopHeader) {
- loops &= ~(1L << block.loopId);
+ workStack.pop();
+ if (!workStack.isEmpty()) {
+ workStack.peek().loops |= step.loops;
+ } else {
+ return step.loops;
+ }
+ }
}
-
- return loops;
}
public static BciBlockMapping create(BytecodeStream stream, Bytecode code, OptionValues options, DebugContext debug) {