use of org.graalvm.compiler.nodes.InvokeWithExceptionNode in project graal by oracle.
the class PEGraphDecoder method ensureExceptionStateDecoded.
protected void ensureExceptionStateDecoded(PEMethodScope methodScope) {
if (methodScope.exceptionState == null && methodScope.caller != null && methodScope.invokeData.invoke instanceof InvokeWithExceptionNode) {
ensureStateAfterDecoded(methodScope);
assert methodScope.exceptionPlaceholderNode == null;
methodScope.exceptionPlaceholderNode = graph.add(new ExceptionPlaceholderNode());
registerNode(methodScope.callerLoopScope, methodScope.invokeData.exceptionOrderId, methodScope.exceptionPlaceholderNode, false, false);
FrameState exceptionState = (FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.exceptionStateOrderId);
if (exceptionState.outerFrameState() == null && methodScope.caller != null) {
ensureOuterStateDecoded(methodScope.caller);
exceptionState.setOuterFrameState(methodScope.caller.outerState);
}
methodScope.exceptionState = exceptionState;
}
}
use of org.graalvm.compiler.nodes.InvokeWithExceptionNode 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.asNode();
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));
}
}
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();
FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, AbstractBeginNode.prevBegin(returnNode));
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, merge);
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);
for (InlineInvokePlugin plugin : inlineInvokePlugins) {
plugin.notifyAfterInline(inlineMethod);
}
}
use of org.graalvm.compiler.nodes.InvokeWithExceptionNode in project graal by oracle.
the class PEGraphDecoder method nodeAfterInvoke.
public FixedNode nodeAfterInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, AbstractBeginNode lastBlock) {
assert lastBlock.isAlive();
FixedNode n;
if (invokeData.invoke instanceof InvokeWithExceptionNode) {
registerNode(loopScope, invokeData.nextOrderId, lastBlock, false, false);
n = makeStubNode(methodScope, loopScope, invokeData.nextNextOrderId);
} else {
n = makeStubNode(methodScope, loopScope, invokeData.nextOrderId);
}
return n;
}
use of org.graalvm.compiler.nodes.InvokeWithExceptionNode in project graal by oracle.
the class CEntryPointCallStubMethod method generateExceptionHandler.
private void generateExceptionHandler(HostedProviders providers, SubstrateGraphKit kit, ExceptionObjectNode exception, JavaKind returnKind) {
if (entryPointData.getExceptionHandler() == CEntryPointOptions.FatalExceptionHandler.class) {
kit.append(new CEntryPointLeaveNode(LeaveAction.ExceptionAbort, exception));
kit.append(new DeadEndNode());
} else {
ResolvedJavaType throwable = providers.getMetaAccess().lookupJavaType(Throwable.class);
ResolvedJavaType handler = providers.getMetaAccess().lookupJavaType(entryPointData.getExceptionHandler());
ResolvedJavaMethod[] handlerMethods = handler.getDeclaredMethods();
UserError.guarantee(handlerMethods.length == 1 && handlerMethods[0].isStatic(), "Exception handler class must declare exactly one static method: " + targetMethod.format("%H.%n(%p)") + " -> " + handler.toJavaName());
JavaType[] handlerParameterTypes = handlerMethods[0].toParameterTypes();
UserError.guarantee(handlerParameterTypes.length == 1 && ((ResolvedJavaType) handlerParameterTypes[0]).isAssignableFrom(throwable), "Exception handler method must have exactly one parameter of type Throwable: " + targetMethod.format("%H.%n(%p)") + " -> " + handlerMethods[0].format("%H.%n(%p)"));
int handlerExceptionBci = kit.bci();
InvokeWithExceptionNode handlerInvoke = kit.startInvokeWithException(handlerMethods[0], InvokeKind.Static, kit.getFrameState(), kit.bci(), handlerExceptionBci, exception);
kit.noExceptionPart();
ValueNode returnValue = handlerInvoke;
if (handlerInvoke.getStackKind() != returnKind) {
JavaKind fromKind = handlerInvoke.getStackKind();
if (fromKind == JavaKind.Float && returnKind == JavaKind.Double) {
returnValue = kit.unique(new FloatConvertNode(FloatConvert.F2D, returnValue));
} else if (fromKind.isUnsigned() && returnKind.isNumericInteger() && returnKind.getBitCount() > fromKind.getBitCount()) {
returnValue = kit.unique(new ZeroExtendNode(returnValue, returnKind.getBitCount()));
} else if (fromKind.isNumericInteger() && returnKind.isNumericInteger() && returnKind.getBitCount() > fromKind.getBitCount()) {
returnValue = kit.unique(new SignExtendNode(returnValue, returnKind.getBitCount()));
} else {
throw UserError.abort("Exception handler method return type must be assignable to entry point method return type: " + targetMethod.format("%H.%n(%p)") + " -> " + handlerMethods[0].format("%H.%n(%p)"));
}
}
kit.createReturn(returnValue, returnValue.getStackKind());
// fail-safe for exceptions in exception handler
kit.exceptionPart();
kit.append(new CEntryPointLeaveNode(LeaveAction.ExceptionAbort, kit.exceptionObject()));
kit.append(new DeadEndNode());
kit.endInvokeWithException();
}
}
use of org.graalvm.compiler.nodes.InvokeWithExceptionNode in project graal by oracle.
the class NodeLIRBuilder method emitInvoke.
@Override
public void emitInvoke(Invoke x) {
LoweredCallTargetNode callTarget = (LoweredCallTargetNode) x.callTarget();
FrameMapBuilder frameMapBuilder = gen.getResult().getFrameMapBuilder();
CallingConvention invokeCc = frameMapBuilder.getRegisterConfig().getCallingConvention(callTarget.callType(), x.asNode().stamp(NodeView.DEFAULT).javaType(gen.getMetaAccess()), callTarget.signature(), gen);
frameMapBuilder.callsMethod(invokeCc);
Value[] parameters = visitInvokeArguments(invokeCc, callTarget.arguments());
LabelRef exceptionEdge = null;
if (x instanceof InvokeWithExceptionNode) {
exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge());
}
LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge);
Value result = invokeCc.getReturn();
if (callTarget instanceof DirectCallTargetNode) {
emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState);
} else if (callTarget instanceof IndirectCallTargetNode) {
emitIndirectCall((IndirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState);
} else {
throw GraalError.shouldNotReachHere();
}
if (isLegal(result)) {
setResult(x.asNode(), gen.emitMove(result));
}
if (x instanceof InvokeWithExceptionNode) {
gen.emitJump(getLIRBlock(((InvokeWithExceptionNode) x).next()));
}
}
Aggregations