8b79cd9c910ed8109378769b095f98f8f93f3a50
[IRC.git] / Robust / src / Analysis / MLP / MLPAnalysis.java
1 package Analysis.MLP;
2
3 import Analysis.CallGraph.*;
4 import Analysis.OwnershipAnalysis.*;
5 import IR.*;
6 import IR.Flat.*;
7 import IR.Tree.*;
8 import java.util.*;
9 import java.io.*;
10
11
12 public class MLPAnalysis {
13
14   // data from the compiler
15   private State             state;
16   private TypeUtil          typeUtil;
17   private CallGraph         callGraph;
18   private OwnershipAnalysis ownAnalysis;
19
20
21   // an implicit SESE is automatically spliced into
22   // the IR graph around the C main before this analysis--it
23   // is nothing special except that we can make assumptions
24   // about it, such as the whole program ends when it ends
25   private FlatSESEEnterNode mainSESE;
26
27   // SESEs that are the root of an SESE tree belong to this
28   // set--the main SESE is always a root, statically SESEs
29   // inside methods are a root because we don't know how they
30   // will fit into the runtime tree of SESEs
31   private Set<FlatSESEEnterNode> rootSESEs;
32
33   // simply a set of every reachable SESE in the program, not
34   // including caller placeholder SESEs
35   private Set<FlatSESEEnterNode> allSESEs;
36
37
38   // A mapping of flat nodes to the stack of SESEs for that node, where
39   // an SESE is the child of the SESE directly below it on the stack.
40   // These stacks do not reflect the heirarchy over methods calls--whenever
41   // there is an empty stack it means all variables are available.
42   private Hashtable< FlatNode, Stack<FlatSESEEnterNode> > seseStacks;
43
44   private Hashtable< FlatNode, Set<TempDescriptor>      > livenessRootView;
45   private Hashtable< FlatNode, Set<TempDescriptor>      > livenessVirtualReads;
46   private Hashtable< FlatNode, VarSrcTokTable           > variableResults;
47   private Hashtable< FlatNode, Set<TempDescriptor>      > notAvailableResults;
48   private Hashtable< FlatNode, CodePlan                 > codePlans;
49
50   private Hashtable< FlatEdge, FlatWriteDynamicVarNode  > wdvNodesToSpliceIn;
51   
52   private Hashtable< MethodContext, HashSet<AllocationSite>> mapMethodContextToLiveInAllocationSiteSet;
53
54   public static int maxSESEage = -1;
55
56
57   // use these methods in BuildCode to have access to analysis results
58   public FlatSESEEnterNode getMainSESE() {
59     return mainSESE;
60   }
61
62   public Set<FlatSESEEnterNode> getRootSESEs() {
63     return rootSESEs;
64   }
65
66   public Set<FlatSESEEnterNode> getAllSESEs() {
67     return allSESEs;
68   }
69
70   public int getMaxSESEage() {
71     return maxSESEage;
72   }
73
74   // may be null
75   public CodePlan getCodePlan( FlatNode fn ) {
76     CodePlan cp = codePlans.get( fn );
77     return cp;
78   }
79
80
81   public MLPAnalysis( State             state,
82                       TypeUtil          tu,
83                       CallGraph         callGraph,
84                       OwnershipAnalysis ownAnalysis
85                       ) {
86
87     double timeStartAnalysis = (double) System.nanoTime();
88
89     this.state       = state;
90     this.typeUtil    = tu;
91     this.callGraph   = callGraph;
92     this.ownAnalysis = ownAnalysis;
93     this.maxSESEage  = state.MLP_MAXSESEAGE;
94
95     rootSESEs = new HashSet<FlatSESEEnterNode>();
96     allSESEs  = new HashSet<FlatSESEEnterNode>();
97
98     seseStacks           = new Hashtable< FlatNode, Stack<FlatSESEEnterNode> >();    
99     livenessRootView     = new Hashtable< FlatNode, Set<TempDescriptor>      >();
100     livenessVirtualReads = new Hashtable< FlatNode, Set<TempDescriptor>      >();
101     variableResults      = new Hashtable< FlatNode, VarSrcTokTable           >();
102     notAvailableResults  = new Hashtable< FlatNode, Set<TempDescriptor>      >();
103     codePlans            = new Hashtable< FlatNode, CodePlan                 >();
104     wdvNodesToSpliceIn   = new Hashtable< FlatEdge, FlatWriteDynamicVarNode  >();
105     
106     mapMethodContextToLiveInAllocationSiteSet = new Hashtable< MethodContext, HashSet<AllocationSite>>();
107     
108
109     FlatMethod fmMain = state.getMethodFlat( typeUtil.getMain() );
110
111     mainSESE = (FlatSESEEnterNode) fmMain.getNext(0);    
112     mainSESE.setfmEnclosing( fmMain );
113     mainSESE.setmdEnclosing( fmMain.getMethod() );
114     mainSESE.setcdEnclosing( fmMain.getMethod().getClassDesc() );
115
116
117     // 1st pass
118     // run analysis on each method that is actually called
119     // reachability analysis already computed this so reuse
120     Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
121     while( methItr.hasNext() ) {
122       Descriptor d  = methItr.next();      
123       FlatMethod fm = state.getMethodFlat( d );
124
125       // find every SESE from methods that may be called
126       // and organize them into roots and children
127       buildForestForward( fm );
128     }
129
130
131     // 2nd pass, results are saved in FlatSESEEnterNode, so
132     // intermediate results, for safety, are discarded
133     Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
134     while( rootItr.hasNext() ) {
135       FlatSESEEnterNode root = rootItr.next();
136       livenessAnalysisBackward( root, 
137                                 true, 
138                                 null );
139     }
140
141
142     // 3rd pass
143     methItr = ownAnalysis.descriptorsToAnalyze.iterator();
144     while( methItr.hasNext() ) {
145       Descriptor d  = methItr.next();      
146       FlatMethod fm = state.getMethodFlat( d );
147
148       // starting from roots do a forward, fixed-point
149       // variable analysis for refinement and stalls
150       variableAnalysisForward( fm );
151     }
152
153     // 4th pass, compute liveness contribution from
154     // virtual reads discovered in variable pass
155     rootItr = rootSESEs.iterator();
156     while( rootItr.hasNext() ) {
157       FlatSESEEnterNode root = rootItr.next();
158       livenessAnalysisBackward( root, 
159                                 true, 
160                                 null );
161     }
162
163
164     /*
165       SOMETHING IS WRONG WITH THIS, DON'T USE IT UNTIL IT CAN BE FIXED
166
167     // 5th pass
168     methItr = ownAnalysis.descriptorsToAnalyze.iterator();
169     while( methItr.hasNext() ) {
170       Descriptor d  = methItr.next();      
171       FlatMethod fm = state.getMethodFlat( d );
172
173       // prune variable results in one traversal
174       // by removing reference variables that are not live
175       pruneVariableResultsWithLiveness( fm );
176     }
177     */
178
179
180     // 6th pass
181     methItr = ownAnalysis.descriptorsToAnalyze.iterator();
182     while( methItr.hasNext() ) {
183       Descriptor d  = methItr.next();      
184       FlatMethod fm = state.getMethodFlat( d );
185
186       // compute what is not available at every program
187       // point, in a forward fixed-point pass
188       notAvailableForward( fm );
189     }
190     
191     // new pass
192     methItr = ownAnalysis.descriptorsToAnalyze.iterator();
193         JavaCallGraph javaCallGraph = new JavaCallGraph(state,tu);
194     while( methItr.hasNext() ) {
195       Descriptor d  = methItr.next();      
196       FlatMethod fm = state.getMethodFlat( d );
197       methodEffects(fm,javaCallGraph);
198     }
199     
200     // disjoint analysis with a set of flagged allocation sites of live-in variable
201         try {
202                 OwnershipAnalysis oa2 = new OwnershipAnalysis(state, tu, callGraph,
203                                 state.OWNERSHIPALLOCDEPTH, false,
204                                 false, state.OWNERSHIPALIASFILE,
205                                 state.METHODEFFECTS,
206                                 mapMethodContextToLiveInAllocationSiteSet);
207                 // debug
208                 methItr = oa2.descriptorsToAnalyze.iterator();
209                 while (methItr.hasNext()) {
210                         Descriptor d = methItr.next();
211                         FlatMethod fm = state.getMethodFlat(d);
212                         debugFunction(oa2, fm);
213                 }
214                 //
215         } catch (IOException e) {
216                 System.err.println(e);
217         }
218     
219
220
221     // 7th pass
222     methItr = ownAnalysis.descriptorsToAnalyze.iterator();
223     while( methItr.hasNext() ) {
224       Descriptor d  = methItr.next();      
225       FlatMethod fm = state.getMethodFlat( d );
226
227       // compute a plan for code injections
228       codePlansForward( fm );
229     }
230
231
232     // splice new IR nodes into graph after all
233     // analysis passes are complete
234     Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
235     while( spliceItr.hasNext() ) {
236       Map.Entry               me    = (Map.Entry)               spliceItr.next();
237       FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
238       fwdvn.spliceIntoIR();
239     }
240
241
242     double timeEndAnalysis = (double) System.nanoTime();
243     double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
244     String treport = String.format( "The mlp analysis took %.3f sec.", dt );
245     System.out.println( treport );
246
247     if( state.MLPDEBUG ) {      
248       try {
249         writeReports( treport );
250       } catch( IOException e ) {}
251     }
252   }
253
254
255   private void buildForestForward( FlatMethod fm ) {
256     
257     // start from flat method top, visit every node in
258     // method exactly once, find SESEs and remember
259     // roots and child relationships
260     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
261     flatNodesToVisit.add( fm );
262
263     Set<FlatNode> visited = new HashSet<FlatNode>();    
264
265     Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
266     seseStacks.put( fm, seseStackFirst );
267
268     while( !flatNodesToVisit.isEmpty() ) {
269       Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
270       FlatNode fn = fnItr.next();
271
272       Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
273       assert seseStack != null;      
274
275       flatNodesToVisit.remove( fn );
276       visited.add( fn );      
277
278       buildForest_nodeActions( fn, seseStack, fm );
279
280       for( int i = 0; i < fn.numNext(); i++ ) {
281         FlatNode nn = fn.getNext( i );
282
283         if( !visited.contains( nn ) ) {
284           flatNodesToVisit.add( nn );
285
286           // clone stack and send along each analysis path
287           seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
288         }
289       }
290     }      
291   }
292
293   private void buildForest_nodeActions( FlatNode fn,                                                       
294                                         Stack<FlatSESEEnterNode> seseStack,
295                                         FlatMethod fm ) {
296     switch( fn.kind() ) {
297
298     case FKind.FlatSESEEnterNode: {
299       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
300
301       if( !fsen.getIsCallerSESEplaceholder() ) {
302         allSESEs.add( fsen );
303       }
304
305       fsen.setfmEnclosing( fm );
306       fsen.setmdEnclosing( fm.getMethod() );
307       fsen.setcdEnclosing( fm.getMethod().getClassDesc() );
308
309       if( seseStack.empty() ) {
310         rootSESEs.add( fsen );
311         fsen.setParent( null );
312       } else {
313         seseStack.peek().addChild( fsen );
314         fsen.setParent( seseStack.peek() );
315       }
316
317       seseStack.push( fsen );
318     } break;
319
320     case FKind.FlatSESEExitNode: {
321       FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
322       assert !seseStack.empty();
323       FlatSESEEnterNode fsen = seseStack.pop();
324     } break;
325
326     case FKind.FlatReturnNode: {
327       FlatReturnNode frn = (FlatReturnNode) fn;
328       if( !seseStack.empty() &&
329           !seseStack.peek().getIsCallerSESEplaceholder() 
330         ) {
331         throw new Error( "Error: return statement enclosed within SESE "+
332                          seseStack.peek().getPrettyIdentifier() );
333       }
334     } break;
335       
336     }
337   }
338
339
340   private void livenessAnalysisBackward( FlatSESEEnterNode fsen, 
341                                          boolean toplevel, 
342                                          Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout ) {
343
344     // start from an SESE exit, visit nodes in reverse up to
345     // SESE enter in a fixed-point scheme, where children SESEs
346     // should already be analyzed and therefore can be skipped 
347     // because child SESE enter node has all necessary info
348     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
349
350     if( toplevel ) {
351       flatNodesToVisit.add( fsen.getfmEnclosing().getFlatExit() );
352     } else {
353       flatNodesToVisit.add( fsen.getFlatExit() );
354     }
355
356     Hashtable<FlatNode, Set<TempDescriptor>> livenessResults = 
357       new Hashtable< FlatNode, Set<TempDescriptor> >();
358
359     if( toplevel ) {
360       liveout = new Hashtable< FlatSESEExitNode, Set<TempDescriptor> >();
361     }
362
363     while( !flatNodesToVisit.isEmpty() ) {
364       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
365       flatNodesToVisit.remove( fn );      
366       
367       Set<TempDescriptor> prev = livenessResults.get( fn );
368
369       // merge sets from control flow joins
370       Set<TempDescriptor> u = new HashSet<TempDescriptor>();
371       for( int i = 0; i < fn.numNext(); i++ ) {
372         FlatNode nn = fn.getNext( i );
373         Set<TempDescriptor> s = livenessResults.get( nn );
374         if( s != null ) {
375           u.addAll( s );
376         }
377       }
378       
379       Set<TempDescriptor> curr = liveness_nodeActions( fn, u, fsen, toplevel, liveout);
380
381       // if a new result, schedule backward nodes for analysis
382       if( !curr.equals( prev ) ) {
383         livenessResults.put( fn, curr );
384
385         // don't flow backwards past current SESE enter
386         if( !fn.equals( fsen ) ) {
387           for( int i = 0; i < fn.numPrev(); i++ ) {
388             FlatNode nn = fn.getPrev( i );
389             flatNodesToVisit.add( nn );
390           }
391         }
392       }
393     }
394     
395     Set<TempDescriptor> s = livenessResults.get( fsen );
396     if( s != null ) {
397       fsen.addInVarSet( s );
398     }
399     
400     // remember liveness per node from the root view as the
401     // global liveness of variables for later passes to use
402     if( toplevel ) {
403       livenessRootView.putAll( livenessResults );
404     }
405
406     // post-order traversal, so do children first
407     Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
408     while( childItr.hasNext() ) {
409       FlatSESEEnterNode fsenChild = childItr.next();
410       livenessAnalysisBackward( fsenChild, false, liveout );
411     }
412   }
413
414   private Set<TempDescriptor> liveness_nodeActions( FlatNode fn, 
415                                                     Set<TempDescriptor> liveIn,
416                                                     FlatSESEEnterNode currentSESE,
417                                                     boolean toplevel,
418                                                     Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout 
419                                                   ) {
420     switch( fn.kind() ) {
421       
422     case FKind.FlatSESEExitNode:
423       if( toplevel ) {
424         FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
425         if( !liveout.containsKey( fsexn ) ) {
426           liveout.put( fsexn, new HashSet<TempDescriptor>() );
427         }
428         liveout.get( fsexn ).addAll( liveIn );
429       }
430       // no break, sese exits should also execute default actions
431       
432     default: {
433       // handle effects of statement in reverse, writes then reads
434       TempDescriptor [] writeTemps = fn.writesTemps();
435       for( int i = 0; i < writeTemps.length; ++i ) {
436         liveIn.remove( writeTemps[i] );
437         
438         if( !toplevel ) {
439           FlatSESEExitNode fsexn = currentSESE.getFlatExit();
440           Set<TempDescriptor> livetemps = liveout.get( fsexn );
441           if( livetemps != null &&
442               livetemps.contains( writeTemps[i] ) ) {
443             // write to a live out temp...
444             // need to put in SESE liveout set
445             currentSESE.addOutVar( writeTemps[i] );
446           }     
447         }
448       }
449
450       TempDescriptor [] readTemps = fn.readsTemps();
451       for( int i = 0; i < readTemps.length; ++i ) {
452         liveIn.add( readTemps[i] );
453       }
454       
455       Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get( fn );
456       if( virtualReadTemps != null ) {
457         liveIn.addAll( virtualReadTemps );
458       }     
459       
460     } break;
461
462     } // end switch
463
464     return liveIn;
465   }
466
467
468   private void variableAnalysisForward( FlatMethod fm ) {
469     
470     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
471     flatNodesToVisit.add( fm );  
472
473     while( !flatNodesToVisit.isEmpty() ) {
474       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
475       flatNodesToVisit.remove( fn );      
476
477       Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
478       assert seseStack != null;      
479
480       VarSrcTokTable prev = variableResults.get( fn );
481
482       // merge sets from control flow joins
483       VarSrcTokTable curr = new VarSrcTokTable();
484       for( int i = 0; i < fn.numPrev(); i++ ) {
485         FlatNode nn = fn.getPrev( i );          
486         VarSrcTokTable incoming = variableResults.get( nn );
487         curr.merge( incoming );
488       }
489
490       if( !seseStack.empty() ) {
491         variable_nodeActions( fn, curr, seseStack.peek() );
492       }
493
494       // if a new result, schedule forward nodes for analysis
495       if( !curr.equals( prev ) ) {       
496         variableResults.put( fn, curr );
497
498         for( int i = 0; i < fn.numNext(); i++ ) {
499           FlatNode nn = fn.getNext( i );         
500           flatNodesToVisit.add( nn );    
501         }
502       }
503     }
504   }
505
506   private void variable_nodeActions( FlatNode fn, 
507                                      VarSrcTokTable vstTable,
508                                      FlatSESEEnterNode currentSESE ) {
509     switch( fn.kind() ) {
510
511     case FKind.FlatSESEEnterNode: {
512       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
513       assert fsen.equals( currentSESE );
514
515       vstTable.age( currentSESE );
516       vstTable.assertConsistency();
517     } break;
518
519     case FKind.FlatSESEExitNode: {
520       FlatSESEExitNode  fsexn = (FlatSESEExitNode)  fn;
521       FlatSESEEnterNode fsen  = fsexn.getFlatEnter();
522       assert currentSESE.getChildren().contains( fsen );
523
524       vstTable.remapChildTokens( fsen );
525       
526       // liveness virtual reads are things that might be 
527       // written by an SESE and should be added to the in-set
528       // anything virtually read by this SESE should be pruned
529       // of parent or sibling sources
530       Set<TempDescriptor> liveVars         = livenessRootView.get( fn );
531       Set<TempDescriptor> fsenVirtReads    = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens( fsen, liveVars );
532       Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get( fn );
533       if( fsenVirtReadsOld != null ) {
534         fsenVirtReads.addAll( fsenVirtReadsOld );
535       }
536       livenessVirtualReads.put( fn, fsenVirtReads );
537
538
539       // then all child out-set tokens are guaranteed
540       // to be filled in, so clobber those entries with
541       // the latest, clean sources
542       Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
543       while( outVarItr.hasNext() ) {
544         TempDescriptor outVar = outVarItr.next();
545         HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
546         ts.add( outVar );
547         VariableSourceToken vst = 
548           new VariableSourceToken( ts,
549                                    fsen,
550                                    new Integer( 0 ),
551                                    outVar
552                                    );
553         vstTable.remove( outVar );
554         vstTable.add( vst );
555       }
556       vstTable.assertConsistency();
557
558     } break;
559
560     case FKind.FlatOpNode: {
561       FlatOpNode fon = (FlatOpNode) fn;
562
563       if( fon.getOp().getOp() == Operation.ASSIGN ) {
564         TempDescriptor lhs = fon.getDest();
565         TempDescriptor rhs = fon.getLeft();        
566
567         vstTable.remove( lhs );
568
569         Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
570
571         Iterator<VariableSourceToken> itr = vstTable.get( rhs ).iterator();
572         while( itr.hasNext() ) {
573           VariableSourceToken vst = itr.next();
574
575           HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
576           ts.add( lhs );
577
578           if( currentSESE.getChildren().contains( vst.getSESE() ) ) {
579             // if the source comes from a child, copy it over
580             forAddition.add( new VariableSourceToken( ts,
581                                                       vst.getSESE(),
582                                                       vst.getAge(),
583                                                       vst.getAddrVar()
584                                                       )
585                              );
586           } else {
587             // otherwise, stamp it as us as the source
588             forAddition.add( new VariableSourceToken( ts,
589                                                       currentSESE,
590                                                       new Integer( 0 ),
591                                                       lhs
592                                                       )
593                              );
594           }
595         }
596
597         vstTable.addAll( forAddition );
598
599         // only break if this is an ASSIGN op node,
600         // otherwise fall through to default case
601         vstTable.assertConsistency();
602         break;
603       }
604     }
605
606     // note that FlatOpNode's that aren't ASSIGN
607     // fall through to this default case
608     default: {
609       TempDescriptor [] writeTemps = fn.writesTemps();
610       if( writeTemps.length > 0 ) {
611
612
613         // for now, when writeTemps > 1, make sure
614         // its a call node, programmer enforce only
615         // doing stuff like calling a print routine
616         //assert writeTemps.length == 1;
617         if( writeTemps.length > 1 ) {
618           assert fn.kind() == FKind.FlatCall ||
619                  fn.kind() == FKind.FlatMethod;
620           break;
621         }
622
623         vstTable.remove( writeTemps[0] );
624
625         HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
626         ts.add( writeTemps[0] );
627
628         vstTable.add( new VariableSourceToken( ts,
629                                                currentSESE,
630                                                new Integer( 0 ),
631                                                writeTemps[0]
632                                              )
633                       );
634       }      
635
636       vstTable.assertConsistency();
637     } break;
638
639     } // end switch
640   }
641
642
643   private void pruneVariableResultsWithLiveness( FlatMethod fm ) {
644     
645     // start from flat method top, visit every node in
646     // method exactly once
647     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
648     flatNodesToVisit.add( fm );
649
650     Set<FlatNode> visited = new HashSet<FlatNode>();    
651
652     while( !flatNodesToVisit.isEmpty() ) {
653       Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
654       FlatNode fn = fnItr.next();
655
656       flatNodesToVisit.remove( fn );
657       visited.add( fn );      
658
659       Set<TempDescriptor> rootLiveSet = livenessRootView.get( fn );
660       VarSrcTokTable      vstTable    = variableResults.get( fn );
661       
662       vstTable.pruneByLiveness( rootLiveSet );
663       
664       for( int i = 0; i < fn.numNext(); i++ ) {
665         FlatNode nn = fn.getNext( i );
666
667         if( !visited.contains( nn ) ) {
668           flatNodesToVisit.add( nn );
669         }
670       }
671     }
672   }
673
674
675   private void notAvailableForward( FlatMethod fm ) {
676
677     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
678     flatNodesToVisit.add( fm );  
679
680     while( !flatNodesToVisit.isEmpty() ) {
681       FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
682       flatNodesToVisit.remove( fn );      
683
684       Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
685       assert seseStack != null;      
686
687       Set<TempDescriptor> prev = notAvailableResults.get( fn );
688
689       Set<TempDescriptor> curr = new HashSet<TempDescriptor>();      
690       for( int i = 0; i < fn.numPrev(); i++ ) {
691         FlatNode nn = fn.getPrev( i );       
692         Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
693         if( notAvailIn != null ) {
694           curr.addAll( notAvailIn );
695         }
696       }
697       
698       if( !seseStack.empty() ) {
699         notAvailable_nodeActions( fn, curr, seseStack.peek() );     
700       }
701
702       // if a new result, schedule forward nodes for analysis
703       if( !curr.equals( prev ) ) {
704         notAvailableResults.put( fn, curr );
705
706         for( int i = 0; i < fn.numNext(); i++ ) {
707           FlatNode nn = fn.getNext( i );         
708           flatNodesToVisit.add( nn );    
709         }
710       }
711     }
712   }
713
714   private void notAvailable_nodeActions( FlatNode fn, 
715                                          Set<TempDescriptor> notAvailSet,
716                                          FlatSESEEnterNode currentSESE ) {
717
718     // any temps that are removed from the not available set
719     // at this node should be marked in this node's code plan
720     // as temps to be grabbed at runtime!
721
722     switch( fn.kind() ) {
723
724     case FKind.FlatSESEEnterNode: {
725       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
726       assert fsen.equals( currentSESE );
727       notAvailSet.clear();
728     } break;
729
730     case FKind.FlatSESEExitNode: {
731       FlatSESEExitNode  fsexn = (FlatSESEExitNode)  fn;
732       FlatSESEEnterNode fsen  = fsexn.getFlatEnter();
733       assert currentSESE.getChildren().contains( fsen );
734       notAvailSet.addAll( fsen.getOutVarSet() );
735     } break;
736
737     case FKind.FlatMethod: {
738       notAvailSet.clear();
739     }
740
741     case FKind.FlatOpNode: {
742       FlatOpNode fon = (FlatOpNode) fn;
743
744       if( fon.getOp().getOp() == Operation.ASSIGN ) {
745         TempDescriptor lhs = fon.getDest();
746         TempDescriptor rhs = fon.getLeft();
747
748         // copy makes lhs same availability as rhs
749         if( notAvailSet.contains( rhs ) ) {
750           notAvailSet.add( lhs );
751         } else {
752           notAvailSet.remove( lhs );
753         }
754
755         // only break if this is an ASSIGN op node,
756         // otherwise fall through to default case
757         break;
758       }
759     }
760
761     // note that FlatOpNode's that aren't ASSIGN
762     // fall through to this default case
763     default: {
764       TempDescriptor [] writeTemps = fn.writesTemps();
765       for( int i = 0; i < writeTemps.length; i++ ) {
766         TempDescriptor wTemp = writeTemps[i];
767         notAvailSet.remove( wTemp );
768       }
769       TempDescriptor [] readTemps = fn.readsTemps();
770       for( int i = 0; i < readTemps.length; i++ ) {
771         TempDescriptor rTemp = readTemps[i];
772         notAvailSet.remove( rTemp );
773
774         // if this variable has exactly one source, potentially
775         // get other things from this source as well
776         VarSrcTokTable vstTable = variableResults.get( fn );
777
778         Integer srcType = 
779           vstTable.getRefVarSrcType( rTemp, 
780                                      currentSESE,
781                                      currentSESE.getParent() );
782
783         if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
784
785           VariableSourceToken vst = vstTable.get( rTemp ).iterator().next();
786
787           Iterator<VariableSourceToken> availItr = vstTable.get( vst.getSESE(),
788                                                                  vst.getAge()
789                                                                  ).iterator();
790
791           // look through things that are also available from same source
792           while( availItr.hasNext() ) {
793             VariableSourceToken vstAlsoAvail = availItr.next();
794           
795             Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
796             while( refVarItr.hasNext() ) {
797               TempDescriptor refVarAlso = refVarItr.next();
798
799               // if a variable is available from the same source, AND it ALSO
800               // only comes from one statically known source, mark it available
801               Integer srcTypeAlso = 
802                 vstTable.getRefVarSrcType( refVarAlso, 
803                                            currentSESE,
804                                            currentSESE.getParent() );
805               if( srcTypeAlso.equals( VarSrcTokTable.SrcType_STATIC ) ) {
806                 notAvailSet.remove( refVarAlso );
807               }
808             }
809           }
810         }
811       }
812     } break;
813
814     } // end switch
815   }
816   
817   private void debugFunction(OwnershipAnalysis oa2, FlatMethod fm) {
818           
819           String methodName="SomeWork";
820           
821           MethodDescriptor md=fm.getMethod();
822                 HashSet<MethodContext> mcSet=oa2.getAllMethodContextSetByDescriptor(md);
823                 Iterator<MethodContext> mcIter=mcSet.iterator();
824                 
825                 while(mcIter.hasNext()){
826                         MethodContext mc=mcIter.next();
827                         
828                         OwnershipGraph og=oa2.getOwnvershipGraphByMethodContext(mc);
829                         
830                         if(fm.toString().indexOf(methodName)>0){
831                                  try {
832                                  og.writeGraph(fm.toString() + "SECONDGRAPH", true, true, true, true, false);
833                                  } catch (IOException e) {
834                                  System.out.println("Error writing debug capture.");
835                                  System.exit(0);
836                                  }
837                         }
838                         
839
840
841                 }
842           
843   }
844   
845         private void methodEffects(FlatMethod fm, CallGraph callGraph) {
846
847                 MethodDescriptor md=fm.getMethod();
848                 HashSet<MethodContext> mcSet=ownAnalysis.getAllMethodContextSetByDescriptor(md);
849                 Iterator<MethodContext> mcIter=mcSet.iterator();
850                 
851                 while(mcIter.hasNext()){
852                         MethodContext mc=mcIter.next();
853                         
854                         Set<FlatNode> visited = new HashSet<FlatNode>();
855                         
856                         Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
857                         flatNodesToVisit.add(fm);
858
859                         while (!flatNodesToVisit.isEmpty()) {
860                                 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
861                                 flatNodesToVisit.remove(fn);
862
863                                 Stack<FlatSESEEnterNode> seseStack = seseStacks.get(fn);
864                                 assert seseStack != null;
865
866                                 if (!seseStack.empty()) {
867                                         effects_nodeActions(mc, fn, seseStack.peek(), callGraph);
868                                 }
869
870                                 flatNodesToVisit.remove(fn);
871                                 visited.add(fn);
872
873                                 for (int i = 0; i < fn.numNext(); i++) {
874                                         FlatNode nn = fn.getNext(i);
875                                         if (!visited.contains(nn)) {
876                                                 flatNodesToVisit.add(nn);
877                                         }
878                                 }
879
880                         }
881                         
882                         
883                 }
884                 
885         }
886         
887         private void analyzeRelatedAllocationSite(MethodDescriptor callerMD,
888                         MethodContext calleeMC, HashSet<Integer> paramIndexSet,
889                         HashSet<HeapRegionNode> visitedHRN) {
890
891                 HashSet<MethodContext> mcSet = ownAnalysis
892                                 .getAllMethodContextSetByDescriptor(callerMD);
893
894                 if (mcSet != null) {
895
896                         Iterator<MethodContext> mcIter = mcSet.iterator();
897
898                         FlatMethod callerFM = state.getMethodFlat(callerMD);
899
900                         while (mcIter.hasNext()) {
901                                 MethodContext mc = mcIter.next();
902
903                                 Set<FlatNode> visited = new HashSet<FlatNode>();
904                                 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
905                                 flatNodesToVisit.add(callerFM);
906
907                                 while (!flatNodesToVisit.isEmpty()) {
908                                         FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
909                                         flatNodesToVisit.remove(fn);
910
911                                         analyzeRelatedAllocationSite_NodeAction(fn, mc, calleeMC,
912                                                         paramIndexSet,visitedHRN);
913
914                                         flatNodesToVisit.remove(fn);
915                                         visited.add(fn);
916
917                                         for (int i = 0; i < fn.numNext(); i++) {
918                                                 FlatNode nn = fn.getNext(i);
919                                                 if (!visited.contains(nn)) {
920                                                         flatNodesToVisit.add(nn);
921                                                 }
922                                         }
923                                 }
924                         }
925                 }
926
927         }
928         
929         private void analyzeRelatedAllocationSite_NodeAction(FlatNode fn, MethodContext callerMC,
930  MethodContext calleeMC,
931                         HashSet<Integer> paramIndexSet, HashSet<HeapRegionNode> visitedHRN) {
932
933                 OwnershipGraph og = ownAnalysis
934                                 .getOwnvershipGraphByMethodContext(callerMC);
935
936                 switch (fn.kind()) {
937
938                 case FKind.FlatCall: {
939
940                         FlatCall fc = (FlatCall) fn;
941
942                         MethodContext calleeMCfromOG = ownAnalysis.getCalleeMethodContext(
943                                         callerMC, fc);
944
945                         // disable below condition. currently collect all possible
946                         // allocation sites without regarding method context
947
948                         // if (calleeMC.equals(calleeMCfromOG)) { // in this case, this
949                         // method context calls corresponding callee.
950
951                         int base;
952                         if (((MethodDescriptor) calleeMC.getDescriptor()).isStatic()) {
953                                 base = 0;
954                         } else {
955                                 base = 1;
956                         }
957
958                         for (Iterator iterator = paramIndexSet.iterator(); iterator
959                                         .hasNext();) {
960                                 Integer integer = (Integer) iterator.next();
961
962                                 int paramIdx = integer - base;
963                                 if (paramIdx >= 0) {
964                                         // if paramIdx is less than 0, assumes that it is
965                                         // related with wrong method contexts.
966                                         TempDescriptor arg = fc.getArg(paramIdx);
967                                         LabelNode argLN = og.td2ln.get(arg);
968                                         if (argLN != null) {
969                                                 Iterator<ReferenceEdge> iterEdge = argLN
970                                                                 .iteratorToReferencees();
971                                                 while (iterEdge.hasNext()) {
972                                                         ReferenceEdge referenceEdge = (ReferenceEdge) iterEdge
973                                                                         .next();
974
975                                                         HeapRegionNode dstHRN = referenceEdge.getDst();
976                                                         if (dstHRN.isParameter()) {
977                                                                 if (!visitedHRN.contains(dstHRN)) {
978                                                                         setupRelatedAllocSiteAnalysis(og, callerMC,
979                                                                                         dstHRN, visitedHRN);
980                                                                 }
981                                                         } else {
982                                                                 addLiveInAllocationSite(callerMC, dstHRN
983                                                                                 .getAllocationSite());
984                                                         }
985                                                 }
986                                         }
987                                 }
988                         }
989                         // }
990
991                 }
992                         break;
993
994                 }
995         }
996         
997         private void setupRelatedAllocSiteAnalysis(OwnershipGraph og,
998                         MethodContext mc, HeapRegionNode dstHRN,
999                         HashSet<HeapRegionNode> visitedHRN) {
1000
1001                 HashSet<Integer> paramIndexSet = new HashSet<Integer>();
1002
1003                 // collect corresponding param index
1004                 Set<Integer> pIndexSet = og.idPrimary2paramIndexSet.get(dstHRN.getID());
1005                 if (pIndexSet != null) {
1006                         for (Iterator iterator = pIndexSet.iterator(); iterator.hasNext();) {
1007                                 Integer integer = (Integer) iterator.next();
1008                                 paramIndexSet.add(integer);
1009                         }
1010                 }
1011
1012                 Set<Integer> sIndexSet = og.idSecondary2paramIndexSet.get(dstHRN
1013                                 .getID());
1014                 if (sIndexSet != null) {
1015                         for (Iterator iterator = sIndexSet.iterator(); iterator.hasNext();) {
1016                                 Integer integer = (Integer) iterator.next();
1017                                 paramIndexSet.add(integer);
1018                         }
1019                 }
1020
1021                 if (mc.getDescriptor() instanceof MethodDescriptor) {
1022                         Set callerSet = callGraph.getCallerSet((MethodDescriptor) mc
1023                                         .getDescriptor());
1024                         for (Iterator iterator = callerSet.iterator(); iterator.hasNext();) {
1025                                 Object obj = (Object) iterator.next();
1026                                 if (obj instanceof MethodDescriptor) {
1027                                         MethodDescriptor callerMD = (MethodDescriptor) obj;
1028
1029                                         analyzeRelatedAllocationSite(callerMD, mc, paramIndexSet,visitedHRN);
1030
1031                                 }
1032                         }
1033                 }
1034         }
1035   
1036         private void effects_nodeActions(MethodContext mc, FlatNode fn,
1037                         FlatSESEEnterNode currentSESE, CallGraph callGraph) {
1038
1039                 OwnershipGraph og = ownAnalysis.getOwnvershipGraphByMethodContext(mc);
1040
1041                 switch (fn.kind()) {
1042
1043                 case FKind.FlatSESEEnterNode: {
1044
1045                         FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
1046                         assert fsen.equals(currentSESE);
1047
1048                         // uniquely taint each live-in variable
1049                         Set<TempDescriptor> set = fsen.getInVarSet();
1050                         Iterator<TempDescriptor> iter = set.iterator();
1051                         int idx = 0;
1052                         while (iter.hasNext()) {
1053                                 TempDescriptor td = iter.next();
1054                                 LabelNode ln = og.td2ln.get(td);
1055                                 if (ln != null) {
1056                                         int taint = (int) Math.pow(2, idx);
1057                                         taintLabelNode(ln, taint);
1058
1059                                         // collects related allocation sites
1060                                         Iterator<ReferenceEdge> referenceeIter = ln
1061                                                         .iteratorToReferencees();
1062                                         while (referenceeIter.hasNext()) {
1063                                                 ReferenceEdge referenceEdge = (ReferenceEdge) referenceeIter
1064                                                                 .next();
1065                                                 HeapRegionNode dstHRN = referenceEdge.getDst();
1066                                                 if (dstHRN.isParameter()) {
1067                                                         
1068                                                         HashSet<HeapRegionNode> visitedHRN=new HashSet<HeapRegionNode>();
1069                                                         visitedHRN.add(dstHRN);
1070                                                         setupRelatedAllocSiteAnalysis(og,mc,dstHRN,visitedHRN);
1071
1072                                                 } else {
1073                                                         addLiveInAllocationSite(mc, dstHRN
1074                                                                         .getAllocationSite());
1075                                                 }
1076                                         }
1077
1078                                 }
1079
1080                                 idx++;
1081                         }
1082
1083                 }
1084                         break;
1085
1086                 case FKind.FlatSESEExitNode: {
1087                         FlatSESEExitNode fsexit = (FlatSESEExitNode) fn;
1088
1089                         FlatSESEEnterNode enterNode = fsexit.getFlatEnter();
1090                         FlatSESEEnterNode parent = enterNode.getParent();
1091                         if (parent != null) {
1092
1093                                 SESEEffectsSet set = enterNode.getSeseEffectsSet();
1094                                 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> readTable = set
1095                                                 .getReadTable();
1096                                 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentReadTable = parent
1097                                                 .getSeseEffectsSet().getReadTable();
1098                                 Set<TempDescriptor> keys = readTable.keySet();
1099                                 Iterator<TempDescriptor> keyIter = keys.iterator();
1100                                 while (keyIter.hasNext()) {
1101                                         TempDescriptor td = (TempDescriptor) keyIter.next();
1102                                         HashSet<SESEEffectsKey> effectsSet = readTable.get(td);
1103                                         HashSet<SESEEffectsKey> parentEffectsSet = parentReadTable
1104                                                         .get(td);
1105                                         if (parentEffectsSet == null) {
1106                                                 parentEffectsSet = new HashSet<SESEEffectsKey>();
1107                                         }
1108
1109                                         for (Iterator iterator = effectsSet.iterator(); iterator
1110                                                         .hasNext();) {
1111                                                 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
1112                                                                 .next();
1113                                                 parentEffectsSet.add(new SESEEffectsKey(seseKey
1114                                                                 .getFieldDescriptor(), seseKey
1115                                                                 .getTypeDescriptor(), seseKey.getHRNId()));
1116                                         }
1117
1118                                         parentReadTable.put(td, parentEffectsSet);
1119                                 }
1120
1121                                 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> writeTable = set
1122                                                 .getWriteTable();
1123                                 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentWriteTable = parent
1124                                                 .getSeseEffectsSet().getWriteTable();
1125                                 keys = writeTable.keySet();
1126                                 keyIter = keys.iterator();
1127                                 while (keyIter.hasNext()) {
1128                                         TempDescriptor td = (TempDescriptor) keyIter.next();
1129                                         HashSet<SESEEffectsKey> effectsSet = writeTable.get(td);
1130                                         HashSet<SESEEffectsKey> parentEffectsSet = parentWriteTable
1131                                                         .get(td);
1132                                         if (parentEffectsSet == null) {
1133                                                 parentEffectsSet = new HashSet<SESEEffectsKey>();
1134                                         }
1135
1136                                         for (Iterator iterator = effectsSet.iterator(); iterator
1137                                                         .hasNext();) {
1138                                                 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
1139                                                                 .next();
1140                                                 parentEffectsSet.add(new SESEEffectsKey(seseKey
1141                                                                 .getFieldDescriptor(), seseKey
1142                                                                 .getTypeDescriptor(), seseKey.getHRNId()));
1143                                         }
1144
1145                                         parentWriteTable.put(td, parentEffectsSet);
1146                                 }
1147
1148                                 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> strongUpdateTable = set
1149                                                 .getStrongUpdateTable();
1150                                 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentstrongUpdateTable = parent
1151                                                 .getSeseEffectsSet().getStrongUpdateTable();
1152                                 keys = strongUpdateTable.keySet();
1153                                 keyIter = keys.iterator();
1154                                 while (keyIter.hasNext()) {
1155                                         TempDescriptor td = (TempDescriptor) keyIter.next();
1156                                         HashSet<SESEEffectsKey> effectsSet = strongUpdateTable
1157                                                         .get(td);
1158                                         HashSet<SESEEffectsKey> parentEffectsSet = parentstrongUpdateTable
1159                                                         .get(td);
1160                                         if (parentEffectsSet == null) {
1161                                                 parentEffectsSet = new HashSet<SESEEffectsKey>();
1162                                         }
1163
1164                                         for (Iterator iterator = effectsSet.iterator(); iterator
1165                                                         .hasNext();) {
1166                                                 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
1167                                                                 .next();
1168                                                 parentEffectsSet.add(new SESEEffectsKey(seseKey
1169                                                                 .getFieldDescriptor(), seseKey
1170                                                                 .getTypeDescriptor(), seseKey.getHRNId()));
1171                                         }
1172
1173                                         parentstrongUpdateTable.put(td, parentEffectsSet);
1174                                 }
1175
1176                         }
1177
1178                 }
1179                         break;
1180
1181                 case FKind.FlatFieldNode: {
1182
1183                         FlatFieldNode ffn = (FlatFieldNode) fn;
1184                         TempDescriptor src = ffn.getSrc();
1185                         FieldDescriptor field = ffn.getField();
1186
1187                         LabelNode srcLN = og.td2ln.get(src);
1188                         if (srcLN != null) {
1189                                 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(srcLN);
1190                                 Iterator<TempDescriptor> affectedIter = affectedTDSet
1191                                                 .iterator();
1192                                 while (affectedIter.hasNext()) {
1193                                         TempDescriptor affectedTD = affectedIter.next();
1194
1195                                         if (currentSESE.getInVarSet().contains(affectedTD)) {
1196
1197                                                 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1198                                                                 og, affectedTD);
1199                                                 Iterator<HeapRegionNode> hrnIter = hrnSet.iterator();
1200                                                 while (hrnIter.hasNext()) {
1201                                                         HeapRegionNode hrn = hrnIter.next();
1202
1203                                                         Iterator<ReferenceEdge> referencers = hrn
1204                                                                         .iteratorToReferencers();
1205                                                         while (referencers.hasNext()) {
1206                                                                 ReferenceEdge referenceEdge = (ReferenceEdge) referencers
1207                                                                                 .next();
1208                                                                 if (field.getSymbol().equals(
1209                                                                                 referenceEdge.getField())) {
1210                                                                         currentSESE.readEffects(affectedTD, field
1211                                                                                         .getSymbol(), src.getType(),
1212                                                                                         referenceEdge.getDst().getID());
1213                                                                 }
1214                                                         }
1215
1216                                                 }
1217                                         }
1218                                 }
1219
1220                                 // handle tainted case
1221
1222                                 Iterator<ReferenceEdge> edgeIter = srcLN
1223                                                 .iteratorToReferencees();
1224                                 while (edgeIter.hasNext()) {
1225                                         ReferenceEdge edge = edgeIter.next();
1226                                         HeapRegionNode accessHRN = edge.getDst();
1227                                         // / follow the chain of reference to identify possible
1228                                         // accesses
1229                                         Iterator<ReferenceEdge> referIter = accessHRN
1230                                                         .iteratorToReferencers();
1231                                         while (referIter.hasNext()) {
1232                                                 ReferenceEdge referEdge = (ReferenceEdge) referIter
1233                                                                 .next();
1234
1235                                                 // if (referEdge.getTaintIdentifier() >0 ||
1236                                                 // referEdge.getSESETaintIdentifier()>0 ) {
1237                                                 HashSet<TempDescriptor> referSet = new HashSet<TempDescriptor>();
1238                                                 followReference(accessHRN, referSet,
1239                                                                 new HashSet<HeapRegionNode>(), currentSESE);
1240
1241                                                 Iterator<TempDescriptor> referSetIter = referSet
1242                                                                 .iterator();
1243                                                 while (referSetIter.hasNext()) {
1244                                                         TempDescriptor tempDescriptor = (TempDescriptor) referSetIter
1245                                                                         .next();
1246                                                         currentSESE.readEffects(tempDescriptor, field
1247                                                                         .getSymbol(), src.getType(), accessHRN
1248                                                                         .getID());
1249                                                 }
1250                                                 // }
1251                                         }
1252                                         // /
1253                                         if (edge.getTaintIdentifier() > 0
1254                                                         || edge.getSESETaintIdentifier() > 0) {
1255
1256                                                 affectedTDSet = getReferenceNodeSet(accessHRN);
1257                                                 affectedIter = affectedTDSet.iterator();
1258                                                 while (affectedIter.hasNext()) {
1259                                                         TempDescriptor affectedTD = affectedIter.next();
1260
1261                                                         if (currentSESE.getInVarSet().contains(affectedTD)) {
1262
1263                                                                 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1264                                                                                 og, affectedTD);
1265                                                                 Iterator<HeapRegionNode> hrnIter = hrnSet
1266                                                                                 .iterator();
1267                                                                 while (hrnIter.hasNext()) {
1268                                                                         HeapRegionNode hrn = hrnIter.next();
1269                                                                         currentSESE.readEffects(affectedTD, field
1270                                                                                         .getSymbol(), src.getType(), hrn
1271                                                                                         .getID());
1272                                                                 }
1273
1274                                                         }
1275
1276                                                 }
1277                                         }
1278                                 }
1279                         }
1280
1281                 }
1282                         break;
1283
1284                 case FKind.FlatSetFieldNode: {
1285
1286                         FlatSetFieldNode fsen = (FlatSetFieldNode) fn;
1287                         TempDescriptor dst = fsen.getDst();
1288                         FieldDescriptor field = fsen.getField();
1289
1290                         LabelNode dstLN = og.td2ln.get(dst);
1291                         if (dstLN != null) {
1292                                 // check possible strong updates
1293                                 boolean strongUpdate = false;
1294
1295                                 if (!field.getType().isImmutable() || field.getType().isArray()) {
1296                                         Iterator<ReferenceEdge> itrXhrn = dstLN
1297                                                         .iteratorToReferencees();
1298                                         while (itrXhrn.hasNext()) {
1299                                                 ReferenceEdge edgeX = itrXhrn.next();
1300                                                 HeapRegionNode hrnX = edgeX.getDst();
1301
1302                                                 // we can do a strong update here if one of two cases
1303                                                 // holds
1304                                                 if (field != null
1305                                                                 && field != OwnershipAnalysis
1306                                                                                 .getArrayField(field.getType())
1307                                                                 && ((hrnX.getNumReferencers() == 1) || // case 1
1308                                                                 (hrnX.isSingleObject() && dstLN
1309                                                                                 .getNumReferencees() == 1) // case 2
1310                                                                 )) {
1311                                                         strongUpdate = true;
1312                                                 }
1313                                         }
1314                                 }
1315
1316                                 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(dstLN);
1317
1318                                 Iterator<TempDescriptor> affectedIter = affectedTDSet
1319                                                 .iterator();
1320
1321                                 while (affectedIter.hasNext()) {
1322                                         TempDescriptor affectedTD = affectedIter.next();
1323                                         if (currentSESE.getInVarSet().contains(affectedTD)) {
1324
1325                                                 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1326                                                                 og, affectedTD);
1327                                                 Iterator<HeapRegionNode> hrnIter = hrnSet.iterator();
1328                                                 while (hrnIter.hasNext()) {
1329                                                         HeapRegionNode hrn = hrnIter.next();
1330
1331                                                         Iterator<ReferenceEdge> referencers = hrn
1332                                                                         .iteratorToReferencers();
1333                                                         while (referencers.hasNext()) {
1334                                                                 ReferenceEdge referenceEdge = (ReferenceEdge) referencers
1335                                                                                 .next();
1336                                                                 if (field.getSymbol().equals(
1337                                                                                 referenceEdge.getField())) {
1338                                                                         currentSESE.writeEffects(affectedTD, field
1339                                                                                         .getSymbol(), dst.getType(),
1340                                                                                         referenceEdge.getDst().getID(),
1341                                                                                         strongUpdate);
1342                                                                 }
1343                                                         }
1344
1345                                                 }
1346                                         }
1347                                 }
1348
1349                                 // handle tainted case
1350                                 Iterator<ReferenceEdge> edgeIter = dstLN
1351                                                 .iteratorToReferencees();
1352                                 while (edgeIter.hasNext()) {
1353                                         ReferenceEdge edge = edgeIter.next();
1354
1355                                         HeapRegionNode accessHRN = edge.getDst();
1356                                         // / follow the chain of reference to identify possible
1357                                         // accesses
1358                                         Iterator<ReferenceEdge> referIter = accessHRN
1359                                                         .iteratorToReferencers();
1360                                         while (referIter.hasNext()) {
1361                                                 ReferenceEdge referEdge = (ReferenceEdge) referIter
1362                                                                 .next();
1363
1364                                                 // if (referEdge.getTaintIdentifier() > 0 ||
1365                                                 // referEdge.getSESETaintIdentifier() > 0 ) {
1366                                                 HashSet<TempDescriptor> referSet = new HashSet<TempDescriptor>();
1367                                                 followReference(accessHRN, referSet,
1368                                                                 new HashSet<HeapRegionNode>(), currentSESE);
1369                                                 Iterator<TempDescriptor> referSetIter = referSet
1370                                                                 .iterator();
1371                                                 while (referSetIter.hasNext()) {
1372                                                         TempDescriptor tempDescriptor = (TempDescriptor) referSetIter
1373                                                                         .next();
1374                                                         currentSESE.writeEffects(tempDescriptor, field
1375                                                                         .getSymbol(), dst.getType(), accessHRN
1376                                                                         .getID(), strongUpdate);
1377                                                 }
1378                                                 // }
1379                                         }
1380                                         // /
1381                                         if (edge.getTaintIdentifier() > 0
1382                                                         || edge.getSESETaintIdentifier() > 0) {
1383                                                 affectedTDSet = getReferenceNodeSet(accessHRN);
1384                                                 affectedIter = affectedTDSet.iterator();
1385                                                 while (affectedIter.hasNext()) {
1386                                                         TempDescriptor affectedTD = affectedIter.next();
1387                                                         if (currentSESE.getInVarSet().contains(affectedTD)) {
1388
1389                                                                 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1390                                                                                 og, affectedTD);
1391                                                                 Iterator<HeapRegionNode> hrnIter = hrnSet
1392                                                                                 .iterator();
1393                                                                 while (hrnIter.hasNext()) {
1394                                                                         HeapRegionNode hrn = hrnIter.next();
1395                                                                         currentSESE.writeEffects(affectedTD, field
1396                                                                                         .getSymbol(), dst.getType(), hrn
1397                                                                                         .getID(), strongUpdate);
1398
1399                                                                 }
1400
1401                                                         }
1402
1403                                                 }
1404                                         }
1405                                 }
1406
1407                         }
1408
1409                 }
1410                         break;
1411
1412                 case FKind.FlatCall: {
1413                         FlatCall fc = (FlatCall) fn;
1414
1415                         MethodContext calleeMC = ownAnalysis.getCalleeMethodContext(mc, fc);
1416
1417                         MethodEffects me = ownAnalysis.getMethodEffectsAnalysis()
1418                                         .getMethodEffectsByMethodContext(calleeMC);
1419
1420                         OwnershipGraph calleeOG = ownAnalysis
1421                                         .getOwnvershipGraphByMethodContext(calleeMC);
1422
1423                         FlatMethod fm = state.getMethodFlat(fc.getMethod());
1424                         ParameterDecomposition decomp = new ParameterDecomposition(
1425                                         ownAnalysis, fc, fm, calleeMC, calleeOG, og);
1426
1427                         int base;
1428                         if (((MethodDescriptor) calleeMC.getDescriptor()).isStatic()) {
1429                                 base = 0;
1430                         } else {
1431                                 base = 1;
1432                         }
1433
1434                         for (int i = 0; i < fc.numArgs(); i++) {
1435
1436                                 TempDescriptor arg = fc.getArg(i);
1437                                 Set<EffectsKey> readSet = me.getEffects().getReadingSet(
1438                                                 i + base);
1439                                 Set<EffectsKey> writeSet = me.getEffects().getWritingSet(
1440                                                 i + base);
1441
1442                                 Set<EffectsKey> strongUpdateSet = me.getEffects()
1443                                                 .getStrongUpdateSet(i + base);
1444
1445                                 LabelNode argLN = og.td2ln.get(arg);
1446                                 if (argLN != null) {
1447                                         HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(argLN);
1448                                         Iterator<TempDescriptor> affectedIter = affectedTDSet
1449                                                         .iterator();
1450
1451                                         while (affectedIter.hasNext()) {
1452
1453                                                 TempDescriptor affectedTD = affectedIter.next();
1454                                                 if (currentSESE.getInVarSet().contains(affectedTD)) {
1455
1456                                                         if (readSet != null) {
1457                                                                 Iterator<EffectsKey> readIter = readSet
1458                                                                                 .iterator();
1459                                                                 while (readIter.hasNext()) {
1460                                                                         EffectsKey key = readIter.next();
1461                                                                         Set<Integer> hrnSet = getCallerHRNId(
1462                                                                                         new Integer(i + base), calleeOG,
1463                                                                                         key.getHRNId(), decomp);
1464                                                                         Iterator<Integer> hrnIter = hrnSet
1465                                                                                         .iterator();
1466                                                                         while (hrnIter.hasNext()) {
1467                                                                                 Integer hrnID = (Integer) hrnIter
1468                                                                                                 .next();
1469                                                                                 currentSESE.readEffects(affectedTD, key
1470                                                                                                 .getFieldDescriptor(), key
1471                                                                                                 .getTypeDescriptor(), hrnID);
1472                                                                         }
1473                                                                 }
1474                                                         }
1475
1476                                                         if (writeSet != null) {
1477                                                                 Iterator<EffectsKey> writeIter = writeSet
1478                                                                                 .iterator();
1479                                                                 while (writeIter.hasNext()) {
1480                                                                         EffectsKey key = writeIter.next();
1481
1482                                                                         Set<Integer> hrnSet = getCallerHRNId(
1483                                                                                         new Integer(i + base), calleeOG,
1484                                                                                         key.getHRNId(), decomp);
1485                                                                         Iterator<Integer> hrnIter = hrnSet
1486                                                                                         .iterator();
1487                                                                         while (hrnIter.hasNext()) {
1488                                                                                 Integer hrnID = (Integer) hrnIter
1489                                                                                                 .next();
1490                                                                                 currentSESE.writeEffects(affectedTD,
1491                                                                                                 key.getFieldDescriptor(), key
1492                                                                                                                 .getTypeDescriptor(),
1493                                                                                                 hrnID, false);
1494                                                                         }
1495
1496                                                                 }
1497                                                         }
1498
1499                                                         if (strongUpdateSet != null) {
1500                                                                 Iterator<EffectsKey> strongUpdateIter = strongUpdateSet
1501                                                                                 .iterator();
1502                                                                 while (strongUpdateIter.hasNext()) {
1503                                                                         EffectsKey key = strongUpdateIter.next();
1504
1505                                                                         Set<Integer> hrnSet = getCallerHRNId(
1506                                                                                         new Integer(i + base), calleeOG,
1507                                                                                         key.getHRNId(), decomp);
1508                                                                         Iterator<Integer> hrnIter = hrnSet
1509                                                                                         .iterator();
1510                                                                         while (hrnIter.hasNext()) {
1511                                                                                 Integer hrnID = (Integer) hrnIter
1512                                                                                                 .next();
1513                                                                                 currentSESE.writeEffects(affectedTD,
1514                                                                                                 key.getFieldDescriptor(), key
1515                                                                                                                 .getTypeDescriptor(),
1516                                                                                                 hrnID, true);
1517                                                                         }
1518
1519                                                                 }
1520                                                         }
1521
1522                                                 }
1523
1524                                         }
1525
1526                                 }
1527
1528                         }
1529
1530                 }
1531                         break;
1532
1533                 }
1534         }
1535         
1536         private void addLiveInAllocationSite(MethodContext mc, AllocationSite ac){
1537                 HashSet<AllocationSite> set=mapMethodContextToLiveInAllocationSiteSet.get(mc);
1538                 if(set==null){
1539                         set=new HashSet<AllocationSite>();                      
1540                 }
1541                 set.add(ac);
1542                 mapMethodContextToLiveInAllocationSiteSet.put(mc, set);
1543         }
1544         
1545         private void followReference(HeapRegionNode hrn,HashSet<TempDescriptor> tdSet, HashSet<HeapRegionNode> visited, FlatSESEEnterNode currentSESE){
1546                 
1547                 Iterator<ReferenceEdge> referIter=hrn.iteratorToReferencers();
1548                 // check whether hrn is referenced by TD
1549                 while (referIter.hasNext()) {
1550                         ReferenceEdge referEdge = (ReferenceEdge) referIter.next();
1551                         if(referEdge.getSrc() instanceof LabelNode){
1552                                 LabelNode ln=(LabelNode)referEdge.getSrc();
1553                                 if(currentSESE.getInVarSet().contains(ln.getTempDescriptor())){
1554                                         tdSet.add(ln.getTempDescriptor());
1555                                 }
1556                         }else if(referEdge.getSrc() instanceof HeapRegionNode){
1557                                 HeapRegionNode nextHRN=(HeapRegionNode)referEdge.getSrc();
1558                                 if(!visited.contains(nextHRN)){
1559                                         visited.add(nextHRN);
1560                                         followReference(nextHRN,tdSet,visited,currentSESE);                             
1561                                 }
1562                                 
1563                         }
1564                 }
1565                 
1566         }
1567         
1568         private Set<Integer> getCallerHRNId(Integer paramIdx,
1569                         OwnershipGraph calleeOG, Integer calleeHRNId,
1570                         ParameterDecomposition paramDecom) {
1571                 
1572                 Integer hrnPrimaryID = calleeOG.paramIndex2idPrimary.get(paramIdx);
1573                 Integer hrnSecondaryID = calleeOG.paramIndex2idSecondary.get(paramIdx);
1574                 
1575                 if (calleeHRNId.equals(hrnPrimaryID)) {
1576                         // it references to primary param heap region
1577                         return paramDecom.getParamObject_hrnIDs(paramIdx);
1578                 } else if (calleeHRNId.equals(hrnSecondaryID)) {
1579                         // it references to secondary param heap region
1580                         return paramDecom.getParamReachable_hrnIDs(paramIdx);
1581                 }
1582
1583                 return new HashSet<Integer>();
1584         }
1585         
1586         private void taintLabelNode(LabelNode ln, int identifier) {
1587
1588                 Iterator<ReferenceEdge> edgeIter = ln.iteratorToReferencees();
1589                 while (edgeIter.hasNext()) {
1590                         ReferenceEdge edge = edgeIter.next();
1591                         HeapRegionNode hrn = edge.getDst();
1592
1593                         Iterator<ReferenceEdge> edgeReferencerIter = hrn
1594                                         .iteratorToReferencers();
1595                         while (edgeReferencerIter.hasNext()) {
1596                                 ReferenceEdge referencerEdge = edgeReferencerIter.next();
1597                                 OwnershipNode node = referencerEdge.getSrc();
1598                                 if (node instanceof LabelNode) {
1599                                         referencerEdge.unionSESETaintIdentifier(identifier);
1600                                 }else if(node instanceof HeapRegionNode){
1601                                         referencerEdge.unionSESETaintIdentifier(identifier);
1602                                 }
1603                         }
1604
1605                 }
1606
1607         }
1608         
1609         private HashSet<TempDescriptor> getReferenceNodeSet(HeapRegionNode hrn){
1610                 
1611                 HashSet<TempDescriptor> returnSet=new HashSet<TempDescriptor>();
1612                 
1613                 Iterator<ReferenceEdge> edgeIter=hrn.iteratorToReferencers();
1614                 while(edgeIter.hasNext()){
1615                         ReferenceEdge edge=edgeIter.next();
1616                         if(edge.getSrc() instanceof LabelNode){
1617                                 LabelNode ln=(LabelNode)edge.getSrc();
1618                                 returnSet.add(ln.getTempDescriptor());
1619                         }
1620                 }
1621                 
1622                 return returnSet;
1623                 
1624         }
1625         
1626         
1627         private HashSet<HeapRegionNode> getReferenceHeapIDSet(OwnershipGraph og, TempDescriptor td){
1628                 
1629                 HashSet<HeapRegionNode> returnSet=new HashSet<HeapRegionNode>();
1630                 
1631                 LabelNode ln=og.td2ln.get(td);
1632                 Iterator<ReferenceEdge> edgeIter=ln.iteratorToReferencees();
1633                 while(edgeIter.hasNext()){
1634                         ReferenceEdge edge=edgeIter.next();
1635                                 HeapRegionNode hrn=edge.getDst();
1636                                 returnSet.add(hrn);
1637                 }
1638                 return returnSet;
1639         }
1640         
1641         
1642         private HashSet<TempDescriptor> getAccessedTaintNodeSet(LabelNode ln) {
1643
1644                 HashSet<TempDescriptor> returnSet = new HashSet<TempDescriptor>();
1645
1646                 Iterator<ReferenceEdge> edgeIter = ln.iteratorToReferencees();
1647                 while (edgeIter.hasNext()) {
1648                         ReferenceEdge edge = edgeIter.next();
1649                         HeapRegionNode hrn = edge.getDst();
1650
1651                         Iterator<ReferenceEdge> edgeReferencerIter = hrn
1652                                         .iteratorToReferencers();
1653                         while (edgeReferencerIter.hasNext()) {
1654                                 ReferenceEdge referencerEdge = edgeReferencerIter.next();
1655
1656                                 if (referencerEdge.getSrc() instanceof LabelNode) {
1657                                         if (!((LabelNode) referencerEdge.getSrc()).equals(ln)) {
1658
1659                                                 if (referencerEdge.getSESETaintIdentifier() > 0) {
1660                                                         TempDescriptor td = ((LabelNode) referencerEdge
1661                                                                         .getSrc()).getTempDescriptor();
1662                                                         returnSet.add(td);
1663                                                 }
1664                                         }
1665                                 }
1666                         }
1667
1668                 }
1669
1670                 return returnSet;
1671
1672         }
1673
1674
1675   private void codePlansForward( FlatMethod fm ) {
1676     
1677     // start from flat method top, visit every node in
1678     // method exactly once
1679     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
1680     flatNodesToVisit.add( fm );
1681
1682     Set<FlatNode> visited = new HashSet<FlatNode>();    
1683
1684     while( !flatNodesToVisit.isEmpty() ) {
1685       Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
1686       FlatNode fn = fnItr.next();
1687
1688       flatNodesToVisit.remove( fn );
1689       visited.add( fn );      
1690
1691       Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
1692       assert seseStack != null;      
1693
1694       // use incoming results as "dot statement" or just
1695       // before the current statement
1696       VarSrcTokTable dotSTtable = new VarSrcTokTable();
1697       for( int i = 0; i < fn.numPrev(); i++ ) {
1698         FlatNode nn = fn.getPrev( i );
1699         dotSTtable.merge( variableResults.get( nn ) );
1700       }
1701
1702       // find dt-st notAvailableSet also
1703       Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();      
1704       for( int i = 0; i < fn.numPrev(); i++ ) {
1705         FlatNode nn = fn.getPrev( i );       
1706         Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
1707         if( notAvailIn != null ) {
1708           dotSTnotAvailSet.addAll( notAvailIn );
1709         }
1710       }
1711
1712       Set<TempDescriptor> dotSTlive = livenessRootView.get( fn );
1713
1714       if( !seseStack.empty() ) {
1715         codePlans_nodeActions( fn, 
1716                                dotSTlive,
1717                                dotSTtable,
1718                                dotSTnotAvailSet,
1719                                seseStack.peek()
1720                                );
1721       }
1722
1723       for( int i = 0; i < fn.numNext(); i++ ) {
1724         FlatNode nn = fn.getNext( i );
1725
1726         if( !visited.contains( nn ) ) {
1727           flatNodesToVisit.add( nn );
1728         }
1729       }
1730     }
1731   }
1732
1733   private void codePlans_nodeActions( FlatNode fn,
1734                                       Set<TempDescriptor> liveSetIn,
1735                                       VarSrcTokTable vstTableIn,
1736                                       Set<TempDescriptor> notAvailSetIn,
1737                                       FlatSESEEnterNode currentSESE ) {
1738     
1739     CodePlan plan = new CodePlan( currentSESE);
1740
1741     switch( fn.kind() ) {
1742
1743     case FKind.FlatSESEEnterNode: {
1744       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
1745
1746       // track the source types of the in-var set so generated
1747       // code at this SESE issue can compute the number of
1748       // dependencies properly
1749       Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
1750       while( inVarItr.hasNext() ) {
1751         TempDescriptor inVar = inVarItr.next();
1752         Integer srcType = 
1753           vstTableIn.getRefVarSrcType( inVar, 
1754                                        fsen,
1755                                        fsen.getParent() );
1756
1757         // the current SESE needs a local space to track the dynamic
1758         // variable and the child needs space in its SESE record
1759         if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1760           fsen.addDynamicInVar( inVar );
1761           fsen.getParent().addDynamicVar( inVar );
1762
1763         } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
1764           fsen.addStaticInVar( inVar );
1765           VariableSourceToken vst = vstTableIn.get( inVar ).iterator().next();
1766           fsen.putStaticInVar2src( inVar, vst );
1767           fsen.addStaticInVarSrc( new SESEandAgePair( vst.getSESE(), 
1768                                                       vst.getAge() 
1769                                                     ) 
1770                                 );
1771
1772         } else {
1773           assert srcType.equals( VarSrcTokTable.SrcType_READY );
1774           fsen.addReadyInVar( inVar );
1775         }       
1776       }
1777
1778     } break;
1779
1780     case FKind.FlatSESEExitNode: {
1781       FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
1782     } break;
1783
1784     case FKind.FlatOpNode: {
1785       FlatOpNode fon = (FlatOpNode) fn;
1786
1787       if( fon.getOp().getOp() == Operation.ASSIGN ) {
1788         TempDescriptor lhs = fon.getDest();
1789         TempDescriptor rhs = fon.getLeft();        
1790
1791         // if this is an op node, don't stall, copy
1792         // source and delay until we need to use value
1793
1794         // ask whether lhs and rhs sources are dynamic, static, etc.
1795         Integer lhsSrcType
1796           = vstTableIn.getRefVarSrcType( lhs,
1797                                          currentSESE,
1798                                          currentSESE.getParent() );
1799
1800         Integer rhsSrcType
1801           = vstTableIn.getRefVarSrcType( rhs,
1802                                          currentSESE,
1803                                          currentSESE.getParent() );
1804
1805         if( rhsSrcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1806           // if rhs is dynamic going in, lhs will definitely be dynamic
1807           // going out of this node, so track that here   
1808           plan.addDynAssign( lhs, rhs );
1809           currentSESE.addDynamicVar( lhs );
1810           currentSESE.addDynamicVar( rhs );
1811
1812         } else if( lhsSrcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1813           // otherwise, if the lhs is dynamic, but the rhs is not, we
1814           // need to update the variable's dynamic source as "current SESE"
1815           plan.addDynAssign( lhs );
1816         }       
1817
1818         // only break if this is an ASSIGN op node,
1819         // otherwise fall through to default case
1820         break;
1821       }
1822     }
1823
1824     // note that FlatOpNode's that aren't ASSIGN
1825     // fall through to this default case
1826     default: {          
1827
1828       // a node with no live set has nothing to stall for
1829       if( liveSetIn == null ) {
1830         break;
1831       }
1832
1833       TempDescriptor[] readarray = fn.readsTemps();
1834       for( int i = 0; i < readarray.length; i++ ) {
1835         TempDescriptor readtmp = readarray[i];
1836
1837         // ignore temps that are definitely available 
1838         // when considering to stall on it
1839         if( !notAvailSetIn.contains( readtmp ) ) {
1840           continue;
1841         }
1842
1843         // check the source type of this variable
1844         Integer srcType 
1845           = vstTableIn.getRefVarSrcType( readtmp,
1846                                          currentSESE,
1847                                          currentSESE.getParent() );
1848
1849         if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1850           // 1) It is not clear statically where this variable will
1851           // come from statically, so dynamically we must keep track
1852           // along various control paths, and therefore when we stall,
1853           // just stall for the exact thing we need and move on
1854           plan.addDynamicStall( readtmp );
1855           currentSESE.addDynamicVar( readtmp );  
1856
1857         } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {    
1858           // 2) Single token/age pair: Stall for token/age pair, and copy
1859           // all live variables with same token/age pair at the same
1860           // time.  This is the same stuff that the notavaialable analysis 
1861           // marks as now available.      
1862
1863           VariableSourceToken vst = vstTableIn.get( readtmp ).iterator().next();
1864
1865           Iterator<VariableSourceToken> availItr = 
1866             vstTableIn.get( vst.getSESE(), vst.getAge() ).iterator();
1867
1868           while( availItr.hasNext() ) {
1869             VariableSourceToken vstAlsoAvail = availItr.next();
1870
1871             // only grab additional stuff that is live
1872             Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
1873
1874             Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
1875             while( refVarItr.hasNext() ) {
1876               TempDescriptor refVar = refVarItr.next();
1877               if( liveSetIn.contains( refVar ) ) {
1878                 copySet.add( refVar );
1879               }
1880             }
1881
1882             if( !copySet.isEmpty() ) {
1883               plan.addStall2CopySet( vstAlsoAvail, copySet );
1884             }
1885           }                      
1886
1887         } else {
1888           // the other case for srcs is READY, so do nothing
1889         }
1890
1891         // assert that everything being stalled for is in the
1892         // "not available" set coming into this flat node and
1893         // that every VST identified is in the possible "stall set"
1894         // that represents VST's from children SESE's
1895
1896       }      
1897     } break;
1898       
1899     } // end switch
1900
1901
1902     // identify sese-age pairs that are statically useful
1903     // and should have an associated SESE variable in code
1904     // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
1905     // AND ALWAYS GIVE NAMES TO PARENTS
1906     Set<VariableSourceToken> staticSet = vstTableIn.get();
1907     Iterator<VariableSourceToken> vstItr = staticSet.iterator();
1908     while( vstItr.hasNext() ) {
1909       VariableSourceToken vst = vstItr.next();
1910
1911       // placeholder source tokens are useful results, but
1912       // the placeholder static name is never needed
1913       if( vst.getSESE().getIsCallerSESEplaceholder() ) {
1914         continue;
1915       }
1916
1917       FlatSESEEnterNode sese = currentSESE;
1918       while( sese != null ) {
1919         sese.addNeededStaticName( 
1920                                  new SESEandAgePair( vst.getSESE(), vst.getAge() ) 
1921                                   );
1922         sese.mustTrackAtLeastAge( vst.getAge() );
1923         
1924         sese = sese.getParent();
1925       }
1926     }
1927
1928
1929     codePlans.put( fn, plan );
1930
1931
1932     // if any variables at this-node-*dot* have a static source (exactly one vst)
1933     // but go to a dynamic source at next-node-*dot*, create a new IR graph
1934     // node on that edge to track the sources dynamically
1935     VarSrcTokTable thisVstTable = variableResults.get( fn );
1936     for( int i = 0; i < fn.numNext(); i++ ) {
1937       FlatNode            nn           = fn.getNext( i );
1938       VarSrcTokTable      nextVstTable = variableResults.get( nn );
1939       Set<TempDescriptor> nextLiveIn   = livenessRootView.get( nn );
1940
1941       // the table can be null if it is one of the few IR nodes
1942       // completely outside of the root SESE scope
1943       if( nextVstTable != null && nextLiveIn != null ) {
1944
1945         Hashtable<TempDescriptor, VariableSourceToken> static2dynamicSet = 
1946           thisVstTable.getStatic2DynamicSet( nextVstTable, 
1947                                              nextLiveIn,
1948                                              currentSESE,
1949                                              currentSESE.getParent() 
1950                                            );
1951         
1952         if( !static2dynamicSet.isEmpty() ) {
1953
1954           // either add these results to partial fixed-point result
1955           // or make a new one if we haven't made any here yet
1956           FlatEdge fe = new FlatEdge( fn, nn );
1957           FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get( fe );
1958
1959           if( fwdvn == null ) {
1960             fwdvn = new FlatWriteDynamicVarNode( fn, 
1961                                                  nn,
1962                                                  static2dynamicSet,
1963                                                  currentSESE
1964                                                  );
1965             wdvNodesToSpliceIn.put( fe, fwdvn );
1966           } else {
1967             fwdvn.addMoreVar2Src( static2dynamicSet );
1968           }
1969         }
1970       }
1971     }
1972   }
1973
1974
1975   public void writeReports( String timeReport ) throws java.io.IOException {
1976
1977     BufferedWriter bw = new BufferedWriter( new FileWriter( "mlpReport_summary.txt" ) );
1978     bw.write( "MLP Analysis Results\n\n" );
1979     bw.write( timeReport+"\n\n" );
1980     printSESEHierarchy( bw );
1981     bw.write( "\n" );
1982     printSESEInfo( bw );
1983     bw.close();
1984
1985     Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
1986     while( methItr.hasNext() ) {
1987       MethodDescriptor md = (MethodDescriptor) methItr.next();      
1988       FlatMethod       fm = state.getMethodFlat( md );
1989       bw = new BufferedWriter( new FileWriter( "mlpReport_"+
1990                                                md.getClassMethodName()+
1991                                                md.getSafeMethodDescriptor()+
1992                                                ".txt" ) );
1993       bw.write( "MLP Results for "+md+"\n-------------------\n");
1994       bw.write( "\n\nLive-In, Root View\n------------------\n"          +fm.printMethod( livenessRootView ) );
1995       bw.write( "\n\nVariable Results-Out\n----------------\n"          +fm.printMethod( variableResults ) );
1996       bw.write( "\n\nNot Available Results-Out\n---------------------\n"+fm.printMethod( notAvailableResults ) );
1997       bw.write( "\n\nCode Plans\n----------\n"                          +fm.printMethod( codePlans ) );
1998       bw.write("\n\nSESE Effects\n----------------------\n"+printSESEEffects());
1999       bw.close();
2000     }
2001   }
2002   
2003         private String printSESEEffects() {
2004
2005                 StringWriter writer = new StringWriter();
2006
2007                 Iterator<FlatSESEEnterNode> keyIter = allSESEs.iterator();
2008
2009                 while (keyIter.hasNext()) {
2010                         FlatSESEEnterNode seseEnter = keyIter.next();
2011                         String result = seseEnter.getSeseEffectsSet().printSet();
2012                         if (result.length() > 0) {
2013                                 writer.write("\nSESE " + seseEnter + "\n");
2014                                 writer.write(result);
2015                         }
2016                 }
2017                 keyIter = rootSESEs.iterator();
2018                 while (keyIter.hasNext()) {
2019                         FlatSESEEnterNode seseEnter = keyIter.next();
2020                         if (seseEnter.getIsCallerSESEplaceholder()) {
2021                                 if (!seseEnter.getChildren().isEmpty()) {
2022                                         String result = seseEnter.getSeseEffectsSet().printSet();
2023                                         if (result.length() > 0) {
2024                                                 writer.write("\nSESE " + seseEnter + "\n");
2025                                                 writer.write(result);
2026                                         }
2027                                 }
2028                         }
2029                 }
2030
2031                 return writer.toString();
2032
2033         }
2034
2035   private void printSESEHierarchy( BufferedWriter bw ) throws java.io.IOException {
2036     bw.write( "SESE Hierarchy\n--------------\n" ); 
2037     Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
2038     while( rootItr.hasNext() ) {
2039       FlatSESEEnterNode root = rootItr.next();
2040       if( root.getIsCallerSESEplaceholder() ) {
2041         if( !root.getChildren().isEmpty() ) {
2042           printSESEHierarchyTree( bw, root, 0 );
2043         }
2044       } else {
2045         printSESEHierarchyTree( bw, root, 0 );
2046       }
2047     }
2048   }
2049
2050   private void printSESEHierarchyTree( BufferedWriter bw,
2051                                        FlatSESEEnterNode fsen,
2052                                        int depth 
2053                                      ) throws java.io.IOException {
2054     for( int i = 0; i < depth; ++i ) {
2055       bw.write( "  " );
2056     }
2057     bw.write( "- "+fsen.getPrettyIdentifier()+"\n" );
2058
2059     Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
2060     while( childItr.hasNext() ) {
2061       FlatSESEEnterNode fsenChild = childItr.next();
2062       printSESEHierarchyTree( bw, fsenChild, depth + 1 );
2063     }
2064   }
2065
2066   
2067   private void printSESEInfo( BufferedWriter bw ) throws java.io.IOException {
2068     bw.write("\nSESE info\n-------------\n" ); 
2069     Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
2070     while( rootItr.hasNext() ) {
2071       FlatSESEEnterNode root = rootItr.next();
2072       if( root.getIsCallerSESEplaceholder() ) {
2073         if( !root.getChildren().isEmpty() ) {
2074           printSESEInfoTree( bw, root );
2075         }
2076       } else {
2077         printSESEInfoTree( bw, root );
2078       }
2079     }
2080   }
2081
2082   private void printSESEInfoTree( BufferedWriter bw,
2083                                   FlatSESEEnterNode fsen 
2084                                 ) throws java.io.IOException {
2085
2086     if( !fsen.getIsCallerSESEplaceholder() ) {
2087       bw.write( "SESE "+fsen.getPrettyIdentifier()+" {\n" );
2088
2089       bw.write( "  in-set: "+fsen.getInVarSet()+"\n" );
2090       Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
2091       while( tItr.hasNext() ) {
2092         TempDescriptor inVar = tItr.next();
2093         if( fsen.getReadyInVarSet().contains( inVar ) ) {
2094           bw.write( "    (ready)  "+inVar+"\n" );
2095         }
2096         if( fsen.getStaticInVarSet().contains( inVar ) ) {
2097           bw.write( "    (static) "+inVar+"\n" );
2098         } 
2099         if( fsen.getDynamicInVarSet().contains( inVar ) ) {
2100           bw.write( "    (dynamic)"+inVar+"\n" );
2101         }
2102       }
2103       
2104       bw.write( "  out-set: "+fsen.getOutVarSet()+"\n" );
2105       bw.write( "}\n" );
2106     }
2107
2108     Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
2109     while( childItr.hasNext() ) {
2110       FlatSESEEnterNode fsenChild = childItr.next();
2111       printSESEInfoTree( bw, fsenChild );
2112     }
2113   }
2114 }