in asm-commons/src/main/java/org/objectweb/asm/commons/JSRInlinerAdapter.java [232:296]
private void findReachableInsns(
final int insnIndex, final BitSet subroutineInsns, final BitSet visitedInsns) {
int currentInsnIndex = insnIndex;
// We implicitly assume below that execution can always fall through to the next instruction
// after a JSR. But a subroutine may never return, in which case the code after the JSR is
// unreachable and can be anything. In particular, it can seem to fall off the end of the
// method, so we must handle this case here (we could instead detect whether execution can
// return or not from a JSR, but this is more complicated).
while (currentInsnIndex < instructions.size()) {
// Visit each instruction at most once.
if (subroutineInsns.get(currentInsnIndex)) {
return;
}
subroutineInsns.set(currentInsnIndex);
// Check if this instruction has already been visited by another subroutine.
if (visitedInsns.get(currentInsnIndex)) {
sharedSubroutineInsns.set(currentInsnIndex);
}
visitedInsns.set(currentInsnIndex);
AbstractInsnNode currentInsnNode = instructions.get(currentInsnIndex);
if (currentInsnNode.getType() == AbstractInsnNode.JUMP_INSN
&& currentInsnNode.getOpcode() != JSR) {
// Don't follow JSR instructions in the control flow graph.
JumpInsnNode jumpInsnNode = (JumpInsnNode) currentInsnNode;
findReachableInsns(instructions.indexOf(jumpInsnNode.label), subroutineInsns, visitedInsns);
} else if (currentInsnNode.getType() == AbstractInsnNode.TABLESWITCH_INSN) {
TableSwitchInsnNode tableSwitchInsnNode = (TableSwitchInsnNode) currentInsnNode;
findReachableInsns(
instructions.indexOf(tableSwitchInsnNode.dflt), subroutineInsns, visitedInsns);
for (LabelNode labelNode : tableSwitchInsnNode.labels) {
findReachableInsns(instructions.indexOf(labelNode), subroutineInsns, visitedInsns);
}
} else if (currentInsnNode.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) {
LookupSwitchInsnNode lookupSwitchInsnNode = (LookupSwitchInsnNode) currentInsnNode;
findReachableInsns(
instructions.indexOf(lookupSwitchInsnNode.dflt), subroutineInsns, visitedInsns);
for (LabelNode labelNode : lookupSwitchInsnNode.labels) {
findReachableInsns(instructions.indexOf(labelNode), subroutineInsns, visitedInsns);
}
}
// Check if this instruction falls through to the next instruction; if not, return.
switch (instructions.get(currentInsnIndex).getOpcode()) {
case GOTO:
case RET:
case TABLESWITCH:
case LOOKUPSWITCH:
case IRETURN:
case LRETURN:
case FRETURN:
case DRETURN:
case ARETURN:
case RETURN:
case ATHROW:
// Note: this either returns from this subroutine, or from a parent subroutine.
return;
default:
// Go to the next instruction.
currentInsnIndex++;
break;
}
}
}