Class ClassFileWriter.StackMapTable

  • Enclosing class:
    ClassFileWriter

    final class ClassFileWriter.StackMapTable
    extends java.lang.Object
    A stack map table is a code attribute introduced in Java 6 that gives type information at key points in the method body (namely, at the beginning of each super block after the first). Each frame of a stack map table contains the state of local variable and operand stack for a given super block.
    • Constructor Summary

      Constructors 
      Constructor Description
      StackMapTable()  
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      private void addToWorkList​(SuperBlock sb)  
      private void clearStack()  
      private void computeRawStackMap()
      Compute a space-optimal stack map table.
      (package private) int computeWriteSize()
      Compute the output size of the stack map table.
      private int execute​(int bci)
      Execute a single byte code instruction.
      private void executeALoad​(int localIndex)  
      private void executeAStore​(int localIndex)  
      private void executeBlock​(SuperBlock work)
      Simulate the local variable and op stack for a super block.
      private void executeStore​(int localIndex, int typeInfo)  
      private void executeWorkList()  
      private void flowInto​(SuperBlock sb)
      Perform a merge of type state and add the super block to the work list if the merge changed anything.
      (package private) void generate()  
      private SuperBlock getBranchTarget​(int bci)
      Get the target super block of a branch instruction.
      private int getLocal​(int localIndex)  
      private int getOperand​(int offset)  
      private int getOperand​(int start, int size)
      Extract a logical operand from the byte code.
      private SuperBlock getSuperBlockFromOffset​(int offset)  
      private int getWorstCaseWriteSize()
      Get the worst case write size of the stack map table.
      private void initializeTypeInfo​(int prevType, int newType)
      Change an UNINITIALIZED_OBJECT or UNINITIALIZED_THIS to the proper type of the object.
      private void initializeTypeInfo​(int prevType, int newType, int[] data, int dataTop)  
      private boolean isBranch​(int opcode)
      Determine whether or not an opcode is a conditional or unconditional jump.
      private boolean isSuperBlockEnd​(int opcode)
      Determine whether or not an opcode is an actual end to a super block.
      private void killSuperBlock​(SuperBlock sb)
      Replace the contents of a super block with no-ops.
      private int pop()  
      private long pop2()
      Pop two words from the op stack.
      private void push​(int typeInfo)  
      private void push2​(long typeInfo)
      Push two words onto the op stack.
      private void setLocal​(int localIndex, int typeInfo)  
      private void verify()
      Calculate initial local variable and op stack types for each super block in the method.
      (package private) int write​(byte[] data, int offset)  
      private void writeAppendFrame​(int[] locals, int localsDelta, int offsetDelta)  
      private void writeChopFrame​(int localsDelta, int offsetDelta)  
      private void writeFullFrame​(int[] locals, int[] stack, int offsetDelta)  
      private void writeSameFrame​(int offsetDelta)  
      private void writeSameLocalsOneStackItemFrame​(int[] stack, int offsetDelta)  
      private int writeType​(int type)  
      private int writeTypes​(int[] types)  
      private int writeTypes​(int[] types, int start)  
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • locals

        private int[] locals
      • localsTop

        private int localsTop
      • stack

        private int[] stack
      • stackTop

        private int stackTop
      • workListTop

        private int workListTop
      • rawStackMap

        private byte[] rawStackMap
      • rawStackMapTop

        private int rawStackMapTop
      • wide

        private boolean wide
    • Constructor Detail

      • StackMapTable

        StackMapTable()
    • Method Detail

      • generate

        void generate()
      • getSuperBlockFromOffset

        private SuperBlock getSuperBlockFromOffset​(int offset)
      • isSuperBlockEnd

        private boolean isSuperBlockEnd​(int opcode)
        Determine whether or not an opcode is an actual end to a super block. This includes any returns or unconditional jumps.
      • getBranchTarget

        private SuperBlock getBranchTarget​(int bci)
        Get the target super block of a branch instruction.
        Parameters:
        bci - the index of the branch instruction in the code buffer
      • isBranch

        private boolean isBranch​(int opcode)
        Determine whether or not an opcode is a conditional or unconditional jump.
      • getOperand

        private int getOperand​(int offset)
      • getOperand

        private int getOperand​(int start,
                               int size)
        Extract a logical operand from the byte code.

        This is used, for example, to get branch offsets.

      • verify

        private void verify()
        Calculate initial local variable and op stack types for each super block in the method.
      • killSuperBlock

        private void killSuperBlock​(SuperBlock sb)
        Replace the contents of a super block with no-ops.

        The above description is not strictly true; the last instruction is an athrow instruction. This technique is borrowed from ASM's developer guide: http://asm.ow2.org/doc/developer-guide.html#deadcode

        The proposed algorithm fills a block with nop, ending it with an athrow. The stack map generated would be empty locals with an exception on the stack. In theory, it shouldn't matter what the locals are, as long as the stack has an exception for the athrow bit. However, it turns out that if the code being modified falls into an exception handler, it causes problems. Therefore, if it does, then we steal the locals from the exception block.

        If the block itself is an exception handler, we remove it from the exception table to simplify block dependencies.

      • executeWorkList

        private void executeWorkList()
      • executeBlock

        private void executeBlock​(SuperBlock work)
        Simulate the local variable and op stack for a super block.
      • flowInto

        private void flowInto​(SuperBlock sb)
        Perform a merge of type state and add the super block to the work list if the merge changed anything.
      • addToWorkList

        private void addToWorkList​(SuperBlock sb)
      • execute

        private int execute​(int bci)
        Execute a single byte code instruction.
        Parameters:
        bci - the index of the byte code instruction to execute
        Returns:
        the length of the byte code instruction
      • executeALoad

        private void executeALoad​(int localIndex)
      • executeAStore

        private void executeAStore​(int localIndex)
      • executeStore

        private void executeStore​(int localIndex,
                                  int typeInfo)
      • initializeTypeInfo

        private void initializeTypeInfo​(int prevType,
                                        int newType)
        Change an UNINITIALIZED_OBJECT or UNINITIALIZED_THIS to the proper type of the object. This occurs when the proper constructor is invoked.
      • initializeTypeInfo

        private void initializeTypeInfo​(int prevType,
                                        int newType,
                                        int[] data,
                                        int dataTop)
      • getLocal

        private int getLocal​(int localIndex)
      • setLocal

        private void setLocal​(int localIndex,
                              int typeInfo)
      • push

        private void push​(int typeInfo)
      • pop

        private int pop()
      • push2

        private void push2​(long typeInfo)
        Push two words onto the op stack.

        This is only meant to be used as a complement to pop2(), and both methods are helpers for the more complex DUP operations.

      • pop2

        private long pop2()
        Pop two words from the op stack.

        If the top of the stack is a DOUBLE or LONG, then the bottom 32 bits reflects the appropriate type and the top 32 bits are 0. Otherwise, the top 32 bits are the first word on the stack and the lower 32 bits are the second word on the stack.

      • clearStack

        private void clearStack()
      • computeWriteSize

        int computeWriteSize()
        Compute the output size of the stack map table.

        Because this would share much in common with actual writing of the stack map table, we instead just write the stack map table to a buffer and return the size from it. The buffer is later used in the actual writing of bytecode.

      • write

        int write​(byte[] data,
                  int offset)
      • computeRawStackMap

        private void computeRawStackMap()
        Compute a space-optimal stack map table.
      • getWorstCaseWriteSize

        private int getWorstCaseWriteSize()
        Get the worst case write size of the stack map table.

        This computes how much full frames would take, if each full frame contained the maximum number of locals and stack operands, and each verification type was 3 bytes.

      • writeSameFrame

        private void writeSameFrame​(int offsetDelta)
      • writeSameLocalsOneStackItemFrame

        private void writeSameLocalsOneStackItemFrame​(int[] stack,
                                                      int offsetDelta)
      • writeFullFrame

        private void writeFullFrame​(int[] locals,
                                    int[] stack,
                                    int offsetDelta)
      • writeAppendFrame

        private void writeAppendFrame​(int[] locals,
                                      int localsDelta,
                                      int offsetDelta)
      • writeChopFrame

        private void writeChopFrame​(int localsDelta,
                                    int offsetDelta)
      • writeTypes

        private int writeTypes​(int[] types)
      • writeTypes

        private int writeTypes​(int[] types,
                               int start)
      • writeType

        private int writeType​(int type)