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