Class CodeContext
- java.lang.Object
-
- org.codehaus.janino.CodeContext
-
public class CodeContext extends java.lang.Object
The context of the compilation of a function (constructor or method). Manages generation of byte code, the exception table, generation of line number tables, allocation of local variables, determining of stack size and local variable table size and flow analysis.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description class
CodeContext.BasicBlock
ThisCodeContext.Offset
marks the first byte of a "basic block" in the sense of JLS 17 "4.10.1 Verification by Type Checking": The intent is that a stack map frame must appear at the beginning of each basic block in a method.private class
CodeContext.Branch
private static class
CodeContext.ExceptionTableEntry
Representation of an entry in the "exception_table" of a "Code" attribute (see JVMS 4.7.3).static interface
CodeContext.FixUp
A throw-in interface that marksCodeContext.Offset
s as "fix-ups": During the execution offixUp()
, all "fix-ups" are invoked and can do last touches to the code attribute.private class
CodeContext.FourByteOffset
class
CodeContext.Inserter
A class that implements an insertion point into a "Code" attribute.class
CodeContext.LineNumberOffset
AnCodeContext.Offset
who's sole purpose is to later create a 'LineNumberTable' attribute.(package private) static class
CodeContext.LocalScope
class
CodeContext.Offset
A class that represents an offset within a "Code" attribute.private class
CodeContext.OffsetBranch
private class
CodeContext.Relocatable
-
Field Summary
Fields Modifier and Type Field Description private java.util.List<Java.LocalVariableSlot>
allLocalVars
All the local variables that are allocated in any block in thisCodeContext
.private CodeContext.Offset
beginning
private static java.util.Map<java.lang.Integer,java.lang.Integer>
BRANCH_OPCODE_INVERSION
private ClassFile
classFile
private byte[]
code
private CodeContext.Inserter
currentInserter
private CodeContext.LocalScope
currentLocalScope
Each List of Java.LocalVariableSlot is the local variables allocated for a block.private CodeContext.Inserter
end
private java.util.List<CodeContext.ExceptionTableEntry>
exceptionTableEntries
private static int
INITIAL_SIZE
private short
maxLocals
private int
maxStack
private short
nextLocalVariableSlot
private java.util.List<CodeContext.Relocatable>
relocatables
private static boolean
SUPPRESS_STACK_MAP_TABLE
-
Constructor Summary
Constructors Constructor Description CodeContext(ClassFile classFile)
Creates an empty "Code" attribute.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addExceptionTableEntry(CodeContext.Offset startPc, CodeContext.Offset endPc, CodeContext.Offset handlerPc, java.lang.String catchTypeFd)
Adds another entry to the "exception_table" of this code attribute (see JVMS 4.7.3).void
addLineNumberOffset(int lineNumber)
short
allocateLocalVariable(short size)
Allocates space for a local variable of the given size (1 or 2) on the local variable array.Java.LocalVariableSlot
allocateLocalVariable(short size, java.lang.String name, IType type)
Allocates space for a local variable of the given size (1 or 2) on the local variable array.private static java.util.Map<java.lang.Integer,java.lang.Integer>
createBranchOpcodeInversion()
CodeContext.Inserter
currentInserter()
private void
fixUp()
Fixes up all offsets.void
fixUpAndRelocate()
Fixes up all of the offsets and relocate() all relocatables.java.util.List<Java.LocalVariableSlot>
getAllLocalVars()
ClassFile
getClassFile()
TheClassFile
this context is related to.private static int
invertBranchOpcode(int branchOpcode)
E.g.int
makeSpace(int size)
Inserts size NUL bytes at the current inserter's offset, advances the current inserter's offset by size, createsCodeContext.LineNumberOffset
s as necessary, and returns the current inserter's original offset (the offset of the first NUL byte that was inserted).private void
maybeGrow()
Grow the code if relocatables are required to.private static StackMap
mergeStackMaps(StackMap sm1, StackMap sm2)
CodeContext.Offset
newBasicBlock()
ClassFile.CodeAttribute
newCodeAttribute(int initialLocalsCount, boolean debugLines, boolean debugVars)
CodeContext.Inserter
newInserter()
Allocates anCodeContext.Inserter
, set it to the current offset, and inserts it before the current offset.private ClassFile.LineNumberTableAttribute
newLineNumberTableAttribute()
protected ClassFile.LocalVariableTableAttribute
newLocalVariableTableAttribute()
CodeContext.Offset
newOffset()
Creates and inserts anCodeContext.Offset
at the current inserter's current position.private ClassFile.StackMapTableAttribute
newStackMapTableAttribute(int initialLocalsCount)
boolean
peekNullOperand()
boolean
peekObjectOperand()
ClassFile.StackMapTableAttribute.VerificationTypeInfo
peekOperand()
void
popInserter()
Replaces the currentCodeContext.Inserter
with the remembered one (seepushInserter(CodeContext.Inserter)
).void
popIntOperand()
Asserts that the top operand is aninteger_variable_info
and pops it.ClassFile.StackMapTableAttribute.VerificationTypeInfo
popIntOrLongOperand()
Asserts that the top operand is anint_variable_info
orlong_variable_info
, then pops and returns it.void
popLongOperand()
Asserts that the top operand is along_variable_info
and pops it.void
popNullOperand()
java.lang.String
popObjectOperand()
Asserts that the top operand is anobject_variable_info
, and pops it.ClassFile.StackMapTableAttribute.VerificationTypeInfo
popObjectOrUninitializedOrUninitializedThisOperand()
Asserts that the top operand is anobject_variable_info
,uninitialized_variable_info
oruninitializedThis_variable_info
, and pops it.ClassFile.StackMapTableAttribute.VerificationTypeInfo
popOperand()
Pops one entry from the current inserter's operand stack.void
popOperand(java.lang.String expectedFd)
Pops the top operand, asserts that it is aninteger_variable_info
,long_variable_info
,float_variable_info
,double_variable_info
orvariable_object_info
, and asserts that it matches the given field descriptor.void
popOperand(ClassFile.StackMapTableAttribute.VerificationTypeInfo expected)
Pops the top entry from the operand stack and assert that it equals expected.void
popOperandAssignableTo(java.lang.String declaredFd)
void
popReferenceOperand()
Asserts that the top operand is anobject_variable_info
or anull_variable_info
and pops it.void
popUninitializedThisOperand()
Asserts that the top operand is anuninitializedThis_variable_info
and pops it.void
popUninitializedVariableOperand()
Asserts that the top operand is anuninitialized_variable_info
and pops it.void
pushDoubleOperand()
void
pushFloatOperand()
void
pushInserter(CodeContext.Inserter ins)
Remembers the currentCodeContext.Inserter
, then replaces it with the new one.void
pushIntOperand()
void
pushLongOperand()
void
pushNullOperand()
void
pushObjectOperand(java.lang.String fieldDescriptor)
void
pushOperand(java.lang.String fieldDescriptor)
Pushes oneobject_variable_info
,integer_variable_info
,double_variable_info
,float_variable_info
orlong_variable_info
entry onto the current inserter's operand stack.void
pushOperand(ClassFile.StackMapTableAttribute.VerificationTypeInfo topOperand)
void
pushTopOperand()
void
pushUninitializedOperand()
void
pushUninitializedThisOperand()
private static IClass
rawTypeOf(IType iType)
private void
relocate()
Relocates all relocatables.void
removeCode(CodeContext.Offset from, CodeContext.Offset to)
Removes all code between from and to.void
restoreLocalVariables()
Restores the previous size of the local variables array.java.util.List<Java.LocalVariableSlot>
saveLocalVariables()
Remembers the current size of the local variables array.java.lang.String
toString()
void
write(byte b1)
Inserts a byte at the current insertion position.void
write(byte[] b)
Inserts a sequence of bytes at the current insertion position.void
write(byte b1, byte b2)
Inserts bytes at the current insertion position.void
write(byte b1, byte b2, byte b3)
Inserts bytes at the current insertion position.void
write(byte b1, byte b2, byte b3, byte b4)
Inserts bytes at the current insertion position.void
write(byte b1, byte b2, byte b3, byte b4, byte b5)
Inserts bytes at the current insertion position.void
writeBranch(int opcode, CodeContext.Offset dst)
Generates a "branch" instruction.void
writeOffset(CodeContext.Offset src, CodeContext.Offset dst)
Writes a four-byte offset (as it is used in TABLESWITCH and LOOKUPSWITCH) into this code context.void
writeShort(int v)
-
-
-
Field Detail
-
SUPPRESS_STACK_MAP_TABLE
private static final boolean SUPPRESS_STACK_MAP_TABLE
-
INITIAL_SIZE
private static final int INITIAL_SIZE
- See Also:
- Constant Field Values
-
classFile
private final ClassFile classFile
-
maxStack
private int maxStack
-
maxLocals
private short maxLocals
-
code
private byte[] code
-
beginning
private final CodeContext.Offset beginning
-
end
private final CodeContext.Inserter end
-
currentInserter
private CodeContext.Inserter currentInserter
-
exceptionTableEntries
private final java.util.List<CodeContext.ExceptionTableEntry> exceptionTableEntries
-
allLocalVars
private final java.util.List<Java.LocalVariableSlot> allLocalVars
All the local variables that are allocated in any block in thisCodeContext
.
-
currentLocalScope
@Nullable private CodeContext.LocalScope currentLocalScope
Each List of Java.LocalVariableSlot is the local variables allocated for a block. They are pushed and popped onto the list together to make allocation of the next local variable slot easy.
-
nextLocalVariableSlot
private short nextLocalVariableSlot
-
relocatables
private final java.util.List<CodeContext.Relocatable> relocatables
-
BRANCH_OPCODE_INVERSION
private static final java.util.Map<java.lang.Integer,java.lang.Integer> BRANCH_OPCODE_INVERSION
-
-
Constructor Detail
-
CodeContext
public CodeContext(ClassFile classFile)
Creates an empty "Code" attribute.
-
-
Method Detail
-
allocateLocalVariable
public short allocateLocalVariable(short size)
Allocates space for a local variable of the given size (1 or 2) on the local variable array.As a side effect, the "max_locals" field of the "Code" attribute is updated.
The only way to deallocate local variables is to
saveLocalVariables()
and laterrestoreLocalVariables()
.- Parameters:
size
- The number of slots to allocate (1 or 2)- Returns:
- The slot index of the allocated variable
-
allocateLocalVariable
public Java.LocalVariableSlot allocateLocalVariable(short size, @Nullable java.lang.String name, @Nullable IType type)
Allocates space for a local variable of the given size (1 or 2) on the local variable array. As a side effect, the "max_locals" field of the "Code" attribute is updated.The only way to deallocate local variables is to
saveLocalVariables()
and laterrestoreLocalVariables()
.- Parameters:
size
- Number of slots to use (1 or 2)name
- The variable name; ifnull
, then the variable won't be written to the LocalVariableTabletype
- The variable type; if the name is not null, then the type is needed to write to the LocalVariableTable
-
saveLocalVariables
public java.util.List<Java.LocalVariableSlot> saveLocalVariables()
Remembers the current size of the local variables array.
-
restoreLocalVariables
public void restoreLocalVariables()
Restores the previous size of the local variables array. This MUST to be called for every call to saveLocalVariables as it closes the variable extent for all the active local variables in the current block.
-
newCodeAttribute
public ClassFile.CodeAttribute newCodeAttribute(int initialLocalsCount, boolean debugLines, boolean debugVars)
- Parameters:
initialLocalsCount
- The number of parameters, plus one iff there is a "this" parameter
-
newLineNumberTableAttribute
private ClassFile.LineNumberTableAttribute newLineNumberTableAttribute()
-
newStackMapTableAttribute
@Nullable private ClassFile.StackMapTableAttribute newStackMapTableAttribute(int initialLocalsCount)
- Returns:
null
iff the stack map is empty
-
newLocalVariableTableAttribute
@Nullable protected ClassFile.LocalVariableTableAttribute newLocalVariableTableAttribute()
- Returns:
- A
ClassFile.LocalVariableTableAttribute
for thisCodeContext
-
fixUpAndRelocate
public void fixUpAndRelocate()
Fixes up all of the offsets and relocate() all relocatables.
-
maybeGrow
private void maybeGrow()
Grow the code if relocatables are required to.
-
fixUp
private void fixUp()
Fixes up all offsets.
-
relocate
private void relocate()
Relocates all relocatables.
-
write
public void write(byte[] b)
Inserts a sequence of bytes at the current insertion position. CreatesCodeContext.LineNumberOffset
s as necessary.
-
write
public void write(byte b1)
Inserts a byte at the current insertion position. CreatesCodeContext.LineNumberOffset
s as necessary.This method is an optimization to avoid allocating small byte[] and ease GC load.
-
write
public void write(byte b1, byte b2)
Inserts bytes at the current insertion position. CreatesCodeContext.LineNumberOffset
s as necessary.This method is an optimization to avoid allocating small byte[] and ease GC load.
-
write
public void write(byte b1, byte b2, byte b3)
Inserts bytes at the current insertion position. CreatesCodeContext.LineNumberOffset
s as necessary.This method is an optimization to avoid allocating small byte[] and ease GC load.
-
write
public void write(byte b1, byte b2, byte b3, byte b4)
Inserts bytes at the current insertion position. CreatesCodeContext.LineNumberOffset
s as necessary.This method is an optimization to avoid allocating small byte[] and ease GC load.
-
write
public void write(byte b1, byte b2, byte b3, byte b4, byte b5)
Inserts bytes at the current insertion position. CreatesCodeContext.LineNumberOffset
s as necessary.This method is an optimization to avoid allocating small byte[] and ease GC load.
-
addLineNumberOffset
public void addLineNumberOffset(int lineNumber)
-
makeSpace
public int makeSpace(int size)
Inserts size NUL bytes at the current inserter's offset, advances the current inserter's offset by size, createsCodeContext.LineNumberOffset
s as necessary, and returns the current inserter's original offset (the offset of the first NUL byte that was inserted).Because the class file format does not support line numbers greater than 65535, these are treated as 65535.
- Parameters:
size
- The number of NUL bytes to inject- Returns:
- The offset of the first inserted byte
-
writeShort
public void writeShort(int v)
-
writeBranch
public void writeBranch(int opcode, CodeContext.Offset dst)
Generates a "branch" instruction.- Parameters:
opcode
- One ofOpcode.GOTO
,Opcode.JSR
andOpcode.IF*
dst
- Where to branch
-
invertBranchOpcode
private static int invertBranchOpcode(int branchOpcode)
E.g.Opcode.IFLT
("less than") inverts toOpcode.IFGE
("greater than or equal to").
-
createBranchOpcodeInversion
private static java.util.Map<java.lang.Integer,java.lang.Integer> createBranchOpcodeInversion()
-
writeOffset
public void writeOffset(CodeContext.Offset src, CodeContext.Offset dst)
Writes a four-byte offset (as it is used in TABLESWITCH and LOOKUPSWITCH) into this code context.
-
newOffset
public CodeContext.Offset newOffset()
Creates and inserts anCodeContext.Offset
at the current inserter's current position.
-
newBasicBlock
public CodeContext.Offset newBasicBlock()
-
newInserter
public CodeContext.Inserter newInserter()
Allocates anCodeContext.Inserter
, set it to the current offset, and inserts it before the current offset.In clear text, this means that you can continue writing to the "Code" attribute, then
pushInserter(CodeContext.Inserter)
theCodeContext.Inserter
, then write again (which inserts bytes into the "Code" attribute at the previously remembered position), and thenpopInserter()
.
-
currentInserter
public CodeContext.Inserter currentInserter()
- Returns:
- The current inserter
-
pushInserter
public void pushInserter(CodeContext.Inserter ins)
Remembers the currentCodeContext.Inserter
, then replaces it with the new one.
-
popInserter
public void popInserter()
Replaces the currentCodeContext.Inserter
with the remembered one (seepushInserter(CodeContext.Inserter)
).
-
mergeStackMaps
@Nullable private static final StackMap mergeStackMaps(@Nullable StackMap sm1, @Nullable StackMap sm2)
-
addExceptionTableEntry
public void addExceptionTableEntry(CodeContext.Offset startPc, CodeContext.Offset endPc, CodeContext.Offset handlerPc, @Nullable java.lang.String catchTypeFd)
Adds another entry to the "exception_table" of this code attribute (see JVMS 4.7.3).- Parameters:
catchTypeFd
-null
meansfinally
clause
-
getAllLocalVars
public java.util.List<Java.LocalVariableSlot> getAllLocalVars()
- Returns:
- All the local variables that are allocated in any block in this
CodeContext
-
removeCode
public void removeCode(CodeContext.Offset from, CodeContext.Offset to)
Removes all code between from and to. Also removes anyCodeContext.Relocatable
s existing in that range.
-
toString
public java.lang.String toString()
- Overrides:
toString
in classjava.lang.Object
-
pushOperand
public void pushOperand(java.lang.String fieldDescriptor)
Pushes oneobject_variable_info
,integer_variable_info
,double_variable_info
,float_variable_info
orlong_variable_info
entry onto the current inserter's operand stack.
-
pushTopOperand
public void pushTopOperand()
-
pushIntOperand
public void pushIntOperand()
-
pushLongOperand
public void pushLongOperand()
-
pushFloatOperand
public void pushFloatOperand()
-
pushDoubleOperand
public void pushDoubleOperand()
-
pushNullOperand
public void pushNullOperand()
-
pushUninitializedThisOperand
public void pushUninitializedThisOperand()
-
pushUninitializedOperand
public void pushUninitializedOperand()
-
pushObjectOperand
public void pushObjectOperand(java.lang.String fieldDescriptor)
-
pushOperand
public void pushOperand(ClassFile.StackMapTableAttribute.VerificationTypeInfo topOperand)
-
peekNullOperand
public boolean peekNullOperand()
- Returns:
- Whether the top operand is a
null_variable_info
-
peekObjectOperand
public boolean peekObjectOperand()
- Returns:
- Whether the top operand is a
object_variable_info
-
peekOperand
public ClassFile.StackMapTableAttribute.VerificationTypeInfo peekOperand()
- Returns:
- The verification type of the top operand
-
popOperand
public ClassFile.StackMapTableAttribute.VerificationTypeInfo popOperand()
Pops one entry from the current inserter's operand stack.
-
popOperand
public void popOperand(ClassFile.StackMapTableAttribute.VerificationTypeInfo expected)
Pops the top entry from the operand stack and assert that it equals expected.
-
popOperand
public void popOperand(java.lang.String expectedFd)
Pops the top operand, asserts that it is aninteger_variable_info
,long_variable_info
,float_variable_info
,double_variable_info
orvariable_object_info
, and asserts that it matches the given field descriptor.
-
popOperandAssignableTo
public void popOperandAssignableTo(java.lang.String declaredFd)
-
popIntOperand
public void popIntOperand()
Asserts that the top operand is aninteger_variable_info
and pops it.
-
popLongOperand
public void popLongOperand()
Asserts that the top operand is along_variable_info
and pops it.
-
popUninitializedThisOperand
public void popUninitializedThisOperand()
Asserts that the top operand is anuninitializedThis_variable_info
and pops it.
-
popUninitializedVariableOperand
public void popUninitializedVariableOperand()
Asserts that the top operand is anuninitialized_variable_info
and pops it.
-
popReferenceOperand
public void popReferenceOperand()
Asserts that the top operand is anobject_variable_info
or anull_variable_info
and pops it.
-
popNullOperand
public void popNullOperand()
-
popObjectOperand
public java.lang.String popObjectOperand()
Asserts that the top operand is anobject_variable_info
, and pops it.- Returns:
- The field descriptor of the popped object operand
-
popObjectOrUninitializedOrUninitializedThisOperand
public ClassFile.StackMapTableAttribute.VerificationTypeInfo popObjectOrUninitializedOrUninitializedThisOperand()
Asserts that the top operand is anobject_variable_info
,uninitialized_variable_info
oruninitializedThis_variable_info
, and pops it.
-
popIntOrLongOperand
public ClassFile.StackMapTableAttribute.VerificationTypeInfo popIntOrLongOperand()
Asserts that the top operand is anint_variable_info
orlong_variable_info
, then pops and returns it.
-
-