use of org.graalvm.compiler.nodeinfo.InputType.Anchor in project graal by oracle.
the class PEGraphDecoder method finishInlining.
@Override
protected void finishInlining(MethodScope is) {
PEMethodScope inlineScope = (PEMethodScope) is;
ResolvedJavaMethod inlineMethod = inlineScope.method;
PEMethodScope methodScope = inlineScope.caller;
LoopScope loopScope = inlineScope.callerLoopScope;
InvokeData invokeData = inlineScope.invokeData;
Invoke invoke = invokeData.invoke;
FixedNode invokeNode = invoke.asFixedNode();
ValueNode exceptionValue = null;
int returnNodeCount = 0;
int unwindNodeCount = 0;
List<ControlSinkNode> returnAndUnwindNodes = inlineScope.returnAndUnwindNodes;
for (int i = 0; i < returnAndUnwindNodes.size(); i++) {
FixedNode fixedNode = returnAndUnwindNodes.get(i);
if (fixedNode instanceof ReturnNode) {
returnNodeCount++;
} else if (fixedNode.isAlive()) {
assert fixedNode instanceof UnwindNode;
unwindNodeCount++;
}
}
if (unwindNodeCount > 0) {
FixedNode unwindReplacement;
if (invoke instanceof InvokeWithExceptionNode) {
/* Decoding continues for the exception handler. */
unwindReplacement = makeStubNode(methodScope, loopScope, invokeData.exceptionNextOrderId);
} else {
/* No exception handler available, so the only thing we can do is deoptimize. */
unwindReplacement = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
}
if (unwindNodeCount == 1) {
/* Only one UnwindNode, we can use the exception directly. */
UnwindNode unwindNode = getSingleMatchingNode(returnAndUnwindNodes, returnNodeCount > 0, UnwindNode.class);
exceptionValue = unwindNode.exception();
unwindNode.replaceAndDelete(unwindReplacement);
} else {
/*
* More than one UnwindNode. This can happen with the loop explosion strategy
* FULL_EXPLODE_UNTIL_RETURN, where we keep exploding after the loop and therefore
* also explode exception paths. Merge the exception in a similar way as multiple
* return values.
*/
MergeNode unwindMergeNode = graph.add(new MergeNode());
exceptionValue = InliningUtil.mergeValueProducers(unwindMergeNode, getMatchingNodes(returnAndUnwindNodes, returnNodeCount > 0, UnwindNode.class, unwindNodeCount), null, unwindNode -> unwindNode.exception());
unwindMergeNode.setNext(unwindReplacement);
ensureExceptionStateDecoded(inlineScope);
unwindMergeNode.setStateAfter(inlineScope.exceptionState.duplicateModified(JavaKind.Object, JavaKind.Object, exceptionValue, null));
}
if (invoke instanceof InvokeWithExceptionNode) {
/*
* Exceptionobject nodes are begin nodes, i.e., they can be used as guards/anchors
* thus we need to ensure nodes decoded later have a correct guarding/anchoring node
* in place, i.e., the exception value must be a node that can be used like the
* original node as value, guard and anchor.
*
* The node unwindReplacement is a stub, its not yet processed thus we insert our
* artificial anchor before it.
*/
assert unwindReplacement != exceptionValue : "Unschedulable unwind replacement";
FixedAnchorNode anchor = graph.add(new FixedAnchorNode(exceptionValue));
graph.addBeforeFixed(unwindReplacement, anchor);
exceptionValue = anchor;
assert anchor.predecessor() != null;
}
}
assert invoke.next() == null;
assert !(invoke instanceof InvokeWithExceptionNode) || ((InvokeWithExceptionNode) invoke).exceptionEdge() == null;
ValueNode returnValue;
if (returnNodeCount == 0) {
returnValue = null;
} else if (returnNodeCount == 1) {
ReturnNode returnNode = getSingleMatchingNode(returnAndUnwindNodes, unwindNodeCount > 0, ReturnNode.class);
returnValue = returnNode.result();
BeginNode prevBegin = null;
if (returnNode.predecessor() instanceof BeginNode) {
// Try to reuse the previous begin node instead of creating another one.
prevBegin = (BeginNode) returnNode.predecessor();
}
FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, prevBegin);
if (n == prevBegin) {
// Reusing the previous BeginNode; just remove the ReturnNode.
returnNode.replaceAtPredecessor(null);
returnNode.safeDelete();
} else {
returnNode.replaceAndDelete(n);
}
} else {
AbstractMergeNode merge = graph.add(new MergeNode());
merge.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, invokeData.stateAfterOrderId));
returnValue = InliningUtil.mergeReturns(merge, getMatchingNodes(returnAndUnwindNodes, unwindNodeCount > 0, ReturnNode.class, returnNodeCount));
FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, null);
merge.setNext(n);
}
invokeNode.replaceAtUsages(returnValue);
/*
* Usage the handles that we have on the return value and the exception to update the
* orderId->Node table.
*/
registerNode(loopScope, invokeData.invokeOrderId, returnValue, true, true);
if (invoke instanceof InvokeWithExceptionNode) {
registerNode(loopScope, invokeData.exceptionOrderId, exceptionValue, true, true);
}
if (inlineScope.exceptionPlaceholderNode != null) {
inlineScope.exceptionPlaceholderNode.replaceAtUsagesAndDelete(exceptionValue);
}
deleteInvoke(invoke);
assert exceptionValue == null || exceptionValue instanceof FixedAnchorNode && exceptionValue.predecessor() != null;
for (InlineInvokePlugin plugin : inlineInvokePlugins) {
plugin.notifyAfterInline(inlineMethod);
}
}
Aggregations