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;
  }
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
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 ) .