private void collectNodes(final ControlFlowNode node) { if (node == end || node == newEnd) { throw new IllegalStateException("Unexpected cycle involving finally constructs!"); } if (oldToNew.containsKey(node)) { return; } final int newBlockIndex = _nodes.size(); final ControlFlowNode copy; switch (node.getNodeType()) { case Normal: copy = new ControlFlowNode(newBlockIndex, node.getStart(), node.getEnd()); break; case FinallyHandler: copy = new ControlFlowNode(newBlockIndex, node.getExceptionHandler(), node.getEndFinallyNode()); break; default: throw ContractUtils.unsupported(); } copy.setCopyFrom(node); _nodes.add(copy); oldToNew.put(node, copy); if (node != start) { for (final ControlFlowNode predecessor : node.getPredecessors()) { collectNodes(predecessor); } } }
private static boolean hasSingleEdgeEnteringBlock(final ControlFlowNode node) { int count = 0; for (final ControlFlowEdge edge : node.getIncoming()) { if (!node.dominates(edge.getSource())) { if (++count > 1) { return false; } } } return count == 1; }
private static String nodeName(final ControlFlowNode node) { String name = "node" + node.getBlockIndex(); if (node.getNodeType() == ControlFlowNodeType.EndFinally) { name += "_ef"; } return name; }
@Override public void accept(final ControlFlowNode n) { final Set<ControlFlowNode> dominanceFrontier = n.getDominanceFrontier(); dominanceFrontier.clear(); for (final ControlFlowNode s : n.getSuccessors()) { if (s.getImmediateDominator() != n) { dominanceFrontier.add(s); } } for (final ControlFlowNode child : n.getDominatorTreeChildren()) { for (final ControlFlowNode p : child.getDominanceFrontier()) { if (p.getImmediateDominator() != n) { dominanceFrontier.add(p); } } } } }
private static boolean shouldIncludeExceptionalExit( final ControlFlowGraph cfg, final ControlFlowNode head, final ControlFlowNode node) { if (node.getNodeType() != ControlFlowNodeType.Normal) { return false; } if (!node.getDominanceFrontier().contains(cfg.getExceptionalExit()) && !node.dominates(cfg.getExceptionalExit())) { final ControlFlowNode innermostHandlerNode = findInnermostExceptionHandlerNode(cfg, node.getEnd().getOffset(), false); if (innermostHandlerNode == null || !node.getDominanceFrontier().contains(innermostHandlerNode)) { return false; } } return head.getNodeType() == ControlFlowNodeType.Normal && node.getNodeType() == ControlFlowNodeType.Normal && node.getStart().getNext() == node.getEnd() && head.getStart().getOpCode().isStore() && node.getStart().getOpCode().isLoad() && node.getEnd().getOpCode() == OpCode.ATHROW && InstructionHelper.getLoadOrStoreSlot(head.getStart()) == InstructionHelper.getLoadOrStoreSlot(node.getStart()); }
public SubroutineInfo(final ControlFlowNode entryNode, final List<ControlFlowNode> contents, final ControlFlowGraph cfg) { this.start = entryNode.getStart(); this.end = last(contents).getEnd(); this.entryNode = entryNode; this.contents = contents; this.cfg = cfg; for (final ControlFlowNode node : contents) { if (node.getNodeType() == ControlFlowNodeType.Normal && node.getEnd().getOpCode().isReturnFromSubroutine()) { this.exitNodes.add(node); } } } }
node.getDominanceFrontier().contains(node) && (node != entryPoint || !excludeEntryPoint)) { final BasicBlock basicBlock = (BasicBlock) node.getUserData(); final StrongBox<Expression> condition = new StrongBox<>(); final StrongBox<Label> trueLabel = new StrongBox<>(); final BasicBlock lastBlock = (BasicBlock) lastInLoop.getUserData(); if (node.dominates(n)) { loopContents.add(n); if (postLoopTarget.getIncoming().size() == 1) { final ControlFlowNode predecessor = firstOrDefault(postLoopTarget.getPredecessors()); final BasicBlock b = (BasicBlock) predecessor.getUserData(); if (scope.contains(n) && node.dominates(n)) { loopContents.add(n); if (n.getBlockIndex() < postLoopTarget.getBlockIndex() && scope.contains(n) && node.dominates(n)) { loopContents.add(n); final BasicBlock postLoopBlock = (BasicBlock) postLoopTarget.getUserData(); final Node postLoopBlockHead = firstOrDefault(postLoopBlock.getBody()); final ControlFlowNode predecessor = single(postLoopTarget.getPredecessors());
private void copyFinallyBlocksIntoLeaveEdges() { // // Step 5b: Copy finally blocks into the LeaveTry edges. // for (int n = _nodes.size(), i = n - 1; i >= 0; i--) { final ControlFlowNode node = _nodes.get(i); final Instruction end = node.getEnd(); if (end != null && node.getOutgoing().size() == 1 && node.getOutgoing().get(0).getType() == JumpType.LeaveTry) { assert end.getOpCode() == OpCode.GOTO || end.getOpCode() == OpCode.GOTO_W; final ControlFlowEdge edge = node.getOutgoing().get(0); final ControlFlowNode target = edge.getTarget(); target.getIncoming().remove(edge); node.getOutgoing().clear(); final ControlFlowNode handler = findInnermostExceptionHandlerNode(end.getEndOffset()); assert handler.getNodeType() == ControlFlowNodeType.FinallyHandler; final ControlFlowNode copy = copyFinallySubGraph(handler, handler.getEndFinallyNode(), target); createEdge(node, copy, JumpType.Normal); } } }
if (diveIntoHandlers && addNode.getExceptionHandler() != null) { addNode = findNode(cfg, addNode.getExceptionHandler().getHandlerBlock().getFirstInstruction()); else if (diveIntoHandlers && addNode.getNodeType() == ControlFlowNodeType.EndFinally) { agenda.addAll(addNode.getDominatorTreeChildren()); continue; if (addNode == null || addNode.getNodeType() != ControlFlowNodeType.Normal) { continue; if (!head.dominates(addNode) && !shouldIncludeExceptionalExit(cfg, head, addNode)) { for (final ControlFlowNode successor : addNode.getSuccessors()) { if (visited.add(successor)) { agenda.add(successor);
@Override public final void accept(final ControlFlowNode b) { if (b == entryPoint) { return; } ControlFlowNode newImmediateDominator = null; for (final ControlFlowNode p : b.getPredecessors()) { if (p.isVisited() && p != b) { newImmediateDominator = p; break; } } if (newImmediateDominator == null) { throw new IllegalStateException("Could not compute new immediate dominator!"); } for (final ControlFlowNode p : b.getPredecessors()) { if (p != b && p.getImmediateDominator() != null) { newImmediateDominator = findCommonDominator(p, newImmediateDominator); } } if (b.getImmediateDominator() != newImmediateDominator) { b.setImmediateDominator(newImmediateDominator); changed.set(true); } } }
public final void computeDominance(final BooleanBox cancelled) { final ControlFlowNode entryPoint = getEntryPoint(); entryPoint.setImmediateDominator(entryPoint); entryPoint.traversePreOrder( new Function<ControlFlowNode, Iterable<ControlFlowNode>>() { @Override entryPoint.setImmediateDominator(null); final ControlFlowNode immediateDominator = node.getImmediateDominator(); immediateDominator.getDominatorTreeChildren().add(node);
private ControlFlowNode findInnermostFinallyHandlerNode(final int offset) { final ExceptionHandler handler = findInnermostFinallyHandler(offset); if (handler == null) { return _exceptionalExit; } for (final ControlFlowNode node : _nodes) { if (node.getExceptionHandler() == handler && node.getCopyFrom() == null) { return node; } } throw new IllegalStateException("Could not find node for exception handler!"); }
final Instruction end = node.getEnd(); for (Instruction instruction = node.getStart(); instruction != null && instruction.getOffset() <= end.getOffset(); instruction = instruction.getNext()) { final ControlFlowNode handlerBlock = findInnermostFinallyBlock(end.getOffset()); if (handlerBlock.getEndFinallyNode() != null) { createEdge(node, handlerBlock.getEndFinallyNode(), JumpType.Normal); if (handlerBlock.getEndFinallyNode() == null) { handlerBlock = findInnermostFinallyHandlerNode( handlerBlock.getExceptionHandler().getTryBlock().getLastInstruction().getOffset() ); if (handlerBlock.getEndFinallyNode() != null) { createEdge(node, handlerBlock.getEndFinallyNode(), JumpType.LeaveTry);
escapeGraphViz(node.toString()) ); output.writeLine("];"); edges.addAll(node.getIncoming()); edges.addAll(node.getOutgoing()); final ControlFlowNode endFinallyNode = node.getEndFinallyNode(); escapeGraphViz(endFinallyNode.toString()) ); output.writeLine("];"); edges.addAll(endFinallyNode.getIncoming()); edges.addAll(endFinallyNode.getOutgoing());
private static Set<ControlFlowNode> findDominatedNodes(final Set<ControlFlowNode> scope, final ControlFlowNode head) { final Set<ControlFlowNode> agenda = new LinkedHashSet<>(); final Set<ControlFlowNode> result = new LinkedHashSet<>(); agenda.add(head); while (!agenda.isEmpty()) { final ControlFlowNode addNode = agenda.iterator().next(); agenda.remove(addNode); if (scope.contains(addNode) && head.dominates(addNode) && result.add(addNode)) { for (final ControlFlowNode successor : addNode.getSuccessors()) { agenda.add(successor); } } } return result; } }
final BasicBlock block = (BasicBlock) node.getUserData(); final List<Node> blockBody = block.getBody(); if (caseTarget.getDominanceFrontier().contains(defaultTarget)) { defaultFollowsSwitch = true; result.add((Node) node.getUserData()); scope.remove(node); final List<ControlFlowNode> dominatorTreeChildren = node.getDominatorTreeChildren(); result.add((Node) node.getUserData());
final ControlFlowNode node = new ControlFlowNode(_nodes.size(), blockStart, instructions.get(i)); node.setUserData(blockStartExceptionHandler); _nodes.add(new ControlFlowNode(index, handler, null));
@Override public boolean test(final ControlFlowNode node) { return node.getExceptionHandler() == other; } }
@Override public final String toString() { switch (_type) { case Normal: return "#" + _target.getBlockIndex(); case JumpToExceptionHandler: return "e:#" + _target.getBlockIndex(); default: return _type + ":#" + _target.getBlockIndex(); } } }
private ControlFlowGraphBuilder(final List<Instruction> instructions, final List<ExceptionHandler> exceptionHandlers) { _instructions = VerifyArgument.notNull(instructions, "instructions"); _exceptionHandlers = coalesceExceptionHandlers(VerifyArgument.notNull(exceptionHandlers, "exceptionHandlers")); _offsets = new int[instructions.size()]; _hasIncomingJumps = new boolean[_offsets.length]; for (int i = 0; i < instructions.size(); i++) { _offsets[i] = instructions.get(i).getOffset(); } _entryPoint = new ControlFlowNode(_nextBlockId++, 0, ControlFlowNodeType.EntryPoint); _regularExit = new ControlFlowNode(_nextBlockId++, -1, ControlFlowNodeType.RegularExit); _exceptionalExit = new ControlFlowNode(_nextBlockId++, -1, ControlFlowNodeType.ExceptionalExit); _nodes.add(_entryPoint); _nodes.add(_regularExit); _nodes.add(_exceptionalExit); }