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