debugged the reach graph support for effect conflicts
[IRC.git] / Robust / src / Analysis / OoOJava / OoOJavaAnalysis.java
1 package Analysis.OoOJava;
2
3 import java.io.BufferedWriter;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.util.Enumeration;
7 import java.util.HashSet;
8 import java.util.Hashtable;
9 import java.util.Iterator;
10 import java.util.Set;
11 import java.util.Stack;
12 import java.util.Map.Entry;
13
14 import Analysis.ArrayReferencees;
15 import Analysis.Liveness;
16 import Analysis.CallGraph.CallGraph;
17 import Analysis.Disjoint.DisjointAnalysis;
18 import Analysis.Disjoint.Effect;
19 import Analysis.Disjoint.EffectsAnalysis;
20 import Analysis.Disjoint.Taint;
21 import IR.Descriptor;
22 import IR.MethodDescriptor;
23 import IR.Operation;
24 import IR.State;
25 import IR.TypeUtil;
26 import IR.Flat.FKind;
27 import IR.Flat.FlatEdge;
28 import IR.Flat.FlatFieldNode;
29 import IR.Flat.FlatMethod;
30 import IR.Flat.FlatNode;
31 import IR.Flat.FlatOpNode;
32 import IR.Flat.FlatNew;
33 import IR.Flat.FlatSESEEnterNode;
34 import IR.Flat.FlatSESEExitNode;
35 import IR.Flat.FlatSetFieldNode;
36 import IR.Flat.FlatWriteDynamicVarNode;
37 import IR.Flat.TempDescriptor;
38
39 public class OoOJavaAnalysis {
40
41   // data from the compiler
42   private State state;
43   private TypeUtil typeUtil;
44   private CallGraph callGraph;
45   private RBlockRelationAnalysis rblockRel;
46   private RBlockStatusAnalysis rblockStatus;
47   private DisjointAnalysis disjointAnalysisTaints;
48   private DisjointAnalysis disjointAnalysisReach;
49
50   private Hashtable<FlatNode, Set<TempDescriptor>> livenessRootView;
51   private Hashtable<FlatNode, Set<TempDescriptor>> livenessVirtualReads;
52   private Hashtable<FlatNode, VarSrcTokTable> variableResults;
53   private Hashtable<FlatNode, Set<TempDescriptor>> notAvailableResults;
54   private Hashtable<FlatNode, CodePlan> codePlans;
55
56   private Hashtable<FlatSESEEnterNode, Set<TempDescriptor>> notAvailableIntoSESE;
57
58   private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
59
60   // temporal data structures to track analysis progress. 
61   static private int uniqueLockSetId = 0;  
62   // mapping of a conflict graph to its compiled lock
63   private Hashtable<ConflictGraph, HashSet<SESELock>> conflictGraph2SESELock;
64   // mapping of a sese block to its conflict graph
65   private Hashtable<FlatNode, ConflictGraph> sese2conflictGraph;
66
67
68   
69
70   // private Hashtable<FlatNode, ParentChildConflictsMap> conflictsResults;
71   // private Hashtable<FlatMethod, MethodSummary> methodSummaryResults;
72   // private OwnershipAnalysis ownAnalysisForSESEConflicts;
73
74   // static private int uniqueLockSetId = 0;
75
76   public static int maxSESEage = -1;
77
78   public int getMaxSESEage() {
79     return maxSESEage;
80   }
81
82   // may be null
83   public CodePlan getCodePlan(FlatNode fn) {
84     CodePlan cp = codePlans.get(fn);
85     return cp;
86   }
87
88   public OoOJavaAnalysis(State state, TypeUtil typeUtil, CallGraph callGraph, Liveness liveness,
89       ArrayReferencees arrayReferencees) {
90
91     double timeStartAnalysis = (double) System.nanoTime();
92
93     this.state = state;
94     this.typeUtil = typeUtil;
95     this.callGraph = callGraph;
96     this.maxSESEage = state.MLP_MAXSESEAGE;
97
98     livenessRootView = new Hashtable<FlatNode, Set<TempDescriptor>>();
99     livenessVirtualReads = new Hashtable<FlatNode, Set<TempDescriptor>>();
100     variableResults = new Hashtable<FlatNode, VarSrcTokTable>();
101     notAvailableResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
102     codePlans = new Hashtable<FlatNode, CodePlan>();
103     wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
104
105     notAvailableIntoSESE = new Hashtable<FlatSESEEnterNode, Set<TempDescriptor>>();
106
107     sese2conflictGraph = new Hashtable<FlatNode, ConflictGraph>();
108     conflictGraph2SESELock = new Hashtable<ConflictGraph, HashSet<SESELock>>();
109
110     // add all methods transitively reachable from the
111     // source's main to set for analysis
112     MethodDescriptor mdSourceEntry = typeUtil.getMain();
113     FlatMethod fmMain = state.getMethodFlat(mdSourceEntry);
114
115     Set<MethodDescriptor> descriptorsToAnalyze = callGraph.getAllMethods(mdSourceEntry);
116
117     descriptorsToAnalyze.add(mdSourceEntry);
118
119     // conflictsResults = new Hashtable<FlatNode, ParentChildConflictsMap>();
120     // methodSummaryResults = new Hashtable<FlatMethod, MethodSummary>();
121     // conflictGraphResults = new Hashtable<FlatNode, ConflictGraph>();
122
123     // seseSummaryMap = new Hashtable<FlatNode, SESESummary>();
124     // isAfterChildSESEIndicatorMap = new Hashtable<FlatNode, Boolean>();
125     // conflictGraphLockMap = new Hashtable<ConflictGraph, HashSet<SESELock>>();
126
127     // 1st pass, find basic rblock relations
128     rblockRel = new RBlockRelationAnalysis(state, typeUtil, callGraph);
129     
130     rblockStatus = new RBlockStatusAnalysis(state, typeUtil, callGraph, rblockRel);
131
132
133     // 2nd pass, liveness, in-set out-set (no virtual reads yet!)
134     Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
135     while (rootItr.hasNext()) {
136       FlatSESEEnterNode root = rootItr.next();
137       livenessAnalysisBackward(root, true, null);
138     }
139
140     // 3rd pass, variable analysis
141     Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
142     while (methItr.hasNext()) {
143       Descriptor d = methItr.next();
144       FlatMethod fm = state.getMethodFlat(d);
145
146       // starting from roots do a forward, fixed-point
147       // variable analysis for refinement and stalls
148       variableAnalysisForward(fm);
149     }
150
151     // 4th pass, compute liveness contribution from
152     // virtual reads discovered in variable pass
153     rootItr = rblockRel.getRootSESEs().iterator();
154     while (rootItr.hasNext()) {
155       FlatSESEEnterNode root = rootItr.next();
156       livenessAnalysisBackward(root, true, null);
157     }
158
159     // 5th pass, use disjointness with NO FLAGGED REGIONS
160     // to compute taints and effects
161     disjointAnalysisTaints = 
162       new DisjointAnalysis(state, 
163                            typeUtil, 
164                            callGraph, 
165                            liveness,
166                            arrayReferencees, 
167                            null, // no FlatNew set to flag
168                            rblockRel, 
169                            rblockStatus
170                            );
171
172     // 6th pass, not available analysis FOR VARIABLES!
173     methItr = descriptorsToAnalyze.iterator();
174     while (methItr.hasNext()) {
175       Descriptor d = methItr.next();
176       FlatMethod fm = state.getMethodFlat(d);
177
178       // compute what is not available at every program
179       // point, in a forward fixed-point pass
180       notAvailableForward(fm);
181     }
182
183     // 7th pass,  make conflict graph
184     // conflict graph is maintained by each parent sese,
185     Iterator descItr=disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
186     while (descItr.hasNext()) {
187       Descriptor d = (Descriptor)descItr.next();
188       FlatMethod fm = state.getMethodFlat(d);
189       if(fm != null)
190         makeConflictGraph(fm);
191     }
192
193     // debug routine 
194     Iterator iter = sese2conflictGraph.entrySet().iterator();
195     while (iter.hasNext()) {
196       Entry e = (Entry) iter.next();
197       FlatNode fn = (FlatNode) e.getKey();
198       ConflictGraph conflictGraph = (ConflictGraph) e.getValue();
199       System.out.println("---------------------------------------");
200       System.out.println("CONFLICT GRAPH for " + fn);
201       Set<String> keySet = conflictGraph.id2cn.keySet();
202       for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
203         String key = (String) iterator.next();
204         ConflictNode node = conflictGraph.id2cn.get(key);
205         System.out.println("key=" + key + " \n" + node.toStringAllEffects());
206       }
207     }
208     
209     // 8th pass, calculate all possible conflicts without using reachability info
210     // and identify set of FlatNew that next disjoint reach. analysis should flag
211     Set<FlatNew> sitesToFlag = new HashSet<FlatNew>();
212     calculateConflicts(sitesToFlag,false);    
213     
214     // 9th pass, ask disjoint analysis to compute reachability
215     // for objects that may cause heap conflicts so the most
216     // efficient method to deal with conflict can be computed
217     // later
218     disjointAnalysisReach = 
219       new DisjointAnalysis(state, 
220                            typeUtil, 
221                            callGraph, 
222                            liveness,
223                            arrayReferencees, 
224                            sitesToFlag,
225                            null, // don't do effects analysis again!
226                            null  // don't do effects analysis again!
227                            );
228     //writeConflictGraph();
229     // 10th pass, calculate conflicts with reachability info
230     calculateConflicts(null, true);
231     
232     /*
233     // 11th pass, compiling locks
234     synthesizeLocks();
235
236     // #th pass, writing conflict graph
237     writeConflictGraph();
238     */
239     
240     if( state.OOODEBUG ) {      
241       try {
242         writeReports( "" );
243         disjointAnalysisTaints.getEffectsAnalysis().writeEffects( "effects.txt" );
244         writeConflictGraph();
245       } catch( IOException e ) {}
246     }
247     
248   }
249
250   private void livenessAnalysisBackward(FlatSESEEnterNode fsen, boolean toplevel,
251       Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
252
253     // start from an SESE exit, visit nodes in reverse up to
254     // SESE enter in a fixed-point scheme, where children SESEs
255     // should already be analyzed and therefore can be skipped
256     // because child SESE enter node has all necessary info
257     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
258
259     if (toplevel) {
260       flatNodesToVisit.add(fsen.getfmEnclosing().getFlatExit());
261     } else {
262       flatNodesToVisit.add(fsen.getFlatExit());
263     }
264
265     Hashtable<FlatNode, Set<TempDescriptor>> livenessResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
266
267     if (toplevel) {
268       liveout = new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
269     }
270
271     while (!flatNodesToVisit.isEmpty()) {
272       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
273       flatNodesToVisit.remove(fn);
274
275       Set<TempDescriptor> prev = livenessResults.get(fn);
276
277       // merge sets from control flow joins
278       Set<TempDescriptor> u = new HashSet<TempDescriptor>();
279       for (int i = 0; i < fn.numNext(); i++) {
280         FlatNode nn = fn.getNext(i);
281         Set<TempDescriptor> s = livenessResults.get(nn);
282         if (s != null) {
283           u.addAll(s);
284         }
285       }
286
287       Set<TempDescriptor> curr = liveness_nodeActions(fn, u, fsen, toplevel, liveout);
288
289       // if a new result, schedule backward nodes for analysis
290       if (!curr.equals(prev)) {
291         livenessResults.put(fn, curr);
292
293         // don't flow backwards past current SESE enter
294         if (!fn.equals(fsen)) {
295           for (int i = 0; i < fn.numPrev(); i++) {
296             FlatNode nn = fn.getPrev(i);
297             flatNodesToVisit.add(nn);
298           }
299         }
300       }
301     }
302
303     Set<TempDescriptor> s = livenessResults.get(fsen);
304     if (s != null) {
305       fsen.addInVarSet(s);
306     }
307
308     // remember liveness per node from the root view as the
309     // global liveness of variables for later passes to use
310     if (toplevel) {
311       livenessRootView.putAll(livenessResults);
312     }
313
314     // post-order traversal, so do children first
315     Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
316     while (childItr.hasNext()) {
317       FlatSESEEnterNode fsenChild = childItr.next();
318       livenessAnalysisBackward(fsenChild, false, liveout);
319     }
320   }
321
322   private Set<TempDescriptor> liveness_nodeActions(FlatNode fn, Set<TempDescriptor> liveIn,
323       FlatSESEEnterNode currentSESE, boolean toplevel,
324       Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
325     switch (fn.kind()) {
326
327     case FKind.FlatSESEExitNode:
328       if (toplevel) {
329         FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
330         if (!liveout.containsKey(fsexn)) {
331           liveout.put(fsexn, new HashSet<TempDescriptor>());
332         }
333         liveout.get(fsexn).addAll(liveIn);
334       }
335       // no break, sese exits should also execute default actions
336
337     default: {
338       // handle effects of statement in reverse, writes then reads
339       TempDescriptor[] writeTemps = fn.writesTemps();
340       for (int i = 0; i < writeTemps.length; ++i) {
341         liveIn.remove(writeTemps[i]);
342
343         if (!toplevel) {
344           FlatSESEExitNode fsexn = currentSESE.getFlatExit();
345           Set<TempDescriptor> livetemps = liveout.get(fsexn);
346           if (livetemps != null && livetemps.contains(writeTemps[i])) {
347             // write to a live out temp...
348             // need to put in SESE liveout set
349             currentSESE.addOutVar(writeTemps[i]);
350           }
351         }
352       }
353
354       TempDescriptor[] readTemps = fn.readsTemps();
355       for (int i = 0; i < readTemps.length; ++i) {
356         liveIn.add(readTemps[i]);
357       }
358
359       Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get(fn);
360       if (virtualReadTemps != null) {
361         liveIn.addAll(virtualReadTemps);
362       }
363
364     }
365       break;
366
367     } // end switch
368
369     return liveIn;
370   }
371
372   private void variableAnalysisForward(FlatMethod fm) {
373
374     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
375     flatNodesToVisit.add(fm);
376
377     while (!flatNodesToVisit.isEmpty()) {
378       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
379       flatNodesToVisit.remove(fn);
380
381       Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
382       assert seseStack != null;
383
384       VarSrcTokTable prev = variableResults.get(fn);
385
386       // merge sets from control flow joins
387       VarSrcTokTable curr = new VarSrcTokTable();
388       for (int i = 0; i < fn.numPrev(); i++) {
389         FlatNode nn = fn.getPrev(i);
390         VarSrcTokTable incoming = variableResults.get(nn);
391         curr.merge(incoming);
392       }
393
394       if (!seseStack.empty()) {
395         variable_nodeActions(fn, curr, seseStack.peek());
396       }
397
398       // if a new result, schedule forward nodes for analysis
399       if (!curr.equals(prev)) {
400         variableResults.put(fn, curr);
401
402         for (int i = 0; i < fn.numNext(); i++) {
403           FlatNode nn = fn.getNext(i);
404           flatNodesToVisit.add(nn);
405         }
406       }
407     }
408   }
409
410   private void variable_nodeActions(FlatNode fn, VarSrcTokTable vstTable,
411       FlatSESEEnterNode currentSESE) {
412     switch (fn.kind()) {
413
414     case FKind.FlatSESEEnterNode: {
415       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
416       assert fsen.equals(currentSESE);
417
418       vstTable.age(currentSESE);
419       vstTable.assertConsistency();
420     }
421       break;
422
423     case FKind.FlatSESEExitNode: {
424       FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
425       FlatSESEEnterNode fsen = fsexn.getFlatEnter();
426       assert currentSESE.getChildren().contains(fsen);
427
428       // remap all of this child's children tokens to be
429       // from this child as the child exits
430       vstTable.remapChildTokens(fsen);
431
432       // liveness virtual reads are things that might be
433       // written by an SESE and should be added to the in-set
434       // anything virtually read by this SESE should be pruned
435       // of parent or sibling sources
436       Set<TempDescriptor> liveVars = livenessRootView.get(fn);
437       Set<TempDescriptor> fsenVirtReads = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(
438           fsen, liveVars);
439       Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
440       if (fsenVirtReadsOld != null) {
441         fsenVirtReads.addAll(fsenVirtReadsOld);
442       }
443       livenessVirtualReads.put(fn, fsenVirtReads);
444
445       // then all child out-set tokens are guaranteed
446       // to be filled in, so clobber those entries with
447       // the latest, clean sources
448       Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
449       while (outVarItr.hasNext()) {
450         TempDescriptor outVar = outVarItr.next();
451         HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
452         ts.add(outVar);
453         VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
454         vstTable.remove(outVar);
455         vstTable.add(vst);
456       }
457       vstTable.assertConsistency();
458
459     }
460       break;
461
462     case FKind.FlatOpNode: {
463       FlatOpNode fon = (FlatOpNode) fn;
464
465       if (fon.getOp().getOp() == Operation.ASSIGN) {
466         TempDescriptor lhs = fon.getDest();
467         TempDescriptor rhs = fon.getLeft();
468
469         vstTable.remove(lhs);
470
471         Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
472
473         Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
474         while (itr.hasNext()) {
475           VariableSourceToken vst = itr.next();
476
477           HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
478           ts.add(lhs);
479
480           if (currentSESE.getChildren().contains(vst.getSESE())) {
481             // if the source comes from a child, copy it over
482             forAddition.add(new VariableSourceToken(ts, vst.getSESE(), vst.getAge(), vst
483                 .getAddrVar()));
484           } else {
485             // otherwise, stamp it as us as the source
486             forAddition.add(new VariableSourceToken(ts, currentSESE, new Integer(0), lhs));
487           }
488         }
489
490         vstTable.addAll(forAddition);
491
492         // only break if this is an ASSIGN op node,
493         // otherwise fall through to default case
494         vstTable.assertConsistency();
495         break;
496       }
497     }
498
499       // note that FlatOpNode's that aren't ASSIGN
500       // fall through to this default case
501     default: {
502       TempDescriptor[] writeTemps = fn.writesTemps();
503       if (writeTemps.length > 0) {
504
505         // for now, when writeTemps > 1, make sure
506         // its a call node, programmer enforce only
507         // doing stuff like calling a print routine
508         // assert writeTemps.length == 1;
509         if (writeTemps.length > 1) {
510           assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
511           break;
512         }
513
514         vstTable.remove(writeTemps[0]);
515
516         HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
517         ts.add(writeTemps[0]);
518
519         vstTable.add(new VariableSourceToken(ts, currentSESE, new Integer(0), writeTemps[0]));
520       }
521
522       vstTable.assertConsistency();
523     }
524       break;
525
526     } // end switch
527   }
528
529   private void notAvailableForward(FlatMethod fm) {
530
531     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
532     flatNodesToVisit.add(fm);
533
534     while (!flatNodesToVisit.isEmpty()) {
535       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
536       flatNodesToVisit.remove(fn);
537
538       Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
539       assert seseStack != null;
540
541       Set<TempDescriptor> prev = notAvailableResults.get(fn);
542
543       Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
544       for (int i = 0; i < fn.numPrev(); i++) {
545         FlatNode nn = fn.getPrev(i);
546         Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
547         if (notAvailIn != null) {
548           curr.addAll(notAvailIn);
549         }
550       }
551
552       if (!seseStack.empty()) {
553         notAvailable_nodeActions(fn, curr, seseStack.peek());
554       }
555
556       // if a new result, schedule forward nodes for analysis
557       if (!curr.equals(prev)) {
558         notAvailableResults.put(fn, curr);
559
560         for (int i = 0; i < fn.numNext(); i++) {
561           FlatNode nn = fn.getNext(i);
562           flatNodesToVisit.add(nn);
563         }
564       }
565     }
566   }
567
568   private void notAvailable_nodeActions(FlatNode fn, Set<TempDescriptor> notAvailSet,
569       FlatSESEEnterNode currentSESE) {
570
571     // any temps that are removed from the not available set
572     // at this node should be marked in this node's code plan
573     // as temps to be grabbed at runtime!
574
575     switch (fn.kind()) {
576
577     case FKind.FlatSESEEnterNode: {
578       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
579       assert fsen.equals(currentSESE);
580
581       // keep a copy of what's not available into the SESE
582       // and restore it at the matching exit node
583       Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
584       Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
585       while (tdItr.hasNext()) {
586         notAvailCopy.add(tdItr.next());
587       }
588       notAvailableIntoSESE.put(fsen, notAvailCopy);
589
590       notAvailSet.clear();
591     }
592       break;
593
594     case FKind.FlatSESEExitNode: {
595       FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
596       FlatSESEEnterNode fsen = fsexn.getFlatEnter();
597       assert currentSESE.getChildren().contains(fsen);
598
599       notAvailSet.addAll(fsen.getOutVarSet());
600
601       Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
602       assert notAvailIn != null;
603       notAvailSet.addAll(notAvailIn);
604
605     }
606       break;
607
608     case FKind.FlatMethod: {
609       notAvailSet.clear();
610     }
611
612     case FKind.FlatOpNode: {
613       FlatOpNode fon = (FlatOpNode) fn;
614
615       if (fon.getOp().getOp() == Operation.ASSIGN) {
616         TempDescriptor lhs = fon.getDest();
617         TempDescriptor rhs = fon.getLeft();
618
619         // copy makes lhs same availability as rhs
620         if (notAvailSet.contains(rhs)) {
621           notAvailSet.add(lhs);
622         } else {
623           notAvailSet.remove(lhs);
624         }
625
626         // only break if this is an ASSIGN op node,
627         // otherwise fall through to default case
628         break;
629       }
630     }
631
632       // note that FlatOpNode's that aren't ASSIGN
633       // fall through to this default case
634     default: {
635       TempDescriptor[] writeTemps = fn.writesTemps();
636       for (int i = 0; i < writeTemps.length; i++) {
637         TempDescriptor wTemp = writeTemps[i];
638         notAvailSet.remove(wTemp);
639       }
640       TempDescriptor[] readTemps = fn.readsTemps();
641       for (int i = 0; i < readTemps.length; i++) {
642         TempDescriptor rTemp = readTemps[i];
643         notAvailSet.remove(rTemp);
644
645         // if this variable has exactly one source, potentially
646         // get other things from this source as well
647         VarSrcTokTable vstTable = variableResults.get(fn);
648
649         VSTWrapper vstIfStatic = new VSTWrapper();
650         Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
651
652         if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
653
654           VariableSourceToken vst = vstIfStatic.vst;
655
656           Iterator<VariableSourceToken> availItr = vstTable.get(vst.getSESE(), vst.getAge())
657               .iterator();
658
659           // look through things that are also available from same source
660           while (availItr.hasNext()) {
661             VariableSourceToken vstAlsoAvail = availItr.next();
662
663             Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
664             while (refVarItr.hasNext()) {
665               TempDescriptor refVarAlso = refVarItr.next();
666
667               // if a variable is available from the same source, AND it ALSO
668               // only comes from one statically known source, mark it available
669               VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
670               Integer srcTypeAlso = vstTable.getRefVarSrcType(refVarAlso, currentSESE,
671                   vstIfStaticNotUsed);
672               if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
673                 notAvailSet.remove(refVarAlso);
674               }
675             }
676           }
677         }
678       }
679     }
680       break;
681
682     } // end switch
683   }
684
685   private void makeConflictGraph(FlatMethod fm) {
686
687     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
688     flatNodesToVisit.add(fm);
689
690     Set<FlatNode> visited = new HashSet<FlatNode>();
691
692     while (!flatNodesToVisit.isEmpty()) {
693       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
694       flatNodesToVisit.remove(fn);
695       visited.add(fn);
696
697       Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
698       assert seseStack != null;
699
700       if (!seseStack.isEmpty()) {
701
702         ConflictGraph conflictGraph = sese2conflictGraph.get(seseStack.peek());
703         if (conflictGraph == null) {
704           conflictGraph = new ConflictGraph();
705         }
706
707         conflictGraph_nodeAction(fn, seseStack.peek());
708       }
709
710       // schedule forward nodes for analysis
711       for (int i = 0; i < fn.numNext(); i++) {
712         FlatNode nn = fn.getNext(i);
713         if (!visited.contains(nn)) {
714           flatNodesToVisit.add(nn);
715         }
716       }
717
718     }
719
720   }
721  
722
723   private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE) {
724
725     ConflictGraph conflictGraph;
726     EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
727
728     switch (fn.kind()) {
729
730     case FKind.FlatSESEEnterNode: {
731
732       if (currentSESE.getParent() == null) {
733         return;
734       }
735       conflictGraph = sese2conflictGraph.get(currentSESE.getParent());
736       if (conflictGraph == null) {
737         conflictGraph = new ConflictGraph();
738       }
739
740       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
741
742       if (!fsen.getIsCallerSESEplaceholder() && currentSESE.getParent() != null) {
743         // collects effects set of invar set and generates invar node
744         Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(currentSESE);
745         conflictGraph.addLiveIn(taint2Effects);
746       }
747
748       if (conflictGraph.id2cn.size() > 0) {
749         sese2conflictGraph.put(currentSESE.getParent(), conflictGraph);
750       }
751
752     }
753       break;
754
755     case FKind.FlatFieldNode:
756     case FKind.FlatElementNode: {
757
758       conflictGraph = sese2conflictGraph.get(currentSESE);
759       if (conflictGraph == null) {
760         conflictGraph = new ConflictGraph();
761       }
762
763       FlatFieldNode ffn = (FlatFieldNode) fn;
764       TempDescriptor rhs = ffn.getSrc();
765
766       // add stall site
767       Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
768       conflictGraph.addStallSite(taint2Effects, rhs);
769
770       if (conflictGraph.id2cn.size() > 0) {
771         sese2conflictGraph.put(currentSESE, conflictGraph);
772       }
773     }
774       break;
775
776     case FKind.FlatSetFieldNode:
777     case FKind.FlatSetElementNode: {
778
779       conflictGraph = sese2conflictGraph.get(currentSESE);
780       if (conflictGraph == null) {
781         conflictGraph = new ConflictGraph();
782       }
783
784       FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
785       TempDescriptor lhs = fsfn.getDst();
786       TempDescriptor rhs = fsfn.getSrc();
787
788       // collects effects of stall site and generates stall site node
789       Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
790       conflictGraph.addStallSite(taint2Effects, rhs);
791       conflictGraph.addStallSite(taint2Effects, lhs);
792
793       if (conflictGraph.id2cn.size() > 0) {
794         sese2conflictGraph.put(currentSESE, conflictGraph);
795       }
796     }
797       break;
798     }
799
800   }
801
802   private void calculateConflicts(Set<FlatNew> sitesToFlag, boolean useReachInfo) {
803     // decide fine-grain edge or coarse-grain edge among all vertexes by
804     // pair-wise comparison
805     Iterator<FlatNode> seseIter = sese2conflictGraph.keySet().iterator();
806     while (seseIter.hasNext()) {
807       FlatSESEEnterNode sese = (FlatSESEEnterNode) seseIter.next();
808       ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
809       if (useReachInfo) {
810         // clear current conflict before recalculating with reachability info
811         conflictGraph.clearAllConflictEdge(); 
812         conflictGraph.setDisJointAnalysis(disjointAnalysisReach);
813         conflictGraph.setFMEnclosing(sese.getfmEnclosing());
814       }
815       conflictGraph.analyzeConflicts(sitesToFlag, useReachInfo);
816       sese2conflictGraph.put(sese, conflictGraph);
817     }
818   }
819   
820   private void writeConflictGraph() {
821     Enumeration<FlatNode> keyEnum = sese2conflictGraph.keys();
822     while (keyEnum.hasMoreElements()) {
823       FlatNode key = (FlatNode) keyEnum.nextElement();
824       ConflictGraph cg = sese2conflictGraph.get(key);
825       try {
826         if (cg.hasConflictEdge()) {
827           cg.writeGraph("ConflictGraphFor" + key, false);
828         }
829       } catch (IOException e) {
830         System.out.println("Error writing");
831         System.exit(0);
832       }
833     }
834   }
835   
836   private void synthesizeLocks() {
837     Set<Entry<FlatNode, ConflictGraph>> graphEntrySet = sese2conflictGraph.entrySet();
838     for (Iterator iterator = graphEntrySet.iterator(); iterator.hasNext();) {
839       Entry<FlatNode, ConflictGraph> graphEntry = (Entry<FlatNode, ConflictGraph>) iterator.next();
840       FlatNode sese = graphEntry.getKey();
841       ConflictGraph conflictGraph = graphEntry.getValue();
842       calculateCovering(conflictGraph);
843     }
844   }
845   
846   private void calculateCovering(ConflictGraph conflictGraph) {
847     uniqueLockSetId = 0; // reset lock counter for every new conflict graph
848     HashSet<ConflictEdge> fineToCover = new HashSet<ConflictEdge>();
849     HashSet<ConflictEdge> coarseToCover = new HashSet<ConflictEdge>();
850     HashSet<SESELock> lockSet = new HashSet<SESELock>();
851
852     Set<ConflictEdge> tempCover = conflictGraph.getEdgeSet();
853     for (Iterator iterator = tempCover.iterator(); iterator.hasNext();) {
854       ConflictEdge conflictEdge = (ConflictEdge) iterator.next();
855       if (conflictEdge.isCoarseEdge()) {
856         coarseToCover.add(conflictEdge);
857       } else {
858         fineToCover.add(conflictEdge);
859       }
860     }
861
862     HashSet<ConflictEdge> toCover = new HashSet<ConflictEdge>();
863     toCover.addAll(fineToCover);
864     toCover.addAll(coarseToCover);
865
866     while (!toCover.isEmpty()) {
867
868       SESELock seseLock = new SESELock();
869       seseLock.setID(uniqueLockSetId++);
870
871       boolean changed;
872
873       do { // fine-grained edge
874
875         changed = false;
876
877         for (Iterator iterator = fineToCover.iterator(); iterator.hasNext();) {
878
879           int type;
880           ConflictEdge edge = (ConflictEdge) iterator.next();
881           if (seseLock.getConflictNodeSet().size() == 0) {
882             // initial setup
883             if (seseLock.isWriteNode(edge.getVertexU())) {
884               // mark as fine_write
885               if (edge.getVertexU().isStallSiteNode()) {
886                 type = ConflictNode.PARENT_WRITE;
887               } else {
888                 type = ConflictNode.FINE_WRITE;
889               }
890               seseLock.addConflictNode(edge.getVertexU(), type);
891             } else {
892               // mark as fine_read
893               if (edge.getVertexU().isStallSiteNode()) {
894                 type = ConflictNode.PARENT_READ;
895               } else {
896                 type = ConflictNode.FINE_READ;
897               }
898               seseLock.addConflictNode(edge.getVertexU(), type);
899             }
900             if (edge.getVertexV() != edge.getVertexU()) {
901               if (seseLock.isWriteNode(edge.getVertexV())) {
902                 // mark as fine_write
903                 if (edge.getVertexV().isStallSiteNode()) {
904                   type = ConflictNode.PARENT_WRITE;
905                 } else {
906                   type = ConflictNode.FINE_WRITE;
907                 }
908                 seseLock.addConflictNode(edge.getVertexV(), type);
909               } else {
910                 // mark as fine_read
911                 if (edge.getVertexV().isStallSiteNode()) {
912                   type = ConflictNode.PARENT_READ;
913                 } else {
914                   type = ConflictNode.FINE_READ;
915                 }
916                 seseLock.addConflictNode(edge.getVertexV(), type);
917               }
918             }
919             changed = true;
920             seseLock.addConflictEdge(edge);
921             fineToCover.remove(edge);
922             break;// exit iterator loop
923           }// end of initial setup
924
925           ConflictNode newNode;
926           if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
927             // new node has a fine-grained edge to all current node
928             // If there is a coarse grained edge where need a fine edge, it's
929             // okay to add the node
930             // but the edge must remain uncovered.
931
932             changed = true;
933
934             if (seseLock.isWriteNode(newNode)) {
935               if (newNode.isStallSiteNode()) {
936                 type = ConflictNode.PARENT_WRITE;
937               } else {
938                 type = ConflictNode.FINE_WRITE;
939               }
940               seseLock.setNodeType(newNode, type);
941             } else {
942               if (newNode.isStallSiteNode()) {
943                 type = ConflictNode.PARENT_READ;
944               } else {
945                 type = ConflictNode.FINE_READ;
946               }
947               seseLock.setNodeType(newNode, type);
948             }
949
950             seseLock.addEdge(edge);
951             Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
952             for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
953               ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
954
955               // mark all fine edges between new node and nodes in the group as
956               // covered
957               if (!conflictEdge.getVertexU().equals(newNode)) {
958                 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
959                   changed = true;
960                   seseLock.addConflictEdge(conflictEdge);
961                   fineToCover.remove(conflictEdge);
962                 }
963               } else if (!conflictEdge.getVertexV().equals(newNode)) {
964                 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
965                   changed = true;
966                   seseLock.addConflictEdge(conflictEdge);
967                   fineToCover.remove(conflictEdge);
968                 }
969               }
970
971             }
972
973             break;// exit iterator loop
974           }
975         }
976
977       } while (changed);
978       do { // coarse
979         changed = false;
980         int type;
981         for (Iterator iterator = coarseToCover.iterator(); iterator.hasNext();) {
982
983           ConflictEdge edge = (ConflictEdge) iterator.next();
984
985           if (seseLock.getConflictNodeSet().size() == 0) {
986             // initial setup
987             if (seseLock.hasSelfCoarseEdge(edge.getVertexU())) {
988               // node has a coarse-grained edge with itself
989               if (!(edge.getVertexU().isStallSiteNode())) {
990                 // and it is not parent
991                 type = ConflictNode.SCC;
992               } else {
993                 type = ConflictNode.PARENT_COARSE;
994               }
995               seseLock.addConflictNode(edge.getVertexU(), type);
996             } else {
997               if (edge.getVertexU().isStallSiteNode()) {
998                 type = ConflictNode.PARENT_COARSE;
999               } else {
1000                 type = ConflictNode.COARSE;
1001               }
1002               seseLock.addConflictNode(edge.getVertexU(), type);
1003             }
1004             if (seseLock.hasSelfCoarseEdge(edge.getVertexV())) {
1005               // node has a coarse-grained edge with itself
1006               if (!(edge.getVertexV().isStallSiteNode())) {
1007                 // and it is not parent
1008                 type = ConflictNode.SCC;
1009               } else {
1010                 type = ConflictNode.PARENT_COARSE;
1011               }
1012               seseLock.addConflictNode(edge.getVertexV(), type);
1013             } else {
1014               if (edge.getVertexV().isStallSiteNode()) {
1015                 type = ConflictNode.PARENT_COARSE;
1016               } else {
1017                 type = ConflictNode.COARSE;
1018               }
1019               seseLock.addConflictNode(edge.getVertexV(), type);
1020             }
1021             changed = true;
1022             coarseToCover.remove(edge);
1023             seseLock.addConflictEdge(edge);
1024             break;// exit iterator loop
1025           }// end of initial setup
1026
1027           ConflictNode newNode;
1028           if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1029             // new node has a coarse-grained edge to all fine-read, fine-write,
1030             // parent
1031             changed = true;
1032
1033             if (seseLock.hasSelfCoarseEdge(newNode)) {
1034               // SCC
1035               if (newNode.isStallSiteNode()) {
1036                 type = ConflictNode.PARENT_COARSE;
1037               } else {
1038                 type = ConflictNode.SCC;
1039               }
1040               seseLock.setNodeType(newNode, type);
1041             } else {
1042               if (newNode.isStallSiteNode()) {
1043                 type = ConflictNode.PARENT_COARSE;
1044               } else {
1045                 type = ConflictNode.COARSE;
1046               }
1047               seseLock.setNodeType(newNode, type);
1048             }
1049
1050             seseLock.addEdge(edge);
1051             Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1052             for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1053               ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1054               // mark all coarse edges between new node and nodes in the group
1055               // as covered
1056               if (!conflictEdge.getVertexU().equals(newNode)) {
1057                 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1058                   changed = true;
1059                   seseLock.addConflictEdge(conflictEdge);
1060                   coarseToCover.remove(conflictEdge);
1061                 }
1062               } else if (!conflictEdge.getVertexV().equals(newNode)) {
1063                 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1064                   changed = true;
1065                   seseLock.addConflictEdge(conflictEdge);
1066                   coarseToCover.remove(conflictEdge);
1067                 }
1068               }
1069
1070             }
1071             break;// exit iterator loop
1072           }
1073
1074         }
1075
1076       } while (changed);
1077       lockSet.add(seseLock);
1078
1079       toCover.clear();
1080       toCover.addAll(fineToCover);
1081       toCover.addAll(coarseToCover);
1082
1083     }
1084
1085     conflictGraph2SESELock.put(conflictGraph, lockSet);
1086   }
1087   
1088   public void writeReports( String timeReport ) throws java.io.IOException {
1089
1090     BufferedWriter bw = new BufferedWriter( new FileWriter( "mlpReport_summary.txt" ) );
1091     bw.write( "MLP Analysis Results\n\n" );
1092     bw.write( timeReport+"\n\n" );
1093     printSESEHierarchy( bw );
1094     bw.write( "\n" );
1095     printSESEInfo( bw );
1096     bw.close();
1097
1098     Iterator<Descriptor> methItr = disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
1099     while( methItr.hasNext() ) {
1100       MethodDescriptor md = (MethodDescriptor) methItr.next();      
1101       FlatMethod       fm = state.getMethodFlat( md );
1102       if (fm!=null) {
1103         bw =
1104             new BufferedWriter(new FileWriter("mlpReport_" + md.getClassMethodName()
1105                 + md.getSafeMethodDescriptor() + ".txt"));
1106         bw.write("MLP Results for " + md + "\n-------------------\n");
1107
1108         FlatSESEEnterNode implicitSESE = (FlatSESEEnterNode) fm.getNext(0);
1109         if (!implicitSESE.getIsCallerSESEplaceholder() && implicitSESE != rblockRel.getMainSESE()) {
1110           System.out.println(implicitSESE + " is not implicit?!");
1111           System.exit(-1);
1112         }
1113         bw.write("Dynamic vars to manage:\n  " + implicitSESE.getDynamicVarSet());
1114
1115         bw.write("\n\nLive-In, Root View\n------------------\n" + fm.printMethod(livenessRootView));
1116         bw.write("\n\nVariable Results-Out\n----------------\n" + fm.printMethod(variableResults));
1117         bw.write("\n\nNot Available Results-Out\n---------------------\n"
1118             + fm.printMethod(notAvailableResults));
1119         bw.write("\n\nCode Plans\n----------\n" + fm.printMethod(codePlans));
1120         bw.close();
1121       }
1122     }
1123   }
1124   
1125   private void printSESEHierarchy( BufferedWriter bw ) throws java.io.IOException {
1126     bw.write( "SESE Hierarchy\n--------------\n" ); 
1127     Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
1128     while( rootItr.hasNext() ) {
1129       FlatSESEEnterNode root = rootItr.next();
1130       if( root.getIsCallerSESEplaceholder() ) {
1131   if( !root.getChildren().isEmpty() ) {
1132     printSESEHierarchyTree( bw, root, 0 );
1133   }
1134       } else {
1135   printSESEHierarchyTree( bw, root, 0 );
1136       }
1137     }
1138   }
1139
1140   private void printSESEHierarchyTree( BufferedWriter bw,
1141                FlatSESEEnterNode fsen,
1142                int depth 
1143              ) throws java.io.IOException {
1144     for( int i = 0; i < depth; ++i ) {
1145       bw.write( "  " );
1146     }
1147     bw.write( "- "+fsen.getPrettyIdentifier()+"\n" );
1148
1149     Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1150     while( childItr.hasNext() ) {
1151       FlatSESEEnterNode fsenChild = childItr.next();
1152       printSESEHierarchyTree( bw, fsenChild, depth + 1 );
1153     }
1154   }
1155
1156   
1157   private void printSESEInfo( BufferedWriter bw ) throws java.io.IOException {
1158     bw.write("\nSESE info\n-------------\n" ); 
1159     Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
1160     while( rootItr.hasNext() ) {
1161       FlatSESEEnterNode root = rootItr.next();
1162       if( root.getIsCallerSESEplaceholder() ) {
1163   if( !root.getChildren().isEmpty() ) {
1164     printSESEInfoTree( bw, root );
1165   }
1166       } else {
1167   printSESEInfoTree( bw, root );
1168       }
1169     }
1170   }
1171
1172   private void printSESEInfoTree( BufferedWriter bw,
1173           FlatSESEEnterNode fsen 
1174         ) throws java.io.IOException {
1175
1176     if( !fsen.getIsCallerSESEplaceholder() ) {
1177       bw.write( "SESE "+fsen.getPrettyIdentifier()+" {\n" );
1178
1179       bw.write( "  in-set: "+fsen.getInVarSet()+"\n" );
1180       Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
1181       while( tItr.hasNext() ) {
1182   TempDescriptor inVar = tItr.next();
1183   if( fsen.getReadyInVarSet().contains( inVar ) ) {
1184     bw.write( "    (ready)  "+inVar+"\n" );
1185   }
1186   if( fsen.getStaticInVarSet().contains( inVar ) ) {
1187     bw.write( "    (static) "+inVar+" from "+
1188                     fsen.getStaticInVarSrc( inVar )+"\n" );
1189   } 
1190   if( fsen.getDynamicInVarSet().contains( inVar ) ) {
1191     bw.write( "    (dynamic)"+inVar+"\n" );
1192   }
1193       }
1194       
1195       bw.write( "   Dynamic vars to manage: "+fsen.getDynamicVarSet()+"\n");
1196       
1197       bw.write( "  out-set: "+fsen.getOutVarSet()+"\n" );
1198       bw.write( "}\n" );
1199     }
1200
1201     Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1202     while( childItr.hasNext() ) {
1203       FlatSESEEnterNode fsenChild = childItr.next();
1204       printSESEInfoTree( bw, fsenChild );
1205     }
1206   }
1207
1208 }