Area (ControlFlowGraph graph, BasicBlock startSample, Set<BasicBlock> catchBlocks, BasicBlock startCatch, int finallyType, Map<BasicBlock, Boolean> mapLast, boolean skippedFirst) { class BlockStackEntry { public final BasicBlock blockCatch; public final BasicBlock blockSample; // TODO: correct handling (merging) of multiple paths public final List<int[]> lstStoreVars; BlockStackEntry(BasicBlock blockCatch, BasicBlock blockSample, List<int[]> lstStoreVars) { this.blockCatch = blockCatch; this.blockSample = blockSample; this.lstStoreVars = new ArrayList<>(lstStoreVars); } } List<BlockStackEntry> stack = new LinkedList<>(); Set<BasicBlock> setSample = new HashSet<>(); Map<String, BasicBlock[]> mapNext = new HashMap<>(); stack.add(new BlockStackEntry(startCatch, startSample, new ArrayList<>())); while (!stack.isEmpty()) { BlockStackEntry entry = stack.remove(0); BasicBlock blockCatch = entry.blockCatch; BasicBlock blockSample = entry.blockSample; boolean isFirstBlock = !skippedFirst && blockCatch == startCatch; boolean isLastBlock = mapLast.containsKey(blockCatch); boolean isTrueLastBlock = isLastBlock && mapLast.get(blockCatch); int compareType = (isFirstBlock ? 1 : 0) | (isTrueLastBlock ? 2 : 0); if (!compareBasicBlocksEx(graph, blockCatch, blockSample, compareType, finallyType, entry.lstStoreVars)) { return null; } if (blockSample.getSuccessors().size() != blockCatch.getSuccessors().size()) { return null; } setSample.add(blockSample); // direct successors for (int i = 0; i < blockCatch.getSuccessors().size(); i++) { BasicBlock sucCatch = blockCatch.getSuccessors().get(i); BasicBlock sucSample = blockSample.getSuccessors().get(i); if (catchBlocks.contains(sucCatch) && !setSample.contains(sucSample)) { stack.add(new BlockStackEntry(sucCatch, sucSample, entry.lstStoreVars)); } } // exception successors if (isLastBlock && blockSample.getSeq().isEmpty()) { // do nothing, blockSample will be removed anyway } else { if (blockCatch.getSuccessorExceptions().size() == blockSample.getSuccessorExceptions().size()) { for (int i = 0; i < blockCatch.getSuccessorExceptions().size(); i++) { BasicBlock sucCatch = blockCatch.getSuccessorExceptions().get(i); BasicBlock sucSample = blockSample.getSuccessorExceptions().get(i); String excCatch = graph.getExceptionRange(sucCatch, blockCatch).getUniqueExceptionsString(); String excSample = graph.getExceptionRange(sucSample, blockSample).getUniqueExceptionsString(); // FIXME: compare handlers if possible if (Objects.equals(excCatch, excSample)) { if (catchBlocks.contains(sucCatch) && !setSample.contains(sucSample)) { List<int[]> lst = entry.lstStoreVars; if (sucCatch.getSeq().length() > 0 && sucSample.getSeq().length() > 0) { Instruction instrCatch = sucCatch.getSeq().getInstr(0); Instruction instrSample = sucSample.getSeq().getInstr(0); if (instrCatch.opcode == CodeConstants.opc_astore && instrSample.opcode == CodeConstants.opc_astore) { lst = new ArrayList<>(lst); lst.add(new int[]{instrCatch.operand(0), instrSample.operand(0)}); } } stack.add(new BlockStackEntry(sucCatch, sucSample, lst)); } } else { return null; } } } else { return null; } } if (isLastBlock) { Set<BasicBlock> successors = new HashSet<>(blockSample.getSuccessors()); successors.removeAll(setSample); for (BlockStackEntry stackEntry : stack) { successors.remove(stackEntry.blockSample); } for (BasicBlock successor : successors) { if (graph.getLast() != successor) { // FIXME: why? mapNext.put(blockSample.id + "#" + successor.id, new BasicBlock[]{blockSample, successor, isTrueLastBlock ? successor : null}); } } } } return new Area(startSample, setSample, getUniqueNext(graph, new HashSet<>(mapNext.values()))); }