use of org.graalvm.compiler.nodes.memory.MemoryKill in project graal by oracle.
the class PlaceholderLogicNode method instantiate.
/**
* Replaces a given fixed node with this specialized snippet.
*
* @param metaAccess
* @param replacee the node that will be replaced
* @param replacer object that replaces the usages of {@code replacee}
* @param args the arguments to be bound to the flattened positional parameters of the snippet
* @param killReplacee is true, the replacee node is deleted
* @return the map of duplicated nodes (original -> duplicate)
*/
@SuppressWarnings("try")
public UnmodifiableEconomicMap<Node, Node> instantiate(MetaAccessProvider metaAccess, FixedNode replacee, UsageReplacer replacer, Arguments args, boolean killReplacee) {
if (!(replacee instanceof ControlSinkNode)) {
/*
* For all use cases of this, the replacee is killed sooner ({@code killReplacee ==
* true}) or later (by the caller of this method). However, we cannot do that if the
* snippet does not have a return node we because that means we kill the {@code
* replacee.next()} which might be connected to a merge whose next node has not yet been
* lowered [GR-33909].
*/
GraalError.guarantee(this.returnNode != null, "Cannot kill %s because snippet %s does not have a return node", replacee, this);
}
DebugContext debug = replacee.getDebug();
assert assertSnippetKills(replacee);
try (DebugCloseable a = args.info.instantiationTimer.start(debug)) {
args.info.instantiationCounter.increment(debug);
// Inline the snippet nodes, replacing parameters with the given args in the process
final FixedNode replaceeGraphPredecessor = (FixedNode) replacee.predecessor();
StartNode entryPointNode = snippet.start();
FixedNode firstCFGNode = entryPointNode.next();
StructuredGraph replaceeGraph = replacee.graph();
EconomicMap<Node, Node> replacements = bind(replaceeGraph, metaAccess, args);
replacements.put(entryPointNode, AbstractBeginNode.prevBegin(replacee));
EconomicMap<Node, Node> duplicates = inlineSnippet(replacee, debug, replaceeGraph, replacements);
// Re-wire the control flow graph around the replacee
FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
replacee.replaceAtPredecessor(firstCFGNodeDuplicate);
if (replacee.graph().getGuardsStage().areFrameStatesAtSideEffects()) {
boolean replaceeHasSideEffect = replacee instanceof StateSplit && ((StateSplit) replacee).hasSideEffect();
boolean replacementHasSideEffect = !sideEffectNodes.isEmpty();
if (replacementHasSideEffect) {
GraalError.guarantee(replaceeHasSideEffect, "Lowering node %s without side-effect to snippet %s with sideeffects=%s", replacee, info, this.sideEffectNodes);
}
}
updateStamps(replacee, duplicates);
rewireMemoryGraph(replacee, duplicates);
rewireFrameStates(replacee, duplicates, replaceeGraphPredecessor);
// Replace all usages of the replacee with the value returned by the snippet
ValueNode returnValue = null;
AbstractBeginNode originalWithExceptionNextNode = null;
if (returnNode != null && !(replacee instanceof ControlSinkNode)) {
ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode);
returnValue = returnDuplicate.result();
if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryKill) {
replacer.replace(replacee, null);
} else {
assert returnValue != null || replacee.hasNoUsages();
replacer.replace(replacee, returnValue);
}
if (returnDuplicate.isAlive()) {
FixedNode next = null;
if (replacee instanceof FixedWithNextNode) {
FixedWithNextNode fwn = (FixedWithNextNode) replacee;
next = fwn.next();
fwn.setNext(null);
} else if (replacee instanceof WithExceptionNode) {
WithExceptionNode withExceptionNode = (WithExceptionNode) replacee;
next = originalWithExceptionNextNode = withExceptionNode.next();
withExceptionNode.setNext(null);
}
returnDuplicate.replaceAndDelete(next);
}
}
if (unwindPath != null && unwindPath.isAlive()) {
GraalError.guarantee(replacee.graph().isBeforeStage(StageFlag.FLOATING_READS) || replacee instanceof WithExceptionNode, "Using a snippet with an UnwindNode after floating reads would require support for the memory graph (unless the replacee has an exception edge)");
GraalError.guarantee(replacee instanceof WithExceptionNode, "Snippet has an UnwindNode, but replacee is not a node with an exception handler");
// snippet exception handler
UnwindNode snippetUnwindDuplicate = (UnwindNode) duplicates.get(unwindPath);
ValueNode snippetExceptionValue = snippetUnwindDuplicate.exception();
FixedWithNextNode snippetUnwindPath = (FixedWithNextNode) snippetUnwindDuplicate.predecessor();
GraalError.guarantee(!(snippetExceptionValue instanceof ExceptionObjectNode) || snippetUnwindPath == snippetExceptionValue, "Snippet unwind predecessor must be the exception object %s: %s", snippetUnwindPath, snippetExceptionValue);
GraalError.guarantee(!(snippetUnwindPath instanceof MergeNode) || snippetExceptionValue instanceof PhiNode, "If the snippet unwind predecessor is a merge node, the exception object must be a phi %s: %s", snippetUnwindPath, snippetExceptionValue);
// replacee exception handler
WithExceptionNode replaceeWithExceptionNode = (WithExceptionNode) replacee;
AbstractBeginNode exceptionEdge = replaceeWithExceptionNode.exceptionEdge();
if (exceptionEdge instanceof ExceptionObjectNode) {
/*
* The exception object node is a begin node, i.e., it can be used as an anchor
* for other nodes, thus we need to re-route them to a valid anchor, i.e. the
* begin node of the unwind block.
*/
GraalError.guarantee(exceptionEdge.usages().filter(x -> x instanceof GuardedNode && ((GuardedNode) x).getGuard() == exceptionEdge).count() == 0, "Must not have guards attached to exception object node %s", exceptionEdge);
replaceeWithExceptionNode.setExceptionEdge(null);
// replace the old exception object with the one
exceptionEdge.replaceAtUsages(snippetExceptionValue);
GraalError.guarantee(originalWithExceptionNextNode != null, "Need to have next node to link placeholder to: %s", replacee);
// replace exceptionEdge with snippetUnwindPath
replaceExceptionObjectNode(exceptionEdge, snippetUnwindPath);
GraphUtil.killCFG(snippetUnwindDuplicate);
} else {
GraalError.guarantee(exceptionEdge instanceof UnreachableBeginNode, "Unexpected exception edge: %s", exceptionEdge);
markExceptionsUnreachable(unwindPath.exception(), duplicates);
}
} else {
/*
* Since the snippet unwindPath is null or has been deleted, a placeholder
* WithExceptionNode needs to be added for any WithExceptionNode replacee. This
* placeholder WithExceptionNode temporarily preserves the replacee's original
* exception edge and is needed because lowering should not remove edges from the
* original CFG.
*/
if (replacee instanceof WithExceptionNode) {
GraalError.guarantee(originalWithExceptionNextNode != null, "Need to have next node to link placeholder to: %s", replacee);
WithExceptionNode newExceptionNode = replacee.graph().add(new PlaceholderWithExceptionNode());
/*
* First attaching placeholder as predecessor of original WithExceptionNode next
* edge.
*/
((FixedWithNextNode) originalWithExceptionNextNode.predecessor()).setNext(newExceptionNode);
newExceptionNode.setNext(originalWithExceptionNextNode);
/* Now connecting exception edge. */
WithExceptionNode oldExceptionNode = (WithExceptionNode) replacee;
AbstractBeginNode exceptionEdge = oldExceptionNode.exceptionEdge();
oldExceptionNode.setExceptionEdge(null);
newExceptionNode.setExceptionEdge(exceptionEdge);
}
}
if (artificialReturnCondition != null) {
((PlaceholderLogicNode) duplicates.get(artificialReturnCondition)).markForDeletion();
}
if (fallbackInvoke != null) {
GraalError.guarantee(replacee instanceof MacroWithExceptionNode, "%s can only be used in snippets replacing %s", FallbackInvokeWithExceptionNode.class.getSimpleName(), MacroWithExceptionNode.class.getSimpleName());
WithExceptionNode fallbackInvokeNode = (WithExceptionNode) duplicates.get(fallbackInvoke);
MacroWithExceptionNode macroNode = (MacroWithExceptionNode) replacee;
// create fallback invoke
InvokeWithExceptionNode invoke = macroNode.createInvoke(returnValue);
// replace placeholder
replaceeGraph.replaceWithExceptionSplit(fallbackInvokeNode, invoke);
// register the invoke as the replacement for the fallback invoke
duplicates.put(fallbackInvoke, invoke);
}
if (killReplacee) {
// Remove the replacee from its graph
GraphUtil.killCFG(replacee);
}
debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
return duplicates;
}
}
Aggregations