Package org.codehaus.janino
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 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.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 'LneNumberTable' attribute.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.Byte,java.lang.Byte>
BRANCH_OPCODE_INVERSION
private ClassFile
classFile
private byte[]
code
private CodeContext.Inserter
currentInserter
private static boolean
DEBUG
private CodeContext.Inserter
end
private java.util.List<CodeContext.ExceptionTableEntry>
exceptionTableEntries
private java.lang.String
functionName
private static int
INITIAL_SIZE
private static byte
INVALID_OFFSET
private static int
MAX_STACK_SIZE
private short
maxLocals
private short
maxStack
private short
nextLocalVariableSlot
private java.util.List<CodeContext.Relocatable>
relocatables
private java.util.List<java.util.List<Java.LocalVariableSlot>>
scopedVars
List of List of Java.LocalVariableSlot objects.private static byte
UNEXAMINED
-
Constructor Summary
Constructors Constructor Description CodeContext(ClassFile classFile, java.lang.String functionName)
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)
Add another entry to the "exception_table" of this code attribute (see JVMS 4.7.3).short
allocateLocalVariable(short size)
Allocate 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, IClass type)
Allocate space for a local variable of the given size (1 or 2) on the local variable array.private static java.util.Map<java.lang.Byte,java.lang.Byte>
createBranchOpcodeInversion()
CodeContext.Inserter
currentInserter()
private int
determineArgumentsSize(short idx)
Analyse the descriptor of the Methodref and return the sum of the arguments' sizes minus the return value's size.private int
determineFieldSize(short idx)
Analyses the descriptor of the Fieldref and return its size.private static int
extract16BitValue(int bias, int offset, byte[] code)
Extract a 16 bit value at offset in code and add bias to itprivate static int
extract32BitValue(int bias, int offset, byte[] code)
Extract a 32 bit value at offset in code and add bias to itprivate void
fixUp()
Fixes up all offsets.void
fixUpAndRelocate()
Fixes up all of the offsets and relocate() all relocatables.void
flowAnalysis(java.lang.String functionName)
Checks the code for consistency; updates the "maxStack" member.private void
flowAnalysis(java.lang.String functionName, byte[] code, int codeSize, int offset, short stackSize, short[] stackSizes)
java.util.List<Java.LocalVariableSlot>
getAllLocalVars()
ClassFile
getClassFile()
TheClassFile
this context is related to.private static byte
invertBranchOpcode(byte branchOpcode)
E.g.void
makeSpace(short lineNumber, int size)
Add space forsize
bytes at current offset.CodeContext.Inserter
newInserter()
Allocate anCodeContext.Inserter
, set it to the current offset, and insert it before the current offset.CodeContext.Offset
newOffset()
Creates and inserts anCodeContext.Offset
at the current inserter's current position.void
popInserter()
Replace the currentCodeContext.Inserter
with the remembered one (seepushInserter(CodeContext.Inserter)
).void
pushInserter(CodeContext.Inserter ins)
Remember the currentCodeContext.Inserter
, then replace it with the new one.private boolean
relocate()
Relocate all relocatables and aggregate their response into a single onevoid
removeCode(CodeContext.Offset from, CodeContext.Offset to)
Removes all code betweenfrom
andto
.void
restoreLocalVariables()
Restore the previous size of the local variables array.java.util.List<Java.LocalVariableSlot>
saveLocalVariables()
Remembers the current size of the local variables array.protected void
storeCodeAttributeBody(java.io.DataOutputStream dos, short lineNumberTableAttributeNameIndex, short localVariableTableAttributeNameIndex)
protected ClassFile.AttributeInfo
storeLocalVariableTable(java.io.DataOutputStream dos, short localVariableTableAttributeNameIndex)
void
write(short lineNumber, byte b1)
Inserts a byte at the current insertion position.void
write(short lineNumber, byte[] b)
Inserts a sequence of bytes at the current insertion position.void
write(short lineNumber, byte b1, byte b2)
Inserts bytes at the current insertion position.void
write(short lineNumber, byte b1, byte b2, byte b3)
Inserts bytes at the current insertion position.void
write(short lineNumber, byte b1, byte b2, byte b3, byte b4)
Inserts bytes at the current insertion position.void
writeBranch(short lineNumber, int opcode, CodeContext.Offset dst)
void
writeOffset(short lineNumber, 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(short lineNumber, int v)
-
-
-
Field Detail
-
DEBUG
private static final boolean DEBUG
- See Also:
- Constant Field Values
-
INITIAL_SIZE
private static final int INITIAL_SIZE
- See Also:
- Constant Field Values
-
UNEXAMINED
private static final byte UNEXAMINED
- See Also:
- Constant Field Values
-
INVALID_OFFSET
private static final byte INVALID_OFFSET
- See Also:
- Constant Field Values
-
MAX_STACK_SIZE
private static final int MAX_STACK_SIZE
- See Also:
- Constant Field Values
-
classFile
private final ClassFile classFile
-
functionName
private final java.lang.String functionName
-
maxStack
private short 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
.
-
scopedVars
private final java.util.List<java.util.List<Java.LocalVariableSlot>> scopedVars
List of List of Java.LocalVariableSlot objects. Each List of Java.LocalVariableSlot is the local variables allocated for a block. They are pushed and poped 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.Byte,java.lang.Byte> BRANCH_OPCODE_INVERSION
-
-
Constructor Detail
-
CodeContext
public CodeContext(ClassFile classFile, java.lang.String functionName)
Creates an empty "Code" attribute.
-
-
Method Detail
-
allocateLocalVariable
public short allocateLocalVariable(short size)
Allocate 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 tosaveLocalVariables()
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, java.lang.String name, IClass type)
Allocate 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 tosaveLocalVariables()
and laterrestoreLocalVariables()
.- Parameters:
size
- Number of slots to use (1 or 2)name
- The variable name, if it's null, the variable won't be written to the localvariabletabletype
- The variable type. if the name isn't null, 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()
Restore 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.
-
storeCodeAttributeBody
protected void storeCodeAttributeBody(java.io.DataOutputStream dos, short lineNumberTableAttributeNameIndex, short localVariableTableAttributeNameIndex) throws java.io.IOException
- Parameters:
dos
-lineNumberTableAttributeNameIndex
- 0 == don't generate a "LineNumberTable" attribute- Throws:
java.io.IOException
-
storeLocalVariableTable
protected ClassFile.AttributeInfo storeLocalVariableTable(java.io.DataOutputStream dos, short localVariableTableAttributeNameIndex)
- Returns:
- A
ClassFile.LocalVariableTableAttribute
for thisCodeContext
-
flowAnalysis
public void flowAnalysis(java.lang.String functionName)
Checks the code for consistency; updates the "maxStack" member. Notice: On inconsistencies, a "RuntimeException" is thrown (KLUDGE).
-
flowAnalysis
private void flowAnalysis(java.lang.String functionName, byte[] code, int codeSize, int offset, short stackSize, short[] stackSizes)
-
extract16BitValue
private static int extract16BitValue(int bias, int offset, byte[] code)
Extract a 16 bit value at offset in code and add bias to it- Parameters:
bias
- An int to skew the final result by (useful for calculating relative offsets)offset
- The position in the code array to extract the bytes fromcode
- The array of bytes- Returns:
- An integer that treats the two bytes at position offset as an UNSIGNED SHORT
-
extract32BitValue
private static int extract32BitValue(int bias, int offset, byte[] code)
Extract a 32 bit value at offset in code and add bias to it- Parameters:
bias
- An int to skew the final result by (useful for calculating relative offsets)offset
- The position in the code array to extract the bytes fromcode
- The array of bytes- Returns:
- The 4 bytes at position offset + bias
-
fixUpAndRelocate
public void fixUpAndRelocate()
Fixes up all of the offsets and relocate() all relocatables.
-
fixUp
private void fixUp()
Fixes up all offsets.
-
relocate
private boolean relocate()
Relocate all relocatables and aggregate their response into a single one- Returns:
- true if all of them relocated successfully false if any of them needed to change size
-
determineFieldSize
private int determineFieldSize(short idx)
Analyses the descriptor of the Fieldref and return its size.
-
determineArgumentsSize
private int determineArgumentsSize(short idx)
Analyse the descriptor of the Methodref and return the sum of the arguments' sizes minus the return value's size.
-
write
public void write(short lineNumber, byte[] b)
Inserts a sequence of bytes at the current insertion position. CreatesCodeContext.LineNumberOffset
s as necessary.- Parameters:
lineNumber
- The line number that corresponds to the byte code, or -1b
-
-
write
public void write(short lineNumber, 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.
- Parameters:
lineNumber
- The line number that corresponds to the byte code, or -1b1
-
-
write
public void write(short lineNumber, 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.
- Parameters:
lineNumber
- The line number that corresponds to the byte code, or -1b1
-b2
-
-
write
public void write(short lineNumber, 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.
- Parameters:
lineNumber
- The line number that corresponds to the byte code, or -1b1
-b2
-b3
-
-
write
public void write(short lineNumber, 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.
- Parameters:
lineNumber
- The line number that corresponds to the byte code, or -1b1
-b2
-b3
-b4
-
-
makeSpace
public void makeSpace(short lineNumber, int size)
Add space forsize
bytes at current offset. CreatesCodeContext.LineNumberOffset
s as necessary.- Parameters:
lineNumber
- The line number that corresponds to the byte code, or -1size
- The size in bytes to inject
-
writeShort
public void writeShort(short lineNumber, int v)
- Parameters:
lineNumber
- The line number that corresponds to the byte code, or -1
-
writeBranch
public void writeBranch(short lineNumber, int opcode, CodeContext.Offset dst)
- Parameters:
lineNumber
- The line number that corresponds to the byte code, or -1
-
invertBranchOpcode
private static byte invertBranchOpcode(byte branchOpcode)
E.g.Opcode.IFLT
("less than") inverts toOpcode.IFGE
("greater than or equal to").
-
createBranchOpcodeInversion
private static java.util.Map<java.lang.Byte,java.lang.Byte> createBranchOpcodeInversion()
-
writeOffset
public void writeOffset(short lineNumber, 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.
-
newInserter
public CodeContext.Inserter newInserter()
Allocate anCodeContext.Inserter
, set it to the current offset, and insert it before the current offset. In clear text, this means that you can continue writing to the "Code" attribute, thenpushInserter(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)
Remember the currentCodeContext.Inserter
, then replace it with the new one.
-
popInserter
public void popInserter()
Replace the currentCodeContext.Inserter
with the remembered one (seepushInserter(CodeContext.Inserter)
).
-
addExceptionTableEntry
public void addExceptionTableEntry(CodeContext.Offset startPc, CodeContext.Offset endPc, CodeContext.Offset handlerPc, java.lang.String catchTypeFd)
Add another entry to the "exception_table" of this code attribute (see JVMS 4.7.3).- Parameters:
catchTypeFd
- null == "finally" 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 betweenfrom
andto
. Also removes anyCodeContext.Relocatable
s existing in that range.
-
-