package soot.jimple.toolkits.thread.mhp; import soot.util.*; import soot.toolkits.scalar.*; import java.util.*; // *** USE AT YOUR OWN RISK *** // May Happen in Parallel (MHP) analysis by Lin Li. // This code should be treated as beta-quality code. // It was written in 2003, but not incorporated into Soot until 2006. // As such, it may contain incorrect assumptions about the usage // of certain Soot classes. // Some portions of this MHP analysis have been quality-checked, and are // now used by the Transactions toolkit. // // -Richard L. Halpert, 2006-11-30 public class CompactSequentNodes{ long compactNodes = 0; long add = 0; public CompactSequentNodes(PegGraph pg){ Chain mainPegChain = pg.getMainPegChain(); compactGraph(mainPegChain, pg); compactStartChain(pg); // PegToDotFile printer = new PegToDotFile(pg, false, "sequence"); System.err.println("compact seq. node: "+compactNodes); System.err.println("number of compacting seq. nodes: "+ add); } private void compactGraph(Chain chain, PegGraph peg){ Set canNotBeCompacted = peg.getCanNotBeCompacted(); List<List<Object>> list = computeSequentNodes(chain, peg); // printSeq(list); Iterator<List<Object>> it = list.iterator(); while (it.hasNext()){ List s = it.next(); if (!checkIfContainsElemsCanNotBeCompacted(s, canNotBeCompacted)){ add++; compact(s, chain, peg); } } } private void compactStartChain(PegGraph graph){ Set maps = graph.getStartToThread().entrySet(); for(Iterator iter=maps.iterator(); iter.hasNext();){ Map.Entry entry = (Map.Entry)iter.next(); List runMethodChainList = (List)entry.getValue(); Iterator it = runMethodChainList.iterator(); while (it.hasNext()){ Chain chain=(Chain)it.next(); compactGraph(chain, graph); } } } private List<List<Object>> computeSequentNodes(Chain chain, PegGraph pg){ Set<Object> gray = new HashSet<Object>(); List<List<Object>> sequentNodes = new ArrayList<List<Object>>(); Set canNotBeCompacted = pg.getCanNotBeCompacted(); TopologicalSorter ts = new TopologicalSorter(chain, pg); ListIterator<Object> it = ts.sorter().listIterator(); while (it.hasNext()){ Object node = it.next(); List<Object> list = new ArrayList<Object>(); if (!gray.contains(node)){ visitNode(pg, node, list, canNotBeCompacted, gray); if (list.size()>1){ gray.addAll(list); sequentNodes.add(list); } } } return sequentNodes; } private void visitNode(PegGraph pg, Object node, List<Object> list, Set canNotBeCompacted, Set<Object> gray){ //System.out.println("node is: "+node); if (pg.getPredsOf(node).size() ==1 && pg.getSuccsOf(node).size()==1 && !canNotBeCompacted.contains(node) && !gray.contains(node)){ list.add(node); Iterator it = pg.getSuccsOf(node).iterator(); while (it.hasNext()){ Object o = it.next(); visitNode(pg, o, list, canNotBeCompacted, gray); } } return; } private boolean checkIfContainsElemsCanNotBeCompacted(List list, Set canNotBeCompacted ){ Iterator sccIt = list.iterator(); while (sccIt.hasNext()){ Object node = sccIt.next(); if (canNotBeCompacted.contains(node)){ //System.out.println("find a syn method!!"); return true; } } return false; } private void compact(List list, Chain chain, PegGraph peg){ Iterator it = list.iterator(); FlowSet allNodes = peg.getAllNodes(); HashMap unitToSuccs = peg.getUnitToSuccs(); HashMap unitToPreds = peg.getUnitToPreds(); List<Object> newPreds = new ArrayList<Object>(); List<Object> newSuccs = new ArrayList<Object>(); while (it.hasNext()){ Object s = it.next(); { Iterator predsIt = peg.getPredsOf(s).iterator(); while (predsIt.hasNext()){ Object pred = predsIt.next(); List succsOfPred = peg.getSuccsOf(pred); succsOfPred.remove(s); if (!list.contains(pred)) { newPreds.add(pred); succsOfPred.add(list); } } } { Iterator succsIt = peg.getSuccsOf(s).iterator(); while (succsIt.hasNext()){ Object succ = succsIt.next(); List predsOfSucc = peg.getPredsOf(succ); predsOfSucc.remove(s); if (!list.contains(succ)){ newSuccs.add(succ); predsOfSucc.add(list); } } } } unitToSuccs.put(list, newSuccs); //System.out.println("put list"+list+"\n"+ "newSuccs: "+newSuccs); unitToPreds.put(list, newPreds); allNodes.add(list); chain.add(list); updateMonitor(peg, list); { it = list.iterator(); while (it.hasNext()){ Object s = it.next(); chain.remove(s); allNodes.remove(s); unitToSuccs.remove(s); unitToPreds.remove(s); } } // System.out.println("inside compactSCC"); // testListSucc(peg); compactNodes+=list.size(); } // The compacted nodes may inside some monitors. We need to update monitor objects. private void updateMonitor(PegGraph pg, List list){ //System.out.println("=======update monitor==="); //add list to corresponding monitor objects sets Set maps = pg.getMonitor().entrySet(); //System.out.println("---test list----"); //testList(list); for(Iterator iter=maps.iterator(); iter.hasNext();){ Map.Entry entry = (Map.Entry)iter.next(); FlowSet fs = (FlowSet)entry.getValue(); Iterator it = list.iterator(); while(it.hasNext() ){ Object obj = it.next(); if (fs.contains(obj)){ fs.add(list); //flag = true; break; // System.out.println("add list to monitor: "+entry.getKey()); } } } //System.out.println("=======update monitor==end===="); } }