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 private Hashtable< MethodContext, HashSet<AllocationSite>> mapMethodContextToLiveInAllocationSiteSet;
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 mapMethodContextToLiveInAllocationSiteSet = new Hashtable< MethodContext, HashSet<AllocationSite>>();
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 );
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);
200 // disjoint analysis with a set of flagged allocation sites of live-in variable
202 OwnershipAnalysis oa2 = new OwnershipAnalysis(state, tu, callGraph,
203 state.OWNERSHIPALLOCDEPTH, false,
204 false, state.OWNERSHIPALIASFILE,
206 mapMethodContextToLiveInAllocationSiteSet);
208 methItr = oa2.descriptorsToAnalyze.iterator();
209 while (methItr.hasNext()) {
210 Descriptor d = methItr.next();
211 FlatMethod fm = state.getMethodFlat(d);
212 debugFunction(oa2, fm);
215 } catch (IOException e) {
216 System.err.println(e);
222 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
223 while( methItr.hasNext() ) {
224 Descriptor d = methItr.next();
225 FlatMethod fm = state.getMethodFlat( d );
227 // compute a plan for code injections
228 codePlansForward( fm );
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();
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 );
247 if( state.MLPDEBUG ) {
249 writeReports( treport );
250 } catch( IOException e ) {}
255 private void buildForestForward( FlatMethod fm ) {
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 );
263 Set<FlatNode> visited = new HashSet<FlatNode>();
265 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
266 seseStacks.put( fm, seseStackFirst );
268 while( !flatNodesToVisit.isEmpty() ) {
269 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
270 FlatNode fn = fnItr.next();
272 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
273 assert seseStack != null;
275 flatNodesToVisit.remove( fn );
278 buildForest_nodeActions( fn, seseStack, fm );
280 for( int i = 0; i < fn.numNext(); i++ ) {
281 FlatNode nn = fn.getNext( i );
283 if( !visited.contains( nn ) ) {
284 flatNodesToVisit.add( nn );
286 // clone stack and send along each analysis path
287 seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
293 private void buildForest_nodeActions( FlatNode fn,
294 Stack<FlatSESEEnterNode> seseStack,
296 switch( fn.kind() ) {
298 case FKind.FlatSESEEnterNode: {
299 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
301 if( !fsen.getIsCallerSESEplaceholder() ) {
302 allSESEs.add( fsen );
305 fsen.setfmEnclosing( fm );
306 fsen.setmdEnclosing( fm.getMethod() );
307 fsen.setcdEnclosing( fm.getMethod().getClassDesc() );
309 if( seseStack.empty() ) {
310 rootSESEs.add( fsen );
311 fsen.setParent( null );
313 seseStack.peek().addChild( fsen );
314 fsen.setParent( seseStack.peek() );
317 seseStack.push( fsen );
320 case FKind.FlatSESEExitNode: {
321 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
322 assert !seseStack.empty();
323 FlatSESEEnterNode fsen = seseStack.pop();
326 case FKind.FlatReturnNode: {
327 FlatReturnNode frn = (FlatReturnNode) fn;
328 if( !seseStack.empty() &&
329 !seseStack.peek().getIsCallerSESEplaceholder()
331 throw new Error( "Error: return statement enclosed within SESE "+
332 seseStack.peek().getPrettyIdentifier() );
340 private void livenessAnalysisBackward( FlatSESEEnterNode fsen,
342 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout ) {
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>();
351 flatNodesToVisit.add( fsen.getfmEnclosing().getFlatExit() );
353 flatNodesToVisit.add( fsen.getFlatExit() );
356 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults =
357 new Hashtable< FlatNode, Set<TempDescriptor> >();
360 liveout = new Hashtable< FlatSESEExitNode, Set<TempDescriptor> >();
363 while( !flatNodesToVisit.isEmpty() ) {
364 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
365 flatNodesToVisit.remove( fn );
367 Set<TempDescriptor> prev = livenessResults.get( fn );
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 );
379 Set<TempDescriptor> curr = liveness_nodeActions( fn, u, fsen, toplevel, liveout);
381 // if a new result, schedule backward nodes for analysis
382 if( !curr.equals( prev ) ) {
383 livenessResults.put( fn, curr );
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 );
395 Set<TempDescriptor> s = livenessResults.get( fsen );
397 fsen.addInVarSet( s );
400 // remember liveness per node from the root view as the
401 // global liveness of variables for later passes to use
403 livenessRootView.putAll( livenessResults );
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 );
414 private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
415 Set<TempDescriptor> liveIn,
416 FlatSESEEnterNode currentSESE,
418 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout
420 switch( fn.kind() ) {
422 case FKind.FlatSESEExitNode:
424 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
425 if( !liveout.containsKey( fsexn ) ) {
426 liveout.put( fsexn, new HashSet<TempDescriptor>() );
428 liveout.get( fsexn ).addAll( liveIn );
430 // no break, sese exits should also execute default actions
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] );
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] );
450 TempDescriptor [] readTemps = fn.readsTemps();
451 for( int i = 0; i < readTemps.length; ++i ) {
452 liveIn.add( readTemps[i] );
455 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get( fn );
456 if( virtualReadTemps != null ) {
457 liveIn.addAll( virtualReadTemps );
468 private void variableAnalysisForward( FlatMethod fm ) {
470 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
471 flatNodesToVisit.add( fm );
473 while( !flatNodesToVisit.isEmpty() ) {
474 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
475 flatNodesToVisit.remove( fn );
477 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
478 assert seseStack != null;
480 VarSrcTokTable prev = variableResults.get( fn );
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 );
490 if( !seseStack.empty() ) {
491 variable_nodeActions( fn, curr, seseStack.peek() );
494 // if a new result, schedule forward nodes for analysis
495 if( !curr.equals( prev ) ) {
496 variableResults.put( fn, curr );
498 for( int i = 0; i < fn.numNext(); i++ ) {
499 FlatNode nn = fn.getNext( i );
500 flatNodesToVisit.add( nn );
506 private void variable_nodeActions( FlatNode fn,
507 VarSrcTokTable vstTable,
508 FlatSESEEnterNode currentSESE ) {
509 switch( fn.kind() ) {
511 case FKind.FlatSESEEnterNode: {
512 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
513 assert fsen.equals( currentSESE );
515 vstTable.age( currentSESE );
516 vstTable.assertConsistency();
519 case FKind.FlatSESEExitNode: {
520 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
521 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
522 assert currentSESE.getChildren().contains( fsen );
524 vstTable.remapChildTokens( fsen );
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 );
536 livenessVirtualReads.put( fn, fsenVirtReads );
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>();
547 VariableSourceToken vst =
548 new VariableSourceToken( ts,
553 vstTable.remove( outVar );
556 vstTable.assertConsistency();
560 case FKind.FlatOpNode: {
561 FlatOpNode fon = (FlatOpNode) fn;
563 if( fon.getOp().getOp() == Operation.ASSIGN ) {
564 TempDescriptor lhs = fon.getDest();
565 TempDescriptor rhs = fon.getLeft();
567 vstTable.remove( lhs );
569 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
571 Iterator<VariableSourceToken> itr = vstTable.get( rhs ).iterator();
572 while( itr.hasNext() ) {
573 VariableSourceToken vst = itr.next();
575 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
578 if( currentSESE.getChildren().contains( vst.getSESE() ) ) {
579 // if the source comes from a child, copy it over
580 forAddition.add( new VariableSourceToken( ts,
587 // otherwise, stamp it as us as the source
588 forAddition.add( new VariableSourceToken( ts,
597 vstTable.addAll( forAddition );
599 // only break if this is an ASSIGN op node,
600 // otherwise fall through to default case
601 vstTable.assertConsistency();
606 // note that FlatOpNode's that aren't ASSIGN
607 // fall through to this default case
609 TempDescriptor [] writeTemps = fn.writesTemps();
610 if( writeTemps.length > 0 ) {
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;
623 vstTable.remove( writeTemps[0] );
625 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
626 ts.add( writeTemps[0] );
628 vstTable.add( new VariableSourceToken( ts,
636 vstTable.assertConsistency();
643 private void pruneVariableResultsWithLiveness( FlatMethod fm ) {
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 );
650 Set<FlatNode> visited = new HashSet<FlatNode>();
652 while( !flatNodesToVisit.isEmpty() ) {
653 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
654 FlatNode fn = fnItr.next();
656 flatNodesToVisit.remove( fn );
659 Set<TempDescriptor> rootLiveSet = livenessRootView.get( fn );
660 VarSrcTokTable vstTable = variableResults.get( fn );
662 vstTable.pruneByLiveness( rootLiveSet );
664 for( int i = 0; i < fn.numNext(); i++ ) {
665 FlatNode nn = fn.getNext( i );
667 if( !visited.contains( nn ) ) {
668 flatNodesToVisit.add( nn );
675 private void notAvailableForward( FlatMethod fm ) {
677 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
678 flatNodesToVisit.add( fm );
680 while( !flatNodesToVisit.isEmpty() ) {
681 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
682 flatNodesToVisit.remove( fn );
684 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
685 assert seseStack != null;
687 Set<TempDescriptor> prev = notAvailableResults.get( fn );
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 );
698 if( !seseStack.empty() ) {
699 notAvailable_nodeActions( fn, curr, seseStack.peek() );
702 // if a new result, schedule forward nodes for analysis
703 if( !curr.equals( prev ) ) {
704 notAvailableResults.put( fn, curr );
706 for( int i = 0; i < fn.numNext(); i++ ) {
707 FlatNode nn = fn.getNext( i );
708 flatNodesToVisit.add( nn );
714 private void notAvailable_nodeActions( FlatNode fn,
715 Set<TempDescriptor> notAvailSet,
716 FlatSESEEnterNode currentSESE ) {
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!
722 switch( fn.kind() ) {
724 case FKind.FlatSESEEnterNode: {
725 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
726 assert fsen.equals( currentSESE );
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() );
737 case FKind.FlatMethod: {
741 case FKind.FlatOpNode: {
742 FlatOpNode fon = (FlatOpNode) fn;
744 if( fon.getOp().getOp() == Operation.ASSIGN ) {
745 TempDescriptor lhs = fon.getDest();
746 TempDescriptor rhs = fon.getLeft();
748 // copy makes lhs same availability as rhs
749 if( notAvailSet.contains( rhs ) ) {
750 notAvailSet.add( lhs );
752 notAvailSet.remove( lhs );
755 // only break if this is an ASSIGN op node,
756 // otherwise fall through to default case
761 // note that FlatOpNode's that aren't ASSIGN
762 // fall through to this default case
764 TempDescriptor [] writeTemps = fn.writesTemps();
765 for( int i = 0; i < writeTemps.length; i++ ) {
766 TempDescriptor wTemp = writeTemps[i];
767 notAvailSet.remove( wTemp );
769 TempDescriptor [] readTemps = fn.readsTemps();
770 for( int i = 0; i < readTemps.length; i++ ) {
771 TempDescriptor rTemp = readTemps[i];
772 notAvailSet.remove( rTemp );
774 // if this variable has exactly one source, potentially
775 // get other things from this source as well
776 VarSrcTokTable vstTable = variableResults.get( fn );
779 vstTable.getRefVarSrcType( rTemp,
781 currentSESE.getParent() );
783 if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
785 VariableSourceToken vst = vstTable.get( rTemp ).iterator().next();
787 Iterator<VariableSourceToken> availItr = vstTable.get( vst.getSESE(),
791 // look through things that are also available from same source
792 while( availItr.hasNext() ) {
793 VariableSourceToken vstAlsoAvail = availItr.next();
795 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
796 while( refVarItr.hasNext() ) {
797 TempDescriptor refVarAlso = refVarItr.next();
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,
804 currentSESE.getParent() );
805 if( srcTypeAlso.equals( VarSrcTokTable.SrcType_STATIC ) ) {
806 notAvailSet.remove( refVarAlso );
817 private void debugFunction(OwnershipAnalysis oa2, FlatMethod fm) {
819 String methodName="SomeWork";
821 MethodDescriptor md=fm.getMethod();
822 HashSet<MethodContext> mcSet=oa2.getAllMethodContextSetByDescriptor(md);
823 Iterator<MethodContext> mcIter=mcSet.iterator();
825 while(mcIter.hasNext()){
826 MethodContext mc=mcIter.next();
828 OwnershipGraph og=oa2.getOwnvershipGraphByMethodContext(mc);
830 if(fm.toString().indexOf(methodName)>0){
832 og.writeGraph(fm.toString() + "SECONDGRAPH",
833 true, // write labels (variables)
834 true, // selectively hide intermediate temp vars
835 true, // prune unreachable heap regions
836 false, // show back edges to confirm graph validity
837 false, // show parameter indices (unmaintained!)
838 true, // hide subset reachability states
839 false);// hide edge taints
840 } catch (IOException e) {
841 System.out.println("Error writing debug capture.");
852 private void methodEffects(FlatMethod fm, CallGraph callGraph) {
854 MethodDescriptor md=fm.getMethod();
855 HashSet<MethodContext> mcSet=ownAnalysis.getAllMethodContextSetByDescriptor(md);
856 Iterator<MethodContext> mcIter=mcSet.iterator();
858 while(mcIter.hasNext()){
859 MethodContext mc=mcIter.next();
861 Set<FlatNode> visited = new HashSet<FlatNode>();
863 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
864 flatNodesToVisit.add(fm);
866 while (!flatNodesToVisit.isEmpty()) {
867 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
868 flatNodesToVisit.remove(fn);
870 Stack<FlatSESEEnterNode> seseStack = seseStacks.get(fn);
871 assert seseStack != null;
873 if (!seseStack.empty()) {
874 effects_nodeActions(mc, fn, seseStack.peek(), callGraph);
877 flatNodesToVisit.remove(fn);
880 for (int i = 0; i < fn.numNext(); i++) {
881 FlatNode nn = fn.getNext(i);
882 if (!visited.contains(nn)) {
883 flatNodesToVisit.add(nn);
894 private void analyzeRelatedAllocationSite(MethodDescriptor callerMD,
895 MethodContext calleeMC, HashSet<Integer> paramIndexSet,
896 HashSet<HeapRegionNode> visitedHRN) {
898 HashSet<MethodContext> mcSet = ownAnalysis
899 .getAllMethodContextSetByDescriptor(callerMD);
903 Iterator<MethodContext> mcIter = mcSet.iterator();
905 FlatMethod callerFM = state.getMethodFlat(callerMD);
907 while (mcIter.hasNext()) {
908 MethodContext mc = mcIter.next();
910 Set<FlatNode> visited = new HashSet<FlatNode>();
911 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
912 flatNodesToVisit.add(callerFM);
914 while (!flatNodesToVisit.isEmpty()) {
915 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
916 flatNodesToVisit.remove(fn);
918 analyzeRelatedAllocationSite_NodeAction(fn, mc, calleeMC,
919 paramIndexSet,visitedHRN);
921 flatNodesToVisit.remove(fn);
924 for (int i = 0; i < fn.numNext(); i++) {
925 FlatNode nn = fn.getNext(i);
926 if (!visited.contains(nn)) {
927 flatNodesToVisit.add(nn);
936 private void analyzeRelatedAllocationSite_NodeAction(FlatNode fn, MethodContext callerMC,
937 MethodContext calleeMC,
938 HashSet<Integer> paramIndexSet, HashSet<HeapRegionNode> visitedHRN) {
940 OwnershipGraph og = ownAnalysis
941 .getOwnvershipGraphByMethodContext(callerMC);
945 case FKind.FlatCall: {
947 FlatCall fc = (FlatCall) fn;
950 MethodContext calleeMCfromOG = ownAnalysis.getCalleeMethodContext(
953 // disable below condition. currently collect all possible
954 // allocation sites without regarding method context
956 // if (calleeMC.equals(calleeMCfromOG)) { // in this case, this
957 // method context calls corresponding callee.
960 if (((MethodDescriptor) calleeMC.getDescriptor()).isStatic()) {
966 for (Iterator iterator = paramIndexSet.iterator(); iterator
968 Integer integer = (Integer) iterator.next();
970 int paramIdx = integer - base;
972 // if paramIdx is less than 0, assumes that it is
973 // related with wrong method contexts.
974 TempDescriptor arg = fc.getArg(paramIdx);
975 LabelNode argLN = og.td2ln.get(arg);
977 Iterator<ReferenceEdge> iterEdge = argLN
978 .iteratorToReferencees();
979 while (iterEdge.hasNext()) {
980 ReferenceEdge referenceEdge = (ReferenceEdge) iterEdge
983 HeapRegionNode dstHRN = referenceEdge.getDst();
984 if (dstHRN.isParameter()) {
985 if (!visitedHRN.contains(dstHRN)) {
986 setupRelatedAllocSiteAnalysis(og, callerMC,
990 addLiveInAllocationSite(callerMC, dstHRN
991 .getAllocationSite());
1008 private void setupRelatedAllocSiteAnalysis(OwnershipGraph og,
1009 MethodContext mc, HeapRegionNode dstHRN,
1010 HashSet<HeapRegionNode> visitedHRN) {
1012 HashSet<Integer> paramIndexSet = new HashSet<Integer>();
1014 // collect corresponding param index
1015 Set<Integer> pIndexSet = og.idPrimary2paramIndexSet.get(dstHRN.getID());
1016 if (pIndexSet != null) {
1017 for (Iterator iterator = pIndexSet.iterator(); iterator.hasNext();) {
1018 Integer integer = (Integer) iterator.next();
1019 paramIndexSet.add(integer);
1023 Set<Integer> sIndexSet = og.idSecondary2paramIndexSet.get(dstHRN
1025 if (sIndexSet != null) {
1026 for (Iterator iterator = sIndexSet.iterator(); iterator.hasNext();) {
1027 Integer integer = (Integer) iterator.next();
1028 paramIndexSet.add(integer);
1032 if (mc.getDescriptor() instanceof MethodDescriptor) {
1033 Set callerSet = callGraph.getCallerSet((MethodDescriptor) mc
1035 for (Iterator iterator = callerSet.iterator(); iterator.hasNext();) {
1036 Object obj = (Object) iterator.next();
1037 if (obj instanceof MethodDescriptor) {
1038 MethodDescriptor callerMD = (MethodDescriptor) obj;
1040 analyzeRelatedAllocationSite(callerMD, mc, paramIndexSet,visitedHRN);
1047 private void effects_nodeActions(MethodContext mc, FlatNode fn,
1048 FlatSESEEnterNode currentSESE, CallGraph callGraph) {
1050 OwnershipGraph og = ownAnalysis.getOwnvershipGraphByMethodContext(mc);
1052 switch (fn.kind()) {
1054 case FKind.FlatSESEEnterNode: {
1056 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
1057 assert fsen.equals(currentSESE);
1059 // uniquely taint each live-in variable
1060 Set<TempDescriptor> set = fsen.getInVarSet();
1061 Iterator<TempDescriptor> iter = set.iterator();
1063 while (iter.hasNext()) {
1064 TempDescriptor td = iter.next();
1065 LabelNode ln = og.td2ln.get(td);
1067 int taint = (int) Math.pow(2, idx);
1068 taintLabelNode(ln, taint);
1070 // collects related allocation sites
1071 Iterator<ReferenceEdge> referenceeIter = ln
1072 .iteratorToReferencees();
1073 while (referenceeIter.hasNext()) {
1074 ReferenceEdge referenceEdge = (ReferenceEdge) referenceeIter
1076 HeapRegionNode dstHRN = referenceEdge.getDst();
1077 if (dstHRN.isParameter()) {
1079 HashSet<HeapRegionNode> visitedHRN=new HashSet<HeapRegionNode>();
1080 visitedHRN.add(dstHRN);
1081 setupRelatedAllocSiteAnalysis(og,mc,dstHRN,visitedHRN);
1084 addLiveInAllocationSite(mc, dstHRN
1085 .getAllocationSite());
1097 case FKind.FlatSESEExitNode: {
1098 FlatSESEExitNode fsexit = (FlatSESEExitNode) fn;
1100 FlatSESEEnterNode enterNode = fsexit.getFlatEnter();
1101 FlatSESEEnterNode parent = enterNode.getParent();
1102 if (parent != null) {
1104 SESEEffectsSet set = enterNode.getSeseEffectsSet();
1105 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> readTable = set
1107 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentReadTable = parent
1108 .getSeseEffectsSet().getReadTable();
1109 Set<TempDescriptor> keys = readTable.keySet();
1110 Iterator<TempDescriptor> keyIter = keys.iterator();
1111 while (keyIter.hasNext()) {
1112 TempDescriptor td = (TempDescriptor) keyIter.next();
1113 HashSet<SESEEffectsKey> effectsSet = readTable.get(td);
1114 HashSet<SESEEffectsKey> parentEffectsSet = parentReadTable
1116 if (parentEffectsSet == null) {
1117 parentEffectsSet = new HashSet<SESEEffectsKey>();
1120 for (Iterator iterator = effectsSet.iterator(); iterator
1122 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
1124 parentEffectsSet.add(new SESEEffectsKey(seseKey
1125 .getFieldDescriptor(), seseKey
1126 .getTypeDescriptor(), seseKey.getHRNId()));
1129 parentReadTable.put(td, parentEffectsSet);
1132 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> writeTable = set
1134 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentWriteTable = parent
1135 .getSeseEffectsSet().getWriteTable();
1136 keys = writeTable.keySet();
1137 keyIter = keys.iterator();
1138 while (keyIter.hasNext()) {
1139 TempDescriptor td = (TempDescriptor) keyIter.next();
1140 HashSet<SESEEffectsKey> effectsSet = writeTable.get(td);
1141 HashSet<SESEEffectsKey> parentEffectsSet = parentWriteTable
1143 if (parentEffectsSet == null) {
1144 parentEffectsSet = new HashSet<SESEEffectsKey>();
1147 for (Iterator iterator = effectsSet.iterator(); iterator
1149 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
1151 parentEffectsSet.add(new SESEEffectsKey(seseKey
1152 .getFieldDescriptor(), seseKey
1153 .getTypeDescriptor(), seseKey.getHRNId()));
1156 parentWriteTable.put(td, parentEffectsSet);
1159 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> strongUpdateTable = set
1160 .getStrongUpdateTable();
1161 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentstrongUpdateTable = parent
1162 .getSeseEffectsSet().getStrongUpdateTable();
1163 keys = strongUpdateTable.keySet();
1164 keyIter = keys.iterator();
1165 while (keyIter.hasNext()) {
1166 TempDescriptor td = (TempDescriptor) keyIter.next();
1167 HashSet<SESEEffectsKey> effectsSet = strongUpdateTable
1169 HashSet<SESEEffectsKey> parentEffectsSet = parentstrongUpdateTable
1171 if (parentEffectsSet == null) {
1172 parentEffectsSet = new HashSet<SESEEffectsKey>();
1175 for (Iterator iterator = effectsSet.iterator(); iterator
1177 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
1179 parentEffectsSet.add(new SESEEffectsKey(seseKey
1180 .getFieldDescriptor(), seseKey
1181 .getTypeDescriptor(), seseKey.getHRNId()));
1184 parentstrongUpdateTable.put(td, parentEffectsSet);
1192 case FKind.FlatFieldNode: {
1194 FlatFieldNode ffn = (FlatFieldNode) fn;
1195 TempDescriptor src = ffn.getSrc();
1196 FieldDescriptor field = ffn.getField();
1198 LabelNode srcLN = og.td2ln.get(src);
1199 if (srcLN != null) {
1200 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(srcLN);
1201 Iterator<TempDescriptor> affectedIter = affectedTDSet
1203 while (affectedIter.hasNext()) {
1204 TempDescriptor affectedTD = affectedIter.next();
1206 if (currentSESE.getInVarSet().contains(affectedTD)) {
1208 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1210 Iterator<HeapRegionNode> hrnIter = hrnSet.iterator();
1211 while (hrnIter.hasNext()) {
1212 HeapRegionNode hrn = hrnIter.next();
1214 Iterator<ReferenceEdge> referencers = hrn
1215 .iteratorToReferencers();
1216 while (referencers.hasNext()) {
1217 ReferenceEdge referenceEdge = (ReferenceEdge) referencers
1219 if (field.getSymbol().equals(
1220 referenceEdge.getField())) {
1221 currentSESE.readEffects(affectedTD, field
1222 .getSymbol(), src.getType(),
1223 referenceEdge.getDst().getID());
1231 // handle tainted case
1233 Iterator<ReferenceEdge> edgeIter = srcLN
1234 .iteratorToReferencees();
1235 while (edgeIter.hasNext()) {
1236 ReferenceEdge edge = edgeIter.next();
1237 HeapRegionNode accessHRN = edge.getDst();
1238 // / follow the chain of reference to identify possible
1240 Iterator<ReferenceEdge> referIter = accessHRN
1241 .iteratorToReferencers();
1242 while (referIter.hasNext()) {
1243 ReferenceEdge referEdge = (ReferenceEdge) referIter
1246 // if (referEdge.getTaintIdentifier() >0 ||
1247 // referEdge.getSESETaintIdentifier()>0 ) {
1248 HashSet<TempDescriptor> referSet = new HashSet<TempDescriptor>();
1249 followReference(accessHRN, referSet,
1250 new HashSet<HeapRegionNode>(), currentSESE);
1252 Iterator<TempDescriptor> referSetIter = referSet
1254 while (referSetIter.hasNext()) {
1255 TempDescriptor tempDescriptor = (TempDescriptor) referSetIter
1257 currentSESE.readEffects(tempDescriptor, field
1258 .getSymbol(), src.getType(), accessHRN
1264 if (edge.getTaintIdentifier() > 0
1265 || edge.getSESETaintIdentifier() > 0) {
1267 affectedTDSet = getReferenceNodeSet(accessHRN);
1268 affectedIter = affectedTDSet.iterator();
1269 while (affectedIter.hasNext()) {
1270 TempDescriptor affectedTD = affectedIter.next();
1272 if (currentSESE.getInVarSet().contains(affectedTD)) {
1274 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1276 Iterator<HeapRegionNode> hrnIter = hrnSet
1278 while (hrnIter.hasNext()) {
1279 HeapRegionNode hrn = hrnIter.next();
1280 currentSESE.readEffects(affectedTD, field
1281 .getSymbol(), src.getType(), hrn
1295 case FKind.FlatSetFieldNode: {
1297 FlatSetFieldNode fsen = (FlatSetFieldNode) fn;
1298 TempDescriptor dst = fsen.getDst();
1299 FieldDescriptor field = fsen.getField();
1301 LabelNode dstLN = og.td2ln.get(dst);
1302 if (dstLN != null) {
1303 // check possible strong updates
1304 boolean strongUpdate = false;
1306 if (!field.getType().isImmutable() || field.getType().isArray()) {
1307 Iterator<ReferenceEdge> itrXhrn = dstLN
1308 .iteratorToReferencees();
1309 while (itrXhrn.hasNext()) {
1310 ReferenceEdge edgeX = itrXhrn.next();
1311 HeapRegionNode hrnX = edgeX.getDst();
1313 // we can do a strong update here if one of two cases
1316 && field != OwnershipAnalysis
1317 .getArrayField(field.getType())
1318 && ((hrnX.getNumReferencers() == 1) || // case 1
1319 (hrnX.isSingleObject() && dstLN
1320 .getNumReferencees() == 1) // case 2
1322 strongUpdate = true;
1327 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(dstLN);
1329 Iterator<TempDescriptor> affectedIter = affectedTDSet
1332 while (affectedIter.hasNext()) {
1333 TempDescriptor affectedTD = affectedIter.next();
1334 if (currentSESE.getInVarSet().contains(affectedTD)) {
1336 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1338 Iterator<HeapRegionNode> hrnIter = hrnSet.iterator();
1339 while (hrnIter.hasNext()) {
1340 HeapRegionNode hrn = hrnIter.next();
1342 Iterator<ReferenceEdge> referencers = hrn
1343 .iteratorToReferencers();
1344 while (referencers.hasNext()) {
1345 ReferenceEdge referenceEdge = (ReferenceEdge) referencers
1347 if (field.getSymbol().equals(
1348 referenceEdge.getField())) {
1349 currentSESE.writeEffects(affectedTD, field
1350 .getSymbol(), dst.getType(),
1351 referenceEdge.getDst().getID(),
1360 // handle tainted case
1361 Iterator<ReferenceEdge> edgeIter = dstLN
1362 .iteratorToReferencees();
1363 while (edgeIter.hasNext()) {
1364 ReferenceEdge edge = edgeIter.next();
1366 HeapRegionNode accessHRN = edge.getDst();
1367 // / follow the chain of reference to identify possible
1369 Iterator<ReferenceEdge> referIter = accessHRN
1370 .iteratorToReferencers();
1371 while (referIter.hasNext()) {
1372 ReferenceEdge referEdge = (ReferenceEdge) referIter
1375 // if (referEdge.getTaintIdentifier() > 0 ||
1376 // referEdge.getSESETaintIdentifier() > 0 ) {
1377 HashSet<TempDescriptor> referSet = new HashSet<TempDescriptor>();
1378 followReference(accessHRN, referSet,
1379 new HashSet<HeapRegionNode>(), currentSESE);
1380 Iterator<TempDescriptor> referSetIter = referSet
1382 while (referSetIter.hasNext()) {
1383 TempDescriptor tempDescriptor = (TempDescriptor) referSetIter
1385 currentSESE.writeEffects(tempDescriptor, field
1386 .getSymbol(), dst.getType(), accessHRN
1387 .getID(), strongUpdate);
1392 if (edge.getTaintIdentifier() > 0
1393 || edge.getSESETaintIdentifier() > 0) {
1394 affectedTDSet = getReferenceNodeSet(accessHRN);
1395 affectedIter = affectedTDSet.iterator();
1396 while (affectedIter.hasNext()) {
1397 TempDescriptor affectedTD = affectedIter.next();
1398 if (currentSESE.getInVarSet().contains(affectedTD)) {
1400 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1402 Iterator<HeapRegionNode> hrnIter = hrnSet
1404 while (hrnIter.hasNext()) {
1405 HeapRegionNode hrn = hrnIter.next();
1406 currentSESE.writeEffects(affectedTD, field
1407 .getSymbol(), dst.getType(), hrn
1408 .getID(), strongUpdate);
1423 case FKind.FlatCall: {
1424 FlatCall fc = (FlatCall) fn;
1426 MethodContext calleeMC = ownAnalysis.getCalleeMethodContext(mc, fc);
1428 MethodEffects me = ownAnalysis.getMethodEffectsAnalysis()
1429 .getMethodEffectsByMethodContext(calleeMC);
1431 OwnershipGraph calleeOG = ownAnalysis
1432 .getOwnvershipGraphByMethodContext(calleeMC);
1434 FlatMethod fm = state.getMethodFlat(fc.getMethod());
1435 ParameterDecomposition decomp = new ParameterDecomposition(
1436 ownAnalysis, fc, fm, calleeMC, calleeOG, og);
1439 if (((MethodDescriptor) calleeMC.getDescriptor()).isStatic()) {
1445 for (int i = 0; i < fc.numArgs(); i++) {
1447 TempDescriptor arg = fc.getArg(i);
1448 Set<EffectsKey> readSet = me.getEffects().getReadingSet(
1450 Set<EffectsKey> writeSet = me.getEffects().getWritingSet(
1453 Set<EffectsKey> strongUpdateSet = me.getEffects()
1454 .getStrongUpdateSet(i + base);
1456 LabelNode argLN = og.td2ln.get(arg);
1457 if (argLN != null) {
1458 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(argLN);
1459 Iterator<TempDescriptor> affectedIter = affectedTDSet
1462 while (affectedIter.hasNext()) {
1464 TempDescriptor affectedTD = affectedIter.next();
1465 if (currentSESE.getInVarSet().contains(affectedTD)) {
1467 if (readSet != null) {
1468 Iterator<EffectsKey> readIter = readSet
1470 while (readIter.hasNext()) {
1471 EffectsKey key = readIter.next();
1472 Set<Integer> hrnSet = getCallerHRNId(
1473 new Integer(i + base), calleeOG,
1474 key.getHRNId(), decomp);
1475 Iterator<Integer> hrnIter = hrnSet
1477 while (hrnIter.hasNext()) {
1478 Integer hrnID = (Integer) hrnIter
1480 currentSESE.readEffects(affectedTD, key
1481 .getFieldDescriptor(), key
1482 .getTypeDescriptor(), hrnID);
1487 if (writeSet != null) {
1488 Iterator<EffectsKey> writeIter = writeSet
1490 while (writeIter.hasNext()) {
1491 EffectsKey key = writeIter.next();
1493 Set<Integer> hrnSet = getCallerHRNId(
1494 new Integer(i + base), calleeOG,
1495 key.getHRNId(), decomp);
1496 Iterator<Integer> hrnIter = hrnSet
1498 while (hrnIter.hasNext()) {
1499 Integer hrnID = (Integer) hrnIter
1501 currentSESE.writeEffects(affectedTD,
1502 key.getFieldDescriptor(), key
1503 .getTypeDescriptor(),
1510 if (strongUpdateSet != null) {
1511 Iterator<EffectsKey> strongUpdateIter = strongUpdateSet
1513 while (strongUpdateIter.hasNext()) {
1514 EffectsKey key = strongUpdateIter.next();
1516 Set<Integer> hrnSet = getCallerHRNId(
1517 new Integer(i + base), calleeOG,
1518 key.getHRNId(), decomp);
1519 Iterator<Integer> hrnIter = hrnSet
1521 while (hrnIter.hasNext()) {
1522 Integer hrnID = (Integer) hrnIter
1524 currentSESE.writeEffects(affectedTD,
1525 key.getFieldDescriptor(), key
1526 .getTypeDescriptor(),
1547 private void addLiveInAllocationSite(MethodContext mc, AllocationSite ac){
1548 HashSet<AllocationSite> set=mapMethodContextToLiveInAllocationSiteSet.get(mc);
1550 set=new HashSet<AllocationSite>();
1553 mapMethodContextToLiveInAllocationSiteSet.put(mc, set);
1556 private void followReference(HeapRegionNode hrn,HashSet<TempDescriptor> tdSet, HashSet<HeapRegionNode> visited, FlatSESEEnterNode currentSESE){
1558 Iterator<ReferenceEdge> referIter=hrn.iteratorToReferencers();
1559 // check whether hrn is referenced by TD
1560 while (referIter.hasNext()) {
1561 ReferenceEdge referEdge = (ReferenceEdge) referIter.next();
1562 if(referEdge.getSrc() instanceof LabelNode){
1563 LabelNode ln=(LabelNode)referEdge.getSrc();
1564 if(currentSESE.getInVarSet().contains(ln.getTempDescriptor())){
1565 tdSet.add(ln.getTempDescriptor());
1567 }else if(referEdge.getSrc() instanceof HeapRegionNode){
1568 HeapRegionNode nextHRN=(HeapRegionNode)referEdge.getSrc();
1569 if(!visited.contains(nextHRN)){
1570 visited.add(nextHRN);
1571 followReference(nextHRN,tdSet,visited,currentSESE);
1579 private Set<Integer> getCallerHRNId(Integer paramIdx,
1580 OwnershipGraph calleeOG, Integer calleeHRNId,
1581 ParameterDecomposition paramDecom) {
1583 Integer hrnPrimaryID = calleeOG.paramIndex2idPrimary.get(paramIdx);
1584 Integer hrnSecondaryID = calleeOG.paramIndex2idSecondary.get(paramIdx);
1586 if (calleeHRNId.equals(hrnPrimaryID)) {
1587 // it references to primary param heap region
1588 return paramDecom.getParamObject_hrnIDs(paramIdx);
1589 } else if (calleeHRNId.equals(hrnSecondaryID)) {
1590 // it references to secondary param heap region
1591 return paramDecom.getParamReachable_hrnIDs(paramIdx);
1594 return new HashSet<Integer>();
1597 private void taintLabelNode(LabelNode ln, int identifier) {
1599 Iterator<ReferenceEdge> edgeIter = ln.iteratorToReferencees();
1600 while (edgeIter.hasNext()) {
1601 ReferenceEdge edge = edgeIter.next();
1602 HeapRegionNode hrn = edge.getDst();
1604 Iterator<ReferenceEdge> edgeReferencerIter = hrn
1605 .iteratorToReferencers();
1606 while (edgeReferencerIter.hasNext()) {
1607 ReferenceEdge referencerEdge = edgeReferencerIter.next();
1608 OwnershipNode node = referencerEdge.getSrc();
1609 if (node instanceof LabelNode) {
1610 referencerEdge.unionSESETaintIdentifier(identifier);
1611 }else if(node instanceof HeapRegionNode){
1612 referencerEdge.unionSESETaintIdentifier(identifier);
1620 private HashSet<TempDescriptor> getReferenceNodeSet(HeapRegionNode hrn){
1622 HashSet<TempDescriptor> returnSet=new HashSet<TempDescriptor>();
1624 Iterator<ReferenceEdge> edgeIter=hrn.iteratorToReferencers();
1625 while(edgeIter.hasNext()){
1626 ReferenceEdge edge=edgeIter.next();
1627 if(edge.getSrc() instanceof LabelNode){
1628 LabelNode ln=(LabelNode)edge.getSrc();
1629 returnSet.add(ln.getTempDescriptor());
1638 private HashSet<HeapRegionNode> getReferenceHeapIDSet(OwnershipGraph og, TempDescriptor td){
1640 HashSet<HeapRegionNode> returnSet=new HashSet<HeapRegionNode>();
1642 LabelNode ln=og.td2ln.get(td);
1643 Iterator<ReferenceEdge> edgeIter=ln.iteratorToReferencees();
1644 while(edgeIter.hasNext()){
1645 ReferenceEdge edge=edgeIter.next();
1646 HeapRegionNode hrn=edge.getDst();
1653 private HashSet<TempDescriptor> getAccessedTaintNodeSet(LabelNode ln) {
1655 HashSet<TempDescriptor> returnSet = new HashSet<TempDescriptor>();
1657 Iterator<ReferenceEdge> edgeIter = ln.iteratorToReferencees();
1658 while (edgeIter.hasNext()) {
1659 ReferenceEdge edge = edgeIter.next();
1660 HeapRegionNode hrn = edge.getDst();
1662 Iterator<ReferenceEdge> edgeReferencerIter = hrn
1663 .iteratorToReferencers();
1664 while (edgeReferencerIter.hasNext()) {
1665 ReferenceEdge referencerEdge = edgeReferencerIter.next();
1667 if (referencerEdge.getSrc() instanceof LabelNode) {
1668 if (!((LabelNode) referencerEdge.getSrc()).equals(ln)) {
1670 if (referencerEdge.getSESETaintIdentifier() > 0) {
1671 TempDescriptor td = ((LabelNode) referencerEdge
1672 .getSrc()).getTempDescriptor();
1686 private void codePlansForward( FlatMethod fm ) {
1688 // start from flat method top, visit every node in
1689 // method exactly once
1690 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
1691 flatNodesToVisit.add( fm );
1693 Set<FlatNode> visited = new HashSet<FlatNode>();
1695 while( !flatNodesToVisit.isEmpty() ) {
1696 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
1697 FlatNode fn = fnItr.next();
1699 flatNodesToVisit.remove( fn );
1702 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
1703 assert seseStack != null;
1705 // use incoming results as "dot statement" or just
1706 // before the current statement
1707 VarSrcTokTable dotSTtable = new VarSrcTokTable();
1708 for( int i = 0; i < fn.numPrev(); i++ ) {
1709 FlatNode nn = fn.getPrev( i );
1710 dotSTtable.merge( variableResults.get( nn ) );
1713 // find dt-st notAvailableSet also
1714 Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
1715 for( int i = 0; i < fn.numPrev(); i++ ) {
1716 FlatNode nn = fn.getPrev( i );
1717 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
1718 if( notAvailIn != null ) {
1719 dotSTnotAvailSet.addAll( notAvailIn );
1723 Set<TempDescriptor> dotSTlive = livenessRootView.get( fn );
1725 if( !seseStack.empty() ) {
1726 codePlans_nodeActions( fn,
1734 for( int i = 0; i < fn.numNext(); i++ ) {
1735 FlatNode nn = fn.getNext( i );
1737 if( !visited.contains( nn ) ) {
1738 flatNodesToVisit.add( nn );
1744 private void codePlans_nodeActions( FlatNode fn,
1745 Set<TempDescriptor> liveSetIn,
1746 VarSrcTokTable vstTableIn,
1747 Set<TempDescriptor> notAvailSetIn,
1748 FlatSESEEnterNode currentSESE ) {
1750 CodePlan plan = new CodePlan( currentSESE);
1752 switch( fn.kind() ) {
1754 case FKind.FlatSESEEnterNode: {
1755 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
1757 // track the source types of the in-var set so generated
1758 // code at this SESE issue can compute the number of
1759 // dependencies properly
1760 Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
1761 while( inVarItr.hasNext() ) {
1762 TempDescriptor inVar = inVarItr.next();
1764 vstTableIn.getRefVarSrcType( inVar,
1768 // the current SESE needs a local space to track the dynamic
1769 // variable and the child needs space in its SESE record
1770 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1771 fsen.addDynamicInVar( inVar );
1772 fsen.getParent().addDynamicVar( inVar );
1774 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
1775 fsen.addStaticInVar( inVar );
1776 VariableSourceToken vst = vstTableIn.get( inVar ).iterator().next();
1777 fsen.putStaticInVar2src( inVar, vst );
1778 fsen.addStaticInVarSrc( new SESEandAgePair( vst.getSESE(),
1784 assert srcType.equals( VarSrcTokTable.SrcType_READY );
1785 fsen.addReadyInVar( inVar );
1791 case FKind.FlatSESEExitNode: {
1792 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
1795 case FKind.FlatOpNode: {
1796 FlatOpNode fon = (FlatOpNode) fn;
1798 if( fon.getOp().getOp() == Operation.ASSIGN ) {
1799 TempDescriptor lhs = fon.getDest();
1800 TempDescriptor rhs = fon.getLeft();
1802 // if this is an op node, don't stall, copy
1803 // source and delay until we need to use value
1805 // ask whether lhs and rhs sources are dynamic, static, etc.
1807 = vstTableIn.getRefVarSrcType( lhs,
1809 currentSESE.getParent() );
1812 = vstTableIn.getRefVarSrcType( rhs,
1814 currentSESE.getParent() );
1816 if( rhsSrcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1817 // if rhs is dynamic going in, lhs will definitely be dynamic
1818 // going out of this node, so track that here
1819 plan.addDynAssign( lhs, rhs );
1820 currentSESE.addDynamicVar( lhs );
1821 currentSESE.addDynamicVar( rhs );
1823 } else if( lhsSrcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1824 // otherwise, if the lhs is dynamic, but the rhs is not, we
1825 // need to update the variable's dynamic source as "current SESE"
1826 plan.addDynAssign( lhs );
1829 // only break if this is an ASSIGN op node,
1830 // otherwise fall through to default case
1835 // note that FlatOpNode's that aren't ASSIGN
1836 // fall through to this default case
1839 // a node with no live set has nothing to stall for
1840 if( liveSetIn == null ) {
1844 TempDescriptor[] readarray = fn.readsTemps();
1845 for( int i = 0; i < readarray.length; i++ ) {
1846 TempDescriptor readtmp = readarray[i];
1848 // ignore temps that are definitely available
1849 // when considering to stall on it
1850 if( !notAvailSetIn.contains( readtmp ) ) {
1854 // check the source type of this variable
1856 = vstTableIn.getRefVarSrcType( readtmp,
1858 currentSESE.getParent() );
1860 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1861 // 1) It is not clear statically where this variable will
1862 // come from statically, so dynamically we must keep track
1863 // along various control paths, and therefore when we stall,
1864 // just stall for the exact thing we need and move on
1865 plan.addDynamicStall( readtmp );
1866 currentSESE.addDynamicVar( readtmp );
1868 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
1869 // 2) Single token/age pair: Stall for token/age pair, and copy
1870 // all live variables with same token/age pair at the same
1871 // time. This is the same stuff that the notavaialable analysis
1872 // marks as now available.
1874 VariableSourceToken vst = vstTableIn.get( readtmp ).iterator().next();
1876 Iterator<VariableSourceToken> availItr =
1877 vstTableIn.get( vst.getSESE(), vst.getAge() ).iterator();
1879 while( availItr.hasNext() ) {
1880 VariableSourceToken vstAlsoAvail = availItr.next();
1882 // only grab additional stuff that is live
1883 Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
1885 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
1886 while( refVarItr.hasNext() ) {
1887 TempDescriptor refVar = refVarItr.next();
1888 if( liveSetIn.contains( refVar ) ) {
1889 copySet.add( refVar );
1893 if( !copySet.isEmpty() ) {
1894 plan.addStall2CopySet( vstAlsoAvail, copySet );
1899 // the other case for srcs is READY, so do nothing
1902 // assert that everything being stalled for is in the
1903 // "not available" set coming into this flat node and
1904 // that every VST identified is in the possible "stall set"
1905 // that represents VST's from children SESE's
1913 // identify sese-age pairs that are statically useful
1914 // and should have an associated SESE variable in code
1915 // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
1916 // AND ALWAYS GIVE NAMES TO PARENTS
1917 Set<VariableSourceToken> staticSet = vstTableIn.get();
1918 Iterator<VariableSourceToken> vstItr = staticSet.iterator();
1919 while( vstItr.hasNext() ) {
1920 VariableSourceToken vst = vstItr.next();
1922 // placeholder source tokens are useful results, but
1923 // the placeholder static name is never needed
1924 if( vst.getSESE().getIsCallerSESEplaceholder() ) {
1928 FlatSESEEnterNode sese = currentSESE;
1929 while( sese != null ) {
1930 sese.addNeededStaticName(
1931 new SESEandAgePair( vst.getSESE(), vst.getAge() )
1933 sese.mustTrackAtLeastAge( vst.getAge() );
1935 sese = sese.getParent();
1940 codePlans.put( fn, plan );
1943 // if any variables at this-node-*dot* have a static source (exactly one vst)
1944 // but go to a dynamic source at next-node-*dot*, create a new IR graph
1945 // node on that edge to track the sources dynamically
1946 VarSrcTokTable thisVstTable = variableResults.get( fn );
1947 for( int i = 0; i < fn.numNext(); i++ ) {
1948 FlatNode nn = fn.getNext( i );
1949 VarSrcTokTable nextVstTable = variableResults.get( nn );
1950 Set<TempDescriptor> nextLiveIn = livenessRootView.get( nn );
1952 // the table can be null if it is one of the few IR nodes
1953 // completely outside of the root SESE scope
1954 if( nextVstTable != null && nextLiveIn != null ) {
1956 Hashtable<TempDescriptor, VariableSourceToken> static2dynamicSet =
1957 thisVstTable.getStatic2DynamicSet( nextVstTable,
1960 currentSESE.getParent()
1963 if( !static2dynamicSet.isEmpty() ) {
1965 // either add these results to partial fixed-point result
1966 // or make a new one if we haven't made any here yet
1967 FlatEdge fe = new FlatEdge( fn, nn );
1968 FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get( fe );
1970 if( fwdvn == null ) {
1971 fwdvn = new FlatWriteDynamicVarNode( fn,
1976 wdvNodesToSpliceIn.put( fe, fwdvn );
1978 fwdvn.addMoreVar2Src( static2dynamicSet );
1986 public void writeReports( String timeReport ) throws java.io.IOException {
1988 BufferedWriter bw = new BufferedWriter( new FileWriter( "mlpReport_summary.txt" ) );
1989 bw.write( "MLP Analysis Results\n\n" );
1990 bw.write( timeReport+"\n\n" );
1991 printSESEHierarchy( bw );
1993 printSESEInfo( bw );
1996 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
1997 while( methItr.hasNext() ) {
1998 MethodDescriptor md = (MethodDescriptor) methItr.next();
1999 FlatMethod fm = state.getMethodFlat( md );
2000 bw = new BufferedWriter( new FileWriter( "mlpReport_"+
2001 md.getClassMethodName()+
2002 md.getSafeMethodDescriptor()+
2004 bw.write( "MLP Results for "+md+"\n-------------------\n");
2005 bw.write( "\n\nLive-In, Root View\n------------------\n" +fm.printMethod( livenessRootView ) );
2006 bw.write( "\n\nVariable Results-Out\n----------------\n" +fm.printMethod( variableResults ) );
2007 bw.write( "\n\nNot Available Results-Out\n---------------------\n"+fm.printMethod( notAvailableResults ) );
2008 bw.write( "\n\nCode Plans\n----------\n" +fm.printMethod( codePlans ) );
2009 bw.write("\n\nSESE Effects\n----------------------\n"+printSESEEffects());
2014 private String printSESEEffects() {
2016 StringWriter writer = new StringWriter();
2018 Iterator<FlatSESEEnterNode> keyIter = allSESEs.iterator();
2020 while (keyIter.hasNext()) {
2021 FlatSESEEnterNode seseEnter = keyIter.next();
2022 String result = seseEnter.getSeseEffectsSet().printSet();
2023 if (result.length() > 0) {
2024 writer.write("\nSESE " + seseEnter + "\n");
2025 writer.write(result);
2028 keyIter = rootSESEs.iterator();
2029 while (keyIter.hasNext()) {
2030 FlatSESEEnterNode seseEnter = keyIter.next();
2031 if (seseEnter.getIsCallerSESEplaceholder()) {
2032 if (!seseEnter.getChildren().isEmpty()) {
2033 String result = seseEnter.getSeseEffectsSet().printSet();
2034 if (result.length() > 0) {
2035 writer.write("\nSESE " + seseEnter + "\n");
2036 writer.write(result);
2042 return writer.toString();
2046 private void printSESEHierarchy( BufferedWriter bw ) throws java.io.IOException {
2047 bw.write( "SESE Hierarchy\n--------------\n" );
2048 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
2049 while( rootItr.hasNext() ) {
2050 FlatSESEEnterNode root = rootItr.next();
2051 if( root.getIsCallerSESEplaceholder() ) {
2052 if( !root.getChildren().isEmpty() ) {
2053 printSESEHierarchyTree( bw, root, 0 );
2056 printSESEHierarchyTree( bw, root, 0 );
2061 private void printSESEHierarchyTree( BufferedWriter bw,
2062 FlatSESEEnterNode fsen,
2064 ) throws java.io.IOException {
2065 for( int i = 0; i < depth; ++i ) {
2068 bw.write( "- "+fsen.getPrettyIdentifier()+"\n" );
2070 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
2071 while( childItr.hasNext() ) {
2072 FlatSESEEnterNode fsenChild = childItr.next();
2073 printSESEHierarchyTree( bw, fsenChild, depth + 1 );
2078 private void printSESEInfo( BufferedWriter bw ) throws java.io.IOException {
2079 bw.write("\nSESE info\n-------------\n" );
2080 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
2081 while( rootItr.hasNext() ) {
2082 FlatSESEEnterNode root = rootItr.next();
2083 if( root.getIsCallerSESEplaceholder() ) {
2084 if( !root.getChildren().isEmpty() ) {
2085 printSESEInfoTree( bw, root );
2088 printSESEInfoTree( bw, root );
2093 private void printSESEInfoTree( BufferedWriter bw,
2094 FlatSESEEnterNode fsen
2095 ) throws java.io.IOException {
2097 if( !fsen.getIsCallerSESEplaceholder() ) {
2098 bw.write( "SESE "+fsen.getPrettyIdentifier()+" {\n" );
2100 bw.write( " in-set: "+fsen.getInVarSet()+"\n" );
2101 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
2102 while( tItr.hasNext() ) {
2103 TempDescriptor inVar = tItr.next();
2104 if( fsen.getReadyInVarSet().contains( inVar ) ) {
2105 bw.write( " (ready) "+inVar+"\n" );
2107 if( fsen.getStaticInVarSet().contains( inVar ) ) {
2108 bw.write( " (static) "+inVar+"\n" );
2110 if( fsen.getDynamicInVarSet().contains( inVar ) ) {
2111 bw.write( " (dynamic)"+inVar+"\n" );
2115 bw.write( " out-set: "+fsen.getOutVarSet()+"\n" );
2119 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
2120 while( childItr.hasNext() ) {
2121 FlatSESEEnterNode fsenChild = childItr.next();
2122 printSESEInfoTree( bw, fsenChild );