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