private void findReachableInsns()

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