package soot.jimple.spark.solver; import java.util.*; import soot.jimple.spark.pag.*; /** * XXX: This is a FIX version of soot.jimple.spark.solver.TopoSorter. * When the PAG chain is too long, the old version can be stack overflowed. * We use a user defined stack instead of recursive call. * */ public class TopoSorter { /** Actually perform the topological sort on the PAG. */ public void sort() { for(Iterator it = pag.getVarNodeNumberer().iterator(); it.hasNext(); ) { dfsVisit( (VarNode) it.next() ); } visited = null; } public TopoSorter( PAG pag, boolean ignoreTypes ) { this.pag = pag; this.ignoreTypes = ignoreTypes; //this.visited = new NumberedSet( pag.getVarNodeNumberer() ); this.visited = new HashSet<Node>(); } /* End of public methods. */ /* End of package methods. */ protected boolean ignoreTypes; protected PAG pag; protected int nextFinishNumber = 1; protected HashSet<Node> visited; protected void dfsVisit( VarNode x ) { Stack<Node> stack = new Stack<Node>(); stack.push(x); while(!stack.isEmpty()){ VarNode node = (VarNode)stack.peek(); if( visited.contains( node ) ){ node.setFinishingNumber( nextFinishNumber++ ); stack.pop(); continue; } visited.add( node ); Node[] succs = pag.simpleLookup( node ); for( int i = 0; i < succs.length; i++ ) { if( ignoreTypes || pag.getTypeManager().castNeverFails( node.getType(), succs[i].getType() ) ) { VarNode succNode = (VarNode) succs[i]; if(!visited.contains(succNode)){ stack.push(succNode); } } } } } }