use of org.graalvm.compiler.nodes.Invoke 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.Invoke in project graal by oracle.
the class PEGraphDecoder method cleanupGraph.
@Override
protected void cleanupGraph(MethodScope methodScope) {
super.cleanupGraph(methodScope);
for (FrameState frameState : graph.getNodes(FrameState.TYPE)) {
if (frameState.bci == BytecodeFrame.UNWIND_BCI) {
/*
* handleMissingAfterExceptionFrameState is called during graph decoding from
* InliningUtil.processFrameState - but during graph decoding it does not do
* anything because the usages of the frameState are not available yet. So we need
* to call it again.
*/
PEMethodScope peMethodScope = (PEMethodScope) methodScope;
Invoke invoke = peMethodScope.invokeData != null ? peMethodScope.invokeData.invoke : null;
InliningUtil.handleMissingAfterExceptionFrameState(frameState, invoke, null, true);
/*
* The frameState must be gone now, because it is not a valid deoptimization point.
*/
assert frameState.isDeleted();
}
}
}
use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.
the class PEGraphDecoder method doInline.
protected LoopScope doInline(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, InlineInfo inlineInfo, ValueNode[] arguments) {
ResolvedJavaMethod inlineMethod = inlineInfo.getMethodToInline();
EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, inlineInfo.getOriginalMethod(), inlineInfo.getIntrinsicBytecodeProvider(), graph.trackNodeSourcePosition());
if (graphToInline == null) {
return null;
}
assert !graph.trackNodeSourcePosition() || graphToInline.trackNodeSourcePosition() : graph + " " + graphToInline;
if (methodScope.inliningDepth > Options.InliningDepthError.getValue(options)) {
throw tooDeepInlining(methodScope);
}
for (InlineInvokePlugin plugin : inlineInvokePlugins) {
plugin.notifyBeforeInline(inlineMethod);
}
Invoke invoke = invokeData.invoke;
FixedNode invokeNode = invoke.asNode();
FixedWithNextNode predecessor = (FixedWithNextNode) invokeNode.predecessor();
invokeNode.replaceAtPredecessor(null);
PEMethodScope inlineScope = new PEMethodScope(graph, methodScope, loopScope, graphToInline, inlineMethod, invokeData, methodScope.inliningDepth + 1, loopExplosionPlugin, arguments);
if (!inlineMethod.isStatic()) {
if (StampTool.isPointerAlwaysNull(arguments[0])) {
/*
* The receiver is null, so we can unconditionally throw a NullPointerException
* instead of performing any inlining.
*/
DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException));
predecessor.setNext(deoptimizeNode);
finishInlining(inlineScope);
/* Continue decoding in the caller. */
return loopScope;
} else if (!StampTool.isPointerNonNull(arguments[0])) {
/* The receiver might be null, so we need to insert a null check. */
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, predecessor);
arguments[0] = graphBuilderContext.nullCheckedValue(arguments[0]);
predecessor = graphBuilderContext.lastInstr;
}
}
LoopScope inlineLoopScope = createInitialLoopScope(inlineScope, predecessor);
/*
* The GraphEncoder assigns parameters a nodeId immediately after the fixed nodes.
* Initializing createdNodes here avoid decoding and immediately replacing the
* ParameterNodes.
*/
int firstArgumentNodeId = inlineScope.maxFixedNodeOrderId + 1;
for (int i = 0; i < arguments.length; i++) {
inlineLoopScope.createdNodes[firstArgumentNodeId + i] = arguments[i];
}
// Copy assumptions from inlinee to caller
Assumptions assumptions = graph.getAssumptions();
Assumptions inlinedAssumptions = graphToInline.getAssumptions();
if (assumptions != null) {
if (inlinedAssumptions != null) {
assumptions.record(inlinedAssumptions);
}
} else {
assert inlinedAssumptions == null : String.format("cannot inline graph (%s) which makes assumptions into a graph (%s) that doesn't", inlineMethod, graph);
}
// Copy inlined methods from inlinee to caller
List<ResolvedJavaMethod> inlinedMethods = graphToInline.getInlinedMethods();
if (inlinedMethods != null) {
graph.getMethods().addAll(inlinedMethods);
}
if (graphToInline.getFields() != null) {
for (ResolvedJavaField field : graphToInline.getFields()) {
graph.recordField(field);
}
}
if (graphToInline.hasUnsafeAccess()) {
graph.markUnsafeAccess();
}
/*
* Do the actual inlining by returning the initial loop scope for the inlined method scope.
*/
return inlineLoopScope;
}
use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.
the class CompileQueue method doInlineTrivial.
@SuppressWarnings("try")
private void doInlineTrivial(DebugContext debug, final HostedMethod method) {
/*
* Make a copy of the graph to avoid concurrency problems. Graph manipulations are not
* thread safe, and another thread can concurrently inline this method.
*/
final StructuredGraph graph = (StructuredGraph) method.compilationInfo.getGraph().copy(debug);
try (DebugContext.Scope s = debug.scope("InlineTrivial", graph, method, this)) {
try {
try (Indent in = debug.logAndIndent("do inline trivial in %s", method)) {
boolean inlined = false;
for (Invoke invoke : graph.getInvokes()) {
if (invoke.useForInlining()) {
inlined |= tryInlineTrivial(graph, invoke, !inlined);
}
}
if (inlined) {
Providers providers = runtimeConfig.lookupBackend(method).getProviders();
new CanonicalizerPhase().apply(graph, new PhaseContext(providers));
/*
* Publish the new graph, it can be picked up immediately by other threads
* trying to inline this method.
*/
method.compilationInfo.setGraph(graph);
checkTrivial(method);
inliningProgress = true;
}
}
} catch (Throwable ex) {
GraalError error = ex instanceof GraalError ? (GraalError) ex : new GraalError(ex);
error.addContext("method: " + method.format("%r %H.%n(%p)"));
throw error;
}
} catch (Throwable e) {
throw debug.handle(e);
}
}
use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.
the class BytecodeParser method genInvokeStatic.
void genInvokeStatic(JavaMethod target) {
if (callTargetIsResolved(target)) {
ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target;
ResolvedJavaType holder = resolvedTarget.getDeclaringClass();
if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue(options)) {
handleUnresolvedInvoke(target, InvokeKind.Static);
} else {
ValueNode classInit = null;
ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedTarget.getDeclaringClass())) {
FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
classInit = classInitializationPlugin.apply(this, resolvedTarget.getDeclaringClass(), stateBefore);
}
ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterCount(false));
Invoke invoke = appendInvoke(InvokeKind.Static, resolvedTarget, args);
if (invoke != null) {
invoke.setClassInit(classInit);
}
}
} else {
handleUnresolvedInvoke(target, InvokeKind.Static);
}
}
Aggregations