1 package Analysis.OoOJava;
3 import java.io.IOException;
4 import java.util.Enumeration;
5 import java.util.HashSet;
6 import java.util.Hashtable;
7 import java.util.Iterator;
9 import java.util.Stack;
10 import java.util.Map.Entry;
12 import Analysis.ArrayReferencees;
13 import Analysis.Liveness;
14 import Analysis.CallGraph.CallGraph;
15 import Analysis.Disjoint.DisjointAnalysis;
16 import Analysis.Disjoint.Effect;
17 import Analysis.Disjoint.EffectsAnalysis;
18 import Analysis.Disjoint.Taint;
20 import IR.MethodDescriptor;
25 import IR.Flat.FlatEdge;
26 import IR.Flat.FlatFieldNode;
27 import IR.Flat.FlatMethod;
28 import IR.Flat.FlatNode;
29 import IR.Flat.FlatOpNode;
30 import IR.Flat.FlatSESEEnterNode;
31 import IR.Flat.FlatSESEExitNode;
32 import IR.Flat.FlatSetFieldNode;
33 import IR.Flat.FlatWriteDynamicVarNode;
34 import IR.Flat.TempDescriptor;
36 public class OoOJavaAnalysis {
38 // data from the compiler
40 private TypeUtil typeUtil;
41 private CallGraph callGraph;
42 private RBlockRelationAnalysis rblockRel;
43 private RBlockStatusAnalysis rblockStatus;
44 private DisjointAnalysis disjointAnalysisTaints;
45 private DisjointAnalysis disjointAnalysisReach;
47 private Hashtable<FlatNode, Set<TempDescriptor>> livenessRootView;
48 private Hashtable<FlatNode, Set<TempDescriptor>> livenessVirtualReads;
49 private Hashtable<FlatNode, VarSrcTokTable> variableResults;
50 private Hashtable<FlatNode, Set<TempDescriptor>> notAvailableResults;
51 private Hashtable<FlatNode, CodePlan> codePlans;
53 private Hashtable<FlatSESEEnterNode, Set<TempDescriptor>> notAvailableIntoSESE;
55 private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
57 // temporal data structures to track analysis progress.
58 static private int uniqueLockSetId = 0;
59 // mapping of a conflict graph to its compiled lock
60 private Hashtable<ConflictGraph, HashSet<SESELock>> conflictGraph2SESELock;
61 // mapping of a sese block to its conflict graph
62 private Hashtable<FlatNode, ConflictGraph> sese2conflictGraph;
67 // private Hashtable<FlatNode, ParentChildConflictsMap> conflictsResults;
68 // private Hashtable<FlatMethod, MethodSummary> methodSummaryResults;
69 // private OwnershipAnalysis ownAnalysisForSESEConflicts;
71 // static private int uniqueLockSetId = 0;
73 public static int maxSESEage = -1;
75 public int getMaxSESEage() {
80 public CodePlan getCodePlan(FlatNode fn) {
81 CodePlan cp = codePlans.get(fn);
85 public OoOJavaAnalysis(State state, TypeUtil typeUtil, CallGraph callGraph, Liveness liveness,
86 ArrayReferencees arrayReferencees) {
88 double timeStartAnalysis = (double) System.nanoTime();
91 this.typeUtil = typeUtil;
92 this.callGraph = callGraph;
93 this.maxSESEage = state.MLP_MAXSESEAGE;
95 livenessRootView = new Hashtable<FlatNode, Set<TempDescriptor>>();
96 livenessVirtualReads = new Hashtable<FlatNode, Set<TempDescriptor>>();
97 variableResults = new Hashtable<FlatNode, VarSrcTokTable>();
98 notAvailableResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
99 codePlans = new Hashtable<FlatNode, CodePlan>();
100 wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
102 notAvailableIntoSESE = new Hashtable<FlatSESEEnterNode, Set<TempDescriptor>>();
104 sese2conflictGraph = new Hashtable<FlatNode, ConflictGraph>();
105 conflictGraph2SESELock = new Hashtable<ConflictGraph, HashSet<SESELock>>();
107 // add all methods transitively reachable from the
108 // source's main to set for analysis
109 MethodDescriptor mdSourceEntry = typeUtil.getMain();
110 FlatMethod fmMain = state.getMethodFlat(mdSourceEntry);
112 Set<MethodDescriptor> descriptorsToAnalyze = callGraph.getAllMethods(mdSourceEntry);
114 descriptorsToAnalyze.add(mdSourceEntry);
116 // conflictsResults = new Hashtable<FlatNode, ParentChildConflictsMap>();
117 // methodSummaryResults = new Hashtable<FlatMethod, MethodSummary>();
118 // conflictGraphResults = new Hashtable<FlatNode, ConflictGraph>();
120 // seseSummaryMap = new Hashtable<FlatNode, SESESummary>();
121 // isAfterChildSESEIndicatorMap = new Hashtable<FlatNode, Boolean>();
122 // conflictGraphLockMap = new Hashtable<ConflictGraph, HashSet<SESELock>>();
124 // 1st pass, find basic rblock relations
125 rblockRel = new RBlockRelationAnalysis(state, typeUtil, callGraph);
127 rblockStatus = new RBlockStatusAnalysis(state, typeUtil, callGraph, rblockRel);
130 // 2nd pass, liveness, in-set out-set (no virtual reads yet!)
131 Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
132 while (rootItr.hasNext()) {
133 FlatSESEEnterNode root = rootItr.next();
134 livenessAnalysisBackward(root, true, null);
137 // 3rd pass, variable analysis
138 Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
139 while (methItr.hasNext()) {
140 Descriptor d = methItr.next();
141 FlatMethod fm = state.getMethodFlat(d);
143 // starting from roots do a forward, fixed-point
144 // variable analysis for refinement and stalls
145 variableAnalysisForward(fm);
148 // 4th pass, compute liveness contribution from
149 // virtual reads discovered in variable pass
150 rootItr = rblockRel.getRootSESEs().iterator();
151 while (rootItr.hasNext()) {
152 FlatSESEEnterNode root = rootItr.next();
153 livenessAnalysisBackward(root, true, null);
156 // 5th pass, use disjointness with NO FLAGGED REGIONS
157 // to compute taints and effects
158 disjointAnalysisTaints = new DisjointAnalysis(state, typeUtil, callGraph, liveness,
159 arrayReferencees, rblockRel, rblockStatus);
161 // 6th pass, not available analysis FOR VARIABLES!
162 methItr = descriptorsToAnalyze.iterator();
163 while (methItr.hasNext()) {
164 Descriptor d = methItr.next();
165 FlatMethod fm = state.getMethodFlat(d);
167 // compute what is not available at every program
168 // point, in a forward fixed-point pass
169 notAvailableForward(fm);
173 // #th pass, make conflict graph
174 // conflict graph is maintained by each parent sese
175 methItr = descriptorsToAnalyze.iterator();
176 while (methItr.hasNext()) {
177 Descriptor d = methItr.next();
178 FlatMethod fm = state.getMethodFlat(d);
179 makeConflictGraph(fm);
183 Iterator iter = sese2conflictGraph.entrySet().iterator();
184 while (iter.hasNext()) {
185 Entry e = (Entry) iter.next();
186 FlatNode fn = (FlatNode) e.getKey();
187 ConflictGraph conflictGraph = (ConflictGraph) e.getValue();
188 System.out.println("CONFLICT GRAPH for " + fn);
189 Set<String> keySet = conflictGraph.id2cn.keySet();
190 for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
191 String key = (String) iterator.next();
192 ConflictNode node = conflictGraph.id2cn.get(key);
193 System.out.println("key=" + key + " --\n" + node.toString());
197 // #th pass, calculate conflicts
198 calculateConflicts();
200 // #th pass, compiling locks
203 // #th pass, writing conflict graph
204 writeConflictGraph();
209 private void livenessAnalysisBackward(FlatSESEEnterNode fsen, boolean toplevel,
210 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
212 // start from an SESE exit, visit nodes in reverse up to
213 // SESE enter in a fixed-point scheme, where children SESEs
214 // should already be analyzed and therefore can be skipped
215 // because child SESE enter node has all necessary info
216 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
219 flatNodesToVisit.add(fsen.getfmEnclosing().getFlatExit());
221 flatNodesToVisit.add(fsen.getFlatExit());
224 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
227 liveout = new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
230 while (!flatNodesToVisit.isEmpty()) {
231 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
232 flatNodesToVisit.remove(fn);
234 Set<TempDescriptor> prev = livenessResults.get(fn);
236 // merge sets from control flow joins
237 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
238 for (int i = 0; i < fn.numNext(); i++) {
239 FlatNode nn = fn.getNext(i);
240 Set<TempDescriptor> s = livenessResults.get(nn);
246 Set<TempDescriptor> curr = liveness_nodeActions(fn, u, fsen, toplevel, liveout);
248 // if a new result, schedule backward nodes for analysis
249 if (!curr.equals(prev)) {
250 livenessResults.put(fn, curr);
252 // don't flow backwards past current SESE enter
253 if (!fn.equals(fsen)) {
254 for (int i = 0; i < fn.numPrev(); i++) {
255 FlatNode nn = fn.getPrev(i);
256 flatNodesToVisit.add(nn);
262 Set<TempDescriptor> s = livenessResults.get(fsen);
267 // remember liveness per node from the root view as the
268 // global liveness of variables for later passes to use
270 livenessRootView.putAll(livenessResults);
273 // post-order traversal, so do children first
274 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
275 while (childItr.hasNext()) {
276 FlatSESEEnterNode fsenChild = childItr.next();
277 livenessAnalysisBackward(fsenChild, false, liveout);
281 private Set<TempDescriptor> liveness_nodeActions(FlatNode fn, Set<TempDescriptor> liveIn,
282 FlatSESEEnterNode currentSESE, boolean toplevel,
283 Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
286 case FKind.FlatSESEExitNode:
288 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
289 if (!liveout.containsKey(fsexn)) {
290 liveout.put(fsexn, new HashSet<TempDescriptor>());
292 liveout.get(fsexn).addAll(liveIn);
294 // no break, sese exits should also execute default actions
297 // handle effects of statement in reverse, writes then reads
298 TempDescriptor[] writeTemps = fn.writesTemps();
299 for (int i = 0; i < writeTemps.length; ++i) {
300 liveIn.remove(writeTemps[i]);
303 FlatSESEExitNode fsexn = currentSESE.getFlatExit();
304 Set<TempDescriptor> livetemps = liveout.get(fsexn);
305 if (livetemps != null && livetemps.contains(writeTemps[i])) {
306 // write to a live out temp...
307 // need to put in SESE liveout set
308 currentSESE.addOutVar(writeTemps[i]);
313 TempDescriptor[] readTemps = fn.readsTemps();
314 for (int i = 0; i < readTemps.length; ++i) {
315 liveIn.add(readTemps[i]);
318 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get(fn);
319 if (virtualReadTemps != null) {
320 liveIn.addAll(virtualReadTemps);
331 private void variableAnalysisForward(FlatMethod fm) {
333 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
334 flatNodesToVisit.add(fm);
336 while (!flatNodesToVisit.isEmpty()) {
337 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
338 flatNodesToVisit.remove(fn);
340 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
341 assert seseStack != null;
343 VarSrcTokTable prev = variableResults.get(fn);
345 // merge sets from control flow joins
346 VarSrcTokTable curr = new VarSrcTokTable();
347 for (int i = 0; i < fn.numPrev(); i++) {
348 FlatNode nn = fn.getPrev(i);
349 VarSrcTokTable incoming = variableResults.get(nn);
350 curr.merge(incoming);
353 if (!seseStack.empty()) {
354 variable_nodeActions(fn, curr, seseStack.peek());
357 // if a new result, schedule forward nodes for analysis
358 if (!curr.equals(prev)) {
359 variableResults.put(fn, curr);
361 for (int i = 0; i < fn.numNext(); i++) {
362 FlatNode nn = fn.getNext(i);
363 flatNodesToVisit.add(nn);
369 private void variable_nodeActions(FlatNode fn, VarSrcTokTable vstTable,
370 FlatSESEEnterNode currentSESE) {
373 case FKind.FlatSESEEnterNode: {
374 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
375 assert fsen.equals(currentSESE);
377 vstTable.age(currentSESE);
378 vstTable.assertConsistency();
382 case FKind.FlatSESEExitNode: {
383 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
384 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
385 assert currentSESE.getChildren().contains(fsen);
387 // remap all of this child's children tokens to be
388 // from this child as the child exits
389 vstTable.remapChildTokens(fsen);
391 // liveness virtual reads are things that might be
392 // written by an SESE and should be added to the in-set
393 // anything virtually read by this SESE should be pruned
394 // of parent or sibling sources
395 Set<TempDescriptor> liveVars = livenessRootView.get(fn);
396 Set<TempDescriptor> fsenVirtReads = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(
398 Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
399 if (fsenVirtReadsOld != null) {
400 fsenVirtReads.addAll(fsenVirtReadsOld);
402 livenessVirtualReads.put(fn, fsenVirtReads);
404 // then all child out-set tokens are guaranteed
405 // to be filled in, so clobber those entries with
406 // the latest, clean sources
407 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
408 while (outVarItr.hasNext()) {
409 TempDescriptor outVar = outVarItr.next();
410 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
412 VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
413 vstTable.remove(outVar);
416 vstTable.assertConsistency();
421 case FKind.FlatOpNode: {
422 FlatOpNode fon = (FlatOpNode) fn;
424 if (fon.getOp().getOp() == Operation.ASSIGN) {
425 TempDescriptor lhs = fon.getDest();
426 TempDescriptor rhs = fon.getLeft();
428 vstTable.remove(lhs);
430 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
432 Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
433 while (itr.hasNext()) {
434 VariableSourceToken vst = itr.next();
436 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
439 if (currentSESE.getChildren().contains(vst.getSESE())) {
440 // if the source comes from a child, copy it over
441 forAddition.add(new VariableSourceToken(ts, vst.getSESE(), vst.getAge(), vst
444 // otherwise, stamp it as us as the source
445 forAddition.add(new VariableSourceToken(ts, currentSESE, new Integer(0), lhs));
449 vstTable.addAll(forAddition);
451 // only break if this is an ASSIGN op node,
452 // otherwise fall through to default case
453 vstTable.assertConsistency();
458 // note that FlatOpNode's that aren't ASSIGN
459 // fall through to this default case
461 TempDescriptor[] writeTemps = fn.writesTemps();
462 if (writeTemps.length > 0) {
464 // for now, when writeTemps > 1, make sure
465 // its a call node, programmer enforce only
466 // doing stuff like calling a print routine
467 // assert writeTemps.length == 1;
468 if (writeTemps.length > 1) {
469 assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
473 vstTable.remove(writeTemps[0]);
475 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
476 ts.add(writeTemps[0]);
478 vstTable.add(new VariableSourceToken(ts, currentSESE, new Integer(0), writeTemps[0]));
481 vstTable.assertConsistency();
488 private void notAvailableForward(FlatMethod fm) {
490 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
491 flatNodesToVisit.add(fm);
493 while (!flatNodesToVisit.isEmpty()) {
494 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
495 flatNodesToVisit.remove(fn);
497 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
498 assert seseStack != null;
500 Set<TempDescriptor> prev = notAvailableResults.get(fn);
502 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
503 for (int i = 0; i < fn.numPrev(); i++) {
504 FlatNode nn = fn.getPrev(i);
505 Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
506 if (notAvailIn != null) {
507 curr.addAll(notAvailIn);
511 if (!seseStack.empty()) {
512 notAvailable_nodeActions(fn, curr, seseStack.peek());
515 // if a new result, schedule forward nodes for analysis
516 if (!curr.equals(prev)) {
517 notAvailableResults.put(fn, curr);
519 for (int i = 0; i < fn.numNext(); i++) {
520 FlatNode nn = fn.getNext(i);
521 flatNodesToVisit.add(nn);
527 private void notAvailable_nodeActions(FlatNode fn, Set<TempDescriptor> notAvailSet,
528 FlatSESEEnterNode currentSESE) {
530 // any temps that are removed from the not available set
531 // at this node should be marked in this node's code plan
532 // as temps to be grabbed at runtime!
536 case FKind.FlatSESEEnterNode: {
537 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
538 assert fsen.equals(currentSESE);
540 // keep a copy of what's not available into the SESE
541 // and restore it at the matching exit node
542 Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
543 Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
544 while (tdItr.hasNext()) {
545 notAvailCopy.add(tdItr.next());
547 notAvailableIntoSESE.put(fsen, notAvailCopy);
553 case FKind.FlatSESEExitNode: {
554 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
555 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
556 assert currentSESE.getChildren().contains(fsen);
558 notAvailSet.addAll(fsen.getOutVarSet());
560 Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
561 assert notAvailIn != null;
562 notAvailSet.addAll(notAvailIn);
567 case FKind.FlatMethod: {
571 case FKind.FlatOpNode: {
572 FlatOpNode fon = (FlatOpNode) fn;
574 if (fon.getOp().getOp() == Operation.ASSIGN) {
575 TempDescriptor lhs = fon.getDest();
576 TempDescriptor rhs = fon.getLeft();
578 // copy makes lhs same availability as rhs
579 if (notAvailSet.contains(rhs)) {
580 notAvailSet.add(lhs);
582 notAvailSet.remove(lhs);
585 // only break if this is an ASSIGN op node,
586 // otherwise fall through to default case
591 // note that FlatOpNode's that aren't ASSIGN
592 // fall through to this default case
594 TempDescriptor[] writeTemps = fn.writesTemps();
595 for (int i = 0; i < writeTemps.length; i++) {
596 TempDescriptor wTemp = writeTemps[i];
597 notAvailSet.remove(wTemp);
599 TempDescriptor[] readTemps = fn.readsTemps();
600 for (int i = 0; i < readTemps.length; i++) {
601 TempDescriptor rTemp = readTemps[i];
602 notAvailSet.remove(rTemp);
604 // if this variable has exactly one source, potentially
605 // get other things from this source as well
606 VarSrcTokTable vstTable = variableResults.get(fn);
608 VSTWrapper vstIfStatic = new VSTWrapper();
609 Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
611 if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
613 VariableSourceToken vst = vstIfStatic.vst;
615 Iterator<VariableSourceToken> availItr = vstTable.get(vst.getSESE(), vst.getAge())
618 // look through things that are also available from same source
619 while (availItr.hasNext()) {
620 VariableSourceToken vstAlsoAvail = availItr.next();
622 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
623 while (refVarItr.hasNext()) {
624 TempDescriptor refVarAlso = refVarItr.next();
626 // if a variable is available from the same source, AND it ALSO
627 // only comes from one statically known source, mark it available
628 VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
629 Integer srcTypeAlso = vstTable.getRefVarSrcType(refVarAlso, currentSESE,
631 if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
632 notAvailSet.remove(refVarAlso);
644 private void makeConflictGraph(FlatMethod fm) {
646 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
647 flatNodesToVisit.add(fm);
649 Set<FlatNode> visited = new HashSet<FlatNode>();
651 while (!flatNodesToVisit.isEmpty()) {
652 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
653 flatNodesToVisit.remove(fn);
656 Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
657 assert seseStack != null;
659 if (!seseStack.isEmpty()) {
661 // Add Stall Node of current program statement
662 // disjointAnalysisTaints.getEffectsAnalysis().getEffects(t);
664 ConflictGraph conflictGraph = sese2conflictGraph.get(seseStack.peek());
665 if (conflictGraph == null) {
666 conflictGraph = new ConflictGraph();
669 conflictGraph_nodeAction(fn, seseStack.peek());
673 // schedule forward nodes for analysis
674 for (int i = 0; i < fn.numNext(); i++) {
675 FlatNode nn = fn.getNext(i);
676 if (!visited.contains(nn)) {
677 flatNodesToVisit.add(nn);
686 private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE) {
688 EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
689 ConflictGraph conflictGraph = sese2conflictGraph.get(currentSESE.getParent());
690 if (conflictGraph == null) {
691 conflictGraph = new ConflictGraph();
696 case FKind.FlatSESEEnterNode: {
698 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
700 if (!fsen.getIsCallerSESEplaceholder() && currentSESE.getParent() != null) {
701 // collects effects set of invar set and generates invar node
702 Hashtable<Taint, Set<Effect>> taint2Effects=effectsAnalysis.getSESEEffects(currentSESE);
703 conflictGraph.addLiveIn(taint2Effects);
708 case FKind.FlatFieldNode:
709 case FKind.FlatElementNode: {
711 FlatFieldNode ffn = (FlatFieldNode) fn;
712 TempDescriptor rhs = ffn.getSrc();
715 Hashtable<Taint, Set<Effect>> taint2Effects=effectsAnalysis.getStallSiteEffects(fn, rhs);
716 conflictGraph.addStallSite(taint2Effects);
721 case FKind.FlatSetFieldNode:
722 case FKind.FlatSetElementNode: {
724 FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
725 TempDescriptor lhs = fsfn.getDst();
726 TempDescriptor rhs = fsfn.getSrc();
728 // collects effects of stall site and generates stall site node
729 Hashtable<Taint, Set<Effect>> taint2Effects=effectsAnalysis.getStallSiteEffects(fn, rhs);
730 conflictGraph.addStallSite(taint2Effects);
732 taint2Effects=effectsAnalysis.getStallSiteEffects(fn, lhs);
733 conflictGraph.addStallSite(taint2Effects);
739 if (conflictGraph.id2cn.size() > 0) {
740 sese2conflictGraph.put(currentSESE.getParent(), conflictGraph);
745 private void calculateConflicts() {
746 // decide fine-grain edge or coarse-grain edge among all vertexes by
747 // pair-wise comparison
749 Iterator<FlatNode> seseIter = sese2conflictGraph.keySet().iterator();
750 while (seseIter.hasNext()) {
751 FlatNode sese = seseIter.next();
752 ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
753 conflictGraph.analyzeConflicts();
754 sese2conflictGraph.put(sese, conflictGraph);
758 private void writeConflictGraph() {
759 Enumeration<FlatNode> keyEnum = sese2conflictGraph.keys();
760 while (keyEnum.hasMoreElements()) {
761 FlatNode key = (FlatNode) keyEnum.nextElement();
762 ConflictGraph cg = sese2conflictGraph.get(key);
764 if (cg.hasConflictEdge()) {
765 cg.writeGraph("ConflictGraphFor" + key, false);
767 } catch (IOException e) {
768 System.out.println("Error writing");
774 private void synthesizeLocks() {
775 Set<Entry<FlatNode, ConflictGraph>> graphEntrySet = sese2conflictGraph.entrySet();
776 for (Iterator iterator = graphEntrySet.iterator(); iterator.hasNext();) {
777 Entry<FlatNode, ConflictGraph> graphEntry = (Entry<FlatNode, ConflictGraph>) iterator.next();
778 FlatNode sese = graphEntry.getKey();
779 ConflictGraph conflictGraph = graphEntry.getValue();
780 calculateCovering(conflictGraph);
784 private void calculateCovering(ConflictGraph conflictGraph) {
785 uniqueLockSetId = 0; // reset lock counter for every new conflict graph
786 HashSet<ConflictEdge> fineToCover = new HashSet<ConflictEdge>();
787 HashSet<ConflictEdge> coarseToCover = new HashSet<ConflictEdge>();
788 HashSet<SESELock> lockSet = new HashSet<SESELock>();
790 Set<ConflictEdge> tempCover = conflictGraph.getEdgeSet();
791 for (Iterator iterator = tempCover.iterator(); iterator.hasNext();) {
792 ConflictEdge conflictEdge = (ConflictEdge) iterator.next();
793 if (conflictEdge.isCoarseEdge()) {
794 coarseToCover.add(conflictEdge);
796 fineToCover.add(conflictEdge);
800 HashSet<ConflictEdge> toCover = new HashSet<ConflictEdge>();
801 toCover.addAll(fineToCover);
802 toCover.addAll(coarseToCover);
804 while (!toCover.isEmpty()) {
806 SESELock seseLock = new SESELock();
807 seseLock.setID(uniqueLockSetId++);
811 do { // fine-grained edge
815 for (Iterator iterator = fineToCover.iterator(); iterator.hasNext();) {
818 ConflictEdge edge = (ConflictEdge) iterator.next();
819 if (seseLock.getConflictNodeSet().size() == 0) {
821 if (seseLock.isWriteNode(edge.getVertexU())) {
822 // mark as fine_write
823 if (edge.getVertexU().isStallSiteNode()) {
824 type = ConflictNode.PARENT_WRITE;
826 type = ConflictNode.FINE_WRITE;
828 seseLock.addConflictNode(edge.getVertexU(), type);
831 if (edge.getVertexU().isStallSiteNode()) {
832 type = ConflictNode.PARENT_READ;
834 type = ConflictNode.FINE_READ;
836 seseLock.addConflictNode(edge.getVertexU(), type);
838 if (edge.getVertexV() != edge.getVertexU()) {
839 if (seseLock.isWriteNode(edge.getVertexV())) {
840 // mark as fine_write
841 if (edge.getVertexV().isStallSiteNode()) {
842 type = ConflictNode.PARENT_WRITE;
844 type = ConflictNode.FINE_WRITE;
846 seseLock.addConflictNode(edge.getVertexV(), type);
849 if (edge.getVertexV().isStallSiteNode()) {
850 type = ConflictNode.PARENT_READ;
852 type = ConflictNode.FINE_READ;
854 seseLock.addConflictNode(edge.getVertexV(), type);
858 seseLock.addConflictEdge(edge);
859 fineToCover.remove(edge);
860 break;// exit iterator loop
861 }// end of initial setup
863 ConflictNode newNode;
864 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
865 // new node has a fine-grained edge to all current node
866 // If there is a coarse grained edge where need a fine edge, it's
867 // okay to add the node
868 // but the edge must remain uncovered.
872 if (seseLock.isWriteNode(newNode)) {
873 if (newNode.isStallSiteNode()) {
874 type = ConflictNode.PARENT_WRITE;
876 type = ConflictNode.FINE_WRITE;
878 seseLock.setNodeType(newNode, type);
880 if (newNode.isStallSiteNode()) {
881 type = ConflictNode.PARENT_READ;
883 type = ConflictNode.FINE_READ;
885 seseLock.setNodeType(newNode, type);
888 seseLock.addEdge(edge);
889 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
890 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
891 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
893 // mark all fine edges between new node and nodes in the group as
895 if (!conflictEdge.getVertexU().equals(newNode)) {
896 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
898 seseLock.addConflictEdge(conflictEdge);
899 fineToCover.remove(conflictEdge);
901 } else if (!conflictEdge.getVertexV().equals(newNode)) {
902 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
904 seseLock.addConflictEdge(conflictEdge);
905 fineToCover.remove(conflictEdge);
911 break;// exit iterator loop
919 for (Iterator iterator = coarseToCover.iterator(); iterator.hasNext();) {
921 ConflictEdge edge = (ConflictEdge) iterator.next();
923 if (seseLock.getConflictNodeSet().size() == 0) {
925 if (seseLock.hasSelfCoarseEdge(edge.getVertexU())) {
926 // node has a coarse-grained edge with itself
927 if (!(edge.getVertexU().isStallSiteNode())) {
928 // and it is not parent
929 type = ConflictNode.SCC;
931 type = ConflictNode.PARENT_COARSE;
933 seseLock.addConflictNode(edge.getVertexU(), type);
935 if (edge.getVertexU().isStallSiteNode()) {
936 type = ConflictNode.PARENT_COARSE;
938 type = ConflictNode.COARSE;
940 seseLock.addConflictNode(edge.getVertexU(), type);
942 if (seseLock.hasSelfCoarseEdge(edge.getVertexV())) {
943 // node has a coarse-grained edge with itself
944 if (!(edge.getVertexV().isStallSiteNode())) {
945 // and it is not parent
946 type = ConflictNode.SCC;
948 type = ConflictNode.PARENT_COARSE;
950 seseLock.addConflictNode(edge.getVertexV(), type);
952 if (edge.getVertexV().isStallSiteNode()) {
953 type = ConflictNode.PARENT_COARSE;
955 type = ConflictNode.COARSE;
957 seseLock.addConflictNode(edge.getVertexV(), type);
960 coarseToCover.remove(edge);
961 seseLock.addConflictEdge(edge);
962 break;// exit iterator loop
963 }// end of initial setup
965 ConflictNode newNode;
966 if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
967 // new node has a coarse-grained edge to all fine-read, fine-write,
971 if (seseLock.hasSelfCoarseEdge(newNode)) {
973 if (newNode.isStallSiteNode()) {
974 type = ConflictNode.PARENT_COARSE;
976 type = ConflictNode.SCC;
978 seseLock.setNodeType(newNode, type);
980 if (newNode.isStallSiteNode()) {
981 type = ConflictNode.PARENT_COARSE;
983 type = ConflictNode.COARSE;
985 seseLock.setNodeType(newNode, type);
988 seseLock.addEdge(edge);
989 Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
990 for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
991 ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
992 // mark all coarse edges between new node and nodes in the group
994 if (!conflictEdge.getVertexU().equals(newNode)) {
995 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
997 seseLock.addConflictEdge(conflictEdge);
998 coarseToCover.remove(conflictEdge);
1000 } else if (!conflictEdge.getVertexV().equals(newNode)) {
1001 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1003 seseLock.addConflictEdge(conflictEdge);
1004 coarseToCover.remove(conflictEdge);
1009 break;// exit iterator loop
1015 lockSet.add(seseLock);
1018 toCover.addAll(fineToCover);
1019 toCover.addAll(coarseToCover);
1023 conflictGraph2SESELock.put(conflictGraph, lockSet);