use of com.oracle.svm.core.graal.nodes.DeoptEntryNode in project graal by oracle.
the class HostedBytecodeParser method parseAndInlineCallee.
@Override
protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) {
assert calleeIntrinsicContext != null : "only inlining replacements";
if (getMethod().compilationInfo.isDeoptEntry(bci(), false, false)) {
/*
* Replacements use the frame state before the invoke for all nodes that need a state,
* i.e., we want to re-execute the whole replacement in case of deoptimization.
* Therefore, we need to register a DeoptEntryNode before inlining the replacement. The
* frame state used for the DeoptEntryNode needs to be the same state that will be used
* later on in the intrinsic.
*/
FrameState stateAfter = frameState.create(bci(), getNonIntrinsicAncestor(), false, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args);
long encodedBci = FrameInfoEncoder.encodeBci(stateAfter.bci, stateAfter.duringCall(), stateAfter.rethrowException());
if (!deoptEntries.containsKey(encodedBci)) {
DeoptEntryNode deoptEntry = graph.add(new DeoptEntryNode());
deoptEntry.setStateAfter(stateAfter);
insertProxies(deoptEntry, frameState);
lastInstr.setNext(deoptEntry);
lastInstr = deoptEntry;
for (int i = 0; i < args.length; i++) {
args[i] = createProxyNode(args[i], deoptEntry);
}
}
/*
* Ensure that no one registers a later state (after the replacement) with the same
* frame state.
*/
deoptEntries.put(encodedBci, STICKY_DEOPT_ENTRY);
}
super.parseAndInlineCallee(targetMethod, args, calleeIntrinsicContext);
}
use of com.oracle.svm.core.graal.nodes.DeoptEntryNode in project graal by oracle.
the class HostedBytecodeParser method finishInstruction.
/**
* Insert deopt entries after all state splits.
*/
@Override
protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, FrameStateBuilder stateBuilder) {
if (getMethod().compilationInfo.isDeoptTarget() && !parsingIntrinsic()) {
FrameState stateAfter = null;
if (instr instanceof StateSplit && !(instr instanceof DeoptEntryNode)) {
/*
* The regular case: the instruction is a state split and we insert a DeoptEntryNode
* right after it.
*/
StateSplit stateSplit = (StateSplit) instr;
stateAfter = stateSplit.stateAfter();
} else if (instr instanceof AbstractBeginNode) {
/*
* We are at a block begin. If the block predecessor is a LoopExitNode or an
* InvokeWithException (both are state splits), we didn't inserted a deopt entry
* yet. So we do it at the begin of a block.
*
* Note that this only happens if the LoopExitNode/InvokeWithException is the
* _single_ predcessor of this block. In case of multiple predecessors, the block
* starts with a MergeNode and this is handled like a regular case.
*/
Node predecessor = instr.predecessor();
if (predecessor instanceof KillingBeginNode) {
/*
* This is between an InvokeWithException and the BlockPlaceholderNode.
*/
predecessor = predecessor.predecessor();
}
if (predecessor instanceof StateSplit && !(predecessor instanceof DeoptEntryNode)) {
stateAfter = ((StateSplit) predecessor).stateAfter();
}
}
boolean needsDeoptEntry = false;
boolean needsProxies = false;
if (stateAfter != null) {
if (getMethod().compilationInfo.isDeoptEntry(stateAfter.bci, stateAfter.duringCall(), stateAfter.rethrowException())) {
needsDeoptEntry = true;
needsProxies = true;
} else if (instr.predecessor() instanceof Invoke && getMethod().compilationInfo.isDeoptEntry(((Invoke) instr.predecessor()).bci(), true, false)) {
/*
* Invoke nodes can be implicit deoptimization entry points. But we cannot
* anchor proxy nodes on invocations: The invoke has two successors (normal and
* exception handler), and we need to proxy values at the beginning of both.
*/
needsProxies = true;
} else if (instr instanceof ExceptionObjectNode && getMethod().compilationInfo.isDeoptEntry(((ExceptionObjectNode) instr).stateAfter().bci, true, false)) {
/*
* The predecessor of the ExceptionObjectNode will be an Invoke, but the Invoke
* has not been created yet. So the check above for the predecessor does not
* trigger.
*/
needsProxies = true;
}
}
if (needsProxies) {
long encodedBci = FrameInfoEncoder.encodeBci(stateAfter.bci, stateAfter.duringCall(), stateAfter.rethrowException());
DeoptProxyAnchorNode existingDeoptEntry = deoptEntries.get(encodedBci);
if (existingDeoptEntry != STICKY_DEOPT_ENTRY) {
if (existingDeoptEntry != null) {
/*
* Some state splits (i.e. MergeNode and DispatchBeginNode) do not have a
* correspondent byte code. Therefore there can be a previously added deopt
* entry with the same BCI. For MergeNodes we replace the previous entry
* because the new frame state has less live locals.
*/
existingDeoptEntry.replaceAtUsages(null);
graph.removeFixed(existingDeoptEntry);
deoptEntries.remove(encodedBci);
if (existingDeoptEntry instanceof DeoptEntryNode) {
/*
* We already had a DeoptEntryNode registered earlier for some reason,
* so be conservative and create one again (and not just a
* DeoptProxyAnchorNode).
*/
needsDeoptEntry = true;
}
}
assert !deoptEntries.containsKey(encodedBci) : "duplicate deopt entry for encoded BCI " + encodedBci;
DeoptProxyAnchorNode deoptEntry = createDeoptEntry(stateBuilder, stateAfter, !needsDeoptEntry);
if (instr instanceof LoopBeginNode) {
/*
* Loop headers to not have their own bci. Never move a deopt entry for the
* loop header down, e.g., into a loop end (that might then end up to be
* dead code).
*/
deoptEntries.put(encodedBci, STICKY_DEOPT_ENTRY);
} else {
deoptEntries.put(encodedBci, deoptEntry);
}
assert instr.next() == null : "cannot append instruction to instruction which isn't end (" + instr + "->" + instr.next() + ")";
instr.setNext(deoptEntry);
return deoptEntry;
}
}
}
return super.finishInstruction(instr, stateBuilder);
}
use of com.oracle.svm.core.graal.nodes.DeoptEntryNode in project graal by oracle.
the class HostedBytecodeParser method createDeoptEntry.
private DeoptProxyAnchorNode createDeoptEntry(FrameStateBuilder stateBuilder, FrameState stateAfter, boolean anchorOnly) {
DeoptProxyAnchorNode deoptEntry = graph.add(anchorOnly ? new DeoptProxyAnchorNode() : new DeoptEntryNode());
deoptEntry.setStateAfter(stateAfter);
insertProxies(deoptEntry, stateBuilder);
return deoptEntry;
}
use of com.oracle.svm.core.graal.nodes.DeoptEntryNode in project graal by oracle.
the class HostedBytecodeParser method finishPrepare.
/**
* Insert a deopt entry for the graph's start node.
*/
@Override
protected void finishPrepare(FixedWithNextNode startInstr, int bci) {
super.finishPrepare(startInstr, bci);
if (getMethod().compilationInfo.isDeoptEntry(bci, false, false)) {
DeoptEntryNode deoptEntry = append(new DeoptEntryNode());
deoptEntry.setStateAfter(frameState.create(bci, deoptEntry));
deoptEntries.put(Long.valueOf(bci), deoptEntry);
}
}
Aggregations