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
Node
or 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. - The node should implement either
executeOSR(VirtualFrame, int, Object)
orexecuteOSR(VirtualFrame, long, Object)
(see note below).
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.
Starting in 24.2, Bytecode OSR supports long
values for target
dispatch
locations. An interpreter can use long
targets by invoking
tryOSR(BytecodeOSRNode, long, Object, Runnable, VirtualFrame)
(instead of
tryOSR(BytecodeOSRNode, int, Object, Runnable, VirtualFrame)
). Refer to the
documentation for the long
overload for more details.
- Since:
- 21.3
-
Method Summary
Modifier and TypeMethodDescriptiondefault void
copyIntoOSRFrame
(VirtualFrame osrFrame, VirtualFrame parentFrame, int target) Deprecated.since 22.2default void
copyIntoOSRFrame
(VirtualFrame osrFrame, VirtualFrame parentFrame, int target, Object targetMetadata) Copies the contents of theparentFrame
into theosrFrame
used to execute OSR.default void
copyIntoOSRFrame
(VirtualFrame osrFrame, VirtualFrame parentFrame, long target, Object targetMetadata) Overload ofcopyIntoOSRFrame(VirtualFrame, VirtualFrame, int, Object)
with along
target.default Object
executeOSR
(VirtualFrame osrFrame, int target, Object interpreterState) Entrypoint to invoke this node through OSR.default Object
executeOSR
(VirtualFrame osrFrame, long target, Object interpreterState) Overload ofexecuteOSR(VirtualFrame, int, Object)
with along
target.Gets the OSR metadata for this instance.static boolean
pollOSRBackEdge
(BytecodeOSRNode osrNode) Reports a back edge, returning whether to try performing OSR.default void
prepareOSR
(int target) Initialization hook which will be invoked before OSR compilation.default void
prepareOSR
(long target) Overload ofprepareOSR(int)
with along
target.default void
restoreParentFrame
(VirtualFrame osrFrame, VirtualFrame parentFrame) Restores the contents of theosrFrame
back into theparentFrame
after OSR.default Frame
restoreParentFrameFromArguments
(Object[] arguments) Return the parent frame that was stored in an arguments array by a previous call tostoreParentFrameInArguments(com.oracle.truffle.api.frame.VirtualFrame)
.void
setOSRMetadata
(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.default void
transferOSRFrame
(VirtualFrame osrFrame, VirtualFrame parentFrame, long target, Object targetMetadata) Helper method that can be called by implementations ofcopyIntoOSRFrame(VirtualFrame, VirtualFrame, long, Object)
.static Object
tryOSR
(BytecodeOSRNode osrNode, int target, Object interpreterState, Runnable beforeTransfer, VirtualFrame parentFrame) Tries to perform OSR.static Object
tryOSR
(BytecodeOSRNode osrNode, long target, Object interpreterState, Runnable beforeTransfer, VirtualFrame parentFrame) Overload oftryOSR(BytecodeOSRNode, int, Object, Runnable, VirtualFrame)
with along
target.
-
Method Details
-
executeOSR
Entrypoint to invoke this node through OSR. Implementers must override this method (or itslong overload
). The implementation should execute bytecode starting from the giventarget
location (e.g., bytecode index).The
osrFrame
may be the parent frame, but for performance reasons could also be a new frame. In case a new frame is created, the frame'sarguments
will 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(BytecodeOSRNode, int, Object, Runnable, VirtualFrame)
for more details.- Returns:
- the result of execution.
- Since:
- 21.3
- See Also:
-
executeOSR
Overload ofexecuteOSR(VirtualFrame, int, Object)
with along
target. An interpreter that useslong
targets must override this method.- Since:
- 24.2
- See Also:
-
getOSRMetadata
Object getOSRMetadata()Gets the OSR metadata for this instance.The metadata must be stored on a
@CompilationFinal
instance 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
@CompilationFinal
instance 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 one
will not be used.- Since:
- 21.3
- See Also:
-
copyIntoOSRFrame
default void copyIntoOSRFrame(VirtualFrame osrFrame, VirtualFrame parentFrame, int target, Object targetMetadata) Copies the contents of theparentFrame
into theosrFrame
used 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 thistarget
for the default frame transfer behavior.- Since:
- 22.2
- See Also:
-
copyIntoOSRFrame
default void copyIntoOSRFrame(VirtualFrame osrFrame, VirtualFrame parentFrame, long target, Object targetMetadata) Overload ofcopyIntoOSRFrame(VirtualFrame, VirtualFrame, int, Object)
with along
target. An interpreter that useslong
targets must override this method.- Since:
- 24.2
- See Also:
-
transferOSRFrame
default void transferOSRFrame(VirtualFrame osrFrame, VirtualFrame parentFrame, long target, Object targetMetadata) Helper method that can be called by implementations ofcopyIntoOSRFrame(VirtualFrame, VirtualFrame, long, Object)
. Should not be overridden.- Since:
- 24.2
- See Also:
-
restoreParentFrame
Restores the contents of theosrFrame
back into theparentFrame
after OSR. By default, performs a slot-wise copy of the frame.Though a bytecode interpreter might not explicitly use
parentFrame
after OSR, it is necessary to restore the state intoparentFrame
if 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
- See Also:
-
prepareOSR
default void prepareOSR(long target) Overload ofprepareOSR(int)
with along
target. An interpreter that useslong
targets must override this method.- Since:
- 24.2
- See Also:
-
pollOSRBackEdge
Reports a back edge, returning whether to try performing OSR.An interpreter must ensure this method returns
true
immediately 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 atrue
result 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
interpreterState
parameter 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
beforeTransfer
callback 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
null
otherwise. - Since:
- 21.3
- See Also:
-
tryOSR
static Object tryOSR(BytecodeOSRNode osrNode, long target, Object interpreterState, Runnable beforeTransfer, VirtualFrame parentFrame) Overload oftryOSR(BytecodeOSRNode, int, Object, Runnable, VirtualFrame)
with along
target. An interpreter that useslong
targets should call this method.If an interpreter uses a
long
representation, it must override the hooks that definelong
overloads, namelyexecuteOSR(VirtualFrame, long, Object)
,copyIntoOSRFrame(VirtualFrame, VirtualFrame, long, Object)
, andprepareOSR(long)
. Overriding is necessary because the defaultlong
overloads call theirint
overloads for backwards compatibility, and these calls will fail forlong
-sized targets.- Since:
- 24.2
- See Also:
-
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 theparentFrame
argument. 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 ofparentFrame
and 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
-