in src/main/java/org/apache/bcel/generic/InstructionList.java [1079:1153]
public void setPositions(final boolean check) { // called by code in other packages
int maxAdditionalBytes = 0;
int additionalBytes = 0;
int index = 0;
int count = 0;
final int[] pos = new int[length];
/*
* Pass 0: Sanity checks
*/
if (check) {
for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
final Instruction i = ih.getInstruction();
if (i instanceof BranchInstruction) { // target instruction within list?
Instruction inst = ((BranchInstruction) i).getTarget().getInstruction();
if (!contains(inst)) {
throw new ClassGenException("Branch target of " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not in instruction list");
}
if (i instanceof Select) {
final InstructionHandle[] targets = ((Select) i).getTargets();
for (final InstructionHandle target : targets) {
inst = target.getInstruction();
if (!contains(inst)) {
throw new ClassGenException("Branch target of " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not in instruction list");
}
}
}
if (!(ih instanceof BranchHandle)) {
throw new ClassGenException(
"Branch instruction " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not contained in BranchHandle.");
}
}
}
}
/*
* Pass 1: Set position numbers and sum up the maximum number of bytes an instruction may be shifted.
*/
for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
final Instruction i = ih.getInstruction();
ih.setPosition(index);
pos[count++] = index;
/*
* Get an estimate about how many additional bytes may be added, because BranchInstructions may have variable length
* depending on the target offset (short vs. int) or alignment issues (TABLESWITCH and LOOKUPSWITCH).
*/
switch (i.getOpcode()) {
case Const.JSR:
case Const.GOTO:
maxAdditionalBytes += 2;
break;
case Const.TABLESWITCH:
case Const.LOOKUPSWITCH:
maxAdditionalBytes += 3;
break;
}
index += i.getLength();
}
/*
* Pass 2: Expand the variable-length (Branch)Instructions depending on the target offset (short or int) and ensure that
* branch targets are within this list.
*/
for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
additionalBytes += ih.updatePosition(additionalBytes, maxAdditionalBytes);
}
/*
* Pass 3: Update position numbers (which may have changed due to the preceding expansions), like pass 1.
*/
index = count = 0;
for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
final Instruction i = ih.getInstruction();
ih.setPosition(index);
pos[count++] = index;
index += i.getLength();
}
bytePositions = Arrays.copyOfRange(pos, 0, count); // Trim to proper size
}