Class 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.
    • Field Detail

      • classFile

        private final ClassFile classFile
      • functionName

        private final java.lang.String functionName
      • maxStack

        private short maxStack
      • maxLocals

        private short maxLocals
      • code

        private byte[] code
      • 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
      • 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

      • getClassFile

        public ClassFile getClassFile()
        The ClassFile this context is related to.
      • 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 to saveLocalVariables() and later restoreLocalVariables().
        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 to saveLocalVariables() and later restoreLocalVariables().
        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 localvariabletable
        type - 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
      • 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 from
        code - 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 from
        code - 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. Creates CodeContext.LineNumberOffsets as necessary.
        Parameters:
        lineNumber - The line number that corresponds to the byte code, or -1
        b -
      • write

        public void write​(short lineNumber,
                          byte b1)
        Inserts a byte at the current insertion position. Creates CodeContext.LineNumberOffsets 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 -1
        b1 -
      • write

        public void write​(short lineNumber,
                          byte b1,
                          byte b2)
        Inserts bytes at the current insertion position. Creates CodeContext.LineNumberOffsets 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 -1
        b1 -
        b2 -
      • write

        public void write​(short lineNumber,
                          byte b1,
                          byte b2,
                          byte b3)
        Inserts bytes at the current insertion position. Creates CodeContext.LineNumberOffsets 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 -1
        b1 -
        b2 -
        b3 -
      • write

        public void write​(short lineNumber,
                          byte b1,
                          byte b2,
                          byte b3,
                          byte b4)
        Inserts bytes at the current insertion position. Creates CodeContext.LineNumberOffsets 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 -1
        b1 -
        b2 -
        b3 -
        b4 -
      • makeSpace

        public void makeSpace​(short lineNumber,
                              int size)
        Add space for size bytes at current offset. Creates CodeContext.LineNumberOffsets as necessary.
        Parameters:
        lineNumber - The line number that corresponds to the byte code, or -1
        size - 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 to Opcode.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.
      • 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