title: Method invocation instruction (invokevirtual/invokestatic) is substituted by some unexpected instructions
body: <p>I have been investigating this error for a whole three days, but still no progress. I hope I can get some tips from here. </p>
  
  <p>What I am trying to do is to inline a MethodNode into a MethodHandle Call Site (#5, #17, and #30) with ASM library. For simplification, the MethodHandle at #5 references a static method <code>static Functions.isFooString(String)boolen</code>. </p>
  
  <p>At the call site, the instruction before inlining is like </p>
  
  <pre><code>    //Before
    stack=3, locals=3, args_size=3
       0: aload_0
       1: getfield      #15                 // Field guard:Ljava/lang/invoke/MethodHandle;
       4: aload_1
       5: invokevirtual #29                 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;)Z
       8: ifeq          24
      11: aload_0
      12: getfield      #17                 // Field trueTarget:Ljava/lang/invoke/MethodHandle;
      15: aload_1
      16: aload_2
      17: invokevirtual #31                 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
      20: checkcast     #33                 // class java/lang/String
      23: areturn
      24: aload_0
      25: getfield      #19                 // Field falseTarget:Ljava/lang/invoke/MethodHandle;
      28: aload_1
      29: aload_2
      30: invokevirtual #31                 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
      33: checkcast     #33                 // class java/lang/String
      36: areturn
     StackMapTable: number_of_entries = 1
     frame_type = 24 /* same */
   Exceptions:
      throws java.lang.Throwable
  </code></pre>
  
  <p>The inlining rule is that copy inline's body into the call site after storing the arguments to local variables. After inlining, the instruction list is: </p>
  
  <pre><code>  //After
  Classfile /C:/temp/DYNGuardWithTestHandle1439587569404.class
    Last modified Aug 14, 2015; size 913 bytes
    MD5 checksum 055a99d52cb622a7e86c59de79347f3e
  public class DYNGuardWithTestHandle1439587569404 extends java.lang.invoke.BaseTemplate
    minor version: 0
    major version: 51
    flags: ACC_PUBLIC, ACC_SUPER
  Constant pool:
     #1 = Utf8               DYNGuardWithTestHandle1439587569404
     #2 = Class              #1             // DYNGuardWithTestHandle1439587569404
     #3 = Utf8               java/lang/invoke/BaseTemplate
     #4 = Class              #3             // java/lang/invoke/BaseTemplate
     #5 = Utf8               guard
     #6 = Utf8               Ljava/lang/invoke/MethodHandle;
     #7 = Utf8               trueTarget
     #8 = Utf8               falseTarget
     #9 = Utf8               &lt;init&gt;
    #10 = Utf8               (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V
    #11 = Utf8               ()V
    #12 = NameAndType        #9:#11         // "&lt;init&gt;":()V
    #13 = Methodref          #4.#12         // java/lang/invoke/BaseTemplate."&lt;init&gt;":()V
    #14 = NameAndType        #5:#6          // guard:Ljava/lang/invoke/MethodHandle;
    #15 = Fieldref           #2.#14         // DYNGuardWithTestHandle1439587569404.guard:Ljava/lang/invoke/MethodHandle;
    #16 = NameAndType        #7:#6          // trueTarget:Ljava/lang/invoke/MethodHandle;
    #17 = Fieldref           #2.#16         // DYNGuardWithTestHandle1439587569404.trueTarget:Ljava/lang/invoke/MethodHandle;
    #18 = NameAndType        #8:#6          // falseTarget:Ljava/lang/invoke/MethodHandle;
    #19 = Fieldref           #2.#18         // DYNGuardWithTestHandle1439587569404.falseTarget:Ljava/lang/invoke/MethodHandle;
    #20 = Utf8               eval
    #21 = Utf8               invokeExact
    #22 = Utf8               (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    #23 = Utf8               java/lang/Throwable
    #24 = Class              #23            // java/lang/Throwable
    #25 = Utf8               test/code/jit/asm/methodhandle/Functions
    #26 = Class              #25            // test/code/jit/asm/methodhandle/Functions
    #27 = Utf8               isFooString
    #28 = Utf8               (Ljava/lang/String;)Z
    #29 = NameAndType        #27:#28        // isFooString:(Ljava/lang/String;)Z
    #30 = Methodref          #26.#29        // test/code/jit/asm/methodhandle/Functions.isFooString:(Ljava/lang/String;)Z
    #31 = Utf8               printTrueTarget
    #32 = NameAndType        #31:#22        // printTrueTarget:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    #33 = Methodref          #26.#32        // test/code/jit/asm/methodhandle/Functions.printTrueTarget:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    #34 = Utf8               java/lang/String
    #35 = Class              #34            // java/lang/String
    #36 = Utf8               java/lang/Object
    #37 = Class              #36            // java/lang/Object
    #38 = Utf8               printFalseTarget
    #39 = NameAndType        #38:#22        // printFalseTarget:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    #40 = Methodref          #26.#39        // test/code/jit/asm/methodhandle/Functions.printFalseTarget:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    #41 = Utf8               Code
    #42 = Utf8               StackMapTable
    #43 = Utf8               Exceptions
  {
    final java.lang.invoke.MethodHandle guard;
      descriptor: Ljava/lang/invoke/MethodHandle;
      flags: ACC_FINAL
  
    final java.lang.invoke.MethodHandle trueTarget;
      descriptor: Ljava/lang/invoke/MethodHandle;
      flags: ACC_FINAL
  
    final java.lang.invoke.MethodHandle falseTarget;
      descriptor: Ljava/lang/invoke/MethodHandle;
      flags: ACC_FINAL
  
    public DYNGuardWithTestHandle1439587569404(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
      descriptor: (Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V
      flags: ACC_PUBLIC
      Code:
        stack=2, locals=4, args_size=4
           0: aload_0
           1: invokespecial #13                 // Method java/lang/invoke/BaseTemplate."&lt;init&gt;":()V
           4: aload_0
           5: aload_1
           6: putfield      #15                 // Field guard:Ljava/lang/invoke/MethodHandle;
           9: aload_0
          10: aload_2
          11: putfield      #17                 // Field trueTarget:Ljava/lang/invoke/MethodHandle;
          14: aload_0
          15: aload_3
          16: putfield      #19                 // Field falseTarget:Ljava/lang/invoke/MethodHandle;
          19: return
  
    public void eval();
      descriptor: ()V
      flags: ACC_PUBLIC
      Code:
        stack=0, locals=1, args_size=1
           0: return
  
    public java.lang.String invokeExact(java.lang.String, java.lang.String) throws java.lang.Throwable;
      descriptor: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
      flags: ACC_PUBLIC
      Code:
        stack=3, locals=8, args_size=3
           0: aload_0
           1: getfield      #15                 // Field guard:Ljava/lang/invoke/MethodHandle;
           4: aload_1
           5: astore_3
           6: aload_3
           7: invokestatic  #0                  // #0
          10: fload_2
          11: nop
          12: iconst_0
          13: swap
          14: pop
          15: ifeq          44
          18: aload_0
          19: getfield      #17                 // Field trueTarget:Ljava/lang/invoke/MethodHandle;
          22: aload_1
          23: aload_2
          24: astore        4
          26: astore        5
          28: aload         5
          30: aload         4
          32: invokestatic  #33                 // Method test/code/jit/asm/methodhandle/Functions.printTrueTarget:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
          35: goto          38
          38: swap
          39: pop
          40: checkcast     #35                 // class java/lang/String
          43: areturn
          44: aload_0
          45: getfield      #19                 // Field falseTarget:Ljava/lang/invoke/MethodHandle;
          48: aload_1
          49: aload_2
          50: astore        6
          52: astore        7
          54: aload         7
          56: aload         6
          58: invokestatic  #40                 // Method test/code/jit/asm/methodhandle/Functions.printFalseTarget:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
          61: goto          64
          64: swap
          65: pop
          66: checkcast     #35                 // class java/lang/String
          69: areturn
        StackMapTable: number_of_entries = 1
          frame_type = 254 /* append */
            offset_delta = 44
            locals = [ class java/lang/Object, class java/lang/Object, class java/lang/Object ]
      Exceptions:
        throws java.lang.Throwable
  
  }
  </code></pre>
  
  <p>Clearly, the #5 (before)in the original instruction is replaced by WRONG instructions #7--#12 (after), which should not exist here. Instead, there should only be one instruction, here: </p>
  
  <pre><code>   invokestatic Method test/code/jit/asm/methodhandle/Functions.isFooString:(Ljava/lang/String;)Z;
  </code></pre>
  
  <p>Worse, the #7 of the invokeExact(after) is completely illegal which caused the JVM crash down. 
  The other two instructions #17 and #30 (before) are correctly substituted. </p>
  
  <p>It is clear from the generated bytecodes, but this is different from the behavior defined by my code. The way to build the MethodNode is: </p>
  
  <pre><code>   MethodNode buildMethod(...){
       ...
      access=ACC_PUBLIC+ACC_STATIC;
      String owner = Type.getType(definingClass).getInternalName();
      String desc = type.toMethodDescriptorString();
      MethodNode methodNode = new MethodNode(Opcodes.ASM5, access, mhName, type.toString(), null, null);
      if(name.equals("isFooString")){
          methodNode.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
          System.out.println("owner="+owner+" name="+name+"  desc="+desc);
         //owner=test/code/jit/asm/methodhandle/Functions name=isFooString  desc=(Ljava/lang/String;)Z
          methodNode.instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, owner, name, desc, false));
          methodNode.instructions.add(new InsnNode(Opcodes.IRETURN));
          return methodNode;
      }
  
      AbstractInsnNode insn = new MethodInsnNode(originIsFindVirtual?Opcodes.INVOKEVIRTUAL: Opcodes.INVOKESTATIC, owner, name, desc, false);
      Type[] args = Type.getArgumentTypes(desc);
  
      for(Type arg : args){
          AbstractInsnNode node = new VarInsnNode(arg.getOpcode(Opcodes.ILOAD), start);
          start += arg.getSize();
          methodNode.instructions.add(node);
      }
      methodNode.instructions.add(insn);
      int Return = Type.getReturnType(desc).getOpcode(Opcodes.IRETURN);
  
      methodNode.instructions.add(new InsnNode(Return));
      return methodNode;
      }
  </code></pre>
  
  <p>And InliningAdapter: </p>
  
  <pre><code>//The full version can be accessed by https://github.com/xushijie/InlineMethod/blob/typeinference/src/main/java/code/jit/asm/core/InliningAdapter.java
  public class InliningAdapter extends RemappingMethodAdapter{
  
  /** The main task in the Constructor is to store pushed parameters of the MethodNode to a new local variables and store the remaining arguments of the stack to another temporary stacks in case of exceptions in the MethodNode */ 
  public InliningAdapter(LocalVariablesSorter lvsMV, int acc, String desc,
  Remapper remapper, Label end, MethodContext context) {
     super(acc, desc, lvsMV, remapper);
     lvs = lvsMV;
     mv = context.getRawMV();
     this.end = end;
     _context = context;
     List&lt;Type&gt; types = _context.getOperandStack();
     int offset = ((acc &amp; Opcodes.ACC_STATIC) != 0 ? 0 : 1);
     Type[] args = Type.getArgumentTypes(desc);
     for (int i = args.length - 1; i &gt;= 0; i--) {
        super.visitVarInsn(args[i].getOpcode(Opcodes.ISTORE), i + offset);
     }
     int poped = args.length;
     if (offset &gt; 0) {
     poped++;
     super.visitVarInsn(Opcodes.ASTORE, 0);
     }
     int left = types.size() - poped - 1;
     while (left &gt; 0) {
     // NON-parameters in the stack =&gt; pop up too and restore back after
     // complete.
     int variable = newLocal(types.get(left));
     int opcode = types.get(left).getOpcode(Opcodes.ISTORE);
     __callerstacks.add(0, new StackEle(types.get(left), variable)); //    |--&gt;TOP
     mv.visitVarInsn(opcode, variable);
     left--;
     }
  }
  
  @Override
  public void visitMethodInsn(final int opcode, final String owner,
          final String name, final String desc, final boolean itf) {
      System.out.println("[Callee: ] invokeVirtual "+ owner +"  "+name+"  "+ desc);
      _context.getRawMV().visitMethodInsn(opcode, owner, name, desc, itf);
      //_context.getRawMV() is a MethodWriter. and the value of the (owner, name, desc) is /.//Functions, isFooString, (String;)Z, which is correct. 
  }
  
  @Override
  public void visitVarInsn(final int opcode, final int var) {
      //I confirm this method is not invoked after visitMethodInsn. 
      super.visitVarInsn(opcode, var + firstLocal);
  }
  }
  </code></pre>
  
  <p>For each invokevirtual instruction (#5, #17. #30) in the original bytecodes, it is like: </p>
  
  <pre><code>mn = buildMethodNode(...);
  mn.accept(new InliningAdapter(this,
                      opcode == Opcodes.INVOKESTATIC ? Opcodes.ACC_STATIC : 0, desc,  _context));  //mn is my constructed MethodNode previsouly, which contains one method invocation. 
  </code></pre>
  
  <p>To resolve the issue( the parameters for the first visited <code>invokestatic</code> is missing and some illegal instructions are added). I debug my code (Sorry I cannot post all of it here because there are too many files), and it monitors all parameters that are written to the MethodWriter in the<code>visitMethodInsn</code> of the <code>InliningAdapter</code>. It proves that all these values (Functions, isFooString, (String;)Z) are correct, which are the same as my expectation. </p>
  
  <p>So my questions are: </p>
  
  <ul>
  <li>Is there something wrong in my MethodNode builder? </li>
  <li><p>What kinds of reasons can result to this issue?  There are also other similar cases, where the first <code>invokevirtual</code> instructions are wrongly substituted by something like, nop, fdouble, and asatore (These substitutions do not exist in my code). </p></li>
  <li><p>Also, I confirm the override method <code>visitMethodInsn</code> is not invoked after the <code>visitMethodInsn</code> before <code>accept</code> completes. That means, the wrong instructions, i.e., #10 <code>fload</code> and #12 <code>iconst</code>, are not from the built MethodNode. </p></li>
  <li><p>I made another try that disable the inlining of the first invokevirtual (#5 //Before). The generated class succeeds and can be launched. For me, it looks like the problem is at <code>isFooString</code> MethodNode  building.</p></li>
  </ul>