# HG changeset patch # User Miguel Garcia # Date 1399658741 -7200 # Node ID 642bd083a5ccf4cdf224d842fc0fa1b570999c53 # Parent 4d5b1e7a4d9368ed29b623d1074e1c8ec0e34cc6 [single-pass-iter] offloading tracking successor-pre-states to nodeQueue diff -r 4d5b1e7a4d93 -r 642bd083a5cc graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/SinglePassNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/SinglePassNodeIterator.java Fri May 09 17:33:14 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/SinglePassNodeIterator.java Fri May 09 20:05:41 2014 +0200 @@ -56,12 +56,45 @@ public abstract class SinglePassNodeIterator> { private final NodeBitMap visitedEnds; - private final Deque nodeQueue; + private final Deque> nodeQueue; private final Map nodeStates; private final StartNode start; protected T state; + /** + * An item queued in {@link #nodeQueue} can be used to continue with the single-pass visit after + * the previous path can't be followed anymore. Such items are: + *
    + *
  • de-queued via {@link #nextQueuedNode()}
  • + *
  • en-queued via {@link #queueMerge(EndNode)} and {@link #queueSuccessors(FixedNode)}
  • + *
+ * + *

+ * Correspondingly each item may stand for: + *

    + *
  • a {@link MergeNode} whose pre-state results from merging those of its forward-ends, see + * {@link #nextQueuedNode()}
  • + *
  • the successor of a control-split node, in which case the pre-state of the successor in + * question is also stored in the item, see {@link #nextQueuedNode()}
  • + *
+ *

+ */ + private static class QElem { + private final FixedNode node; + private final U preState; + + private QElem(FixedNode node, U preState) { + this.node = node; + this.preState = preState; + assert repOK(); + } + + private boolean repOK() { + return (node instanceof MergeNode && preState == null) || (node instanceof BeginNode && preState != null); + } + } + public SinglePassNodeIterator(StartNode start, T initialState) { StructuredGraph graph = start.graph(); visitedEnds = graph.createNodeBitMap(); @@ -127,10 +160,9 @@ } private void queueSuccessors(FixedNode x) { - keepForLater(x, state); for (Node node : x.successors()) { if (node != null) { - nodeQueue.addFirst((BeginNode) node); + nodeQueue.addFirst(new QElem<>((BeginNode) node, state)); } } } @@ -146,28 +178,28 @@ *

*/ private FixedNode nextQueuedNode() { - int maxIterations = nodeQueue.size(); - while (maxIterations-- > 0) { - BeginNode node = nodeQueue.removeFirst(); - if (node instanceof MergeNode) { - MergeNode merge = (MergeNode) node; - state = pruneEntry(merge.forwardEndAt(0)).clone(); - ArrayList states = new ArrayList<>(merge.forwardEndCount() - 1); - for (int i = 1; i < merge.forwardEndCount(); i++) { - T other = pruneEntry(merge.forwardEndAt(i)); - states.add(other); - } - boolean ready = state.merge(merge, states); - assert ready : "Not a single-pass iterator after all"; - return merge; - } else { - assert node.predecessor() != null; - state = nodeStates.get(node.predecessor()).clone(); - state.afterSplit(node); - return node; + if (nodeQueue.isEmpty()) { + return null; + } + QElem elem = nodeQueue.removeFirst(); + if (elem.node instanceof MergeNode) { + MergeNode merge = (MergeNode) elem.node; + state = pruneEntry(merge.forwardEndAt(0)).clone(); + ArrayList states = new ArrayList<>(merge.forwardEndCount() - 1); + for (int i = 1; i < merge.forwardEndCount(); i++) { + T other = pruneEntry(merge.forwardEndAt(i)); + states.add(other); } + boolean ready = state.merge(merge, states); + assert ready : "Not a single-pass iterator after all"; + return merge; + } else { + BeginNode begin = (BeginNode) elem.node; + assert begin.predecessor() != null; + state = elem.preState.clone(); + state.afterSplit(begin); + return begin; } - return null; } /** @@ -223,7 +255,7 @@ } } if (endsVisited) { - nodeQueue.add(merge); + nodeQueue.add(new QElem<>(merge, null)); } } @@ -257,7 +289,8 @@ * The lifecycle that single-pass node iterators go through is described in {@link #apply()} */ protected void finished() { - // nothing to do + assert nodeQueue.isEmpty(); + assert nodeStates.isEmpty(); } private void keepForLater(FixedNode x, T s) {