Class BytecodeFrame

java.lang.Object
com.oracle.truffle.api.bytecode.BytecodeFrame

public final class BytecodeFrame extends Object
Represents a captured Bytecode DSL frame, including the location metadata needed to access the data in the frame.

BytecodeFrame is intended for use cases where the frame escapes or outlives the root node invocation. Prefer using a built-in operation or LocalAccessor to access the frame whenever possible.

BytecodeFrame should be used instead of TruffleStackTraceElement or FrameInstance to access frame data because the frame captured in these abstractions is not always the actual frame used in execution (e.g., it may be different for a resumed continuation).

There are a few ways to capture the frame:

Copied frames do not observe updates made to the original frame.

Note: if the interpreter uses block scoping, local offsets are location-dependent and physical frame slots may be reused for different locals as execution proceeds. After execution continues, a captured frame may therefore expose values belonging to a different lexical scope. Any non-copied BytecodeFrame is consequently only valid until the interpreter continues execution. The frame must not be used after this point; doing so can cause undefined behaviour. If you need to access the frame after execution continues, you should capture a copy or explicitly copy() the captured bytecode frame. This restriction also applies to frames created by methods like get(TruffleStackTraceElement), which do not specify whether they capture the original frame or a copy.

Since:
25.1
  • Method Details

    • copy

      public BytecodeFrame copy()
      Returns a copy of this frame. This method can be used to snapshot the current state of a bytecode frame, in case it may be modified or become invalid in the future.
      Returns:
      a copy of this frame that is always valid and will not observe updates
      Since:
      25.1
    • getLocation

      public BytecodeLocation getLocation()
      Returns the bytecode location associated with the captured frame. This location is only valid until the bytecode interpreter resumes execution.
      Since:
      25.1
    • getBytecodeNode

      public BytecodeNode getBytecodeNode()
      Returns the bytecode node associated with the captured frame.
      Since:
      25.1
    • getBytecodeIndex

      public int getBytecodeIndex()
      Returns the bytecode index associated with the captured frame.
      Since:
      25.1
    • getLocalCount

      public int getLocalCount()
      Returns the number of live locals in the captured frame.
      Since:
      25.1
    • getLocalValue

      public Object getLocalValue(int localOffset)
      Returns the value of the local at the given offset. The offset should be in the range [0, getLocalCount()).
      Since:
      25.1
    • setLocalValue

      public void setLocalValue(int localOffset, Object value)
      Updates the value of the local at the given offset. The offset should be in the range [0, getLocalCount()).

      This method will throw an AssertionError if the captured frame does not support writes.

      Since:
      25.1
    • getLocalNames

      public Object[] getLocalNames()
      Returns the names associated with the live locals, if provided.
      Since:
      25.1
    • getArgumentCount

      public int getArgumentCount()
      Returns the number of arguments in the captured frame.
      Since:
      25.1
    • getArgument

      public Object getArgument(int argumentIndex)
      Returns the value of the argument at the given index. The offset should be between 0 and getArgumentCount().
      Since:
      25.1
    • setArgument

      public void setArgument(int argumentIndex, Object value)
      Updates the value of the local at the given offset. The offset should be between 0 and getArgumentCount().
      Since:
      25.1
    • getFrameDescriptorInfo

      public Object getFrameDescriptorInfo()
      Returns the info object associated with the frame's descriptor.
      Since:
      25.1
    • get

      public static BytecodeFrame get(FrameInstance frameInstance, FrameInstance.FrameAccess access)
      Creates a bytecode frame from the given frame instance.
      Parameters:
      frameInstance - the frame instance
      access - the access mode to use when capturing the frame
      Returns:
      a bytecode frame, or null if the frame instance is missing location info.
      Since:
      25.1
    • getNonVirtual

      public static BytecodeFrame getNonVirtual(FrameInstance frameInstance)
      Attempts to create a bytecode frame from the given frame instance. Returns null if the corresponding frame is virtual. The frame can be read from, written to, and escaped.

      This method can be used to probe for a frame that can safely escape without forcing materialization. For example, if a language needs to capture local variables from a stack frame, it's often more efficient to use an existing non-virtual frame rather than create a copy of all variables.

      Parameters:
      frameInstance - the frame instance
      Returns:
      a bytecode frame or null if the frame is virtual or if the frame instance is missing location info.
      Since:
      25.1
    • get

      public static BytecodeFrame get(TruffleStackTraceElement element)
      Creates a bytecode frame from the given stack trace element.

      This method will return null unless the interpreter specifies GenerateBytecode.captureFramesForTrace(), which indicates whether frames should be captured.

      Parameters:
      element - the stack trace element
      Returns:
      a bytecode frame, or null if the frame was not captured or the stack trace element is missing location information.
      Throws:
      IllegalArgumentException - if the element has an invalid bytecode index.
      Since:
      25.1
    • getNonVirtual

      public static BytecodeFrame getNonVirtual(TruffleStackTraceElement element)
      Attempts to create a bytecode frame from the given stack trace element. Returns null if the corresponding frame is virtual. The frame can be read from, written to, and escaped.

      This method can be used to probe for a frame that can safely escape without forcing materialization. For example, if a language needs to capture local variables from a stack frame, it's often more efficient to use an existing non-virtual frame rather than create a copy of all variables.

      Parameters:
      element - the stack trace element
      Returns:
      a bytecode frame or null if the frame is virtual/unavailable or if the frame instance is missing location info.
      Throws:
      IllegalArgumentException - if the element has an invalid bytecode index.
      Since:
      25.1
    • getTop

      public static BytecodeFrame getTop(FrameInstance.FrameAccess access, Node topLocation, int topBytecodeIndex)
      Returns the current top stack activation as a bytecode frame.

      The top frame's location is derived using topLocation and topBytecodeIndex. If topBytecodeIndex is -1, the bytecode index is resolved from topLocation and the resolved top Frame.

      Parameters:
      access - the access mode used when resolving the top frame
      topLocation - a node in the current top bytecode activation
      topBytecodeIndex - the bytecode index of the current top bytecode activation, or -1 to resolve it from topLocation and the resolved frame
      Returns:
      the current top bytecode frame
      Throws:
      IllegalArgumentException - if topLocation and topBytecodeIndex do not identify a valid location for the top frame, or if the top frame is not a bytecode frame.
      Since:
      25.1
    • iterateBytecodeFrames

      public static <T> T iterateBytecodeFrames(Function<BytecodeFrame, T> visitor, FrameInstance.FrameAccess access, Node topLocation, int topBytecodeIndex, int skipBytecodeFrames)
      Iterates the current stack as bytecode frames, starting with the current top activation.

      This method uses TruffleRuntime.iterateFrames(FrameInstanceVisitor) to perform a stack walk, constructing each BytecodeFrame instance from an underlying FrameInstance. Frame instances that do not correspond to bytecode frames are ignored.

      The visitor is invoked for each available bytecode frame until it returns a non-null value, which is then returned from this method. If the visitor always returns null, this method returns null.

      The stack walk begins with the current (top) activation. The top frame's location is derived using topLocation and topBytecodeIndex. These parameters are necessary because the FrameInstance for the top activation does not necessarily provide location information.

      If skipBytecodeFrames > 0, the top frame is skipped and topLocation and topBytecodeIndex are ignored. Otherwise, topLocation must identify a node in the current top bytecode activation, and topBytecodeIndex must be a valid bytecode index or -1. When topBytecodeIndex is -1, the bytecode index of the top frame is computed using topLocation and the resolved top Frame.

      Parameters:
      visitor - the visitor applied to each bytecode frame
      access - the access mode used when resolving frames from runtime stack frames
      topLocation - a node in the current top bytecode activation; ignored if skipBytecodeFrames > 0
      topBytecodeIndex - the bytecode index of the current top bytecode activation, or -1 to resolve it from topLocation and the resolved frame; ignored if skipBytecodeFrames > 0
      skipBytecodeFrames - the number of bytecode frames to skip before invoking the visitor
      Returns:
      the first non-null value returned by visitor, or null if no visited frame produces one
      Throws:
      IllegalArgumentException - if the top frame is not skipped and topLocation and topBytecodeIndex do not identify a valid location for the top frame, or if the top frame is not a bytecode frame.
      Since:
      25.1