private static void DeleteArea(ControlFlowGraph graph, FinallyProcessor.Area area ) { BasicBlock start = area.start; BasicBlock next = area.next; if (start == next) { return; } if (next == null) { // dummy exit block next = graph.GetLast(); } // collect common exception ranges of predecessors and successors HashSet <BasicBlock> setCommonExceptionHandlers = new HashSet <BasicBlock>(next.GetSuccExceptions ()); foreach (BasicBlock pred in start.GetPreds()) { setCommonExceptionHandlers.RetainAll(pred.GetSuccExceptions()); } bool is_outside_range = false; HashSet <BasicBlock> setPredecessors = new HashSet <BasicBlock>(start.GetPreds()); // replace start with next foreach (BasicBlock pred in setPredecessors) { pred.ReplaceSuccessor(start, next); } HashSet <BasicBlock> setBlocks = area.sample; HashSet <ExceptionRangeCFG> setCommonRemovedExceptionRanges = null; // remove all the blocks inbetween foreach (BasicBlock block in setBlocks) { // artificial basic blocks (those resulted from splitting) // can belong to more than one area if (graph.GetBlocks().ContainsKey(block.id)) { if (!block.GetSuccExceptions().ContainsAll(setCommonExceptionHandlers)) { is_outside_range = true; } HashSet <ExceptionRangeCFG> setRemovedExceptionRanges = new HashSet <ExceptionRangeCFG >(); foreach (BasicBlock handler in block.GetSuccExceptions()) { setRemovedExceptionRanges.Add(graph.GetExceptionRange(handler, block)); } if (setCommonRemovedExceptionRanges == null) { setCommonRemovedExceptionRanges = setRemovedExceptionRanges; } else { setCommonRemovedExceptionRanges.RetainAll(setRemovedExceptionRanges); } // shift extern edges on splitted blocks if (block.GetSeq().IsEmpty() && block.GetSuccs().Count == 1) { BasicBlock succs = block.GetSuccs()[0]; foreach (BasicBlock pred in new List <BasicBlock>(block.GetPreds())) { if (!setBlocks.Contains(pred)) { pred.ReplaceSuccessor(block, succs); } } if (graph.GetFirst() == block) { graph.SetFirst(succs); } } graph.RemoveBlock(block); } } if (is_outside_range) { // new empty block BasicBlock emptyblock = new BasicBlock(++graph.last_id); graph.GetBlocks().AddWithKey(emptyblock, emptyblock.id); // add to ranges if necessary foreach (ExceptionRangeCFG range in setCommonRemovedExceptionRanges) { emptyblock.AddSuccessorException(range.GetHandler()); range.GetProtectedRange().Add(emptyblock); } // insert between predecessors and next emptyblock.AddSuccessor(next); foreach (BasicBlock pred in setPredecessors) { pred.ReplaceSuccessor(next, emptyblock); } } }
private bool VerifyFinallyEx(ControlFlowGraph graph, CatchAllStatement fstat, FinallyProcessor.Record information) { HashSet <BasicBlock> tryBlocks = GetAllBasicBlocks(fstat.GetFirst()); HashSet <BasicBlock> catchBlocks = GetAllBasicBlocks(fstat.GetHandler()); int finallytype = information.firstCode; Dictionary <BasicBlock, bool> mapLast = information.mapLast; BasicBlock first = fstat.GetHandler().GetBasichead().GetBlock(); bool skippedFirst = false; if (finallytype == 3) { // empty finally RemoveExceptionInstructionsEx(first, 3, finallytype); if (mapLast.ContainsKey(first)) { graph.GetFinallyExits().Add(first); } return(true); } else if (first.GetSeq().Length() == 1 && finallytype > 0) { BasicBlock firstsuc = first.GetSuccs()[0]; if (catchBlocks.Contains(firstsuc)) { first = firstsuc; skippedFirst = true; } } // identify start blocks HashSet <BasicBlock> startBlocks = new HashSet <BasicBlock>(); foreach (BasicBlock block in tryBlocks) { Sharpen.Collections.AddAll(startBlocks, block.GetSuccs()); } // throw in the try body will point directly to the dummy exit // so remove dummy exit startBlocks.Remove(graph.GetLast()); startBlocks.RemoveAll(tryBlocks); List <FinallyProcessor.Area> lstAreas = new List <FinallyProcessor.Area>(); foreach (BasicBlock start in startBlocks) { FinallyProcessor.Area arr = CompareSubgraphsEx(graph, start, catchBlocks, first, finallytype, mapLast, skippedFirst); if (arr == null) { return(false); } lstAreas.Add(arr); } // try { // DotExporter.toDotFile(graph, new File("c:\\Temp\\fern5.dot"), true); // } catch(Exception ex){ex.printStackTrace();} // delete areas foreach (FinallyProcessor.Area area in lstAreas) { DeleteArea(graph, area); } // try { // DotExporter.toDotFile(graph, new File("c:\\Temp\\fern5.dot"), true); // } catch(Exception ex){ex.printStackTrace();} // INFO: empty basic blocks may remain in the graph! foreach (KeyValuePair <BasicBlock, bool> entry in mapLast) { BasicBlock last = entry.Key; if (entry.Value) { RemoveExceptionInstructionsEx(last, 2, finallytype); graph.GetFinallyExits().Add(last); } } RemoveExceptionInstructionsEx(fstat.GetHandler().GetBasichead().GetBlock(), 1, finallytype ); return(true); }