public class CodeContext
extends java.lang.Object
Modifier and Type | Class and 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 marks
CodeContext.Offset s
as "fix-ups": During the execution of
fixUp() , 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
An
CodeContext.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 |
Modifier and Type | Field and Description |
---|---|
private java.util.List<Java.LocalVariableSlot> |
allLocalVars
All the local variables that are allocated in any block in this
CodeContext . |
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 and Description |
---|
CodeContext(ClassFile classFile,
java.lang.String functionName)
Creates an empty "Code" attribute.
|
Modifier and Type | Method and 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 it
|
private static int |
extract32BitValue(int bias,
int offset,
byte[] code)
Extract a 32 bit value at offset in code and add bias to it
|
private 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()
The
ClassFile this context is related to. |
private static byte |
invertBranchOpcode(byte branchOpcode)
E.g.
|
void |
makeSpace(short lineNumber,
int size)
Add space for
size bytes at current offset. |
CodeContext.Inserter |
newInserter()
Allocate an
CodeContext.Inserter , set it to the current offset, and
insert it before the current offset. |
CodeContext.Offset |
newOffset()
Creates and inserts an
CodeContext.Offset at the current inserter's current position. |
void |
popInserter()
Replace the current
CodeContext.Inserter with the remembered one (see
pushInserter(CodeContext.Inserter) ). |
void |
pushInserter(CodeContext.Inserter ins)
Remember the current
CodeContext.Inserter , then replace it with the new one. |
private boolean |
relocate()
Relocate all relocatables and aggregate their response into a single one
|
void |
removeCode(CodeContext.Offset from,
CodeContext.Offset to)
Removes all code between
from and to . |
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) |
private static final boolean DEBUG
private static final int INITIAL_SIZE
private static final byte UNEXAMINED
private static final byte INVALID_OFFSET
private static final int MAX_STACK_SIZE
private final ClassFile classFile
private final java.lang.String functionName
private short maxStack
private short maxLocals
private byte[] code
private final CodeContext.Offset beginning
private final CodeContext.Inserter end
private CodeContext.Inserter currentInserter
private final java.util.List<CodeContext.ExceptionTableEntry> exceptionTableEntries
private final java.util.List<Java.LocalVariableSlot> allLocalVars
CodeContext
.private final java.util.List<java.util.List<Java.LocalVariableSlot>> scopedVars
private short nextLocalVariableSlot
private final java.util.List<CodeContext.Relocatable> relocatables
private static final java.util.Map<java.lang.Byte,java.lang.Byte> BRANCH_OPCODE_INVERSION
public CodeContext(ClassFile classFile, java.lang.String functionName)
public short allocateLocalVariable(short size)
saveLocalVariables()
and later restoreLocalVariables()
.size
- The number of slots to allocate (1 or 2)public Java.LocalVariableSlot allocateLocalVariable(short size, java.lang.String name, IClass type)
saveLocalVariables()
and later restoreLocalVariables()
.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 localvariabletablepublic java.util.List<Java.LocalVariableSlot> saveLocalVariables()
public void restoreLocalVariables()
protected void storeCodeAttributeBody(java.io.DataOutputStream dos, short lineNumberTableAttributeNameIndex, short localVariableTableAttributeNameIndex) throws java.io.IOException
dos
- lineNumberTableAttributeNameIndex
- 0 == don't generate a "LineNumberTable" attributejava.io.IOException
protected ClassFile.AttributeInfo storeLocalVariableTable(java.io.DataOutputStream dos, short localVariableTableAttributeNameIndex)
ClassFile.LocalVariableTableAttribute
for this CodeContext
public void flowAnalysis(java.lang.String functionName)
private void flowAnalysis(java.lang.String functionName, byte[] code, int codeSize, int offset, short stackSize, short[] stackSizes)
private static int extract16BitValue(int bias, int offset, byte[] code)
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 bytesprivate static int extract32BitValue(int bias, int offset, byte[] code)
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 bytespublic void fixUpAndRelocate()
private void fixUp()
private boolean relocate()
private int determineFieldSize(short idx)
private int determineArgumentsSize(short idx)
public void write(short lineNumber, byte[] b)
CodeContext.LineNumberOffset
s as necessary.lineNumber
- The line number that corresponds to the byte code, or -1b
- public void write(short lineNumber, byte b1)
CodeContext.LineNumberOffset
s as necessary.
This method is an optimization to avoid allocating small byte[] and ease GC load.
lineNumber
- The line number that corresponds to the byte code, or -1b1
- public void write(short lineNumber, byte b1, byte b2)
CodeContext.LineNumberOffset
s as necessary.
This method is an optimization to avoid allocating small byte[] and ease GC load.
lineNumber
- The line number that corresponds to the byte code, or -1b1
- b2
- public void write(short lineNumber, byte b1, byte b2, byte b3)
CodeContext.LineNumberOffset
s as necessary.
This method is an optimization to avoid allocating small byte[] and ease GC load.
lineNumber
- The line number that corresponds to the byte code, or -1b1
- b2
- b3
- public void write(short lineNumber, byte b1, byte b2, byte b3, byte b4)
CodeContext.LineNumberOffset
s as necessary.
This method is an optimization to avoid allocating small byte[] and ease GC load.
lineNumber
- The line number that corresponds to the byte code, or -1b1
- b2
- b3
- b4
- public void makeSpace(short lineNumber, int size)
size
bytes at current offset. Creates CodeContext.LineNumberOffset
s as necessary.lineNumber
- The line number that corresponds to the byte code, or -1size
- The size in bytes to injectpublic void writeShort(short lineNumber, int v)
lineNumber
- The line number that corresponds to the byte code, or -1public void writeBranch(short lineNumber, int opcode, CodeContext.Offset dst)
lineNumber
- The line number that corresponds to the byte code, or -1private static byte invertBranchOpcode(byte branchOpcode)
Opcode.IFLT
("less than") inverts to Opcode.IFGE
("greater than or equal to").private static java.util.Map<java.lang.Byte,java.lang.Byte> createBranchOpcodeInversion()
public void writeOffset(short lineNumber, CodeContext.Offset src, CodeContext.Offset dst)
public CodeContext.Offset newOffset()
CodeContext.Offset
at the current inserter's current position.public CodeContext.Inserter newInserter()
CodeContext.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, then pushInserter(CodeContext.Inserter)
the
CodeContext.Inserter
, then write again (which inserts bytes into the
"Code" attribute at the previously remembered position), and then
popInserter()
.public CodeContext.Inserter currentInserter()
public void pushInserter(CodeContext.Inserter ins)
CodeContext.Inserter
, then replace it with the new one.public void popInserter()
CodeContext.Inserter
with the remembered one (see
pushInserter(CodeContext.Inserter)
).public void addExceptionTableEntry(CodeContext.Offset startPc, CodeContext.Offset endPc, CodeContext.Offset handlerPc, java.lang.String catchTypeFd)
catchTypeFd
- null == "finally" clausepublic java.util.List<Java.LocalVariableSlot> getAllLocalVars()
CodeContext
public void removeCode(CodeContext.Offset from, CodeContext.Offset to)
from
and to
. Also removes any CodeContext.Relocatable
s existing
in that range.