| 282 | } |
| 283 | |
| 284 | private void findSubroutine(int insn, final Subroutine sub, final List<AbstractInsnNode> calls) throws AnalyzerException { |
| 285 | while (true) { |
| 286 | if (insn < 0 || insn >= n) { |
| 287 | throw new AnalyzerException(null, "Execution can fall off end of the code"); |
| 288 | } |
| 289 | if (subroutines[insn] != null) { |
| 290 | return; |
| 291 | } |
| 292 | subroutines[insn] = sub.copy(); |
| 293 | AbstractInsnNode node = insns.get(insn); |
| 294 | |
| 295 | // calls findSubroutine recursively on normal successors |
| 296 | if (node instanceof JumpInsnNode) { |
| 297 | if (node.getOpcode() == JSR) { |
| 298 | // do not follow a JSR, it leads to another subroutine! |
| 299 | calls.add(node); |
| 300 | } else { |
| 301 | JumpInsnNode jnode = (JumpInsnNode) node; |
| 302 | findSubroutine(insns.indexOf(jnode.label), sub, calls); |
| 303 | } |
| 304 | } else if (node instanceof TableSwitchInsnNode) { |
| 305 | TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node; |
| 306 | findSubroutine(insns.indexOf(tsnode.dflt), sub, calls); |
| 307 | for (int i = tsnode.labels.size() - 1; i >= 0; --i) { |
| 308 | LabelNode l = tsnode.labels.get(i); |
| 309 | findSubroutine(insns.indexOf(l), sub, calls); |
| 310 | } |
| 311 | } else if (node instanceof LookupSwitchInsnNode) { |
| 312 | LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node; |
| 313 | findSubroutine(insns.indexOf(lsnode.dflt), sub, calls); |
| 314 | for (int i = lsnode.labels.size() - 1; i >= 0; --i) { |
| 315 | LabelNode l = lsnode.labels.get(i); |
| 316 | findSubroutine(insns.indexOf(l), sub, calls); |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | // calls findSubroutine recursively on exception handler successors |
| 321 | List<TryCatchBlockNode> insnHandlers = handlers[insn]; |
| 322 | if (insnHandlers != null) { |
| 323 | for (int i = 0; i < insnHandlers.size(); ++i) { |
| 324 | TryCatchBlockNode tcb = insnHandlers.get(i); |
| 325 | findSubroutine(insns.indexOf(tcb.handler), sub, calls); |
| 326 | } |
| 327 | } |
| 328 | |
| 329 | // if insn does not falls through to the next instruction, return. |
| 330 | switch (node.getOpcode()) { |
| 331 | case GOTO: |
| 332 | case RET: |
| 333 | case TABLESWITCH: |
| 334 | case LOOKUPSWITCH: |
| 335 | case IRETURN: |
| 336 | case LRETURN: |
| 337 | case FRETURN: |
| 338 | case DRETURN: |
| 339 | case ARETURN: |
| 340 | case RETURN: |
| 341 | case ATHROW: |