use of com.oracle.svm.core.graal.nodes.DeoptProxyAnchorNode 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.DeoptProxyAnchorNode 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;
}
Aggregations