use of org.graalvm.compiler.nodes.UnreachableBeginNode in project graal by oracle.
the class PlaceholderLogicNode method verifyWithExceptionNode.
/**
* Verifies that a {@link WithExceptionNode} has only memory usages via the
* {@link WithExceptionNode#next()} edge. On the {@link WithExceptionNode#exceptionEdge()} there
* must be a {@link MemoryKill} (or an {@link UnreachableBeginNode}), otherwise we would not
* know from which edge a memory usage is coming from.
*/
private static void verifyWithExceptionNode(ValueNode node) {
if (node instanceof WithExceptionNode && node instanceof MemoryKill) {
WithExceptionNode withExceptionNode = (WithExceptionNode) node;
AbstractBeginNode exceptionEdge = withExceptionNode.exceptionEdge();
if (exceptionEdge instanceof UnreachableBeginNode) {
// exception edge is unreachable - we are good
return;
}
GraalError.guarantee(exceptionEdge instanceof MemoryKill, "The exception edge of %s is not a memory kill %s", node, exceptionEdge);
if (exceptionEdge instanceof SingleMemoryKill) {
SingleMemoryKill exceptionEdgeKill = (SingleMemoryKill) exceptionEdge;
if (exceptionEdgeKill.getKilledLocationIdentity().isAny()) {
// exception edge kills any - we are good
return;
}
// if the exception edge does not kill any, it must kill the same location
GraalError.guarantee(withExceptionNode instanceof SingleMemoryKill, "Not a single memory kill: %s", withExceptionNode);
SingleMemoryKill withExceptionKill = (SingleMemoryKill) withExceptionNode;
GraalError.guarantee(withExceptionKill.getKilledLocationIdentity().equals(exceptionEdgeKill.getKilledLocationIdentity()), "Kill locations do not match: %s (%s) vs %s (%s)", withExceptionKill, withExceptionKill.getKilledLocationIdentity(), exceptionEdgeKill, exceptionEdgeKill.getKilledLocationIdentity());
} else if (exceptionEdge instanceof MultiMemoryKill) {
// for multi memory kills the locations must match
MultiMemoryKill exceptionEdgeKill = (MultiMemoryKill) exceptionEdge;
GraalError.guarantee(withExceptionNode instanceof MultiMemoryKill, "Not a single memory kill: %s", withExceptionNode);
MultiMemoryKill withExceptionKill = (MultiMemoryKill) withExceptionNode;
GraalError.guarantee(Arrays.equals(withExceptionKill.getKilledLocationIdentities(), exceptionEdgeKill.getKilledLocationIdentities()), "Kill locations do not match: %s (%s) vs %s (%s)", withExceptionKill, withExceptionKill.getKilledLocationIdentities(), exceptionEdgeKill, exceptionEdgeKill.getKilledLocationIdentities());
} else {
GraalError.shouldNotReachHere("Unexpected exception edge: " + exceptionEdge);
}
}
}
use of org.graalvm.compiler.nodes.UnreachableBeginNode in project graal by oracle.
the class DeoptEntryNode method generate.
@Override
public void generate(NodeLIRBuilderTool gen) {
LabelRef exceptionRef;
AbstractBeginNode exceptionNode = exceptionEdge();
if (exceptionNode instanceof UnreachableBeginNode) {
exceptionRef = null;
} else {
/* Only register exception handler if it is meaningful. */
exceptionRef = ((NodeLIRBuilder) gen).getLIRBlock(exceptionNode);
}
gen.getLIRGeneratorTool().append(new DeoptEntryOp(((NodeLIRBuilder) gen).stateForWithExceptionEdge(this, stateAfter(), exceptionRef)));
/* Link to next() instruction. */
gen.getLIRGeneratorTool().emitJump(((NodeLIRBuilder) gen).getLIRBlock(next()));
}
use of org.graalvm.compiler.nodes.UnreachableBeginNode 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 org.graalvm.compiler.nodes.UnreachableBeginNode in project graal by oracle.
the class ForeignCallWithExceptionNode method simplify.
@Override
public void simplify(SimplifierTool tool) {
if (exceptionEdge instanceof UnreachableBeginNode) {
FixedNode replacement = replaceWithNonThrowing();
tool.addToWorkList(replacement);
}
}
use of org.graalvm.compiler.nodes.UnreachableBeginNode in project graal by oracle.
the class PlaceholderLogicNode method rewireFrameStatesAfterFSA.
private void rewireFrameStatesAfterFSA(ValueNode replacee, UnmodifiableEconomicMap<Node, Node> duplicates) {
DeoptimizingNode replaceeDeopt = (DeoptimizingNode) replacee;
GraalError.guarantee(replaceeDeopt.canDeoptimize(), "Method expects the replacee to have deopt state");
FrameState stateBefore = null;
FrameState stateDuring = null;
FrameState stateAfter = null;
if (replaceeDeopt instanceof DeoptimizingNode.DeoptBefore) {
stateBefore = ((DeoptimizingNode.DeoptBefore) replaceeDeopt).stateBefore();
}
if (replaceeDeopt instanceof DeoptimizingNode.DeoptDuring) {
stateDuring = ((DeoptimizingNode.DeoptDuring) replaceeDeopt).stateDuring();
}
if (replaceeDeopt instanceof DeoptimizingNode.DeoptAfter) {
stateAfter = ((DeoptimizingNode.DeoptAfter) replaceeDeopt).stateAfter();
}
if (stateAfter == null && stateDuring == null && stateBefore == null) {
/*
* There should only be no state available to transfer during testing or if the
* replacee's graph itself is a substitution.
*/
StructuredGraph graph = replacee.graph();
boolean condition = graph.isStateAfterClearedForTesting() || graph.isSubstitution();
GraalError.guarantee(condition, "No state available to transfer");
return;
}
final ExceptionObjectNode exceptionObject;
if (replacee instanceof WithExceptionNode) {
WithExceptionNode withExceptionNode = (WithExceptionNode) replacee;
if (withExceptionNode.exceptionEdge() instanceof ExceptionObjectNode) {
exceptionObject = (ExceptionObjectNode) withExceptionNode.exceptionEdge();
} else {
GraalError.guarantee(withExceptionNode.exceptionEdge() instanceof UnreachableBeginNode, "Unexpected exception edge %s", withExceptionNode.exceptionEdge());
exceptionObject = null;
}
} else {
exceptionObject = null;
}
for (DeoptimizingNode deoptNode : deoptNodes) {
DeoptimizingNode deoptDup = (DeoptimizingNode) duplicates.get(deoptNode.asNode());
if (deoptDup.canDeoptimize()) {
if (deoptDup instanceof ExceptionObjectNode) {
ExceptionObjectNode newExceptionObject = (ExceptionObjectNode) deoptDup;
rewireExceptionFrameState(exceptionObject, newExceptionObject, newExceptionObject);
continue;
}
if (deoptDup instanceof DeoptimizingNode.DeoptBefore) {
GraalError.guarantee(stateBefore != null, "Invalid stateBefore being transferred.");
((DeoptimizingNode.DeoptBefore) deoptDup).setStateBefore(stateBefore);
}
if (deoptDup instanceof DeoptimizingNode.DeoptDuring) {
// compute a state "during" for a DeoptDuring inside the snippet depending
// on what kind of states we had on the node we are replacing.
// If the original node had a state "during" already, we just use that,
// otherwise we need to find a strategy to compute a state during based on
// some other state (before or after).
DeoptimizingNode.DeoptDuring deoptDupDuring = (DeoptimizingNode.DeoptDuring) deoptDup;
if (stateDuring != null) {
deoptDupDuring.setStateDuring(stateDuring);
} else if (stateAfter != null) {
deoptDupDuring.computeStateDuring(stateAfter);
} else if (stateBefore != null) {
boolean guarantee = ((DeoptBefore) replaceeDeopt).canUseAsStateDuring() || !deoptDupDuring.hasSideEffect();
GraalError.guarantee(guarantee, "Can't use stateBefore as stateDuring for state split %s", deoptDupDuring);
deoptDupDuring.setStateDuring(stateBefore);
} else {
throw GraalError.shouldNotReachHere("No stateDuring assigned.");
}
}
if (deoptDup instanceof DeoptimizingNode.DeoptAfter) {
DeoptimizingNode.DeoptAfter deoptDupAfter = (DeoptimizingNode.DeoptAfter) deoptDup;
if (stateAfter != null) {
deoptDupAfter.setStateAfter(stateAfter);
} else {
boolean guarantee = stateBefore != null && !deoptDupAfter.hasSideEffect();
GraalError.guarantee(guarantee, "Can't use stateBefore as stateAfter for state split %s", deoptDupAfter);
deoptDupAfter.setStateAfter(stateBefore);
}
}
}
}
}
Aggregations