import java.util.Map.Entry;
import Analysis.Disjoint.AllocSite;
+import Analysis.Disjoint.DisjointAnalysis;
import Analysis.Disjoint.Effect;
import Analysis.Disjoint.Taint;
+import IR.Flat.FlatMethod;
+import IR.Flat.FlatNew;
import IR.Flat.FlatNode;
import IR.Flat.FlatSESEEnterNode;
import IR.Flat.TempDescriptor;
public class ConflictGraph {
- public Hashtable<String, ConflictNode> id2cn;
+ protected Hashtable<String, ConflictNode> id2cn;
+
+ protected DisjointAnalysis da;
+ protected FlatMethod fmEnclosing;
public static final int NON_WRITE_CONFLICT = 0;
public static final int FINE_GRAIN_EDGE = 1;
public static final int COARSE_GRAIN_EDGE = 2;
+ public static final int CONFLICT = 3;
public ConflictGraph() {
id2cn = new Hashtable<String, ConflictNode>();
}
-
+
+ public void setDisJointAnalysis(DisjointAnalysis da) {
+ this.da = da;
+ }
+
+ public void setFMEnclosing(FlatMethod fmEnclosing) {
+ this.fmEnclosing = fmEnclosing;
+ }
+
public void addLiveIn(Hashtable<Taint, Set<Effect>> taint2Effects) {
+ if (taint2Effects == null) {
+ return;
+ }
Iterator entryIter = taint2Effects.entrySet().iterator();
while (entryIter.hasNext()) {
Entry entry = (Entry) entryIter.next();
}
}
- public void addStallSite(Hashtable<Taint, Set<Effect>> taint2Effects) {
+ public void addStallSite(Hashtable<Taint, Set<Effect>> taint2Effects, TempDescriptor var) {
+ if (taint2Effects == null) {
+ return;
+ }
Iterator entryIter = taint2Effects.entrySet().iterator();
while (entryIter.hasNext()) {
Entry entry = (Entry) entryIter.next();
Iterator<Effect> effectIter = effectSet.iterator();
while (effectIter.hasNext()) {
Effect effect = (Effect) effectIter.next();
- addStallSiteEffect(taint, effect);
+ if (taint.getVar().equals(var)) {
+ addStallSiteEffect(taint, effect);
+ }
}
}
}
TempDescriptor var = t.getVar();
AllocSite as = t.getAllocSite();
- String id = var + "_" + fn;
+ String id = var + "_fn" + fn.hashCode();
ConflictNode node = id2cn.get(id);
if (node == null) {
- node = new ConflictNode(id, ConflictNode.INVAR);
- }
-
- if (!id2cn.containsKey(id)) {
-
- } else {
- node = id2cn.get(id);
+ node = new ConflictNode(id, ConflictNode.STALLSITE);
}
node.addEffect(as, e);
id2cn.put(id, node);
-
}
public void addLiveInNodeEffect(Taint t, Effect e) {
TempDescriptor invar = t.getVar();
AllocSite as = t.getAllocSite();
- String id = invar + "_" + sese.getIdentifier();
-
+ String id = invar + "_sese" + sese.getIdentifier();
ConflictNode node = id2cn.get(id);
if (node == null) {
node = new ConflictNode(id, ConflictNode.INVAR);
}
-
- if (!id2cn.containsKey(id)) {
-
- } else {
- node = id2cn.get(id);
- }
node.addEffect(as, e);
id2cn.put(id, node);
}
- public void analyzeConflicts() {
+ public void analyzeConflicts(Set<FlatNew> sitesToFlag, boolean useReachInfo) {
Set<String> keySet = id2cn.keySet();
Set<String> analyzedIDSet = new HashSet<String>();
for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
String nodeID = (String) iterator.next();
ConflictNode node = id2cn.get(nodeID);
- analyzePossibleConflicts(analyzedIDSet, node);
+ analyzePossibleConflicts(analyzedIDSet, node, sitesToFlag, useReachInfo);
}
}
- private void analyzePossibleConflicts(Set<String> analyzedIDSet, ConflictNode currentNode) {
+ private void analyzePossibleConflicts(Set<String> analyzedIDSet, ConflictNode currentNode,
+ Set<FlatNew> sitesToFlag, boolean useReachInfo) {
// compare with all nodes
// examine the case where self-edge exists
int conflictType;
if (currentNode.isInVarNode()) {
- conflictType = calculateConflictType(currentNode);
+ conflictType = calculateConflictType(currentNode, useReachInfo);
if (conflictType > ConflictGraph.NON_WRITE_CONFLICT) {
addConflictEdge(conflictType, currentNode, currentNode);
+ if (sitesToFlag != null) {
+ sitesToFlag.addAll(currentNode.getFlatNewSet());
+ }
}
}
&& !(analyzedIDSet.contains(currentNode.getID() + entryNodeID) || analyzedIDSet
.contains(entryNodeID + currentNode.getID()))) {
- if (currentNode.isStallSiteNode() && entryNode.isInVarNode()) {
- /*
- * int conflictType = calculateConflictType((StallSiteNode)
- * currentNode, (LiveInNode) entryNode); if (conflictType > 0) {
- * addConflictEdge(conflictType, currentNode, entryNode); }
- *
- * analyzedIDSet.add(currentNode.getID() + entryNodeID);
- */
- } else if (currentNode.isInVarNode() && entryNode.isInVarNode()) {
- conflictType = calculateConflictType(currentNode, entryNode);
- if (conflictType > ConflictGraph.NON_WRITE_CONFLICT) {
- addConflictEdge(conflictType, currentNode, entryNode);
+ conflictType = calculateConflictType(currentNode, entryNode, useReachInfo);
+ if (conflictType > ConflictGraph.NON_WRITE_CONFLICT) {
+ addConflictEdge(conflictType, currentNode, entryNode);
+ if (sitesToFlag != null) {
+ sitesToFlag.addAll(currentNode.getFlatNewSet());
+ sitesToFlag.addAll(entryNode.getFlatNewSet());
}
- analyzedIDSet.add(currentNode.getID() + entryNodeID);
}
+ analyzedIDSet.add(currentNode.getID() + entryNodeID);
+
}
}
}
- private int calculateConflictType(ConflictNode node) {
+ private int calculateConflictType(ConflictNode node, boolean useReachInfo) {
int conflictType = ConflictGraph.NON_WRITE_CONFLICT;
Hashtable<AllocSite, Set<Effect>> alloc2readEffects = node.getReadEffectSet();
conflictType =
updateConflictType(conflictType, determineConflictType(alloc2writeEffects,
- alloc2writeEffects));
+ alloc2writeEffects, useReachInfo));
conflictType =
updateConflictType(conflictType, hasStrongUpdateConflicts(alloc2SUEffects,
- alloc2readEffects, alloc2writeEffects));
+ alloc2readEffects, alloc2writeEffects, useReachInfo));
return conflictType;
}
- private int calculateConflictType(ConflictNode nodeA, ConflictNode nodeB) {
+ private int calculateConflictType(ConflictNode nodeA, ConflictNode nodeB, boolean useReachInfo) {
int conflictType = ConflictGraph.NON_WRITE_CONFLICT;
// if node A has write effects on reading/writing regions of node B
conflictType =
updateConflictType(conflictType, determineConflictType(alloc2writeEffectsA,
- alloc2readEffectsB));
+ alloc2readEffectsB, useReachInfo));
conflictType =
updateConflictType(conflictType, determineConflictType(alloc2writeEffectsA,
- alloc2writeEffectsB));
+ alloc2writeEffectsB, useReachInfo));
// if node B has write effects on reading regions of node A
- determineConflictType(alloc2writeEffectsB, alloc2readEffectsA);
+ conflictType =
+ updateConflictType(conflictType, determineConflictType(alloc2writeEffectsB,
+ alloc2readEffectsA, useReachInfo));
// strong udpate effects conflict with all effects
// on objects that are reachable from the same heap roots
if (!alloc2SUEffectsA.isEmpty()) {
conflictType =
updateConflictType(conflictType, hasStrongUpdateConflicts(alloc2SUEffectsA,
- alloc2readEffectsB, alloc2writeEffectsB));
+ alloc2readEffectsB, alloc2writeEffectsB, useReachInfo));
}
// if node B has SU on regions of node A
if (!alloc2SUEffectsB.isEmpty()) {
conflictType =
updateConflictType(conflictType, hasStrongUpdateConflicts(alloc2SUEffectsB,
- alloc2readEffectsA, alloc2writeEffectsA));
+ alloc2readEffectsA, alloc2writeEffectsA, useReachInfo));
}
return conflictType;
}
private int hasStrongUpdateConflicts(Hashtable<AllocSite, Set<Effect>> SUEffectsTableA,
- Hashtable<AllocSite, Set<Effect>> readTableB, Hashtable<AllocSite, Set<Effect>> writeTableB) {
+ Hashtable<AllocSite, Set<Effect>> readTableB, Hashtable<AllocSite, Set<Effect>> writeTableB,
+ boolean useReachInfo) {
int conflictType = ConflictGraph.NON_WRITE_CONFLICT;
if (strongUpdateA.getAffectedAllocSite().equals(effectB.getAffectedAllocSite())
&& strongUpdateA.getField().equals(effectB.getField())) {
- // possible conflict
- // check affected allocation site can be reached from both heap
- // roots
- // if(og.isReachable(asA, asB,
- // strongUpdateA.getAffectedAllocSite()){
- // return ConflictGraph.COARSE_GRAIN_EDGE;
- // }
+ if (useReachInfo) {
+ FlatNew fnRoot1 = asA.getFlatNew();
+ FlatNew fnRoot2 = asB.getFlatNew();
+ FlatNew fnTarget = strongUpdateA.getAffectedAllocSite().getFlatNew();
+ if (da.mayBothReachTarget(fmEnclosing, fnRoot1, fnRoot2, fnTarget)) {
+ conflictType = updateConflictType(conflictType, ConflictGraph.COARSE_GRAIN_EDGE);
+ }
+ } else {
+ return ConflictGraph.CONFLICT;
+ }
+
}
}
if (strongUpdateA.getAffectedAllocSite().equals(effectB.getAffectedAllocSite())
&& strongUpdateA.getField().equals(effectB.getField())) {
- // possible conflict
- // check affected allocation site can be reached from both heap
- // roots
- // if(og.isReachable(asA, asB,
- // strongUpdateA.getAffectedAllocSite()){
- // return ConflictGraph.COARSE_GRAIN_EDGE;
- // }
+
+ FlatNew fnRoot1 = asA.getFlatNew();
+ FlatNew fnRoot2 = asB.getFlatNew();
+ FlatNew fnTarget = strongUpdateA.getAffectedAllocSite().getFlatNew();
+ if (da.mayBothReachTarget(fmEnclosing, fnRoot1, fnRoot2, fnTarget)) {
+ conflictType = updateConflictType(conflictType, ConflictGraph.COARSE_GRAIN_EDGE);
+ }
}
}
}
private int determineConflictType(Hashtable<AllocSite, Set<Effect>> nodeAtable,
- Hashtable<AllocSite, Set<Effect>> nodeBtable) {
+ Hashtable<AllocSite, Set<Effect>> nodeBtable, boolean useReachInfo) {
int conflictType = ConflictGraph.NON_WRITE_CONFLICT;
Iterator effectItrB = nodeBtable.entrySet().iterator();
while (effectItrB.hasNext()) {
Map.Entry meB = (Map.Entry) effectItrB.next();
- AllocSite asB = (AllocSite) meA.getKey();
- Set<Effect> esB = (Set<Effect>) meA.getValue();
+ AllocSite asB = (AllocSite) meB.getKey();
+ Set<Effect> esB = (Set<Effect>) meB.getValue();
for (Iterator iterator = esA.iterator(); iterator.hasNext();) {
Effect effectA = (Effect) iterator.next();
if (effectA.getAffectedAllocSite().equals(effectB.getAffectedAllocSite())
&& effectA.getField().equals(effectB.getField())) {
- // possible conflict
- /*
- * if(og.isReachable(asA, asB, effectA.getAffectedAllocSite())){
- * //affected allocation site can be reached from both heap roots
- * if(isFineGrainConflict()){
- * conflictType=updateConflictType(conflictType
- * ,ConflictGraph.FINE_GRAIN_EDGE); }else{
- * conflictType=updateConflictType
- * (conflictType,ConflictGraph.COARSE_GRAIN_EDGE); } }
- */
+
+ if (useReachInfo) {
+ FlatNew fnRoot1 = asA.getFlatNew();
+ FlatNew fnRoot2 = asB.getFlatNew();
+ FlatNew fnTarget = effectA.getAffectedAllocSite().getFlatNew();
+ if (da.mayBothReachTarget(fmEnclosing, fnRoot1, fnRoot2, fnTarget)) {
+ if (fnRoot1.equals(fnRoot2)) {
+ if (!da.mayManyReachTarget(fmEnclosing, fnRoot1, fnTarget)) {
+ // fine-grained conflict case
+ conflictType =
+ updateConflictType(conflictType, ConflictGraph.FINE_GRAIN_EDGE);
+ } else {
+ conflictType =
+ updateConflictType(conflictType, ConflictGraph.COARSE_GRAIN_EDGE);
+ }
+ } else {
+ conflictType =
+ updateConflictType(conflictType, ConflictGraph.COARSE_GRAIN_EDGE);
+ }
+ }
+ } else {
+ return ConflictGraph.CONFLICT;
+ }
}
}
}
}
}
+ public void clearAllConflictEdge() {
+ Collection<ConflictNode> nodes = id2cn.values();
+ for (Iterator iterator = nodes.iterator(); iterator.hasNext();) {
+ ConflictNode conflictNode = (ConflictNode) iterator.next();
+ conflictNode.getEdgeSet().clear();
+ }
+ }
+
public HashSet<ConflictEdge> getEdgeSet() {
HashSet<ConflictEdge> returnSet = new HashSet<ConflictEdge>();
// 7th pass, make conflict graph
// conflict graph is maintained by each parent sese,
- // and while making the graph identify set of FlatNew
- // that next disjoint reach. analysis should flag
- Set<FlatNew> sitesToFlag = new HashSet<FlatNew>();
-
- methItr = descriptorsToAnalyze.iterator();
- while (methItr.hasNext()) {
- Descriptor d = methItr.next();
+ Iterator descItr=disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
+ while (descItr.hasNext()) {
+ Descriptor d = (Descriptor)descItr.next();
FlatMethod fm = state.getMethodFlat(d);
- makeConflictGraph(fm, sitesToFlag);
+ if(fm != null)
+ makeConflictGraph(fm);
}
// debug routine
Entry e = (Entry) iter.next();
FlatNode fn = (FlatNode) e.getKey();
ConflictGraph conflictGraph = (ConflictGraph) e.getValue();
+ System.out.println("---------------------------------------");
System.out.println("CONFLICT GRAPH for " + fn);
Set<String> keySet = conflictGraph.id2cn.keySet();
for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
ConflictNode node = conflictGraph.id2cn.get(key);
- System.out.println("key=" + key + " --\n" + node.toString());
+ System.out.println("key=" + key + " \n" + node.toStringAllEffects());
}
}
- // 8th pass, ask disjoint analysis to compute reachability
+ // 8th pass, calculate all possible conflicts without using reachability info
+ // and identify set of FlatNew that next disjoint reach. analysis should flag
+ Set<FlatNew> sitesToFlag = new HashSet<FlatNew>();
+ calculateConflicts(sitesToFlag,false);
+
+ // 9th pass, ask disjoint analysis to compute reachability
// for objects that may cause heap conflicts so the most
// efficient method to deal with conflict can be computed
// later
null // don't do effects analysis again!
);
- // 9th pass, calculate conflicts
- //calculateConflicts();
+ // 10th pass, calculate conflicts with reachability info
+ calculateConflicts(null, true);
/*
- // #th pass, compiling locks
+ // 11th pass, compiling locks
synthesizeLocks();
// #th pass, writing conflict graph
} // end switch
}
- private void makeConflictGraph(FlatMethod fm, Set<FlatNew> sitesToFlag) {
+ private void makeConflictGraph(FlatMethod fm) {
Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
flatNodesToVisit.add(fm);
conflictGraph = new ConflictGraph();
}
- conflictGraph_nodeAction(fn, seseStack.peek(), sitesToFlag);
+ conflictGraph_nodeAction(fn, seseStack.peek());
}
// schedule forward nodes for analysis
}
- private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE, Set<FlatNew> sitesToFlag) {
+ private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE) {
+ ConflictGraph conflictGraph;
EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
- ConflictGraph conflictGraph = sese2conflictGraph.get(currentSESE.getParent());
- if (conflictGraph == null) {
- conflictGraph = new ConflictGraph();
- }
-
+
switch (fn.kind()) {
case FKind.FlatSESEEnterNode: {
+ if (currentSESE.getParent() == null) {
+ return;
+ }
+ conflictGraph = sese2conflictGraph.get(currentSESE.getParent());
+ if (conflictGraph == null) {
+ conflictGraph = new ConflictGraph();
+ }
+
FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
if (!fsen.getIsCallerSESEplaceholder() && currentSESE.getParent() != null) {
// collects effects set of invar set and generates invar node
- Hashtable<Taint, Set<Effect>> taint2Effects=effectsAnalysis.get(currentSESE);
+ Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(currentSESE);
conflictGraph.addLiveIn(taint2Effects);
}
+
+ if (conflictGraph.id2cn.size() > 0) {
+ sese2conflictGraph.put(currentSESE.getParent(), conflictGraph);
+ }
+
}
break;
-
- case FKind.FlatFieldNode:
+
+ case FKind.FlatFieldNode:
case FKind.FlatElementNode: {
-
+
+ conflictGraph = sese2conflictGraph.get(currentSESE);
+ if (conflictGraph == null) {
+ conflictGraph = new ConflictGraph();
+ }
+
FlatFieldNode ffn = (FlatFieldNode) fn;
TempDescriptor rhs = ffn.getSrc();
-
- // add stall site
- //Hashtable<Taint, Set<Effect>> taint2Effects=effectsAnalysis.get(fn, rhs);
- //conflictGraph.addStallSite(taint2Effects);
-
- }
+
+ // add stall site
+ Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
+ conflictGraph.addStallSite(taint2Effects, rhs);
+
+ if (conflictGraph.id2cn.size() > 0) {
+ sese2conflictGraph.put(currentSESE, conflictGraph);
+ }
+ }
break;
-
- case FKind.FlatSetFieldNode:
+
+ case FKind.FlatSetFieldNode:
case FKind.FlatSetElementNode: {
-
+
+ conflictGraph = sese2conflictGraph.get(currentSESE);
+ if (conflictGraph == null) {
+ conflictGraph = new ConflictGraph();
+ }
+
FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
TempDescriptor lhs = fsfn.getDst();
TempDescriptor rhs = fsfn.getSrc();
-
+
// collects effects of stall site and generates stall site node
- //Hashtable<Taint, Set<Effect>> taint2Effects=effectsAnalysis.get(fn, rhs);
- //conflictGraph.addStallSite(taint2Effects);
-
- //taint2Effects=effectsAnalysis.get(fn, lhs);
- //conflictGraph.addStallSite(taint2Effects);
-
- }
+ Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
+ conflictGraph.addStallSite(taint2Effects, rhs);
+ conflictGraph.addStallSite(taint2Effects, lhs);
+
+ if (conflictGraph.id2cn.size() > 0) {
+ sese2conflictGraph.put(currentSESE, conflictGraph);
+ }
+ }
break;
}
- if (conflictGraph.id2cn.size() > 0) {
- sese2conflictGraph.put(currentSESE.getParent(), conflictGraph);
- }
-
}
-
- private void calculateConflicts() {
+
+ private void calculateConflicts(Set<FlatNew> sitesToFlag, boolean useReachInfo) {
// decide fine-grain edge or coarse-grain edge among all vertexes by
// pair-wise comparison
-
Iterator<FlatNode> seseIter = sese2conflictGraph.keySet().iterator();
while (seseIter.hasNext()) {
- FlatNode sese = seseIter.next();
+ FlatSESEEnterNode sese = (FlatSESEEnterNode) seseIter.next();
ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
- conflictGraph.analyzeConflicts();
+ if (useReachInfo) {
+ // clear current conflict before recalculating with reachability info
+ conflictGraph.clearAllConflictEdge();
+ conflictGraph.setDisJointAnalysis(disjointAnalysisReach);
+ conflictGraph.setFMEnclosing(sese.getfmEnclosing());
+ }
+ conflictGraph.analyzeConflicts(sitesToFlag, useReachInfo);
sese2conflictGraph.put(sese, conflictGraph);
}
}