3 import Analysis.CallGraph.*;
4 import Analysis.OwnershipAnalysis.*;
12 public class MLPAnalysis {
14 // data from the compiler
16 private TypeUtil typeUtil;
17 private CallGraph callGraph;
18 private OwnershipAnalysis ownAnalysis;
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;
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;
33 // simply a set of every reachable SESE in the program, not
34 // including caller placeholder SESEs
35 private Set<FlatSESEEnterNode> allSESEs;
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;
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;
50 private Hashtable< FlatEdge, FlatWriteDynamicVarNode > wdvNodesToSpliceIn;
52 public static int maxSESEage = -1;
55 // use these methods in BuildCode to have access to analysis results
56 public FlatSESEEnterNode getMainSESE() {
60 public Set<FlatSESEEnterNode> getRootSESEs() {
64 public Set<FlatSESEEnterNode> getAllSESEs() {
68 public int getMaxSESEage() {
73 public CodePlan getCodePlan( FlatNode fn ) {
74 CodePlan cp = codePlans.get( fn );
79 public MLPAnalysis( State state,
82 OwnershipAnalysis ownAnalysis
85 double timeStartAnalysis = (double) System.nanoTime();
89 this.callGraph = callGraph;
90 this.ownAnalysis = ownAnalysis;
91 this.maxSESEage = state.MLP_MAXSESEAGE;
93 rootSESEs = new HashSet<FlatSESEEnterNode>();
94 allSESEs = new HashSet<FlatSESEEnterNode>();
96 seseStacks = new Hashtable< FlatNode, Stack<FlatSESEEnterNode> >();
97 livenessRootView = new Hashtable< FlatNode, Set<TempDescriptor> >();
98 livenessVirtualReads = new Hashtable< FlatNode, Set<TempDescriptor> >();
99 variableResults = new Hashtable< FlatNode, VarSrcTokTable >();
100 notAvailableResults = new Hashtable< FlatNode, Set<TempDescriptor> >();
101 codePlans = new Hashtable< FlatNode, CodePlan >();
102 wdvNodesToSpliceIn = new Hashtable< FlatEdge, FlatWriteDynamicVarNode >();
105 FlatMethod fmMain = state.getMethodFlat( typeUtil.getMain() );
107 mainSESE = (FlatSESEEnterNode) fmMain.getNext(0);
108 mainSESE.setfmEnclosing( fmMain );
109 mainSESE.setmdEnclosing( fmMain.getMethod() );
110 mainSESE.setcdEnclosing( fmMain.getMethod().getClassDesc() );
114 // run analysis on each method that is actually called
115 // reachability analysis already computed this so reuse
116 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
117 while( methItr.hasNext() ) {
118 Descriptor d = methItr.next();
119 FlatMethod fm = state.getMethodFlat( d );
121 // find every SESE from methods that may be called
122 // and organize them into roots and children
123 buildForestForward( fm );
127 // 2nd pass, results are saved in FlatSESEEnterNode, so
128 // intermediate results, for safety, are discarded
129 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
130 while( rootItr.hasNext() ) {
131 FlatSESEEnterNode root = rootItr.next();
132 livenessAnalysisBackward( root,
139 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
140 while( methItr.hasNext() ) {
141 Descriptor d = methItr.next();
142 FlatMethod fm = state.getMethodFlat( d );
144 // starting from roots do a forward, fixed-point
145 // variable analysis for refinement and stalls
146 variableAnalysisForward( fm );
149 // 4th pass, compute liveness contribution from
150 // virtual reads discovered in variable pass
151 rootItr = rootSESEs.iterator();
152 while( rootItr.hasNext() ) {
153 FlatSESEEnterNode root = rootItr.next();
154 livenessAnalysisBackward( root,
161 SOMETHING IS WRONG WITH THIS, DON'T USE IT UNTIL IT CAN BE FIXED
164 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
165 while( methItr.hasNext() ) {
166 Descriptor d = methItr.next();
167 FlatMethod fm = state.getMethodFlat( d );
169 // prune variable results in one traversal
170 // by removing reference variables that are not live
171 pruneVariableResultsWithLiveness( fm );
177 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
178 while( methItr.hasNext() ) {
179 Descriptor d = methItr.next();
180 FlatMethod fm = state.getMethodFlat( d );
182 // compute what is not available at every program
183 // point, in a forward fixed-point pass
184 notAvailableForward( fm );
188 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
189 while( methItr.hasNext() ) {
190 Descriptor d = methItr.next();
191 FlatMethod fm = state.getMethodFlat( d );
197 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
198 while( methItr.hasNext() ) {
199 Descriptor d = methItr.next();
200 FlatMethod fm = state.getMethodFlat( d );
202 // compute a plan for code injections
203 codePlansForward( fm );
207 // splice new IR nodes into graph after all
208 // analysis passes are complete
209 Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
210 while( spliceItr.hasNext() ) {
211 Map.Entry me = (Map.Entry) spliceItr.next();
212 FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
213 fwdvn.spliceIntoIR();
217 double timeEndAnalysis = (double) System.nanoTime();
218 double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
219 String treport = String.format( "The mlp analysis took %.3f sec.", dt );
220 System.out.println( treport );
222 if( state.MLPDEBUG ) {
224 writeReports( treport );
225 } catch( IOException e ) {}
230 private void buildForestForward( FlatMethod fm ) {
232 // start from flat method top, visit every node in
233 // method exactly once, find SESEs and remember
234 // roots and child relationships
235 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
236 flatNodesToVisit.add( fm );
238 Set<FlatNode> visited = new HashSet<FlatNode>();
240 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
241 seseStacks.put( fm, seseStackFirst );
243 while( !flatNodesToVisit.isEmpty() ) {
244 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
245 FlatNode fn = fnItr.next();
247 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
248 assert seseStack != null;
250 flatNodesToVisit.remove( fn );
253 buildForest_nodeActions( fn, seseStack, fm );
255 for( int i = 0; i < fn.numNext(); i++ ) {
256 FlatNode nn = fn.getNext( i );
258 if( !visited.contains( nn ) ) {
259 flatNodesToVisit.add( nn );
261 // clone stack and send along each analysis path
262 seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
268 private void buildForest_nodeActions( FlatNode fn,
269 Stack<FlatSESEEnterNode> seseStack,
271 switch( fn.kind() ) {
273 case FKind.FlatSESEEnterNode: {
274 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
276 if( !fsen.getIsCallerSESEplaceholder() ) {
277 allSESEs.add( fsen );
280 fsen.setfmEnclosing( fm );
281 fsen.setmdEnclosing( fm.getMethod() );
282 fsen.setcdEnclosing( fm.getMethod().getClassDesc() );
284 if( seseStack.empty() ) {
285 rootSESEs.add( fsen );
286 fsen.setParent( null );
288 seseStack.peek().addChild( fsen );
289 fsen.setParent( seseStack.peek() );
292 seseStack.push( fsen );
295 case FKind.FlatSESEExitNode: {
296 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
297 assert !seseStack.empty();
298 FlatSESEEnterNode fsen = seseStack.pop();
301 case FKind.FlatReturnNode: {
302 FlatReturnNode frn = (FlatReturnNode) fn;
303 if( !seseStack.empty() &&
304 !seseStack.peek().getIsCallerSESEplaceholder()
306 throw new Error( "Error: return statement enclosed within SESE "+
307 seseStack.peek().getPrettyIdentifier() );
315 private void livenessAnalysisBackward( FlatSESEEnterNode fsen,
317 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout ) {
319 // start from an SESE exit, visit nodes in reverse up to
320 // SESE enter in a fixed-point scheme, where children SESEs
321 // should already be analyzed and therefore can be skipped
322 // because child SESE enter node has all necessary info
323 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
326 flatNodesToVisit.add( fsen.getfmEnclosing().getFlatExit() );
328 flatNodesToVisit.add( fsen.getFlatExit() );
331 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults =
332 new Hashtable< FlatNode, Set<TempDescriptor> >();
335 liveout = new Hashtable< FlatSESEExitNode, Set<TempDescriptor> >();
338 while( !flatNodesToVisit.isEmpty() ) {
339 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
340 flatNodesToVisit.remove( fn );
342 Set<TempDescriptor> prev = livenessResults.get( fn );
344 // merge sets from control flow joins
345 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
346 for( int i = 0; i < fn.numNext(); i++ ) {
347 FlatNode nn = fn.getNext( i );
348 Set<TempDescriptor> s = livenessResults.get( nn );
354 Set<TempDescriptor> curr = liveness_nodeActions( fn, u, fsen, toplevel, liveout);
356 // if a new result, schedule backward nodes for analysis
357 if( !curr.equals( prev ) ) {
358 livenessResults.put( fn, curr );
360 // don't flow backwards past current SESE enter
361 if( !fn.equals( fsen ) ) {
362 for( int i = 0; i < fn.numPrev(); i++ ) {
363 FlatNode nn = fn.getPrev( i );
364 flatNodesToVisit.add( nn );
370 Set<TempDescriptor> s = livenessResults.get( fsen );
372 fsen.addInVarSet( s );
375 // remember liveness per node from the root view as the
376 // global liveness of variables for later passes to use
378 livenessRootView.putAll( livenessResults );
381 // post-order traversal, so do children first
382 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
383 while( childItr.hasNext() ) {
384 FlatSESEEnterNode fsenChild = childItr.next();
385 livenessAnalysisBackward( fsenChild, false, liveout );
389 private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
390 Set<TempDescriptor> liveIn,
391 FlatSESEEnterNode currentSESE,
393 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout
395 switch( fn.kind() ) {
397 case FKind.FlatSESEExitNode:
399 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
400 if( !liveout.containsKey( fsexn ) ) {
401 liveout.put( fsexn, new HashSet<TempDescriptor>() );
403 liveout.get( fsexn ).addAll( liveIn );
405 // no break, sese exits should also execute default actions
408 // handle effects of statement in reverse, writes then reads
409 TempDescriptor [] writeTemps = fn.writesTemps();
410 for( int i = 0; i < writeTemps.length; ++i ) {
411 liveIn.remove( writeTemps[i] );
414 FlatSESEExitNode fsexn = currentSESE.getFlatExit();
415 Set<TempDescriptor> livetemps = liveout.get( fsexn );
416 if( livetemps != null &&
417 livetemps.contains( writeTemps[i] ) ) {
418 // write to a live out temp...
419 // need to put in SESE liveout set
420 currentSESE.addOutVar( writeTemps[i] );
425 TempDescriptor [] readTemps = fn.readsTemps();
426 for( int i = 0; i < readTemps.length; ++i ) {
427 liveIn.add( readTemps[i] );
430 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get( fn );
431 if( virtualReadTemps != null ) {
432 liveIn.addAll( virtualReadTemps );
443 private void variableAnalysisForward( FlatMethod fm ) {
445 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
446 flatNodesToVisit.add( fm );
448 while( !flatNodesToVisit.isEmpty() ) {
449 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
450 flatNodesToVisit.remove( fn );
452 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
453 assert seseStack != null;
455 VarSrcTokTable prev = variableResults.get( fn );
457 // merge sets from control flow joins
458 VarSrcTokTable curr = new VarSrcTokTable();
459 for( int i = 0; i < fn.numPrev(); i++ ) {
460 FlatNode nn = fn.getPrev( i );
461 VarSrcTokTable incoming = variableResults.get( nn );
462 curr.merge( incoming );
465 if( !seseStack.empty() ) {
466 variable_nodeActions( fn, curr, seseStack.peek() );
469 // if a new result, schedule forward nodes for analysis
470 if( !curr.equals( prev ) ) {
471 variableResults.put( fn, curr );
473 for( int i = 0; i < fn.numNext(); i++ ) {
474 FlatNode nn = fn.getNext( i );
475 flatNodesToVisit.add( nn );
481 private void variable_nodeActions( FlatNode fn,
482 VarSrcTokTable vstTable,
483 FlatSESEEnterNode currentSESE ) {
484 switch( fn.kind() ) {
486 case FKind.FlatSESEEnterNode: {
487 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
488 assert fsen.equals( currentSESE );
490 vstTable.age( currentSESE );
491 vstTable.assertConsistency();
494 case FKind.FlatSESEExitNode: {
495 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
496 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
497 assert currentSESE.getChildren().contains( fsen );
499 vstTable.remapChildTokens( fsen );
501 // liveness virtual reads are things that might be
502 // written by an SESE and should be added to the in-set
503 // anything virtually read by this SESE should be pruned
504 // of parent or sibling sources
505 Set<TempDescriptor> liveVars = livenessRootView.get( fn );
506 Set<TempDescriptor> fsenVirtReads = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens( fsen, liveVars );
507 Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get( fn );
508 if( fsenVirtReadsOld != null ) {
509 fsenVirtReads.addAll( fsenVirtReadsOld );
511 livenessVirtualReads.put( fn, fsenVirtReads );
514 // then all child out-set tokens are guaranteed
515 // to be filled in, so clobber those entries with
516 // the latest, clean sources
517 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
518 while( outVarItr.hasNext() ) {
519 TempDescriptor outVar = outVarItr.next();
520 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
522 VariableSourceToken vst =
523 new VariableSourceToken( ts,
528 vstTable.remove( outVar );
531 vstTable.assertConsistency();
535 case FKind.FlatOpNode: {
536 FlatOpNode fon = (FlatOpNode) fn;
538 if( fon.getOp().getOp() == Operation.ASSIGN ) {
539 TempDescriptor lhs = fon.getDest();
540 TempDescriptor rhs = fon.getLeft();
542 vstTable.remove( lhs );
544 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
546 Iterator<VariableSourceToken> itr = vstTable.get( rhs ).iterator();
547 while( itr.hasNext() ) {
548 VariableSourceToken vst = itr.next();
550 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
553 if( currentSESE.getChildren().contains( vst.getSESE() ) ) {
554 // if the source comes from a child, copy it over
555 forAddition.add( new VariableSourceToken( ts,
562 // otherwise, stamp it as us as the source
563 forAddition.add( new VariableSourceToken( ts,
572 vstTable.addAll( forAddition );
574 // only break if this is an ASSIGN op node,
575 // otherwise fall through to default case
576 vstTable.assertConsistency();
581 // note that FlatOpNode's that aren't ASSIGN
582 // fall through to this default case
584 TempDescriptor [] writeTemps = fn.writesTemps();
585 if( writeTemps.length > 0 ) {
588 // for now, when writeTemps > 1, make sure
589 // its a call node, programmer enforce only
590 // doing stuff like calling a print routine
591 //assert writeTemps.length == 1;
592 if( writeTemps.length > 1 ) {
593 assert fn.kind() == FKind.FlatCall ||
594 fn.kind() == FKind.FlatMethod;
598 vstTable.remove( writeTemps[0] );
600 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
601 ts.add( writeTemps[0] );
603 vstTable.add( new VariableSourceToken( ts,
611 vstTable.assertConsistency();
618 private void pruneVariableResultsWithLiveness( FlatMethod fm ) {
620 // start from flat method top, visit every node in
621 // method exactly once
622 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
623 flatNodesToVisit.add( fm );
625 Set<FlatNode> visited = new HashSet<FlatNode>();
627 while( !flatNodesToVisit.isEmpty() ) {
628 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
629 FlatNode fn = fnItr.next();
631 flatNodesToVisit.remove( fn );
634 Set<TempDescriptor> rootLiveSet = livenessRootView.get( fn );
635 VarSrcTokTable vstTable = variableResults.get( fn );
637 vstTable.pruneByLiveness( rootLiveSet );
639 for( int i = 0; i < fn.numNext(); i++ ) {
640 FlatNode nn = fn.getNext( i );
642 if( !visited.contains( nn ) ) {
643 flatNodesToVisit.add( nn );
650 private void notAvailableForward( FlatMethod fm ) {
652 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
653 flatNodesToVisit.add( fm );
655 while( !flatNodesToVisit.isEmpty() ) {
656 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
657 flatNodesToVisit.remove( fn );
659 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
660 assert seseStack != null;
662 Set<TempDescriptor> prev = notAvailableResults.get( fn );
664 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
665 for( int i = 0; i < fn.numPrev(); i++ ) {
666 FlatNode nn = fn.getPrev( i );
667 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
668 if( notAvailIn != null ) {
669 curr.addAll( notAvailIn );
673 if( !seseStack.empty() ) {
674 notAvailable_nodeActions( fn, curr, seseStack.peek() );
677 // if a new result, schedule forward nodes for analysis
678 if( !curr.equals( prev ) ) {
679 notAvailableResults.put( fn, curr );
681 for( int i = 0; i < fn.numNext(); i++ ) {
682 FlatNode nn = fn.getNext( i );
683 flatNodesToVisit.add( nn );
689 private void notAvailable_nodeActions( FlatNode fn,
690 Set<TempDescriptor> notAvailSet,
691 FlatSESEEnterNode currentSESE ) {
693 // any temps that are removed from the not available set
694 // at this node should be marked in this node's code plan
695 // as temps to be grabbed at runtime!
697 switch( fn.kind() ) {
699 case FKind.FlatSESEEnterNode: {
700 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
701 assert fsen.equals( currentSESE );
705 case FKind.FlatSESEExitNode: {
706 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
707 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
708 assert currentSESE.getChildren().contains( fsen );
709 notAvailSet.addAll( fsen.getOutVarSet() );
712 case FKind.FlatMethod: {
716 case FKind.FlatOpNode: {
717 FlatOpNode fon = (FlatOpNode) fn;
719 if( fon.getOp().getOp() == Operation.ASSIGN ) {
720 TempDescriptor lhs = fon.getDest();
721 TempDescriptor rhs = fon.getLeft();
723 // copy makes lhs same availability as rhs
724 if( notAvailSet.contains( rhs ) ) {
725 notAvailSet.add( lhs );
727 notAvailSet.remove( lhs );
730 // only break if this is an ASSIGN op node,
731 // otherwise fall through to default case
736 // note that FlatOpNode's that aren't ASSIGN
737 // fall through to this default case
739 TempDescriptor [] writeTemps = fn.writesTemps();
740 for( int i = 0; i < writeTemps.length; i++ ) {
741 TempDescriptor wTemp = writeTemps[i];
742 notAvailSet.remove( wTemp );
744 TempDescriptor [] readTemps = fn.readsTemps();
745 for( int i = 0; i < readTemps.length; i++ ) {
746 TempDescriptor rTemp = readTemps[i];
747 notAvailSet.remove( rTemp );
749 // if this variable has exactly one source, potentially
750 // get other things from this source as well
751 VarSrcTokTable vstTable = variableResults.get( fn );
754 vstTable.getRefVarSrcType( rTemp,
756 currentSESE.getParent() );
758 if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
760 VariableSourceToken vst = vstTable.get( rTemp ).iterator().next();
762 Iterator<VariableSourceToken> availItr = vstTable.get( vst.getSESE(),
766 // look through things that are also available from same source
767 while( availItr.hasNext() ) {
768 VariableSourceToken vstAlsoAvail = availItr.next();
770 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
771 while( refVarItr.hasNext() ) {
772 TempDescriptor refVarAlso = refVarItr.next();
774 // if a variable is available from the same source, AND it ALSO
775 // only comes from one statically known source, mark it available
776 Integer srcTypeAlso =
777 vstTable.getRefVarSrcType( refVarAlso,
779 currentSESE.getParent() );
780 if( srcTypeAlso.equals( VarSrcTokTable.SrcType_STATIC ) ) {
781 notAvailSet.remove( refVarAlso );
792 private void methodEffects(FlatMethod fm) {
794 MethodDescriptor md=fm.getMethod();
795 HashSet<MethodContext> mcSet=ownAnalysis.getAllMethodContextSetByDescriptor(md);
796 Iterator<MethodContext> mcIter=mcSet.iterator();
798 while(mcIter.hasNext()){
799 MethodContext mc=mcIter.next();
801 Set<FlatNode> visited = new HashSet<FlatNode>();
803 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
804 flatNodesToVisit.add(fm);
806 while (!flatNodesToVisit.isEmpty()) {
807 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
808 flatNodesToVisit.remove(fn);
810 Stack<FlatSESEEnterNode> seseStack = seseStacks.get(fn);
811 assert seseStack != null;
813 if (!seseStack.empty()) {
814 effects_nodeActions(mc, fn, seseStack.peek());
817 flatNodesToVisit.remove(fn);
820 for (int i = 0; i < fn.numNext(); i++) {
821 FlatNode nn = fn.getNext(i);
822 if (!visited.contains(nn)) {
823 flatNodesToVisit.add(nn);
834 private void effects_nodeActions(MethodContext mc, FlatNode fn,
835 FlatSESEEnterNode currentSESE) {
837 OwnershipGraph og = ownAnalysis.getOwnvershipGraphByMethodContext(mc);
841 case FKind.FlatSESEEnterNode: {
843 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
844 assert fsen.equals(currentSESE);
846 // uniquely taint each live-in variable
847 Set<TempDescriptor> set = fsen.getInVarSet();
848 Iterator<TempDescriptor> iter = set.iterator();
850 while (iter.hasNext()) {
851 TempDescriptor td = iter.next();
852 LabelNode ln = og.td2ln.get(td);
854 int taint = (int) Math.pow(2, idx);
855 taintLabelNode(ln, taint);
863 case FKind.FlatSESEExitNode: {
864 FlatSESEExitNode fsexit = (FlatSESEExitNode) fn;
866 FlatSESEEnterNode enterNode = fsexit.getFlatEnter();
867 FlatSESEEnterNode parent = enterNode.getParent();
868 if (parent != null) {
870 SESEEffectsSet set = enterNode.getSeseEffectsSet();
871 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> readTable = set
873 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentReadTable = parent
874 .getSeseEffectsSet().getReadTable();
875 Set<TempDescriptor> keys = readTable.keySet();
876 Iterator<TempDescriptor> keyIter = keys.iterator();
877 while (keyIter.hasNext()) {
878 TempDescriptor td = (TempDescriptor) keyIter.next();
879 HashSet<SESEEffectsKey> effectsSet = readTable.get(td);
880 HashSet<SESEEffectsKey> parentEffectsSet = parentReadTable
882 if (parentEffectsSet == null) {
883 parentEffectsSet = new HashSet<SESEEffectsKey>();
886 for (Iterator iterator = effectsSet.iterator(); iterator
888 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
890 parentEffectsSet.add(new SESEEffectsKey(seseKey.getFieldDescriptor(), seseKey.getTypeDescriptor(), seseKey.getHRNId()));
893 parentReadTable.put(td, parentEffectsSet);
896 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> writeTable = set
898 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentWriteTable = parent
899 .getSeseEffectsSet().getWriteTable();
900 keys = writeTable.keySet();
901 keyIter = keys.iterator();
902 while (keyIter.hasNext()) {
903 TempDescriptor td = (TempDescriptor) keyIter.next();
904 HashSet<SESEEffectsKey> effectsSet = writeTable.get(td);
905 HashSet<SESEEffectsKey> parentEffectsSet = parentWriteTable
907 if (parentEffectsSet == null) {
908 parentEffectsSet = new HashSet<SESEEffectsKey>();
911 for (Iterator iterator = effectsSet.iterator(); iterator
913 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
915 parentEffectsSet.add(new SESEEffectsKey(seseKey
916 .getFieldDescriptor(), seseKey
917 .getTypeDescriptor(), seseKey.getHRNId()));
920 parentWriteTable.put(td, parentEffectsSet);
928 case FKind.FlatFieldNode: {
930 FlatFieldNode ffn = (FlatFieldNode) fn;
931 TempDescriptor src = ffn.getSrc();
932 FieldDescriptor field = ffn.getField();
934 LabelNode srcLN = og.td2ln.get(src);
936 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(srcLN);
937 Iterator<TempDescriptor> affectedIter = affectedTDSet
939 while (affectedIter.hasNext()) {
940 TempDescriptor affectedTD = affectedIter.next();
941 if (currentSESE.getInVarSet().contains(affectedTD)) {
943 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
945 Iterator<HeapRegionNode> hrnIter = hrnSet.iterator();
946 while (hrnIter.hasNext()) {
947 HeapRegionNode hrn = hrnIter.next();
949 Iterator<ReferenceEdge> referencers = hrn
950 .iteratorToReferencers();
951 while (referencers.hasNext()) {
952 ReferenceEdge referenceEdge = (ReferenceEdge) referencers
954 if (field.getSymbol().equals(
955 referenceEdge.getField())) {
956 currentSESE.readEffects(affectedTD, field
957 .getSymbol(), src.getType(),
958 referenceEdge.getDst().getID());
966 // handle tainted case
968 Iterator<ReferenceEdge> edgeIter = srcLN
969 .iteratorToReferencees();
970 while (edgeIter.hasNext()) {
971 ReferenceEdge edge = edgeIter.next();
973 if(edge.getTaintIdentifier()>0){
974 HeapRegionNode accessHRN = edge.getDst();
975 affectedTDSet = getReferenceNodeSet(accessHRN);
976 affectedIter = affectedTDSet.iterator();
977 while (affectedIter.hasNext()) {
978 TempDescriptor affectedTD = affectedIter.next();
979 if (currentSESE.getInVarSet().contains(affectedTD)) {
981 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
983 Iterator<HeapRegionNode> hrnIter = hrnSet
985 while (hrnIter.hasNext()) {
986 HeapRegionNode hrn = hrnIter.next();
987 currentSESE.readEffects(affectedTD, field
988 .getSymbol(), src.getType(), hrn
1002 case FKind.FlatSetFieldNode: {
1004 FlatSetFieldNode fsen = (FlatSetFieldNode) fn;
1005 TempDescriptor dst = fsen.getDst();
1006 FieldDescriptor field = fsen.getField();
1008 LabelNode dstLN = og.td2ln.get(dst);
1009 if (dstLN != null) {
1010 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(dstLN);
1012 Iterator<TempDescriptor> affectedIter = affectedTDSet
1015 while (affectedIter.hasNext()) {
1016 TempDescriptor affectedTD = affectedIter.next();
1017 if (currentSESE.getInVarSet().contains(affectedTD)) {
1019 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1021 Iterator<HeapRegionNode> hrnIter = hrnSet.iterator();
1022 while (hrnIter.hasNext()) {
1023 HeapRegionNode hrn = hrnIter.next();
1025 if (field.getType().isImmutable()) {
1026 currentSESE.writeEffects(affectedTD, field
1027 .getSymbol(), dst.getType(), hrn
1031 Iterator<ReferenceEdge> referencers = hrn
1032 .iteratorToReferencers();
1033 while (referencers.hasNext()) {
1034 ReferenceEdge referenceEdge = (ReferenceEdge) referencers
1036 if (field.getSymbol().equals(
1037 referenceEdge.getField())) {
1038 currentSESE.writeEffects(affectedTD,
1039 field.getSymbol(), dst
1041 referenceEdge.getDst().getID());
1050 // handle tainted case
1051 Iterator<ReferenceEdge> edgeIter = dstLN
1052 .iteratorToReferencees();
1053 while (edgeIter.hasNext()) {
1054 ReferenceEdge edge = edgeIter.next();
1055 if (edge.getTaintIdentifier() > 0) {
1056 HeapRegionNode accessHRN = edge.getDst();
1057 affectedTDSet = getReferenceNodeSet(accessHRN);
1058 affectedIter = affectedTDSet.iterator();
1059 while (affectedIter.hasNext()) {
1060 TempDescriptor affectedTD = affectedIter.next();
1061 if (currentSESE.getInVarSet().contains(affectedTD)) {
1063 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1065 Iterator<HeapRegionNode> hrnIter = hrnSet
1067 while (hrnIter.hasNext()) {
1068 HeapRegionNode hrn = hrnIter.next();
1069 currentSESE.writeEffects(affectedTD, field
1070 .getSymbol(), dst.getType(), hrn
1086 case FKind.FlatCall: {
1087 FlatCall fc = (FlatCall) fn;
1089 MethodContext calleeMC = ownAnalysis.getCalleeMethodContext(mc, fc);
1091 MethodEffects me = ownAnalysis.getMethodEffectsAnalysis()
1092 .getMethodEffectsByMethodContext(calleeMC);
1094 OwnershipGraph calleeOG = ownAnalysis
1095 .getOwnvershipGraphByMethodContext(calleeMC);
1097 FlatMethod fm = state.getMethodFlat(fc.getMethod());
1098 ParameterDecomposition decomp = new ParameterDecomposition(
1099 ownAnalysis, fc, fm, calleeMC, calleeOG, og);
1102 if (((MethodDescriptor) calleeMC.getDescriptor()).isStatic()) {
1108 for (int i = 0; i < fc.numArgs(); i++) {
1110 TempDescriptor arg = fc.getArg(i);
1111 Set<EffectsKey> readSet = me.getEffects().getReadingSet(
1113 Set<EffectsKey> writeSet = me.getEffects().getWritingSet(
1116 LabelNode argLN = og.td2ln.get(arg);
1117 if (argLN != null) {
1118 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(argLN);
1119 Iterator<TempDescriptor> affectedIter = affectedTDSet
1122 while (affectedIter.hasNext()) {
1124 TempDescriptor affectedTD = affectedIter.next();
1125 if (currentSESE.getInVarSet().contains(affectedTD)) {
1127 if (readSet != null) {
1128 Iterator<EffectsKey> readIter = readSet
1130 while (readIter.hasNext()) {
1131 EffectsKey key = readIter.next();
1132 Set<Integer> hrnSet = getCallerHRNId(
1133 new Integer(i + base), calleeOG,
1134 key.getHRNId(), decomp);
1135 Iterator<Integer> hrnIter = hrnSet
1137 while (hrnIter.hasNext()) {
1138 Integer hrnID = (Integer) hrnIter
1140 currentSESE.readEffects(affectedTD, key
1141 .getFieldDescriptor(), key
1142 .getTypeDescriptor(), hrnID);
1147 if (writeSet != null) {
1148 Iterator<EffectsKey> writeIter = writeSet
1150 while (writeIter.hasNext()) {
1151 EffectsKey key = writeIter.next();
1153 Set<Integer> hrnSet = getCallerHRNId(
1154 new Integer(i + base), calleeOG,
1155 key.getHRNId(), decomp);
1156 Iterator<Integer> hrnIter = hrnSet
1158 while (hrnIter.hasNext()) {
1159 Integer hrnID = (Integer) hrnIter
1161 currentSESE.writeEffects(affectedTD,
1162 key.getFieldDescriptor(), key
1163 .getTypeDescriptor(),
1184 private Set<Integer> getCallerHRNId(Integer paramIdx,
1185 OwnershipGraph calleeOG, Integer calleeHRNId,
1186 ParameterDecomposition paramDecom) {
1188 Integer hrnPrimaryID = calleeOG.paramIndex2idPrimary.get(paramIdx);
1189 Integer hrnSecondaryID = calleeOG.paramIndex2idSecondary.get(paramIdx);
1191 if (calleeHRNId.equals(hrnPrimaryID)) {
1192 // it references to primary param heap region
1193 return paramDecom.getParamObject_hrnIDs(paramIdx);
1194 } else if (calleeHRNId.equals(hrnSecondaryID)) {
1195 // it references to secondary param heap region
1196 return paramDecom.getParamReachable_hrnIDs(paramIdx);
1199 return new HashSet<Integer>();
1202 private void taintLabelNode(LabelNode ln, int identifier) {
1204 Iterator<ReferenceEdge> edgeIter = ln.iteratorToReferencees();
1205 while (edgeIter.hasNext()) {
1206 ReferenceEdge edge = edgeIter.next();
1207 HeapRegionNode hrn = edge.getDst();
1209 Iterator<ReferenceEdge> edgeReferencerIter = hrn
1210 .iteratorToReferencers();
1211 while (edgeReferencerIter.hasNext()) {
1212 ReferenceEdge referencerEdge = edgeReferencerIter.next();
1213 OwnershipNode node = referencerEdge.getSrc();
1214 if (node instanceof LabelNode) {
1215 referencerEdge.unionSESETaintIdentifier(identifier);
1223 private HashSet<TempDescriptor> getReferenceNodeSet(HeapRegionNode hrn){
1225 HashSet<TempDescriptor> returnSet=new HashSet<TempDescriptor>();
1227 Iterator<ReferenceEdge> edgeIter=hrn.iteratorToReferencers();
1228 while(edgeIter.hasNext()){
1229 ReferenceEdge edge=edgeIter.next();
1230 if(edge.getSrc() instanceof LabelNode){
1231 LabelNode ln=(LabelNode)edge.getSrc();
1232 returnSet.add(ln.getTempDescriptor());
1241 private HashSet<HeapRegionNode> getReferenceHeapIDSet(OwnershipGraph og, TempDescriptor td){
1243 HashSet<HeapRegionNode> returnSet=new HashSet<HeapRegionNode>();
1245 LabelNode ln=og.td2ln.get(td);
1246 Iterator<ReferenceEdge> edgeIter=ln.iteratorToReferencees();
1247 while(edgeIter.hasNext()){
1248 ReferenceEdge edge=edgeIter.next();
1249 HeapRegionNode hrn=edge.getDst();
1256 private HashSet<TempDescriptor> getAccessedTaintNodeSet(LabelNode ln) {
1258 HashSet<TempDescriptor> returnSet = new HashSet<TempDescriptor>();
1260 Iterator<ReferenceEdge> edgeIter = ln.iteratorToReferencees();
1261 while (edgeIter.hasNext()) {
1262 ReferenceEdge edge = edgeIter.next();
1263 HeapRegionNode hrn = edge.getDst();
1265 Iterator<ReferenceEdge> edgeReferencerIter = hrn
1266 .iteratorToReferencers();
1267 while (edgeReferencerIter.hasNext()) {
1268 ReferenceEdge referencerEdge = edgeReferencerIter.next();
1270 if (referencerEdge.getSrc() instanceof LabelNode) {
1271 if (!((LabelNode) referencerEdge.getSrc()).equals(ln)) {
1273 if (referencerEdge.getSESETaintIdentifier() > 0) {
1274 TempDescriptor td = ((LabelNode) referencerEdge
1275 .getSrc()).getTempDescriptor();
1289 private void codePlansForward( FlatMethod fm ) {
1291 // start from flat method top, visit every node in
1292 // method exactly once
1293 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
1294 flatNodesToVisit.add( fm );
1296 Set<FlatNode> visited = new HashSet<FlatNode>();
1298 while( !flatNodesToVisit.isEmpty() ) {
1299 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
1300 FlatNode fn = fnItr.next();
1302 flatNodesToVisit.remove( fn );
1305 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
1306 assert seseStack != null;
1308 // use incoming results as "dot statement" or just
1309 // before the current statement
1310 VarSrcTokTable dotSTtable = new VarSrcTokTable();
1311 for( int i = 0; i < fn.numPrev(); i++ ) {
1312 FlatNode nn = fn.getPrev( i );
1313 dotSTtable.merge( variableResults.get( nn ) );
1316 // find dt-st notAvailableSet also
1317 Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
1318 for( int i = 0; i < fn.numPrev(); i++ ) {
1319 FlatNode nn = fn.getPrev( i );
1320 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
1321 if( notAvailIn != null ) {
1322 dotSTnotAvailSet.addAll( notAvailIn );
1326 Set<TempDescriptor> dotSTlive = livenessRootView.get( fn );
1328 if( !seseStack.empty() ) {
1329 codePlans_nodeActions( fn,
1337 for( int i = 0; i < fn.numNext(); i++ ) {
1338 FlatNode nn = fn.getNext( i );
1340 if( !visited.contains( nn ) ) {
1341 flatNodesToVisit.add( nn );
1347 private void codePlans_nodeActions( FlatNode fn,
1348 Set<TempDescriptor> liveSetIn,
1349 VarSrcTokTable vstTableIn,
1350 Set<TempDescriptor> notAvailSetIn,
1351 FlatSESEEnterNode currentSESE ) {
1353 CodePlan plan = new CodePlan( currentSESE);
1355 switch( fn.kind() ) {
1357 case FKind.FlatSESEEnterNode: {
1358 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
1360 // track the source types of the in-var set so generated
1361 // code at this SESE issue can compute the number of
1362 // dependencies properly
1363 Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
1364 while( inVarItr.hasNext() ) {
1365 TempDescriptor inVar = inVarItr.next();
1367 vstTableIn.getRefVarSrcType( inVar,
1371 // the current SESE needs a local space to track the dynamic
1372 // variable and the child needs space in its SESE record
1373 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1374 fsen.addDynamicInVar( inVar );
1375 fsen.getParent().addDynamicVar( inVar );
1377 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
1378 fsen.addStaticInVar( inVar );
1379 VariableSourceToken vst = vstTableIn.get( inVar ).iterator().next();
1380 fsen.putStaticInVar2src( inVar, vst );
1381 fsen.addStaticInVarSrc( new SESEandAgePair( vst.getSESE(),
1387 assert srcType.equals( VarSrcTokTable.SrcType_READY );
1388 fsen.addReadyInVar( inVar );
1394 case FKind.FlatSESEExitNode: {
1395 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
1398 case FKind.FlatOpNode: {
1399 FlatOpNode fon = (FlatOpNode) fn;
1401 if( fon.getOp().getOp() == Operation.ASSIGN ) {
1402 TempDescriptor lhs = fon.getDest();
1403 TempDescriptor rhs = fon.getLeft();
1405 // if this is an op node, don't stall, copy
1406 // source and delay until we need to use value
1408 // ask whether lhs and rhs sources are dynamic, static, etc.
1410 = vstTableIn.getRefVarSrcType( lhs,
1412 currentSESE.getParent() );
1415 = vstTableIn.getRefVarSrcType( rhs,
1417 currentSESE.getParent() );
1419 if( rhsSrcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1420 // if rhs is dynamic going in, lhs will definitely be dynamic
1421 // going out of this node, so track that here
1422 plan.addDynAssign( lhs, rhs );
1423 currentSESE.addDynamicVar( lhs );
1424 currentSESE.addDynamicVar( rhs );
1426 } else if( lhsSrcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1427 // otherwise, if the lhs is dynamic, but the rhs is not, we
1428 // need to update the variable's dynamic source as "current SESE"
1429 plan.addDynAssign( lhs );
1432 // only break if this is an ASSIGN op node,
1433 // otherwise fall through to default case
1438 // note that FlatOpNode's that aren't ASSIGN
1439 // fall through to this default case
1442 // a node with no live set has nothing to stall for
1443 if( liveSetIn == null ) {
1447 TempDescriptor[] readarray = fn.readsTemps();
1448 for( int i = 0; i < readarray.length; i++ ) {
1449 TempDescriptor readtmp = readarray[i];
1451 // ignore temps that are definitely available
1452 // when considering to stall on it
1453 if( !notAvailSetIn.contains( readtmp ) ) {
1457 // check the source type of this variable
1459 = vstTableIn.getRefVarSrcType( readtmp,
1461 currentSESE.getParent() );
1463 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1464 // 1) It is not clear statically where this variable will
1465 // come from statically, so dynamically we must keep track
1466 // along various control paths, and therefore when we stall,
1467 // just stall for the exact thing we need and move on
1468 plan.addDynamicStall( readtmp );
1469 currentSESE.addDynamicVar( readtmp );
1471 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
1472 // 2) Single token/age pair: Stall for token/age pair, and copy
1473 // all live variables with same token/age pair at the same
1474 // time. This is the same stuff that the notavaialable analysis
1475 // marks as now available.
1477 VariableSourceToken vst = vstTableIn.get( readtmp ).iterator().next();
1479 Iterator<VariableSourceToken> availItr =
1480 vstTableIn.get( vst.getSESE(), vst.getAge() ).iterator();
1482 while( availItr.hasNext() ) {
1483 VariableSourceToken vstAlsoAvail = availItr.next();
1485 // only grab additional stuff that is live
1486 Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
1488 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
1489 while( refVarItr.hasNext() ) {
1490 TempDescriptor refVar = refVarItr.next();
1491 if( liveSetIn.contains( refVar ) ) {
1492 copySet.add( refVar );
1496 if( !copySet.isEmpty() ) {
1497 plan.addStall2CopySet( vstAlsoAvail, copySet );
1502 // the other case for srcs is READY, so do nothing
1505 // assert that everything being stalled for is in the
1506 // "not available" set coming into this flat node and
1507 // that every VST identified is in the possible "stall set"
1508 // that represents VST's from children SESE's
1516 // identify sese-age pairs that are statically useful
1517 // and should have an associated SESE variable in code
1518 // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
1519 // AND ALWAYS GIVE NAMES TO PARENTS
1520 Set<VariableSourceToken> staticSet = vstTableIn.get();
1521 Iterator<VariableSourceToken> vstItr = staticSet.iterator();
1522 while( vstItr.hasNext() ) {
1523 VariableSourceToken vst = vstItr.next();
1525 // placeholder source tokens are useful results, but
1526 // the placeholder static name is never needed
1527 if( vst.getSESE().getIsCallerSESEplaceholder() ) {
1531 FlatSESEEnterNode sese = currentSESE;
1532 while( sese != null ) {
1533 sese.addNeededStaticName(
1534 new SESEandAgePair( vst.getSESE(), vst.getAge() )
1536 sese.mustTrackAtLeastAge( vst.getAge() );
1538 sese = sese.getParent();
1543 codePlans.put( fn, plan );
1546 // if any variables at this-node-*dot* have a static source (exactly one vst)
1547 // but go to a dynamic source at next-node-*dot*, create a new IR graph
1548 // node on that edge to track the sources dynamically
1549 VarSrcTokTable thisVstTable = variableResults.get( fn );
1550 for( int i = 0; i < fn.numNext(); i++ ) {
1551 FlatNode nn = fn.getNext( i );
1552 VarSrcTokTable nextVstTable = variableResults.get( nn );
1553 Set<TempDescriptor> nextLiveIn = livenessRootView.get( nn );
1555 // the table can be null if it is one of the few IR nodes
1556 // completely outside of the root SESE scope
1557 if( nextVstTable != null && nextLiveIn != null ) {
1559 Hashtable<TempDescriptor, VariableSourceToken> static2dynamicSet =
1560 thisVstTable.getStatic2DynamicSet( nextVstTable,
1563 currentSESE.getParent()
1566 if( !static2dynamicSet.isEmpty() ) {
1568 // either add these results to partial fixed-point result
1569 // or make a new one if we haven't made any here yet
1570 FlatEdge fe = new FlatEdge( fn, nn );
1571 FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get( fe );
1573 if( fwdvn == null ) {
1574 fwdvn = new FlatWriteDynamicVarNode( fn,
1579 wdvNodesToSpliceIn.put( fe, fwdvn );
1581 fwdvn.addMoreVar2Src( static2dynamicSet );
1589 public void writeReports( String timeReport ) throws java.io.IOException {
1591 BufferedWriter bw = new BufferedWriter( new FileWriter( "mlpReport_summary.txt" ) );
1592 bw.write( "MLP Analysis Results\n\n" );
1593 bw.write( timeReport+"\n\n" );
1594 printSESEHierarchy( bw );
1596 printSESEInfo( bw );
1599 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
1600 while( methItr.hasNext() ) {
1601 MethodDescriptor md = (MethodDescriptor) methItr.next();
1602 FlatMethod fm = state.getMethodFlat( md );
1603 bw = new BufferedWriter( new FileWriter( "mlpReport_"+
1604 md.getClassMethodName()+
1605 md.getSafeMethodDescriptor()+
1607 bw.write( "MLP Results for "+md+"\n-------------------\n");
1608 bw.write( "\n\nLive-In, Root View\n------------------\n" +fm.printMethod( livenessRootView ) );
1609 bw.write( "\n\nVariable Results-Out\n----------------\n" +fm.printMethod( variableResults ) );
1610 bw.write( "\n\nNot Available Results-Out\n---------------------\n"+fm.printMethod( notAvailableResults ) );
1611 bw.write( "\n\nCode Plans\n----------\n" +fm.printMethod( codePlans ) );
1612 bw.write("\n\nSESE Effects\n----------------------\n"+printSESEEffects());
1617 private String printSESEEffects() {
1619 StringWriter writer = new StringWriter();
1621 Iterator<FlatSESEEnterNode> keyIter = allSESEs.iterator();
1623 while (keyIter.hasNext()) {
1624 FlatSESEEnterNode seseEnter = keyIter.next();
1625 String result = seseEnter.getSeseEffectsSet().printSet();
1626 if (result.length() > 0) {
1627 writer.write("\nSESE " + seseEnter + "\n");
1628 writer.write(result);
1631 keyIter = rootSESEs.iterator();
1632 while (keyIter.hasNext()) {
1633 FlatSESEEnterNode seseEnter = keyIter.next();
1634 if (seseEnter.getIsCallerSESEplaceholder()) {
1635 if (!seseEnter.getChildren().isEmpty()) {
1636 String result = seseEnter.getSeseEffectsSet().printSet();
1637 if (result.length() > 0) {
1638 writer.write("\nSESE " + seseEnter + "\n");
1639 writer.write(result);
1645 return writer.toString();
1649 private void printSESEHierarchy( BufferedWriter bw ) throws java.io.IOException {
1650 bw.write( "SESE Hierarchy\n--------------\n" );
1651 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
1652 while( rootItr.hasNext() ) {
1653 FlatSESEEnterNode root = rootItr.next();
1654 if( root.getIsCallerSESEplaceholder() ) {
1655 if( !root.getChildren().isEmpty() ) {
1656 printSESEHierarchyTree( bw, root, 0 );
1659 printSESEHierarchyTree( bw, root, 0 );
1664 private void printSESEHierarchyTree( BufferedWriter bw,
1665 FlatSESEEnterNode fsen,
1667 ) throws java.io.IOException {
1668 for( int i = 0; i < depth; ++i ) {
1671 bw.write( "- "+fsen.getPrettyIdentifier()+"\n" );
1673 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1674 while( childItr.hasNext() ) {
1675 FlatSESEEnterNode fsenChild = childItr.next();
1676 printSESEHierarchyTree( bw, fsenChild, depth + 1 );
1681 private void printSESEInfo( BufferedWriter bw ) throws java.io.IOException {
1682 bw.write("\nSESE info\n-------------\n" );
1683 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
1684 while( rootItr.hasNext() ) {
1685 FlatSESEEnterNode root = rootItr.next();
1686 if( root.getIsCallerSESEplaceholder() ) {
1687 if( !root.getChildren().isEmpty() ) {
1688 printSESEInfoTree( bw, root );
1691 printSESEInfoTree( bw, root );
1696 private void printSESEInfoTree( BufferedWriter bw,
1697 FlatSESEEnterNode fsen
1698 ) throws java.io.IOException {
1700 if( !fsen.getIsCallerSESEplaceholder() ) {
1701 bw.write( "SESE "+fsen.getPrettyIdentifier()+" {\n" );
1703 bw.write( " in-set: "+fsen.getInVarSet()+"\n" );
1704 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
1705 while( tItr.hasNext() ) {
1706 TempDescriptor inVar = tItr.next();
1707 if( fsen.getReadyInVarSet().contains( inVar ) ) {
1708 bw.write( " (ready) "+inVar+"\n" );
1710 if( fsen.getStaticInVarSet().contains( inVar ) ) {
1711 bw.write( " (static) "+inVar+"\n" );
1713 if( fsen.getDynamicInVarSet().contains( inVar ) ) {
1714 bw.write( " (dynamic)"+inVar+"\n" );
1718 bw.write( " out-set: "+fsen.getOutVarSet()+"\n" );
1722 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1723 while( childItr.hasNext() ) {
1724 FlatSESEEnterNode fsenChild = childItr.next();
1725 printSESEInfoTree( bw, fsenChild );