private BlockNode processMonitorEnter( IRegion curRegion, BlockNode block, InsnNode insn, RegionStack stack) { SynchronizedRegion synchRegion = new SynchronizedRegion(curRegion, insn); synchRegion.getSubBlocks().add(block); curRegion.getSubBlocks().add(synchRegion); Set<BlockNode> exits = new HashSet<BlockNode>(); cacheSet.clear(); traverseMonitorExits(synchRegion, insn.getArg(0), block, exits, cacheSet); for (InsnNode exitInsn : synchRegion.getExitInsns()) { InstructionRemover.unbindInsn(mth, exitInsn); } BlockNode body = getNextBlock(block); if (body == null) { ErrorsCounter.methodError(mth, "Unexpected end of synchronized block"); return null; } BlockNode exit; if (exits.size() == 1) { exit = getNextBlock(exits.iterator().next()); } else { cacheSet.clear(); exit = traverseMonitorExitsCross(body, exits, cacheSet); } stack.push(synchRegion); stack.addExit(exit); synchRegion.getSubBlocks().add(makeRegion(body, stack)); stack.pop(); return exit; }
/** Traverse from monitor-enter thru successors and collect blocks contains monitor-exit */ private static void traverseMonitorExits( SynchronizedRegion region, InsnArg arg, BlockNode block, Set<BlockNode> exits, Set<BlockNode> visited) { visited.add(block); for (InsnNode insn : block.getInstructions()) { if (insn.getType() == InsnType.MONITOR_EXIT && insn.getArg(0).equals(arg)) { exits.add(block); region.getExitInsns().add(insn); return; } } for (BlockNode node : block.getSuccessors()) { if (!visited.contains(node)) { traverseMonitorExits(region, arg, node, exits, visited); } } }