private bool ProcessStatementEx(StructMethod mt, RootStatement root, ControlFlowGraph graph) { int bytecode_version = mt.GetClassStruct().GetBytecodeVersion(); LinkedList <Statement> stack = new LinkedList <Statement>(); stack.AddLast(root); while (!(stack.Count == 0)) { Statement stat = Sharpen.Collections.RemoveLast(stack); Statement parent = stat.GetParent(); if (parent != null && parent.type == Statement.Type_Catchall && stat == parent.GetFirst () && !parent.IsCopied()) { CatchAllStatement fin = (CatchAllStatement)parent; BasicBlock head = fin.GetBasichead().GetBlock(); BasicBlock handler = fin.GetHandler().GetBasichead().GetBlock(); if (catchallBlockIDs.ContainsKey(handler.id)) { } else if (finallyBlockIDs.ContainsKey(handler.id)) { // do nothing fin.SetFinally(true); int?var = finallyBlockIDs.GetOrNullable(handler.id); fin.SetMonitor(var == null ? null : new VarExprent(var.Value, VarType.Vartype_Int , varProcessor)); } else { FinallyProcessor.Record inf = GetFinallyInformation(mt, root, fin); if (inf == null) { // inconsistent finally Sharpen.Collections.Put(catchallBlockIDs, handler.id, null); } else { if (DecompilerContext.GetOption(IFernflowerPreferences.Finally_Deinline) && VerifyFinallyEx (graph, fin, inf)) { Sharpen.Collections.Put(finallyBlockIDs, handler.id, null); } else { int varindex = DecompilerContext.GetCounterContainer().GetCounterAndIncrement(CounterContainer .Var_Counter); InsertSemaphore(graph, GetAllBasicBlocks(fin.GetFirst()), head, handler, varindex , inf, bytecode_version); Sharpen.Collections.Put(finallyBlockIDs, handler.id, varindex); } DeadCodeHelper.RemoveDeadBlocks(graph); // e.g. multiple return blocks after a nested finally DeadCodeHelper.RemoveEmptyBlocks(graph); DeadCodeHelper.MergeBasicBlocks(graph); } return(true); } } Sharpen.Collections.AddAll(stack, stat.GetStats()); } return(false); }
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); }
private static void InsertSemaphore(ControlFlowGraph graph, HashSet <BasicBlock> setTry , BasicBlock head, BasicBlock handler, int var, FinallyProcessor.Record information , int bytecode_version) { HashSet <BasicBlock> setCopy = new HashSet <BasicBlock>(setTry); int finallytype = information.firstCode; Dictionary <BasicBlock, bool> mapLast = information.mapLast; // first and last statements RemoveExceptionInstructionsEx(handler, 1, finallytype); foreach (KeyValuePair <BasicBlock, bool> entry in mapLast) { BasicBlock last = entry.Key; if (entry.Value) { RemoveExceptionInstructionsEx(last, 2, finallytype); graph.GetFinallyExits().Add(last); } } // disable semaphore at statement exit points foreach (BasicBlock block in setTry) { List <BasicBlock> lstSucc = block.GetSuccs(); foreach (BasicBlock dest in lstSucc) { // break out if (dest != graph.GetLast() && !setCopy.Contains(dest)) { // disable semaphore SimpleInstructionSequence seq = new SimpleInstructionSequence(); seq.AddInstruction(Instruction.Create(ICodeConstants.opc_bipush, false, ICodeConstants .Group_General, bytecode_version, new int[] { 0 }), -1); seq.AddInstruction(Instruction.Create(ICodeConstants.opc_istore, false, ICodeConstants .Group_General, bytecode_version, new int[] { var }), -1); // build a separate block BasicBlock newblock = new BasicBlock(++graph.last_id); newblock.SetSeq(seq); // insert between block and dest block.ReplaceSuccessor(dest, newblock); newblock.AddSuccessor(dest); setCopy.Add(newblock); graph.GetBlocks().AddWithKey(newblock, newblock.id); // exception ranges // FIXME: special case synchronized // copy exception edges and extend protected ranges for (int j = 0; j < block.GetSuccExceptions().Count; j++) { BasicBlock hd = block.GetSuccExceptions()[j]; newblock.AddSuccessorException(hd); ExceptionRangeCFG range = graph.GetExceptionRange(hd, block); range.GetProtectedRange().Add(newblock); } } } } // enable semaphore at the statement entrance SimpleInstructionSequence seq_1 = new SimpleInstructionSequence(); seq_1.AddInstruction(Instruction.Create(ICodeConstants.opc_bipush, false, ICodeConstants .Group_General, bytecode_version, new int[] { 1 }), -1); seq_1.AddInstruction(Instruction.Create(ICodeConstants.opc_istore, false, ICodeConstants .Group_General, bytecode_version, new int[] { var }), -1); BasicBlock newhead = new BasicBlock(++graph.last_id); newhead.SetSeq(seq_1); InsertBlockBefore(graph, head, newhead); // initialize semaphor with false seq_1 = new SimpleInstructionSequence(); seq_1.AddInstruction(Instruction.Create(ICodeConstants.opc_bipush, false, ICodeConstants .Group_General, bytecode_version, new int[] { 0 }), -1); seq_1.AddInstruction(Instruction.Create(ICodeConstants.opc_istore, false, ICodeConstants .Group_General, bytecode_version, new int[] { var }), -1); BasicBlock newheadinit = new BasicBlock(++graph.last_id); newheadinit.SetSeq(seq_1); InsertBlockBefore(graph, newhead, newheadinit); setCopy.Add(newhead); setCopy.Add(newheadinit); foreach (BasicBlock hd in new HashSet <BasicBlock>(newheadinit.GetSuccExceptions() )) { ExceptionRangeCFG range = graph.GetExceptionRange(hd, newheadinit); if (setCopy.ContainsAll(range.GetProtectedRange())) { newheadinit.RemoveSuccessorException(hd); range.GetProtectedRange().Remove(newheadinit); } } }