Class CodeContext

java.lang.Object
org.codehaus.janino.CodeContext

public class CodeContext extends 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 Details

  • Constructor Details

    • CodeContext

      public CodeContext(ClassFile classFile)
      Creates an empty "Code" attribute.
  • Method Details

    • getClassFile

      public ClassFile getClassFile()
      The ClassFile this context is related to.
    • 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 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, @Nullable 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 later restoreLocalVariables().

      Parameters:
      size - Number of slots to use (1 or 2)
      name - The variable name; if null, then the variable won't be written to the LocalVariableTable
      type - The variable type; if the name is not null, then the type is needed to write to the LocalVariableTable
    • saveLocalVariables

      public 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(boolean debugLines, boolean debugVars)
    • newLineNumberTableAttribute

      private ClassFile.LineNumberTableAttribute newLineNumberTableAttribute()
    • newStackMapTableAttribute

      private ClassFile.StackMapTableAttribute newStackMapTableAttribute()
    • rawTypeOf

      private static IClass rawTypeOf(IType iType)
    • newLocalVariableTableAttribute

      @Nullable protected ClassFile.LocalVariableTableAttribute newLocalVariableTableAttribute()
      Returns:
      A ClassFile.LocalVariableTableAttribute for this CodeContext
    • 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. Creates CodeContext.LineNumberOffsets as necessary.
    • write

      public void write(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.

    • write

      public void write(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.

    • write

      public void write(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.

    • write

      public void write(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.

    • 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, creates CodeContext.LineNumberOffsets 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 of Opcode.GOTO, Opcode.JSR and Opcode.IF*
      dst - Where to branch
    • invertBranchOpcode

      private static int invertBranchOpcode(int branchOpcode)
      E.g. Opcode.IFLT ("less than") inverts to Opcode.IFGE ("greater than or equal to").
    • createBranchOpcodeInversion

      private static Map<Integer,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 an CodeContext.Offset at the current inserter's current position.
    • newInserter

      public CodeContext.Inserter newInserter()
      Allocates an CodeContext.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) the CodeContext.Inserter, then write again (which inserts bytes into the "Code" attribute at the previously remembered position), and then popInserter().

    • currentInserter

      public CodeContext.Inserter currentInserter()
      Returns:
      The current inserter
    • pushInserter

      public void pushInserter(CodeContext.Inserter ins)
      Remembers the current CodeContext.Inserter, then replaces it with the new one.
    • popInserter

      public void popInserter()
      Replaces the current CodeContext.Inserter with the remembered one (see pushInserter(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 String catchTypeFd)
      Adds another entry to the "exception_table" of this code attribute (see JVMS 4.7.3).
      Parameters:
      catchTypeFd - null means finally clause
    • getAllLocalVars

      public 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 any CodeContext.Relocatables existing in that range.
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • pushOperand

      public void pushOperand(String fieldDescriptor)
      Pushes one object_variable_info, integer_variable_info, double_variable_info, float_variable_info or long_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(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

      Returns:
      The verification type of the top operand
    • 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(String expectedFd)
      Pops the top operand, asserts that it is an integer_variable_info, long_variable_info, float_variable_info, double_variable_info or variable_object_info, and asserts that it matches the given field descriptor.
    • popOperandAssignableTo

      public void popOperandAssignableTo(String declaredFd)
    • popIntOperand

      public void popIntOperand()
      Asserts that the top operand is an integer_variable_info and pops it.
    • popLongOperand

      public void popLongOperand()
      Asserts that the top operand is a long_variable_info and pops it.
    • popUninitializedThisOperand

      public void popUninitializedThisOperand()
      Asserts that the top operand is an uninitializedThis_variable_info and pops it.
    • popUninitializedVariableOperand

      public void popUninitializedVariableOperand()
      Asserts that the top operand is an uninitialized_variable_info and pops it.
    • popReferenceOperand

      public void popReferenceOperand()
      Asserts that the top operand is an object_variable_info or a null_variable_info and pops it.
    • popObjectOperand

      public String popObjectOperand()
      Asserts that the top operand is an object_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 an object_variable_info, uninitialized_variable_info or uninitializedThis_variable_info, and pops it.
    • popIntOrLongOperand

      Asserts that the top operand is an int_variable_info or long_variable_info, then pops and returns it.