Class ClassFileWriter.StackMapTable
- java.lang.Object
-
- org.mozilla.classfile.ClassFileWriter.StackMapTable
-
- Enclosing class:
- ClassFileWriter
final class ClassFileWriter.StackMapTable extends java.lang.Object
A stack map table is a code attribute introduced in Java 6 that gives type information at key points in the method body (namely, at the beginning of each super block after the first). Each frame of a stack map table contains the state of local variable and operand stack for a given super block.
-
-
Field Summary
Fields Modifier and Type Field Description (package private) static boolean
DEBUGSTACKMAP
private int[]
locals
private int
localsTop
private byte[]
rawStackMap
private int
rawStackMapTop
private int[]
stack
private int
stackTop
private SuperBlock[]
superBlocks
private boolean
wide
private SuperBlock[]
workList
private int
workListTop
-
Constructor Summary
Constructors Constructor Description StackMapTable()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description private void
addToWorkList(SuperBlock sb)
private void
clearStack()
private void
computeRawStackMap()
Compute a space-optimal stack map table.(package private) int
computeWriteSize()
Compute the output size of the stack map table.private int
execute(int bci)
Execute a single byte code instruction.private void
executeALoad(int localIndex)
private void
executeAStore(int localIndex)
private void
executeBlock(SuperBlock work)
Simulate the local variable and op stack for a super block.private void
executeStore(int localIndex, int typeInfo)
private void
executeWorkList()
private void
flowInto(SuperBlock sb)
Perform a merge of type state and add the super block to the work list if the merge changed anything.(package private) void
generate()
private SuperBlock
getBranchTarget(int bci)
Get the target super block of a branch instruction.private int
getLocal(int localIndex)
private int
getOperand(int offset)
private int
getOperand(int start, int size)
Extract a logical operand from the byte code.private SuperBlock
getSuperBlockFromOffset(int offset)
private int
getWorstCaseWriteSize()
Get the worst case write size of the stack map table.private void
initializeTypeInfo(int prevType, int newType)
Change an UNINITIALIZED_OBJECT or UNINITIALIZED_THIS to the proper type of the object.private void
initializeTypeInfo(int prevType, int newType, int[] data, int dataTop)
private boolean
isBranch(int opcode)
Determine whether or not an opcode is a conditional or unconditional jump.private boolean
isSuperBlockEnd(int opcode)
Determine whether or not an opcode is an actual end to a super block.private void
killSuperBlock(SuperBlock sb)
Replace the contents of a super block with no-ops.private int
pop()
private long
pop2()
Pop two words from the op stack.private void
push(int typeInfo)
private void
push2(long typeInfo)
Push two words onto the op stack.private void
setLocal(int localIndex, int typeInfo)
private void
verify()
Calculate initial local variable and op stack types for each super block in the method.(package private) int
write(byte[] data, int offset)
private void
writeAppendFrame(int[] locals, int localsDelta, int offsetDelta)
private void
writeChopFrame(int localsDelta, int offsetDelta)
private void
writeFullFrame(int[] locals, int[] stack, int offsetDelta)
private void
writeSameFrame(int offsetDelta)
private void
writeSameLocalsOneStackItemFrame(int[] stack, int offsetDelta)
private int
writeType(int type)
private int
writeTypes(int[] types)
private int
writeTypes(int[] types, int start)
-
-
-
Field Detail
-
locals
private int[] locals
-
localsTop
private int localsTop
-
stack
private int[] stack
-
stackTop
private int stackTop
-
workList
private SuperBlock[] workList
-
workListTop
private int workListTop
-
superBlocks
private SuperBlock[] superBlocks
-
rawStackMap
private byte[] rawStackMap
-
rawStackMapTop
private int rawStackMapTop
-
wide
private boolean wide
-
DEBUGSTACKMAP
static final boolean DEBUGSTACKMAP
- See Also:
- Constant Field Values
-
-
Method Detail
-
generate
void generate()
-
getSuperBlockFromOffset
private SuperBlock getSuperBlockFromOffset(int offset)
-
isSuperBlockEnd
private boolean isSuperBlockEnd(int opcode)
Determine whether or not an opcode is an actual end to a super block. This includes any returns or unconditional jumps.
-
getBranchTarget
private SuperBlock getBranchTarget(int bci)
Get the target super block of a branch instruction.- Parameters:
bci
- the index of the branch instruction in the code buffer
-
isBranch
private boolean isBranch(int opcode)
Determine whether or not an opcode is a conditional or unconditional jump.
-
getOperand
private int getOperand(int offset)
-
getOperand
private int getOperand(int start, int size)
Extract a logical operand from the byte code.This is used, for example, to get branch offsets.
-
verify
private void verify()
Calculate initial local variable and op stack types for each super block in the method.
-
killSuperBlock
private void killSuperBlock(SuperBlock sb)
Replace the contents of a super block with no-ops.The above description is not strictly true; the last instruction is an athrow instruction. This technique is borrowed from ASM's developer guide: http://asm.ow2.org/doc/developer-guide.html#deadcode
The proposed algorithm fills a block with nop, ending it with an athrow. The stack map generated would be empty locals with an exception on the stack. In theory, it shouldn't matter what the locals are, as long as the stack has an exception for the athrow bit. However, it turns out that if the code being modified falls into an exception handler, it causes problems. Therefore, if it does, then we steal the locals from the exception block.
If the block itself is an exception handler, we remove it from the exception table to simplify block dependencies.
-
executeWorkList
private void executeWorkList()
-
executeBlock
private void executeBlock(SuperBlock work)
Simulate the local variable and op stack for a super block.
-
flowInto
private void flowInto(SuperBlock sb)
Perform a merge of type state and add the super block to the work list if the merge changed anything.
-
addToWorkList
private void addToWorkList(SuperBlock sb)
-
execute
private int execute(int bci)
Execute a single byte code instruction.- Parameters:
bci
- the index of the byte code instruction to execute- Returns:
- the length of the byte code instruction
-
executeALoad
private void executeALoad(int localIndex)
-
executeAStore
private void executeAStore(int localIndex)
-
executeStore
private void executeStore(int localIndex, int typeInfo)
-
initializeTypeInfo
private void initializeTypeInfo(int prevType, int newType)
Change an UNINITIALIZED_OBJECT or UNINITIALIZED_THIS to the proper type of the object. This occurs when the proper constructor is invoked.
-
initializeTypeInfo
private void initializeTypeInfo(int prevType, int newType, int[] data, int dataTop)
-
getLocal
private int getLocal(int localIndex)
-
setLocal
private void setLocal(int localIndex, int typeInfo)
-
push
private void push(int typeInfo)
-
pop
private int pop()
-
push2
private void push2(long typeInfo)
Push two words onto the op stack.This is only meant to be used as a complement to pop2(), and both methods are helpers for the more complex DUP operations.
-
pop2
private long pop2()
Pop two words from the op stack.If the top of the stack is a DOUBLE or LONG, then the bottom 32 bits reflects the appropriate type and the top 32 bits are 0. Otherwise, the top 32 bits are the first word on the stack and the lower 32 bits are the second word on the stack.
-
clearStack
private void clearStack()
-
computeWriteSize
int computeWriteSize()
Compute the output size of the stack map table.Because this would share much in common with actual writing of the stack map table, we instead just write the stack map table to a buffer and return the size from it. The buffer is later used in the actual writing of bytecode.
-
write
int write(byte[] data, int offset)
-
computeRawStackMap
private void computeRawStackMap()
Compute a space-optimal stack map table.
-
getWorstCaseWriteSize
private int getWorstCaseWriteSize()
Get the worst case write size of the stack map table.This computes how much full frames would take, if each full frame contained the maximum number of locals and stack operands, and each verification type was 3 bytes.
-
writeSameFrame
private void writeSameFrame(int offsetDelta)
-
writeSameLocalsOneStackItemFrame
private void writeSameLocalsOneStackItemFrame(int[] stack, int offsetDelta)
-
writeFullFrame
private void writeFullFrame(int[] locals, int[] stack, int offsetDelta)
-
writeAppendFrame
private void writeAppendFrame(int[] locals, int localsDelta, int offsetDelta)
-
writeChopFrame
private void writeChopFrame(int localsDelta, int offsetDelta)
-
writeTypes
private int writeTypes(int[] types)
-
writeTypes
private int writeTypes(int[] types, int start)
-
writeType
private int writeType(int type)
-
-