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<FlatNode, AccSet> effectsResults;
52 private Hashtable< FlatEdge, FlatWriteDynamicVarNode > wdvNodesToSpliceIn;
54 public static int maxSESEage = -1;
57 // use these methods in BuildCode to have access to analysis results
58 public FlatSESEEnterNode getMainSESE() {
62 public Set<FlatSESEEnterNode> getRootSESEs() {
66 public Set<FlatSESEEnterNode> getAllSESEs() {
70 public int getMaxSESEage() {
75 public CodePlan getCodePlan( FlatNode fn ) {
76 CodePlan cp = codePlans.get( fn );
81 public MLPAnalysis( State state,
84 OwnershipAnalysis ownAnalysis
87 double timeStartAnalysis = (double) System.nanoTime();
91 this.callGraph = callGraph;
92 this.ownAnalysis = ownAnalysis;
93 this.maxSESEage = state.MLP_MAXSESEAGE;
95 rootSESEs = new HashSet<FlatSESEEnterNode>();
96 allSESEs = new HashSet<FlatSESEEnterNode>();
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 >();
106 effectsResults = new Hashtable<FlatNode, AccSet>();
109 FlatMethod fmMain = state.getMethodFlat( typeUtil.getMain() );
111 mainSESE = (FlatSESEEnterNode) fmMain.getNext(0);
112 mainSESE.setfmEnclosing( fmMain );
113 mainSESE.setmdEnclosing( fmMain.getMethod() );
114 mainSESE.setcdEnclosing( fmMain.getMethod().getClassDesc() );
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 );
125 // find every SESE from methods that may be called
126 // and organize them into roots and children
127 buildForestForward( fm );
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,
143 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
144 while( methItr.hasNext() ) {
145 Descriptor d = methItr.next();
146 FlatMethod fm = state.getMethodFlat( d );
148 // starting from roots do a forward, fixed-point
149 // variable analysis for refinement and stalls
150 variableAnalysisForward( fm );
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,
165 SOMETHING IS WRONG WITH THIS, DON'T USE IT UNTIL IT CAN BE FIXED
168 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
169 while( methItr.hasNext() ) {
170 Descriptor d = methItr.next();
171 FlatMethod fm = state.getMethodFlat( d );
173 // prune variable results in one traversal
174 // by removing reference variables that are not live
175 pruneVariableResultsWithLiveness( fm );
181 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
182 while( methItr.hasNext() ) {
183 Descriptor d = methItr.next();
184 FlatMethod fm = state.getMethodFlat( d );
186 // compute what is not available at every program
187 // point, in a forward fixed-point pass
188 notAvailableForward( fm );
191 // new pass for method effects analysis
192 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
193 while (methItr.hasNext()) {
194 Descriptor d = methItr.next();
195 FlatMethod fm = state.getMethodFlat(d);
200 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
201 while( methItr.hasNext() ) {
202 Descriptor d = methItr.next();
203 FlatMethod fm = state.getMethodFlat( d );
205 // compute a plan for code injections
206 codePlansForward( fm );
210 // splice new IR nodes into graph after all
211 // analysis passes are complete
212 Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
213 while( spliceItr.hasNext() ) {
214 Map.Entry me = (Map.Entry) spliceItr.next();
215 FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
216 fwdvn.spliceIntoIR();
220 double timeEndAnalysis = (double) System.nanoTime();
221 double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
222 String treport = String.format( "The mlp analysis took %.3f sec.", dt );
223 System.out.println( treport );
225 if( state.MLPDEBUG ) {
227 writeReports( treport );
228 } catch( IOException e ) {}
233 private void buildForestForward( FlatMethod fm ) {
235 // start from flat method top, visit every node in
236 // method exactly once, find SESEs and remember
237 // roots and child relationships
238 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
239 flatNodesToVisit.add( fm );
241 Set<FlatNode> visited = new HashSet<FlatNode>();
243 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
244 seseStacks.put( fm, seseStackFirst );
246 while( !flatNodesToVisit.isEmpty() ) {
247 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
248 FlatNode fn = fnItr.next();
250 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
251 assert seseStack != null;
253 flatNodesToVisit.remove( fn );
256 buildForest_nodeActions( fn, seseStack, fm );
258 for( int i = 0; i < fn.numNext(); i++ ) {
259 FlatNode nn = fn.getNext( i );
261 if( !visited.contains( nn ) ) {
262 flatNodesToVisit.add( nn );
264 // clone stack and send along each analysis path
265 seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
271 private void buildForest_nodeActions( FlatNode fn,
272 Stack<FlatSESEEnterNode> seseStack,
274 switch( fn.kind() ) {
276 case FKind.FlatSESEEnterNode: {
277 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
279 if( !fsen.getIsCallerSESEplaceholder() ) {
280 allSESEs.add( fsen );
283 fsen.setfmEnclosing( fm );
284 fsen.setmdEnclosing( fm.getMethod() );
285 fsen.setcdEnclosing( fm.getMethod().getClassDesc() );
287 if( seseStack.empty() ) {
288 rootSESEs.add( fsen );
289 fsen.setParent( null );
291 seseStack.peek().addChild( fsen );
292 fsen.setParent( seseStack.peek() );
295 seseStack.push( fsen );
298 case FKind.FlatSESEExitNode: {
299 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
300 assert !seseStack.empty();
301 FlatSESEEnterNode fsen = seseStack.pop();
304 case FKind.FlatReturnNode: {
305 FlatReturnNode frn = (FlatReturnNode) fn;
306 if( !seseStack.empty() &&
307 !seseStack.peek().getIsCallerSESEplaceholder()
309 throw new Error( "Error: return statement enclosed within SESE "+
310 seseStack.peek().getPrettyIdentifier() );
318 private void livenessAnalysisBackward( FlatSESEEnterNode fsen,
320 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout ) {
322 // start from an SESE exit, visit nodes in reverse up to
323 // SESE enter in a fixed-point scheme, where children SESEs
324 // should already be analyzed and therefore can be skipped
325 // because child SESE enter node has all necessary info
326 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
329 flatNodesToVisit.add( fsen.getfmEnclosing().getFlatExit() );
331 flatNodesToVisit.add( fsen.getFlatExit() );
334 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults =
335 new Hashtable< FlatNode, Set<TempDescriptor> >();
338 liveout = new Hashtable< FlatSESEExitNode, Set<TempDescriptor> >();
341 while( !flatNodesToVisit.isEmpty() ) {
342 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
343 flatNodesToVisit.remove( fn );
345 Set<TempDescriptor> prev = livenessResults.get( fn );
347 // merge sets from control flow joins
348 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
349 for( int i = 0; i < fn.numNext(); i++ ) {
350 FlatNode nn = fn.getNext( i );
351 Set<TempDescriptor> s = livenessResults.get( nn );
357 Set<TempDescriptor> curr = liveness_nodeActions( fn, u, fsen, toplevel, liveout);
359 // if a new result, schedule backward nodes for analysis
360 if( !curr.equals( prev ) ) {
361 livenessResults.put( fn, curr );
363 // don't flow backwards past current SESE enter
364 if( !fn.equals( fsen ) ) {
365 for( int i = 0; i < fn.numPrev(); i++ ) {
366 FlatNode nn = fn.getPrev( i );
367 flatNodesToVisit.add( nn );
373 Set<TempDescriptor> s = livenessResults.get( fsen );
375 fsen.addInVarSet( s );
378 // remember liveness per node from the root view as the
379 // global liveness of variables for later passes to use
381 livenessRootView.putAll( livenessResults );
384 // post-order traversal, so do children first
385 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
386 while( childItr.hasNext() ) {
387 FlatSESEEnterNode fsenChild = childItr.next();
388 livenessAnalysisBackward( fsenChild, false, liveout );
392 private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
393 Set<TempDescriptor> liveIn,
394 FlatSESEEnterNode currentSESE,
396 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout
398 switch( fn.kind() ) {
400 case FKind.FlatSESEExitNode:
402 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
403 if( !liveout.containsKey( fsexn ) ) {
404 liveout.put( fsexn, new HashSet<TempDescriptor>() );
406 liveout.get( fsexn ).addAll( liveIn );
408 // no break, sese exits should also execute default actions
411 // handle effects of statement in reverse, writes then reads
412 TempDescriptor [] writeTemps = fn.writesTemps();
413 for( int i = 0; i < writeTemps.length; ++i ) {
414 liveIn.remove( writeTemps[i] );
417 FlatSESEExitNode fsexn = currentSESE.getFlatExit();
418 Set<TempDescriptor> livetemps = liveout.get( fsexn );
419 if( livetemps != null &&
420 livetemps.contains( writeTemps[i] ) ) {
421 // write to a live out temp...
422 // need to put in SESE liveout set
423 currentSESE.addOutVar( writeTemps[i] );
428 TempDescriptor [] readTemps = fn.readsTemps();
429 for( int i = 0; i < readTemps.length; ++i ) {
430 liveIn.add( readTemps[i] );
433 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get( fn );
434 if( virtualReadTemps != null ) {
435 liveIn.addAll( virtualReadTemps );
446 private void variableAnalysisForward( FlatMethod fm ) {
448 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
449 flatNodesToVisit.add( fm );
451 while( !flatNodesToVisit.isEmpty() ) {
452 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
453 flatNodesToVisit.remove( fn );
455 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
456 assert seseStack != null;
458 VarSrcTokTable prev = variableResults.get( fn );
460 // merge sets from control flow joins
461 VarSrcTokTable curr = new VarSrcTokTable();
462 for( int i = 0; i < fn.numPrev(); i++ ) {
463 FlatNode nn = fn.getPrev( i );
464 VarSrcTokTable incoming = variableResults.get( nn );
465 curr.merge( incoming );
468 if( !seseStack.empty() ) {
469 variable_nodeActions( fn, curr, seseStack.peek() );
472 // if a new result, schedule forward nodes for analysis
473 if( !curr.equals( prev ) ) {
474 variableResults.put( fn, curr );
476 for( int i = 0; i < fn.numNext(); i++ ) {
477 FlatNode nn = fn.getNext( i );
478 flatNodesToVisit.add( nn );
484 private void variable_nodeActions( FlatNode fn,
485 VarSrcTokTable vstTable,
486 FlatSESEEnterNode currentSESE ) {
487 switch( fn.kind() ) {
489 case FKind.FlatSESEEnterNode: {
490 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
491 assert fsen.equals( currentSESE );
493 vstTable.age( currentSESE );
494 vstTable.assertConsistency();
497 case FKind.FlatSESEExitNode: {
498 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
499 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
500 assert currentSESE.getChildren().contains( fsen );
502 vstTable.remapChildTokens( fsen );
504 // liveness virtual reads are things that might be
505 // written by an SESE and should be added to the in-set
506 // anything virtually read by this SESE should be pruned
507 // of parent or sibling sources
508 Set<TempDescriptor> liveVars = livenessRootView.get( fn );
509 Set<TempDescriptor> fsenVirtReads = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens( fsen, liveVars );
510 Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get( fn );
511 if( fsenVirtReadsOld != null ) {
512 fsenVirtReads.addAll( fsenVirtReadsOld );
514 livenessVirtualReads.put( fn, fsenVirtReads );
517 // then all child out-set tokens are guaranteed
518 // to be filled in, so clobber those entries with
519 // the latest, clean sources
520 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
521 while( outVarItr.hasNext() ) {
522 TempDescriptor outVar = outVarItr.next();
523 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
525 VariableSourceToken vst =
526 new VariableSourceToken( ts,
531 vstTable.remove( outVar );
534 vstTable.assertConsistency();
538 case FKind.FlatOpNode: {
539 FlatOpNode fon = (FlatOpNode) fn;
541 if( fon.getOp().getOp() == Operation.ASSIGN ) {
542 TempDescriptor lhs = fon.getDest();
543 TempDescriptor rhs = fon.getLeft();
545 vstTable.remove( lhs );
547 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
549 Iterator<VariableSourceToken> itr = vstTable.get( rhs ).iterator();
550 while( itr.hasNext() ) {
551 VariableSourceToken vst = itr.next();
553 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
556 if( currentSESE.getChildren().contains( vst.getSESE() ) ) {
557 // if the source comes from a child, copy it over
558 forAddition.add( new VariableSourceToken( ts,
565 // otherwise, stamp it as us as the source
566 forAddition.add( new VariableSourceToken( ts,
575 vstTable.addAll( forAddition );
577 // only break if this is an ASSIGN op node,
578 // otherwise fall through to default case
579 vstTable.assertConsistency();
584 // note that FlatOpNode's that aren't ASSIGN
585 // fall through to this default case
587 TempDescriptor [] writeTemps = fn.writesTemps();
588 if( writeTemps.length > 0 ) {
591 // for now, when writeTemps > 1, make sure
592 // its a call node, programmer enforce only
593 // doing stuff like calling a print routine
594 //assert writeTemps.length == 1;
595 if( writeTemps.length > 1 ) {
596 assert fn.kind() == FKind.FlatCall ||
597 fn.kind() == FKind.FlatMethod;
601 vstTable.remove( writeTemps[0] );
603 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
604 ts.add( writeTemps[0] );
606 vstTable.add( new VariableSourceToken( ts,
614 vstTable.assertConsistency();
621 private void pruneVariableResultsWithLiveness( FlatMethod fm ) {
623 // start from flat method top, visit every node in
624 // method exactly once
625 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
626 flatNodesToVisit.add( fm );
628 Set<FlatNode> visited = new HashSet<FlatNode>();
630 while( !flatNodesToVisit.isEmpty() ) {
631 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
632 FlatNode fn = fnItr.next();
634 flatNodesToVisit.remove( fn );
637 Set<TempDescriptor> rootLiveSet = livenessRootView.get( fn );
638 VarSrcTokTable vstTable = variableResults.get( fn );
640 vstTable.pruneByLiveness( rootLiveSet );
642 for( int i = 0; i < fn.numNext(); i++ ) {
643 FlatNode nn = fn.getNext( i );
645 if( !visited.contains( nn ) ) {
646 flatNodesToVisit.add( nn );
652 private void effectsForward(FlatMethod fm) {
653 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
654 flatNodesToVisit.add(fm);
656 while (!flatNodesToVisit.isEmpty()) {
657 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
658 flatNodesToVisit.remove(fn);
660 AccSet prev = effectsResults.get(fn);
661 AccSet curr = new AccSet();
664 for (int i = 0; i < fn.numPrev(); i++) {
665 FlatNode nn = fn.getPrev(i);
666 AccSet accSet = effectsResults.get(nn);
667 if (accSet != null) {
672 effects_nodeActions(fn, curr);
674 // if a new result, schedule forward nodes for analysis
675 if (!curr.equals(prev)) {
676 effectsResults.put(fn, curr);
677 for (int i = 0; i < fn.numNext(); i++) {
678 FlatNode nn = fn.getNext(i);
679 flatNodesToVisit.add(nn);
689 private void effects_nodeActions(FlatNode fn, AccSet curr) {
691 OwnershipGraph fnOG = ownAnalysis
692 .getMappingFlatNodeToOwnershipGraph(fn);
696 case FKind.FlatMethod: {
698 FlatMethod fm = (FlatMethod) fn;
699 int numParam = fm.numParameters();
701 for (int i = 0; i < numParam; i++) {
702 TempDescriptor paramTD = fm.getParameter(i);
704 curr.addParam(paramTD);
708 // OwnershipGraph fnOG =
709 // ownAnalysis.getMappingFlatNodeToOwnershipGraph(fn);
711 // fnOG.writeGraph(fn + "FOOGRAPH", true, true, true, true, false);
712 // } catch (IOException e) {
713 // System.out.println("Error writing debug capture.");
720 case FKind.FlatSetFieldNode: {
722 FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
724 TempDescriptor dstDesc = fsfn.getDst();
725 FieldDescriptor fieldDesc = fsfn.getField();
726 TempDescriptor srcDesc = fsfn.getSrc();
728 LabelNode ln = fnOG.td2ln.get(dstDesc);
730 Iterator<ReferenceEdge> heapRegionsItr = ln
731 .iteratorToReferencees();
734 while (heapRegionsItr.hasNext()) {
735 HeapRegionNode hrn2 = heapRegionsItr.next().getDst();
737 Set<Integer> paramSet = fnOG.idSecondary2paramIndexSet
741 if (paramSet != null) {
742 Iterator<Integer> paramIter = paramSet.iterator();
744 while (paramIter.hasNext()) {
745 param += paramIter.next() + " ";
748 tempStr += " " + hrn2 + "(" + param + ")";
751 heapRegionsItr = ln.iteratorToReferencees();
752 while (heapRegionsItr.hasNext()) {
753 ReferenceEdge edge = heapRegionsItr.next();
754 HeapRegionNode hrn = edge.getDst();
756 if (hrn.isParameter()) {
757 // currently, handle this case. otherwise, ignore it.
758 Iterator<ReferenceEdge> iter = hrn
759 .iteratorToReferencers();
760 while (iter.hasNext()) {
761 ReferenceEdge re = iter.next();
762 if (re.getSrc() instanceof LabelNode) {
763 LabelNode labelNode = (LabelNode) re.getSrc();
765 if (curr.containsParam(labelNode
766 .getTempDescriptor())) {
768 curr.addWritingVar(labelNode
769 .getTempDescriptor(), new AccKey(
770 fieldDesc.getSymbol(), dstDesc
778 // check weather this heap region is parameter
781 Set<Integer> paramSet = fnOG.idSecondary2paramIndexSet
783 if (paramSet != null) {
784 Iterator<Integer> paramIter = paramSet.iterator();
786 while (paramIter.hasNext()) {
787 Integer paramID = paramIter.next();
789 Integer primaryID = fnOG.paramIndex2idPrimary
791 HeapRegionNode paramHRN = fnOG.id2hrn
794 HashSet<LabelNode> LNSet = getParameterLabelNodeSet(
795 fnOG, curr, paramHRN);
797 Iterator<LabelNode> LNSetIter = LNSet
799 while (LNSetIter.hasNext()) {
800 LabelNode labelNode = LNSetIter.next();
802 curr.addWritingVar(labelNode
803 .getTempDescriptor(), new AccKey(
804 fieldDesc.getSymbol(), dstDesc
819 case FKind.FlatFieldNode: {
821 FlatFieldNode ffn = (FlatFieldNode) fn;
823 TempDescriptor srcDesc = ffn.getSrc();
824 FieldDescriptor fieldDesc = ffn.getField();
826 LabelNode ln = fnOG.td2ln.get(srcDesc);
829 Iterator<ReferenceEdge> heapRegionsItr = ln
830 .iteratorToReferencees();
832 while (heapRegionsItr.hasNext()) {
834 HeapRegionNode hrn = heapRegionsItr.next().getDst();
836 Set<Integer> paramSet = fnOG.idSecondary2paramIndexSet
840 if (paramSet != null) {
841 Iterator<Integer> paramIter = paramSet.iterator();
843 while (paramIter.hasNext()) {
844 param += paramIter.next() + " ";
847 tempStr += " " + hrn + "(" + param + ")";
850 heapRegionsItr = ln.iteratorToReferencees();
851 while (heapRegionsItr.hasNext()) {
852 ReferenceEdge edge = heapRegionsItr.next();
853 HeapRegionNode hrn = edge.getDst();
855 if (hrn.isParameter()) {
856 Iterator<ReferenceEdge> iter = hrn
857 .iteratorToReferencers();
859 while (iter.hasNext()) {
860 ReferenceEdge re = iter.next();
861 if (re.getSrc() instanceof LabelNode) {
863 LabelNode labelNode = (LabelNode) re.getSrc();
865 if (curr.containsParam(labelNode
866 .getTempDescriptor())) {
867 curr.addReadingVar(labelNode
868 .getTempDescriptor(), new AccKey(
869 fieldDesc.getSymbol(), srcDesc
876 // check weather this heap region is parameter
880 Set<Integer> paramSet = fnOG.idSecondary2paramIndexSet
882 if (paramSet != null) {
883 Iterator<Integer> paramIter = paramSet.iterator();
885 while (paramIter.hasNext()) {
886 Integer paramID = paramIter.next();
888 Integer primaryID = fnOG.paramIndex2idPrimary
890 HeapRegionNode paramHRN = fnOG.id2hrn
893 HashSet<LabelNode> LNSet = getParameterLabelNodeSet(
894 fnOG, curr, paramHRN);
896 Iterator<LabelNode> LNSetIter = LNSet
898 while (LNSetIter.hasNext()) {
899 LabelNode labelNode = LNSetIter.next();
901 curr.addReadingVar(labelNode
902 .getTempDescriptor(), new AccKey(
903 fieldDesc.getSymbol(), srcDesc
920 // returns the set of parameter label node which are associated with the
921 // specific heap region node.
922 private HashSet<LabelNode> getParameterLabelNodeSet(OwnershipGraph og,
923 AccSet curr, HeapRegionNode hrn) {
925 HashSet<LabelNode> set = new HashSet<LabelNode>();
926 Iterator<ReferenceEdge> iter = hrn.iteratorToReferencers();
927 while (iter.hasNext()) {
928 ReferenceEdge re = iter.next();
929 if (re.getSrc() instanceof LabelNode) {
930 LabelNode labelNode = (LabelNode) re.getSrc();
931 if (curr.containsParam(labelNode.getTempDescriptor())) {
939 private void notAvailableForward( FlatMethod fm ) {
941 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
942 flatNodesToVisit.add( fm );
944 while( !flatNodesToVisit.isEmpty() ) {
945 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
946 flatNodesToVisit.remove( fn );
948 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
949 assert seseStack != null;
951 Set<TempDescriptor> prev = notAvailableResults.get( fn );
953 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
954 for( int i = 0; i < fn.numPrev(); i++ ) {
955 FlatNode nn = fn.getPrev( i );
956 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
957 if( notAvailIn != null ) {
958 curr.addAll( notAvailIn );
962 if( !seseStack.empty() ) {
963 notAvailable_nodeActions( fn, curr, seseStack.peek() );
966 // if a new result, schedule forward nodes for analysis
967 if( !curr.equals( prev ) ) {
968 notAvailableResults.put( fn, curr );
970 for( int i = 0; i < fn.numNext(); i++ ) {
971 FlatNode nn = fn.getNext( i );
972 flatNodesToVisit.add( nn );
978 private void notAvailable_nodeActions( FlatNode fn,
979 Set<TempDescriptor> notAvailSet,
980 FlatSESEEnterNode currentSESE ) {
982 // any temps that are removed from the not available set
983 // at this node should be marked in this node's code plan
984 // as temps to be grabbed at runtime!
986 switch( fn.kind() ) {
988 case FKind.FlatSESEEnterNode: {
989 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
990 assert fsen.equals( currentSESE );
994 case FKind.FlatSESEExitNode: {
995 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
996 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
997 assert currentSESE.getChildren().contains( fsen );
998 notAvailSet.addAll( fsen.getOutVarSet() );
1001 case FKind.FlatMethod: {
1002 notAvailSet.clear();
1005 case FKind.FlatOpNode: {
1006 FlatOpNode fon = (FlatOpNode) fn;
1008 if( fon.getOp().getOp() == Operation.ASSIGN ) {
1009 TempDescriptor lhs = fon.getDest();
1010 TempDescriptor rhs = fon.getLeft();
1012 // copy makes lhs same availability as rhs
1013 if( notAvailSet.contains( rhs ) ) {
1014 notAvailSet.add( lhs );
1016 notAvailSet.remove( lhs );
1019 // only break if this is an ASSIGN op node,
1020 // otherwise fall through to default case
1025 // note that FlatOpNode's that aren't ASSIGN
1026 // fall through to this default case
1028 TempDescriptor [] writeTemps = fn.writesTemps();
1029 for( int i = 0; i < writeTemps.length; i++ ) {
1030 TempDescriptor wTemp = writeTemps[i];
1031 notAvailSet.remove( wTemp );
1033 TempDescriptor [] readTemps = fn.readsTemps();
1034 for( int i = 0; i < readTemps.length; i++ ) {
1035 TempDescriptor rTemp = readTemps[i];
1036 notAvailSet.remove( rTemp );
1038 // if this variable has exactly one source, potentially
1039 // get other things from this source as well
1040 VarSrcTokTable vstTable = variableResults.get( fn );
1043 vstTable.getRefVarSrcType( rTemp,
1045 currentSESE.getParent() );
1047 if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
1049 VariableSourceToken vst = vstTable.get( rTemp ).iterator().next();
1051 Iterator<VariableSourceToken> availItr = vstTable.get( vst.getSESE(),
1055 // look through things that are also available from same source
1056 while( availItr.hasNext() ) {
1057 VariableSourceToken vstAlsoAvail = availItr.next();
1059 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
1060 while( refVarItr.hasNext() ) {
1061 TempDescriptor refVarAlso = refVarItr.next();
1063 // if a variable is available from the same source, AND it ALSO
1064 // only comes from one statically known source, mark it available
1065 Integer srcTypeAlso =
1066 vstTable.getRefVarSrcType( refVarAlso,
1068 currentSESE.getParent() );
1069 if( srcTypeAlso.equals( VarSrcTokTable.SrcType_STATIC ) ) {
1070 notAvailSet.remove( refVarAlso );
1082 private void codePlansForward( FlatMethod fm ) {
1084 // start from flat method top, visit every node in
1085 // method exactly once
1086 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
1087 flatNodesToVisit.add( fm );
1089 Set<FlatNode> visited = new HashSet<FlatNode>();
1091 while( !flatNodesToVisit.isEmpty() ) {
1092 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
1093 FlatNode fn = fnItr.next();
1095 flatNodesToVisit.remove( fn );
1098 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
1099 assert seseStack != null;
1101 // use incoming results as "dot statement" or just
1102 // before the current statement
1103 VarSrcTokTable dotSTtable = new VarSrcTokTable();
1104 for( int i = 0; i < fn.numPrev(); i++ ) {
1105 FlatNode nn = fn.getPrev( i );
1106 dotSTtable.merge( variableResults.get( nn ) );
1109 // find dt-st notAvailableSet also
1110 Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
1111 for( int i = 0; i < fn.numPrev(); i++ ) {
1112 FlatNode nn = fn.getPrev( i );
1113 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
1114 if( notAvailIn != null ) {
1115 dotSTnotAvailSet.addAll( notAvailIn );
1119 Set<TempDescriptor> dotSTlive = livenessRootView.get( fn );
1121 if( !seseStack.empty() ) {
1122 codePlans_nodeActions( fn,
1130 for( int i = 0; i < fn.numNext(); i++ ) {
1131 FlatNode nn = fn.getNext( i );
1133 if( !visited.contains( nn ) ) {
1134 flatNodesToVisit.add( nn );
1140 private void codePlans_nodeActions( FlatNode fn,
1141 Set<TempDescriptor> liveSetIn,
1142 VarSrcTokTable vstTableIn,
1143 Set<TempDescriptor> notAvailSetIn,
1144 FlatSESEEnterNode currentSESE ) {
1146 CodePlan plan = new CodePlan( currentSESE);
1148 switch( fn.kind() ) {
1150 case FKind.FlatSESEEnterNode: {
1151 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
1153 // track the source types of the in-var set so generated
1154 // code at this SESE issue can compute the number of
1155 // dependencies properly
1156 Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
1157 while( inVarItr.hasNext() ) {
1158 TempDescriptor inVar = inVarItr.next();
1160 vstTableIn.getRefVarSrcType( inVar,
1164 // the current SESE needs a local space to track the dynamic
1165 // variable and the child needs space in its SESE record
1166 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1167 fsen.addDynamicInVar( inVar );
1168 fsen.getParent().addDynamicVar( inVar );
1170 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
1171 fsen.addStaticInVar( inVar );
1172 VariableSourceToken vst = vstTableIn.get( inVar ).iterator().next();
1173 fsen.putStaticInVar2src( inVar, vst );
1174 fsen.addStaticInVarSrc( new SESEandAgePair( vst.getSESE(),
1180 assert srcType.equals( VarSrcTokTable.SrcType_READY );
1181 fsen.addReadyInVar( inVar );
1187 case FKind.FlatSESEExitNode: {
1188 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
1191 case FKind.FlatOpNode: {
1192 FlatOpNode fon = (FlatOpNode) fn;
1194 if( fon.getOp().getOp() == Operation.ASSIGN ) {
1195 TempDescriptor lhs = fon.getDest();
1196 TempDescriptor rhs = fon.getLeft();
1198 // if this is an op node, don't stall, copy
1199 // source and delay until we need to use value
1201 // ask whether lhs and rhs sources are dynamic, static, etc.
1203 = vstTableIn.getRefVarSrcType( lhs,
1205 currentSESE.getParent() );
1208 = vstTableIn.getRefVarSrcType( rhs,
1210 currentSESE.getParent() );
1212 if( rhsSrcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1213 // if rhs is dynamic going in, lhs will definitely be dynamic
1214 // going out of this node, so track that here
1215 plan.addDynAssign( lhs, rhs );
1216 currentSESE.addDynamicVar( lhs );
1217 currentSESE.addDynamicVar( rhs );
1219 } else if( lhsSrcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1220 // otherwise, if the lhs is dynamic, but the rhs is not, we
1221 // need to update the variable's dynamic source as "current SESE"
1222 plan.addDynAssign( lhs );
1225 // only break if this is an ASSIGN op node,
1226 // otherwise fall through to default case
1231 // note that FlatOpNode's that aren't ASSIGN
1232 // fall through to this default case
1235 // a node with no live set has nothing to stall for
1236 if( liveSetIn == null ) {
1240 TempDescriptor[] readarray = fn.readsTemps();
1241 for( int i = 0; i < readarray.length; i++ ) {
1242 TempDescriptor readtmp = readarray[i];
1244 // ignore temps that are definitely available
1245 // when considering to stall on it
1246 if( !notAvailSetIn.contains( readtmp ) ) {
1250 // check the source type of this variable
1252 = vstTableIn.getRefVarSrcType( readtmp,
1254 currentSESE.getParent() );
1256 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1257 // 1) It is not clear statically where this variable will
1258 // come from statically, so dynamically we must keep track
1259 // along various control paths, and therefore when we stall,
1260 // just stall for the exact thing we need and move on
1261 plan.addDynamicStall( readtmp );
1262 currentSESE.addDynamicVar( readtmp );
1264 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
1265 // 2) Single token/age pair: Stall for token/age pair, and copy
1266 // all live variables with same token/age pair at the same
1267 // time. This is the same stuff that the notavaialable analysis
1268 // marks as now available.
1270 VariableSourceToken vst = vstTableIn.get( readtmp ).iterator().next();
1272 Iterator<VariableSourceToken> availItr =
1273 vstTableIn.get( vst.getSESE(), vst.getAge() ).iterator();
1275 while( availItr.hasNext() ) {
1276 VariableSourceToken vstAlsoAvail = availItr.next();
1278 // only grab additional stuff that is live
1279 Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
1281 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
1282 while( refVarItr.hasNext() ) {
1283 TempDescriptor refVar = refVarItr.next();
1284 if( liveSetIn.contains( refVar ) ) {
1285 copySet.add( refVar );
1289 if( !copySet.isEmpty() ) {
1290 plan.addStall2CopySet( vstAlsoAvail, copySet );
1295 // the other case for srcs is READY, so do nothing
1298 // assert that everything being stalled for is in the
1299 // "not available" set coming into this flat node and
1300 // that every VST identified is in the possible "stall set"
1301 // that represents VST's from children SESE's
1309 // identify sese-age pairs that are statically useful
1310 // and should have an associated SESE variable in code
1311 // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
1312 // AND ALWAYS GIVE NAMES TO PARENTS
1313 Set<VariableSourceToken> staticSet = vstTableIn.get();
1314 Iterator<VariableSourceToken> vstItr = staticSet.iterator();
1315 while( vstItr.hasNext() ) {
1316 VariableSourceToken vst = vstItr.next();
1318 // placeholder source tokens are useful results, but
1319 // the placeholder static name is never needed
1320 if( vst.getSESE().getIsCallerSESEplaceholder() ) {
1324 FlatSESEEnterNode sese = currentSESE;
1325 while( sese != null ) {
1326 sese.addNeededStaticName(
1327 new SESEandAgePair( vst.getSESE(), vst.getAge() )
1329 sese.mustTrackAtLeastAge( vst.getAge() );
1331 sese = sese.getParent();
1336 codePlans.put( fn, plan );
1339 // if any variables at this-node-*dot* have a static source (exactly one vst)
1340 // but go to a dynamic source at next-node-*dot*, create a new IR graph
1341 // node on that edge to track the sources dynamically
1342 VarSrcTokTable thisVstTable = variableResults.get( fn );
1343 for( int i = 0; i < fn.numNext(); i++ ) {
1344 FlatNode nn = fn.getNext( i );
1345 VarSrcTokTable nextVstTable = variableResults.get( nn );
1346 Set<TempDescriptor> nextLiveIn = livenessRootView.get( nn );
1348 // the table can be null if it is one of the few IR nodes
1349 // completely outside of the root SESE scope
1350 if( nextVstTable != null && nextLiveIn != null ) {
1352 Hashtable<TempDescriptor, VariableSourceToken> static2dynamicSet =
1353 thisVstTable.getStatic2DynamicSet( nextVstTable,
1356 currentSESE.getParent()
1359 if( !static2dynamicSet.isEmpty() ) {
1361 // either add these results to partial fixed-point result
1362 // or make a new one if we haven't made any here yet
1363 FlatEdge fe = new FlatEdge( fn, nn );
1364 FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get( fe );
1366 if( fwdvn == null ) {
1367 fwdvn = new FlatWriteDynamicVarNode( fn,
1372 wdvNodesToSpliceIn.put( fe, fwdvn );
1374 fwdvn.addMoreVar2Src( static2dynamicSet );
1382 public void writeReports( String timeReport ) throws java.io.IOException {
1384 BufferedWriter bw = new BufferedWriter( new FileWriter( "mlpReport_summary.txt" ) );
1385 bw.write( "MLP Analysis Results\n\n" );
1386 bw.write( timeReport+"\n\n" );
1387 printSESEHierarchy( bw );
1389 printSESEInfo( bw );
1392 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
1393 while( methItr.hasNext() ) {
1394 MethodDescriptor md = (MethodDescriptor) methItr.next();
1395 FlatMethod fm = state.getMethodFlat( md );
1396 bw = new BufferedWriter( new FileWriter( "mlpReport_"+
1397 md.getClassMethodName()+
1398 md.getSafeMethodDescriptor()+
1400 bw.write( "MLP Results for "+md+"\n-------------------\n");
1401 bw.write( "\n\nLive-In, Root View\n------------------\n" +fm.printMethod( livenessRootView ) );
1402 bw.write( "\n\nVariable Results-Out\n----------------\n" +fm.printMethod( variableResults ) );
1403 bw.write( "\n\nNot Available Results-Out\n---------------------\n"+fm.printMethod( notAvailableResults ) );
1404 bw.write( "\n\nCode Plans\n----------\n" +fm.printMethod( codePlans ) );
1409 private void printSESEHierarchy( BufferedWriter bw ) throws java.io.IOException {
1410 bw.write( "SESE Hierarchy\n--------------\n" );
1411 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
1412 while( rootItr.hasNext() ) {
1413 FlatSESEEnterNode root = rootItr.next();
1414 if( root.getIsCallerSESEplaceholder() ) {
1415 if( !root.getChildren().isEmpty() ) {
1416 printSESEHierarchyTree( bw, root, 0 );
1419 printSESEHierarchyTree( bw, root, 0 );
1424 private void printSESEHierarchyTree( BufferedWriter bw,
1425 FlatSESEEnterNode fsen,
1427 ) throws java.io.IOException {
1428 for( int i = 0; i < depth; ++i ) {
1431 bw.write( "- "+fsen.getPrettyIdentifier()+"\n" );
1433 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1434 while( childItr.hasNext() ) {
1435 FlatSESEEnterNode fsenChild = childItr.next();
1436 printSESEHierarchyTree( bw, fsenChild, depth + 1 );
1441 private void printSESEInfo( BufferedWriter bw ) throws java.io.IOException {
1442 bw.write("\nSESE info\n-------------\n" );
1443 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
1444 while( rootItr.hasNext() ) {
1445 FlatSESEEnterNode root = rootItr.next();
1446 if( root.getIsCallerSESEplaceholder() ) {
1447 if( !root.getChildren().isEmpty() ) {
1448 printSESEInfoTree( bw, root );
1451 printSESEInfoTree( bw, root );
1456 private void printSESEInfoTree( BufferedWriter bw,
1457 FlatSESEEnterNode fsen
1458 ) throws java.io.IOException {
1460 if( !fsen.getIsCallerSESEplaceholder() ) {
1461 bw.write( "SESE "+fsen.getPrettyIdentifier()+" {\n" );
1463 bw.write( " in-set: "+fsen.getInVarSet()+"\n" );
1464 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
1465 while( tItr.hasNext() ) {
1466 TempDescriptor inVar = tItr.next();
1467 if( fsen.getReadyInVarSet().contains( inVar ) ) {
1468 bw.write( " (ready) "+inVar+"\n" );
1470 if( fsen.getStaticInVarSet().contains( inVar ) ) {
1471 bw.write( " (static) "+inVar+"\n" );
1473 if( fsen.getDynamicInVarSet().contains( inVar ) ) {
1474 bw.write( " (dynamic)"+inVar+"\n" );
1478 bw.write( " out-set: "+fsen.getOutVarSet()+"\n" );
1482 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
1483 while( childItr.hasNext() ) {
1484 FlatSESEEnterNode fsenChild = childItr.next();
1485 printSESEInfoTree( bw, fsenChild );