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