Skip to content

Commit a8217b9

Browse files
committed
rewrote the code that finds all statements that have a monitor on them. The new implementation now supports nested monitors
1 parent 3b8cbeb commit a8217b9

File tree

1 file changed

+39
-30
lines changed

1 file changed

+39
-30
lines changed

src/soot/toolkits/exceptions/TrapTransformer.java

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22

33
import java.util.ArrayList;
44
import java.util.HashSet;
5-
import java.util.Iterator;
65
import java.util.List;
76
import java.util.Set;
87

98
import soot.BodyTransformer;
9+
import soot.Local;
1010
import soot.Unit;
1111
import soot.jimple.EnterMonitorStmt;
1212
import soot.jimple.ExitMonitorStmt;
1313
import soot.toolkits.graph.UnitGraph;
14+
import soot.util.HashMultiMap;
15+
import soot.util.MultiMap;
1416

1517
/**
1618
* Common abstract base class for all body transformers that change the trap
@@ -20,43 +22,50 @@
2022
*
2123
*/
2224
public abstract class TrapTransformer extends BodyTransformer {
23-
25+
2426
public Set<Unit> getUnitsWithMonitor(UnitGraph ug) {
25-
Set<Unit> unitsWithMonitor = new HashSet<Unit>();
27+
// Idea: Associate each unit with a set of monitors held at that
28+
// statement
29+
MultiMap<Unit, Local> unitMonitors = new HashMultiMap<>();
2630

31+
// Start at the heads of the unit graph
32+
List<Unit> workList = new ArrayList<>();
33+
Set<Unit> doneSet = new HashSet<>();
2734
for (Unit head : ug.getHeads()) {
28-
List<Unit> workList = new ArrayList<Unit>();
2935
workList.add(head);
30-
Set<Unit> doneSet = new HashSet<Unit>();
31-
doneSet.add(head);
36+
}
37+
38+
while (!workList.isEmpty()) {
39+
Unit curUnit = workList.remove(0);
3240

33-
while (!workList.isEmpty()) {
34-
Unit curUnit = workList.remove(0);
35-
for (Unit succ : ug.getSuccsOf(curUnit))
36-
if (doneSet.add(succ))
37-
workList.add(succ);
38-
39-
// If this is an "entermonitor" construct,
40-
// we're in a monitor from now on
41-
if (curUnit instanceof EnterMonitorStmt)
42-
unitsWithMonitor.add(curUnit);
43-
// If we leave a monitor, we're out now
44-
else if (curUnit instanceof ExitMonitorStmt)
45-
continue;
46-
else {
47-
for (Unit pred : ug.getPredsOf(curUnit))
48-
if (unitsWithMonitor.contains(pred))
49-
unitsWithMonitor.add(curUnit);
50-
}
41+
boolean hasChanged = false;
42+
Local exitLocal = null;
43+
if (curUnit instanceof EnterMonitorStmt) {
44+
// We enter a new monitor
45+
EnterMonitorStmt ems = (EnterMonitorStmt) curUnit;
46+
if (ems.getOp() instanceof Local)
47+
hasChanged = unitMonitors.put(curUnit, (Local) ems.getOp());
48+
}
49+
else if (curUnit instanceof ExitMonitorStmt) {
50+
// We leave a minitor
51+
ExitMonitorStmt ems = (ExitMonitorStmt) curUnit;
52+
if (ems.getOp() instanceof Local)
53+
exitLocal = (Local) ems.getOp();
5154
}
55+
56+
// Copy over the monitors from the predecessors
57+
for (Unit pred : ug.getPredsOf(curUnit))
58+
for (Local l : unitMonitors.get(pred))
59+
if (l != exitLocal)
60+
if (unitMonitors.put(curUnit, l))
61+
hasChanged = true;
62+
63+
// Work on the successors
64+
if (doneSet.add(curUnit) || hasChanged)
65+
workList.addAll(ug.getSuccsOf(curUnit));
5266
}
5367

54-
// Get rid of the entermonitor statements themselves
55-
for (Iterator<Unit> it = unitsWithMonitor.iterator(); it.hasNext(); )
56-
if (it.next() instanceof EnterMonitorStmt)
57-
it.remove();
58-
59-
return unitsWithMonitor;
68+
return unitMonitors.keySet();
6069
}
6170

6271
}

0 commit comments

Comments
 (0)