use of com.oracle.svm.core.graal.nodes.LoweredDeadEndNode in project graal by oracle.
the class OptimizeExceptionPathsPhase method run.
@Override
protected void run(StructuredGraph graph) {
/*
* First walk back from all exceptional control flow sinks to a control flow split that also
* goes to a "regular" return.
*/
NodeBitMap exceptionPaths = new NodeBitMap(graph);
for (UnwindNode unwind : graph.getNodes(UnwindNode.TYPE)) {
walkBack(unwind, exceptionPaths);
}
for (DeadEndNode deadEnd : graph.getNodes(DeadEndNode.TYPE)) {
walkBack(deadEnd, exceptionPaths);
}
for (LoweredDeadEndNode deadEnd : graph.getNodes(LoweredDeadEndNode.TYPE)) {
walkBack(deadEnd, exceptionPaths);
}
/* Now that we know all control flow splits, we modify the branch probabilities. */
for (Node n : exceptionPaths) {
AbstractBeginNode exceptionBegin = (AbstractBeginNode) n;
ControlSplitNode controlSplitNode = (ControlSplitNode) exceptionBegin.predecessor();
/*
* Only overwrite the branch probability if it comes from non-profiled sources. If we
* have proper PGO information that the exception edge is used, it deserves to be
* optimized.
*/
if (controlSplitNode.getProfileData().getProfileSource() != ProfileData.ProfileSource.PROFILED) {
controlSplitNode.setProbability(exceptionBegin, BranchProbabilityNode.EXTREMELY_SLOW_PATH_PROFILE);
}
}
}
use of com.oracle.svm.core.graal.nodes.LoweredDeadEndNode in project graal by oracle.
the class HostedBciBlockMapping method insertDeoptNode.
/**
* Inserts either a DeoptEntryNode or DeoptProxyAnchorNode into the graph.
*/
private void insertDeoptNode(HostedBciBlockMapping.DeoptEntryInsertionPoint deopt) {
/* Ensuring current frameState matches the expectations of the DeoptEntryInsertionPoint. */
if (deopt instanceof HostedBciBlockMapping.DeoptBciBlock) {
assert !frameState.rethrowException();
} else {
assert deopt instanceof HostedBciBlockMapping.DeoptExceptionDispatchBlock;
assert frameState.rethrowException();
}
DeoptEntrySupport deoptNode = graph.add(deopt.isProxy() ? new DeoptProxyAnchorNode() : new DeoptEntryNode());
FrameState stateAfter = frameState.create(deopt.frameStateBci(), deoptNode);
deoptNode.setStateAfter(stateAfter);
if (lastInstr != null) {
lastInstr.setNext(deoptNode.asFixedNode());
}
if (deopt.isProxy()) {
lastInstr = (DeoptProxyAnchorNode) deoptNode;
} else {
assert !deopt.duringCall() : "Implicit deopt entries from invokes cannot have explicit deopt entries.";
DeoptEntryNode deoptEntryNode = (DeoptEntryNode) deoptNode;
deoptEntryNode.setNext(graph.add(new DeoptEntryBeginNode()));
/*
* DeoptEntries for positions not during an exception dispatch (rethrowException) also
* must be linked to their exception target.
*/
if (!deopt.rethrowException()) {
/*
* Saving frameState so that different modifications can be made for next() and
* exceptionEdge().
*/
FrameStateBuilder originalFrameState = frameState.copy();
/* Creating exception object and its state after. */
ExceptionObjectNode newExceptionObject = graph.add(new ExceptionObjectNode(getMetaAccess()));
frameState.clearStack();
frameState.push(JavaKind.Object, newExceptionObject);
frameState.setRethrowException(true);
int bci = ((HostedBciBlockMapping.DeoptBciBlock) deopt).getStartBci();
newExceptionObject.setStateAfter(frameState.create(bci, newExceptionObject));
deoptEntryNode.setExceptionEdge(newExceptionObject);
/* Inserting proxies for the exception edge. */
insertProxies(newExceptionObject, frameState);
/* Linking exception object to exception target. */
newExceptionObject.setNext(handleException(newExceptionObject, bci, false));
/* Now restoring FrameState so proxies can be inserted for the next() edge. */
frameState = originalFrameState;
} else {
/* Otherwise, indicate that the exception edge is not reachable. */
AbstractBeginNode newExceptionEdge = graph.add(new UnreachableBeginNode());
newExceptionEdge.setNext(graph.add(new LoweredDeadEndNode()));
deoptEntryNode.setExceptionEdge(newExceptionEdge);
}
/* Correctly setting last instruction. */
lastInstr = deoptEntryNode.next();
}
insertProxies(deoptNode.asFixedNode(), frameState);
}
use of com.oracle.svm.core.graal.nodes.LoweredDeadEndNode in project graal by oracle.
the class CEntryPointSupport method registerEntryPointActionsPlugins.
private static void registerEntryPointActionsPlugins(InvocationPlugins plugins) {
Registration r = new Registration(plugins, CEntryPointActions.class);
r.register(new RequiredInvocationPlugin("enterCreateIsolate", CEntryPointCreateIsolateParameters.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode parameters) {
b.addPush(JavaKind.Int, CEntryPointEnterNode.createIsolate(parameters));
return true;
}
});
r.register(new RequiredInvocationPlugin("enterAttachThread", Isolate.class, boolean.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode isolate, ValueNode ensureJavaThreadNode) {
if (!ensureJavaThreadNode.isConstant()) {
b.bailout("Parameter ensureJavaThread of enterAttachThread must be a compile time constant");
}
b.addPush(JavaKind.Int, CEntryPointEnterNode.attachThread(isolate, ensureJavaThreadNode.asJavaConstant().asInt() != 0, false));
return true;
}
});
r.register(new RequiredInvocationPlugin("enter", IsolateThread.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode thread) {
b.addPush(JavaKind.Int, CEntryPointEnterNode.enter(thread));
return true;
}
});
r.register(new RequiredInvocationPlugin("enterIsolate", Isolate.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode isolate) {
b.addPush(JavaKind.Int, CEntryPointEnterNode.enterIsolate(isolate));
return true;
}
});
r.register(new RequiredInvocationPlugin("enterAttachThreadFromCrashHandler", Isolate.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode isolate) {
b.addPush(JavaKind.Int, CEntryPointEnterNode.attachThread(isolate, false, true));
return true;
}
});
r.register(new RequiredInvocationPlugin("leave") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
StateSplitProxyNode proxy = new StateSplitProxyNode(null);
b.add(proxy);
b.setStateAfter(proxy);
b.addPush(JavaKind.Int, new CEntryPointLeaveNode(LeaveAction.Leave));
return true;
}
});
r.register(new RequiredInvocationPlugin("leaveDetachThread") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
StateSplitProxyNode proxy = new StateSplitProxyNode(null);
b.add(proxy);
b.setStateAfter(proxy);
b.addPush(JavaKind.Int, new CEntryPointLeaveNode(LeaveAction.DetachThread));
return true;
}
});
r.register(new RequiredInvocationPlugin("leaveTearDownIsolate") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
StateSplitProxyNode proxy = new StateSplitProxyNode(null);
b.add(proxy);
b.setStateAfter(proxy);
b.addPush(JavaKind.Int, new CEntryPointLeaveNode(LeaveAction.TearDownIsolate));
return true;
}
});
r.register(new RequiredInvocationPlugin("failFatally", int.class, CCharPointer.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) {
b.add(new CEntryPointUtilityNode(UtilityAction.FailFatally, arg1, arg2));
/*
* FailFatally does not return, so we can cut out any control flow afterwards and
* set the probability of the IfNode that leads to this branch.
*/
LoweredDeadEndNode deadEndNode = b.add(new LoweredDeadEndNode());
AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(deadEndNode);
if (prevBegin != null && prevBegin.predecessor() instanceof IfNode) {
((IfNode) prevBegin.predecessor()).setProbability(prevBegin, BranchProbabilityNode.EXTREMELY_SLOW_PATH_PROFILE);
}
return true;
}
});
r.register(new RequiredInvocationPlugin("isCurrentThreadAttachedTo", Isolate.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode isolate) {
b.addPush(JavaKind.Boolean, new CEntryPointUtilityNode(UtilityAction.IsAttached, isolate));
return true;
}
});
}
use of com.oracle.svm.core.graal.nodes.LoweredDeadEndNode in project graal by oracle.
the class GraphPrepareMetaAccessExtensionProvider method registerDeoptEntries.
private static void registerDeoptEntries(CallTreeNode node) {
for (FrameState frameState : node.graph.getNodes(FrameState.TYPE)) {
if (frameState.hasExactlyOneUsage()) {
Node usage = frameState.usages().first();
if (node.level > 0 && usage == node.graph.start()) {
/*
* During method inlining, the FrameState associated with the StartNode
* disappears. Therefore, this frame state cannot be a deoptimization target.
*/
continue;
} else if (usage instanceof Invoke && ((Invoke) usage).stateAfter() == frameState) {
/*
* If the FrameState is followed immediately by a dead end, then this state can
* never be reached and does not need to be registered.
*/
FixedNode next = ((Invoke) usage).next();
while (next instanceof AbstractBeginNode) {
next = ((AbstractBeginNode) next).next();
}
if (next instanceof LoweredDeadEndNode) {
continue;
}
}
}
/*
* We need to make sure that all inlined caller frames are available for deoptimization
* too.
*/
for (FrameState inlineState = frameState; inlineState != null; inlineState = inlineState.outerFrameState()) {
if (inlineState.bci >= 0) {
CompilationInfoSupport.singleton().registerDeoptEntry(inlineState);
}
}
}
for (Node n : node.graph.getNodes()) {
/*
* graph.getInvokes() only iterates invokes that have a MethodCallTarget, so by using it
* we would miss invocations that are already intrinsified to an indirect call.
*/
if (n instanceof Invoke) {
Invoke invoke = (Invoke) n;
/*
* The FrameState for the invoke (which is visited by the above loop) is the state
* after the call (where deoptimization that happens after the call has returned
* will continue execution). We also need to register the state during the call
* (where deoptimization while the call is on the stack will continue execution).
*
* Note that the bci of the Invoke and the bci of the FrameState of the Invoke are
* different: the Invoke has the bci of the invocation bytecode, the FrameState has
* the bci of the next bytecode after the invoke.
*/
FrameState stateDuring = invoke.stateAfter().duplicateModifiedDuringCall(invoke.bci(), invoke.asNode().getStackKind());
assert stateDuring.duringCall() && !stateDuring.rethrowException();
CompilationInfoSupport.singleton().registerDeoptEntry(stateDuring);
}
}
}
use of com.oracle.svm.core.graal.nodes.LoweredDeadEndNode in project graal by oracle.
the class ReflectionGraphKit method emitInvocationTargetException.
public void emitInvocationTargetException() {
AbstractMergeNode merge = continueWithMerge(invocationTargetExceptionPaths);
ValueNode exception = createPhi(invocationTargetExceptionPaths, merge);
ResolvedJavaMethod throwInvocationTargetException = FactoryMethodSupport.singleton().lookup((UniverseMetaAccess) getMetaAccess(), getMetaAccess().lookupJavaMethod(invocationTargetExceptionConstructor), true);
createJavaCallWithExceptionAndUnwind(CallTargetNode.InvokeKind.Static, throwInvocationTargetException, exception);
append(new LoweredDeadEndNode());
}
Aggregations