package org.graalvm.compiler.phases.graph;
import java.util.ArrayDeque;
import java.util.Deque;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeBitMap;
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.nodes.AbstractEndNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.ControlSinkNode;
import org.graalvm.compiler.nodes.ControlSplitNode;
import org.graalvm.compiler.nodes.EndNode;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.LoopEndNode;
import org.graalvm.compiler.nodes.LoopExitNode;
import org.graalvm.compiler.nodes.StructuredGraph;
public abstract class ScopedPostOrderNodeIterator {
private final Deque<FixedNode> nodeQueue;
private final NodeBitMap queuedNodes;
private final Deque<FixedNode> scopes;
protected FixedNode currentScopeStart;
public ScopedPostOrderNodeIterator(StructuredGraph graph) {
this.queuedNodes = graph.createNodeBitMap();
this.nodeQueue = new ArrayDeque<>();
this.scopes = getScopes(graph);
}
public void apply() {
while (!scopes.isEmpty()) {
queuedNodes.clearAll();
this.currentScopeStart = scopes.pop();
initializeScope();
processScope();
}
}
public void processScope() {
FixedNode current;
queue(currentScopeStart);
while ((current = nextQueuedNode()) != null) {
assert current.isAlive();
if (current instanceof Invoke) {
invoke((Invoke) current);
queueSuccessors(current);
} else if (current instanceof LoopBeginNode) {
queueLoopBeginSuccessors((LoopBeginNode) current);
} else if (current instanceof LoopExitNode) {
queueLoopExitSuccessors((LoopExitNode) current);
} else if (current instanceof LoopEndNode) {
} else if (current instanceof AbstractMergeNode) {
queueSuccessors(current);
} else if (current instanceof FixedWithNextNode) {
queueSuccessors(current);
} else if (current instanceof EndNode) {
queueMerge((EndNode) current);
} else if (current instanceof ControlSinkNode) {
} else if (current instanceof ControlSplitNode) {
queueSuccessors(current);
} else {
assert false : current;
}
}
}
protected void queueLoopBeginSuccessors(LoopBeginNode node) {
if (currentScopeStart == node) {
queue(node.next());
} else if (currentScopeStart instanceof LoopBeginNode) {
for (LoopExitNode loopExit : node.loopExits()) {
if (!((LoopBeginNode) currentScopeStart).loopExits().contains(loopExit)) {
queue(loopExit);
}
}
} else {
queue(node.loopExits());
}
}
protected void queueLoopExitSuccessors(LoopExitNode node) {
if (!(currentScopeStart instanceof LoopBeginNode) || !((LoopBeginNode) currentScopeStart).loopExits().contains(node)) {
queueSuccessors(node);
}
}
protected Deque<FixedNode> getScopes(StructuredGraph graph) {
Deque<FixedNode> result = new ArrayDeque<>();
result.push(graph.start());
for (LoopBeginNode loopBegin : graph.getNodes(LoopBeginNode.TYPE)) {
result.push(loopBegin);
}
return result;
}
private void queueSuccessors(FixedNode x) {
queue(x.successors());
}
private void queue(NodeIterable<? extends Node> iter) {
for (Node node : iter) {
queue(node);
}
}
private void queue(Node node) {
if (node != null && !queuedNodes.isMarked(node)) {
queuedNodes.mark(node);
nodeQueue.addFirst((FixedNode) node);
}
}
private FixedNode nextQueuedNode() {
if (nodeQueue.isEmpty()) {
return null;
}
FixedNode result = nodeQueue.removeFirst();