bringing ooojava code gen around, some todos still to work out
[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.Map;
11 import java.util.Set;
12 import java.util.Stack;
13 import java.util.Map.Entry;
14
15 import Analysis.ArrayReferencees;
16 import Analysis.Liveness;
17 import Analysis.CallGraph.CallGraph;
18 import Analysis.Disjoint.DisjointAnalysis;
19 import Analysis.Disjoint.Effect;
20 import Analysis.Disjoint.EffectsAnalysis;
21 import Analysis.Disjoint.Taint;
22 import IR.Descriptor;
23 import IR.MethodDescriptor;
24 import IR.Operation;
25 import IR.State;
26 import IR.TypeUtil;
27 import IR.Flat.FKind;
28 import IR.Flat.FlatCall;
29 import IR.Flat.FlatEdge;
30 import IR.Flat.FlatElementNode;
31 import IR.Flat.FlatFieldNode;
32 import IR.Flat.FlatMethod;
33 import IR.Flat.FlatNew;
34 import IR.Flat.FlatNode;
35 import IR.Flat.FlatOpNode;
36 import IR.Flat.FlatSESEEnterNode;
37 import IR.Flat.FlatSESEExitNode;
38 import IR.Flat.FlatSetElementNode;
39 import IR.Flat.FlatSetFieldNode;
40 import IR.Flat.FlatWriteDynamicVarNode;
41 import IR.Flat.TempDescriptor;
42
43 public class OoOJavaAnalysis {
44
45   // data from the compiler
46   private State state;
47   private TypeUtil typeUtil;
48   private CallGraph callGraph;
49   private RBlockRelationAnalysis rblockRel;
50   private DisjointAnalysis disjointAnalysisTaints;
51   private DisjointAnalysis disjointAnalysisReach;
52
53   private Set<MethodDescriptor> descriptorsToAnalyze;
54
55   private Hashtable<FlatNode, Set<TempDescriptor>> livenessGlobalView;
56   private Hashtable<FlatNode, Set<TempDescriptor>> livenessVirtualReads;
57   private Hashtable<FlatNode, VarSrcTokTable> variableResults;
58   private Hashtable<FlatNode, Set<TempDescriptor>> notAvailableResults;
59   private Hashtable<FlatNode, CodePlan> codePlans;
60
61   private Hashtable<FlatSESEEnterNode, Set<TempDescriptor>> notAvailableIntoSESE;
62
63   private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
64
65   private Hashtable<FlatNode, ContextTaskNames> fn2contextTaskNames;
66
67   // get the flat method that contains any given flat node
68   private Hashtable<FlatNode, FlatMethod> fn2fm;
69
70   // temporal data structures to track analysis progress.
71   static private int uniqueLockSetId = 0;
72   // mapping of a conflict graph to its compiled lock
73   private Hashtable<ConflictGraph, HashSet<SESELock>> conflictGraph2SESELock;
74   // mapping of a sese block to its conflict graph
75   private Hashtable<FlatNode, ConflictGraph> sese2conflictGraph;
76
77   public static int maxSESEage = -1;
78
79   public int getMaxSESEage() {
80     return maxSESEage;
81   }
82
83   // may be null
84   public CodePlan getCodePlan(FlatNode fn) {
85     CodePlan cp = codePlans.get(fn);
86     return cp;
87   }
88
89   public Set<FlatNode> getNodesWithPlans() {
90     return codePlans.keySet();
91   }
92
93   public ContextTaskNames getContextTaskNames( FlatMethod fm ) {
94     ContextTaskNames out = fn2contextTaskNames.get( fm );
95     if( out == null ) {
96       out = new ContextTaskNames();
97     }
98     return out;
99   }
100
101   public ContextTaskNames getContextTaskNames( FlatSESEEnterNode fsen ) {
102     ContextTaskNames out = fn2contextTaskNames.get( fsen );
103     if( out == null ) {
104       out = new ContextTaskNames();
105     }
106     return out;
107   }
108
109   public FlatMethod getContainingFlatMethod( FlatNode fn ) {
110     FlatMethod fm = fn2fm.get( fn );
111     assert fm != null;
112     return fm;
113   }
114
115   public DisjointAnalysis getDisjointAnalysis() {
116     return disjointAnalysisTaints;
117   }
118
119
120   public OoOJavaAnalysis(State state, 
121                          TypeUtil typeUtil, 
122                          CallGraph callGraph, 
123                          Liveness liveness,
124                          ArrayReferencees arrayReferencees) {
125
126     double timeStartAnalysis = (double) System.nanoTime();
127
128     this.state = state;
129     this.typeUtil = typeUtil;
130     this.callGraph = callGraph;
131     this.maxSESEage = state.OOO_MAXSESEAGE;
132
133     livenessGlobalView     = new Hashtable<FlatNode, Set<TempDescriptor>>();
134     livenessVirtualReads   = new Hashtable<FlatNode, Set<TempDescriptor>>();
135     variableResults        = new Hashtable<FlatNode, VarSrcTokTable>();
136     notAvailableResults    = new Hashtable<FlatNode, Set<TempDescriptor>>();
137     codePlans              = new Hashtable<FlatNode, CodePlan>();
138     wdvNodesToSpliceIn     = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
139     notAvailableIntoSESE   = new Hashtable<FlatSESEEnterNode, Set<TempDescriptor>>();
140     sese2conflictGraph     = new Hashtable<FlatNode, ConflictGraph>();
141     conflictGraph2SESELock = new Hashtable<ConflictGraph, HashSet<SESELock>>();
142     fn2contextTaskNames    = new Hashtable<FlatNode, ContextTaskNames>();
143
144     // add all methods transitively reachable from the
145     // source's main to set for analysis
146     MethodDescriptor mdSourceEntry = typeUtil.getMain();
147     FlatMethod fmMain = state.getMethodFlat(mdSourceEntry);
148
149     descriptorsToAnalyze = callGraph.getAllMethods(mdSourceEntry);
150
151     descriptorsToAnalyze.add(mdSourceEntry);
152
153     // 0th pass, setup a useful mapping of any flat node to the
154     // flat method it is a part of
155     Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
156     while (methItr.hasNext()) {
157       Descriptor d = methItr.next();
158       FlatMethod fm = state.getMethodFlat( d );
159       buildFlatNodeToFlatMethod( fm );
160     }
161
162     // 1st pass, find basic rblock relations & potential stall sites
163     rblockRel = new RBlockRelationAnalysis(state, typeUtil, callGraph);
164     VarSrcTokTable.rblockRel = rblockRel;
165
166     // 2nd pass, liveness, in-set out-set (no virtual reads yet!)
167     methItr = descriptorsToAnalyze.iterator();
168     while (methItr.hasNext()) {
169       Descriptor d = methItr.next();
170       FlatMethod fm = state.getMethodFlat(d);
171
172       // note we can't use the general liveness analysis already in
173       // the compiler because this analysis is task-aware
174       livenessAnalysisBackward(fm);
175     }
176
177     // 3rd pass, variable analysis
178     methItr = descriptorsToAnalyze.iterator();
179     while (methItr.hasNext()) {
180       Descriptor d = methItr.next();
181       FlatMethod fm = state.getMethodFlat(d);
182
183       // starting from roots do a forward, fixed-point
184       // variable analysis for refinement and stalls
185       variableAnalysisForward(fm);
186     }
187
188     // 4th pass, compute liveness contribution from
189     // virtual reads discovered in variable pass
190     methItr = descriptorsToAnalyze.iterator();
191     while (methItr.hasNext()) {
192       Descriptor d = methItr.next();
193       FlatMethod fm = state.getMethodFlat(d);
194       livenessAnalysisBackward(fm);
195     }
196
197     // 5th pass, use disjointness with NO FLAGGED REGIONS
198     // to compute taints and effects
199     disjointAnalysisTaints =
200         new DisjointAnalysis(state, typeUtil, callGraph, liveness, arrayReferencees, null, 
201                              rblockRel,
202                              true ); // suppress output--this is an intermediate pass
203
204     // 6th pass, not available analysis FOR VARIABLES!
205     methItr = descriptorsToAnalyze.iterator();
206     while (methItr.hasNext()) {
207       Descriptor d = methItr.next();
208       FlatMethod fm = state.getMethodFlat(d);
209
210       // compute what is not available at every program
211       // point, in a forward fixed-point pass
212       notAvailableForward(fm);
213     }
214
215     // 7th pass, make conflict graph
216     // conflict graph is maintained by each parent sese,
217     // where its' own stall sites and children may appear
218     Set<FlatSESEEnterNode> allSESEs=rblockRel.getAllSESEs();
219     for (Iterator iterator = allSESEs.iterator(); iterator.hasNext();) {
220
221       FlatSESEEnterNode parent = (FlatSESEEnterNode) iterator.next();
222       if (!parent.getIsLeafSESE()) {
223
224         EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
225         ConflictGraph conflictGraph = sese2conflictGraph.get(parent);     
226         if (conflictGraph == null) {
227           conflictGraph = new ConflictGraph(state);
228         }
229
230         Set<FlatSESEEnterNode> children = parent.getChildren();
231         for (Iterator iterator2 = children.iterator(); iterator2.hasNext();) {
232           FlatSESEEnterNode child = (FlatSESEEnterNode) iterator2.next();
233           Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(child);
234           conflictGraph.addLiveIn(taint2Effects);
235           sese2conflictGraph.put(parent, conflictGraph);
236         }
237       }
238     }
239     
240     Iterator descItr = descriptorsToAnalyze.iterator();
241     while (descItr.hasNext()) {
242       Descriptor d = (Descriptor) descItr.next();
243       FlatMethod fm = state.getMethodFlat(d);
244       if (fm != null) {
245         makeConflictGraph(fm);
246       }
247     }    
248
249     
250     // 8th pass, calculate all possible conflicts without using
251     // reachability info and identify set of FlatNew that next
252     // disjoint reach. analysis should flag
253     Set<FlatNew> sitesToFlag = new HashSet<FlatNew>();
254     calculateConflicts(sitesToFlag, false);
255
256
257     if (!state.RCR) {
258       // 9th pass, ask disjoint analysis to compute reachability
259       // for objects that may cause heap conflicts so the most
260       // efficient method to deal with conflict can be computed
261       // later      
262       disjointAnalysisReach =
263         new DisjointAnalysis(state, typeUtil, callGraph, liveness, 
264                              arrayReferencees, sitesToFlag,
265                              null // don't do effects analysis again!
266                              );
267
268       // 10th pass, calculate conflicts with reachability info
269       calculateConflicts(null, true);
270     }
271
272     // 11th pass, compiling locks
273     synthesizeLocks();
274
275     // 12th pass, compute a plan for code injections
276     methItr = descriptorsToAnalyze.iterator();
277     while (methItr.hasNext()) {
278       Descriptor d = methItr.next();
279       FlatMethod fm = state.getMethodFlat(d);
280       codePlansForward(fm);
281     }
282
283     // 13th pass,
284     // splice new IR nodes into graph after all
285     // analysis passes are complete
286     Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
287     while (spliceItr.hasNext()) {
288       Map.Entry me = (Map.Entry) spliceItr.next();
289       FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
290       fwdvn.spliceIntoIR();
291     }
292
293
294     if (state.OOODEBUG) {
295       try {
296         writeReports("");
297         disjointAnalysisTaints.getEffectsAnalysis().writeEffects("effects.txt");
298         writeConflictGraph();
299       } catch (IOException e) {}
300     }
301     
302
303     System.out.println("\n\n\n##########################################################\n"+
304                        "Warning, lots of code changes going on, OoOJava and RCR/DFJ\n"+
305                        "systems are being cleaned up.  Until the analyses and code gen\n"+
306                        "are fully altered and coordinated, these systems will not run\n"+
307                        "to completion.  Partial stable check-ins are necessary to manage\n"+
308                        "the number of files getting touched.\n"+
309                        "##########################################################" );
310     System.exit( 0 );
311   }
312
313
314   private void buildFlatNodeToFlatMethod( FlatMethod fm ) {
315     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
316     flatNodesToVisit.add( fm.getFlatExit() );
317
318     Set<FlatNode> flatNodesVisited = new HashSet<FlatNode>();
319
320     while( !flatNodesToVisit.isEmpty() ) {
321       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
322       flatNodesToVisit.remove( fn );
323       flatNodesVisited.add( fn );
324
325       fn2fm.put( fn, fm );
326
327       for( int i = 0; i < fn.numNext(); i++ ) {
328         FlatNode nn = fn.getNext( i );
329         if( !flatNodesVisited.contains( nn ) ) {
330           flatNodesToVisit.add( nn );
331         }
332       }
333     }
334   }
335
336
337     // debug routine
338     /*
339      * Iterator iter = sese2conflictGraph.entrySet().iterator(); while
340      * (iter.hasNext()) { Entry e = (Entry) iter.next(); FlatNode fn =
341      * (FlatNode) e.getKey(); ConflictGraph conflictGraph = (ConflictGraph)
342      * e.getValue();
343      * System.out.println("---------------------------------------");
344      * System.out.println("CONFLICT GRAPH for " + fn); Set<String> keySet =
345      * conflictGraph.id2cn.keySet(); for (Iterator iterator = keySet.iterator();
346      * iterator.hasNext();) { String key = (String) iterator.next();
347      * ConflictNode node = conflictGraph.id2cn.get(key);
348      * System.out.println("key=" + key + " \n" + node.toStringAllEffects()); } }
349      */
350
351
352   
353
354   private void writeFile(Set<FlatNew> sitesToFlag) {
355
356     try {
357       BufferedWriter bw = new BufferedWriter(new FileWriter("sitesToFlag.txt"));
358
359       for (Iterator iterator = sitesToFlag.iterator(); iterator.hasNext();) {
360         FlatNew fn = (FlatNew) iterator.next();
361         bw.write(fn + "\n");
362       }
363       bw.close();
364     } catch (IOException e) {
365
366     }
367
368   }
369
370
371   private void livenessAnalysisBackward(FlatMethod fm) {
372
373     // flow backward across nodes to compute liveness, and
374     // take special care with sese enter/exit nodes that
375     // alter this from normal liveness analysis
376     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
377     flatNodesToVisit.add( fm.getFlatExit() );
378
379     while( !flatNodesToVisit.isEmpty() ) {
380       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
381       flatNodesToVisit.remove( fn );
382
383       Set<TempDescriptor> prev = livenessGlobalView.get( fn );
384
385       // merge sets from control flow joins
386       Set<TempDescriptor> livein = new HashSet<TempDescriptor>();
387       for (int i = 0; i < fn.numNext(); i++) {
388         FlatNode nn = fn.getNext( i );
389         Set<TempDescriptor> s = livenessGlobalView.get( nn );
390         if( s != null ) {
391           livein.addAll( s );
392         }
393       }
394       
395       Set<TempDescriptor> curr = liveness_nodeActions( fn, livein );
396
397       // if a new result, schedule backward nodes for analysis
398       if( !curr.equals( prev ) ) {
399         livenessGlobalView.put( fn, curr );
400
401         for( int i = 0; i < fn.numPrev(); i++ ) {
402           FlatNode nn = fn.getPrev( i );
403           flatNodesToVisit.add( nn );
404         }
405       }
406     }
407   }
408
409   private Set<TempDescriptor> liveness_nodeActions( FlatNode            fn, 
410                                                     Set<TempDescriptor> liveIn
411                                                     ) {
412     switch( fn.kind() ) {
413
414     case FKind.FlatSESEEnterNode: {
415       // add whatever is live-in at a task enter to that
416       // task's in-var set
417       FlatSESEEnterNode fsen = (FlatSESEEnterNode)fn;
418       if( liveIn != null ) {
419         fsen.addInVarSet( liveIn );
420       }
421       // no break, should also execute default actions
422     }
423
424     default: {
425       // handle effects of statement in reverse, writes then reads
426       TempDescriptor[] writeTemps = fn.writesTemps();
427       for( int i = 0; i < writeTemps.length; ++i ) {
428         liveIn.remove( writeTemps[i] );
429
430         // if we are analyzing code declared directly in a task,
431         FlatSESEEnterNode fsen = rblockRel.getLocalInnerRBlock( fn );
432         if( fsen != null ) {
433           // check to see if we are writing to variables that will
434           // be live-out at the task's exit (and therefore should
435           // go in the task's out-var set)
436           FlatSESEExitNode fsexn = fsen.getFlatExit();
437           Set<TempDescriptor> livetemps = livenessGlobalView.get( fsexn );
438           if( livetemps != null && livetemps.contains( writeTemps[i] ) ) {
439             fsen.addOutVar( writeTemps[i] );
440           }          
441         }
442       }
443
444       TempDescriptor[] readTemps = fn.readsTemps();
445       for( int i = 0; i < readTemps.length; ++i ) {
446         liveIn.add( readTemps[i] );
447       }
448
449       Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get( fn );
450       if( virtualReadTemps != null ) {
451         liveIn.addAll( virtualReadTemps );
452       }      
453     } break;
454
455     } // end switch
456
457     return liveIn;
458   }
459
460
461   private void variableAnalysisForward(FlatMethod fm) {
462
463     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
464     flatNodesToVisit.add(fm);
465
466     while (!flatNodesToVisit.isEmpty()) {
467       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
468       flatNodesToVisit.remove(fn);
469
470       VarSrcTokTable prev = variableResults.get(fn);
471
472       // merge sets from control flow joins
473       VarSrcTokTable curr = new VarSrcTokTable();
474       for (int i = 0; i < fn.numPrev(); i++) {
475         FlatNode nn = fn.getPrev(i);
476         VarSrcTokTable incoming = variableResults.get(nn);
477         curr.merge(incoming);
478       }
479
480       FlatSESEEnterNode currentSESE = rblockRel.getLocalInnerRBlock( fn );
481       if( currentSESE == null ) {
482         currentSESE = rblockRel.getCallerProxySESE();
483       }
484       
485       variable_nodeActions(fn, curr, currentSESE);
486
487       // if a new result, schedule forward nodes for analysis
488       if (!curr.equals(prev)) {
489         variableResults.put(fn, curr);
490
491         for (int i = 0; i < fn.numNext(); i++) {
492           FlatNode nn = fn.getNext(i);
493           flatNodesToVisit.add(nn);
494         }
495       }
496     }
497   }
498
499   private void variable_nodeActions(FlatNode          fn, 
500                                     VarSrcTokTable    vstTable,
501                                     FlatSESEEnterNode currentSESE) {
502     switch (fn.kind()) {
503
504
505     case FKind.FlatSESEEnterNode: {
506       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
507       // ignore currently executing SESE, at this point
508       // the analysis considers a new instance is becoming
509       // the current SESE
510       vstTable.age(fsen);
511       vstTable.assertConsistency();
512     } break;
513
514
515     case FKind.FlatSESEExitNode: {
516       FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
517
518       // fsen is the child of currently executing tasks
519       FlatSESEEnterNode fsen = fsexn.getFlatEnter();
520
521       // remap all of this child's children tokens to be
522       // from this child as the child exits
523       vstTable.remapChildTokens(fsen);
524
525       // liveness virtual reads are things that might be
526       // written by an SESE and should be added to the in-set
527       // anything virtually read by this SESE should be pruned
528       // of parent or sibling sources
529       Set<TempDescriptor> liveVars = livenessGlobalView.get(fn);
530       Set<TempDescriptor> fsenVirtReads =
531         vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(fsen, 
532                                                              liveVars);
533
534       Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
535       if (fsenVirtReadsOld != null) {
536         fsenVirtReads.addAll(fsenVirtReadsOld);
537       }
538       livenessVirtualReads.put(fn, fsenVirtReads);
539
540       // then all child out-set tokens are guaranteed
541       // to be filled in, so clobber those entries with
542       // the latest, clean sources
543       Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
544       while (outVarItr.hasNext()) {
545         TempDescriptor outVar = outVarItr.next();
546         HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
547         ts.add(outVar);
548         VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
549         vstTable.remove(outVar);
550         vstTable.add(vst);
551       }
552       vstTable.assertConsistency();
553     } break;
554
555
556     case FKind.FlatOpNode: {
557       FlatOpNode fon = (FlatOpNode) fn;
558
559       if (fon.getOp().getOp() == Operation.ASSIGN) {
560         TempDescriptor lhs = fon.getDest();
561         TempDescriptor rhs = fon.getLeft();
562
563         vstTable.remove(lhs);
564
565         Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
566
567         Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
568         while (itr.hasNext()) {
569           VariableSourceToken vst = itr.next();
570
571           HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
572           ts.add(lhs);
573
574           // when we do x = y for variables, just copy over from a child,
575           // there are two cases:
576           //  1. if the current task is the caller proxy, any local root is a child
577           boolean case1 = 
578             currentSESE.getIsCallerProxySESE() &&
579             rblockRel.getLocalRootSESEs().contains( vst.getSESE() );
580
581           //  2. if the child task is a locally-defined child of the current task
582           boolean case2 = currentSESE.getLocalChildren().contains( vst.getSESE() );
583             
584           if( case1 || case2 ) {
585             // if the source comes from a child, copy it over
586             forAddition.add( new VariableSourceToken( ts, 
587                                                       vst.getSESE(), 
588                                                       vst.getAge(), 
589                                                       vst.getAddrVar()
590                                                       )
591                              );
592           } else {
593             // otherwise, stamp it as us as the source
594             forAddition.add( new VariableSourceToken( ts, 
595                                                       currentSESE, 
596                                                       new Integer( 0 ), 
597                                                       lhs
598                                                       )
599                              );
600           }
601         }
602
603         vstTable.addAll( forAddition );
604
605         // only break if this is an ASSIGN op node,
606         // otherwise fall through to default case
607         vstTable.assertConsistency();
608         break;
609       }
610     }
611
612       // note that FlatOpNode's that aren't ASSIGN
613       // fall through to this default case
614     default: {
615       TempDescriptor[] writeTemps = fn.writesTemps();
616       if( writeTemps.length > 0 ) {
617
618         // for now, when writeTemps > 1, make sure
619         // its a call node, programmer enforce only
620         // doing stuff like calling a print routine
621         if( writeTemps.length > 1 ) {
622           assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
623           break;
624         }
625
626         vstTable.remove( writeTemps[0] );
627
628         HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
629         ts.add( writeTemps[0] );
630
631         vstTable.add( new VariableSourceToken( ts,
632                                                currentSESE, 
633                                                new Integer( 0 ), 
634                                                writeTemps[0]
635                                                )
636                       );
637       }
638
639       vstTable.assertConsistency();
640     } break;
641
642     } // end switch
643   }
644
645
646   private void notAvailableForward(FlatMethod fm) {
647
648     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
649     flatNodesToVisit.add(fm);
650
651     while (!flatNodesToVisit.isEmpty()) {
652       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
653       flatNodesToVisit.remove(fn);
654
655       Set<TempDescriptor> prev = notAvailableResults.get(fn);
656
657       Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
658       for (int i = 0; i < fn.numPrev(); i++) {
659         FlatNode nn = fn.getPrev(i);
660         Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
661         if (notAvailIn != null) {
662           curr.addAll(notAvailIn);
663         }
664       }
665
666       FlatSESEEnterNode currentSESE = rblockRel.getLocalInnerRBlock( fn );
667       if( currentSESE == null ) {
668         currentSESE = rblockRel.getCallerProxySESE();
669       }
670
671       notAvailable_nodeActions(fn, curr, currentSESE);
672
673       // if a new result, schedule forward nodes for analysis
674       if (!curr.equals(prev)) {
675         notAvailableResults.put(fn, curr);
676
677         for (int i = 0; i < fn.numNext(); i++) {
678           FlatNode nn = fn.getNext(i);
679           flatNodesToVisit.add(nn);
680         }
681       }
682     }
683   }
684
685   private void notAvailable_nodeActions(FlatNode            fn, 
686                                         Set<TempDescriptor> notAvailSet,
687                                         FlatSESEEnterNode   currentSESE
688                                         ) {
689
690     // any temps that are removed from the not available set
691     // at this node should be marked in this node's code plan
692     // as temps to be grabbed at runtime!
693
694     switch (fn.kind()) {
695
696     case FKind.FlatSESEEnterNode: {
697       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
698
699       // keep a copy of what's not available into the SESE
700       // and restore it at the matching exit node
701       Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
702       Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
703       while (tdItr.hasNext()) {
704         notAvailCopy.add(tdItr.next());
705       }
706       notAvailableIntoSESE.put(fsen, notAvailCopy);
707
708       notAvailSet.clear();
709     } break;
710
711     case FKind.FlatSESEExitNode: {
712       FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
713       FlatSESEEnterNode fsen = fsexn.getFlatEnter();
714
715       notAvailSet.addAll(fsen.getOutVarSet());
716
717       Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
718       assert notAvailIn != null;
719       notAvailSet.addAll(notAvailIn);
720     } break;
721
722     case FKind.FlatMethod: {
723       notAvailSet.clear();
724     } break;
725
726     case FKind.FlatOpNode: {
727       FlatOpNode fon = (FlatOpNode) fn;
728
729       if (fon.getOp().getOp() == Operation.ASSIGN) {
730         TempDescriptor lhs = fon.getDest();
731         TempDescriptor rhs = fon.getLeft();
732
733         // copy makes lhs same availability as rhs
734         if (notAvailSet.contains(rhs)) {
735           notAvailSet.add(lhs);
736         } else {
737           notAvailSet.remove(lhs);
738         }
739
740         // only break if this is an ASSIGN op node,
741         // otherwise fall through to default case
742         break;
743       }
744     }
745
746       // note that FlatOpNode's that aren't ASSIGN
747       // fall through to this default case
748     default: {
749       TempDescriptor[] writeTemps = fn.writesTemps();
750       for (int i = 0; i < writeTemps.length; i++) {
751         TempDescriptor wTemp = writeTemps[i];
752         notAvailSet.remove(wTemp);
753       }
754       TempDescriptor[] readTemps = fn.readsTemps();
755       for (int i = 0; i < readTemps.length; i++) {
756         TempDescriptor rTemp = readTemps[i];
757         notAvailSet.remove(rTemp);
758
759         // if this variable has exactly one source, potentially
760         // get other things from this source as well
761         VarSrcTokTable vstTable = variableResults.get(fn);
762
763         VSTWrapper vstIfStatic = new VSTWrapper();
764         Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
765
766         if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
767
768           VariableSourceToken vst = vstIfStatic.vst;
769
770           Iterator<VariableSourceToken> availItr =
771               vstTable.get(vst.getSESE(), vst.getAge()).iterator();
772
773           // look through things that are also available from same source
774           while (availItr.hasNext()) {
775             VariableSourceToken vstAlsoAvail = availItr.next();
776
777             Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
778             while (refVarItr.hasNext()) {
779               TempDescriptor refVarAlso = refVarItr.next();
780
781               // if a variable is available from the same source, AND it ALSO
782               // only comes from one statically known source, mark it available
783               VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
784               Integer srcTypeAlso =
785                   vstTable.getRefVarSrcType(refVarAlso, currentSESE, vstIfStaticNotUsed);
786               if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
787                 notAvailSet.remove(refVarAlso);
788               }
789             }
790           }
791         }
792       }
793     } break;
794
795     } // end switch
796   }
797
798
799   private void codePlansForward(FlatMethod fm) {
800
801     // start from flat method top, visit every node in
802     // method exactly once
803     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
804     flatNodesToVisit.add(fm);
805
806     Set<FlatNode> visited = new HashSet<FlatNode>();
807
808     while (!flatNodesToVisit.isEmpty()) {
809       Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
810       FlatNode fn = fnItr.next();
811
812       flatNodesToVisit.remove(fn);
813       visited.add(fn);
814
815       // use incoming results as "dot statement" or just
816       // before the current statement
817       VarSrcTokTable dotSTtable = new VarSrcTokTable();
818       for (int i = 0; i < fn.numPrev(); i++) {
819         FlatNode nn = fn.getPrev(i);
820         dotSTtable.merge(variableResults.get(nn));
821       }
822
823       // find dt-st notAvailableSet also
824       Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
825       for (int i = 0; i < fn.numPrev(); i++) {
826         FlatNode nn = fn.getPrev(i);
827         Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
828         if (notAvailIn != null) {
829           dotSTnotAvailSet.addAll(notAvailIn);
830         }
831       }
832
833       Set<TempDescriptor> dotSTlive = livenessGlobalView.get(fn);
834
835       FlatSESEEnterNode currentSESE = rblockRel.getLocalInnerRBlock( fn );
836       if( currentSESE == null ) {
837         currentSESE = rblockRel.getCallerProxySESE();
838       }
839
840       codePlans_nodeActions(fm, fn, 
841                             dotSTlive, dotSTtable, dotSTnotAvailSet, 
842                             currentSESE);
843
844       for (int i = 0; i < fn.numNext(); i++) {
845         FlatNode nn = fn.getNext(i);
846
847         if (!visited.contains(nn)) {
848           flatNodesToVisit.add(nn);
849         }
850       }
851     }
852   }
853       
854   private void codePlans_nodeActions(FlatMethod fm,
855                                      FlatNode fn,
856                                      Set<TempDescriptor> liveSetIn,
857                                      VarSrcTokTable vstTableIn, 
858                                      Set<TempDescriptor> notAvailSetIn, 
859                                      FlatSESEEnterNode currentSESE) {
860
861     CodePlan plan = new CodePlan(currentSESE);
862
863     switch (fn.kind()) {
864
865     case FKind.FlatSESEEnterNode: {
866       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
867
868       // track the source types of the in-var set so generated
869       // code at this SESE issue can compute the number of
870       // dependencies properly
871       Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
872       while (inVarItr.hasNext()) {
873         TempDescriptor inVar = inVarItr.next();
874
875         // when we get to an SESE enter node we change the
876         // currentSESE variable of this analysis to the
877         // child that is declared by the enter node, so
878         // in order to classify in-vars correctly, pass
879         // the parent SESE in--at other FlatNode types just
880         // use the currentSESE
881         FlatSESEEnterNode parent = rblockRel.getLocalInnerRBlock( fn );
882         if( parent == null ) {
883           parent = rblockRel.getCallerProxySESE();
884         }
885                 
886         VSTWrapper vstIfStatic = new VSTWrapper();
887         Integer srcType = vstTableIn.getRefVarSrcType(inVar, parent, vstIfStatic);
888
889         // the current SESE needs a local space to track the dynamic
890         // variable and the child needs space in its SESE record
891         if (srcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
892           fsen.addDynamicInVar(inVar);
893           addDynamicVar( fsen, fm, inVar );
894
895         } else if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
896           fsen.addStaticInVar(inVar);
897           VariableSourceToken vst = vstIfStatic.vst;
898           fsen.putStaticInVar2src(inVar, vst);
899           fsen.addStaticInVarSrc(new SESEandAgePair(vst.getSESE(), vst.getAge()));
900         } else {
901           assert srcType.equals(VarSrcTokTable.SrcType_READY);
902           fsen.addReadyInVar(inVar);
903         }
904       }
905     } break;
906
907     case FKind.FlatSESEExitNode: {
908       FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
909       //TODO! Shouldn't there be a code plan for task exit
910       // where the exiting task calculates whether its own
911       // siblings need variables from its children, so the
912       // exiter should copy those variables into its own out-set
913       // and make the available?
914     } break;
915
916     case FKind.FlatOpNode: {
917       FlatOpNode fon = (FlatOpNode) fn;
918
919       if (fon.getOp().getOp() == Operation.ASSIGN) {
920         TempDescriptor lhs = fon.getDest();
921         TempDescriptor rhs = fon.getLeft();
922
923         // if this is an op node, don't stall, copy
924         // source and delay until we need to use value
925
926         // ask whether lhs and rhs sources are dynamic, static, etc.
927         VSTWrapper vstIfStatic = new VSTWrapper();
928         Integer lhsSrcType = vstTableIn.getRefVarSrcType(lhs, currentSESE, vstIfStatic);
929         Integer rhsSrcType = vstTableIn.getRefVarSrcType(rhs, currentSESE, vstIfStatic);
930
931         if (rhsSrcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
932           // if rhs is dynamic going in, lhs will definitely be dynamic
933           // going out of this node, so track that here
934           plan.addDynAssign( lhs, rhs );
935           addDynamicVar( currentSESE, fm, lhs );
936           addDynamicVar( currentSESE, fm, rhs );
937
938         } else if (lhsSrcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
939           // otherwise, if the lhs is dynamic, but the rhs is not, we
940           // need to update the variable's dynamic source as "current SESE"
941           plan.addDynAssign(lhs);
942         }
943
944         // only break if this is an ASSIGN op node,
945         // otherwise fall through to default case
946         break;
947       }
948     }
949
950       // note that FlatOpNode's that aren't ASSIGN
951       // fall through to this default case
952     default: {
953
954       // a node with no live set has nothing to stall for
955       if (liveSetIn == null) {
956         break;
957       }
958
959       TempDescriptor[] readarray = fn.readsTemps();
960       for (int i = 0; i < readarray.length; i++) {
961         TempDescriptor readtmp = readarray[i];
962
963         // ignore temps that are definitely available
964         // when considering to stall on it
965         if (!notAvailSetIn.contains(readtmp)) {
966           continue;
967         }
968
969         // check the source type of this variable
970         VSTWrapper vstIfStatic = new VSTWrapper();
971         Integer srcType = vstTableIn.getRefVarSrcType(readtmp, currentSESE, vstIfStatic);
972
973         if (srcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
974           // 1) It is not clear statically where this variable will
975           // come from, so dynamically we must keep track
976           // along various control paths, and therefore when we stall,
977           // just stall for the exact thing we need and move on
978           plan.addDynamicStall( readtmp );
979           addDynamicVar( currentSESE, fm, readtmp );
980
981         } else if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
982           // 2) Single token/age pair: Stall for token/age pair, and copy
983           // all live variables with same token/age pair at the same
984           // time. This is the same stuff that the notavaialable analysis
985           // marks as now available.
986           VariableSourceToken vst = vstIfStatic.vst;
987
988           Iterator<VariableSourceToken> availItr =
989               vstTableIn.get(vst.getSESE(), vst.getAge()).iterator();
990
991           while (availItr.hasNext()) {
992             VariableSourceToken vstAlsoAvail = availItr.next();
993
994             // only grab additional stuff that is live
995             Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
996
997             Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
998             while (refVarItr.hasNext()) {
999               TempDescriptor refVar = refVarItr.next();
1000               if (liveSetIn.contains(refVar)) {
1001                 copySet.add(refVar);
1002               }
1003             }
1004
1005             if (!copySet.isEmpty()) {
1006               plan.addStall2CopySet(vstAlsoAvail, copySet);
1007             }
1008           }
1009
1010         } else {
1011           // the other case for srcs is READY, so do nothing
1012         }
1013
1014         // assert that everything being stalled for is in the
1015         // "not available" set coming into this flat node and
1016         // that every VST identified is in the possible "stall set"
1017         // that represents VST's from children SESE's
1018
1019       }
1020     }
1021       break;
1022
1023     } // end switch
1024
1025     // identify sese-age pairs that are statically useful
1026     // and should have an associated SESE variable in code
1027     // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
1028     // AND ALWAYS GIVE NAMES TO LOCAL PARENTS
1029     Set<VariableSourceToken> staticSet = vstTableIn.get();
1030     Iterator<VariableSourceToken> vstItr = staticSet.iterator();
1031     while (vstItr.hasNext()) {
1032       VariableSourceToken vst = vstItr.next();
1033
1034       // the caller proxy generates useful analysis facts, but we
1035       // never need to generate another name for it in code (it is
1036       // ALWAYS the task executing the local method context)
1037       if( vst.getSESE().getIsCallerProxySESE() ) {
1038         continue;
1039       }
1040
1041       SESEandAgePair sap = new SESEandAgePair( vst.getSESE(), vst.getAge() );
1042       sap.getSESE().mustTrackAtLeastAge( sap.getAge() );
1043
1044       FlatSESEEnterNode sese = currentSESE;
1045       while( sese != null ) {
1046         addNeededStaticName( sese, fm, sap );      
1047         sese = sese.getLocalParent();
1048       }
1049     }
1050
1051     codePlans.put(fn, plan);
1052
1053     // if any variables at this-node-*dot* have a static source (exactly one
1054     // vst)
1055     // but go to a dynamic source at next-node-*dot*, create a new IR graph
1056     // node on that edge to track the sources dynamically
1057     VarSrcTokTable thisVstTable = variableResults.get(fn);
1058     for (int i = 0; i < fn.numNext(); i++) {
1059       FlatNode nn = fn.getNext(i);
1060       VarSrcTokTable nextVstTable = variableResults.get(nn);
1061       Set<TempDescriptor> nextLiveIn = livenessGlobalView.get(nn);
1062
1063       // the table can be null if it is one of the few IR nodes
1064       // completely outside of the root SESE scope
1065       if (nextVstTable != null && nextLiveIn != null) {
1066
1067         Hashtable<TempDescriptor, VSTWrapper> readyOrStatic2dynamicSet =
1068             thisVstTable.getReadyOrStatic2DynamicSet(nextVstTable, nextLiveIn, currentSESE);
1069
1070         if (!readyOrStatic2dynamicSet.isEmpty()) {
1071
1072           // either add these results to partial fixed-point result
1073           // or make a new one if we haven't made any here yet
1074           FlatEdge fe = new FlatEdge(fn, nn);
1075           FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get(fe);
1076
1077           if (fwdvn == null) {
1078             fwdvn = new FlatWriteDynamicVarNode(fn, nn, readyOrStatic2dynamicSet, currentSESE);
1079             wdvNodesToSpliceIn.put(fe, fwdvn);
1080           } else {
1081             fwdvn.addMoreVar2Src(readyOrStatic2dynamicSet);
1082           }
1083         }
1084       }
1085     }
1086   }
1087
1088   private void addDynamicVar( FlatSESEEnterNode fsen, 
1089                               FlatMethod        fm, 
1090                               TempDescriptor    var ) {
1091     FlatNode fnContext;
1092
1093     if( fsen.getIsCallerProxySESE() ) {
1094       // attach the dynamic variable to track to
1095       // the flat method, so it can be declared at entry
1096       fnContext = fm;
1097     } else {
1098       // otherwise the code context is a task body
1099       fnContext = fsen;
1100     }
1101
1102     ContextTaskNames ctn = fn2contextTaskNames.get( fnContext );
1103     if( ctn == null ) {
1104       ctn = new ContextTaskNames();
1105     }
1106
1107     ctn.addDynamicVar( var );
1108     fn2contextTaskNames.put( fnContext, ctn );
1109   }
1110
1111   private void addNeededStaticName( FlatSESEEnterNode fsen, 
1112                                     FlatMethod        fm, 
1113                                     SESEandAgePair    sap ) {
1114     FlatNode fnContext;
1115
1116     if( fsen.getIsCallerProxySESE() ) {
1117       // attach the dynamic variable to track to
1118       // the flat method, so it can be declared at entry
1119       fnContext = fm;
1120     } else {
1121       // otherwise the code context is a task body
1122       fnContext = fsen;
1123     }
1124
1125     ContextTaskNames ctn = fn2contextTaskNames.get( fnContext );
1126     if( ctn == null ) {
1127       ctn = new ContextTaskNames();
1128     }
1129
1130     ctn.addNeededStaticName( sap );
1131
1132     fn2contextTaskNames.put( fnContext, ctn );
1133   }
1134
1135
1136   private void makeConflictGraph(FlatMethod fm) {
1137
1138     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
1139     flatNodesToVisit.add(fm);
1140
1141     Set<FlatNode> visited = new HashSet<FlatNode>();
1142
1143     while (!flatNodesToVisit.isEmpty()) {
1144       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
1145       flatNodesToVisit.remove(fn);
1146       visited.add(fn);
1147
1148       Set<FlatSESEEnterNode> currentSESEs = 
1149         rblockRel.getPossibleExecutingRBlocks( fn );
1150
1151       conflictGraph_nodeAction(fn, currentSESEs);
1152
1153       // schedule forward nodes for analysis
1154       for (int i = 0; i < fn.numNext(); i++) {
1155         FlatNode nn = fn.getNext(i);
1156         if (!visited.contains(nn)) {
1157           flatNodesToVisit.add(nn);
1158         }
1159       }
1160
1161     }
1162
1163   }
1164
1165   private void conflictGraph_nodeAction(FlatNode fn, 
1166                                         Set<FlatSESEEnterNode> currentSESEs
1167                                         ) {
1168     ConflictGraph conflictGraph;
1169     TempDescriptor lhs;
1170     TempDescriptor rhs;
1171     
1172     EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
1173
1174
1175     switch (fn.kind()) {
1176
1177
1178     case FKind.FlatFieldNode:
1179     case FKind.FlatElementNode: {
1180
1181       if (fn instanceof FlatFieldNode) {
1182         FlatFieldNode ffn = (FlatFieldNode) fn;
1183         rhs = ffn.getSrc();
1184       } else {
1185         FlatElementNode fen = (FlatElementNode) fn;
1186         rhs = fen.getSrc();
1187       }
1188
1189       for( Iterator<FlatSESEEnterNode> itr = currentSESEs.iterator();
1190            itr.hasNext();
1191            ) {
1192         FlatSESEEnterNode currentSESE = itr.next();
1193
1194         conflictGraph = sese2conflictGraph.get(currentSESE);
1195         if (conflictGraph == null) {
1196           conflictGraph = new ConflictGraph(state);
1197         }
1198
1199         // add stall site
1200         Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1201         conflictGraph.addStallSite(taint2Effects, rhs);
1202
1203         if (conflictGraph.id2cn.size() > 0) {
1204           sese2conflictGraph.put(currentSESE, conflictGraph);
1205         }
1206       }
1207     } break;
1208
1209
1210     case FKind.FlatSetFieldNode:
1211     case FKind.FlatSetElementNode: {
1212
1213       if (fn instanceof FlatSetFieldNode) {
1214         FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
1215         lhs = fsfn.getDst();
1216         rhs = fsfn.getSrc();
1217       } else {
1218         FlatSetElementNode fsen = (FlatSetElementNode) fn;
1219         lhs = fsen.getDst();
1220         rhs = fsen.getSrc();
1221       }
1222
1223       for( Iterator<FlatSESEEnterNode> itr = currentSESEs.iterator();
1224            itr.hasNext();
1225            ) {
1226         FlatSESEEnterNode currentSESE = itr.next();
1227
1228         conflictGraph = sese2conflictGraph.get(currentSESE);
1229         if (conflictGraph == null) {
1230           conflictGraph = new ConflictGraph(state);
1231         }
1232
1233         Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1234         conflictGraph.addStallSite(taint2Effects, rhs);
1235         conflictGraph.addStallSite(taint2Effects, lhs);
1236
1237         if (conflictGraph.id2cn.size() > 0) {
1238           sese2conflictGraph.put(currentSESE, conflictGraph);
1239         }
1240       }
1241     } break;
1242
1243
1244     case FKind.FlatCall: {
1245       FlatCall fc = (FlatCall) fn;
1246       lhs = fc.getThis();
1247
1248       for( Iterator<FlatSESEEnterNode> itr = currentSESEs.iterator();
1249            itr.hasNext();
1250            ) {
1251         FlatSESEEnterNode currentSESE = itr.next();
1252
1253         conflictGraph = sese2conflictGraph.get(currentSESE);
1254         if (conflictGraph == null) {
1255           conflictGraph = new ConflictGraph(state);
1256         }
1257
1258         // collects effects of stall site and generates stall site node
1259         Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
1260
1261         conflictGraph.addStallSite(taint2Effects, lhs);
1262         if (conflictGraph.id2cn.size() > 0) {
1263           sese2conflictGraph.put(currentSESE, conflictGraph);
1264         }          
1265       }
1266     } break;
1267
1268     }
1269   }
1270
1271
1272   private void calculateConflicts( Set<FlatNew> sitesToFlag, 
1273                                    boolean      useReachInfo ) {
1274
1275     // decide fine-grain edge or coarse-grain edge among all vertexes by
1276     // pair-wise comparison
1277     Iterator<FlatNode> seseIter = sese2conflictGraph.keySet().iterator();
1278     while (seseIter.hasNext()) {
1279       FlatSESEEnterNode sese = (FlatSESEEnterNode) seseIter.next();
1280       ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
1281
1282       if (useReachInfo) {
1283         // clear current conflict before recalculating with reachability info
1284         conflictGraph.clearAllConflictEdge();
1285         conflictGraph.setDisJointAnalysis(disjointAnalysisReach);
1286         conflictGraph.setFMEnclosing(sese.getfmEnclosing());
1287       }
1288       conflictGraph.analyzeConflicts(sitesToFlag, useReachInfo);
1289       sese2conflictGraph.put(sese, conflictGraph);
1290     }
1291   }
1292
1293
1294   private void writeConflictGraph() {
1295     Enumeration<FlatNode> keyEnum = sese2conflictGraph.keys();
1296     while (keyEnum.hasMoreElements()) {
1297       FlatNode key = (FlatNode) keyEnum.nextElement();
1298       ConflictGraph cg = sese2conflictGraph.get(key);
1299       try {
1300         if (cg.hasConflictEdge()) {
1301           cg.writeGraph("ConflictGraphFor" + key, false);
1302         }
1303       } catch (IOException e) {
1304         System.out.println("Error writing");
1305         System.exit(0);
1306       }
1307     }
1308   }
1309
1310   private void synthesizeLocks() {
1311     Set<Entry<FlatNode, ConflictGraph>> graphEntrySet = sese2conflictGraph.entrySet();
1312     for (Iterator iterator = graphEntrySet.iterator(); iterator.hasNext();) {
1313       Entry<FlatNode, ConflictGraph> graphEntry = (Entry<FlatNode, ConflictGraph>) iterator.next();
1314       FlatNode sese = graphEntry.getKey();
1315       ConflictGraph conflictGraph = graphEntry.getValue();
1316       calculateCovering(conflictGraph);
1317     }
1318   }
1319
1320   private void calculateCovering(ConflictGraph conflictGraph) {
1321     uniqueLockSetId = 0; // reset lock counter for every new conflict graph
1322     HashSet<ConflictEdge> fineToCover = new HashSet<ConflictEdge>();
1323     HashSet<ConflictEdge> coarseToCover = new HashSet<ConflictEdge>();
1324     HashSet<SESELock> lockSet = new HashSet<SESELock>();
1325
1326     Set<ConflictEdge> tempCover = conflictGraph.getEdgeSet();
1327     for (Iterator iterator = tempCover.iterator(); iterator.hasNext();) {
1328       ConflictEdge conflictEdge = (ConflictEdge) iterator.next();
1329       if (conflictEdge.isCoarseEdge()) {
1330         coarseToCover.add(conflictEdge);
1331       } else {
1332         fineToCover.add(conflictEdge);
1333       }
1334     }
1335
1336     HashSet<ConflictEdge> toCover = new HashSet<ConflictEdge>();
1337     toCover.addAll(fineToCover);
1338     toCover.addAll(coarseToCover);
1339
1340     while (!toCover.isEmpty()) {
1341
1342       SESELock seseLock = new SESELock();
1343       seseLock.setID(uniqueLockSetId++);
1344
1345       boolean changed;
1346
1347       do { // fine-grained edge
1348
1349         changed = false;
1350
1351         for (Iterator iterator = fineToCover.iterator(); iterator.hasNext();) {
1352
1353           int type;
1354           ConflictEdge edge = (ConflictEdge) iterator.next();
1355           if (seseLock.getConflictNodeSet().size() == 0) {
1356             // initial setup
1357             if (seseLock.isWriteNode(edge.getVertexU())) {
1358               // mark as fine_write
1359               if (edge.getVertexU().isStallSiteNode()) {
1360                 type = ConflictNode.PARENT_WRITE;
1361               } else {
1362                 type = ConflictNode.FINE_WRITE;
1363               }
1364               seseLock.addConflictNode(edge.getVertexU(), type);
1365             } else {
1366               // mark as fine_read
1367               if (edge.getVertexU().isStallSiteNode()) {
1368                 type = ConflictNode.PARENT_READ;
1369               } else {
1370                 type = ConflictNode.FINE_READ;
1371               }
1372               seseLock.addConflictNode(edge.getVertexU(), type);
1373             }
1374             if (edge.getVertexV() != edge.getVertexU()) {
1375               if (seseLock.isWriteNode(edge.getVertexV())) {
1376                 // mark as fine_write
1377                 if (edge.getVertexV().isStallSiteNode()) {
1378                   type = ConflictNode.PARENT_WRITE;
1379                 } else {
1380                   type = ConflictNode.FINE_WRITE;
1381                 }
1382                 seseLock.addConflictNode(edge.getVertexV(), type);
1383               } else {
1384                 // mark as fine_read
1385                 if (edge.getVertexV().isStallSiteNode()) {
1386                   type = ConflictNode.PARENT_READ;
1387                 } else {
1388                   type = ConflictNode.FINE_READ;
1389                 }
1390                 seseLock.addConflictNode(edge.getVertexV(), type);
1391               }
1392             }
1393             changed = true;
1394             seseLock.addConflictEdge(edge);
1395             fineToCover.remove(edge);
1396             break;// exit iterator loop
1397           }// end of initial setup
1398
1399           ConflictNode newNode;
1400           if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1401             // new node has a fine-grained edge to all current node
1402             // If there is a coarse grained edge where need a fine edge, it's
1403             // okay to add the node
1404             // but the edge must remain uncovered.
1405
1406             changed = true;
1407
1408             if (seseLock.containsConflictNode(newNode)) {
1409               seseLock.addEdge(edge);
1410               fineToCover.remove(edge);
1411               break;
1412             }
1413
1414             if (seseLock.isWriteNode(newNode)) {
1415               if (newNode.isStallSiteNode()) {
1416                 type = ConflictNode.PARENT_WRITE;
1417               } else {
1418                 type = ConflictNode.FINE_WRITE;
1419               }
1420               seseLock.setNodeType(newNode, type);
1421             } else {
1422               if (newNode.isStallSiteNode()) {
1423                 type = ConflictNode.PARENT_READ;
1424               } else {
1425                 type = ConflictNode.FINE_READ;
1426               }
1427               seseLock.setNodeType(newNode, type);
1428             }
1429
1430             seseLock.addEdge(edge);
1431             Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1432             for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1433               ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1434
1435               // mark all fine edges between new node and nodes in the group as
1436               // covered
1437               if (!conflictEdge.getVertexU().equals(newNode)) {
1438                 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1439                   changed = true;
1440                   seseLock.addConflictEdge(conflictEdge);
1441                   fineToCover.remove(conflictEdge);
1442                 }
1443               } else if (!conflictEdge.getVertexV().equals(newNode)) {
1444                 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1445                   changed = true;
1446                   seseLock.addConflictEdge(conflictEdge);
1447                   fineToCover.remove(conflictEdge);
1448                 }
1449               }
1450
1451             }
1452
1453             break;// exit iterator loop
1454           }
1455         }
1456
1457       } while (changed);
1458       HashSet<ConflictEdge> notCovered=new HashSet<ConflictEdge>();
1459       do { // coarse
1460         changed = false;
1461         int type;
1462         for (Iterator iterator = coarseToCover.iterator(); iterator.hasNext();) {
1463
1464           ConflictEdge edge = (ConflictEdge) iterator.next();
1465           if (seseLock.getConflictNodeSet().size() == 0) {
1466             // initial setup
1467             if (seseLock.hasSelfCoarseEdge(edge.getVertexU())) {
1468               // node has a coarse-grained edge with itself
1469               if (!(edge.getVertexU().isStallSiteNode())) {
1470                 // and it is not parent
1471                 type = ConflictNode.SCC;
1472               } else {
1473                 if(state.RCR){
1474                   type = ConflictNode.PARENT_COARSE;
1475                 }else{
1476                   type = ConflictNode.PARENT_WRITE;
1477                 }
1478               }
1479               seseLock.addConflictNode(edge.getVertexU(), type);
1480             } else {
1481               if (edge.getVertexU().isStallSiteNode()) {
1482                 if(state.RCR){
1483                   type = ConflictNode.PARENT_COARSE;
1484                 }else{
1485                   if (edge.getVertexU().getWriteEffectSet().isEmpty()) {
1486                     type = ConflictNode.PARENT_READ;
1487                   } else {
1488                     type = ConflictNode.PARENT_WRITE;
1489                   }
1490                 }
1491               } else {
1492                 type = ConflictNode.COARSE;
1493               }
1494               seseLock.addConflictNode(edge.getVertexU(), type);
1495             }
1496             if (seseLock.hasSelfCoarseEdge(edge.getVertexV())) {
1497               // node has a coarse-grained edge with itself
1498               if (!(edge.getVertexV().isStallSiteNode())) {
1499                 // and it is not parent
1500                 type = ConflictNode.SCC;
1501               } else {
1502                 if(state.RCR){
1503                   type = ConflictNode.PARENT_COARSE;
1504                 }else{
1505                   type = ConflictNode.PARENT_WRITE;
1506                 }
1507               }
1508               seseLock.addConflictNode(edge.getVertexV(), type);
1509             } else {
1510               if (edge.getVertexV().isStallSiteNode()) {
1511                 if(state.RCR){
1512                   type = ConflictNode.PARENT_COARSE;
1513                 }else{
1514                   if (edge.getVertexV().getWriteEffectSet().isEmpty()) {
1515                     type = ConflictNode.PARENT_READ;
1516                   } else {
1517                     type = ConflictNode.PARENT_WRITE;
1518                   }
1519                 }
1520               } else {
1521                 type = ConflictNode.COARSE;
1522               }
1523               seseLock.addConflictNode(edge.getVertexV(), type);
1524             }
1525             changed = true;
1526             coarseToCover.remove(edge);
1527             seseLock.addConflictEdge(edge);
1528             break;// exit iterator loop
1529           }// end of initial setup
1530
1531           ConflictNode newNode;
1532           if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
1533             // new node has a coarse-grained edge to all fine-read, fine-write,
1534             // parent
1535             changed = true;
1536             
1537             if (newNode.isInVarNode() && (!seseLock.hasSelfCoarseEdge(newNode))
1538                 && seseLock.hasCoarseEdgeWithParentCoarse(newNode)) {
1539               // this case can't be covered by this queue
1540               coarseToCover.remove(edge);
1541               notCovered.add(edge);
1542               break;
1543             }
1544
1545             if (seseLock.containsConflictNode(newNode)) {
1546               seseLock.addEdge(edge);
1547               coarseToCover.remove(edge);
1548               break;
1549             }
1550             
1551             if (seseLock.hasSelfCoarseEdge(newNode)) {
1552               // SCC
1553               if (newNode.isStallSiteNode()) {
1554                 type = ConflictNode.PARENT_COARSE;
1555               } else {
1556                 type = ConflictNode.SCC;
1557               }
1558               seseLock.setNodeType(newNode, type);
1559             } else {
1560               if (newNode.isStallSiteNode()) {
1561                 type = ConflictNode.PARENT_COARSE;
1562               } else {
1563                 type = ConflictNode.COARSE;
1564               }
1565               seseLock.setNodeType(newNode, type);
1566             }
1567
1568             seseLock.addEdge(edge);
1569             Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
1570             for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
1571               ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
1572               // mark all coarse edges between new node and nodes in the group
1573               // as covered
1574               if (!conflictEdge.getVertexU().equals(newNode)) {
1575                 if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
1576                   changed = true;
1577                   seseLock.addConflictEdge(conflictEdge);
1578                   coarseToCover.remove(conflictEdge);
1579                 }
1580               } else if (!conflictEdge.getVertexV().equals(newNode)) {
1581                 if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
1582                   changed = true;
1583                   seseLock.addConflictEdge(conflictEdge);
1584                   coarseToCover.remove(conflictEdge);
1585                 }
1586               }
1587
1588             }
1589             break;// exit iterator loop
1590           }
1591
1592         }
1593
1594       } while (changed);
1595       lockSet.add(seseLock);
1596
1597       toCover.clear();
1598       coarseToCover.addAll(notCovered);
1599       toCover.addAll(fineToCover);
1600       toCover.addAll(coarseToCover);
1601
1602     }
1603
1604     conflictGraph2SESELock.put(conflictGraph, lockSet);
1605   }
1606
1607   public ConflictGraph getConflictGraph(FlatNode sese) {
1608     return sese2conflictGraph.get(sese);
1609   }
1610
1611   public Set<SESELock> getLockMappings(ConflictGraph graph) {
1612     return conflictGraph2SESELock.get(graph);
1613   }
1614
1615   public Set<FlatSESEEnterNode> getAllSESEs() {
1616     return rblockRel.getAllSESEs();
1617   }
1618
1619   public FlatSESEEnterNode getMainSESE() {
1620     return rblockRel.getMainSESE();
1621   }
1622
1623   public FlatSESEEnterNode getCallerProxySESE() {
1624     return rblockRel.getCallerProxySESE();
1625   }
1626
1627
1628   public void writeReports(String timeReport) throws java.io.IOException {
1629
1630     BufferedWriter bw = new BufferedWriter(new FileWriter("ooojReport_summary.txt"));
1631     bw.write("OoOJava Analysis Results\n\n");
1632     bw.write(timeReport + "\n\n");
1633     printSESEHierarchy(bw);
1634     bw.write("\n");
1635     printSESEInfo(bw);
1636     bw.close();
1637
1638     Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
1639     while (methItr.hasNext()) {
1640       MethodDescriptor md = methItr.next();
1641       FlatMethod fm = state.getMethodFlat(md);
1642       if (fm != null) {
1643         bw = new BufferedWriter(new FileWriter("ooojReport_" + 
1644                                                md.getClassMethodName() +
1645                                                md.getSafeMethodDescriptor() + 
1646                                                ".txt"));
1647         bw.write("OoOJava Results for " + md + "\n-------------------\n");
1648
1649         bw.write("Dynamic vars to manage:\n  " + getContextTaskNames( fm ).getDynamicVarSet() );
1650
1651         bw.write("\n\nLive-In, Root View\n------------------\n" + fm.printMethod(livenessGlobalView));
1652         bw.write("\n\nVariable Results-Out\n----------------\n" + fm.printMethod(variableResults));
1653         bw.write("\n\nNot Available Results-Out\n---------------------\n" + fm.printMethod(notAvailableResults));
1654         bw.write("\n\nCode Plans\n----------\n" + fm.printMethod(codePlans));
1655         bw.close();
1656       }
1657     }
1658   }
1659
1660   private void printSESEHierarchy(BufferedWriter bw) throws java.io.IOException {
1661     bw.write("SESE Local Hierarchy\n--------------\n");
1662     Iterator<FlatSESEEnterNode> rootItr = rblockRel.getLocalRootSESEs().iterator();
1663     while (rootItr.hasNext()) {
1664       FlatSESEEnterNode root = rootItr.next();
1665       printSESEHierarchyTree(bw, root, 0);      
1666     }
1667   }
1668
1669   private void printSESEHierarchyTree(BufferedWriter    bw, 
1670                                       FlatSESEEnterNode fsen, 
1671                                       int               depth
1672                                       ) throws java.io.IOException {
1673     for (int i = 0; i < depth; ++i) {
1674       bw.write("  ");
1675     }
1676     bw.write("- " + fsen.getPrettyIdentifier() + "\n");
1677
1678     Iterator<FlatSESEEnterNode> childItr = fsen.getLocalChildren().iterator();
1679     while (childItr.hasNext()) {
1680       FlatSESEEnterNode fsenChild = childItr.next();
1681       printSESEHierarchyTree(bw, fsenChild, depth + 1);
1682     }
1683   }
1684
1685   private void printSESEInfo(BufferedWriter bw) throws java.io.IOException {
1686     bw.write("\nSESE info\n-------------\n");
1687     Iterator<FlatSESEEnterNode> fsenItr = rblockRel.getAllSESEs().iterator();
1688     while( fsenItr.hasNext() ) {
1689       FlatSESEEnterNode fsen = fsenItr.next();
1690
1691       bw.write("SESE " + fsen.getPrettyIdentifier());
1692       if( fsen.getIsLeafSESE() ) {
1693         bw.write(" (leaf)");
1694       }
1695       bw.write(" {\n");
1696
1697       bw.write("  in-set: " + fsen.getInVarSet() + "\n");
1698       Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
1699       while (tItr.hasNext()) {
1700         TempDescriptor inVar = tItr.next();
1701         if (fsen.getReadyInVarSet().contains(inVar)) {
1702           bw.write("    (ready)  " + inVar + "\n");
1703         }
1704         if (fsen.getStaticInVarSet().contains(inVar)) {
1705           bw.write("    (static) " + inVar + " from " + fsen.getStaticInVarSrc(inVar) + "\n");
1706         }
1707         if (fsen.getDynamicInVarSet().contains(inVar)) {
1708           bw.write("    (dynamic)" + inVar + "\n");
1709         }
1710       }
1711
1712       bw.write("   Dynamic vars to manage: " + getContextTaskNames( fsen ).getDynamicVarSet() + "\n");
1713
1714       bw.write("  out-set: " + fsen.getOutVarSet() + "\n");
1715
1716       bw.write("  local parent:   " + fsen.getLocalParent() + "\n");
1717       bw.write("  local children: " + fsen.getLocalChildren() + "\n");
1718
1719       bw.write("  possible parents:  " + fsen.getParents() + "\n");
1720       bw.write("  possible children: " + fsen.getChildren() + "\n");
1721
1722       bw.write("}\n");
1723     }
1724   }
1725 }