src/main/java/org/plumelib/bcelutil/InstructionListUtils.java
protected final void insert_before_handle(
      MethodGen mg,
      InstructionHandle ih,
      @Nullable InstructionList new_il,
      boolean redirect_branches) {

    if (new_il == null) {
      return;
    }

    // Ignore methods with no instructions
    InstructionList il = mg.getInstructionList();
    if (il == null) {
      return;
    }

    boolean at_start = (ih.getPrev() == null);
    new_il.setPositions();
    InstructionHandle new_end = new_il.getEnd();
    int new_length = new_end.getPosition() + new_end.getInstruction().getLength();

    print_stack_map_table("Before insert_inst");
    debug_instrument.log("  insert_inst: %d%n%s%n", new_il.getLength(), new_il);

    // Add the new code in front of the instruction handle.
    InstructionHandle new_start = il.insert(ih, new_il);
    il.setPositions();

    if (redirect_branches) {
      // Move all of the branches from the old instruction to the new start.
      il.redirectBranches(ih, new_start);
    }

    // Move other targets to the new start.
    if (ih.hasTargeters()) {
      for (InstructionTargeter it : ih.getTargeters()) {
        if ((it instanceof LineNumberGen) && redirect_branches) {
          it.updateTarget(ih, new_start);
        } else if (it instanceof LocalVariableGen) {
          LocalVariableGen lvg = (LocalVariableGen) it;
          // If ih is end of local variable range, leave as is.
          // If ih is start of local variable range and we are
          // at the begining of the method go ahead and change
          // start to new_start.  This is to preserve live range
          // for variables that are live for entire method.
          if ((lvg.getStart() == ih) && at_start) {
            it.updateTarget(ih, new_start);
          }
        } else if ((it instanceof CodeExceptionGen) && redirect_branches) {
          CodeExceptionGen exc = (CodeExceptionGen) it;
          if (exc.getStartPC() == ih) exc.updateTarget(ih, new_start);
          // else if (exc.getEndPC() == ih) leave as is
          else if (exc.getHandlerPC() == ih) exc.setHandlerPC(new_start);
          else System.out.printf("Malformed CodeException: %s%n", exc);
        }
      }
    }

    // Need to update stack map for change in length of instruction bytes.
    // If redirect_branches is true then we don't want to change the
    // offset of a stack map that was on the original ih, we want it
    // to 'move' to the new_start.  If we did not redirect the branches
    // then we do want any stack map associated with the original ih
    // to stay there. The routine update_stack_map starts looking for
    // a stack map after the location given as its first argument.
    // Thus we need to subtract one from this location if the
    // redirect_branches flag is false.
    il.setPositions();
    update_stack_map_offset(new_start.getPosition() - (redirect_branches ? 0 : 1), new_length);

    print_il(new_start, "After update_stack_map_offset");

    // We need to see if inserting the additional instructions caused
    // a change in the amount of switch instruction padding bytes.
    modify_stack_maps_for_switches(new_start, il);
  }
protected final void insert_before_handle(
      MethodGen mg,
      InstructionHandle ih,
      @Nullable InstructionList new_il,
      boolean redirect_branches) {

    if (new_il == null) {
      return;
    }

    // Ignore methods with no instructions
    InstructionList il = mg.getInstructionList();
    if (il == null) {
      return;
    }

    boolean at_start = (ih.getPrev() == null);
    new_il.setPositions();
    InstructionHandle new_end = new_il.getEnd();
    int new_length = new_end.getPosition() + new_end.getInstruction().getLength();

    print_stack_map_table("Before insert_inst");
    debug_instrument.log("  insert_inst: %d%n%s%n", new_il.getLength(), new_il);

    // Add the new code in front of the instruction handle.
    InstructionHandle new_start = il.insert(ih, new_il);
    il.setPositions();

    if (redirect_branches) {
      // Move all of the branches from the old instruction to the new start.
      il.redirectBranches(ih, new_start);
    }

    // Move other targets to the new start.
    if (ih.hasTargeters()) {
      for (InstructionTargeter it : ih.getTargeters()) {
        if ((it instanceof LineNumberGen) && redirect_branches) {
          it.updateTarget(ih, new_start);
        } else if (it instanceof LocalVariableGen) {
          LocalVariableGen lvg = (LocalVariableGen) it;
          // If ih is end of local variable range, leave as is.
          // If ih is start of local variable range and we are
          // at the begining of the method go ahead and change
          // start to new_start.  This is to preserve live range
          // for variables that are live for entire method.
          if ((lvg.getStart() == ih) && at_start) {
            it.updateTarget(ih, new_start);
          }
        } else if ((it instanceof CodeExceptionGen) && redirect_branches) {
          CodeExceptionGen exc = (CodeExceptionGen) it;
          if (exc.getStartPC() == ih) exc.updateTarget(ih, new_start);
          // else if (exc.getEndPC() == ih) leave as is
          else if (exc.getHandlerPC() == ih) exc.setHandlerPC(new_start);
          else System.out.printf("Malformed CodeException: %s%n", exc);
        }
      }
    }

    // Need to update stack map for change in length of instruction bytes.
    // If redirect_branches is true then we don't want to change the
    // offset of a stack map that was on the original ih, we want it
    // to 'move' to the new_start.  If we did not redirect the branches
    // then we do want any stack map associated with the original ih
    // to stay there. The routine update_stack_map starts looking for
    // a stack map after the location given as its first argument.
    // Thus we need to subtract one from this location if the
    // redirect_branches flag is false.
    il.setPositions();
    update_stack_map_offset(new_start.getPosition() - (redirect_branches ? 0 : 1), new_length);

    print_il(new_start, "After update_stack_map_offset");

    // We need to see if inserting the additional instructions caused
    // a change in the amount of switch instruction padding bytes.
    modify_stack_maps_for_switches(new_start, il);
  }
Inserts a new instruction list into an existing instruction list just prior to the indicated
instruction handle (which must be a member of the existing instruction list). If new_il is
null, do nothing.

@param mg MethodGen containing the instruction handle
@param ih InstructionHandle indicating where to insert new code
@param new_il InstructionList holding the new code
@param redirect_branches flag indicating if branch targets should be moved from ih to new_il