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