src/main/java/org/plumelib/bcelutil/StackMapUtils.java
protected final LocalVariableGen add_new_parameter(
      MethodGen mgen, String arg_name, Type arg_type) {
    // We add a new parameter, after any current ones, and then
    // we need to make a pass over the byte codes to update the local
    // offset values of all the locals we just shifted up.  This may have
    // a 'knock on' effect if we are forced to change an instruction that
    // references implict local #3 to an instruction with an explict
    // reference to local #4 as this would require the insertion of an
    // offset into the byte codes. This means we would need to make an
    // additional pass to update branch targets (no - BCEL does this for
    // us) and the StackMapTable (yes - BCEL should do this, but it doesn't).
    //

    LocalVariableGen arg_new = null;
    // get a copy of the locals before modification
    LocalVariableGen[] locals = mgen.getLocalVariables();
    Type[] arg_types = mgen.getArgumentTypes();
    int new_index = 0;
    int new_offset = 0;

    boolean has_code = (mgen.getInstructionList() != null);

    if (has_code) {
      if (!mgen.isStatic()) {
        // Skip the 'this' pointer.
        new_index++;
        new_offset++; // size of 'this' is 1
      }

      if (arg_types.length > 0) {
        LocalVariableGen last_arg;
        new_index = new_index + arg_types.length;
        // new_index is now positive, because arg_types.length is
        last_arg = locals[new_index - 1];
        new_offset = last_arg.getIndex() + (last_arg.getType()).getSize();
      }

      // Insert our new local variable into existing table at 'new_offset'.
      arg_new = mgen.addLocalVariable(arg_name, arg_type, new_offset, null, null);

      // Update the index of the first 'true' local in the local variable table.
      first_local_index++;
    }
    initial_locals_count++;

    // Update the method's parameter information.
    arg_types = BcelUtil.postpendToArray(arg_types, arg_type);
    String[] arg_names = add_string(mgen.getArgumentNames(), arg_name);
    mgen.setArgumentTypes(arg_types);
    mgen.setArgumentNames(arg_names);

    if (has_code) {
      // we need to adjust the offset of any locals after our insertion
      for (int i = new_index; i < locals.length; i++) {
        LocalVariableGen lv = locals[i];
        lv.setIndex(lv.getIndex() + arg_type.getSize());
      }
      mgen.setMaxLocals(mgen.getMaxLocals() + arg_type.getSize());

      debug_instrument.log(
          "Added arg    %s%n",
          arg_new.getIndex() + ": " + arg_new.getName() + ", " + arg_new.getType());

      // Now process the instruction list, adding one to the offset
      // within each LocalVariableInstruction that references a
      // local that is 'higher' in the local map than new local
      // we just inserted.
      adjust_code_for_locals_change(mgen, new_offset, arg_type.getSize());

      // Finally, we need to update any FULL_FRAME StackMap entries to
      // add in the new local variable type.
      update_full_frame_stack_map_entries(new_offset, arg_type, locals);

      debug_instrument.log("New LocalVariableTable:%n%s%n", mgen.getLocalVariableTable(pool));
    }
    return arg_new;
  }
protected final LocalVariableGen add_new_parameter(
      MethodGen mgen, String arg_name, Type arg_type) {
    // We add a new parameter, after any current ones, and then
    // we need to make a pass over the byte codes to update the local
    // offset values of all the locals we just shifted up.  This may have
    // a 'knock on' effect if we are forced to change an instruction that
    // references implict local #3 to an instruction with an explict
    // reference to local #4 as this would require the insertion of an
    // offset into the byte codes. This means we would need to make an
    // additional pass to update branch targets (no - BCEL does this for
    // us) and the StackMapTable (yes - BCEL should do this, but it doesn't).
    //

    LocalVariableGen arg_new = null;
    // get a copy of the locals before modification
    LocalVariableGen[] locals = mgen.getLocalVariables();
    Type[] arg_types = mgen.getArgumentTypes();
    int new_index = 0;
    int new_offset = 0;

    boolean has_code = (mgen.getInstructionList() != null);

    if (has_code) {
      if (!mgen.isStatic()) {
        // Skip the 'this' pointer.
        new_index++;
        new_offset++; // size of 'this' is 1
      }

      if (arg_types.length > 0) {
        LocalVariableGen last_arg;
        new_index = new_index + arg_types.length;
        // new_index is now positive, because arg_types.length is
        last_arg = locals[new_index - 1];
        new_offset = last_arg.getIndex() + (last_arg.getType()).getSize();
      }

      // Insert our new local variable into existing table at 'new_offset'.
      arg_new = mgen.addLocalVariable(arg_name, arg_type, new_offset, null, null);

      // Update the index of the first 'true' local in the local variable table.
      first_local_index++;
    }
    initial_locals_count++;

    // Update the method's parameter information.
    arg_types = BcelUtil.postpendToArray(arg_types, arg_type);
    String[] arg_names = add_string(mgen.getArgumentNames(), arg_name);
    mgen.setArgumentTypes(arg_types);
    mgen.setArgumentNames(arg_names);

    if (has_code) {
      // we need to adjust the offset of any locals after our insertion
      for (int i = new_index; i < locals.length; i++) {
        LocalVariableGen lv = locals[i];
        lv.setIndex(lv.getIndex() + arg_type.getSize());
      }
      mgen.setMaxLocals(mgen.getMaxLocals() + arg_type.getSize());

      debug_instrument.log(
          "Added arg    %s%n",
          arg_new.getIndex() + ": " + arg_new.getName() + ", " + arg_new.getType());

      // Now process the instruction list, adding one to the offset
      // within each LocalVariableInstruction that references a
      // local that is 'higher' in the local map than new local
      // we just inserted.
      adjust_code_for_locals_change(mgen, new_offset, arg_type.getSize());

      // Finally, we need to update any FULL_FRAME StackMap entries to
      // add in the new local variable type.
      update_full_frame_stack_map_entries(new_offset, arg_type, locals);

      debug_instrument.log("New LocalVariableTable:%n%s%n", mgen.getLocalVariableTable(pool));
    }
    return arg_new;
  }
Add a new parameter to the method. This will be added after last current parameter and before
the first local variable. This might have the side effect of causing us to rewrite the method
byte codes to adjust the offsets for the local variables - see below for details.

<p>Must call fix_local_variable_table (just once per method) before calling this routine.

@param mgen MethodGen to be modified
@param arg_name name of new parameter
@param arg_type type of new parameter
@return a LocalVariableGen for the new parameter