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