Class BCMethod

  • All Implemented Interfaces:
    MethodBuilder

    class BCMethod
    extends java.lang.Object
    implements MethodBuilder
    MethodBuilder is used to piece together a method when building a java class definition.

    When a method is first created, it has:

    • a return type
    • modifiers
    • a name
    • an empty parameter list
    • an empty throws list
    • an empty statement block

    MethodBuilder implementations are required to supply a way for Statements and Expressions to give them code. Most typically, they may have a stream to which their contents writes the code that is of the type to satisfy what the contents represent. MethodBuilder implementations also have to have a way to supply ClassBuilders with their code, that satisfies the type of class builder they are implemented with. This is implementation-dependent, so ClassBuilders, MethodBuilders, Statements, and Expressions all have to be of the same implementation in order to interact to generate a class.

    Method Builder implementation for generating bytecode.

    • Field Summary

      Fields 
      Modifier and Type Field Description
      (package private) BCClass cb  
      (package private) static int CODE_SPLIT_LENGTH
      Code length at which to split into sub-methods.
      private Conditional condition  
      private int currentVarNum  
      private boolean handlingOverflow
      True if we are currently switching control over to a sub method to avoid hitting the code generation limit of 65535 bytes per method.
      (package private) int maxStack
      Maximum stack depth seen in this method, measured in words.
      protected ClassHolder modClass  
      (package private) CodeChunk myCode  
      protected ClassMember myEntry  
      private java.lang.String myName
      The original name of the method, this represents how any user would call this method.
      (package private) java.lang.String myReturnType  
      private static byte[] newArrayElementTypeMap
      this array maps the BCExpr vm_* constants 0..6 to the expected VM type constants for the newarray instruction.
      (package private) BCLocalField[] parameters
      Fast access for the parametes, will be null if the method has no parameters.
      private java.lang.String[] parameterTypes
      List of parameter types with java language class names.
      private int stackDepth
      Current stack depth in this method, measured in words.
      private int stackTypeOffset
      Points to the next array offset in stackTypes to be used.
      private Type[] stackTypes
      Array of the current types of the values on the stack.
      private int statementNum  
      private int subMethodCount
      How many sub-methods we have overflowed to.
      (package private) static byte T_BOOLEAN  
      (package private) java.util.Vector<java.lang.String> thrownExceptions  
    • Constructor Summary

      Constructors 
      Constructor Description
      BCMethod​(ClassBuilder cb, java.lang.String returnType, java.lang.String methodName, int modifiers, java.lang.String[] parms, BCJava factory)  
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      private void addInstrCPE​(short opcode, int cpe)
      Write a instruction that uses a constant pool entry as an operand, add a limit exceeded message if the number of constant pool entries has exceeded the limit.
      void addThrownException​(java.lang.String exceptionClass)
      a throwable can be added to the end of the list of thrownExceptions.
      int callMethod​(short opcode, java.lang.String declaringClass, java.lang.String methodName, java.lang.String returnType, int numArgs)
      Call a method.
      int callMethod​(java.lang.Object methodDescriptor)
      Call a method previously described by describeMethod().
      (package private) void callSubMethod​(BCMethod subMethod)
      Call a sub-method created by getNewSubMethod handling parameters correctly.
      void callSuper()
      Call super().
      void cast​(java.lang.String className)
      Cast the top stack value.
      void complete()
      when the method has had all of its parameters and thrown exceptions defined, and its statement block has been completed, it can be completed and its class file information generated.
      void completeConditional()
      Complete a conditional which completes the false code path.
      void conditionalIf()
      Initiate a conditional sequence.
      private void conditionalIf​(short opcode)  
      void conditionalIfNull()
      Initiate a conditional sequence.
      (package private) ClassHolder constantPool()
      In their giveCode methods, the parts of the method body will want to get to the constant pool to add their constants.
      private Type[] copyStack()  
      java.lang.Object describeMethod​(short opcode, java.lang.String declaringClass, java.lang.String methodName, java.lang.String returnType)
      Return an object that efficiently (to the implementation) describes a zero-argument method and can be used with the single argument callMethod().
      void dup()
      Duplicate the top value on the stack.
      void endStatement()
      End a statement.
      void getArrayElement​(int element)
      Pop an array refrence off the stack and push an element from that array.
      private void getField​(short opcode, java.lang.String declaringClass, java.lang.String fieldName, java.lang.String fieldType)  
      void getField​(java.lang.String declaringClass, java.lang.String fieldName, java.lang.String fieldType)
      Push the contents of the described field onto the stack.
      void getField​(LocalField field)
      Push the contents of the local field onto the stack.
      java.lang.String getName()
      Return the logical name of the method.
      (package private) BCMethod getNewSubMethod​(java.lang.String returnType, boolean withParameters)
      Create a sub-method from this method to allow the code builder to split a single logical method into multiple methods to avoid the 64k per-method code size limit.
      void getParameter​(int id)
      Push a parameter value.
      void getStaticField​(java.lang.String declaringClass, java.lang.String fieldName, java.lang.String fieldType)
      Push the contents of the described static field onto the stack.
      private void growStack​(int size, Type type)  
      private void growStack​(Type type)  
      void isInstanceOf​(java.lang.String className)
      Pop the top stack value and push a boolean that is the result of an instanceof check on the popped reference.
      void methodReturn()
      Return from a method, optionally with a value.
      private void overflowMethodCheck()
      Check to see if the current method byte code is nearing the limit of 65535.
      void pop()
      Pop the top value off the stack
      private Type popStack()  
      void push​(boolean value)
      Push a boolean constant onto the stack
      void push​(byte value)
      Push a byte constant onto the stack
      void push​(double value)
      Push a double constant onto the stack
      void push​(float value)
      Push a float constant onto the stack
      void push​(int value)
      Push a int constant onto the stack
      private void push​(int value, Type type)
      Push an integer value.
      void push​(long value)
      Push a long value onto the stack.
      void push​(short value)
      Push a short constant onto the stack
      void push​(java.lang.String value)
      Push a String constant onto the stack
      void pushNewArray​(java.lang.String className, int size)
      Create an array instance Stack
      void pushNewComplete​(int numArgs)
      Complete the sequence that was started with pushNewStart().
      void pushNewStart​(java.lang.String className)
      Initiate a sequence that calls a constructor, equivalent to the new operator in Java.
      void pushNull​(java.lang.String type)
      Push a typed null onto the stack
      void pushThis()
      Push this onto the stack.
      void putField​(java.lang.String fieldName, java.lang.String fieldType)
      Pop the top stack value and store it in the instance field of this class.
      void putField​(java.lang.String declaringClass, java.lang.String fieldName, java.lang.String fieldType)
      Pop the top stack value and store it in the field.
      void putField​(LocalField field)
      Upon entry the top word(s) on the stack is the value to be put into the field.
      private void putField​(Type fieldType, int cpi, boolean dup)  
      void setArrayElement​(int element)
      Pop an array reference off the stack, store a value in the array at the passed in offset.
      void setField​(LocalField field)
      Set the field but don't duplicate its value so nothing is left on the stack after this call.
      private void splitMethod()
      Attempt to split a large method by pushing code out to several sub-methods.
      void startElseCode()
      Complete the true code path of a conditional.
      boolean statementNumHitLimit​(int noStatementsAdded)
      Tell if statement number in this method builder hits limit.
      void swap()
      Swap the top two values on the stack.
      void upCast​(java.lang.String className)
      Upcast the top stack value.
      private Type vmNameDeclaringClass​(java.lang.String declaringClass)  
      protected void writeExceptions()
      sets exceptionBytes to the attribute_info needed for a method's Exceptions attribute.
      • Methods inherited from class java.lang.Object

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

      • CODE_SPLIT_LENGTH

        static final int CODE_SPLIT_LENGTH
        Code length at which to split into sub-methods. Normally set to the maximim code length the JVM can support, but for testing the split code it can be reduced so that the standard tests cause some splitting. Tested with value set to 2000.
        See Also:
        Constant Field Values
      • myReturnType

        final java.lang.String myReturnType
      • myName

        private final java.lang.String myName
        The original name of the method, this represents how any user would call this method.
      • parameters

        BCLocalField[] parameters
        Fast access for the parametes, will be null if the method has no parameters.
      • parameterTypes

        private final java.lang.String[] parameterTypes
        List of parameter types with java language class names. Can be null or zero length for no parameters.
      • thrownExceptions

        java.util.Vector<java.lang.String> thrownExceptions
      • currentVarNum

        private int currentVarNum
      • statementNum

        private int statementNum
      • handlingOverflow

        private boolean handlingOverflow
        True if we are currently switching control over to a sub method to avoid hitting the code generation limit of 65535 bytes per method.
      • subMethodCount

        private int subMethodCount
        How many sub-methods we have overflowed to.
      • stackTypes

        private Type[] stackTypes
        Array of the current types of the values on the stack. A type that types up two words on the stack, e.g. double will only occupy one element in this array. This array is dynamically re-sized as needed.
      • stackTypeOffset

        private int stackTypeOffset
        Points to the next array offset in stackTypes to be used. Really it's the number of valid entries in stackTypes.
      • maxStack

        int maxStack
        Maximum stack depth seen in this method, measured in words. Corresponds to max_stack in the Code attribute of section 4.7.3 of the vm spec.
      • stackDepth

        private int stackDepth
        Current stack depth in this method, measured in words.
      • newArrayElementTypeMap

        private static final byte[] newArrayElementTypeMap
        this array maps the BCExpr vm_* constants 0..6 to the expected VM type constants for the newarray instruction.

        Because boolean was mapped to integer for general instructions, it will have to be specially matched and mapped to its value directly (4).

    • Constructor Detail

      • BCMethod

        BCMethod​(ClassBuilder cb,
                 java.lang.String returnType,
                 java.lang.String methodName,
                 int modifiers,
                 java.lang.String[] parms,
                 BCJava factory)
    • Method Detail

      • getName

        public java.lang.String getName()
        Return the logical name of the method. The current myEntry refers to the sub method we are currently overflowing to. Those sub-methods are hidden from any caller.
        Specified by:
        getName in interface MethodBuilder
      • getParameter

        public void getParameter​(int id)
        Description copied from interface: MethodBuilder
        Push a parameter value.
                        Stack ...  =>
                              ...,param_value
                        
        Specified by:
        getParameter in interface MethodBuilder
        Parameters:
        id - position of the parameter (zero based).
      • addThrownException

        public void addThrownException​(java.lang.String exceptionClass)
        a throwable can be added to the end of the list of thrownExceptions.
        Specified by:
        addThrownException in interface MethodBuilder
      • complete

        public void complete()
        when the method has had all of its parameters and thrown exceptions defined, and its statement block has been completed, it can be completed and its class file information generated.

        further alterations of the method will not be reflected in the code generated for it.

        Specified by:
        complete in interface MethodBuilder
      • splitMethod

        private void splitMethod()
        Attempt to split a large method by pushing code out to several sub-methods. Performs a number of steps.
        1. Split at zero stack depth.
        2. Split at non-zero stack depth (FUTURE)
        If the class has already exceeded some limit in building the class file format structures then don't attempt to split. Most likely the number of constant pool entries has been exceeded and thus the built class file no longer has integrity. The split code relies on being able to read the in-memory version of the class file in order to determine descriptors for methods and fields.
      • constantPool

        ClassHolder constantPool()
        In their giveCode methods, the parts of the method body will want to get to the constant pool to add their constants. We really only want them treating it like a constant pool inclusion mechanism, we could write a wrapper to limit it to that.
      • writeExceptions

        protected void writeExceptions()
        sets exceptionBytes to the attribute_info needed for a method's Exceptions attribute. The ClassUtilities take care of the header 6 bytes for us, so they are not included here. See The Java Virtual Machine Specification Section 4.7.5, Exceptions attribute.
      • growStack

        private void growStack​(int size,
                               Type type)
      • growStack

        private void growStack​(Type type)
      • popStack

        private Type popStack()
      • copyStack

        private Type[] copyStack()
      • pushThis

        public void pushThis()
        Description copied from interface: MethodBuilder
        Push this onto the stack.
                        Stack ...  =>
                              ...,this_ref
                        
        Specified by:
        pushThis in interface MethodBuilder
      • push

        public void push​(byte value)
        Description copied from interface: MethodBuilder
        Push a byte constant onto the stack
                        Stack ...  =>
                              ...,byte_value
                        
        Specified by:
        push in interface MethodBuilder
      • push

        public void push​(boolean value)
        Description copied from interface: MethodBuilder
        Push a boolean constant onto the stack
                        Stack ...  =>
                              ...,boolean_value
                        
        Specified by:
        push in interface MethodBuilder
      • push

        public void push​(short value)
        Description copied from interface: MethodBuilder
        Push a short constant onto the stack
                        Stack ...  =>
                              ...,short_value
                        
        Specified by:
        push in interface MethodBuilder
      • push

        public void push​(int value)
        Description copied from interface: MethodBuilder
        Push a int constant onto the stack
                        Stack ...  =>
                              ...,int_value
                        
        Specified by:
        push in interface MethodBuilder
      • dup

        public void dup()
        Description copied from interface: MethodBuilder
        Duplicate the top value on the stack.
                        Stack ...,value =>
                              ...,value,value
                        
        Specified by:
        dup in interface MethodBuilder
      • swap

        public void swap()
        Description copied from interface: MethodBuilder
        Swap the top two values on the stack.
                        Stack ...,valueA,valueB =>
                              ...,valueB,valueA
                        
        Specified by:
        swap in interface MethodBuilder
      • push

        private void push​(int value,
                          Type type)
        Push an integer value. Uses the special integer opcodes for the constants -1 to 5, BIPUSH for values that fit in a byte and SIPUSH for values that fit in a short. Otherwise uses LDC with a constant pool entry.
        Parameters:
        value - Value to be pushed
        type - Final type of the value.
      • push

        public void push​(long value)
        Push a long value onto the stack. For the values zero and one the LCONST_0 and LCONST_1 instructions are used. For values betwee Short.MIN_VALUE and Short.MAX_VALUE inclusive an byte/short/int value is pushed using push(int, Type) followed by an I2L instruction. This saves using a constant pool entry for such values. All other values use a constant pool entry. For values in the range of an Integer an integer constant pool entry is created to allow sharing with integer constants and to reduce constant pool slot entries.
        Specified by:
        push in interface MethodBuilder
      • push

        public void push​(float value)
        Description copied from interface: MethodBuilder
        Push a float constant onto the stack
                        Stack ...  =>
                              ...,float_value
                        
        Specified by:
        push in interface MethodBuilder
      • push

        public void push​(double value)
        Description copied from interface: MethodBuilder
        Push a double constant onto the stack
                        Stack ...  =>
                              ...,double_value
                        
        Specified by:
        push in interface MethodBuilder
      • push

        public void push​(java.lang.String value)
        Description copied from interface: MethodBuilder
        Push a String constant onto the stack
                        Stack ...  =>
                              ...,String_value
                        
        Specified by:
        push in interface MethodBuilder
      • methodReturn

        public void methodReturn()
        Description copied from interface: MethodBuilder
        Return from a method, optionally with a value. Must only be called if zero or one item exists on the stack. If the stack contains a single value then that is popped and used as the returned value.
                        Stack value =>
                              :empty:
                        or
        
                        Stack :empty: =>
                              :empty:
        
                        
        .
        Specified by:
        methodReturn in interface MethodBuilder
      • describeMethod

        public java.lang.Object describeMethod​(short opcode,
                                               java.lang.String declaringClass,
                                               java.lang.String methodName,
                                               java.lang.String returnType)
        Description copied from interface: MethodBuilder
        Return an object that efficiently (to the implementation) describes a zero-argument method and can be used with the single argument callMethod(). Descriptions for the parameters to this method are the same as the five argument callMethod(). This allows the caller to cache frequently used methods. The returned object is only valid for use by this MethodBuilder.
        This call does not affect the Stack.
        Specified by:
        describeMethod in interface MethodBuilder
      • callMethod

        public int callMethod​(java.lang.Object methodDescriptor)
        Description copied from interface: MethodBuilder
        Call a method previously described by describeMethod().
                        static methods
        
                        Stack ...,value* => [numArgs number of values will be popped]
                              ...,return_value [void methods will not push a value]
        
                        non-static methods
        
                        Stack ...,ref,value* => [numArgs number of values will be popped]
                              ...,return_value [void methods will not push a value]
                        
        Specified by:
        callMethod in interface MethodBuilder
      • callMethod

        public int callMethod​(short opcode,
                              java.lang.String declaringClass,
                              java.lang.String methodName,
                              java.lang.String returnType,
                              int numArgs)
        Description copied from interface: MethodBuilder
        Call a method. The instance (receiver or reference) for non-static methods must be pushed by the caller. The instance (for non-static) and the arguments are popped of the stack, and the return value (if any) is pushed onto the stack.
        The type needs to be one of:
        • VMOpcode.INVOKESTATIC - call a static method
        • VMOpcode.INVOKEVIRTUAL - call method declared in the class or super-class.
        • VMOpcode.INVOKEINTERFACE - call a method declared in an interface
                        static methods
        
                        Stack ...,value* => [numArgs number of values will be popped]
                              ...,return_value [void methods will not push a value]
        
                        non-static methods
        
                        Stack ...,ref,value* => [numArgs number of values will be popped]
                              ...,return_value [void methods will not push a value]
                        

        The type of the arguments to the methods must exactly match the declared types of the parameters to the methods. If a argument is of the incorrect type the caller must up cast it or down cast it.
        Specified by:
        callMethod in interface MethodBuilder
        Parameters:
        opcode - type of method invocation
        declaringClass - Class or interface the method is declared in. If it is a non-static method call then if declaringClass is null, the declared type is taken to be the type of the reference that will be popped.
        methodName - name of the method
        returnType - class name or primitive type (including "void") of the return type of the method, can not be null.
        numArgs - number of arguments to the method (can be 0).
      • vmNameDeclaringClass

        private Type vmNameDeclaringClass​(java.lang.String declaringClass)
      • callSuper

        public void callSuper()
        Description copied from interface: MethodBuilder
        Call super(). Caller must only add this to a constructor.
        
                        Stack ... =>
                              ... 
                        
        Specified by:
        callSuper in interface MethodBuilder
      • pushNewStart

        public void pushNewStart​(java.lang.String className)
        Description copied from interface: MethodBuilder
        Initiate a sequence that calls a constructor, equivalent to the new operator in Java. After this call, the caller must push any arguments and then complete the construction with a call to pushNewComplete(). Only arguments to the constructor can be pushed onto the stack between the pushNewStart() and pushNewComplete() method calls.
                        Stack ... => [unchanged]
                              ...
                        
        Specified by:
        pushNewStart in interface MethodBuilder
        Parameters:
        className - class name of object to be created.
      • pushNewComplete

        public void pushNewComplete​(int numArgs)
        Description copied from interface: MethodBuilder
        Complete the sequence that was started with pushNewStart(). Pop the arguments to the constructor and push the reference to the newly created object.
                        Stack ...,value* => [numArgs number of values will be popped]
                              ...,new_ref
                        
        Specified by:
        pushNewComplete in interface MethodBuilder
        Parameters:
        numArgs - number of arguments to the constructor (can be 0).
      • upCast

        public void upCast​(java.lang.String className)
        Description copied from interface: MethodBuilder
        Upcast the top stack value. This is used for correct method resolution by upcasting method parameters. It does not put any casting code into the byte code stream. Can only be used for refrences.
                        Stack ...,ref =>
                              ...,ref
                        
        Specified by:
        upCast in interface MethodBuilder
      • cast

        public void cast​(java.lang.String className)
        Description copied from interface: MethodBuilder
        Cast the top stack value. Correctly down-casts a reference or casts a primitive type (e.g. int to short).
                        Stack ...,value =>
                              ...,cast_value
                        
        Specified by:
        cast in interface MethodBuilder
        Parameters:
        className - type (primitive, interface or class) to cast to.
      • isInstanceOf

        public void isInstanceOf​(java.lang.String className)
        Description copied from interface: MethodBuilder
        Pop the top stack value and push a boolean that is the result of an instanceof check on the popped reference.
                        Stack ...,ref =>
                              ...,boolean_value
                        
        .
        Specified by:
        isInstanceOf in interface MethodBuilder
      • pushNull

        public void pushNull​(java.lang.String type)
        Description copied from interface: MethodBuilder
        Push a typed null onto the stack
                        Stack ...  =>
                              ...,null
                        
        Specified by:
        pushNull in interface MethodBuilder
      • getField

        public void getField​(LocalField field)
        Description copied from interface: MethodBuilder
        Push the contents of the local field onto the stack. This call pushes the this instance required to access the field itself.
                        Stack ...  =>
                              ...,field_value
                        
        Specified by:
        getField in interface MethodBuilder
      • getField

        public void getField​(java.lang.String declaringClass,
                             java.lang.String fieldName,
                             java.lang.String fieldType)
        Description copied from interface: MethodBuilder
        Push the contents of the described field onto the stack. This call requires the instance (reference) to be pushed by the caller.
                        Stack ...,field_ref  =>
                              ...,field_value
                        
        Specified by:
        getField in interface MethodBuilder
      • getStaticField

        public void getStaticField​(java.lang.String declaringClass,
                                   java.lang.String fieldName,
                                   java.lang.String fieldType)
        Push the contents of the described static field onto the stack.
        Specified by:
        getStaticField in interface MethodBuilder
      • getField

        private void getField​(short opcode,
                              java.lang.String declaringClass,
                              java.lang.String fieldName,
                              java.lang.String fieldType)
      • setField

        public void setField​(LocalField field)
        Set the field but don't duplicate its value so nothing is left on the stack after this call.
        Specified by:
        setField in interface MethodBuilder
      • putField

        public void putField​(LocalField field)
        Upon entry the top word(s) on the stack is the value to be put into the field. Ie. we have
                        word
                        
        Before the call we need
                        word
                        this
                        word
                        
        word2,word1 -> word2, word1, word2 So that we are left with word after the put.
        Specified by:
        putField in interface MethodBuilder
      • putField

        public void putField​(java.lang.String fieldName,
                             java.lang.String fieldType)
        Pop the top stack value and store it in the instance field of this class.
        Specified by:
        putField in interface MethodBuilder
      • putField

        private void putField​(Type fieldType,
                              int cpi,
                              boolean dup)
      • putField

        public void putField​(java.lang.String declaringClass,
                             java.lang.String fieldName,
                             java.lang.String fieldType)
        Pop the top stack value and store it in the field. This call requires the instance to be pushed by the caller.
        Specified by:
        putField in interface MethodBuilder
      • conditionalIfNull

        public void conditionalIfNull()
        Description copied from interface: MethodBuilder
        Initiate a conditional sequence. The top value on the stack (a reference) is popped and compared to 'null'. If the value is null then the code following this call until the startElseCode() will be executed at runtime, otherwise the code following startElseCode() until the completeConditional() is called.
        E.g.
                        mb.callMethod(...); // pushes an object onto the stack
                        mb.conditionalIfNull();
                          mb.push(3);
                        mb.startElseCode();
                          mb.push(5);
                        mb.completeConditional();
                        // at this point 3 or 5 will be on the stack
                        
        Each path through the ?: statement must leave the stack at the same depth as the other.
        If the if or else code pops values from the stack that were before the conditional value, then they must use the same number of values from the stack.
                        Stack ...,ref =>
                              ...
                        
        .
        Specified by:
        conditionalIfNull in interface MethodBuilder
      • conditionalIf

        public void conditionalIf()
        Description copied from interface: MethodBuilder
        Initiate a conditional sequence. The top value on the stack must be a boolean and will be popped. If it is true then the code following this call until the startElseCode() will be executed at runtime, otherwise the code following startElseCode() until the completeConditional() is called. See conditionalIfNull() for example and restrictions.
                        Stack ...,boolean_value =>
                              ...
                        
        .
        Specified by:
        conditionalIf in interface MethodBuilder
      • conditionalIf

        private void conditionalIf​(short opcode)
      • startElseCode

        public void startElseCode()
        Description copied from interface: MethodBuilder
        Complete the true code path of a conditional.
        Specified by:
        startElseCode in interface MethodBuilder
      • completeConditional

        public void completeConditional()
        Description copied from interface: MethodBuilder
        Complete a conditional which completes the false code path.
        Specified by:
        completeConditional in interface MethodBuilder
      • pop

        public void pop()
        Description copied from interface: MethodBuilder
        Pop the top value off the stack
                        Stack ..., value =>
                              ...
                        
        .
        Specified by:
        pop in interface MethodBuilder
      • endStatement

        public void endStatement()
        Description copied from interface: MethodBuilder
        End a statement. Pops the top-word of the stack, if any. Must only be called if zero or one item exists on the stack.
                        Stack value =>
                              :empty:
                        or
        
                        Stack :empty: =>
                              :empty:
        
                        
        .
        Specified by:
        endStatement in interface MethodBuilder
      • getArrayElement

        public void getArrayElement​(int element)
        Description copied from interface: MethodBuilder
        Pop an array refrence off the stack and push an element from that array.
                        Stack ...,array_ref =>
                              ...,value
                        
        Specified by:
        getArrayElement in interface MethodBuilder
        Parameters:
        element - Offset into the array (zero based)
      • setArrayElement

        public void setArrayElement​(int element)
        Description copied from interface: MethodBuilder
        Pop an array reference off the stack, store a value in the array at the passed in offset.
                        Stack ...,array_ref, value =>
                              ...
                        
        Specified by:
        setArrayElement in interface MethodBuilder
        Parameters:
        element - Offset into the array (zero based)
      • pushNewArray

        public void pushNewArray​(java.lang.String className,
                                 int size)
        Create an array instance Stack ... => ...,arrayref
        Specified by:
        pushNewArray in interface MethodBuilder
        Parameters:
        className - - type of array.
        size - - number of elements in the array
      • addInstrCPE

        private void addInstrCPE​(short opcode,
                                 int cpe)
        Write a instruction that uses a constant pool entry as an operand, add a limit exceeded message if the number of constant pool entries has exceeded the limit.
      • statementNumHitLimit

        public boolean statementNumHitLimit​(int noStatementsAdded)
        Tell if statement number in this method builder hits limit. This method builder keeps a counter of how many statements are added to it. Caller should call this function every time it tries to add a statement to this method builder (counter is increased by 1), then the function returns whether the accumulated statement number hits a limit. The reason of doing this is that Java compiler has a limit of 64K code size for each method. We might hit this limit if an extremely long insert statement is issued, for example (see beetle 4293). Counting statement number is an approximation without too much overhead.
        Specified by:
        statementNumHitLimit in interface MethodBuilder
      • overflowMethodCheck

        private void overflowMethodCheck()
        Check to see if the current method byte code is nearing the limit of 65535. If it is start overflowing to a new method.

        Overflow is handled for a method named e23 as: public Object e23() { ... existing code // split point return e23_0(); } private Object e23_0() { ... first set overflowed code // split point return e23_1(); } private Object e23_1() { ... second set overflowed code // method complete return result; }

        These overflow methods are hidden from the code using this MethodBuilder, it continues to think that it is building a single method with the original name.
        Restrictions:

        • Only handles methods with no arguments
        • Stack depth must be zero
      • getNewSubMethod

        final BCMethod getNewSubMethod​(java.lang.String returnType,
                                       boolean withParameters)
        Create a sub-method from this method to allow the code builder to split a single logical method into multiple methods to avoid the 64k per-method code size limit. The sub method with inherit the thrown exceptions of this method.
        Parameters:
        returnType - Return type of the new method
        withParameters - True to define the method with matching parameters false to define it with no parameters.
        Returns:
        A valid empty sub method.
      • callSubMethod

        final void callSubMethod​(BCMethod subMethod)
        Call a sub-method created by getNewSubMethod handling parameters correctly.