title: Construct FrameNode with ASM api
body: <p>I succeeded in implementing bytecode method inline optimization and the generated code seems OK for me. Yet, the verification fails with message: </p>
  
  <pre><code>java.lang.VerifyError: Expecting a stackmap frame at branch target 47
  Exception Details:
    Location:
      code/sxu/asm/example/Caller.test(II)V @44: goto
    Reason:
      Expected stackmap frame at this location.
  </code></pre>
  
  <p>And the corresponding bytecode is: </p>
  
  <pre><code>public void test(int, int);
      flags: ACC_PUBLIC
      Code:
        stack=4, locals=8, args_size=3
           0: iload_1       
           1: iload_2       
           2: iadd          
           3: aload_0       
           4: getfield      #14                 // Field _callee:Lcode/sxu/asm/example/Callee;
           7: iload_1       
           8: iload_2       
           9: istore_3      
          10: istore        4
          12: astore        5
          14: aload         5
          16: getfield      #40                 // Field code/sxu/asm/example/Callee._a:Ljava/lang/String;
          19: invokevirtual #46                 // Method java/lang/String.length:()I
          22: aload         5
          24: getfield      #49                 // Field code/sxu/asm/example/Callee._b:Ljava/lang/String;
          27: invokevirtual #46                 // Method java/lang/String.length:()I
          30: iadd          
          31: istore        6
          33: iload         6
          35: iload         4
          37: iload_3       
          38: iadd          
          39: iadd          
          40: istore        6
          42: iload         6
          44: goto          47
          47: isub          
          48: istore        7
          50: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
          53: iload         7
          55: invokevirtual #65                 // Method java/io/PrintStream.println:(I)V
          58: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
          61: ldc           #67                 // String 1..........
          63: invokevirtual #70                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          66: return        
        LocalVariableTable:
          Start  Length  Slot  Name   Signature
                14      33     0  this   Lcode/sxu/asm/example/Callee;
                14      33     1     t   I
                14      33     2     p   I
                33      14     7   tmp   I
                 0      67     0  this   Lcode/sxu/asm/example/Caller;
                 0      67     1     a   I
                 0      67     2     b   I
                50      17     7     r   I
        LineNumberTable:
          line 16: 0
          line 13: 14
          line 14: 33
          line 15: 42
          line 18: 50
          line 19: 58
          line 20: 66
  }
  </code></pre>
  
  <p>Line 9-11: store stacked parameters. Line 14-44: inlined bytecodes of Callee, and its last <code>ireturn</code> is replaced by <code>GOTO</code>.</p>
  
  <p>Two possible solutions for the verification failure in Java7:</p>
  
  <ul>
  <li><p>Add <code>-XX:-UseSplitVerifier</code> for VM argument. The option works but the it is deprecated in Java8. </p></li>
  <li><p>Add the stackmap table before line 44 (The one before GOTO instruction), that lists the types at positions which are targets of jumps (from <a href="https://stackoverflow.com/questions/25109942/is-there-a-better-explanation-of-stack-map-frames">Stackmap frame description</a>). </p></li>
  </ul>
  
  <p>For me, option 2 is preferable, but i have problem in construction of the frame. My code is: </p>
  
  <pre><code>    if (opcode == Opcodes.RETURN || opcode == Opcodes.IRETURN) {
          FrameNode stackMap = new FrameNode(Opcodes.NEW, -1, null, -1, null);
          stackMap.accept(mv);    //Visit The framenode before GOTO
          super.visitJumpInsn(Opcodes.GOTO, end);
      } else {
          super.visitInsn(opcode);
      }
  </code></pre>
  
  <p>I think both <code>Opcodes.NEW/SMAE</code> should work here. But it is impossible to calculate the remaining four arguments because the visitor has not visited the target codes and it does not know the nStack, nlocals..</p>
  
  <p><strong>So can anyone give suggestion in constructing the FrameNode here or example to handle this case? Thanks.</strong> </p>
  
  <p>The description for FramNode<a href="http://asm.ow2.org/asm50/javadoc/user/org/objectweb/asm/tree/FrameNode.html#FrameNode%28int,%20int,%20java.lang.Object[],%20int,%20java.lang.Object[]%29" rel="nofollow noreferrer">FrameNode ASM Document</a>: </p>
  
  <blockquote>
    <p>public FrameNode(int type,
                     int nLocal,
                     Object[] local,
                     int nStack,
                     Object[] stack)</p>
    
    <p>Constructs a new FrameNode.</p>
    
    <p>Parameters:</p>
  </blockquote>
  
  <pre><code>type - the type of this frame. Must be Opcodes.F_NEW for expanded frames, or Opcodes.F_FULL, Opcodes.F_APPEND, Opcodes.F_CHOP, Opcodes.F_SAME or Opcodes.F_APPEND, Opcodes.F_SAME1 for compressed frames.
  nLocal - number of local variables of this stack map frame.
  local - the types of the local variables of this stack map frame. Elements of this list can be Integer, String or LabelNode objects (for primitive, reference and uninitialized types respectively - see MethodVisitor).
  nStack - number of operand stack elements of this stack map frame.
  stack - the types of the operand stack elements of this stack map frame. Elements of this list can be Integer, String or LabelNode objects (for primitive, reference and uninitialized types respectively - see MethodVisitor). 
  </code></pre>