Stack map frames are computed in two steps:
MethodWriter#computeAllFrames.
Output stack map frames are computed relatively to the input frame of the basic block, which is not yet known when output frames are computed. It is therefore necessary to be able to represent abstract types such as "the type at position x in the input frame locals" or "the type at position x from the top of the input frame stack" or even "the type at position x in the input frame, with y more (or less) array dimensions". This explains the rather complicated type format used in this class, explained below.
The local variables and the operand stack of input and output frames contain values called "abstract types" hereafter. An abstract type is represented with 4 fields named DIM, KIND, FLAGS and VALUE, packed in a single int value for better performance and memory efficiency:
===================================== |...DIM|KIND|.F|...............VALUE| =====================================
DIM_MASK and a
right shift of DIM_SHIFT.
KIND_MASK and, without any shift, must be equal to CONSTANT_KIND, REFERENCE_KIND, UNINITIALIZED_KIND, FORWARD_UNINITIALIZED_KIND,LOCAL_KIND or STACK_KIND.
TOP_IF_LONG_OR_DOUBLE_FLAG.
ITEM_TOP, ITEM_ASM_BOOLEAN, ITEM_ASM_BYTE, ITEM_ASM_CHAR or ITEM_ASM_SHORT, ITEM_INTEGER, ITEM_FLOAT, ITEM_LONG, ITEM_DOUBLE, ITEM_NULL or ITEM_UNINITIALIZED_THIS, if KIND is equal to CONSTANT_KIND.
Symbol#TYPE_TAG Symbol in the type table of a SymbolTable, if KIND is equal to REFERENCE_KIND.
Symbol#UNINITIALIZED_TYPE_TAG Symbol in the type
table of a SymbolTable, if KIND is equal to UNINITIALIZED_KIND.
Symbol#FORWARD_UNINITIALIZED_TYPE_TAG Symbol in the
type table of a SymbolTable, if KIND is equal to FORWARD_UNINITIALIZED_KIND.
LOCAL_KIND.
STACK_KIND,
Output frames can contain abstract types of any kind and with a positive or negative array dimension (and even unassigned types, represented by 0 - which does not correspond to any valid abstract type value). Input frames can only contain CONSTANT_KIND, REFERENCE_KIND, UNINITIALIZED_KIND or FORWARD_UNINITIALIZED_KIND abstract types of positive or null array dimension. In all cases the type table contains only internal type names (array type descriptors are forbidden - array dimensions must be represented through the DIM field).
The LONG and DOUBLE types are always represented by using two slots (LONG + TOP or DOUBLE + TOP), for local variables as well as in the operand stack. This is necessary to be able to simulate DUPx_y instructions, whose effect would be dependent on the concrete types represented by the abstract types in the stack (which are not always known).
| Modifier and Type | Field and Description |
|---|---|
| pack-priv static final int | |
| private static final int | ARRAY_OF
The constant to be added to an abstract type to get one with one more array dimension. |
| private static final int | |
| private static final int | |
| private static final int | |
| pack-priv static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | ELEMENT_OF
The constant to be added to an abstract type to get one with one less array dimension. |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| pack-priv static final int | |
| private int | initializationCount
The number of types that are initialized in the basic block. |
| private int[] | initializations
The abstract types that are initialized in the basic block. |
| private int[] | inputLocals
The input stack map frame locals. |
| private int[] | inputStack
The input stack map frame stack. |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private int[] | outputLocals
The output stack map frame locals. |
| private int[] | outputStack
The output stack map frame stack. |
| private short | outputStackStart
The start of the output stack, relatively to the input stack. |
| private short | outputStackTop
The index of the top stack element in |
| pack-priv Label | owner
The basic block to which these input and output stack map frames correspond. |
| private static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| pack-priv static final int | |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int | TOP_IF_LONG_OR_DOUBLE_FLAG
A flag used for LOCAL_KIND and STACK_KIND abstract types, indicating that if the resolved, concrete type is LONG or DOUBLE, TOP should be used instead (because the value has been partially overridden with an xSTORE instruction). |
| private static final int | |
| private static final int | |
| private static final int | |
| private static final int |
| Access | Constructor and Description |
|---|---|
| pack-priv |
| Modifier and Type | Method and Description |
|---|---|
| pack-priv final void | accept(final MethodWriter
the methodWriter)MethodWriter that should visit the input frame of this Frame.Makes the given |
| private void | addInitializedType(final int
an abstract type on a which a constructor is invoked. abstractType)Adds an abstract type to the list of types on which a constructor is invoked in the basic block. |
| pack-priv final void | |
| pack-priv void | execute(final int
the opcode of the instruction. opcode, final int the numeric operand of the instruction, if any. arg, final Symbol the Symbol operand of the instruction, if any. argSymbol, final SymbolTable the type table to use to lookup and store type symbolTable)Symbol.Simulates the action of the given instruction on the output stack frame. |
| pack-priv static int | Returns: the abstract type corresponding to the given frame element type.the type table to use to lookup and store type symbolTable, final Object Symbol.a frame element type described using the same format as in type)MethodVisitor#visitFrame, i.e. either Opcodes#TOP, Opcodes#INTEGER, Opcodes#FLOAT, Opcodes#LONG, Opcodes#DOUBLE, Opcodes#NULL, or
Opcodes#UNINITIALIZED_THIS, or the internal name of a class, or a Label designating
a NEW instruction (for uninitialized types).Returns the abstract type corresponding to the given public API frame element type. |
| private static int | Returns: the abstract type corresponding to the given type descriptor.the type table to use to lookup and store type symbolTable, final String Symbol.a string ending with a type descriptor. buffer, final int the start offset of the type descriptor in buffer. offset)Returns the abstract type corresponding to the given type descriptor. |
| pack-priv static int | Returns: the abstract type value corresponding to the given internal name.the type table to use to lookup and store type symbolTable, final String Symbol.the internal name of a class. This must not be an array type
descriptor. internalName)Returns the abstract type corresponding to the internal name of a class. |
| private int | Returns: the concrete output type corresponding to 'abstractOutputType'.an abstract output type. abstractOutputType, final int the size of the input stack, used to resolve abstract output types of
STACK_KIND kind. numStack)Computes the concrete output type corresponding to a given abstract output type. |
| private int | Returns: the REFERENCE_KIND abstract type corresponding to abstractType if it is UNINITIALIZED_THIS or an UNINITIALIZED_KIND or FORWARD_UNINITIALIZED_KIND abstract type for one of the types on which a constructor is invoked in the basic block. Otherwise returns abstractType.the type table to use to lookup and store type symbolTable, final int Symbol.an abstract type. abstractType)Returns the "initialized" abstract type corresponding to the given abstract type. |
| pack-priv final int | |
| private int | Returns: the abstract type stored at the given local variable index in the output frame.the index of the local variable whose value must be returned. localIndex)Returns the abstract type stored at the given local variable index in the output frame. |
| pack-priv final boolean | Returns: true if the input frame of 'frame' has been changed by this operation.the type table to use to lookup and store type symbolTable, final Frame Symbol.the dstFrame, final int Frame whose input frame must be updated. This should be the frame
of a successor, in the control flow graph, of the basic block corresponding to this frame.if 'frame' corresponds to an exception handler basic block, the type
table index of the caught exception type, otherwise 0. catchTypeIndex)Merges the input frame of the given |
| private static boolean | Returns: true if the type array has been modified by this operation.the type table to use to lookup and store type symbolTable, final int Symbol.the abstract type with which the abstract type array element must be merged.
This type should be of sourceType, final int[] CONSTANT_KIND, REFERENCE_KIND, UNINITIALIZED_KIND or FORWARD_UNINITIALIZED_KIND kind, with positive or
null array dimensions.an array of abstract types. These types should be of dstTypes, final int CONSTANT_KIND,
REFERENCE_KIND, UNINITIALIZED_KIND or FORWARD_UNINITIALIZED_KIND
kind, with positive or null array dimensions.the index of the type that must be merged in dstTypes. dstIndex)Merges the type at the given index in the given abstract type array with the given type. |
| private int | Returns: the abstract type that has been popped from the output frame stack.Pops an abstract type from the output frame stack and returns its value. |
| private void | pop(final int
the number of abstract types that must be popped. elements)Pops the given number of abstract types from the output frame stack. |
| private void | |
| private void | push(final int
an abstract type. abstractType)Pushes the given abstract type on the output frame stack. |
| private void | push(final SymbolTable
the type table to use to lookup and store type symbolTable, final String Symbol.a type or method descriptor (in which case its return type is pushed). descriptor)Pushes the abstract type corresponding to the given descriptor on the output frame stack. |
| pack-priv static void | putAbstractType(final SymbolTable
the type table to use to lookup and store type symbolTable, final int Symbol.an abstract type, restricted to abstractType, final ByteVector Frame#CONSTANT_KIND, Frame#REFERENCE_KIND, Frame#UNINITIALIZED_KIND or Frame#FORWARD_UNINITIALIZED_KIND types.where the abstract type must be put. output)Put the given abstract type in the given ByteVector, using the JVMS verification_type_info format used in StackMapTable attributes. |
| pack-priv final void | setInputFrameFromApiFormat(final SymbolTable
the type table to use to lookup and store type symbolTable, final int Symbol.the number of local variables. numLocal, final Object[] the local variable types, described using the same format as in local, final int MethodVisitor#visitFrame.the number of operand stack elements. numStack, final Object[] the operand stack types, described using the same format as in stack)MethodVisitor#visitFrame.Sets the input frame from the given public API frame description. |
| pack-priv final void | setInputFrameFromDescriptor(final SymbolTable
the type table to use to lookup and store type symbolTable, final int Symbol.the method's access flags. access, final String the method descriptor. descriptor, final int the maximum number of local variables of the method. maxLocals)Sets the input frame from the given method description. |
| private void | setLocal(final int
the index of the output frame local variable that must be set. localIndex, final int the value that must be set. abstractType)Replaces the abstract type stored at the given local variable index in the output frame. |
| APPEND_FRAME | back to summary |
|---|---|
| pack-priv static final int APPEND_FRAME | |
| ARRAY_OF | back to summary |
|---|---|
| private static final int ARRAY_OF The constant to be added to an abstract type to get one with one more array dimension. | |
| BOOLEAN | back to summary |
|---|---|
| private static final int BOOLEAN | |
| BYTE | back to summary |
|---|---|
| private static final int BYTE | |
| CHAR | back to summary |
|---|---|
| private static final int CHAR | |
| CHOP_FRAME | back to summary |
|---|---|
| pack-priv static final int CHOP_FRAME | |
| CONSTANT_KIND | back to summary |
|---|---|
| private static final int CONSTANT_KIND | |
| DIM_MASK | back to summary |
|---|---|
| private static final int DIM_MASK | |
| DIM_SHIFT | back to summary |
|---|---|
| private static final int DIM_SHIFT | |
| DIM_SIZE | back to summary |
|---|---|
| private static final int DIM_SIZE | |
| DOUBLE | back to summary |
|---|---|
| private static final int DOUBLE | |
| ELEMENT_OF | back to summary |
|---|---|
| private static final int ELEMENT_OF The constant to be added to an abstract type to get one with one less array dimension. | |
| FLAGS_SHIFT | back to summary |
|---|---|
| private static final int FLAGS_SHIFT | |
| FLAGS_SIZE | back to summary |
|---|---|
| private static final int FLAGS_SIZE | |
| FLOAT | back to summary |
|---|---|
| private static final int FLOAT | |
| FORWARD_UNINITIALIZED_KIND | back to summary |
|---|---|
| private static final int FORWARD_UNINITIALIZED_KIND | |
| FULL_FRAME | back to summary |
|---|---|
| pack-priv static final int FULL_FRAME | |
| initializationCount | back to summary |
|---|---|
| private int initializationCount The number of types that are initialized in the basic block. See | |
| initializations | back to summary |
|---|---|
| private int[] initializations The abstract types that are initialized in the basic block. A constructor invocation on an UNINITIALIZED, FORWARD_UNINITIALIZED or UNINITIALIZED_THIS abstract type must replace every occurrence of this type in the local variables and in the operand stack. This cannot be done during the first step of the algorithm since, during this step, the local variables and the operand stack types are still abstract. It is therefore necessary to store the abstract types of the constructors which are invoked in the basic block, in order to do this replacement during the second step of the algorithm, where the frames are fully computed. Note that this array can contain abstract types that are relative to the input locals or to the input stack. | |
| inputLocals | back to summary |
|---|---|
| private int[] inputLocals The input stack map frame locals. This is an array of abstract types. | |
| inputStack | back to summary |
|---|---|
| private int[] inputStack The input stack map frame stack. This is an array of abstract types. | |
| INTEGER | back to summary |
|---|---|
| private static final int INTEGER | |
| ITEM_ASM_BOOLEAN | back to summary |
|---|---|
| private static final int ITEM_ASM_BOOLEAN | |
| ITEM_ASM_BYTE | back to summary |
|---|---|
| private static final int ITEM_ASM_BYTE | |
| ITEM_ASM_CHAR | back to summary |
|---|---|
| private static final int ITEM_ASM_CHAR | |
| ITEM_ASM_SHORT | back to summary |
|---|---|
| private static final int ITEM_ASM_SHORT | |
| ITEM_DOUBLE | back to summary |
|---|---|
| pack-priv static final int ITEM_DOUBLE | |
| ITEM_FLOAT | back to summary |
|---|---|
| pack-priv static final int ITEM_FLOAT | |
| ITEM_INTEGER | back to summary |
|---|---|
| pack-priv static final int ITEM_INTEGER | |
| ITEM_LONG | back to summary |
|---|---|
| pack-priv static final int ITEM_LONG | |
| ITEM_NULL | back to summary |
|---|---|
| pack-priv static final int ITEM_NULL | |
| ITEM_OBJECT | back to summary |
|---|---|
| pack-priv static final int ITEM_OBJECT | |
| ITEM_TOP | back to summary |
|---|---|
| pack-priv static final int ITEM_TOP | |
| ITEM_UNINITIALIZED | back to summary |
|---|---|
| pack-priv static final int ITEM_UNINITIALIZED | |
| ITEM_UNINITIALIZED_THIS | back to summary |
|---|---|
| pack-priv static final int ITEM_UNINITIALIZED_THIS | |
| KIND_MASK | back to summary |
|---|---|
| private static final int KIND_MASK | |
| KIND_SHIFT | back to summary |
|---|---|
| private static final int KIND_SHIFT | |
| KIND_SIZE | back to summary |
|---|---|
| private static final int KIND_SIZE | |
| LOCAL_KIND | back to summary |
|---|---|
| private static final int LOCAL_KIND | |
| LONG | back to summary |
|---|---|
| private static final int LONG | |
| NULL | back to summary |
|---|---|
| private static final int NULL | |
| outputLocals | back to summary |
|---|---|
| private int[] outputLocals The output stack map frame locals. This is an array of abstract types. | |
| outputStack | back to summary |
|---|---|
| private int[] outputStack The output stack map frame stack. This is an array of abstract types. | |
| outputStackStart | back to summary |
|---|---|
| private short outputStackStart The start of the output stack, relatively to the input stack. This offset is always negative or null. A null offset means that the output stack must be appended to the input stack. A -n offset means that the first n output stack elements must replace the top n input stack elements, and that the other elements must be appended to the input stack. | |
| outputStackTop | back to summary |
|---|---|
| private short outputStackTop The index of the top stack element in | |
| owner | back to summary |
|---|---|
| pack-priv Label owner The basic block to which these input and output stack map frames correspond. | |
| REFERENCE_KIND | back to summary |
|---|---|
| private static final int REFERENCE_KIND | |
| RESERVED | back to summary |
|---|---|
| pack-priv static final int RESERVED | |
| SAME_FRAME | back to summary |
|---|---|
| pack-priv static final int SAME_FRAME | |
| SAME_FRAME_EXTENDED | back to summary |
|---|---|
| pack-priv static final int SAME_FRAME_EXTENDED | |
| SAME_LOCALS_1_STACK_ITEM_FRAME | back to summary |
|---|---|
| pack-priv static final int SAME_LOCALS_1_STACK_ITEM_FRAME | |
| SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED | back to summary |
|---|---|
| pack-priv static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED | |
| SHORT | back to summary |
|---|---|
| private static final int SHORT | |
| STACK_KIND | back to summary |
|---|---|
| private static final int STACK_KIND | |
| TOP | back to summary |
|---|---|
| private static final int TOP | |
| TOP_IF_LONG_OR_DOUBLE_FLAG | back to summary |
|---|---|
| private static final int TOP_IF_LONG_OR_DOUBLE_FLAG A flag used for LOCAL_KIND and STACK_KIND abstract types, indicating that if the resolved, concrete type is LONG or DOUBLE, TOP should be used instead (because the value has been partially overridden with an xSTORE instruction). | |
| UNINITIALIZED_KIND | back to summary |
|---|---|
| private static final int UNINITIALIZED_KIND | |
| UNINITIALIZED_THIS | back to summary |
|---|---|
| private static final int UNINITIALIZED_THIS | |
| VALUE_MASK | back to summary |
|---|---|
| private static final int VALUE_MASK | |
| VALUE_SIZE | back to summary |
|---|---|
| private static final int VALUE_SIZE | |
| Frame | back to summary |
|---|---|
| pack-priv Frame(final Label owner) Constructs a new Frame.
| |
| accept | back to summary |
|---|---|
| pack-priv final void accept(final MethodWriter methodWriter) Makes the given
| |
| addInitializedType | back to summary |
|---|---|
| private void addInitializedType(final int abstractType) Adds an abstract type to the list of types on which a constructor is invoked in the basic block.
| |
| copyFrom | back to summary |
|---|---|
| pack-priv final void copyFrom(final Frame frame) Sets this frame to the value of the given frame. Warning after this method is called the two frames share the same data structures. It is recommended to discard the given frame to avoid unexpected side effects.
| |
| execute | back to summary |
|---|---|
| pack-priv void execute(final int opcode, final int arg, final Symbol argSymbol, final SymbolTable symbolTable) Simulates the action of the given instruction on the output stack frame.
| |
| getAbstractTypeFromApiFormat | back to summary |
|---|---|
| pack-priv static int getAbstractTypeFromApiFormat(final SymbolTable symbolTable, final Object type) Returns the abstract type corresponding to the given public API frame element type.
| |
| getAbstractTypeFromDescriptor | back to summary |
|---|---|
| private static int getAbstractTypeFromDescriptor(final SymbolTable symbolTable, final String buffer, final int offset) Returns the abstract type corresponding to the given type descriptor.
| |
| getAbstractTypeFromInternalName | back to summary |
|---|---|
| pack-priv static int getAbstractTypeFromInternalName(final SymbolTable symbolTable, final String internalName) Returns the abstract type corresponding to the internal name of a class.
| |
| getConcreteOutputType | back to summary |
|---|---|
| private int getConcreteOutputType(final int abstractOutputType, final int numStack) Computes the concrete output type corresponding to a given abstract output type.
| |
| getInitializedType | back to summary |
|---|---|
| private int getInitializedType(final SymbolTable symbolTable, final int abstractType) Returns the "initialized" abstract type corresponding to the given abstract type.
| |
| getInputStackSize | back to summary |
|---|---|
| pack-priv final int getInputStackSize() | |
| getLocal | back to summary |
|---|---|
| private int getLocal(final int localIndex) Returns the abstract type stored at the given local variable index in the output frame.
| |
| merge | back to summary |
|---|---|
| pack-priv final boolean merge(final SymbolTable symbolTable, final Frame dstFrame, final int catchTypeIndex) Merges the input frame of the given
| |
| merge | back to summary |
|---|---|
| private static boolean merge(final SymbolTable symbolTable, final int sourceType, final int[] dstTypes, final int dstIndex) Merges the type at the given index in the given abstract type array with the given type. Returns true if the type array has been modified by this operation.
| |
| pop | back to summary |
|---|---|
| private int pop() Pops an abstract type from the output frame stack and returns its value.
| |
| pop | back to summary |
|---|---|
| private void pop(final int elements) Pops the given number of abstract types from the output frame stack.
| |
| pop | back to summary |
|---|---|
| private void pop(final String descriptor) Pops as many abstract types from the output frame stack as described by the given descriptor.
| |
| push | back to summary |
|---|---|
| private void push(final int abstractType) Pushes the given abstract type on the output frame stack.
| |
| push | back to summary |
|---|---|
| private void push(final SymbolTable symbolTable, final String descriptor) Pushes the abstract type corresponding to the given descriptor on the output frame stack.
| |
| putAbstractType | back to summary |
|---|---|
| pack-priv static void putAbstractType(final SymbolTable symbolTable, final int abstractType, final ByteVector output) Put the given abstract type in the given ByteVector, using the JVMS verification_type_info format used in StackMapTable attributes.
| |
| setInputFrameFromApiFormat | back to summary |
|---|---|
| pack-priv final void setInputFrameFromApiFormat(final SymbolTable symbolTable, final int numLocal, final Object[] local, final int numStack, final Object[] stack) Sets the input frame from the given public API frame description.
| |
| setInputFrameFromDescriptor | back to summary |
|---|---|
| pack-priv final void setInputFrameFromDescriptor(final SymbolTable symbolTable, final int access, final String descriptor, final int maxLocals) Sets the input frame from the given method description. This method is used to initialize the first frame of a method, which is implicit (i.e. not stored explicitly in the StackMapTable attribute).
| |
| setLocal | back to summary |
|---|---|
| private void setLocal(final int localIndex, final int abstractType) Replaces the abstract type stored at the given local variable index in the output frame.
| |