3 import Analysis.CallGraph.*;
4 import Analysis.Liveness;
5 import Analysis.OwnershipAnalysis.*;
13 public class MLPAnalysis {
15 // data from the compiler
17 private TypeUtil typeUtil;
18 private CallGraph callGraph;
19 private OwnershipAnalysis ownAnalysis;
22 // an implicit SESE is automatically spliced into
23 // the IR graph around the C main before this analysis--it
24 // is nothing special except that we can make assumptions
25 // about it, such as the whole program ends when it ends
26 private FlatSESEEnterNode mainSESE;
28 // SESEs that are the root of an SESE tree belong to this
29 // set--the main SESE is always a root, statically SESEs
30 // inside methods are a root because we don't know how they
31 // will fit into the runtime tree of SESEs
32 private Set<FlatSESEEnterNode> rootSESEs;
34 // simply a set of every reachable SESE in the program, not
35 // including caller placeholder SESEs
36 private Set<FlatSESEEnterNode> allSESEs;
39 // A mapping of flat nodes to the stack of SESEs for that node, where
40 // an SESE is the child of the SESE directly below it on the stack.
41 // These stacks do not reflect the heirarchy over methods calls--whenever
42 // there is an empty stack it means all variables are available.
43 private Hashtable< FlatNode, Stack<FlatSESEEnterNode> > seseStacks;
45 private Hashtable< FlatNode, Set<TempDescriptor> > livenessRootView;
46 private Hashtable< FlatNode, Set<TempDescriptor> > livenessVirtualReads;
47 private Hashtable< FlatNode, VarSrcTokTable > variableResults;
48 private Hashtable< FlatNode, Set<TempDescriptor> > notAvailableResults;
49 private Hashtable< FlatNode, CodePlan > codePlans;
51 private Hashtable< FlatEdge, FlatWriteDynamicVarNode > wdvNodesToSpliceIn;
53 private Hashtable< MethodContext, HashSet<AllocationSite>> mapMethodContextToLiveInAllocationSiteSet;
55 private Hashtable < FlatNode, ParentChildConflictsMap > conflictsResults;
56 private ParentChildConflictsMap currentConflictsMap;
57 private Hashtable < ReferenceEdge, StallSite > stallEdgeMapping;
58 private Hashtable< FlatMethod, MethodSummary > methodSummaryResults;
60 // temporal data structures to track analysis progress.
61 private MethodSummary currentMethodSummary;
62 private HashSet<PreEffectsKey> preeffectsSet;
64 public static int maxSESEage = -1;
67 // use these methods in BuildCode to have access to analysis results
68 public FlatSESEEnterNode getMainSESE() {
72 public Set<FlatSESEEnterNode> getRootSESEs() {
76 public Set<FlatSESEEnterNode> getAllSESEs() {
80 public int getMaxSESEage() {
85 public CodePlan getCodePlan( FlatNode fn ) {
86 CodePlan cp = codePlans.get( fn );
91 public MLPAnalysis( State state,
94 OwnershipAnalysis ownAnalysis
97 double timeStartAnalysis = (double) System.nanoTime();
101 this.callGraph = callGraph;
102 this.ownAnalysis = ownAnalysis;
103 this.maxSESEage = state.MLP_MAXSESEAGE;
105 rootSESEs = new HashSet<FlatSESEEnterNode>();
106 allSESEs = new HashSet<FlatSESEEnterNode>();
108 seseStacks = new Hashtable< FlatNode, Stack<FlatSESEEnterNode> >();
109 livenessRootView = new Hashtable< FlatNode, Set<TempDescriptor> >();
110 livenessVirtualReads = new Hashtable< FlatNode, Set<TempDescriptor> >();
111 variableResults = new Hashtable< FlatNode, VarSrcTokTable >();
112 notAvailableResults = new Hashtable< FlatNode, Set<TempDescriptor> >();
113 codePlans = new Hashtable< FlatNode, CodePlan >();
114 wdvNodesToSpliceIn = new Hashtable< FlatEdge, FlatWriteDynamicVarNode >();
116 mapMethodContextToLiveInAllocationSiteSet = new Hashtable< MethodContext, HashSet<AllocationSite>>();
118 conflictsResults = new Hashtable < FlatNode, ParentChildConflictsMap >();
119 stallEdgeMapping = new Hashtable < ReferenceEdge, StallSite >();
120 methodSummaryResults=new Hashtable<FlatMethod, MethodSummary>();
122 FlatMethod fmMain = state.getMethodFlat( typeUtil.getMain() );
124 mainSESE = (FlatSESEEnterNode) fmMain.getNext(0);
125 mainSESE.setfmEnclosing( fmMain );
126 mainSESE.setmdEnclosing( fmMain.getMethod() );
127 mainSESE.setcdEnclosing( fmMain.getMethod().getClassDesc() );
131 // run analysis on each method that is actually called
132 // reachability analysis already computed this so reuse
133 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
134 while( methItr.hasNext() ) {
135 Descriptor d = methItr.next();
136 FlatMethod fm = state.getMethodFlat( d );
138 // find every SESE from methods that may be called
139 // and organize them into roots and children
140 buildForestForward( fm );
144 // 2nd pass, results are saved in FlatSESEEnterNode, so
145 // intermediate results, for safety, are discarded
146 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
147 while( rootItr.hasNext() ) {
148 FlatSESEEnterNode root = rootItr.next();
149 livenessAnalysisBackward( root,
156 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
157 while( methItr.hasNext() ) {
158 Descriptor d = methItr.next();
159 FlatMethod fm = state.getMethodFlat( d );
161 // starting from roots do a forward, fixed-point
162 // variable analysis for refinement and stalls
163 variableAnalysisForward( fm );
166 // 4th pass, compute liveness contribution from
167 // virtual reads discovered in variable pass
168 rootItr = rootSESEs.iterator();
169 while( rootItr.hasNext() ) {
170 FlatSESEEnterNode root = rootItr.next();
171 livenessAnalysisBackward( root,
178 SOMETHING IS WRONG WITH THIS, DON'T USE IT UNTIL IT CAN BE FIXED
181 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
182 while( methItr.hasNext() ) {
183 Descriptor d = methItr.next();
184 FlatMethod fm = state.getMethodFlat( d );
186 // prune variable results in one traversal
187 // by removing reference variables that are not live
188 pruneVariableResultsWithLiveness( fm );
194 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
195 while( methItr.hasNext() ) {
196 Descriptor d = methItr.next();
197 FlatMethod fm = state.getMethodFlat( d );
199 // compute what is not available at every program
200 // point, in a forward fixed-point pass
201 notAvailableForward( fm );
205 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
206 JavaCallGraph javaCallGraph = new JavaCallGraph(state,tu);
207 while( methItr.hasNext() ) {
208 Descriptor d = methItr.next();
209 FlatMethod fm = state.getMethodFlat( d );
210 methodEffects(fm,javaCallGraph);
213 // Parent/child memory conflicts analysis
214 seseConflictsForward(javaCallGraph);
217 // disjoint analysis with a set of flagged allocation sites of live-in variable
219 OwnershipAnalysis oa2 = new OwnershipAnalysis(state, tu, callGraph, new Liveness(),
220 state.OWNERSHIPALLOCDEPTH, false,
221 false, state.OWNERSHIPALIASFILE,
223 mapMethodContextToLiveInAllocationSiteSet);
225 methItr = oa2.descriptorsToAnalyze.iterator();
226 while (methItr.hasNext()) {
227 Descriptor d = methItr.next();
228 FlatMethod fm = state.getMethodFlat(d);
229 debugFunction(oa2, fm);
232 } catch (IOException e) {
233 System.err.println(e);
239 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
240 while( methItr.hasNext() ) {
241 Descriptor d = methItr.next();
242 FlatMethod fm = state.getMethodFlat( d );
244 // compute a plan for code injections
245 codePlansForward( fm );
249 // splice new IR nodes into graph after all
250 // analysis passes are complete
251 Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
252 while( spliceItr.hasNext() ) {
253 Map.Entry me = (Map.Entry) spliceItr.next();
254 FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
255 fwdvn.spliceIntoIR();
259 double timeEndAnalysis = (double) System.nanoTime();
260 double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
261 String treport = String.format( "The mlp analysis took %.3f sec.", dt );
262 System.out.println( treport );
264 if( state.MLPDEBUG ) {
266 writeReports( treport );
267 } catch( IOException e ) {}
272 private void buildForestForward( FlatMethod fm ) {
274 // start from flat method top, visit every node in
275 // method exactly once, find SESEs and remember
276 // roots and child relationships
277 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
278 flatNodesToVisit.add( fm );
280 Set<FlatNode> visited = new HashSet<FlatNode>();
282 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
283 seseStacks.put( fm, seseStackFirst );
285 while( !flatNodesToVisit.isEmpty() ) {
286 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
287 FlatNode fn = fnItr.next();
289 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
290 assert seseStack != null;
292 flatNodesToVisit.remove( fn );
295 buildForest_nodeActions( fn, seseStack, fm );
297 for( int i = 0; i < fn.numNext(); i++ ) {
298 FlatNode nn = fn.getNext( i );
300 if( !visited.contains( nn ) ) {
301 flatNodesToVisit.add( nn );
303 // clone stack and send along each analysis path
304 seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
310 private void buildForest_nodeActions( FlatNode fn,
311 Stack<FlatSESEEnterNode> seseStack,
313 switch( fn.kind() ) {
315 case FKind.FlatSESEEnterNode: {
316 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
318 if( !fsen.getIsCallerSESEplaceholder() ) {
319 allSESEs.add( fsen );
322 fsen.setfmEnclosing( fm );
323 fsen.setmdEnclosing( fm.getMethod() );
324 fsen.setcdEnclosing( fm.getMethod().getClassDesc() );
326 if( seseStack.empty() ) {
327 rootSESEs.add( fsen );
328 fsen.setParent( null );
330 seseStack.peek().addChild( fsen );
331 fsen.setParent( seseStack.peek() );
334 seseStack.push( fsen );
337 case FKind.FlatSESEExitNode: {
338 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
339 assert !seseStack.empty();
340 FlatSESEEnterNode fsen = seseStack.pop();
343 case FKind.FlatReturnNode: {
344 FlatReturnNode frn = (FlatReturnNode) fn;
345 if( !seseStack.empty() &&
346 !seseStack.peek().getIsCallerSESEplaceholder()
348 throw new Error( "Error: return statement enclosed within SESE "+
349 seseStack.peek().getPrettyIdentifier() );
357 private void livenessAnalysisBackward( FlatSESEEnterNode fsen,
359 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout ) {
361 // start from an SESE exit, visit nodes in reverse up to
362 // SESE enter in a fixed-point scheme, where children SESEs
363 // should already be analyzed and therefore can be skipped
364 // because child SESE enter node has all necessary info
365 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
368 flatNodesToVisit.add( fsen.getfmEnclosing().getFlatExit() );
370 flatNodesToVisit.add( fsen.getFlatExit() );
373 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults =
374 new Hashtable< FlatNode, Set<TempDescriptor> >();
377 liveout = new Hashtable< FlatSESEExitNode, Set<TempDescriptor> >();
380 while( !flatNodesToVisit.isEmpty() ) {
381 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
382 flatNodesToVisit.remove( fn );
384 Set<TempDescriptor> prev = livenessResults.get( fn );
386 // merge sets from control flow joins
387 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
388 for( int i = 0; i < fn.numNext(); i++ ) {
389 FlatNode nn = fn.getNext( i );
390 Set<TempDescriptor> s = livenessResults.get( nn );
396 Set<TempDescriptor> curr = liveness_nodeActions( fn, u, fsen, toplevel, liveout);
398 // if a new result, schedule backward nodes for analysis
399 if( !curr.equals( prev ) ) {
400 livenessResults.put( fn, curr );
402 // don't flow backwards past current SESE enter
403 if( !fn.equals( fsen ) ) {
404 for( int i = 0; i < fn.numPrev(); i++ ) {
405 FlatNode nn = fn.getPrev( i );
406 flatNodesToVisit.add( nn );
412 Set<TempDescriptor> s = livenessResults.get( fsen );
414 fsen.addInVarSet( s );
417 // remember liveness per node from the root view as the
418 // global liveness of variables for later passes to use
420 livenessRootView.putAll( livenessResults );
423 // post-order traversal, so do children first
424 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
425 while( childItr.hasNext() ) {
426 FlatSESEEnterNode fsenChild = childItr.next();
427 livenessAnalysisBackward( fsenChild, false, liveout );
431 private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
432 Set<TempDescriptor> liveIn,
433 FlatSESEEnterNode currentSESE,
435 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout
437 switch( fn.kind() ) {
439 case FKind.FlatSESEExitNode:
441 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
442 if( !liveout.containsKey( fsexn ) ) {
443 liveout.put( fsexn, new HashSet<TempDescriptor>() );
445 liveout.get( fsexn ).addAll( liveIn );
447 // no break, sese exits should also execute default actions
450 // handle effects of statement in reverse, writes then reads
451 TempDescriptor [] writeTemps = fn.writesTemps();
452 for( int i = 0; i < writeTemps.length; ++i ) {
453 liveIn.remove( writeTemps[i] );
456 FlatSESEExitNode fsexn = currentSESE.getFlatExit();
457 Set<TempDescriptor> livetemps = liveout.get( fsexn );
458 if( livetemps != null &&
459 livetemps.contains( writeTemps[i] ) ) {
460 // write to a live out temp...
461 // need to put in SESE liveout set
462 currentSESE.addOutVar( writeTemps[i] );
467 TempDescriptor [] readTemps = fn.readsTemps();
468 for( int i = 0; i < readTemps.length; ++i ) {
469 liveIn.add( readTemps[i] );
472 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get( fn );
473 if( virtualReadTemps != null ) {
474 liveIn.addAll( virtualReadTemps );
485 private void variableAnalysisForward( FlatMethod fm ) {
487 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
488 flatNodesToVisit.add( fm );
490 while( !flatNodesToVisit.isEmpty() ) {
491 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
492 flatNodesToVisit.remove( fn );
494 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
495 assert seseStack != null;
497 VarSrcTokTable prev = variableResults.get( fn );
499 // merge sets from control flow joins
500 VarSrcTokTable curr = new VarSrcTokTable();
501 for( int i = 0; i < fn.numPrev(); i++ ) {
502 FlatNode nn = fn.getPrev( i );
503 VarSrcTokTable incoming = variableResults.get( nn );
504 curr.merge( incoming );
507 if( !seseStack.empty() ) {
508 variable_nodeActions( fn, curr, seseStack.peek() );
511 // if a new result, schedule forward nodes for analysis
512 if( !curr.equals( prev ) ) {
513 variableResults.put( fn, curr );
515 for( int i = 0; i < fn.numNext(); i++ ) {
516 FlatNode nn = fn.getNext( i );
517 flatNodesToVisit.add( nn );
523 private void variable_nodeActions( FlatNode fn,
524 VarSrcTokTable vstTable,
525 FlatSESEEnterNode currentSESE ) {
526 switch( fn.kind() ) {
528 case FKind.FlatSESEEnterNode: {
529 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
530 assert fsen.equals( currentSESE );
532 vstTable.age( currentSESE );
533 vstTable.assertConsistency();
536 case FKind.FlatSESEExitNode: {
537 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
538 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
539 assert currentSESE.getChildren().contains( fsen );
541 vstTable.remapChildTokens( fsen );
543 // liveness virtual reads are things that might be
544 // written by an SESE and should be added to the in-set
545 // anything virtually read by this SESE should be pruned
546 // of parent or sibling sources
547 Set<TempDescriptor> liveVars = livenessRootView.get( fn );
548 Set<TempDescriptor> fsenVirtReads = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens( fsen, liveVars );
549 Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get( fn );
550 if( fsenVirtReadsOld != null ) {
551 fsenVirtReads.addAll( fsenVirtReadsOld );
553 livenessVirtualReads.put( fn, fsenVirtReads );
556 // then all child out-set tokens are guaranteed
557 // to be filled in, so clobber those entries with
558 // the latest, clean sources
559 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
560 while( outVarItr.hasNext() ) {
561 TempDescriptor outVar = outVarItr.next();
562 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
564 VariableSourceToken vst =
565 new VariableSourceToken( ts,
570 vstTable.remove( outVar );
573 vstTable.assertConsistency();
577 case FKind.FlatOpNode: {
578 FlatOpNode fon = (FlatOpNode) fn;
580 if( fon.getOp().getOp() == Operation.ASSIGN ) {
581 TempDescriptor lhs = fon.getDest();
582 TempDescriptor rhs = fon.getLeft();
584 vstTable.remove( lhs );
586 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
588 Iterator<VariableSourceToken> itr = vstTable.get( rhs ).iterator();
589 while( itr.hasNext() ) {
590 VariableSourceToken vst = itr.next();
592 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
595 if( currentSESE.getChildren().contains( vst.getSESE() ) ) {
596 // if the source comes from a child, copy it over
597 forAddition.add( new VariableSourceToken( ts,
604 // otherwise, stamp it as us as the source
605 forAddition.add( new VariableSourceToken( ts,
614 vstTable.addAll( forAddition );
616 // only break if this is an ASSIGN op node,
617 // otherwise fall through to default case
618 vstTable.assertConsistency();
623 // note that FlatOpNode's that aren't ASSIGN
624 // fall through to this default case
626 TempDescriptor [] writeTemps = fn.writesTemps();
627 if( writeTemps.length > 0 ) {
630 // for now, when writeTemps > 1, make sure
631 // its a call node, programmer enforce only
632 // doing stuff like calling a print routine
633 //assert writeTemps.length == 1;
634 if( writeTemps.length > 1 ) {
635 assert fn.kind() == FKind.FlatCall ||
636 fn.kind() == FKind.FlatMethod;
640 vstTable.remove( writeTemps[0] );
642 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
643 ts.add( writeTemps[0] );
645 vstTable.add( new VariableSourceToken( ts,
653 vstTable.assertConsistency();
660 private void pruneVariableResultsWithLiveness( FlatMethod fm ) {
662 // start from flat method top, visit every node in
663 // method exactly once
664 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
665 flatNodesToVisit.add( fm );
667 Set<FlatNode> visited = new HashSet<FlatNode>();
669 while( !flatNodesToVisit.isEmpty() ) {
670 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
671 FlatNode fn = fnItr.next();
673 flatNodesToVisit.remove( fn );
676 Set<TempDescriptor> rootLiveSet = livenessRootView.get( fn );
677 VarSrcTokTable vstTable = variableResults.get( fn );
679 vstTable.pruneByLiveness( rootLiveSet );
681 for( int i = 0; i < fn.numNext(); i++ ) {
682 FlatNode nn = fn.getNext( i );
684 if( !visited.contains( nn ) ) {
685 flatNodesToVisit.add( nn );
692 private void notAvailableForward( FlatMethod fm ) {
694 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
695 flatNodesToVisit.add( fm );
697 while( !flatNodesToVisit.isEmpty() ) {
698 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
699 flatNodesToVisit.remove( fn );
701 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
702 assert seseStack != null;
704 Set<TempDescriptor> prev = notAvailableResults.get( fn );
706 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
707 for( int i = 0; i < fn.numPrev(); i++ ) {
708 FlatNode nn = fn.getPrev( i );
709 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
710 if( notAvailIn != null ) {
711 curr.addAll( notAvailIn );
715 if( !seseStack.empty() ) {
716 notAvailable_nodeActions( fn, curr, seseStack.peek() );
719 // if a new result, schedule forward nodes for analysis
720 if( !curr.equals( prev ) ) {
721 notAvailableResults.put( fn, curr );
723 for( int i = 0; i < fn.numNext(); i++ ) {
724 FlatNode nn = fn.getNext( i );
725 flatNodesToVisit.add( nn );
731 private void notAvailable_nodeActions( FlatNode fn,
732 Set<TempDescriptor> notAvailSet,
733 FlatSESEEnterNode currentSESE ) {
735 // any temps that are removed from the not available set
736 // at this node should be marked in this node's code plan
737 // as temps to be grabbed at runtime!
739 switch( fn.kind() ) {
741 case FKind.FlatSESEEnterNode: {
742 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
743 assert fsen.equals( currentSESE );
747 case FKind.FlatSESEExitNode: {
748 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
749 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
750 assert currentSESE.getChildren().contains( fsen );
751 notAvailSet.addAll( fsen.getOutVarSet() );
754 case FKind.FlatMethod: {
758 case FKind.FlatOpNode: {
759 FlatOpNode fon = (FlatOpNode) fn;
761 if( fon.getOp().getOp() == Operation.ASSIGN ) {
762 TempDescriptor lhs = fon.getDest();
763 TempDescriptor rhs = fon.getLeft();
765 // copy makes lhs same availability as rhs
766 if( notAvailSet.contains( rhs ) ) {
767 notAvailSet.add( lhs );
769 notAvailSet.remove( lhs );
772 // only break if this is an ASSIGN op node,
773 // otherwise fall through to default case
778 // note that FlatOpNode's that aren't ASSIGN
779 // fall through to this default case
781 TempDescriptor [] writeTemps = fn.writesTemps();
782 for( int i = 0; i < writeTemps.length; i++ ) {
783 TempDescriptor wTemp = writeTemps[i];
784 notAvailSet.remove( wTemp );
786 TempDescriptor [] readTemps = fn.readsTemps();
787 for( int i = 0; i < readTemps.length; i++ ) {
788 TempDescriptor rTemp = readTemps[i];
789 notAvailSet.remove( rTemp );
791 // if this variable has exactly one source, potentially
792 // get other things from this source as well
793 VarSrcTokTable vstTable = variableResults.get( fn );
796 vstTable.getRefVarSrcType( rTemp,
798 currentSESE.getParent() );
800 if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
802 VariableSourceToken vst = vstTable.get( rTemp ).iterator().next();
804 Iterator<VariableSourceToken> availItr = vstTable.get( vst.getSESE(),
808 // look through things that are also available from same source
809 while( availItr.hasNext() ) {
810 VariableSourceToken vstAlsoAvail = availItr.next();
812 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
813 while( refVarItr.hasNext() ) {
814 TempDescriptor refVarAlso = refVarItr.next();
816 // if a variable is available from the same source, AND it ALSO
817 // only comes from one statically known source, mark it available
818 Integer srcTypeAlso =
819 vstTable.getRefVarSrcType( refVarAlso,
821 currentSESE.getParent() );
822 if( srcTypeAlso.equals( VarSrcTokTable.SrcType_STATIC ) ) {
823 notAvailSet.remove( refVarAlso );
834 private void debugFunction(OwnershipAnalysis oa2, FlatMethod fm) {
836 String methodName="SomeWork";
838 MethodDescriptor md=fm.getMethod();
839 HashSet<MethodContext> mcSet=oa2.getAllMethodContextSetByDescriptor(md);
840 Iterator<MethodContext> mcIter=mcSet.iterator();
842 while(mcIter.hasNext()){
843 MethodContext mc=mcIter.next();
845 OwnershipGraph og=oa2.getOwnvershipGraphByMethodContext(mc);
847 if(fm.toString().indexOf(methodName)>0){
849 og.writeGraph(fm.toString() + "SECONDGRAPH",
850 true, // write labels (variables)
851 true, // selectively hide intermediate temp vars
852 true, // prune unreachable heap regions
853 false, // show back edges to confirm graph validity
854 false, // show parameter indices (unmaintained!)
855 true, // hide subset reachability states
856 false);// hide edge taints
857 } catch (IOException e) {
858 System.out.println("Error writing debug capture.");
869 private void methodEffects(FlatMethod fm, CallGraph callGraph) {
871 MethodDescriptor md=fm.getMethod();
872 HashSet<MethodContext> mcSet=ownAnalysis.getAllMethodContextSetByDescriptor(md);
873 Iterator<MethodContext> mcIter=mcSet.iterator();
875 while(mcIter.hasNext()){
876 MethodContext mc=mcIter.next();
878 Set<FlatNode> visited = new HashSet<FlatNode>();
880 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
881 flatNodesToVisit.add(fm);
883 while (!flatNodesToVisit.isEmpty()) {
884 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
885 flatNodesToVisit.remove(fn);
887 Stack<FlatSESEEnterNode> seseStack = seseStacks.get(fn);
888 assert seseStack != null;
890 if (!seseStack.empty()) {
891 effects_nodeActions(mc, fn, seseStack.peek(), callGraph);
894 flatNodesToVisit.remove(fn);
897 for (int i = 0; i < fn.numNext(); i++) {
898 FlatNode nn = fn.getNext(i);
899 if (!visited.contains(nn)) {
900 flatNodesToVisit.add(nn);
911 private void analyzeRelatedAllocationSite(MethodDescriptor callerMD,
912 MethodContext calleeMC, HashSet<Integer> paramIndexSet,
913 HashSet<HeapRegionNode> visitedHRN) {
915 HashSet<MethodContext> mcSet = ownAnalysis
916 .getAllMethodContextSetByDescriptor(callerMD);
920 Iterator<MethodContext> mcIter = mcSet.iterator();
922 FlatMethod callerFM = state.getMethodFlat(callerMD);
924 while (mcIter.hasNext()) {
925 MethodContext mc = mcIter.next();
927 Set<FlatNode> visited = new HashSet<FlatNode>();
928 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
929 flatNodesToVisit.add(callerFM);
931 while (!flatNodesToVisit.isEmpty()) {
932 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
933 flatNodesToVisit.remove(fn);
935 analyzeRelatedAllocationSite_NodeAction(fn, mc, calleeMC,
936 paramIndexSet,visitedHRN);
938 flatNodesToVisit.remove(fn);
941 for (int i = 0; i < fn.numNext(); i++) {
942 FlatNode nn = fn.getNext(i);
943 if (!visited.contains(nn)) {
944 flatNodesToVisit.add(nn);
953 private void analyzeRelatedAllocationSite_NodeAction(FlatNode fn, MethodContext callerMC,
954 MethodContext calleeMC,
955 HashSet<Integer> paramIndexSet, HashSet<HeapRegionNode> visitedHRN) {
957 OwnershipGraph og = ownAnalysis
958 .getOwnvershipGraphByMethodContext(callerMC);
962 case FKind.FlatCall: {
964 FlatCall fc = (FlatCall) fn;
967 MethodContext calleeMCfromOG = ownAnalysis.getCalleeMethodContext(
970 // disable below condition. currently collect all possible
971 // allocation sites without regarding method context
973 // if (calleeMC.equals(calleeMCfromOG)) { // in this case, this
974 // method context calls corresponding callee.
977 if (((MethodDescriptor) calleeMC.getDescriptor()).isStatic()) {
983 for (Iterator iterator = paramIndexSet.iterator(); iterator
985 Integer integer = (Integer) iterator.next();
987 int paramIdx = integer - base;
989 // if paramIdx is less than 0, assumes that it is
990 // related with wrong method contexts.
991 TempDescriptor arg = fc.getArg(paramIdx);
992 LabelNode argLN = og.td2ln.get(arg);
994 Iterator<ReferenceEdge> iterEdge = argLN
995 .iteratorToReferencees();
996 while (iterEdge.hasNext()) {
997 ReferenceEdge referenceEdge = (ReferenceEdge) iterEdge
1000 HeapRegionNode dstHRN = referenceEdge.getDst();
1001 if (dstHRN.isParameter()) {
1002 if (!visitedHRN.contains(dstHRN)) {
1003 setupRelatedAllocSiteAnalysis(og, callerMC,
1004 dstHRN, visitedHRN);
1007 addLiveInAllocationSite(callerMC, dstHRN
1008 .getAllocationSite());
1025 private void setupRelatedAllocSiteAnalysis(OwnershipGraph og,
1026 MethodContext mc, HeapRegionNode dstHRN,
1027 HashSet<HeapRegionNode> visitedHRN) {
1029 HashSet<Integer> paramIndexSet = new HashSet<Integer>();
1031 // collect corresponding param index
1032 Set<Integer> pIndexSet = og.idPrimary2paramIndexSet.get(dstHRN.getID());
1033 if (pIndexSet != null) {
1034 for (Iterator iterator = pIndexSet.iterator(); iterator.hasNext();) {
1035 Integer integer = (Integer) iterator.next();
1036 paramIndexSet.add(integer);
1040 Set<Integer> sIndexSet = og.idSecondary2paramIndexSet.get(dstHRN
1042 if (sIndexSet != null) {
1043 for (Iterator iterator = sIndexSet.iterator(); iterator.hasNext();) {
1044 Integer integer = (Integer) iterator.next();
1045 paramIndexSet.add(integer);
1049 if (mc.getDescriptor() instanceof MethodDescriptor) {
1050 Set callerSet = callGraph.getCallerSet((MethodDescriptor) mc
1052 for (Iterator iterator = callerSet.iterator(); iterator.hasNext();) {
1053 Object obj = (Object) iterator.next();
1054 if (obj instanceof MethodDescriptor) {
1055 MethodDescriptor callerMD = (MethodDescriptor) obj;
1057 if(callerMD.equals(mc.getDescriptor())){
1060 analyzeRelatedAllocationSite(callerMD, mc, paramIndexSet,visitedHRN);
1067 private void effects_nodeActions(MethodContext mc, FlatNode fn,
1068 FlatSESEEnterNode currentSESE, CallGraph callGraph) {
1070 OwnershipGraph og = ownAnalysis.getOwnvershipGraphByMethodContext(mc);
1072 switch (fn.kind()) {
1074 case FKind.FlatSESEEnterNode: {
1076 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
1077 assert fsen.equals(currentSESE);
1079 // uniquely taint each live-in variable
1080 Set<TempDescriptor> set = fsen.getInVarSet();
1081 Iterator<TempDescriptor> iter = set.iterator();
1083 while (iter.hasNext()) {
1084 TempDescriptor td = iter.next();
1085 LabelNode ln = og.td2ln.get(td);
1087 int taint = (int) Math.pow(2, idx);
1088 taintLabelNode(ln, taint);
1090 // collects related allocation sites
1091 Iterator<ReferenceEdge> referenceeIter = ln
1092 .iteratorToReferencees();
1093 while (referenceeIter.hasNext()) {
1094 ReferenceEdge referenceEdge = (ReferenceEdge) referenceeIter
1096 HeapRegionNode dstHRN = referenceEdge.getDst();
1097 if (dstHRN.isParameter()) {
1099 HashSet<HeapRegionNode> visitedHRN=new HashSet<HeapRegionNode>();
1100 visitedHRN.add(dstHRN);
1101 setupRelatedAllocSiteAnalysis(og,mc,dstHRN,visitedHRN);
1104 addLiveInAllocationSite(mc, dstHRN
1105 .getAllocationSite());
1117 case FKind.FlatSESEExitNode: {
1118 FlatSESEExitNode fsexit = (FlatSESEExitNode) fn;
1120 FlatSESEEnterNode enterNode = fsexit.getFlatEnter();
1121 FlatSESEEnterNode parent = enterNode.getParent();
1122 if (parent != null) {
1124 SESEEffectsSet set = enterNode.getSeseEffectsSet();
1125 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> readTable = set
1127 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentReadTable = parent
1128 .getSeseEffectsSet().getReadTable();
1129 Set<TempDescriptor> keys = readTable.keySet();
1130 Iterator<TempDescriptor> keyIter = keys.iterator();
1131 while (keyIter.hasNext()) {
1132 TempDescriptor td = (TempDescriptor) keyIter.next();
1133 HashSet<SESEEffectsKey> effectsSet = readTable.get(td);
1134 HashSet<SESEEffectsKey> parentEffectsSet = parentReadTable
1136 if (parentEffectsSet == null) {
1137 parentEffectsSet = new HashSet<SESEEffectsKey>();
1140 for (Iterator iterator = effectsSet.iterator(); iterator
1142 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
1144 parentEffectsSet.add(new SESEEffectsKey(seseKey
1145 .getFieldDescriptor(), seseKey
1146 .getTypeDescriptor(), seseKey.getHRNId()));
1149 parentReadTable.put(td, parentEffectsSet);
1152 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> writeTable = set
1154 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentWriteTable = parent
1155 .getSeseEffectsSet().getWriteTable();
1156 keys = writeTable.keySet();
1157 keyIter = keys.iterator();
1158 while (keyIter.hasNext()) {
1159 TempDescriptor td = (TempDescriptor) keyIter.next();
1160 HashSet<SESEEffectsKey> effectsSet = writeTable.get(td);
1161 HashSet<SESEEffectsKey> parentEffectsSet = parentWriteTable
1163 if (parentEffectsSet == null) {
1164 parentEffectsSet = new HashSet<SESEEffectsKey>();
1167 for (Iterator iterator = effectsSet.iterator(); iterator
1169 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
1171 parentEffectsSet.add(new SESEEffectsKey(seseKey
1172 .getFieldDescriptor(), seseKey
1173 .getTypeDescriptor(), seseKey.getHRNId()));
1176 parentWriteTable.put(td, parentEffectsSet);
1179 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> strongUpdateTable = set
1180 .getStrongUpdateTable();
1181 Hashtable<TempDescriptor, HashSet<SESEEffectsKey>> parentstrongUpdateTable = parent
1182 .getSeseEffectsSet().getStrongUpdateTable();
1183 keys = strongUpdateTable.keySet();
1184 keyIter = keys.iterator();
1185 while (keyIter.hasNext()) {
1186 TempDescriptor td = (TempDescriptor) keyIter.next();
1187 HashSet<SESEEffectsKey> effectsSet = strongUpdateTable
1189 HashSet<SESEEffectsKey> parentEffectsSet = parentstrongUpdateTable
1191 if (parentEffectsSet == null) {
1192 parentEffectsSet = new HashSet<SESEEffectsKey>();
1195 for (Iterator iterator = effectsSet.iterator(); iterator
1197 SESEEffectsKey seseKey = (SESEEffectsKey) iterator
1199 parentEffectsSet.add(new SESEEffectsKey(seseKey
1200 .getFieldDescriptor(), seseKey
1201 .getTypeDescriptor(), seseKey.getHRNId()));
1204 parentstrongUpdateTable.put(td, parentEffectsSet);
1212 case FKind.FlatFieldNode: {
1214 FlatFieldNode ffn = (FlatFieldNode) fn;
1215 TempDescriptor src = ffn.getSrc();
1216 FieldDescriptor field = ffn.getField();
1218 LabelNode srcLN = og.td2ln.get(src);
1219 if (srcLN != null) {
1220 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(srcLN);
1221 Iterator<TempDescriptor> affectedIter = affectedTDSet
1223 while (affectedIter.hasNext()) {
1224 TempDescriptor affectedTD = affectedIter.next();
1226 if (currentSESE.getInVarSet().contains(affectedTD)) {
1228 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1230 Iterator<HeapRegionNode> hrnIter = hrnSet.iterator();
1231 while (hrnIter.hasNext()) {
1232 HeapRegionNode hrn = hrnIter.next();
1234 Iterator<ReferenceEdge> referencers = hrn
1235 .iteratorToReferencers();
1236 while (referencers.hasNext()) {
1237 ReferenceEdge referenceEdge = (ReferenceEdge) referencers
1239 if (field.getSymbol().equals(
1240 referenceEdge.getField())) {
1241 currentSESE.readEffects(affectedTD, field
1242 .getSymbol(), src.getType(),
1243 referenceEdge.getDst().getID());
1251 // handle tainted case
1253 Iterator<ReferenceEdge> edgeIter = srcLN
1254 .iteratorToReferencees();
1255 while (edgeIter.hasNext()) {
1256 ReferenceEdge edge = edgeIter.next();
1257 HeapRegionNode accessHRN = edge.getDst();
1258 // / follow the chain of reference to identify possible
1260 Iterator<ReferenceEdge> referIter = accessHRN
1261 .iteratorToReferencers();
1262 while (referIter.hasNext()) {
1263 ReferenceEdge referEdge = (ReferenceEdge) referIter
1266 // if (referEdge.getTaintIdentifier() >0 ||
1267 // referEdge.getSESETaintIdentifier()>0 ) {
1268 HashSet<TempDescriptor> referSet = new HashSet<TempDescriptor>();
1269 followReference(accessHRN, referSet,
1270 new HashSet<HeapRegionNode>(), currentSESE);
1272 Iterator<TempDescriptor> referSetIter = referSet
1274 while (referSetIter.hasNext()) {
1275 TempDescriptor tempDescriptor = (TempDescriptor) referSetIter
1277 currentSESE.readEffects(tempDescriptor, field
1278 .getSymbol(), src.getType(), accessHRN
1284 if (edge.getTaintIdentifier() > 0
1285 || edge.getSESETaintIdentifier() > 0) {
1287 affectedTDSet = getReferenceNodeSet(accessHRN);
1288 affectedIter = affectedTDSet.iterator();
1289 while (affectedIter.hasNext()) {
1290 TempDescriptor affectedTD = affectedIter.next();
1292 if (currentSESE.getInVarSet().contains(affectedTD)) {
1294 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1296 Iterator<HeapRegionNode> hrnIter = hrnSet
1298 while (hrnIter.hasNext()) {
1299 HeapRegionNode hrn = hrnIter.next();
1300 currentSESE.readEffects(affectedTD, field
1301 .getSymbol(), src.getType(), hrn
1315 case FKind.FlatSetFieldNode: {
1317 FlatSetFieldNode fsen = (FlatSetFieldNode) fn;
1318 TempDescriptor dst = fsen.getDst();
1319 FieldDescriptor field = fsen.getField();
1321 LabelNode dstLN = og.td2ln.get(dst);
1322 if (dstLN != null) {
1323 // check possible strong updates
1324 boolean strongUpdate = false;
1326 if (!field.getType().isImmutable() || field.getType().isArray()) {
1327 Iterator<ReferenceEdge> itrXhrn = dstLN
1328 .iteratorToReferencees();
1329 while (itrXhrn.hasNext()) {
1330 ReferenceEdge edgeX = itrXhrn.next();
1331 HeapRegionNode hrnX = edgeX.getDst();
1333 // we can do a strong update here if one of two cases
1336 && field != OwnershipAnalysis
1337 .getArrayField(field.getType())
1338 && ((hrnX.getNumReferencers() == 1) || // case 1
1339 (hrnX.isSingleObject() && dstLN
1340 .getNumReferencees() == 1) // case 2
1342 strongUpdate = true;
1347 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(dstLN);
1349 Iterator<TempDescriptor> affectedIter = affectedTDSet
1352 while (affectedIter.hasNext()) {
1353 TempDescriptor affectedTD = affectedIter.next();
1354 if (currentSESE.getInVarSet().contains(affectedTD)) {
1356 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1358 Iterator<HeapRegionNode> hrnIter = hrnSet.iterator();
1359 while (hrnIter.hasNext()) {
1360 HeapRegionNode hrn = hrnIter.next();
1362 Iterator<ReferenceEdge> referencers = hrn
1363 .iteratorToReferencers();
1364 while (referencers.hasNext()) {
1365 ReferenceEdge referenceEdge = (ReferenceEdge) referencers
1367 if (field.getSymbol().equals(
1368 referenceEdge.getField())) {
1369 currentSESE.writeEffects(affectedTD, field
1370 .getSymbol(), dst.getType(),
1371 referenceEdge.getDst().getID(),
1380 // handle tainted case
1381 Iterator<ReferenceEdge> edgeIter = dstLN
1382 .iteratorToReferencees();
1383 while (edgeIter.hasNext()) {
1384 ReferenceEdge edge = edgeIter.next();
1386 HeapRegionNode accessHRN = edge.getDst();
1387 // / follow the chain of reference to identify possible
1389 Iterator<ReferenceEdge> referIter = accessHRN
1390 .iteratorToReferencers();
1391 while (referIter.hasNext()) {
1392 ReferenceEdge referEdge = (ReferenceEdge) referIter
1395 // if (referEdge.getTaintIdentifier() > 0 ||
1396 // referEdge.getSESETaintIdentifier() > 0 ) {
1397 HashSet<TempDescriptor> referSet = new HashSet<TempDescriptor>();
1398 followReference(accessHRN, referSet,
1399 new HashSet<HeapRegionNode>(), currentSESE);
1400 Iterator<TempDescriptor> referSetIter = referSet
1402 while (referSetIter.hasNext()) {
1403 TempDescriptor tempDescriptor = (TempDescriptor) referSetIter
1405 currentSESE.writeEffects(tempDescriptor, field
1406 .getSymbol(), dst.getType(), accessHRN
1407 .getID(), strongUpdate);
1412 if (edge.getTaintIdentifier() > 0
1413 || edge.getSESETaintIdentifier() > 0) {
1414 affectedTDSet = getReferenceNodeSet(accessHRN);
1415 affectedIter = affectedTDSet.iterator();
1416 while (affectedIter.hasNext()) {
1417 TempDescriptor affectedTD = affectedIter.next();
1418 if (currentSESE.getInVarSet().contains(affectedTD)) {
1420 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(
1422 Iterator<HeapRegionNode> hrnIter = hrnSet
1424 while (hrnIter.hasNext()) {
1425 HeapRegionNode hrn = hrnIter.next();
1426 currentSESE.writeEffects(affectedTD, field
1427 .getSymbol(), dst.getType(), hrn
1428 .getID(), strongUpdate);
1443 case FKind.FlatCall: {
1444 FlatCall fc = (FlatCall) fn;
1446 MethodContext calleeMC = ownAnalysis.getCalleeMethodContext(mc, fc);
1448 MethodEffects me = ownAnalysis.getMethodEffectsAnalysis()
1449 .getMethodEffectsByMethodContext(calleeMC);
1451 OwnershipGraph calleeOG = ownAnalysis
1452 .getOwnvershipGraphByMethodContext(calleeMC);
1454 FlatMethod fm = state.getMethodFlat(fc.getMethod());
1455 ParameterDecomposition decomp = new ParameterDecomposition(
1456 ownAnalysis, fc, fm, calleeMC, calleeOG, og);
1459 if (((MethodDescriptor) calleeMC.getDescriptor()).isStatic()) {
1465 for (int i = 0; i < fc.numArgs(); i++) {
1467 TempDescriptor arg = fc.getArg(i);
1468 Set<EffectsKey> readSet = me.getEffects().getReadingSet(
1470 Set<EffectsKey> writeSet = me.getEffects().getWritingSet(
1473 Set<EffectsKey> strongUpdateSet = me.getEffects()
1474 .getStrongUpdateSet(i + base);
1476 LabelNode argLN = og.td2ln.get(arg);
1477 if (argLN != null) {
1478 HashSet<TempDescriptor> affectedTDSet = getAccessedTaintNodeSet(argLN);
1479 Iterator<TempDescriptor> affectedIter = affectedTDSet
1482 while (affectedIter.hasNext()) {
1484 TempDescriptor affectedTD = affectedIter.next();
1485 if (currentSESE.getInVarSet().contains(affectedTD)) {
1487 if (readSet != null) {
1488 Iterator<EffectsKey> readIter = readSet
1490 while (readIter.hasNext()) {
1491 EffectsKey key = readIter.next();
1492 Set<Integer> hrnSet = getCallerHRNId(
1493 new Integer(i + base), calleeOG,
1494 key.getHRNId(), decomp);
1495 Iterator<Integer> hrnIter = hrnSet
1497 while (hrnIter.hasNext()) {
1498 Integer hrnID = (Integer) hrnIter
1500 currentSESE.readEffects(affectedTD, key
1501 .getFieldDescriptor(), key
1502 .getTypeDescriptor(), hrnID);
1507 if (writeSet != null) {
1508 Iterator<EffectsKey> writeIter = writeSet
1510 while (writeIter.hasNext()) {
1511 EffectsKey key = writeIter.next();
1513 Set<Integer> hrnSet = getCallerHRNId(
1514 new Integer(i + base), calleeOG,
1515 key.getHRNId(), decomp);
1516 Iterator<Integer> hrnIter = hrnSet
1518 while (hrnIter.hasNext()) {
1519 Integer hrnID = (Integer) hrnIter
1521 currentSESE.writeEffects(affectedTD,
1522 key.getFieldDescriptor(), key
1523 .getTypeDescriptor(),
1530 if (strongUpdateSet != null) {
1531 Iterator<EffectsKey> strongUpdateIter = strongUpdateSet
1533 while (strongUpdateIter.hasNext()) {
1534 EffectsKey key = strongUpdateIter.next();
1536 Set<Integer> hrnSet = getCallerHRNId(
1537 new Integer(i + base), calleeOG,
1538 key.getHRNId(), decomp);
1539 Iterator<Integer> hrnIter = hrnSet
1541 while (hrnIter.hasNext()) {
1542 Integer hrnID = (Integer) hrnIter
1544 currentSESE.writeEffects(affectedTD,
1545 key.getFieldDescriptor(), key
1546 .getTypeDescriptor(),
1567 private void addLiveInAllocationSite(MethodContext mc, AllocationSite ac){
1568 HashSet<AllocationSite> set=mapMethodContextToLiveInAllocationSiteSet.get(mc);
1570 set=new HashSet<AllocationSite>();
1573 mapMethodContextToLiveInAllocationSiteSet.put(mc, set);
1576 private void followReference(HeapRegionNode hrn,HashSet<TempDescriptor> tdSet, HashSet<HeapRegionNode> visited, FlatSESEEnterNode currentSESE){
1578 Iterator<ReferenceEdge> referIter=hrn.iteratorToReferencers();
1579 // check whether hrn is referenced by TD
1580 while (referIter.hasNext()) {
1581 ReferenceEdge referEdge = (ReferenceEdge) referIter.next();
1582 if(referEdge.getSrc() instanceof LabelNode){
1583 LabelNode ln=(LabelNode)referEdge.getSrc();
1584 if(currentSESE.getInVarSet().contains(ln.getTempDescriptor())){
1585 tdSet.add(ln.getTempDescriptor());
1587 }else if(referEdge.getSrc() instanceof HeapRegionNode){
1588 HeapRegionNode nextHRN=(HeapRegionNode)referEdge.getSrc();
1589 if(!visited.contains(nextHRN)){
1590 visited.add(nextHRN);
1591 followReference(nextHRN,tdSet,visited,currentSESE);
1599 private Set<Integer> getCallerHRNId(Integer paramIdx,
1600 OwnershipGraph calleeOG, Integer calleeHRNId,
1601 ParameterDecomposition paramDecom) {
1603 Integer hrnPrimaryID = calleeOG.paramIndex2idPrimary.get(paramIdx);
1604 Integer hrnSecondaryID = calleeOG.paramIndex2idSecondary.get(paramIdx);
1606 if (calleeHRNId.equals(hrnPrimaryID)) {
1607 // it references to primary param heap region
1608 return paramDecom.getParamObject_hrnIDs(paramIdx);
1609 } else if (calleeHRNId.equals(hrnSecondaryID)) {
1610 // it references to secondary param heap region
1611 return paramDecom.getParamReachable_hrnIDs(paramIdx);
1614 return new HashSet<Integer>();
1617 private void taintLabelNode(LabelNode ln, int identifier) {
1619 Iterator<ReferenceEdge> edgeIter = ln.iteratorToReferencees();
1620 while (edgeIter.hasNext()) {
1621 ReferenceEdge edge = edgeIter.next();
1622 HeapRegionNode hrn = edge.getDst();
1624 Iterator<ReferenceEdge> edgeReferencerIter = hrn
1625 .iteratorToReferencers();
1626 while (edgeReferencerIter.hasNext()) {
1627 ReferenceEdge referencerEdge = edgeReferencerIter.next();
1628 OwnershipNode node = referencerEdge.getSrc();
1629 if (node instanceof LabelNode) {
1630 referencerEdge.unionSESETaintIdentifier(identifier);
1631 }else if(node instanceof HeapRegionNode){
1632 referencerEdge.unionSESETaintIdentifier(identifier);
1640 private HashSet<TempDescriptor> getReferenceNodeSet(HeapRegionNode hrn){
1642 HashSet<TempDescriptor> returnSet=new HashSet<TempDescriptor>();
1644 Iterator<ReferenceEdge> edgeIter=hrn.iteratorToReferencers();
1645 while(edgeIter.hasNext()){
1646 ReferenceEdge edge=edgeIter.next();
1647 if(edge.getSrc() instanceof LabelNode){
1648 LabelNode ln=(LabelNode)edge.getSrc();
1649 returnSet.add(ln.getTempDescriptor());
1658 private HashSet<HeapRegionNode> getReferenceHeapIDSet(OwnershipGraph og, TempDescriptor td){
1660 HashSet<HeapRegionNode> returnSet=new HashSet<HeapRegionNode>();
1662 LabelNode ln=og.td2ln.get(td);
1664 Iterator<ReferenceEdge> edgeIter=ln.iteratorToReferencees();
1665 while(edgeIter.hasNext()){
1666 ReferenceEdge edge=edgeIter.next();
1667 HeapRegionNode hrn=edge.getDst();
1675 private HashSet<TempDescriptor> getAccessedTaintNodeSet(LabelNode ln) {
1677 HashSet<TempDescriptor> returnSet = new HashSet<TempDescriptor>();
1679 Iterator<ReferenceEdge> edgeIter = ln.iteratorToReferencees();
1680 while (edgeIter.hasNext()) {
1681 ReferenceEdge edge = edgeIter.next();
1682 HeapRegionNode hrn = edge.getDst();
1684 Iterator<ReferenceEdge> edgeReferencerIter = hrn
1685 .iteratorToReferencers();
1686 while (edgeReferencerIter.hasNext()) {
1687 ReferenceEdge referencerEdge = edgeReferencerIter.next();
1689 if (referencerEdge.getSrc() instanceof LabelNode) {
1690 if (!((LabelNode) referencerEdge.getSrc()).equals(ln)) {
1692 if (referencerEdge.getSESETaintIdentifier() > 0) {
1693 TempDescriptor td = ((LabelNode) referencerEdge
1694 .getSrc()).getTempDescriptor();
1707 private HashSet<ReferenceEdge> getRefEdgeSetReferenceToSameHRN(
1708 OwnershipGraph og, TempDescriptor td) {
1710 HashSet<ReferenceEdge> returnSet = new HashSet<ReferenceEdge>();
1712 HashSet<HeapRegionNode> heapIDs = getReferenceHeapIDSet(og, td);
1713 for (Iterator<HeapRegionNode> iterator = heapIDs.iterator(); iterator
1715 HeapRegionNode heapRegionNode = (HeapRegionNode) iterator.next();
1716 Iterator<ReferenceEdge> referenceeIter = heapRegionNode
1717 .iteratorToReferencees();
1718 while (referenceeIter.hasNext()) {
1719 ReferenceEdge edge = (ReferenceEdge) referenceeIter.next();
1720 if (edge.getSrc() instanceof HeapRegionNode) {
1721 returnSet.add(edge);
1728 private HashSet<TempDescriptor> getTempDescSetReferenceToSameHRN(
1729 OwnershipGraph og, TempDescriptor td) {
1731 HashSet<TempDescriptor> returnSet = new HashSet<TempDescriptor>();
1733 HashSet<HeapRegionNode> heapIDs = getReferenceHeapIDSet(og, td);
1734 for (Iterator<HeapRegionNode> iterator = heapIDs.iterator(); iterator
1736 HeapRegionNode heapRegionNode = (HeapRegionNode) iterator.next();
1737 Iterator<ReferenceEdge> referencerIter = heapRegionNode
1738 .iteratorToReferencers();
1739 while (referencerIter.hasNext()) {
1740 ReferenceEdge edge = (ReferenceEdge) referencerIter.next();
1741 if (edge.getSrc() instanceof LabelNode) {
1742 LabelNode ln = (LabelNode) edge.getSrc();
1743 returnSet.add(ln.getTempDescriptor());
1750 private void DFSVisit( MethodDescriptor md,
1751 LinkedList<MethodDescriptor> sorted,
1752 HashSet<MethodDescriptor> discovered, JavaCallGraph javaCallGraph) {
1756 Iterator itr = javaCallGraph.getCallerSet(md).iterator();
1757 while (itr.hasNext()) {
1758 MethodDescriptor mdCaller = (MethodDescriptor) itr.next();
1760 if (!discovered.contains(mdCaller)) {
1761 DFSVisit(mdCaller, sorted, discovered, javaCallGraph);
1765 sorted.addFirst(md);
1769 private LinkedList<MethodDescriptor> topologicalSort(Set set,
1770 JavaCallGraph javaCallGraph) {
1771 HashSet<MethodDescriptor> discovered = new HashSet<MethodDescriptor>();
1772 LinkedList<MethodDescriptor> sorted = new LinkedList<MethodDescriptor>();
1774 Iterator<MethodDescriptor> itr = set.iterator();
1775 while (itr.hasNext()) {
1776 MethodDescriptor md = itr.next();
1778 if (!discovered.contains(md)) {
1779 DFSVisit(md, sorted, discovered, javaCallGraph);
1787 private void seseConflictsForward(JavaCallGraph javaCallGraph) {
1789 Set methodCallSet = javaCallGraph.getAllMethods(typeUtil.getMain());
1791 // topologically sort java call chain so that leaf calls are ordered
1793 LinkedList<MethodDescriptor> sortedMethodCalls = topologicalSort(
1794 methodCallSet, javaCallGraph);
1796 for (Iterator iterator = sortedMethodCalls.iterator(); iterator
1798 MethodDescriptor md = (MethodDescriptor) iterator.next();
1800 FlatMethod fm = state.getMethodFlat(md);
1802 HashSet<MethodContext> mcSet = ownAnalysis
1803 .getAllMethodContextSetByDescriptor(md);
1804 Iterator<MethodContext> mcIter = mcSet.iterator();
1806 currentMethodSummary=new MethodSummary();
1807 preeffectsSet=new HashSet<PreEffectsKey>();
1809 while (mcIter.hasNext()) {
1811 MethodContext mc = mcIter.next();
1813 Set<FlatNode> visited = new HashSet<FlatNode>();
1815 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
1816 flatNodesToVisit.add(fm);
1818 currentConflictsMap=null;
1819 while (!flatNodesToVisit.isEmpty()) {
1820 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
1821 flatNodesToVisit.remove(fn);
1823 conflicts_nodeAction(mc, fn, callGraph, preeffectsSet);
1825 flatNodesToVisit.remove(fn);
1828 for (int i = 0; i < fn.numNext(); i++) {
1829 FlatNode nn = fn.getNext(i);
1830 if (!visited.contains(nn)) {
1831 flatNodesToVisit.add(nn);
1836 methodSummaryResults.put(fm, currentMethodSummary);
1841 private void conflicts_nodeAction(MethodContext mc, FlatNode fn,
1842 CallGraph callGraph, HashSet<PreEffectsKey> preeffectsSet) {
1844 OwnershipGraph og = ownAnalysis.getOwnvershipGraphByMethodContext(mc);
1846 switch (fn.kind()) {
1848 case FKind.FlatSESEEnterNode: {
1850 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
1851 if (!fsen.getIsCallerSESEplaceholder()) {
1852 currentMethodSummary.increaseChildSESECount();
1855 if (currentMethodSummary.getChildSESECount() == 1) {
1856 // need to store pre-effects
1857 currentMethodSummary.getEffectsSet().addAll(preeffectsSet);
1859 for (Iterator iterator = currentMethodSummary.getEffectsSet()
1860 .iterator(); iterator.hasNext();) {
1861 PreEffectsKey preEffectsKey = (PreEffectsKey) iterator
1865 preeffectsSet.clear();
1871 case FKind.FlatSESEExitNode: {
1872 // all object variables are inaccessible.
1873 currentConflictsMap = new ParentChildConflictsMap();
1877 case FKind.FlatNew: {
1879 if (currentConflictsMap != null) {
1880 FlatNew fnew = (FlatNew) fn;
1881 TempDescriptor dst = fnew.getDst();
1882 currentConflictsMap.addAccessibleVar(dst);
1888 case FKind.FlatFieldNode: {
1890 FlatFieldNode ffn = (FlatFieldNode) fn;
1891 TempDescriptor dst = ffn.getDst();
1892 TempDescriptor src = ffn.getSrc();
1893 FieldDescriptor field = ffn.getField();
1895 if (currentConflictsMap != null) {
1897 HashSet<TempDescriptor> srcTempSet = getTempDescSetReferenceToSameHRN(
1899 for (Iterator iterator = srcTempSet.iterator(); iterator
1901 TempDescriptor possibleSrc = (TempDescriptor) iterator
1903 if (!currentConflictsMap.isAccessible(possibleSrc)) {
1904 currentConflictsMap.addStallSite(possibleSrc);
1907 currentConflictsMap.addAccessibleVar(possibleSrc);
1909 // contribute read effect on source's stall site
1910 currentConflictsMap.contributeEffect(src, field.getType()
1911 .getSafeSymbol(), field.toString(),
1912 StallSite.READ_EFFECT);
1915 HashSet<TempDescriptor> dstTempSet = getTempDescSetReferenceToSameHRN(
1917 for (Iterator iterator = dstTempSet.iterator(); iterator
1919 TempDescriptor possibleDst = (TempDescriptor) iterator
1921 currentConflictsMap.addAccessibleVar(possibleDst);
1925 if (currentMethodSummary.getChildSESECount() == 0) {
1926 // analyze preeffects
1927 preEffectAnalysis(og, src, field, PreEffectsKey.READ_EFFECT);
1933 case FKind.FlatSetFieldNode: {
1935 FlatSetFieldNode fsen = (FlatSetFieldNode) fn;
1936 TempDescriptor dst = fsen.getDst();
1937 FieldDescriptor field = fsen.getField();
1938 TempDescriptor src = fsen.getSrc();
1940 if (currentConflictsMap != null) {
1942 HashSet<TempDescriptor> srcTempSet = getTempDescSetReferenceToSameHRN(
1944 for (Iterator iterator = srcTempSet.iterator(); iterator
1946 TempDescriptor possibleSrc = (TempDescriptor) iterator
1948 if (!currentConflictsMap.isAccessible(possibleSrc)) {
1949 currentConflictsMap.addStallSite(possibleSrc);
1951 currentConflictsMap.addAccessibleVar(possibleSrc);
1954 HashSet<TempDescriptor> dstTempSet = getTempDescSetReferenceToSameHRN(
1956 for (Iterator iterator = dstTempSet.iterator(); iterator
1958 TempDescriptor possibleDst = (TempDescriptor) iterator
1961 if (!currentConflictsMap.isAccessible(possibleDst)) {
1962 currentConflictsMap.addStallSite(possibleDst);
1964 currentConflictsMap.addAccessibleVar(possibleDst);
1965 // contribute write effect on destination's stall site
1966 currentConflictsMap.contributeEffect(possibleDst, field
1967 .getType().getSafeSymbol(), field.toString(),
1968 StallSite.WRITE_EFFECT);
1971 // TODO need to create edge mapping for newly created edge
1972 HashSet<ReferenceEdge> edges = getRefEdgeSetReferenceToSameHRN(
1975 StallSite ss = currentConflictsMap.getStallMap().get(dst);
1977 for (Iterator iterator = edges.iterator(); iterator
1979 ReferenceEdge referenceEdge = (ReferenceEdge) iterator
1981 stallEdgeMapping.put(referenceEdge, ss);
1982 // System.out.println("STALL EDGE MAPPING WITH "+referenceEdge+" -> "+ss);
1987 if (currentMethodSummary.getChildSESECount() == 0) {
1988 // analyze preeffects
1989 preEffectAnalysis(og, dst, field, PreEffectsKey.WRITE_EFFECT);
1995 case FKind.FlatOpNode: {
1996 if (currentConflictsMap != null) {
1998 // destination variable gets the status of source.
1999 FlatOpNode fon = (FlatOpNode) fn;
2001 if (fon.getOp().getOp() == Operation.ASSIGN
2002 && currentConflictsMap != null) {
2004 TempDescriptor dst = fon.getDest();
2005 TempDescriptor src = fon.getLeft();
2007 Integer sourceStatus = currentConflictsMap
2008 .getAccessibleMap().get(src);
2009 if (sourceStatus == null) {
2010 sourceStatus = ParentChildConflictsMap.INACCESSIBLE;
2013 HashSet<TempDescriptor> dstTempSet = getTempDescSetReferenceToSameHRN(
2016 for (Iterator<TempDescriptor> iterator = dstTempSet
2017 .iterator(); iterator.hasNext();) {
2018 TempDescriptor possibleDst = iterator.next();
2021 .equals(ParentChildConflictsMap.ACCESSIBLE)) {
2022 currentConflictsMap.addAccessibleVar(possibleDst);
2024 currentConflictsMap.addInaccessibleVar(possibleDst);
2035 case FKind.FlatNop: {
2037 FlatNop fnop = (FlatNop) fn;
2038 if (fnop.numPrev() > 1) {
2040 for (int i = 0; i < fnop.numPrev(); i++) {
2041 FlatNode prev = fnop.getPrev(i);
2042 ParentChildConflictsMap prevConflictsMap = conflictsResults
2044 if (prevConflictsMap != null) {
2045 if (currentConflictsMap == null) {
2046 currentConflictsMap = new ParentChildConflictsMap();
2048 currentConflictsMap.merge(prevConflictsMap);
2053 // TODO: need to merge edge mappings
2058 case FKind.FlatCall: {
2060 FlatCall fc = (FlatCall) fn;
2062 FlatMethod calleeFM = state.getMethodFlat(fc.getMethod());
2064 // retrieve callee's method summary
2065 MethodSummary calleeMethodSummary = methodSummaryResults
2068 if (calleeMethodSummary != null
2069 && calleeMethodSummary.getChildSESECount() > 0) {
2071 // when parameter variable is accessible,
2072 // use callee's preeffects to figure out about how it affects
2073 // caller's stall site
2075 for (int i = 0; i < fc.numArgs(); i++) {
2076 TempDescriptor paramTemp = fc.getArg(i);
2078 if (currentConflictsMap != null) {
2079 if (currentConflictsMap.isAccessible(paramTemp)
2080 && currentConflictsMap.hasStallSite(paramTemp)) {
2081 // preeffect contribute its effect to caller's stall
2085 if (!fc.getMethod().isStatic()) {
2089 HashSet<PreEffectsKey> preeffectSet = calleeMethodSummary
2090 .getEffectsSetByParamIdx(i + offset);
2092 for (Iterator iterator = preeffectSet.iterator(); iterator
2094 PreEffectsKey preEffectsKey = (PreEffectsKey) iterator
2096 currentConflictsMap.contributeEffect(paramTemp,
2097 preEffectsKey.getType(), preEffectsKey
2098 .getField(), preEffectsKey
2103 // in other cases, child SESE has not been discovered,
2104 // assumes that all variables are accessible
2108 // If callee has at least one child sese, all parent object
2109 // is going to be inaccessible.
2110 currentConflictsMap = new ParentChildConflictsMap();
2112 TempDescriptor returnTemp = fc.getReturnTemp();
2114 if (calleeMethodSummary.getReturnValueAccessibility().equals(
2115 MethodSummary.ACCESSIBLE)) {
2116 // when return value is accessible, associate with its
2118 currentConflictsMap.addAccessibleVar(returnTemp);
2119 currentConflictsMap.addStallSite(returnTemp,
2120 calleeMethodSummary.getReturnStallSite());
2121 } else if (calleeMethodSummary.getReturnValueAccessibility()
2122 .equals(MethodSummary.INACCESSIBLE)) {
2123 // when return value is inaccessible
2124 currentConflictsMap.addInaccessibleVar(returnTemp);
2128 // TODO: need to handle edge mappings from callee
2133 case FKind.FlatReturnNode: {
2135 FlatReturnNode frn = (FlatReturnNode) fn;
2136 TempDescriptor returnTD = frn.getReturnTemp();
2138 if (returnTD != null) {
2139 if (currentConflictsMap == null) {
2140 // in this case, all variables is accessible. There are no
2143 if (currentConflictsMap.isAccessible(returnTD)) {
2144 currentMethodSummary
2145 .setReturnValueAccessibility(MethodSummary.ACCESSIBLE);
2146 StallSite returnStallSite = currentConflictsMap
2147 .getStallMap().get(returnTD);
2148 currentMethodSummary
2149 .setReturnStallSite(returnStallSite);
2151 currentMethodSummary
2152 .setReturnValueAccessibility(MethodSummary.INACCESSIBLE);
2159 case FKind.FlatExit: {
2161 // store method summary when it has at least one child SESE
2162 if (currentMethodSummary.getChildSESECount() > 0) {
2163 FlatMethod fm = state.getMethodFlat(mc.getDescriptor()); // current
2166 methodSummaryResults.put(fm, currentMethodSummary);
2174 // for every program point, we keep accessible map and stall map.
2175 if (currentConflictsMap != null) {
2176 conflictsResults.put(fn, currentConflictsMap);
2181 private void preEffectAnalysis(OwnershipGraph og, TempDescriptor td,
2182 FieldDescriptor field, Integer effectType) {
2184 // analyze preeffects
2185 HashSet<HeapRegionNode> hrnSet = getReferenceHeapIDSet(og, td);
2186 for (Iterator iterator = hrnSet.iterator(); iterator.hasNext();) {
2187 HeapRegionNode hrn = (HeapRegionNode) iterator.next();
2188 if (hrn.isParameter()) {
2189 // effects on param heap region
2191 Set<Integer> paramSet = og.idPrimary2paramIndexSet.get(hrn
2194 if (paramSet != null) {
2195 Iterator<Integer> paramIter = paramSet.iterator();
2196 while (paramIter.hasNext()) {
2197 Integer paramID = paramIter.next();
2198 PreEffectsKey effectKey = new PreEffectsKey(paramID,
2199 field.toString(), field.getType()
2200 .getSafeSymbol(), effectType);
2201 preeffectsSet.add(effectKey);
2205 // check weather this heap region is parameter
2208 paramSet = og.idSecondary2paramIndexSet.get(hrn.getID());
2209 if (paramSet != null) {
2210 Iterator<Integer> paramIter = paramSet.iterator();
2212 while (paramIter.hasNext()) {
2213 Integer paramID = paramIter.next();
2214 PreEffectsKey effectKey = new PreEffectsKey(paramID,
2215 field.toString(), field.getType()
2216 .getSafeSymbol(), effectType);
2217 preeffectsSet.add(effectKey);
2225 private MethodSummary analysisMethodCall(FlatMethod fm, OwnershipGraph calleeOG){
2227 MethodSummary methodSummary=new MethodSummary();
2229 Set<FlatNode> visited = new HashSet<FlatNode>();
2230 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
2231 flatNodesToVisit.add(fm);
2233 while (!flatNodesToVisit.isEmpty()) {
2234 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
2235 flatNodesToVisit.remove(fn);
2237 // conflicts_nodeAction(mc, fn, callGraph);
2239 flatNodesToVisit.remove(fn);
2242 for (int i = 0; i < fn.numNext(); i++) {
2243 FlatNode nn = fn.getNext(i);
2244 if (!visited.contains(nn)) {
2245 flatNodesToVisit.add(nn);
2252 return methodSummary;
2258 private void codePlansForward( FlatMethod fm ) {
2260 // start from flat method top, visit every node in
2261 // method exactly once
2262 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
2263 flatNodesToVisit.add( fm );
2265 Set<FlatNode> visited = new HashSet<FlatNode>();
2267 while( !flatNodesToVisit.isEmpty() ) {
2268 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
2269 FlatNode fn = fnItr.next();
2271 flatNodesToVisit.remove( fn );
2274 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
2275 assert seseStack != null;
2277 // use incoming results as "dot statement" or just
2278 // before the current statement
2279 VarSrcTokTable dotSTtable = new VarSrcTokTable();
2280 for( int i = 0; i < fn.numPrev(); i++ ) {
2281 FlatNode nn = fn.getPrev( i );
2282 dotSTtable.merge( variableResults.get( nn ) );
2285 // find dt-st notAvailableSet also
2286 Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
2287 for( int i = 0; i < fn.numPrev(); i++ ) {
2288 FlatNode nn = fn.getPrev( i );
2289 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
2290 if( notAvailIn != null ) {
2291 dotSTnotAvailSet.addAll( notAvailIn );
2295 Set<TempDescriptor> dotSTlive = livenessRootView.get( fn );
2297 if( !seseStack.empty() ) {
2298 codePlans_nodeActions( fn,
2306 for( int i = 0; i < fn.numNext(); i++ ) {
2307 FlatNode nn = fn.getNext( i );
2309 if( !visited.contains( nn ) ) {
2310 flatNodesToVisit.add( nn );
2316 private void codePlans_nodeActions( FlatNode fn,
2317 Set<TempDescriptor> liveSetIn,
2318 VarSrcTokTable vstTableIn,
2319 Set<TempDescriptor> notAvailSetIn,
2320 FlatSESEEnterNode currentSESE ) {
2322 CodePlan plan = new CodePlan( currentSESE);
2324 switch( fn.kind() ) {
2326 case FKind.FlatSESEEnterNode: {
2327 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
2329 // track the source types of the in-var set so generated
2330 // code at this SESE issue can compute the number of
2331 // dependencies properly
2332 Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
2333 while( inVarItr.hasNext() ) {
2334 TempDescriptor inVar = inVarItr.next();
2336 vstTableIn.getRefVarSrcType( inVar,
2340 // the current SESE needs a local space to track the dynamic
2341 // variable and the child needs space in its SESE record
2342 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
2343 fsen.addDynamicInVar( inVar );
2344 fsen.getParent().addDynamicVar( inVar );
2346 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
2347 fsen.addStaticInVar( inVar );
2348 VariableSourceToken vst = vstTableIn.get( inVar ).iterator().next();
2349 fsen.putStaticInVar2src( inVar, vst );
2350 fsen.addStaticInVarSrc( new SESEandAgePair( vst.getSESE(),
2356 assert srcType.equals( VarSrcTokTable.SrcType_READY );
2357 fsen.addReadyInVar( inVar );
2363 case FKind.FlatSESEExitNode: {
2364 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
2367 case FKind.FlatOpNode: {
2368 FlatOpNode fon = (FlatOpNode) fn;
2370 if( fon.getOp().getOp() == Operation.ASSIGN ) {
2371 TempDescriptor lhs = fon.getDest();
2372 TempDescriptor rhs = fon.getLeft();
2374 // if this is an op node, don't stall, copy
2375 // source and delay until we need to use value
2377 // ask whether lhs and rhs sources are dynamic, static, etc.
2379 = vstTableIn.getRefVarSrcType( lhs,
2381 currentSESE.getParent() );
2384 = vstTableIn.getRefVarSrcType( rhs,
2386 currentSESE.getParent() );
2388 if( rhsSrcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
2389 // if rhs is dynamic going in, lhs will definitely be dynamic
2390 // going out of this node, so track that here
2391 plan.addDynAssign( lhs, rhs );
2392 currentSESE.addDynamicVar( lhs );
2393 currentSESE.addDynamicVar( rhs );
2395 } else if( lhsSrcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
2396 // otherwise, if the lhs is dynamic, but the rhs is not, we
2397 // need to update the variable's dynamic source as "current SESE"
2398 plan.addDynAssign( lhs );
2401 // only break if this is an ASSIGN op node,
2402 // otherwise fall through to default case
2407 // note that FlatOpNode's that aren't ASSIGN
2408 // fall through to this default case
2411 // a node with no live set has nothing to stall for
2412 if( liveSetIn == null ) {
2416 TempDescriptor[] readarray = fn.readsTemps();
2417 for( int i = 0; i < readarray.length; i++ ) {
2418 TempDescriptor readtmp = readarray[i];
2420 // ignore temps that are definitely available
2421 // when considering to stall on it
2422 if( !notAvailSetIn.contains( readtmp ) ) {
2426 // check the source type of this variable
2428 = vstTableIn.getRefVarSrcType( readtmp,
2430 currentSESE.getParent() );
2432 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
2433 // 1) It is not clear statically where this variable will
2434 // come from statically, so dynamically we must keep track
2435 // along various control paths, and therefore when we stall,
2436 // just stall for the exact thing we need and move on
2437 plan.addDynamicStall( readtmp );
2438 currentSESE.addDynamicVar( readtmp );
2440 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
2441 // 2) Single token/age pair: Stall for token/age pair, and copy
2442 // all live variables with same token/age pair at the same
2443 // time. This is the same stuff that the notavaialable analysis
2444 // marks as now available.
2446 VariableSourceToken vst = vstTableIn.get( readtmp ).iterator().next();
2448 Iterator<VariableSourceToken> availItr =
2449 vstTableIn.get( vst.getSESE(), vst.getAge() ).iterator();
2451 while( availItr.hasNext() ) {
2452 VariableSourceToken vstAlsoAvail = availItr.next();
2454 // only grab additional stuff that is live
2455 Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
2457 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
2458 while( refVarItr.hasNext() ) {
2459 TempDescriptor refVar = refVarItr.next();
2460 if( liveSetIn.contains( refVar ) ) {
2461 copySet.add( refVar );
2465 if( !copySet.isEmpty() ) {
2466 plan.addStall2CopySet( vstAlsoAvail, copySet );
2471 // the other case for srcs is READY, so do nothing
2474 // assert that everything being stalled for is in the
2475 // "not available" set coming into this flat node and
2476 // that every VST identified is in the possible "stall set"
2477 // that represents VST's from children SESE's
2485 // identify sese-age pairs that are statically useful
2486 // and should have an associated SESE variable in code
2487 // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
2488 // AND ALWAYS GIVE NAMES TO PARENTS
2489 Set<VariableSourceToken> staticSet = vstTableIn.get();
2490 Iterator<VariableSourceToken> vstItr = staticSet.iterator();
2491 while( vstItr.hasNext() ) {
2492 VariableSourceToken vst = vstItr.next();
2494 // placeholder source tokens are useful results, but
2495 // the placeholder static name is never needed
2496 if( vst.getSESE().getIsCallerSESEplaceholder() ) {
2500 FlatSESEEnterNode sese = currentSESE;
2501 while( sese != null ) {
2502 sese.addNeededStaticName(
2503 new SESEandAgePair( vst.getSESE(), vst.getAge() )
2505 sese.mustTrackAtLeastAge( vst.getAge() );
2507 sese = sese.getParent();
2512 codePlans.put( fn, plan );
2515 // if any variables at this-node-*dot* have a static source (exactly one vst)
2516 // but go to a dynamic source at next-node-*dot*, create a new IR graph
2517 // node on that edge to track the sources dynamically
2518 VarSrcTokTable thisVstTable = variableResults.get( fn );
2519 for( int i = 0; i < fn.numNext(); i++ ) {
2520 FlatNode nn = fn.getNext( i );
2521 VarSrcTokTable nextVstTable = variableResults.get( nn );
2522 Set<TempDescriptor> nextLiveIn = livenessRootView.get( nn );
2524 // the table can be null if it is one of the few IR nodes
2525 // completely outside of the root SESE scope
2526 if( nextVstTable != null && nextLiveIn != null ) {
2528 Hashtable<TempDescriptor, VariableSourceToken> static2dynamicSet =
2529 thisVstTable.getStatic2DynamicSet( nextVstTable,
2532 currentSESE.getParent()
2535 if( !static2dynamicSet.isEmpty() ) {
2537 // either add these results to partial fixed-point result
2538 // or make a new one if we haven't made any here yet
2539 FlatEdge fe = new FlatEdge( fn, nn );
2540 FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get( fe );
2542 if( fwdvn == null ) {
2543 fwdvn = new FlatWriteDynamicVarNode( fn,
2548 wdvNodesToSpliceIn.put( fe, fwdvn );
2550 fwdvn.addMoreVar2Src( static2dynamicSet );
2558 public void writeReports( String timeReport ) throws java.io.IOException {
2560 BufferedWriter bw = new BufferedWriter( new FileWriter( "mlpReport_summary.txt" ) );
2561 bw.write( "MLP Analysis Results\n\n" );
2562 bw.write( timeReport+"\n\n" );
2563 printSESEHierarchy( bw );
2565 printSESEInfo( bw );
2568 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
2569 while( methItr.hasNext() ) {
2570 MethodDescriptor md = (MethodDescriptor) methItr.next();
2571 FlatMethod fm = state.getMethodFlat( md );
2572 bw = new BufferedWriter( new FileWriter( "mlpReport_"+
2573 md.getClassMethodName()+
2574 md.getSafeMethodDescriptor()+
2576 bw.write( "MLP Results for "+md+"\n-------------------\n");
2577 bw.write( "\n\nLive-In, Root View\n------------------\n" +fm.printMethod( livenessRootView ) );
2578 bw.write( "\n\nVariable Results-Out\n----------------\n" +fm.printMethod( variableResults ) );
2579 bw.write( "\n\nNot Available Results-Out\n---------------------\n"+fm.printMethod( notAvailableResults ) );
2580 bw.write( "\n\nCode Plans\n----------\n" +fm.printMethod( codePlans ) );
2581 bw.write("\n\nSESE Effects\n----------------------\n"+printSESEEffects());
2586 private String printSESEEffects() {
2588 StringWriter writer = new StringWriter();
2590 Iterator<FlatSESEEnterNode> keyIter = allSESEs.iterator();
2592 while (keyIter.hasNext()) {
2593 FlatSESEEnterNode seseEnter = keyIter.next();
2594 String result = seseEnter.getSeseEffectsSet().printSet();
2595 if (result.length() > 0) {
2596 writer.write("\nSESE " + seseEnter + "\n");
2597 writer.write(result);
2600 keyIter = rootSESEs.iterator();
2601 while (keyIter.hasNext()) {
2602 FlatSESEEnterNode seseEnter = keyIter.next();
2603 if (seseEnter.getIsCallerSESEplaceholder()) {
2604 if (!seseEnter.getChildren().isEmpty()) {
2605 String result = seseEnter.getSeseEffectsSet().printSet();
2606 if (result.length() > 0) {
2607 writer.write("\nSESE " + seseEnter + "\n");
2608 writer.write(result);
2614 return writer.toString();
2618 private void printSESEHierarchy( BufferedWriter bw ) throws java.io.IOException {
2619 bw.write( "SESE Hierarchy\n--------------\n" );
2620 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
2621 while( rootItr.hasNext() ) {
2622 FlatSESEEnterNode root = rootItr.next();
2623 if( root.getIsCallerSESEplaceholder() ) {
2624 if( !root.getChildren().isEmpty() ) {
2625 printSESEHierarchyTree( bw, root, 0 );
2628 printSESEHierarchyTree( bw, root, 0 );
2633 private void printSESEHierarchyTree( BufferedWriter bw,
2634 FlatSESEEnterNode fsen,
2636 ) throws java.io.IOException {
2637 for( int i = 0; i < depth; ++i ) {
2640 bw.write( "- "+fsen.getPrettyIdentifier()+"\n" );
2642 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
2643 while( childItr.hasNext() ) {
2644 FlatSESEEnterNode fsenChild = childItr.next();
2645 printSESEHierarchyTree( bw, fsenChild, depth + 1 );
2650 private void printSESEInfo( BufferedWriter bw ) throws java.io.IOException {
2651 bw.write("\nSESE info\n-------------\n" );
2652 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
2653 while( rootItr.hasNext() ) {
2654 FlatSESEEnterNode root = rootItr.next();
2655 if( root.getIsCallerSESEplaceholder() ) {
2656 if( !root.getChildren().isEmpty() ) {
2657 printSESEInfoTree( bw, root );
2660 printSESEInfoTree( bw, root );
2665 private void printSESEInfoTree( BufferedWriter bw,
2666 FlatSESEEnterNode fsen
2667 ) throws java.io.IOException {
2669 if( !fsen.getIsCallerSESEplaceholder() ) {
2670 bw.write( "SESE "+fsen.getPrettyIdentifier()+" {\n" );
2672 bw.write( " in-set: "+fsen.getInVarSet()+"\n" );
2673 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
2674 while( tItr.hasNext() ) {
2675 TempDescriptor inVar = tItr.next();
2676 if( fsen.getReadyInVarSet().contains( inVar ) ) {
2677 bw.write( " (ready) "+inVar+"\n" );
2679 if( fsen.getStaticInVarSet().contains( inVar ) ) {
2680 bw.write( " (static) "+inVar+"\n" );
2682 if( fsen.getDynamicInVarSet().contains( inVar ) ) {
2683 bw.write( " (dynamic)"+inVar+"\n" );
2687 bw.write( " out-set: "+fsen.getOutVarSet()+"\n" );
2691 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
2692 while( childItr.hasNext() ) {
2693 FlatSESEEnterNode fsenChild = childItr.next();
2694 printSESEInfoTree( bw, fsenChild );