final List<ExceptionHandler> handlers = new ArrayList<>();
final Map<ExceptionTableEntry, ControlFlowNode> handlerStartNodes = new IdentityHashMap<>();
for (final ExceptionTableEntry entry : builder._tableEntries) {
final Instruction handlerStart = instructions.atOffset(entry.getHandlerOffset());
final ControlFlowNode handlerStartNode = builder.findNode(handlerStart);
if (handlerStartNode == null) {
throw new IllegalStateException(
format(
"Could not find entry node for handler at offset %d.",
handlerStart.getOffset()
)
);
}
if (handlerStartNode.getIncoming().isEmpty()) {
builder.createEdge(cfg.getEntryPoint(), handlerStartNode, JumpType.Normal);
}
handlerStartNodes.put(entry, handlerStartNode);
}
cfg.computeDominance();
cfg.computeDominanceFrontier();
for (final ExceptionTableEntry entry : builder._tableEntries) {
final ControlFlowNode handlerStart = handlerStartNodes.get(entry);
final List<ControlFlowNode> dominatedNodes = new ArrayList<>();
for (final ControlFlowNode node : findDominatedNodes(cfg, handlerStart)) {
if (node.getNodeType() == ControlFlowNodeType.Normal) {
dominatedNodes.add(node);
}
}
Collections.sort(
dominatedNodes,
new Comparator<ControlFlowNode>() {
@Override
public int compare(@NotNull final ControlFlowNode o1, @NotNull final ControlFlowNode o2) {
return Integer.compare(o1.getBlockIndex(), o2.getBlockIndex());
}
}
);
for (int i = 1; i < dominatedNodes.size(); i++) {
final ControlFlowNode prev = dominatedNodes.get(i - 1);
final ControlFlowNode node = dominatedNodes.get(i);
if (node.getBlockIndex() != prev.getBlockIndex() + 1) {
for (int j = i; j < dominatedNodes.size(); j++) {
dominatedNodes.remove(i);
break;
}
}
}
final Instruction lastInstruction = instructions.get(instructions.size() - 1);
final InstructionBlock tryBlock;
if (entry.getEndOffset() == lastInstruction.getEndOffset()) {
tryBlock = new InstructionBlock(
instructions.atOffset(entry.getStartOffset()),
lastInstruction
);
}