Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
ASM: a very small and fast Java bytecode manipulation framework Copyright (c) 2000-2011 INRIA, France Telecom All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  package com.sleepycat.asm;

Information about the input and output stack map frames of a basic block.

Author(s):
Eric Bruneton
  
  final class Frame {
  
      /*
       * Frames are computed in a two steps process: during the visit of each
       * instruction, the state of the frame at the end of current basic block is
       * updated by simulating the action of the instruction on the previous state
       * of this so called "output frame". In visitMaxs, a fix point algorithm is
       * used to compute the "input frame" of each basic block, i.e. the stack map
       * frame at the beginning of the basic block, starting from the input frame
       * of the first basic block (which is computed from the method descriptor),
       * and by using the previously computed output frames to compute the input
       * state of the other blocks.
       *
       * All output and input frames are stored as arrays of integers. Reference
       * and array types are represented by an index into a type table (which is
       * not the same as the constant pool of the class, in order to avoid adding
       * unnecessary constants in the pool - not all computed frames will end up
       * being stored in the stack map table). This allows very fast type
       * comparisons.
       *
       * Output stack map frames are computed relatively to the input frame of the
       * basic block, which is not yet known when output frames are computed. It
       * is therefore necessary to be able to represent abstract types such as
       * "the type at position x in the input frame locals" or "the type at
       * position x from the top of the input frame stack" or even "the type at
       * position x in the input frame, with y more (or less) array dimensions".
       * This explains the rather complicated type format used in output frames.
       *
       * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
       * signed number of array dimensions (from -8 to 7). KIND is either BASE,
       * LOCAL or STACK. BASE is used for types that are not relative to the input
       * frame. LOCAL is used for types that are relative to the input local
       * variable types. STACK is used for types that are relative to the input
       * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
       * the input local variable types. For STACK types, it is a position
       * relatively to the top of input frame stack. For BASE types, it is either
       * one of the constants defined in FrameVisitor, or for OBJECT and
       * UNINITIALIZED types, a tag and an index in the type table.
       *
       * Output frames can contain types of any kind and with a positive or
       * negative dimension (and even unassigned types, represented by 0 - which
       * does not correspond to any valid type value). Input frames can only
       * contain BASE types of positive or null dimension. In all cases the type
       * table contains only internal type names (array type descriptors are
       * forbidden - dimensions must be represented through the DIM field).
       *
       * The LONG and DOUBLE types are always represented by using two slots (LONG +
       * TOP or DOUBLE + TOP), for local variable types as well as in the operand
       * stack. This is necessary to be able to simulate DUPx_y instructions,
       * whose effect would be dependent on the actual type values if types were
       * always represented by a single slot in the stack (and this is not
       * possible, since actual type values are not always known - cf LOCAL and
       * STACK type kinds).
       */

    
Mask to get the dimension of a frame type. This dimension is a signed integer between -8 and 7.
  
      static final int DIM = 0xF0000000;

    
Constant to be added to a type to get a type with one more dimension.
 
     static final int ARRAY_OF = 0x10000000;

    
Constant to be added to a type to get a type with one less dimension.
 
     static final int ELEMENT_OF = 0xF0000000;

    
Mask to get the kind of a frame type.

See also:
BASE
LOCAL
STACK
 
     static final int KIND = 0xF000000;

    
Flag used for LOCAL and STACK types. Indicates that if this type happens to be a long or double type (during the computations of input frames), then it must be set to TOP because the second word of this value has been reused to store other data in the basic block. Hence the first word no longer stores a valid long or double value.
 
     static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;

    
Mask to get the value of a frame type.
 
     static final int VALUE = 0x7FFFFF;

    
Mask to get the kind of base types.
 
     static final int BASE_KIND = 0xFF00000;

    
Mask to get the value of base types.
 
     static final int BASE_VALUE = 0xFFFFF;

    
Kind of the types that are not relative to an input stack map frame.
 
     static final int BASE = 0x1000000;

    
Base kind of the base reference types. The BASE_VALUE of such types is an index into the type table.
 
     static final int OBJECT =  | 0x700000;

    
Base kind of the uninitialized base types. The BASE_VALUE of such types in an index into the type table (the Item at that index contains both an instruction offset and an internal class name).
 
     static final int UNINITIALIZED =  | 0x800000;

    
Kind of the types that are relative to the local variable types of an input stack map frame. The value of such types is a local variable index.
 
     private static final int LOCAL = 0x2000000;

    
Kind of the the types that are relative to the stack of an input stack map frame. The value of such types is a position relatively to the top of this stack.
 
     private static final int STACK = 0x3000000;

    
The TOP type. This is a BASE type.
 
     static final int TOP =  | 0;

    
The BOOLEAN type. This is a BASE type mainly used for array types.
 
     static final int BOOLEAN =  | 9;

    
The BYTE type. This is a BASE type mainly used for array types.
 
     static final int BYTE =  | 10;

    
The CHAR type. This is a BASE type mainly used for array types.
 
     static final int CHAR =  | 11;

    
The SHORT type. This is a BASE type mainly used for array types.
 
     static final int SHORT =  | 12;

    
The INTEGER type. This is a BASE type.
 
     static final int INTEGER =  | 1;

    
The FLOAT type. This is a BASE type.
 
     static final int FLOAT =  | 2;

    
The DOUBLE type. This is a BASE type.
 
     static final int DOUBLE =  | 3;

    
The LONG type. This is a BASE type.
 
     static final int LONG =  | 4;

    
The NULL type. This is a BASE type.
 
     static final int NULL =  | 5;

    
The UNINITIALIZED_THIS type. This is a BASE type.
 
     static final int UNINITIALIZED_THIS =  | 6;

    
The stack size variation corresponding to each JVM instruction. This stack variation is equal to the size of the values produced by an instruction, minus the size of the values consumed by this instruction.
 
     static final int[] SIZE;

    
Computes the stack size variation corresponding to each JVM instruction.
 
     static {
         int i;
         int[] b = new int[202];
         String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
                 + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
                 + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
                 + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
         for (i = 0; i < b.length; ++i) {
             b[i] = s.charAt(i) - 'E';
         }
          = b;
 
         // code to generate the above string
         //
         // int NA = 0; // not applicable (unused opcode or variable size opcode)
         //
         // b = new int[] {
         // 0, //NOP, // visitInsn
         // 1, //ACONST_NULL, // -
         // 1, //ICONST_M1, // -
         // 1, //ICONST_0, // -
         // 1, //ICONST_1, // -
         // 1, //ICONST_2, // -
         // 1, //ICONST_3, // -
         // 1, //ICONST_4, // -
         // 1, //ICONST_5, // -
         // 2, //LCONST_0, // -
         // 2, //LCONST_1, // -
         // 1, //FCONST_0, // -
         // 1, //FCONST_1, // -
         // 1, //FCONST_2, // -
         // 2, //DCONST_0, // -
         // 2, //DCONST_1, // -
         // 1, //BIPUSH, // visitIntInsn
         // 1, //SIPUSH, // -
         // 1, //LDC, // visitLdcInsn
         // NA, //LDC_W, // -
         // NA, //LDC2_W, // -
         // 1, //ILOAD, // visitVarInsn
         // 2, //LLOAD, // -
         // 1, //FLOAD, // -
         // 2, //DLOAD, // -
         // 1, //ALOAD, // -
         // NA, //ILOAD_0, // -
         // NA, //ILOAD_1, // -
         // NA, //ILOAD_2, // -
         // NA, //ILOAD_3, // -
         // NA, //LLOAD_0, // -
         // NA, //LLOAD_1, // -
         // NA, //LLOAD_2, // -
         // NA, //LLOAD_3, // -
         // NA, //FLOAD_0, // -
         // NA, //FLOAD_1, // -
         // NA, //FLOAD_2, // -
         // NA, //FLOAD_3, // -
         // NA, //DLOAD_0, // -
         // NA, //DLOAD_1, // -
         // NA, //DLOAD_2, // -
         // NA, //DLOAD_3, // -
         // NA, //ALOAD_0, // -
         // NA, //ALOAD_1, // -
         // NA, //ALOAD_2, // -
         // NA, //ALOAD_3, // -
         // -1, //IALOAD, // visitInsn
         // 0, //LALOAD, // -
         // -1, //FALOAD, // -
         // 0, //DALOAD, // -
         // -1, //AALOAD, // -
         // -1, //BALOAD, // -
         // -1, //CALOAD, // -
         // -1, //SALOAD, // -
         // -1, //ISTORE, // visitVarInsn
         // -2, //LSTORE, // -
         // -1, //FSTORE, // -
         // -2, //DSTORE, // -
         // -1, //ASTORE, // -
         // NA, //ISTORE_0, // -
         // NA, //ISTORE_1, // -
         // NA, //ISTORE_2, // -
         // NA, //ISTORE_3, // -
         // NA, //LSTORE_0, // -
         // NA, //LSTORE_1, // -
         // NA, //LSTORE_2, // -
         // NA, //LSTORE_3, // -
         // NA, //FSTORE_0, // -
         // NA, //FSTORE_1, // -
         // NA, //FSTORE_2, // -
         // NA, //FSTORE_3, // -
         // NA, //DSTORE_0, // -
         // NA, //DSTORE_1, // -
         // NA, //DSTORE_2, // -
         // NA, //DSTORE_3, // -
         // NA, //ASTORE_0, // -
         // NA, //ASTORE_1, // -
         // NA, //ASTORE_2, // -
         // NA, //ASTORE_3, // -
         // -3, //IASTORE, // visitInsn
         // -4, //LASTORE, // -
         // -3, //FASTORE, // -
         // -4, //DASTORE, // -
         // -3, //AASTORE, // -
         // -3, //BASTORE, // -
         // -3, //CASTORE, // -
         // -3, //SASTORE, // -
         // -1, //POP, // -
         // -2, //POP2, // -
         // 1, //DUP, // -
         // 1, //DUP_X1, // -
         // 1, //DUP_X2, // -
         // 2, //DUP2, // -
         // 2, //DUP2_X1, // -
         // 2, //DUP2_X2, // -
         // 0, //SWAP, // -
         // -1, //IADD, // -
         // -2, //LADD, // -
         // -1, //FADD, // -
         // -2, //DADD, // -
         // -1, //ISUB, // -
         // -2, //LSUB, // -
         // -1, //FSUB, // -
         // -2, //DSUB, // -
         // -1, //IMUL, // -
         // -2, //LMUL, // -
         // -1, //FMUL, // -
         // -2, //DMUL, // -
         // -1, //IDIV, // -
         // -2, //LDIV, // -
         // -1, //FDIV, // -
         // -2, //DDIV, // -
         // -1, //IREM, // -
         // -2, //LREM, // -
         // -1, //FREM, // -
         // -2, //DREM, // -
         // 0, //INEG, // -
         // 0, //LNEG, // -
         // 0, //FNEG, // -
         // 0, //DNEG, // -
         // -1, //ISHL, // -
         // -1, //LSHL, // -
         // -1, //ISHR, // -
         // -1, //LSHR, // -
         // -1, //IUSHR, // -
         // -1, //LUSHR, // -
         // -1, //IAND, // -
         // -2, //LAND, // -
         // -1, //IOR, // -
         // -2, //LOR, // -
         // -1, //IXOR, // -
         // -2, //LXOR, // -
         // 0, //IINC, // visitIincInsn
         // 1, //I2L, // visitInsn
         // 0, //I2F, // -
         // 1, //I2D, // -
         // -1, //L2I, // -
         // -1, //L2F, // -
         // 0, //L2D, // -
         // 0, //F2I, // -
         // 1, //F2L, // -
         // 1, //F2D, // -
         // -1, //D2I, // -
         // 0, //D2L, // -
         // -1, //D2F, // -
         // 0, //I2B, // -
         // 0, //I2C, // -
         // 0, //I2S, // -
         // -3, //LCMP, // -
         // -1, //FCMPL, // -
         // -1, //FCMPG, // -
         // -3, //DCMPL, // -
         // -3, //DCMPG, // -
         // -1, //IFEQ, // visitJumpInsn
         // -1, //IFNE, // -
         // -1, //IFLT, // -
         // -1, //IFGE, // -
         // -1, //IFGT, // -
         // -1, //IFLE, // -
         // -2, //IF_ICMPEQ, // -
         // -2, //IF_ICMPNE, // -
         // -2, //IF_ICMPLT, // -
         // -2, //IF_ICMPGE, // -
         // -2, //IF_ICMPGT, // -
         // -2, //IF_ICMPLE, // -
         // -2, //IF_ACMPEQ, // -
         // -2, //IF_ACMPNE, // -
         // 0, //GOTO, // -
         // 1, //JSR, // -
         // 0, //RET, // visitVarInsn
         // -1, //TABLESWITCH, // visiTableSwitchInsn
         // -1, //LOOKUPSWITCH, // visitLookupSwitch
         // -1, //IRETURN, // visitInsn
         // -2, //LRETURN, // -
         // -1, //FRETURN, // -
         // -2, //DRETURN, // -
         // -1, //ARETURN, // -
         // 0, //RETURN, // -
         // NA, //GETSTATIC, // visitFieldInsn
         // NA, //PUTSTATIC, // -
         // NA, //GETFIELD, // -
         // NA, //PUTFIELD, // -
         // NA, //INVOKEVIRTUAL, // visitMethodInsn
         // NA, //INVOKESPECIAL, // -
         // NA, //INVOKESTATIC, // -
         // NA, //INVOKEINTERFACE, // -
         // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn
         // 1, //NEW, // visitTypeInsn
         // 0, //NEWARRAY, // visitIntInsn
         // 0, //ANEWARRAY, // visitTypeInsn
         // 0, //ARRAYLENGTH, // visitInsn
         // NA, //ATHROW, // -
         // 0, //CHECKCAST, // visitTypeInsn
         // 0, //INSTANCEOF, // -
         // -1, //MONITORENTER, // visitInsn
         // -1, //MONITOREXIT, // -
         // NA, //WIDE, // NOT VISITED
         // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
         // -1, //IFNULL, // visitJumpInsn
         // -1, //IFNONNULL, // -
         // NA, //GOTO_W, // -
         // NA, //JSR_W, // -
         // };
         // for (i = 0; i < b.length; ++i) {
         // System.err.print((char)('E' + b[i]));
         // }
         // System.err.println();
     }

    
The label (i.e. basic block) to which these input and output stack map frames correspond.
 
     Label owner;

    
The input stack map frame locals.
 
     int[] inputLocals;

    
The input stack map frame stack.
 
     int[] inputStack;

    
The output stack map frame locals.
 
     private int[] outputLocals;

    
The output stack map frame stack.
 
     private int[] outputStack;

    
Relative size of the output stack. The exact semantics of this field depends on the algorithm that is used. When only the maximum stack size is computed, this field is the size of the output stack relatively to the top of the input stack. When the stack map frames are completely computed, this field is the actual number of types in outputStack.
 
     private int outputStackTop;

    
Number of types that are initialized in the basic block.

See also:
initializations
 
     private int initializationCount;

    
The types that are initialized in the basic block. A constructor invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace every occurence of this type in the local variables and in the operand stack. This cannot be done during the first phase of the algorithm since, during this phase, the local variables and the operand stack are not completely computed. It is therefore necessary to store the types on which constructors are invoked in the basic block, in order to do this replacement during the second phase of the algorithm, where the frames are fully computed. Note that this array can contain types that are relative to input locals or to the input stack (see below for the description of the algorithm).
 
     private int[] initializations;

    
Returns the output frame local variable type at the given index.

Parameters:
local the index of the local that must be returned.
Returns:
the output frame local variable type at the given index.
 
     private int get(final int local) {
         if ( == null || local >= .) {
             // this local has never been assigned in this basic block,
             // so it is still equal to its value in the input frame
             return  | local;
         } else {
             int type = [local];
             if (type == 0) {
                 // this local has never been assigned in this basic block,
                 // so it is still equal to its value in the input frame
                 type = [local] =  | local;
             }
             return type;
         }
     }

    
Sets the output frame local variable type at the given index.

Parameters:
local the index of the local that must be set.
type the value of the local that must be set.
 
     private void set(final int localfinal int type) {
         // creates and/or resizes the output local variables array if necessary
         if ( == null) {
              = new int[10];
         }
         int n = .;
         if (local >= n) {
             int[] t = new int[Math.max(local + 1, 2 * n)];
             System.arraycopy(, 0, t, 0, n);
              = t;
         }
         // sets the local variable
         [local] = type;
     }

    
Pushes a new type onto the output frame stack.

Parameters:
type the type that must be pushed.
 
     private void push(final int type) {
         // creates and/or resizes the output stack array if necessary
         if ( == null) {
              = new int[10];
         }
         int n = .;
         if ( >= n) {
             int[] t = new int[Math.max( + 1, 2 * n)];
             System.arraycopy(, 0, t, 0, n);
              = t;
         }
         // pushes the type on the output stack
         [++] = type;
         // updates the maximun height reached by the output stack, if needed
         int top = . + ;
         if (top > .) {
             . = top;
         }
     }

    
Pushes a new type onto the output frame stack.

Parameters:
cw the ClassWriter to which this label belongs.
desc the descriptor of the type to be pushed. Can also be a method descriptor (in this case this method pushes its return type onto the output frame stack).
 
     private void push(final ClassWriter cwfinal String desc) {
         int type = type(cwdesc);
         if (type != 0) {
             push(type);
             if (type ==  || type == ) {
                 push();
             }
         }
     }

    
Returns the int encoding of the given type.

Parameters:
cw the ClassWriter to which this label belongs.
desc a type descriptor.
Returns:
the int encoding of the given type.
 
     private static int type(final ClassWriter cwfinal String desc) {
         String t;
         int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
         switch (desc.charAt(index)) {
             case 'V':
                 return 0;
             case 'Z':
             case 'C':
             case 'B':
             case 'S':
             case 'I':
                 return ;
             case 'F':
                 return ;
             case 'J':
                 return ;
             case 'D':
                 return ;
             case 'L':
                 // stores the internal name, not the descriptor!
                 t = desc.substring(index + 1, desc.length() - 1);
                 return  | cw.addType(t);
                 // case '[':
             default:
                 // extracts the dimensions and the element type
                 int data;
                 int dims = index + 1;
                 while (desc.charAt(dims) == '[') {
                     ++dims;
                 }
                 switch (desc.charAt(dims)) {
                     case 'Z':
                         data = ;
                         break;
                     case 'C':
                         data = ;
                         break;
                     case 'B':
                         data = ;
                         break;
                     case 'S':
                         data = ;
                         break;
                     case 'I':
                         data = ;
                         break;
                     case 'F':
                         data = ;
                         break;
                     case 'J':
                         data = ;
                         break;
                     case 'D':
                         data = ;
                         break;
                     // case 'L':
                     default:
                         // stores the internal name, not the descriptor
                         t = desc.substring(dims + 1, desc.length() - 1);
                         data =  | cw.addType(t);
                 }
                 return (dims - index) << 28 | data;
         }
     }

    
Pops a type from the output frame stack and returns its value.

Returns:
the type that has been popped from the output frame stack.
 
     private int pop() {
         if ( > 0) {
             return [--];
         } else {
             // if the output frame stack is empty, pops from the input stack
             return  | -(--.);
         }
     }

    
Pops the given number of types from the output frame stack.

Parameters:
elements the number of types that must be popped.
 
     private void pop(final int elements) {
         if ( >= elements) {
              -= elements;
         } else {
             // if the number of elements to be popped is greater than the number
             // of elements in the output stack, clear it, and pops the remaining
             // elements from the input stack.
             . -= elements - ;
              = 0;
         }
     }

    
Pops a type from the output frame stack.

Parameters:
desc the descriptor of the type to be popped. Can also be a method descriptor (in this case this method pops the types corresponding to the method arguments).
 
     private void pop(final String desc) {
         char c = desc.charAt(0);
         if (c == '(') {
             pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1);
         } else if (c == 'J' || c == 'D') {
             pop(2);
         } else {
             pop(1);
         }
     }

    
Adds a new type to the list of types on which a constructor is invoked in the basic block.

Parameters:
var a type on a which a constructor is invoked.
 
     private void init(final int var) {
         // creates and/or resizes the initializations array if necessary
         if ( == null) {
              = new int[2];
         }
         int n = .;
         if ( >= n) {
             int[] t = new int[Math.max( + 1, 2 * n)];
             System.arraycopy(, 0, t, 0, n);
              = t;
         }
         // stores the type to be initialized
         [++] = var;
     }

    
Replaces the given type with the appropriate type if it is one of the types on which a constructor is invoked in the basic block.

Parameters:
cw the ClassWriter to which this label belongs.
t a type
Returns:
t or, if t is one of the types on which a constructor is invoked in the basic block, the type corresponding to this constructor.
 
     private int init(final ClassWriter cwfinal int t) {
         int s;
         if (t == ) {
             s =  | cw.addType(cw.thisName);
         } else if ((t & ( | )) == ) {
             String type = cw.typeTable[t & ].;
             s =  | cw.addType(type);
         } else {
             return t;
         }
         for (int j = 0; j < ; ++j) {
             int u = [j];
             int dim = u & ;
             int kind = u & ;
             if (kind == ) {
                 u = dim + [u & ];
             } else if (kind == ) {
                 u = dim + [. - (u & )];
             }
             if (t == u) {
                 return s;
             }
         }
         return t;
     }

    
Initializes the input frame of the first basic block from the method descriptor.

Parameters:
cw the ClassWriter to which this label belongs.
access the access flags of the method to which this label belongs.
args the formal parameter types of this method.
maxLocals the maximum number of local variables of this method.
 
     void initInputFrame(
         final ClassWriter cw,
         final int access,
         final Type[] args,
         final int maxLocals)
     {
          = new int[maxLocals];
          = new int[0];
         int i = 0;
         if ((access & .) == 0) {
             if ((access & .) == 0) {
                 [i++] =  | cw.addType(cw.thisName);
             } else {
                 [i++] = ;
             }
         }
         for (int j = 0; j < args.length; ++j) {
             int t = type(cwargs[j].getDescriptor());
             [i++] = t;
             if (t ==  || t == ) {
                 [i++] = ;
             }
         }
         while (i < maxLocals) {
             [i++] = ;
         }
     }

    
Simulates the action of the given instruction on the output stack frame.

Parameters:
opcode the opcode of the instruction.
arg the operand of the instruction, if any.
cw the class writer to which this label belongs.
item the operand of the instructions, if any.
 
     void execute(
         final int opcode,
         final int arg,
         final ClassWriter cw,
         final Item item)
     {
         int t1t2t3t4;
         switch (opcode) {
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
                 break;
             case .:
                 push();
                 break;
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
                 push();
                 break;
             case .:
             case .:
             case .:
                 push();
                 push();
                 break;
             case .:
             case .:
             case .:
             case .:
                 push();
                 break;
             case .:
             case .:
             case .:
                 push();
                 push();
                 break;
             case .:
                 switch (item.type) {
                     case .:
                         push();
                         break;
                     case .:
                         push();
                         push();
                         break;
                     case .:
                         push();
                         break;
                     case .:
                         push();
                         push();
                         break;
                     case .:
                         push( | cw.addType("java/lang/Class"));
                         break;
                     case .:
                         push( | cw.addType("java/lang/String"));
                         break;
                     case .:
                         push( | cw.addType("java/lang/invoke/MethodType"));
                         break;
                     // case ClassWriter.HANDLE_BASE + [1..9]:
                     default:
                         push( | cw.addType("java/lang/invoke/MethodHandle"));
                 }
                 break;
             case .:
                 push(get(arg));
                 break;
             case .:
             case .:
             case .:
             case .:
                 pop(2);
                 push();
                 break;
             case .:
             case .:
                 pop(2);
                 push();
                 push();
                 break;
             case .:
                 pop(2);
                 push();
                 break;
             case .:
             case .:
                 pop(2);
                 push();
                 push();
                 break;
             case .:
                 pop(1);
                 t1 = pop();
                 push( + t1);
                 break;
             case .:
             case .:
             case .:
                 t1 = pop();
                 set(argt1);
                 if (arg > 0) {
                     t2 = get(arg - 1);
                     // if t2 is of kind STACK or LOCAL we cannot know its size!
                     if (t2 ==  || t2 == ) {
                         set(arg - 1, );
                     } else if ((t2 & ) != ) {
                         set(arg - 1, t2 | );
                     }
                 }
                 break;
             case .:
             case .:
                 pop(1);
                 t1 = pop();
                 set(argt1);
                 set(arg + 1, );
                 if (arg > 0) {
                     t2 = get(arg - 1);
                     // if t2 is of kind STACK or LOCAL we cannot know its size!
                     if (t2 ==  || t2 == ) {
                         set(arg - 1, );
                     } else if ((t2 & ) != ) {
                         set(arg - 1, t2 | );
                     }
                 }
                 break;
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
                 pop(3);
                 break;
             case .:
             case .:
                 pop(4);
                 break;
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
            case .:
            case .:
            case .:
            case .:
                pop(1);
                break;
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
                pop(2);
                break;
            case .:
                t1 = pop();
                push(t1);
                push(t1);
                break;
            case .:
                t1 = pop();
                t2 = pop();
                push(t1);
                push(t2);
                push(t1);
                break;
            case .:
                t1 = pop();
                t2 = pop();
                t3 = pop();
                push(t1);
                push(t3);
                push(t2);
                push(t1);
                break;
            case .:
                t1 = pop();
                t2 = pop();
                push(t2);
                push(t1);
                push(t2);
                push(t1);
                break;
            case .:
                t1 = pop();
                t2 = pop();
                t3 = pop();
                push(t2);
                push(t1);
                push(t3);
                push(t2);
                push(t1);
                break;
            case .:
                t1 = pop();
                t2 = pop();
                t3 = pop();
                t4 = pop();
                push(t2);
                push(t1);
                push(t4);
                push(t3);
                push(t2);
                push(t1);
                break;
            case .:
                t1 = pop();
                t2 = pop();
                push(t1);
                push(t2);
                break;
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
                pop(2);
                push();
                break;
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
                pop(4);
                push();
                push();
                break;
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
            case .:
                pop(2);
                push();
                break;
            case .:
            case .:
            case .:
            case .:
            case .:
                pop(4);
                push();
                push();
                break;
            case .:
            case .:
            case .:
                pop(3);
                push();
                push();
                break;
            case .:
                set(arg);
                break;
            case .:
            case .:
                pop(1);
                push();
                push();
                break;
            case .:
                pop(1);
                push();
                break;
            case .:
            case .:
                pop(1);
                push();
                push();
                break;
            case .:
            case .:
            case .:
                pop(1);
                push();
                break;
            case .:
            case .:
            case .:
                pop(4);
                push();
                break;
            case .:
            case .:
                throw new RuntimeException("JSR/RET are not supported with computeFrames option");
            case .:
                push(cwitem.strVal3);
                break;
            case .:
                pop(item.strVal3);
                break;
            case .:
                pop(1);
                push(cwitem.strVal3);
                break;
            case .:
                pop(item.strVal3);
                pop();
                break;
            case .:
            case .:
            case .:
            case .:
                pop(item.strVal3);
                if (opcode != .) {
                    t1 = pop();
                    if (opcode == .
                            && item.strVal2.charAt(0) == '<')
                    {
                        init(t1);
                    }
                }
                push(cwitem.strVal3);
                break;
            case .:
                pop(item.strVal2);
                push(cwitem.strVal2);
                break;
            case .:
                push( | cw.addUninitializedType(item.strVal1arg));
                break;
            case .:
                pop();
                switch (arg) {
                    case .:
                        push( | );
                        break;
                    case .:
                        push( | );
                        break;
                    case .:
                        push( | );
                        break;
                    case .:
                        push( | );
                        break;
                    case .:
                        push( | );
                        break;
                    case .:
                        push( | );
                        break;
                    case .:
                        push( | );
                        break;
                    // case Opcodes.T_LONG:
                    default:
                        push( | );
                        break;
                }
                break;
            case .:
                String s = item.strVal1;
                pop();
                if (s.charAt(0) == '[') {
                    push(cw'[' + s);
                } else {
                    push( |  | cw.addType(s));
                }
                break;
            case .:
                s = item.strVal1;
                pop();
                if (s.charAt(0) == '[') {
                    push(cws);
                } else {
                    push( | cw.addType(s));
                }
                break;
            // case Opcodes.MULTIANEWARRAY:
            default:
                pop(arg);
                push(cwitem.strVal1);
                break;
        }
    }

    
Merges the input frame of the given basic block with the input and output frames of this basic block. Returns true if the input frame of the given label has been changed by this operation.

Parameters:
cw the ClassWriter to which this label belongs.
frame the basic block whose input frame must be updated.
edge the kind of the Edge between this label and 'label'. See Edge.info.
Returns:
true if the input frame of the given label has been changed by this operation.
    boolean merge(final ClassWriter cwfinal Frame framefinal int edge) {
        boolean changed = false;
        int isdimkindt;
        int nLocal = .;
        int nStack = .;
        if (frame.inputLocals == null) {
            frame.inputLocals = new int[nLocal];
            changed = true;
        }
        for (i = 0; i < nLocal; ++i) {
            if ( != null && i < .) {
                s = [i];
                if (s == 0) {
                    t = [i];
                } else {
                    dim = s & ;
                    kind = s & ;
                    if (kind == ) {
                        t = s;
                    } else {
                        if (kind == ) {
                            t = dim + [s & ];
                        } else {
                            t = dim + [nStack - (s & )];
                        }
                        if ((s & ) != 0 && (t ==  || t == )) {
                            t = ;
                        }
                    }
                }
            } else {
                t = [i];
            }
            if ( != null) {
                t = init(cwt);
            }
            changed |= merge(cwtframe.inputLocalsi);
        }
        if (edge > 0) {
            for (i = 0; i < nLocal; ++i) {
                t = [i];
                changed |= merge(cwtframe.inputLocalsi);
            }
            if (frame.inputStack == null) {
                frame.inputStack = new int[1];