use of org.graalvm.compiler.nodes.VirtualState in project graal by oracle.
the class BinaryGraphPrinter method nodeProperties.
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void nodeProperties(GraphInfo info, Node node, Map<String, Object> props) {
node.getDebugProperties((Map) props);
Graph graph = info.graph;
ControlFlowGraph cfg = info.cfg;
NodeMap<Block> nodeToBlocks = info.nodeToBlocks;
if (cfg != null && DebugOptions.PrintGraphProbabilities.getValue(graph.getOptions()) && node instanceof FixedNode) {
try {
props.put("probability", cfg.blockFor(node).probability());
} catch (Throwable t) {
props.put("probability", 0.0);
props.put("probability-exception", t);
}
}
try {
props.put("NodeCost-Size", node.estimatedNodeSize());
props.put("NodeCost-Cycles", node.estimatedNodeCycles());
} catch (Throwable t) {
props.put("node-cost-exception", t.getMessage());
}
if (nodeToBlocks != null) {
Object block = getBlockForNode(node, nodeToBlocks);
if (block != null) {
props.put("node-to-block", block);
}
}
if (node instanceof ControlSinkNode) {
props.put("category", "controlSink");
} else if (node instanceof ControlSplitNode) {
props.put("category", "controlSplit");
} else if (node instanceof AbstractMergeNode) {
props.put("category", "merge");
} else if (node instanceof AbstractBeginNode) {
props.put("category", "begin");
} else if (node instanceof AbstractEndNode) {
props.put("category", "end");
} else if (node instanceof FixedNode) {
props.put("category", "fixed");
} else if (node instanceof VirtualState) {
props.put("category", "state");
} else if (node instanceof PhiNode) {
props.put("category", "phi");
} else if (node instanceof ProxyNode) {
props.put("category", "proxy");
} else {
if (node instanceof ConstantNode) {
ConstantNode cn = (ConstantNode) node;
updateStringPropertiesForConstant((Map) props, cn);
}
props.put("category", "floating");
}
if (getSnippetReflectionProvider() != null) {
for (Map.Entry<String, Object> prop : props.entrySet()) {
if (prop.getValue() instanceof JavaConstantFormattable) {
props.put(prop.getKey(), ((JavaConstantFormattable) prop.getValue()).format(this));
}
}
}
}
use of org.graalvm.compiler.nodes.VirtualState in project graal by oracle.
the class GraphOrder method assertSchedulableGraph.
/**
* This method schedules the graph and makes sure that, for every node, all inputs are available
* at the position where it is scheduled. This is a very expensive assertion.
*/
public static boolean assertSchedulableGraph(final StructuredGraph graph) {
assert graph.getGuardsStage() != GuardsStage.AFTER_FSA : "Cannot use the BlockIteratorClosure after FrameState Assignment, HIR Loop Data Structures are no longer valid.";
try {
final SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true);
final EconomicMap<LoopBeginNode, NodeBitMap> loopEntryStates = EconomicMap.create(Equivalence.IDENTITY);
schedulePhase.apply(graph, false);
final ScheduleResult schedule = graph.getLastSchedule();
BlockIteratorClosure<NodeBitMap> closure = new BlockIteratorClosure<NodeBitMap>() {
@Override
protected List<NodeBitMap> processLoop(Loop<Block> loop, NodeBitMap initialState) {
return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates;
}
@Override
protected NodeBitMap processBlock(final Block block, final NodeBitMap currentState) {
final List<Node> list = graph.getLastSchedule().getBlockToNodesMap().get(block);
/*
* A stateAfter is not valid directly after its associated state split, but
* right before the next fixed node. Therefore a pending stateAfter is kept that
* will be checked at the correct position.
*/
FrameState pendingStateAfter = null;
for (final Node node : list) {
if (node instanceof ValueNode) {
FrameState stateAfter = node instanceof StateSplit ? ((StateSplit) node).stateAfter() : null;
if (node instanceof FullInfopointNode) {
stateAfter = ((FullInfopointNode) node).getState();
}
if (pendingStateAfter != null && node instanceof FixedNode) {
pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {
@Override
public void apply(Node usage, Node nonVirtualNode) {
assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + " not available at virtualstate " + usage + " before " + node + " in block " + block + " \n" + list;
}
});
pendingStateAfter = null;
}
if (node instanceof AbstractMergeNode) {
// phis aren't scheduled, so they need to be added explicitly
currentState.markAll(((AbstractMergeNode) node).phis());
if (node instanceof LoopBeginNode) {
// remember the state at the loop entry, it's restored at exits
loopEntryStates.put((LoopBeginNode) node, currentState.copy());
}
} else if (node instanceof ProxyNode) {
assert false : "proxy nodes should not be in the schedule";
} else if (node instanceof LoopExitNode) {
if (graph.hasValueProxies()) {
for (ProxyNode proxy : ((LoopExitNode) node).proxies()) {
for (Node input : proxy.inputs()) {
if (input != proxy.proxyPoint()) {
assert currentState.isMarked(input) : input + " not available at " + proxy + " in block " + block + "\n" + list;
}
}
}
// loop contents are only accessible via proxies at the exit
currentState.clearAll();
currentState.markAll(loopEntryStates.get(((LoopExitNode) node).loopBegin()));
}
// Loop proxies aren't scheduled, so they need to be added
// explicitly
currentState.markAll(((LoopExitNode) node).proxies());
} else {
for (Node input : node.inputs()) {
if (input != stateAfter) {
if (input instanceof FrameState) {
((FrameState) input).applyToNonVirtual(new VirtualState.NodeClosure<Node>() {
@Override
public void apply(Node usage, Node nonVirtual) {
assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list;
}
});
} else {
assert currentState.isMarked(input) || input instanceof VirtualObjectNode || input instanceof ConstantNode : input + " not available at " + node + " in block " + block + "\n" + list;
}
}
}
}
if (node instanceof AbstractEndNode) {
AbstractMergeNode merge = ((AbstractEndNode) node).merge();
for (PhiNode phi : merge.phis()) {
ValueNode phiValue = phi.valueAt((AbstractEndNode) node);
assert phiValue == null || currentState.isMarked(phiValue) || phiValue instanceof ConstantNode : phiValue + " not available at phi " + phi + " / end " + node + " in block " + block;
}
}
if (stateAfter != null) {
assert pendingStateAfter == null;
pendingStateAfter = stateAfter;
}
currentState.mark(node);
}
}
if (pendingStateAfter != null) {
pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {
@Override
public void apply(Node usage, Node nonVirtualNode) {
assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + " not available at virtualstate " + usage + " at end of block " + block + " \n" + list;
}
});
}
return currentState;
}
@Override
protected NodeBitMap merge(Block merge, List<NodeBitMap> states) {
NodeBitMap result = states.get(0);
for (int i = 1; i < states.size(); i++) {
result.intersect(states.get(i));
}
return result;
}
@Override
protected NodeBitMap getInitialState() {
NodeBitMap ret = graph.createNodeBitMap();
ret.markAll(graph.getNodes().filter(ConstantNode.class));
return ret;
}
@Override
protected NodeBitMap cloneState(NodeBitMap oldState) {
return oldState.copy();
}
};
ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
} catch (Throwable t) {
graph.getDebug().handle(t);
}
return true;
}
use of org.graalvm.compiler.nodes.VirtualState in project graal by oracle.
the class LoopFragment method mergeEarlyExits.
/**
* Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with
* the original fragment's exits.
*/
protected void mergeEarlyExits() {
assert isDuplicate();
StructuredGraph graph = graph();
for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().loop().getExits())) {
LoopExitNode loopEarlyExit = (LoopExitNode) earlyExit;
FixedNode next = loopEarlyExit.next();
if (loopEarlyExit.isDeleted() || !this.original().contains(loopEarlyExit)) {
continue;
}
AbstractBeginNode newEarlyExit = getDuplicatedNode(loopEarlyExit);
if (newEarlyExit == null) {
continue;
}
MergeNode merge = graph.add(new MergeNode());
EndNode originalEnd = graph.add(new EndNode());
EndNode newEnd = graph.add(new EndNode());
merge.addForwardEnd(originalEnd);
merge.addForwardEnd(newEnd);
loopEarlyExit.setNext(originalEnd);
newEarlyExit.setNext(newEnd);
merge.setNext(next);
FrameState exitState = loopEarlyExit.stateAfter();
if (exitState != null) {
FrameState originalExitState = exitState;
exitState = exitState.duplicateWithVirtualState();
loopEarlyExit.setStateAfter(exitState);
merge.setStateAfter(originalExitState);
/*
* Using the old exit's state as the merge's state is necessary because some of the
* VirtualState nodes contained in the old exit's state may be shared by other
* dominated VirtualStates. Those dominated virtual states need to see the
* proxy->phi update that are applied below.
*
* We now update the original fragment's nodes accordingly:
*/
originalExitState.applyToVirtual(node -> original.nodes.clearAndGrow(node));
exitState.applyToVirtual(node -> original.nodes.markAndGrow(node));
}
FrameState finalExitState = exitState;
for (Node anchored : loopEarlyExit.anchored().snapshot()) {
anchored.replaceFirstInput(loopEarlyExit, merge);
}
boolean newEarlyExitIsLoopExit = newEarlyExit instanceof LoopExitNode;
for (ProxyNode vpn : loopEarlyExit.proxies().snapshot()) {
if (vpn.hasNoUsages()) {
continue;
}
if (vpn.value() == null) {
assert vpn instanceof GuardProxyNode;
vpn.replaceAtUsages(null);
continue;
}
final ValueNode replaceWith;
ValueNode newVpn = prim(newEarlyExitIsLoopExit ? vpn : vpn.value());
if (newVpn != null) {
PhiNode phi;
if (vpn instanceof ValueProxyNode) {
phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(NodeView.DEFAULT), merge));
} else if (vpn instanceof GuardProxyNode) {
phi = graph.addWithoutUnique(new GuardPhiNode(merge));
} else {
throw GraalError.shouldNotReachHere();
}
phi.addInput(vpn);
phi.addInput(newVpn);
replaceWith = phi;
} else {
replaceWith = vpn.value();
}
vpn.replaceAtMatchingUsages(replaceWith, usage -> {
if (merge.isPhiAtMerge(usage)) {
return false;
}
if (usage instanceof VirtualState) {
VirtualState stateUsage = (VirtualState) usage;
if (finalExitState != null && finalExitState.isPartOfThisState(stateUsage)) {
return false;
}
}
return true;
});
}
}
}
Aggregations