Class Frame
- java.lang.Object
-
- org.objectweb.asm.Frame
-
- Direct Known Subclasses:
CurrentFrame
class Frame extends java.lang.Object
The input and output stack map frames of a basic block.Stack map frames are computed in two steps:
- During the visit of each instruction in MethodWriter, the state of the frame at the end of the current basic block is updated by simulating the action of the instruction on the previous state of this so called "output frame".
- After all instructions have been visited, a fix point algorithm is used in MethodWriter to
compute the "input frame" of each basic block (i.e. the stack map frame at the beginning of
the basic block). See
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| =====================================
- the DIM field, stored in the 6 most significant bits, is a signed number of array
dimensions (from -32 to 31, included). It can be retrieved with
DIM_MASK
and a right shift ofDIM_SHIFT
. - the KIND field, stored in 4 bits, indicates the kind of VALUE used. These 4 bits can be
retrieved with
KIND_MASK
and, without any shift, must be equal toCONSTANT_KIND
,REFERENCE_KIND
,UNINITIALIZED_KIND
,LOCAL_KIND
orSTACK_KIND
. - the FLAGS field, stored in 2 bits, contains up to 2 boolean flags. Currently only one flag
is defined, namely
TOP_IF_LONG_OR_DOUBLE_FLAG
. - the VALUE field, stored in the remaining 20 bits, contains either
- one of the constants
ITEM_TOP
,ITEM_ASM_BOOLEAN
,ITEM_ASM_BYTE
,ITEM_ASM_CHAR
orITEM_ASM_SHORT
,ITEM_INTEGER
,ITEM_FLOAT
,ITEM_LONG
,ITEM_DOUBLE
,ITEM_NULL
orITEM_UNINITIALIZED_THIS
, if KIND is equal toCONSTANT_KIND
. - the index of a
Symbol.TYPE_TAG
Symbol
in the type table of aSymbolTable
, if KIND is equal toREFERENCE_KIND
. - the index of an
Symbol.UNINITIALIZED_TYPE_TAG
Symbol
in the type table of a SymbolTable, if KIND is equal toUNINITIALIZED_KIND
. - the index of a local variable in the input stack frame, if KIND is equal to
LOCAL_KIND
. - a position relatively to the top of the stack of the input stack frame, if KIND is
equal to
STACK_KIND
,
- one of the constants
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 or 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).
-
-
Field Summary
Fields Modifier and Type Field Description (package private) static int
APPEND_FRAME
private static int
ARRAY_OF
The constant to be added to an abstract type to get one with one more array dimension.private static int
BOOLEAN
private static int
BYTE
private static int
CHAR
(package private) static int
CHOP_FRAME
private static int
CONSTANT_KIND
private static int
DIM_MASK
private static int
DIM_SHIFT
private static int
DIM_SIZE
private static int
DOUBLE
private static int
ELEMENT_OF
The constant to be added to an abstract type to get one with one less array dimension.private static int
FLAGS_SHIFT
private static int
FLAGS_SIZE
private static int
FLOAT
(package private) static int
FULL_FRAME
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 int
INTEGER
private static int
ITEM_ASM_BOOLEAN
private static int
ITEM_ASM_BYTE
private static int
ITEM_ASM_CHAR
private static int
ITEM_ASM_SHORT
(package private) static int
ITEM_DOUBLE
(package private) static int
ITEM_FLOAT
(package private) static int
ITEM_INTEGER
(package private) static int
ITEM_LONG
(package private) static int
ITEM_NULL
(package private) static int
ITEM_OBJECT
(package private) static int
ITEM_TOP
(package private) static int
ITEM_UNINITIALIZED
(package private) static int
ITEM_UNINITIALIZED_THIS
private static int
KIND_MASK
private static int
KIND_SHIFT
private static int
KIND_SIZE
private static int
LOCAL_KIND
private static int
LONG
private static int
NULL
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 inoutputStack
.(package private) Label
owner
The basic block to which these input and output stack map frames correspond.private static int
REFERENCE_KIND
(package private) static int
RESERVED
(package private) static int
SAME_FRAME
(package private) static int
SAME_FRAME_EXTENDED
(package private) static int
SAME_LOCALS_1_STACK_ITEM_FRAME
(package private) static int
SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED
private static int
SHORT
private static int
STACK_KIND
private static int
TOP
private static 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 int
UNINITIALIZED_KIND
private static int
UNINITIALIZED_THIS
private static int
VALUE_MASK
private static int
VALUE_SIZE
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description (package private) void
accept(MethodWriter methodWriter)
Makes the givenMethodWriter
visit the input frame of thisFrame
.private void
addInitializedType(int abstractType)
Adds an abstract type to the list of types on which a constructor is invoked in the basic block.(package private) void
copyFrom(Frame frame)
Sets this frame to the value of the given frame.(package private) void
execute(int opcode, int arg, Symbol argSymbol, SymbolTable symbolTable)
Simulates the action of the given instruction on the output stack frame.(package private) static int
getAbstractTypeFromApiFormat(SymbolTable symbolTable, java.lang.Object type)
Returns the abstract type corresponding to the given public API frame element type.private static int
getAbstractTypeFromDescriptor(SymbolTable symbolTable, java.lang.String buffer, int offset)
Returns the abstract type corresponding to the given type descriptor.(package private) static int
getAbstractTypeFromInternalName(SymbolTable symbolTable, java.lang.String internalName)
Returns the abstract type corresponding to the internal name of a class.private int
getConcreteOutputType(int abstractOutputType, int numStack)
Computes the concrete output type corresponding to a given abstract output type.private int
getInitializedType(SymbolTable symbolTable, int abstractType)
Returns the "initialized" abstract type corresponding to the given abstract type.(package private) int
getInputStackSize()
private int
getLocal(int localIndex)
Returns the abstract type stored at the given local variable index in the output frame.private static boolean
merge(SymbolTable symbolTable, int sourceType, int[] dstTypes, int dstIndex)
Merges the type at the given index in the given abstract type array with the given type.(package private) boolean
merge(SymbolTable symbolTable, Frame dstFrame, int catchTypeIndex)
private int
pop()
Pops an abstract type from the output frame stack and returns its value.private void
pop(int elements)
Pops the given number of abstract types from the output frame stack.private void
pop(java.lang.String descriptor)
Pops as many abstract types from the output frame stack as described by the given descriptor.private void
push(int abstractType)
Pushes the given abstract type on the output frame stack.private void
push(SymbolTable symbolTable, java.lang.String descriptor)
Pushes the abstract type corresponding to the given descriptor on the output frame stack.(package private) static void
putAbstractType(SymbolTable symbolTable, int abstractType, ByteVector output)
Put the given abstract type in the given ByteVector, using the JVMS verification_type_info format used in StackMapTable attributes.(package private) void
setInputFrameFromApiFormat(SymbolTable symbolTable, int numLocal, java.lang.Object[] local, int numStack, java.lang.Object[] stack)
Sets the input frame from the given public API frame description.(package private) void
setInputFrameFromDescriptor(SymbolTable symbolTable, int access, java.lang.String descriptor, int maxLocals)
Sets the input frame from the given method description.private void
setLocal(int localIndex, int abstractType)
Replaces the abstract type stored at the given local variable index in the output frame.
-
-
-
Field Detail
-
SAME_FRAME
static final int SAME_FRAME
- See Also:
- Constant Field Values
-
SAME_LOCALS_1_STACK_ITEM_FRAME
static final int SAME_LOCALS_1_STACK_ITEM_FRAME
- See Also:
- Constant Field Values
-
RESERVED
static final int RESERVED
- See Also:
- Constant Field Values
-
SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED
static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED
- See Also:
- Constant Field Values
-
CHOP_FRAME
static final int CHOP_FRAME
- See Also:
- Constant Field Values
-
SAME_FRAME_EXTENDED
static final int SAME_FRAME_EXTENDED
- See Also:
- Constant Field Values
-
APPEND_FRAME
static final int APPEND_FRAME
- See Also:
- Constant Field Values
-
FULL_FRAME
static final int FULL_FRAME
- See Also:
- Constant Field Values
-
ITEM_TOP
static final int ITEM_TOP
- See Also:
- Constant Field Values
-
ITEM_INTEGER
static final int ITEM_INTEGER
- See Also:
- Constant Field Values
-
ITEM_FLOAT
static final int ITEM_FLOAT
- See Also:
- Constant Field Values
-
ITEM_DOUBLE
static final int ITEM_DOUBLE
- See Also:
- Constant Field Values
-
ITEM_LONG
static final int ITEM_LONG
- See Also:
- Constant Field Values
-
ITEM_NULL
static final int ITEM_NULL
- See Also:
- Constant Field Values
-
ITEM_UNINITIALIZED_THIS
static final int ITEM_UNINITIALIZED_THIS
- See Also:
- Constant Field Values
-
ITEM_OBJECT
static final int ITEM_OBJECT
- See Also:
- Constant Field Values
-
ITEM_UNINITIALIZED
static final int ITEM_UNINITIALIZED
- See Also:
- Constant Field Values
-
ITEM_ASM_BOOLEAN
private static final int ITEM_ASM_BOOLEAN
- See Also:
- Constant Field Values
-
ITEM_ASM_BYTE
private static final int ITEM_ASM_BYTE
- See Also:
- Constant Field Values
-
ITEM_ASM_CHAR
private static final int ITEM_ASM_CHAR
- See Also:
- Constant Field Values
-
ITEM_ASM_SHORT
private static final int ITEM_ASM_SHORT
- See Also:
- Constant Field Values
-
DIM_SIZE
private static final int DIM_SIZE
- See Also:
- Constant Field Values
-
KIND_SIZE
private static final int KIND_SIZE
- See Also:
- Constant Field Values
-
FLAGS_SIZE
private static final int FLAGS_SIZE
- See Also:
- Constant Field Values
-
VALUE_SIZE
private static final int VALUE_SIZE
- See Also:
- Constant Field Values
-
DIM_SHIFT
private static final int DIM_SHIFT
- See Also:
- Constant Field Values
-
KIND_SHIFT
private static final int KIND_SHIFT
- See Also:
- Constant Field Values
-
FLAGS_SHIFT
private static final int FLAGS_SHIFT
- See Also:
- Constant Field Values
-
DIM_MASK
private static final int DIM_MASK
- See Also:
- Constant Field Values
-
KIND_MASK
private static final int KIND_MASK
- See Also:
- Constant Field Values
-
VALUE_MASK
private static final int VALUE_MASK
- See Also:
- Constant Field Values
-
ARRAY_OF
private static final int ARRAY_OF
The constant to be added to an abstract type to get one with one more array dimension.- See Also:
- Constant Field Values
-
ELEMENT_OF
private static final int ELEMENT_OF
The constant to be added to an abstract type to get one with one less array dimension.- See Also:
- Constant Field Values
-
CONSTANT_KIND
private static final int CONSTANT_KIND
- See Also:
- Constant Field Values
-
REFERENCE_KIND
private static final int REFERENCE_KIND
- See Also:
- Constant Field Values
-
UNINITIALIZED_KIND
private static final int UNINITIALIZED_KIND
- See Also:
- Constant Field Values
-
LOCAL_KIND
private static final int LOCAL_KIND
- See Also:
- Constant Field Values
-
STACK_KIND
private static final int STACK_KIND
- See Also:
- Constant Field Values
-
TOP_IF_LONG_OR_DOUBLE_FLAG
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).- See Also:
- Constant Field Values
-
TOP
private static final int TOP
- See Also:
- Constant Field Values
-
BOOLEAN
private static final int BOOLEAN
- See Also:
- Constant Field Values
-
BYTE
private static final int BYTE
- See Also:
- Constant Field Values
-
CHAR
private static final int CHAR
- See Also:
- Constant Field Values
-
SHORT
private static final int SHORT
- See Also:
- Constant Field Values
-
INTEGER
private static final int INTEGER
- See Also:
- Constant Field Values
-
FLOAT
private static final int FLOAT
- See Also:
- Constant Field Values
-
LONG
private static final int LONG
- See Also:
- Constant Field Values
-
DOUBLE
private static final int DOUBLE
- See Also:
- Constant Field Values
-
NULL
private static final int NULL
- See Also:
- Constant Field Values
-
UNINITIALIZED_THIS
private static final int UNINITIALIZED_THIS
- See Also:
- Constant Field Values
-
owner
Label owner
The basic block to which these input and output stack map frames correspond.
-
inputLocals
private int[] inputLocals
The input stack map frame locals. This is an array of abstract types.
-
inputStack
private int[] inputStack
The input stack map frame stack. This is an array of abstract types.
-
outputLocals
private int[] outputLocals
The output stack map frame locals. This is an array of abstract types.
-
outputStack
private int[] outputStack
The output stack map frame stack. This is an array of abstract types.
-
outputStackStart
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
private short outputStackTop
The index of the top stack element inoutputStack
.
-
initializationCount
private int initializationCount
The number of types that are initialized in the basic block. Seeinitializations
.
-
initializations
private int[] initializations
The abstract types that are initialized in the basic block. A constructor invocation on an 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.
-
-
Constructor Detail
-
Frame
Frame(Label owner)
Constructs a new Frame.- Parameters:
owner
- the basic block to which these input and output stack map frames correspond.
-
-
Method Detail
-
copyFrom
final void copyFrom(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.
- Parameters:
frame
- The new frame value.
-
getAbstractTypeFromApiFormat
static int getAbstractTypeFromApiFormat(SymbolTable symbolTable, java.lang.Object type)
Returns the abstract type corresponding to the given public API frame element type.- Parameters:
symbolTable
- the type table to use to lookup and store typeSymbol
.type
- a frame element type described using the same format as inMethodVisitor.visitFrame(int, int, java.lang.Object[], int, java.lang.Object[])
, i.e. eitherOpcodes.TOP
,Opcodes.INTEGER
,Opcodes.FLOAT
,Opcodes.LONG
,Opcodes.DOUBLE
,Opcodes.NULL
, orOpcodes.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 frame element type.
-
getAbstractTypeFromInternalName
static int getAbstractTypeFromInternalName(SymbolTable symbolTable, java.lang.String internalName)
Returns the abstract type corresponding to the internal name of a class.- Parameters:
symbolTable
- the type table to use to lookup and store typeSymbol
.internalName
- the internal name of a class. This must not be an array type descriptor.- Returns:
- the abstract type value corresponding to the given internal name.
-
getAbstractTypeFromDescriptor
private static int getAbstractTypeFromDescriptor(SymbolTable symbolTable, java.lang.String buffer, int offset)
Returns the abstract type corresponding to the given type descriptor.- Parameters:
symbolTable
- the type table to use to lookup and store typeSymbol
.buffer
- a string ending with a type descriptor.offset
- the start offset of the type descriptor in buffer.- Returns:
- the abstract type corresponding to the given type descriptor.
-
setInputFrameFromDescriptor
final void setInputFrameFromDescriptor(SymbolTable symbolTable, int access, java.lang.String descriptor, 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).- Parameters:
symbolTable
- the type table to use to lookup and store typeSymbol
.access
- the method's access flags.descriptor
- the method descriptor.maxLocals
- the maximum number of local variables of the method.
-
setInputFrameFromApiFormat
final void setInputFrameFromApiFormat(SymbolTable symbolTable, int numLocal, java.lang.Object[] local, int numStack, java.lang.Object[] stack)
Sets the input frame from the given public API frame description.- Parameters:
symbolTable
- the type table to use to lookup and store typeSymbol
.numLocal
- the number of local variables.local
- the local variable types, described using the same format as inMethodVisitor.visitFrame(int, int, java.lang.Object[], int, java.lang.Object[])
.numStack
- the number of operand stack elements.stack
- the operand stack types, described using the same format as inMethodVisitor.visitFrame(int, int, java.lang.Object[], int, java.lang.Object[])
.
-
getInputStackSize
final int getInputStackSize()
-
getLocal
private int getLocal(int localIndex)
Returns the abstract type stored at the given local variable index in the output frame.- Parameters:
localIndex
- the index of the local variable whose value must be returned.- Returns:
- the abstract type stored at the given local variable index in the output frame.
-
setLocal
private void setLocal(int localIndex, int abstractType)
Replaces the abstract type stored at the given local variable index in the output frame.- Parameters:
localIndex
- the index of the output frame local variable that must be set.abstractType
- the value that must be set.
-
push
private void push(int abstractType)
Pushes the given abstract type on the output frame stack.- Parameters:
abstractType
- an abstract type.
-
push
private void push(SymbolTable symbolTable, java.lang.String descriptor)
Pushes the abstract type corresponding to the given descriptor on the output frame stack.- Parameters:
symbolTable
- the type table to use to lookup and store typeSymbol
.descriptor
- a type or method descriptor (in which case its return type is pushed).
-
pop
private int pop()
Pops an abstract type from the output frame stack and returns its value.- Returns:
- the abstract type that has been popped from the output frame stack.
-
pop
private void pop(int elements)
Pops the given number of abstract types from the output frame stack.- Parameters:
elements
- the number of abstract types that must be popped.
-
pop
private void pop(java.lang.String descriptor)
Pops as many abstract types from the output frame stack as described by the given descriptor.- Parameters:
descriptor
- a type or method descriptor (in which case its argument types are popped).
-
addInitializedType
private void addInitializedType(int abstractType)
Adds an abstract type to the list of types on which a constructor is invoked in the basic block.- Parameters:
abstractType
- an abstract type on a which a constructor is invoked.
-
getInitializedType
private int getInitializedType(SymbolTable symbolTable, int abstractType)
Returns the "initialized" abstract type corresponding to the given abstract type.- Parameters:
symbolTable
- the type table to use to lookup and store typeSymbol
.abstractType
- an abstract type.- Returns:
- the REFERENCE_KIND abstract type corresponding to abstractType if it is UNINITIALIZED_THIS or an UNINITIALIZED_KIND abstract type for one of the types on which a constructor is invoked in the basic block. Otherwise returns abstractType.
-
execute
void execute(int opcode, int arg, Symbol argSymbol, SymbolTable symbolTable)
Simulates the action of the given instruction on the output stack frame.- Parameters:
opcode
- the opcode of the instruction.arg
- the numeric operand of the instruction, if any.argSymbol
- the Symbol operand of the instruction, if any.symbolTable
- the type table to use to lookup and store typeSymbol
.
-
getConcreteOutputType
private int getConcreteOutputType(int abstractOutputType, int numStack)
Computes the concrete output type corresponding to a given abstract output type.- Parameters:
abstractOutputType
- an abstract output type.numStack
- the size of the input stack, used to resolve abstract output types of STACK_KIND kind.- Returns:
- the concrete output type corresponding to 'abstractOutputType'.
-
merge
final boolean merge(SymbolTable symbolTable, Frame dstFrame, int catchTypeIndex)
Merges the input frame of the givenFrame
with the input and output frames of thisFrame
. Returns true if the given frame has been changed by this operation (the input and output frames of thisFrame
are never changed).- Parameters:
symbolTable
- the type table to use to lookup and store typeSymbol
.dstFrame
- theFrame
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.catchTypeIndex
- if 'frame' corresponds to an exception handler basic block, the type table index of the caught exception type, otherwise 0.- Returns:
- true if the input frame of 'frame' has been changed by this operation.
-
merge
private static boolean merge(SymbolTable symbolTable, int sourceType, int[] dstTypes, 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.- Parameters:
symbolTable
- the type table to use to lookup and store typeSymbol
.sourceType
- the abstract type with which the abstract type array element must be merged. This type should be ofCONSTANT_KIND
,REFERENCE_KIND
orUNINITIALIZED_KIND
kind, with positive or null array dimensions.dstTypes
- an array of abstract types. These types should be ofCONSTANT_KIND
,REFERENCE_KIND
orUNINITIALIZED_KIND
kind, with positive or null array dimensions.dstIndex
- the index of the type that must be merged in dstTypes.- Returns:
- true if the type array has been modified by this operation.
-
accept
final void accept(MethodWriter methodWriter)
Makes the givenMethodWriter
visit the input frame of thisFrame
. The visit is done with theMethodWriter.visitFrameStart(int, int, int)
,MethodWriter.visitAbstractType(int, int)
andMethodWriter.visitFrameEnd()
methods.- Parameters:
methodWriter
- theMethodWriter
that should visit the input frame of thisFrame
.
-
putAbstractType
static void putAbstractType(SymbolTable symbolTable, int abstractType, ByteVector output)
Put the given abstract type in the given ByteVector, using the JVMS verification_type_info format used in StackMapTable attributes.- Parameters:
symbolTable
- the type table to use to lookup and store typeSymbol
.abstractType
- an abstract type, restricted toCONSTANT_KIND
,REFERENCE_KIND
orUNINITIALIZED_KIND
types.output
- where the abstract type must be put.- See Also:
- JVMS 4.7.4
-
-