Interface BytecodeOSRNode
- All Superinterfaces:
NodeInterface
There are a few restrictions Bytecode OSR nodes must satisfy in order for OSR to work correctly:
- The node must extend
Nodeor a subclass ofNode. - The node must provide storage for the OSR metadata maintained by the runtime using an
instance field. The field must be
@CompilationFinal, and thegetOSRMetadata()andsetOSRMetadata(java.lang.Object)methods must proxy accesses to it. - The node should call
pollOSRBackEdge(com.oracle.truffle.api.nodes.BytecodeOSRNode)andtryOSR(com.oracle.truffle.api.nodes.BytecodeOSRNode, int, java.lang.Object, java.lang.Runnable, com.oracle.truffle.api.frame.VirtualFrame)as described by their documentation.
For performance reasons, the parent frame may be copied into a new frame used for OSR. If this
happens, copyIntoOSRFrame(VirtualFrame, VirtualFrame, int, Object) is
used to perform the copy, and restoreParentFrame(com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.frame.VirtualFrame) is used to copy the OSR
frame contents back into the parent frame after OSR. A node may override these methods; by
default, they perform slot-wise copies.
A node may also wish to override prepareOSR(int) to perform initialization.
This method will be called before compilation, and can be useful to avoid deoptimizing inside
compiled code.
- Since:
- 21.3
-
Method Summary
Modifier and TypeMethodDescriptiondefault voidcopyIntoOSRFrame(VirtualFrame osrFrame, VirtualFrame parentFrame, int target) Deprecated.since 22.2default voidcopyIntoOSRFrame(VirtualFrame osrFrame, VirtualFrame parentFrame, int target, Object targetMetadata) Copies the contents of theparentFrameinto theosrFrameused to execute OSR.executeOSR(VirtualFrame osrFrame, int target, Object interpreterState) Entrypoint to invoke this node through OSR.Gets the OSR metadata for this instance.static booleanpollOSRBackEdge(BytecodeOSRNode osrNode) Reports a back edge, returning whether to try performing OSR.default voidprepareOSR(int target) Initialization hook which will be invoked before OSR compilation.default voidrestoreParentFrame(VirtualFrame osrFrame, VirtualFrame parentFrame) Restores the contents of theosrFrameback into theparentFrameafter OSR.default FramerestoreParentFrameFromArguments(Object[] arguments) Return the parent frame that was stored in an arguments array by a previous call tostoreParentFrameInArguments(com.oracle.truffle.api.frame.VirtualFrame).voidsetOSRMetadata(Object osrMetadata) Sets the OSR metadata for this instance.default Object[]storeParentFrameInArguments(VirtualFrame parentFrame) Produce the arguments that will be used to perform the call to the new OSR root.static ObjecttryOSR(BytecodeOSRNode osrNode, int target, Object interpreterState, Runnable beforeTransfer, VirtualFrame parentFrame) Tries to perform OSR.
-
Method Details
-
executeOSR
Entrypoint to invoke this node through OSR. This method should execute from thetargetlocation.The
osrFramemay be the parent frame, but for performance reasons could also be a new frame. In case a new frame is created, the frame'sargumentswill be provided bystoreParentFrameInArguments(com.oracle.truffle.api.frame.VirtualFrame).Typically, a bytecode node's
execute(VirtualFrame)method already contains a dispatch loop. This loop can be extracted into a separate method which can also be used by this method. For example:Object execute(VirtualFrame frame) { return dispatchFromBCI(frame, 0); } Object executeOSR(VirtualFrame osrFrame, int target, Object interpreterState) { return dispatchFromBCI(osrFrame, target); } Object dispatchFromBCI(VirtualFrame frame, int bci) { // main dispatch loop while(true) { switch(instructions[bci]) { ... } } }- Parameters:
osrFrame- the frame to use for OSR.target- the target location to execute from (e.g., bytecode index).interpreterState- other interpreter state used to resume execution. SeetryOSR(com.oracle.truffle.api.nodes.BytecodeOSRNode, int, java.lang.Object, java.lang.Runnable, com.oracle.truffle.api.frame.VirtualFrame)for more details.- Returns:
- the result of execution.
- Since:
- 21.3
-
getOSRMetadata
Object getOSRMetadata()Gets the OSR metadata for this instance.The metadata must be stored on a
@CompilationFinalinstance field. Refer to the documentation for this interface for a more complete description.- Returns:
- the OSR metadata.
- Since:
- 21.3
-
setOSRMetadata
Sets the OSR metadata for this instance.The metadata must be stored on a
@CompilationFinalinstance field. Refer to the documentation for this interface for a more complete description.- Parameters:
osrMetadata- the OSR metadata.- Since:
- 21.3
-
copyIntoOSRFrame
@Deprecated(since="22.2") default void copyIntoOSRFrame(VirtualFrame osrFrame, VirtualFrame parentFrame, int target) Deprecated.since 22.2Note that if this method is implemented, thepreferred onewill not be used.- Since:
- 21.3
- See Also:
-
copyIntoOSRFrame
default void copyIntoOSRFrame(VirtualFrame osrFrame, VirtualFrame parentFrame, int target, Object targetMetadata) Copies the contents of theparentFrameinto theosrFrameused to execute OSR. By default, performs a slot-wise copy of the frame.NOTE: This method is only used if the Truffle runtime decides to copy the frame. OSR may also reuse the parent frame directly.
- Parameters:
osrFrame- the frame to use for OSR.parentFrame- the frame used before performing OSR.target- the target location OSR will execute from (e.g., bytecode index).targetMetadata- Additional metadata associated with thistargetfor the default frame transfer behavior.- Since:
- 22.2
-
restoreParentFrame
Restores the contents of theosrFrameback into theparentFrameafter OSR. By default, performs a slot-wise copy of the frame.Though a bytecode interpreter might not explicitly use
parentFrameafter OSR, it is necessary to restore the state intoparentFrameif it may be accessed through instrumentation.NOTE: This method is only used if the Truffle runtime decided to copy the frame using
copyIntoOSRFrame(VirtualFrame, VirtualFrame, int, Object).- Parameters:
osrFrame- the frame which was used for OSR.parentFrame- the frame which will be used by the parent after returning from OSR.- Since:
- 21.3
-
prepareOSR
default void prepareOSR(int target) Initialization hook which will be invoked before OSR compilation. This hook can be used to perform any necessary initialization before compilation happens.For example, consider a field which must be initialized in the interpreter:
@CompilationFinal Object field; Object getField() { if (field == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); field = new Object(); } return field; }If the field is accessed from compiled OSR code, it may trigger a deoptimization in order to initialize the field. Using
prepareOSR(int)to initialize the field can prevent this.- Parameters:
target- the target location OSR will execute from (e.g., bytecode index).- Since:
- 21.3
-
pollOSRBackEdge
Reports a back edge, returning whether to try performing OSR.An interpreter must ensure this method returns
trueimmediately before callingtryOSR(com.oracle.truffle.api.nodes.BytecodeOSRNode, int, java.lang.Object, java.lang.Runnable, com.oracle.truffle.api.frame.VirtualFrame). For example:if (BytecodeOSRNode.pollOSRBackEdge(this)) { Object osrResult = BytecodeOSRNode.tryOSR(...); ... }- Parameters:
osrNode- the node to report a back-edge for.- Returns:
- whether to try OSR.
- Since:
- 21.3
-
tryOSR
static Object tryOSR(BytecodeOSRNode osrNode, int target, Object interpreterState, Runnable beforeTransfer, VirtualFrame parentFrame) Tries to perform OSR. This method must only be called immediately after atrueresult frompollOSRBackEdge(com.oracle.truffle.api.nodes.BytecodeOSRNode).Depending on the Truffle runtime, this method can trigger OSR compilation and then (typically in a subsequent call) transfer to OSR code. If OSR occurs, this method returns the result of OSR execution. The caller of this method can forward the result back to its caller rather than continuing execution from the
target. For example:if (BytecodeOSRNode.pollOSRBackEdge(this)) { Object osrResult = BytecodeOSRNode.tryOSR(...); if (osrResult != null) return osrResult; }The optional
interpreterStateparameter will be forwarded toexecuteOSR(com.oracle.truffle.api.frame.VirtualFrame, int, java.lang.Object)when OSR is performed. It should consist of additional interpreter state (e.g., data pointers) needed to resume execution fromtarget. The state should be fixed (i.e., final) for the giventarget. For example:// class definition class InterpreterState { final int dataPtr; InterpreterState(int dataPtr) { ... } } // call site Object osrResult = BytecodeOSRNode.tryOSR(this, target, new InterpreterState(dataPtr), ...); // executeOSR Object executeOSR(VirtualFrame osrFrame, int target, Object interpreterState) { InterpreterState state = (InterpreterState) interpreterState; return dispatchFromBCI(osrFrame, target, interpreterState.dataPtr); }The optional
beforeTransfercallback will be called before transferring control to the OSR target. Since this method may or may not perform a transfer, it is a way to ensure certain actions (e.g., instrumentation events) occur before transferring to OSR code. For example:// call site Object osrResult = BytecodeNode.tryOSR(this, target, ..., () -> { instrument.notify(current, target); });- Parameters:
osrNode- the node to try OSR for.target- the target location OSR will execute from (e.g., bytecode index).interpreterState- other interpreter state used to resume execution.beforeTransfer- a callback invoked before OSR. Can benull.parentFrame- frame at the current point of execution.- Returns:
- the result if OSR was performed, or
nullotherwise. - Since:
- 21.3
-
storeParentFrameInArguments
Produce the arguments that will be used to perform the call to the new OSR root. It will become the arguments array of the frame passed intoexecuteOSR(com.oracle.truffle.api.frame.VirtualFrame, int, java.lang.Object)in case a new frame is generated for the call for performance reasons. The contents are up to language, Truffle only requires that a subsequent call torestoreParentFrame(com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.frame.VirtualFrame)with the arguments array will return the same object as was passed into theparentFrameargument. By default, this method creates a new one-element array, which discards the original frame arguments. Override this method to be able to preserve a subset of the original frame arguments. It is permitted to modify arguments array ofparentFrameand return it. This is called only in the interpreter, therefore the frame is not virtual and it is safe to store it into the arguments array.- Parameters:
parentFrame- the frame object to be stored in the resulting arguments array- Returns:
- arguments array containing
parentFrame - Since:
- 22.2
-
restoreParentFrameFromArguments
Return the parent frame that was stored in an arguments array by a previous call tostoreParentFrameInArguments(com.oracle.truffle.api.frame.VirtualFrame).- Parameters:
arguments- frame arguments originally produced bystoreParentFrameInArguments(com.oracle.truffle.api.frame.VirtualFrame).- Returns:
- stored parent frame
- Since:
- 22.2
-