src/main/java/org/plumelib/bcelutil/StackMapUtils.java
protected final LocalVariableGen create_method_scope_local(
      MethodGen mgen, String local_name, Type local_type) {
    // BCEL sorts local vars and presents them in offset order.  Search
    // locals for first var with start != 0. If none, just add the new
    // var at the end of the table and exit. Otherwise, insert the new
    // var just prior to the local we just found.
    // Now 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).
    //
    // We never want to insert our local prior to any parameters.  This would
    // happen naturally, but some old class files have non zero addresses
    // for 'this' and/or the parameters so we need to add an explicit
    // check to make sure we skip these variables.

    LocalVariableGen lv_new;
    int max_offset = 0;
    int new_offset = -1;
    // get a copy of the local before modification
    LocalVariableGen[] locals = mgen.getLocalVariables();
    @IndexOrLow("locals") int compiler_temp_i = -1;
    int new_index = -1;
    int i;

    for (i = 0; i < locals.length; i++) {
      LocalVariableGen lv = locals[i];
      if (i >= first_local_index) {
        if (lv.getStart().getPosition() != 0) {
          if (new_offset == -1) {
            if (compiler_temp_i != -1) {
              new_offset = locals[compiler_temp_i].getIndex();
              new_index = compiler_temp_i;
            } else {
              new_offset = lv.getIndex();
              new_index = i;
            }
          }
        }
      }

      // calculate max local size seen so far (+1)
      max_offset = lv.getIndex() + lv.getType().getSize();

      if (lv.getName().startsWith("DaIkOnTeMp")) {
        // Remember the index of a compiler temp.  We may wish
        // to insert our new local prior to a temp to simplfy
        // the generation of StackMaps.
        if (compiler_temp_i == -1) {
          compiler_temp_i = i;
        }
      } else {
        // If there were compiler temps prior to this local, we don't
        // need to worry about them as the compiler will have already
        // included them in the StackMaps. Reset the indicators.
        compiler_temp_i = -1;
      }
    }

    // We have looked at all the local variables; if we have not found
    // a place for our new local, check to see if last local was a
    // compiler temp and insert prior.
    if ((new_offset == -1) && (compiler_temp_i != -1)) {
      new_offset = locals[compiler_temp_i].getIndex();
      new_index = compiler_temp_i;
    }

    // If new_offset is still unset, we can just add our local at the
    // end.  There may be unnamed compiler temps here, so we need to
    // check for this (via max_offset) and move them up.
    if (new_offset == -1) {
      new_offset = max_offset;
      if (new_offset < mgen.getMaxLocals()) {
        mgen.setMaxLocals(mgen.getMaxLocals() + local_type.getSize());
      }
      lv_new = mgen.addLocalVariable(local_name, local_type, new_offset, null, null);
    } else {
      // insert our new local variable into existing table at 'new_offset'
      lv_new = mgen.addLocalVariable(local_name, local_type, new_offset, null, null);
      // we need to adjust the offset of any locals after our insertion
      for (i = new_index; i < locals.length; i++) {
        LocalVariableGen lv = locals[i];
        lv.setIndex(lv.getIndex() + local_type.getSize());
      }
      mgen.setMaxLocals(mgen.getMaxLocals() + local_type.getSize());
    }

    debug_instrument.log(
        "Added local  %s%n", lv_new.getIndex() + ": " + lv_new.getName() + ", " + lv_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, local_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, local_type, locals);

    debug_instrument.log("New LocalVariableTable:%n%s%n", mgen.getLocalVariableTable(pool));
    return lv_new;
  }
protected final LocalVariableGen create_method_scope_local(
      MethodGen mgen, String local_name, Type local_type) {
    // BCEL sorts local vars and presents them in offset order.  Search
    // locals for first var with start != 0. If none, just add the new
    // var at the end of the table and exit. Otherwise, insert the new
    // var just prior to the local we just found.
    // Now 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).
    //
    // We never want to insert our local prior to any parameters.  This would
    // happen naturally, but some old class files have non zero addresses
    // for 'this' and/or the parameters so we need to add an explicit
    // check to make sure we skip these variables.

    LocalVariableGen lv_new;
    int max_offset = 0;
    int new_offset = -1;
    // get a copy of the local before modification
    LocalVariableGen[] locals = mgen.getLocalVariables();
    @IndexOrLow("locals") int compiler_temp_i = -1;
    int new_index = -1;
    int i;

    for (i = 0; i < locals.length; i++) {
      LocalVariableGen lv = locals[i];
      if (i >= first_local_index) {
        if (lv.getStart().getPosition() != 0) {
          if (new_offset == -1) {
            if (compiler_temp_i != -1) {
              new_offset = locals[compiler_temp_i].getIndex();
              new_index = compiler_temp_i;
            } else {
              new_offset = lv.getIndex();
              new_index = i;
            }
          }
        }
      }

      // calculate max local size seen so far (+1)
      max_offset = lv.getIndex() + lv.getType().getSize();

      if (lv.getName().startsWith("DaIkOnTeMp")) {
        // Remember the index of a compiler temp.  We may wish
        // to insert our new local prior to a temp to simplfy
        // the generation of StackMaps.
        if (compiler_temp_i == -1) {
          compiler_temp_i = i;
        }
      } else {
        // If there were compiler temps prior to this local, we don't
        // need to worry about them as the compiler will have already
        // included them in the StackMaps. Reset the indicators.
        compiler_temp_i = -1;
      }
    }

    // We have looked at all the local variables; if we have not found
    // a place for our new local, check to see if last local was a
    // compiler temp and insert prior.
    if ((new_offset == -1) && (compiler_temp_i != -1)) {
      new_offset = locals[compiler_temp_i].getIndex();
      new_index = compiler_temp_i;
    }

    // If new_offset is still unset, we can just add our local at the
    // end.  There may be unnamed compiler temps here, so we need to
    // check for this (via max_offset) and move them up.
    if (new_offset == -1) {
      new_offset = max_offset;
      if (new_offset < mgen.getMaxLocals()) {
        mgen.setMaxLocals(mgen.getMaxLocals() + local_type.getSize());
      }
      lv_new = mgen.addLocalVariable(local_name, local_type, new_offset, null, null);
    } else {
      // insert our new local variable into existing table at 'new_offset'
      lv_new = mgen.addLocalVariable(local_name, local_type, new_offset, null, null);
      // we need to adjust the offset of any locals after our insertion
      for (i = new_index; i < locals.length; i++) {
        LocalVariableGen lv = locals[i];
        lv.setIndex(lv.getIndex() + local_type.getSize());
      }
      mgen.setMaxLocals(mgen.getMaxLocals() + local_type.getSize());
    }

    debug_instrument.log(
        "Added local  %s%n", lv_new.getIndex() + ": " + lv_new.getName() + ", " + lv_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, local_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, local_type, locals);

    debug_instrument.log("New LocalVariableTable:%n%s%n", mgen.getLocalVariableTable(pool));
    return lv_new;
  }
Create a new local with a scope of the full method. This means we need to search the existing
locals to find the proper index for our new local. This might have the side effect of causing
us to rewrite the method byte codes to adjust the offsets for the existing 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 local_name name of new local
@param local_type type of new local
@return a LocalVariableGen for the new local