private void processExcHandler(ExceptionHandler handler, Set<BlockNode> exits) { BlockNode start = handler.getHandlerBlock(); if (start == null) { return; } RegionStack stack = new RegionStack(mth); BlockNode dom; if (handler.isFinally()) { SplitterBlockAttr splitterAttr = start.get(AType.SPLITTER_BLOCK); if (splitterAttr == null) { return; } dom = splitterAttr.getBlock(); } else { dom = start; stack.addExits(exits); } BitSet domFrontier = dom.getDomFrontier(); List<BlockNode> handlerExits = BlockUtils.bitSetToBlocks(mth, domFrontier); boolean inLoop = mth.getLoopForBlock(start) != null; for (BlockNode exit : handlerExits) { if ((!inLoop || BlockUtils.isPathExists(start, exit)) && RegionUtils.isRegionContainsBlock(mth.getRegion(), exit)) { stack.addExit(exit); } } handler.setHandlerRegion(makeRegion(start, stack)); ExcHandlerAttr excHandlerAttr = start.get(AType.EXC_HANDLER); if (excHandlerAttr == null) { LOG.warn("Missing exception handler attribute for start block"); } else { handler.getHandlerRegion().addAttr(excHandlerAttr); } }
private BlockNode makeEndlessLoop( IRegion curRegion, RegionStack stack, LoopInfo loop, BlockNode loopStart) { LoopRegion loopRegion = new LoopRegion(curRegion, loop, null, false); curRegion.getSubBlocks().add(loopRegion); loopStart.remove(AType.LOOP); stack.push(loopRegion); BlockNode loopExit = null; // insert 'break' for exits List<Edge> exitEdges = loop.getExitEdges(); for (Edge exitEdge : exitEdges) { BlockNode exit = exitEdge.getTarget(); if (insertBreak(stack, exit, exitEdge)) { BlockNode nextBlock = getNextBlock(exit); if (nextBlock != null) { stack.addExit(nextBlock); loopExit = nextBlock; } } } Region body = makeRegion(loopStart, stack); BlockNode loopEnd = loop.getEnd(); if (!RegionUtils.isRegionContainsBlock(body, loopEnd) && !loopEnd.contains(AType.EXC_HANDLER) && !inExceptionHandlerBlocks(loopEnd)) { body.getSubBlocks().add(loopEnd); } loopRegion.setBody(body); if (loopExit == null) { BlockNode next = getNextBlock(loopEnd); loopExit = RegionUtils.isRegionContainsBlock(body, next) ? null : next; } stack.pop(); loopStart.addAttr(AType.LOOP, loop); return loopExit; }
private BlockNode processLoop(IRegion curRegion, LoopInfo loop, RegionStack stack) { BlockNode loopStart = loop.getStart(); Set<BlockNode> exitBlocksSet = loop.getExitNodes(); // set exit blocks scan order priority // this can help if loop have several exits (after using 'break' or 'return' in loop) List<BlockNode> exitBlocks = new ArrayList<BlockNode>(exitBlocksSet.size()); BlockNode nextStart = getNextBlock(loopStart); if (nextStart != null && exitBlocksSet.remove(nextStart)) { exitBlocks.add(nextStart); } if (exitBlocksSet.remove(loopStart)) { exitBlocks.add(loopStart); } if (exitBlocksSet.remove(loop.getEnd())) { exitBlocks.add(loop.getEnd()); } exitBlocks.addAll(exitBlocksSet); LoopRegion loopRegion = makeLoopRegion(curRegion, loop, exitBlocks); if (loopRegion == null) { BlockNode exit = makeEndlessLoop(curRegion, stack, loop, loopStart); insertContinue(loop); return exit; } curRegion.getSubBlocks().add(loopRegion); IRegion outerRegion = stack.peekRegion(); stack.push(loopRegion); IfInfo condInfo = makeIfInfo(loopRegion.getHeader()); condInfo = searchNestedIf(condInfo); confirmMerge(condInfo); if (!loop.getLoopBlocks().contains(condInfo.getThenBlock())) { // invert loop condition if 'then' points to exit condInfo = IfInfo.invert(condInfo); } loopRegion.setCondition(condInfo.getCondition()); exitBlocks.removeAll(condInfo.getMergedBlocks()); if (!exitBlocks.isEmpty()) { BlockNode loopExit = condInfo.getElseBlock(); if (loopExit != null) { // add 'break' instruction before path cross between main loop exit and sub-exit for (Edge exitEdge : loop.getExitEdges()) { if (!exitBlocks.contains(exitEdge.getSource())) { continue; } insertBreak(stack, loopExit, exitEdge); } } } BlockNode out; if (loopRegion.isConditionAtEnd()) { BlockNode thenBlock = condInfo.getThenBlock(); out = thenBlock == loopStart ? condInfo.getElseBlock() : thenBlock; loopStart.remove(AType.LOOP); loop.getEnd().add(AFlag.SKIP); stack.addExit(loop.getEnd()); loopRegion.setBody(makeRegion(loopStart, stack)); loopStart.addAttr(AType.LOOP, loop); loop.getEnd().remove(AFlag.SKIP); } else { out = condInfo.getElseBlock(); if (outerRegion != null && out.contains(AFlag.LOOP_START) && !out.getAll(AType.LOOP).contains(loop) && RegionUtils.isRegionContainsBlock(outerRegion, out)) { // exit to already processed outer loop out = null; } stack.addExit(out); BlockNode loopBody = condInfo.getThenBlock(); Region body = makeRegion(loopBody, stack); // add blocks from loop start to first condition block BlockNode conditionBlock = condInfo.getIfBlock(); if (loopStart != conditionBlock) { Set<BlockNode> blocks = BlockUtils.getAllPathsBlocks(loopStart, conditionBlock); blocks.remove(conditionBlock); for (BlockNode block : blocks) { if (block.getInstructions().isEmpty() && !block.contains(AFlag.SKIP) && !RegionUtils.isRegionContainsBlock(body, block)) { body.add(block); } } } loopRegion.setBody(body); } stack.pop(); insertContinue(loop); return out; }