package soot.jimple.toolkits.thread.mhp;
import soot.jimple.toolkits.thread.mhp.stmt.JPegStmt;
import soot.toolkits.scalar.*;
import soot.util.*;
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 CompactStronglyConnectedComponents{
long compactNodes = 0;
long add = 0;
public CompactStronglyConnectedComponents(PegGraph pg){
Chain mainPegChain = pg.getMainPegChain();
compactGraph(mainPegChain, pg);
compactStartChain(pg);
//PegToDotFile printer = new PegToDotFile(pg, false, "compact");
System.err.println("compact SCC nodes: "+compactNodes);
System.err.println(" number of compacting scc nodes: "+add);
}
private void compactGraph(Chain chain, PegGraph peg){
Set canNotBeCompacted = peg.getCanNotBeCompacted();
// testCan(speg.getMainPegChain(), canNotBeCompacted);
// SCC scc = new SCC(chain, peg);
SCC scc = new SCC(chain.iterator(), peg);
List<List<Object>> sccList = scc.getSccList();
//testSCC(sccList);
Iterator<List<Object>> sccListIt = sccList.iterator();
while (sccListIt.hasNext()){
List s = sccListIt.next();
if (s.size()>1){
//printSCC(s);
if (!checkIfContainsElemsCanNotBeCompacted(s, canNotBeCompacted)){
add++;
compact(s, chain, peg);
}
}
}
//testListSucc(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 boolean checkIfContainsElemsCanNotBeCompacted(List list,
Set canNotBeCompacted ){
Iterator sccIt = list.iterator();
// System.out.println("sccList: ");
while (sccIt.hasNext()){
JPegStmt node = (JPegStmt)sccIt.next();
// System.out.println("elem of scc:");
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()){
JPegStmt s = (JPegStmt)it.next();
//Replace the SCC with a list node.
{
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()){
JPegStmt s = (JPegStmt)it.next();
chain.remove(s);
allNodes.remove(s);
unitToSuccs.remove(s);
unitToPreds.remove(s);
}
}
//System.out.println("inside compactSCC");
// testListSucc(peg);
// add for get experimental results
compactNodes += list.size();
}
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);
break;
// System.out.println("add list to monitor: "+entry.getKey());
}
}
}
//System.out.println("=======update monitor==end====");
}
}