src/main/java/org/plumelib/bcelutil/StackMapUtils.java
protected final int gen_temp_locals(MethodGen mgen, int offset) {
    int live_start = 0;
    Type live_type = null;
    InstructionList il = mgen.getInstructionList();
    il.setPositions();

    // Set up inital state of StackMap info on entry to method.
    int locals_offset_height = 0;
    int byte_code_offset = -1;
    LocalVariableGen new_lvg;
    int min_size = 3; // only sizes are 1 or 2; start with something larger.

    number_active_locals = initial_locals_count;
    StackMapType[] types_of_active_locals = new StackMapType[number_active_locals];
    for (int ii = 0; ii < number_active_locals; ii++) {
      types_of_active_locals[ii] = initial_type_list[ii];
      locals_offset_height += getSize(initial_type_list[ii]);
    }

    // update state for each StackMap entry
    for (StackMapEntry smte : stack_map_table) {
      int frame_type = smte.getFrameType();
      byte_code_offset += smte.getByteCodeOffset() + 1;

      if (frame_type >= Const.APPEND_FRAME && frame_type <= Const.APPEND_FRAME_MAX) {
        // number to append is frame_type - 251
        types_of_active_locals =
            Arrays.copyOf(types_of_active_locals, number_active_locals + frame_type - 251);
        for (StackMapType smt : smte.getTypesOfLocals()) {
          types_of_active_locals[number_active_locals++] = smt;
          locals_offset_height += getSize(smt);
        }
      } else if (frame_type >= Const.CHOP_FRAME && frame_type <= Const.CHOP_FRAME_MAX) {
        int number_to_chop = 251 - frame_type;
        while (number_to_chop > 0) {
          locals_offset_height -= getSize(types_of_active_locals[--number_active_locals]);
          number_to_chop--;
        }
        types_of_active_locals = Arrays.copyOf(types_of_active_locals, number_active_locals);
      } else if (frame_type == Const.FULL_FRAME) {
        locals_offset_height = 0;
        number_active_locals = 0;
        types_of_active_locals = new StackMapType[smte.getNumberOfLocals()];
        for (StackMapType smt : smte.getTypesOfLocals()) {
          types_of_active_locals[number_active_locals++] = smt;
          locals_offset_height += getSize(smt);
        }
      }
      // all other frame_types do not modify locals.

      // System.out.printf("byte_code_offset: %d, temp offset: %d, locals_offset_height: %d,
      // number_active_locals: %d, local types: %s%n",
      //       byte_code_offset, offset, locals_offset_height, number_active_locals,
      // Arrays.toString(types_of_active_locals));

      if (live_start == 0) {
        // did the latest StackMap entry define the temp in question?
        if (offset < locals_offset_height) {
          live_start = byte_code_offset;
          int running_offset = 0;
          for (StackMapType smt : types_of_active_locals) {
            if (running_offset == offset) {
              live_type = generate_Type_from_StackMapType(smt);
              break;
            }
            running_offset += getSize(smt);
          }
          if (live_type == null) {
            // No matching offset in stack maps so this offset must be
            // second half of long or double. Just skip to next stack map.
            live_start = 0;
          }
        }
      } else {
        // did the latest StackMap entry undefine the temp in question?
        if (offset >= locals_offset_height) {
          // create the temp variable
          new_lvg =
              mgen.addLocalVariable(
                  "DaIkOnTeMp" + offset,
                  live_type,
                  offset,
                  il.findHandle(live_start),
                  il.findHandle(byte_code_offset));
          debug_instrument.log(
              "Added local  %s, %d, %d : %s, %s%n",
              new_lvg.getIndex(),
              new_lvg.getStart().getPosition(),
              new_lvg.getEnd().getPosition(),
              new_lvg.getName(),
              new_lvg.getType());
          min_size = Math.min(min_size, live_type.getSize());
          // reset to look for more temps at same offset
          live_start = 0;
          live_type = null;
        }
      }
      // go on to next StackMap entry
    }
    // we are done with stack maps; need to see if any temps still active
    if (live_start != 0) {
      // live range is to end of method; create the temp variable
      new_lvg =
          mgen.addLocalVariable(
              "DaIkOnTeMp" + offset, live_type, offset, il.findHandle(live_start), null);
      debug_instrument.log(
          "Added local  %s, %d, %d : %s, %s%n",
          new_lvg.getIndex(),
          new_lvg.getStart().getPosition(),
          il.getEnd().getPosition(),
          new_lvg.getName(),
          new_lvg.getType());
      min_size = Math.min(min_size, live_type.getSize());
    } else {
      if (min_size == 3) {
        // did not find a temp in any of the stack maps; that must mean the
        // temp live range is in between two stack maps or after last stack map
        // need to scan all byte codes to get live range and type
        // HACK: for now, just make a guess and put it after last stack map
        // Note we may be defining a bogus temp for second half of long or double.
        if (byte_code_offset == -1) {
          // no stack maps at all, set start to 0
          byte_code_offset = 0;
        }
        new_lvg =
            mgen.addLocalVariable(
                "DaIkOnTeMp" + offset, Type.OBJECT, offset, il.findHandle(byte_code_offset), null);
        debug_instrument.log(
            "Added local  %s, %d, %d : %s, %s%n",
            new_lvg.getIndex(),
            new_lvg.getStart().getPosition(),
            il.getEnd().getPosition(),
            new_lvg.getName(),
            new_lvg.getType());
        min_size = Math.min(min_size, Type.OBJECT.getSize());
      }
    }
    return offset + min_size;
  }
protected final int gen_temp_locals(MethodGen mgen, int offset) {
    int live_start = 0;
    Type live_type = null;
    InstructionList il = mgen.getInstructionList();
    il.setPositions();

    // Set up inital state of StackMap info on entry to method.
    int locals_offset_height = 0;
    int byte_code_offset = -1;
    LocalVariableGen new_lvg;
    int min_size = 3; // only sizes are 1 or 2; start with something larger.

    number_active_locals = initial_locals_count;
    StackMapType[] types_of_active_locals = new StackMapType[number_active_locals];
    for (int ii = 0; ii < number_active_locals; ii++) {
      types_of_active_locals[ii] = initial_type_list[ii];
      locals_offset_height += getSize(initial_type_list[ii]);
    }

    // update state for each StackMap entry
    for (StackMapEntry smte : stack_map_table) {
      int frame_type = smte.getFrameType();
      byte_code_offset += smte.getByteCodeOffset() + 1;

      if (frame_type >= Const.APPEND_FRAME && frame_type <= Const.APPEND_FRAME_MAX) {
        // number to append is frame_type - 251
        types_of_active_locals =
            Arrays.copyOf(types_of_active_locals, number_active_locals + frame_type - 251);
        for (StackMapType smt : smte.getTypesOfLocals()) {
          types_of_active_locals[number_active_locals++] = smt;
          locals_offset_height += getSize(smt);
        }
      } else if (frame_type >= Const.CHOP_FRAME && frame_type <= Const.CHOP_FRAME_MAX) {
        int number_to_chop = 251 - frame_type;
        while (number_to_chop > 0) {
          locals_offset_height -= getSize(types_of_active_locals[--number_active_locals]);
          number_to_chop--;
        }
        types_of_active_locals = Arrays.copyOf(types_of_active_locals, number_active_locals);
      } else if (frame_type == Const.FULL_FRAME) {
        locals_offset_height = 0;
        number_active_locals = 0;
        types_of_active_locals = new StackMapType[smte.getNumberOfLocals()];
        for (StackMapType smt : smte.getTypesOfLocals()) {
          types_of_active_locals[number_active_locals++] = smt;
          locals_offset_height += getSize(smt);
        }
      }
      // all other frame_types do not modify locals.

      // System.out.printf("byte_code_offset: %d, temp offset: %d, locals_offset_height: %d,
      // number_active_locals: %d, local types: %s%n",
      //       byte_code_offset, offset, locals_offset_height, number_active_locals,
      // Arrays.toString(types_of_active_locals));

      if (live_start == 0) {
        // did the latest StackMap entry define the temp in question?
        if (offset < locals_offset_height) {
          live_start = byte_code_offset;
          int running_offset = 0;
          for (StackMapType smt : types_of_active_locals) {
            if (running_offset == offset) {
              live_type = generate_Type_from_StackMapType(smt);
              break;
            }
            running_offset += getSize(smt);
          }
          if (live_type == null) {
            // No matching offset in stack maps so this offset must be
            // second half of long or double. Just skip to next stack map.
            live_start = 0;
          }
        }
      } else {
        // did the latest StackMap entry undefine the temp in question?
        if (offset >= locals_offset_height) {
          // create the temp variable
          new_lvg =
              mgen.addLocalVariable(
                  "DaIkOnTeMp" + offset,
                  live_type,
                  offset,
                  il.findHandle(live_start),
                  il.findHandle(byte_code_offset));
          debug_instrument.log(
              "Added local  %s, %d, %d : %s, %s%n",
              new_lvg.getIndex(),
              new_lvg.getStart().getPosition(),
              new_lvg.getEnd().getPosition(),
              new_lvg.getName(),
              new_lvg.getType());
          min_size = Math.min(min_size, live_type.getSize());
          // reset to look for more temps at same offset
          live_start = 0;
          live_type = null;
        }
      }
      // go on to next StackMap entry
    }
    // we are done with stack maps; need to see if any temps still active
    if (live_start != 0) {
      // live range is to end of method; create the temp variable
      new_lvg =
          mgen.addLocalVariable(
              "DaIkOnTeMp" + offset, live_type, offset, il.findHandle(live_start), null);
      debug_instrument.log(
          "Added local  %s, %d, %d : %s, %s%n",
          new_lvg.getIndex(),
          new_lvg.getStart().getPosition(),
          il.getEnd().getPosition(),
          new_lvg.getName(),
          new_lvg.getType());
      min_size = Math.min(min_size, live_type.getSize());
    } else {
      if (min_size == 3) {
        // did not find a temp in any of the stack maps; that must mean the
        // temp live range is in between two stack maps or after last stack map
        // need to scan all byte codes to get live range and type
        // HACK: for now, just make a guess and put it after last stack map
        // Note we may be defining a bogus temp for second half of long or double.
        if (byte_code_offset == -1) {
          // no stack maps at all, set start to 0
          byte_code_offset = 0;
        }
        new_lvg =
            mgen.addLocalVariable(
                "DaIkOnTeMp" + offset, Type.OBJECT, offset, il.findHandle(byte_code_offset), null);
        debug_instrument.log(
            "Added local  %s, %d, %d : %s, %s%n",
            new_lvg.getIndex(),
            new_lvg.getStart().getPosition(),
            il.getEnd().getPosition(),
            new_lvg.getName(),
            new_lvg.getType());
        min_size = Math.min(min_size, Type.OBJECT.getSize());
      }
    }
    return offset + min_size;
  }
Find the live range of the compiler temp(s) at the given offset and create a LocalVariableGen
for each. Note the compiler might generate temps of different sizes at the same offset (must
have disjoint lifetimes).

@param mgen the method
@param offset compiler assigned local offset of hidden temp
@return offset incremented by size of smallest temp found at offset