Skip to content

Commit 8d83f26

Browse files
author
Michael Emmi
committed
Compute topological sort using post-order traversal
* fixes #2080
1 parent e4365f6 commit 8d83f26

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

src/main/java/soot/jimple/spark/solver/TopoSorter.java

+7-10
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,16 @@
2222
* #L%
2323
*/
2424

25-
import java.util.ArrayList;
2625
import java.util.HashSet;
27-
import java.util.List;
26+
import java.util.Stack;
2827

2928
import soot.jimple.spark.pag.Node;
3029
import soot.jimple.spark.pag.PAG;
3130
import soot.jimple.spark.pag.VarNode;
3231

3332
/**
3433
* Performs a pseudo-topological sort on the VarNodes in a PAG.
35-
*
34+
*
3635
* @author Ondrej Lhotak
3736
*/
3837

@@ -64,23 +63,21 @@ protected void dfsVisit(VarNode n) {
6463
if (visited.contains(n)) {
6564
return;
6665
}
67-
List<VarNode> stack = new ArrayList<>();
68-
List<VarNode> all = new ArrayList<>();
66+
Stack<VarNode> stack = new Stack<>();
6967
stack.add(n);
7068
while (!stack.isEmpty()) {
71-
VarNode s = stack.remove(stack.size() - 1);
69+
VarNode s = stack.peek();
7270
if (visited.add(s)) {
73-
all.add(s);
7471
Node[] succs = pag.simpleLookup(s);
7572
for (Node element : succs) {
7673
if (ignoreTypes || pag.getTypeManager().castNeverFails(n.getType(), element.getType())) {
7774
stack.add((VarNode) element);
7875
}
7976
}
77+
} else {
78+
stack.pop();
79+
s.setFinishingNumber(nextFinishNumber++);
8080
}
8181
}
82-
for (int i = all.size() - 1; i >= 0; i--) {
83-
all.get(i).setFinishingNumber(nextFinishNumber++);
84-
}
8582
}
8683
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package soot.jimple.spark.solver;
2+
3+
import java.util.Collections;
4+
5+
import org.junit.Test;
6+
7+
import static org.junit.Assert.assertEquals;
8+
9+
import soot.Scene;
10+
import soot.Type;
11+
import soot.jimple.spark.pag.PAG;
12+
import soot.jimple.spark.pag.VarNode;
13+
import soot.options.SparkOptions;
14+
15+
public class SCCCollapserTest {
16+
17+
@Test
18+
public void testSeparateComponents() {
19+
Scene.v().loadBasicClasses();
20+
Type type = Scene.v().getObjectType();
21+
22+
SparkOptions sparkOptions = new SparkOptions(Collections.emptyMap());
23+
PAG pag = new PAG(sparkOptions);
24+
25+
VarNode a = pag.makeGlobalVarNode("a", type);
26+
VarNode b = pag.makeGlobalVarNode("b", type);
27+
VarNode c = pag.makeGlobalVarNode("c", type);
28+
pag.addEdge(a, b);
29+
pag.addEdge(a, c);
30+
pag.addEdge(b, c);
31+
32+
SCCCollapser sccCollapser = new SCCCollapser(pag, false);
33+
sccCollapser.collapse();
34+
pag.cleanUpMerges();
35+
36+
assertEquals(a, a.getReplacement());
37+
assertEquals(b, b.getReplacement());
38+
assertEquals(c, c.getReplacement());
39+
}
40+
}

0 commit comments

Comments
 (0)