1 package Analysis.OwnershipAnalysis;
8 public class OwnershipGraph {
10 private int allocationDepth;
12 // there was already one other very similar reason
13 // for traversing heap nodes that is no longer needed
14 // instead of writing a new heap region visitor, use
15 // the existing method with a new mode to describe what
16 // actions to take during the traversal
17 protected static final int VISIT_HRN_WRITE_FULL = 0;
20 public Hashtable<Integer, HeapRegionNode> id2hrn;
21 public Hashtable<TempDescriptor, LabelNode > td2ln;
22 public Hashtable<Integer, Integer > id2paramIndex;
23 public Hashtable<Integer, Integer > paramIndex2id;
25 public HashSet<AllocationSite> allocationSites;
28 public OwnershipGraph( int allocationDepth ) {
29 this.allocationDepth = allocationDepth;
31 id2hrn = new Hashtable<Integer, HeapRegionNode>();
32 td2ln = new Hashtable<TempDescriptor, LabelNode >();
33 id2paramIndex = new Hashtable<Integer, Integer >();
34 paramIndex2id = new Hashtable<Integer, Integer >();
36 allocationSites = new HashSet <AllocationSite>();
40 // label nodes are much easier to deal with than
41 // heap region nodes. Whenever there is a request
42 // for the label node that is associated with a
43 // temp descriptor we can either find it or make a
44 // new one and return it. This is because temp
45 // descriptors are globally unique and every label
46 // node is mapped to exactly one temp descriptor.
47 protected LabelNode getLabelNodeFromTemp( TempDescriptor td ) {
50 if( !td2ln.containsKey( td ) ) {
51 td2ln.put( td, new LabelNode( td ) );
54 return td2ln.get( td );
58 // the reason for this method is to have the option
59 // creating new heap regions with specific IDs, or
60 // duplicating heap regions with specific IDs (especially
61 // in the merge() operation) or to create new heap
62 // regions with a new unique ID.
63 protected HeapRegionNode
64 createNewHeapRegionNode( Integer id,
65 boolean isSingleObject,
69 AllocationSite allocSite,
70 ReachabilitySet alpha,
71 String description ) {
74 id = OwnershipAnalysis.generateUniqueHeapRegionNodeID();
78 if( isFlagged || isParameter ) {
79 alpha = new ReachabilitySet( new TokenTuple( id,
81 TokenTuple.ARITY_ONE ) );
83 alpha = new ReachabilitySet();
87 HeapRegionNode hrn = new HeapRegionNode( id,
94 id2hrn.put( id, hrn );
100 ////////////////////////////////////////////////
102 // Low-level referencee and referencer methods
104 // These methods provide the lowest level for
105 // creating references between ownership nodes
106 // and handling the details of maintaining both
107 // list of referencers and referencees.
109 ////////////////////////////////////////////////
110 protected void addReferenceEdge( OwnershipNode referencer,
111 HeapRegionNode referencee,
112 ReferenceEdgeProperties rep ) {
113 assert referencer != null;
114 assert referencee != null;
116 referencer.addReferencedRegion( referencee, rep );
117 referencee.addReferencer( referencer );
118 rep.setSrc( referencer );
119 rep.setDst( referencee );
122 protected void removeReferenceEdge( OwnershipNode referencer,
123 HeapRegionNode referencee ) {
124 assert referencer != null;
125 assert referencee != null;
126 assert referencer.getReferenceTo( referencee ) != null;
127 assert referencee.isReferencedBy( referencer );
129 referencer.removeReferencedRegion( referencee );
130 referencee.removeReferencer( referencer );
133 protected void clearReferenceEdgesFrom( OwnershipNode referencer ) {
134 assert referencer != null;
136 // get a copy of the table to iterate over, otherwise
137 // we will be trying to take apart the table as we
138 // are iterating over it, which won't work
139 Iterator i = referencer.setIteratorToReferencedRegionsClone();
140 while( i.hasNext() ) {
141 Map.Entry me = (Map.Entry) i.next();
142 HeapRegionNode referencee = (HeapRegionNode) me.getKey();
143 removeReferenceEdge( referencer, referencee );
147 protected void clearReferenceEdgesTo( HeapRegionNode referencee ) {
148 assert referencee != null;
150 // get a copy of the table to iterate over, otherwise
151 // we will be trying to take apart the table as we
152 // are iterating over it, which won't work
153 Iterator i = referencee.iteratorToReferencersClone();
154 while( i.hasNext() ) {
155 OwnershipNode referencer = (OwnershipNode) i.next();
156 removeReferenceEdge( referencer, referencee );
161 protected void propagateTokensOverNodes( HeapRegionNode nPrime,
163 HashSet<HeapRegionNode> nodesWithNewAlpha,
164 HashSet<ReferenceEdgeProperties> edgesWithNewBeta ) {
166 HashSet<HeapRegionNode> todoNodes
167 = new HashSet<HeapRegionNode>();
168 todoNodes.add( nPrime );
170 HashSet<ReferenceEdgeProperties> todoEdges
171 = new HashSet<ReferenceEdgeProperties>();
173 Hashtable<HeapRegionNode, ChangeTupleSet> nodePlannedChanges
174 = new Hashtable<HeapRegionNode, ChangeTupleSet>();
175 nodePlannedChanges.put( nPrime, c0 );
177 Hashtable<ReferenceEdgeProperties, ChangeTupleSet> edgePlannedChanges
178 = new Hashtable<ReferenceEdgeProperties, ChangeTupleSet>();
181 while( !todoNodes.isEmpty() ) {
182 HeapRegionNode n = todoNodes.iterator().next();
183 ChangeTupleSet C = nodePlannedChanges.get( n );
185 Iterator itrC = C.iterator();
186 while( itrC.hasNext() ) {
187 ChangeTuple c = (ChangeTuple) itrC.next();
189 if( n.getAlpha().contains( c.getSetToMatch() ) ) {
190 ReachabilitySet withChange = n.getAlpha().union( c.getSetToAdd() );
191 n.setAlphaNew( n.getAlphaNew().union( withChange ) );
192 nodesWithNewAlpha.add( n );
196 Iterator referItr = n.iteratorToReferencers();
197 while( referItr.hasNext() ) {
198 OwnershipNode on = (OwnershipNode) referItr.next();
199 ReferenceEdgeProperties rep = on.getReferenceTo( n );
200 todoEdges.add( rep );
202 if( !edgePlannedChanges.containsKey( rep ) ) {
203 edgePlannedChanges.put( rep, new ChangeTupleSet().makeCanonical() );
206 edgePlannedChanges.put( rep, edgePlannedChanges.get( rep ).union( C ) );
209 HeapRegionNode m = null;
210 ReferenceEdgeProperties f = null;
211 Iterator refeeItr = n.setIteratorToReferencedRegions();
212 while( refeeItr.hasNext() ) {
213 Map.Entry me = (Map.Entry) refeeItr.next();
214 m = (HeapRegionNode) me.getKey();
215 f = (ReferenceEdgeProperties) me.getValue();
217 ChangeTupleSet changesToPass = new ChangeTupleSet().makeCanonical();
219 Iterator itrCprime = C.iterator();
220 while( itrCprime.hasNext() ) {
221 ChangeTuple c = (ChangeTuple) itrCprime.next();
222 if( f.getBeta().contains( c.getSetToMatch() ) ) {
223 changesToPass = changesToPass.union( c );
227 if( !changesToPass.isEmpty() ) {
228 if( !nodePlannedChanges.containsKey( m ) ) {
229 nodePlannedChanges.put( m, new ChangeTupleSet().makeCanonical() );
232 ChangeTupleSet currentChanges = nodePlannedChanges.get( m );
234 if( !changesToPass.isSubset( currentChanges ) ) {
236 nodePlannedChanges.put( m, currentChanges.union( changesToPass ) );
242 todoNodes.remove( n );
245 propagateTokensOverEdges( todoEdges, edgePlannedChanges, nodesWithNewAlpha, edgesWithNewBeta );
249 protected void propagateTokensOverEdges(
250 HashSet<ReferenceEdgeProperties> todoEdges,
251 Hashtable<ReferenceEdgeProperties, ChangeTupleSet> edgePlannedChanges,
252 HashSet<HeapRegionNode> nodesWithNewAlpha,
253 HashSet<ReferenceEdgeProperties> edgesWithNewBeta ) {
256 while( !todoEdges.isEmpty() ) {
257 ReferenceEdgeProperties e = todoEdges.iterator().next();
258 todoEdges.remove( e );
260 if( !edgePlannedChanges.containsKey( e ) ) {
261 edgePlannedChanges.put( e, new ChangeTupleSet().makeCanonical() );
264 ChangeTupleSet C = edgePlannedChanges.get( e );
266 ChangeTupleSet changesToPass = new ChangeTupleSet().makeCanonical();
268 Iterator itrC = C.iterator();
269 while( itrC.hasNext() ) {
270 ChangeTuple c = (ChangeTuple) itrC.next();
271 if( e.getBeta().contains( c.getSetToMatch() ) ) {
272 ReachabilitySet withChange = e.getBeta().union( c.getSetToAdd() );
273 e.setBetaNew( e.getBetaNew().union( withChange ) );
274 edgesWithNewBeta.add( e );
275 changesToPass = changesToPass.union( c );
279 OwnershipNode onSrc = e.getSrc();
281 if( !changesToPass.isEmpty() && onSrc instanceof HeapRegionNode ) {
282 HeapRegionNode n = (HeapRegionNode) onSrc;
283 Iterator referItr = n.iteratorToReferencers();
285 while( referItr.hasNext() ) {
286 OwnershipNode onRef = (OwnershipNode) referItr.next();
287 ReferenceEdgeProperties f = onRef.getReferenceTo( n );
289 if( !edgePlannedChanges.containsKey( f ) ) {
290 edgePlannedChanges.put( f, new ChangeTupleSet().makeCanonical() );
293 ChangeTupleSet currentChanges = edgePlannedChanges.get( f );
295 if( !changesToPass.isSubset( currentChanges ) ) {
297 edgePlannedChanges.put( f, currentChanges.union( changesToPass ) );
305 ////////////////////////////////////////////////////
307 // Assignment Operation Methods
309 // These methods are high-level operations for
310 // modeling program assignment statements using
311 // the low-level reference create/remove methods
314 // The destination in an assignment statement is
315 // going to have new references. The method of
316 // determining the references depends on the type
317 // of the FlatNode assignment and the predicates
318 // of the nodes and edges involved.
320 ////////////////////////////////////////////////////
321 public void assignTempToTemp( TempDescriptor src,
322 TempDescriptor dst ) {
323 LabelNode srcln = getLabelNodeFromTemp( src );
324 LabelNode dstln = getLabelNodeFromTemp( dst );
326 clearReferenceEdgesFrom( dstln );
328 HeapRegionNode newReferencee = null;
329 Iterator srcRegionsItr = srcln.setIteratorToReferencedRegions();
330 while( srcRegionsItr.hasNext() ) {
331 Map.Entry me = (Map.Entry) srcRegionsItr.next();
332 newReferencee = (HeapRegionNode) me.getKey();
333 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
335 addReferenceEdge( dstln, newReferencee, rep.copy() );
339 public void assignTempToField( TempDescriptor src,
341 FieldDescriptor fd ) {
342 LabelNode srcln = getLabelNodeFromTemp( src );
343 LabelNode dstln = getLabelNodeFromTemp( dst );
345 clearReferenceEdgesFrom( dstln );
347 HeapRegionNode hrn = null;
348 Iterator srcRegionsItr = srcln.setIteratorToReferencedRegions();
349 while( srcRegionsItr.hasNext() ) {
350 Map.Entry me = (Map.Entry) srcRegionsItr.next();
351 hrn = (HeapRegionNode) me.getKey();
352 ReferenceEdgeProperties rep1 = (ReferenceEdgeProperties) me.getValue();
353 ReachabilitySet beta1 = rep1.getBeta();
355 HeapRegionNode hrnOneHop = null;
356 Iterator hrnRegionsItr = hrn.setIteratorToReferencedRegions();
357 while( hrnRegionsItr.hasNext() ) {
358 Map.Entry meH = (Map.Entry) hrnRegionsItr.next();
359 hrnOneHop = (HeapRegionNode) meH.getKey();
360 ReferenceEdgeProperties rep2 = (ReferenceEdgeProperties) meH.getValue();
361 ReachabilitySet beta2 = rep2.getBeta();
363 ReferenceEdgeProperties rep =
364 new ReferenceEdgeProperties( null,
366 beta1.intersection( beta2 ) );
368 addReferenceEdge( dstln, hrnOneHop, rep );
379 public void assignFieldToTemp( TempDescriptor src,
381 FieldDescriptor fd ) {
383 // I think my use of src and dst are actually backwards in this method!
384 // acccording to the Reachability Notes, think of dst at N and src as N prime
386 LabelNode srcln = getLabelNodeFromTemp( src );
387 LabelNode dstln = getLabelNodeFromTemp( dst );
389 HashSet<HeapRegionNode> nodesWithNewAlpha = new HashSet<HeapRegionNode>();
390 HashSet<ReferenceEdgeProperties> edgesWithNewBeta = new HashSet<ReferenceEdgeProperties>();
392 HeapRegionNode hrn = null;
393 ReferenceEdgeProperties rep = null;
394 Iterator dstRegionsItr = dstln.setIteratorToReferencedRegions();
395 while( dstRegionsItr.hasNext() ) {
396 Map.Entry me = (Map.Entry) dstRegionsItr.next();
397 hrn = (HeapRegionNode) me.getKey();
398 rep = (ReferenceEdgeProperties) me.getValue();
400 ReachabilitySet R = hrn.getAlpha().intersection( rep.getBeta() );
402 HeapRegionNode hrnSrc = null;
403 ReferenceEdgeProperties repSrc = null;
404 Iterator srcRegionsItr = srcln.setIteratorToReferencedRegions();
405 while( srcRegionsItr.hasNext() ) {
406 Map.Entry meS = (Map.Entry) srcRegionsItr.next();
407 hrnSrc = (HeapRegionNode) meS.getKey();
408 repSrc = (ReferenceEdgeProperties) meS.getValue();
410 ReachabilitySet O = repSrc.getBeta();
414 System.out.println( "x is "+x );
416 String s = String.format( "debug%04d", x );
418 writeGraph( s, true, true, true, false );
419 } catch( Exception e ) {}
423 System.out.println( " O is "+O );
425 // propagate tokens over nodes starting from hrnSrc, and it will
426 // take care of propagating back up edges from any touched nodes
427 ChangeTupleSet Cy = O.unionUpArityToChangeSet( R );
428 propagateTokensOverNodes( hrnSrc, Cy, nodesWithNewAlpha, edgesWithNewBeta );
431 // then propagate back just up the edges from hrn
432 ChangeTupleSet Cx = R.unionUpArityToChangeSet( O );
434 HashSet<ReferenceEdgeProperties> todoEdges =
435 new HashSet<ReferenceEdgeProperties>();
437 Hashtable<ReferenceEdgeProperties, ChangeTupleSet> edgePlannedChanges =
438 new Hashtable<ReferenceEdgeProperties, ChangeTupleSet>();
440 Iterator referItr = hrn.iteratorToReferencers();
441 while( referItr.hasNext() ) {
442 OwnershipNode onRef = (OwnershipNode) referItr.next();
444 System.out.println( " "+onRef+" is upstream" );
446 ReferenceEdgeProperties repUpstream = onRef.getReferenceTo( hrn );
448 todoEdges.add( repUpstream );
449 edgePlannedChanges.put( repUpstream, Cx );
452 System.out.println( "plans "+edgePlannedChanges );
454 propagateTokensOverEdges( todoEdges,
459 System.out.println( " Onew = "+repSrc.getBetaNew() );
461 // finally, create the actual reference edge hrn->hrnSrc
462 ReferenceEdgeProperties repNew
463 = new ReferenceEdgeProperties( fd,
465 repSrc.getBetaNew().pruneBy( hrn.getAlpha() )
468 addReferenceEdge( hrn, hrnSrc, repNew );
472 Iterator nodeItr = nodesWithNewAlpha.iterator();
473 while( nodeItr.hasNext() ) {
474 ((HeapRegionNode) nodeItr.next()).applyAlphaNew();
477 Iterator edgeItr = edgesWithNewBeta.iterator();
478 while( edgeItr.hasNext() ) {
479 ((ReferenceEdgeProperties) edgeItr.next()).applyBetaNew();
483 public void assignTempToParameterAllocation( boolean isTask,
485 Integer paramIndex ) {
488 LabelNode lnParam = getLabelNodeFromTemp( td );
489 HeapRegionNode hrn = createNewHeapRegionNode( null,
496 "param" + paramIndex );
498 // keep track of heap regions that were created for
499 // parameter labels, the index of the parameter they
500 // are for is important when resolving method calls
501 Integer newID = hrn.getID();
502 assert !id2paramIndex.containsKey ( newID );
503 assert !id2paramIndex.containsValue( paramIndex );
504 id2paramIndex.put( newID, paramIndex );
505 paramIndex2id.put( paramIndex, newID );
507 ReachabilitySet beta = new ReachabilitySet( new TokenTuple( newID,
509 TokenTuple.ARITY_ONE ) );
511 // heap regions for parameters are always multiple object (see above)
512 // and have a reference to themselves, because we can't know the
513 // structure of memory that is passed into the method. We're assuming
515 addReferenceEdge( lnParam, hrn, new ReferenceEdgeProperties( null, false, beta ) );
516 addReferenceEdge( hrn, hrn, new ReferenceEdgeProperties( null, true, beta ) );
519 public void assignTempToNewAllocation( TempDescriptor td,
520 AllocationSite as ) {
527 // after the age operation the newest (or zero-ith oldest)
528 // node associated with the allocation site should have
529 // no references to it as if it were a newly allocated
530 // heap region, so make a reference to it to complete
532 Integer idNewest = as.getIthOldest( 0 );
533 HeapRegionNode hrnNewest = id2hrn.get( idNewest );
534 assert hrnNewest != null;
536 LabelNode dst = getLabelNodeFromTemp( td );
538 clearReferenceEdgesFrom( dst );
540 addReferenceEdge( dst, hrnNewest, new ReferenceEdgeProperties( null, false, hrnNewest.getAlpha() ) );
544 // use the allocation site (unique to entire analysis) to
545 // locate the heap region nodes in this ownership graph
546 // that should be aged. The process models the allocation
547 // of new objects and collects all the oldest allocations
548 // in a summary node to allow for a finite analysis
550 // There is an additional property of this method. After
551 // running it on a particular ownership graph (many graphs
552 // may have heap regions related to the same allocation site)
553 // the heap region node objects in this ownership graph will be
554 // allocated. Therefore, after aging a graph for an allocation
555 // site, attempts to retrieve the heap region nodes using the
556 // integer id's contained in the allocation site should always
557 // return non-null heap regions.
558 public void age( AllocationSite as ) {
560 // aging adds this allocation site to the graph's
561 // list of sites that exist in the graph, or does
562 // nothing if the site is already in the list
563 allocationSites.add( as );
565 // get the summary node for the allocation site in the context
566 // of this particular ownership graph
567 HeapRegionNode hrnSummary = getSummaryNode( as );
569 // merge oldest node into summary
570 Integer idK = as.getOldest();
571 HeapRegionNode hrnK = id2hrn.get( idK );
572 mergeIntoSummary( hrnK, hrnSummary );
574 // move down the line of heap region nodes
575 // clobbering the ith and transferring all references
576 // to and from i-1 to node i. Note that this clobbers
577 // the oldest node (hrnK) that was just merged into
579 for( int i = allocationDepth - 1; i > 0; --i ) {
581 // move references from the i-1 oldest to the ith oldest
582 Integer idIth = as.getIthOldest( i );
583 HeapRegionNode hrnI = id2hrn.get( idIth );
584 Integer idImin1th = as.getIthOldest( i - 1 );
585 HeapRegionNode hrnImin1 = id2hrn.get( idImin1th );
587 transferOnto( hrnImin1, hrnI );
590 // as stated above, the newest node should have had its
591 // references moved over to the second oldest, so we wipe newest
592 // in preparation for being the new object to assign something to
593 Integer id0th = as.getIthOldest( 0 );
594 HeapRegionNode hrn0 = id2hrn.get( id0th );
597 // clear all references in and out of newest node
598 clearReferenceEdgesFrom( hrn0 );
599 clearReferenceEdgesTo ( hrn0 );
602 // now tokens in reachability sets need to "age" also
603 ReferenceEdgeProperties repToAge = null;
604 Iterator itrAllLabelNodes = td2ln.entrySet().iterator();
605 while( itrAllLabelNodes.hasNext() ) {
606 Map.Entry me = (Map.Entry) itrAllLabelNodes.next();
607 LabelNode ln = (LabelNode) me.getValue();
609 Iterator itrEdges = ln.setIteratorToReferencedRegions();
610 while( itrEdges.hasNext() ) {
611 Map.Entry meE = (Map.Entry) itrEdges.next();
612 repToAge = (ReferenceEdgeProperties) meE.getValue();
614 ageTokens( as, repToAge );
617 HeapRegionNode hrnToAge = null;
618 Iterator itrAllHRNodes = id2hrn.entrySet().iterator();
619 while( itrAllHRNodes.hasNext() ) {
620 Map.Entry me = (Map.Entry) itrAllHRNodes.next();
621 hrnToAge = (HeapRegionNode) me.getValue();
623 ageTokens( as, hrnToAge );
625 Iterator itrEdges = hrnToAge.setIteratorToReferencedRegions();
626 while( itrEdges.hasNext() ) {
627 Map.Entry meE = (Map.Entry) itrEdges.next();
628 repToAge = (ReferenceEdgeProperties) meE.getValue();
630 ageTokens( as, repToAge );
635 // after tokens have been aged, reset newest node's reachability
636 hrn0.setAlpha( new ReachabilitySet(
638 new TokenTuple( hrn0 )
645 protected HeapRegionNode getSummaryNode( AllocationSite as ) {
647 Integer idSummary = as.getSummary();
648 HeapRegionNode hrnSummary = id2hrn.get( idSummary );
650 // If this is null then we haven't touched this allocation site
651 // in the context of the current ownership graph, so allocate
652 // heap region nodes appropriate for the entire allocation site.
653 // This should only happen once per ownership graph per allocation site,
654 // and a particular integer id can be used to locate the heap region
655 // in different ownership graphs that represents the same part of an
657 if( hrnSummary == null ) {
659 boolean hasFlags = false;
660 if( as.getType().isClass() ) {
661 hasFlags = as.getType().getClassDesc().hasFlags();
664 hrnSummary = createNewHeapRegionNode( idSummary,
671 as + "\\n" + as.getType() + "\\nsummary" );
673 for( int i = 0; i < as.getAllocationDepth(); ++i ) {
674 Integer idIth = as.getIthOldest( i );
675 assert !id2hrn.containsKey( idIth );
676 createNewHeapRegionNode( idIth,
683 as + "\\n" + as.getType() + "\\n" + i + " oldest" );
691 protected HeapRegionNode getShadowSummaryNode( AllocationSite as ) {
693 Integer idShadowSummary = -(as.getSummary());
694 HeapRegionNode hrnShadowSummary = id2hrn.get( idShadowSummary );
696 if( hrnShadowSummary == null ) {
698 boolean hasFlags = false;
699 if( as.getType().isClass() ) {
700 hasFlags = as.getType().getClassDesc().hasFlags();
703 hrnShadowSummary = createNewHeapRegionNode( idShadowSummary,
710 as + "\\n" + as.getType() + "\\nshadowSum" );
712 for( int i = 0; i < as.getAllocationDepth(); ++i ) {
713 Integer idShadowIth = -(as.getIthOldest( i ));
714 assert !id2hrn.containsKey( idShadowIth );
715 createNewHeapRegionNode( idShadowIth,
722 as + "\\n" + as.getType() + "\\n" + i + " shadow" );
726 return hrnShadowSummary;
730 protected void mergeIntoSummary( HeapRegionNode hrn, HeapRegionNode hrnSummary ) {
731 assert hrnSummary.isNewSummary();
733 // transfer references _from_ hrn over to hrnSummary
734 HeapRegionNode hrnReferencee = null;
735 Iterator itrReferencee = hrn.setIteratorToReferencedRegions();
736 while( itrReferencee.hasNext() ) {
737 Map.Entry me = (Map.Entry) itrReferencee.next();
738 hrnReferencee = (HeapRegionNode) me.getKey();
739 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
741 ReferenceEdgeProperties repSummary = hrnSummary.getReferenceTo( hrnReferencee );
742 ReferenceEdgeProperties repMerged = rep.copy();
744 if( repSummary == null ) {
745 // the merge is trivial, nothing to be done
747 // otherwise an edge from the referencer to hrnSummary exists already
748 // and the edge referencer->hrn should be merged with it
749 repMerged.setBeta( repMerged.getBeta().union( repSummary.getBeta() ) );
752 addReferenceEdge( hrnSummary, hrnReferencee, repMerged );
755 // next transfer references _to_ hrn over to hrnSummary
756 OwnershipNode onReferencer = null;
757 Iterator itrReferencer = hrn.iteratorToReferencers();
758 while( itrReferencer.hasNext() ) {
759 onReferencer = (OwnershipNode) itrReferencer.next();
761 ReferenceEdgeProperties rep = onReferencer.getReferenceTo( hrn );
763 ReferenceEdgeProperties repSummary = onReferencer.getReferenceTo( hrnSummary );
764 ReferenceEdgeProperties repMerged = rep.copy();
766 if( repSummary == null ) {
767 // the merge is trivial, nothing to be done
769 // otherwise an edge from the referencer to alpha_S exists already
770 // and the edge referencer->alpha_K should be merged with it
771 repMerged.setBeta( repMerged.getBeta().union( repSummary.getBeta() ) );
774 addReferenceEdge( onReferencer, hrnSummary, repMerged );
777 // then merge hrn reachability into hrnSummary
778 hrnSummary.setAlpha( hrnSummary.getAlpha().union( hrn.getAlpha() ) );
782 protected void transferOnto( HeapRegionNode hrnA, HeapRegionNode hrnB ) {
784 // clear references in and out of node i
785 clearReferenceEdgesFrom( hrnB );
786 clearReferenceEdgesTo ( hrnB );
788 // copy each edge in and out of A to B
789 HeapRegionNode hrnReferencee = null;
790 Iterator itrReferencee = hrnA.setIteratorToReferencedRegions();
791 while( itrReferencee.hasNext() ) {
792 Map.Entry me = (Map.Entry) itrReferencee.next();
793 hrnReferencee = (HeapRegionNode) me.getKey();
794 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
796 addReferenceEdge( hrnB, hrnReferencee, rep.copy() );
799 OwnershipNode onReferencer = null;
800 Iterator itrReferencer = hrnA.iteratorToReferencers();
801 while( itrReferencer.hasNext() ) {
802 onReferencer = (OwnershipNode) itrReferencer.next();
804 ReferenceEdgeProperties rep = onReferencer.getReferenceTo( hrnA );
807 addReferenceEdge( onReferencer, hrnB, rep.copy() );
810 // replace hrnB reachability with hrnA's
811 hrnB.setAlpha( hrnA.getAlpha() );
815 protected void ageTokens( AllocationSite as, ReferenceEdgeProperties rep ) {
816 rep.setBeta( rep.getBeta().ageTokens( as ) );
819 protected void ageTokens( AllocationSite as, HeapRegionNode hrn ) {
820 hrn.setAlpha( hrn.getAlpha().ageTokens( as ) );
823 protected void majorAgeTokens( AllocationSite as, ReferenceEdgeProperties rep ) {
824 //rep.setBeta( rep.getBeta().majorAgeTokens( as ) );
827 protected void majorAgeTokens( AllocationSite as, HeapRegionNode hrn ) {
828 //hrn.setAlpha( hrn.getAlpha().majorAgeTokens( as ) );
833 // the heap regions that are specially allocated as multiple-object
834 // regions for method parameters need to be remembered in order to
835 // resolve a function call. So actually, we need a mapping from
836 // caller argument descriptors to the callee parameter heap regions
837 // to apply reference edges in the callee to the caller graph.
839 // also, Constructors and virtual dispatch methods have a "this"
840 // argument that make the mapping of arguments to parameters a little
841 // tricky. What happens to that this region?
844 public void resolveMethodCall( FlatCall fc,
847 OwnershipGraph ogCallee ) {
850 // verify the existence of allocation sites and their
851 // shadows from the callee in the context of this caller graph
852 Iterator<AllocationSite> asItr = ogCallee.allocationSites.iterator();
853 while( asItr.hasNext() ) {
854 AllocationSite allocSite = asItr.next();
855 HeapRegionNode hrnSummary = getSummaryNode ( allocSite );
856 HeapRegionNode hrnShadowSummary = getShadowSummaryNode( allocSite );
859 // in non-static methods there is a "this" pointer
860 // that should be taken into account
862 assert fc.numArgs() == fm.numParameters();
864 assert fc.numArgs() + 1 == fm.numParameters();
867 // make a change set to translate callee tokens into caller tokens
868 ChangeTupleSet C = new ChangeTupleSet().makeCanonical();
870 for( int i = 0; i < fm.numParameters(); ++i ) {
872 Integer indexParam = new Integer( i );
874 System.out.println( "In method "+fm+ " on param "+indexParam );
876 assert ogCallee.paramIndex2id.containsKey( indexParam );
877 Integer idParam = ogCallee.paramIndex2id.get( indexParam );
879 assert ogCallee.id2hrn.containsKey( idParam );
880 HeapRegionNode hrnParam = ogCallee.id2hrn.get( idParam );
881 assert hrnParam != null;
883 TokenTupleSet calleeTokenToMatch =
884 new TokenTupleSet( new TokenTuple( hrnParam ) ).makeCanonical();
887 // now depending on whether the callee is static or not
888 // we need to account for a "this" argument in order to
889 // find the matching argument in the caller context
890 TempDescriptor argTemp;
892 argTemp = fc.getArg( indexParam );
894 if( indexParam == 0 ) {
895 argTemp = fc.getThis();
897 argTemp = fc.getArg( indexParam - 1 );
901 LabelNode argLabel = getLabelNodeFromTemp( argTemp );
902 Iterator argHeapRegionsItr = argLabel.setIteratorToReferencedRegions();
903 while( argHeapRegionsItr.hasNext() ) {
904 Map.Entry meArg = (Map.Entry) argHeapRegionsItr.next();
905 HeapRegionNode argHeapRegion = (HeapRegionNode) meArg.getKey();
906 ReferenceEdgeProperties repArg = (ReferenceEdgeProperties) meArg.getValue();
908 Iterator<TokenTupleSet> ttsItr = repArg.getBeta().iterator();
909 while( ttsItr.hasNext() ) {
910 TokenTupleSet callerTokensToReplace = ttsItr.next();
912 ChangeTuple ct = new ChangeTuple( calleeTokenToMatch,
913 callerTokensToReplace ).makeCanonical();
920 System.out.println( "Applying method call "+fm );
921 System.out.println( " Change: "+C );
924 // the heap regions represented by the arguments (caller graph)
925 // and heap regions for the parameters (callee graph)
926 // don't correspond to each other by heap region ID. In fact,
927 // an argument label node can be referencing several heap regions
928 // so the parameter label always references a multiple-object
929 // heap region in order to handle the range of possible contexts
930 // for a method call. This means we need to make a special mapping
931 // of argument->parameter regions in order to update the caller graph
933 // for every heap region->heap region edge in the
934 // callee graph, create the matching edge or edges
935 // in the caller graph
936 Set sCallee = ogCallee.id2hrn.entrySet();
937 Iterator iCallee = sCallee.iterator();
938 while( iCallee.hasNext() ) {
939 Map.Entry meCallee = (Map.Entry) iCallee.next();
940 Integer idCallee = (Integer) meCallee.getKey();
941 HeapRegionNode hrnCallee = (HeapRegionNode) meCallee.getValue();
943 HeapRegionNode hrnChildCallee = null;
944 Iterator heapRegionsItrCallee = hrnCallee.setIteratorToReferencedRegions();
945 while( heapRegionsItrCallee.hasNext() ) {
946 Map.Entry me = (Map.Entry) heapRegionsItrCallee.next();
947 hrnChildCallee = (HeapRegionNode) me.getKey();
948 ReferenceEdgeProperties repC = (ReferenceEdgeProperties) me.getValue();
950 Integer idChildCallee = hrnChildCallee.getID();
952 // only address this edge if it is not a special reflexive edge
953 if( !repC.isInitialParamReflexive() ) {
955 // now we know that in the callee method's ownership graph
956 // there is a heap region->heap region reference edge given
957 // by heap region pointers:
958 // hrnCallee -> heapChildCallee
960 // or by the ownership-graph independent ID's:
961 // idCallee -> idChildCallee
963 // So now make a set of possible source heaps in the caller graph
964 // and a set of destination heaps in the caller graph, and make
965 // a reference edge in the caller for every possible (src,dst) pair
966 HashSet<HeapRegionNode> possibleCallerSrcs =
967 getHRNSetThatPossiblyMapToCalleeHRN( ogCallee,
972 HashSet<HeapRegionNode> possibleCallerDsts =
973 getHRNSetThatPossiblyMapToCalleeHRN( ogCallee,
978 // make every possible pair of {srcSet} -> {dstSet} edges in the caller
979 Iterator srcItr = possibleCallerSrcs.iterator();
980 while( srcItr.hasNext() ) {
981 HeapRegionNode src = (HeapRegionNode) srcItr.next();
983 Iterator dstItr = possibleCallerDsts.iterator();
984 while( dstItr.hasNext() ) {
985 HeapRegionNode dst = (HeapRegionNode) dstItr.next();
987 addReferenceEdge( src, dst, repC.copy() );
997 private HashSet<HeapRegionNode> getHRNSetThatPossiblyMapToCalleeHRN( OwnershipGraph ogCallee,
1000 boolean isStatic ) {
1002 HashSet<HeapRegionNode> possibleCallerHRNs = new HashSet<HeapRegionNode>();
1004 if( ogCallee.id2paramIndex.containsKey( idCallee ) ) {
1005 // the heap region that is part of this
1006 // reference edge won't have a matching ID in the
1007 // caller graph because it is specifically allocated
1008 // for a particular parameter. Use that information
1009 // to find the corresponding argument label in the
1010 // caller in order to create the proper reference edge
1012 assert !id2hrn.containsKey( idCallee );
1014 Integer paramIndex = ogCallee.id2paramIndex.get( idCallee );
1015 TempDescriptor argTemp;
1017 // now depending on whether the callee is static or not
1018 // we need to account for a "this" argument in order to
1019 // find the matching argument in the caller context
1021 argTemp = fc.getArg( paramIndex );
1023 if( paramIndex == 0 ) {
1024 argTemp = fc.getThis();
1026 argTemp = fc.getArg( paramIndex - 1 );
1030 LabelNode argLabel = getLabelNodeFromTemp( argTemp );
1031 Iterator argHeapRegionsItr = argLabel.setIteratorToReferencedRegions();
1032 while( argHeapRegionsItr.hasNext() ) {
1033 Map.Entry meArg = (Map.Entry) argHeapRegionsItr.next();
1034 HeapRegionNode argHeapRegion = (HeapRegionNode) meArg.getKey();
1035 ReferenceEdgeProperties repArg = (ReferenceEdgeProperties) meArg.getValue();
1037 possibleCallerHRNs.add( (HeapRegionNode) argHeapRegion );
1041 // this heap region is not a parameter, so it should
1042 // have a matching heap region in the caller graph
1043 assert id2hrn.containsKey( idCallee );
1044 possibleCallerHRNs.add( id2hrn.get( idCallee ) );
1047 return possibleCallerHRNs;
1052 ////////////////////////////////////////////////////
1053 // in merge() and equals() methods the suffix A
1054 // represents the passed in graph and the suffix
1055 // B refers to the graph in this object
1056 // Merging means to take the incoming graph A and
1057 // merge it into B, so after the operation graph B
1058 // is the final result.
1059 ////////////////////////////////////////////////////
1060 public void merge( OwnershipGraph og ) {
1066 mergeOwnershipNodes ( og );
1067 mergeReferenceEdges ( og );
1068 mergeId2paramIndex ( og );
1069 mergeAllocationSites( og );
1073 protected void mergeOwnershipNodes( OwnershipGraph og ) {
1074 Set sA = og.id2hrn.entrySet();
1075 Iterator iA = sA.iterator();
1076 while( iA.hasNext() ) {
1077 Map.Entry meA = (Map.Entry) iA.next();
1078 Integer idA = (Integer) meA.getKey();
1079 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1081 // if this graph doesn't have a node the
1082 // incoming graph has, allocate it
1083 if( !id2hrn.containsKey( idA ) ) {
1084 HeapRegionNode hrnB = hrnA.copy();
1085 id2hrn.put( idA, hrnB );
1088 // otherwise this is a node present in both graphs
1089 // so make the new reachability set a union of the
1090 // nodes' reachability sets
1091 HeapRegionNode hrnB = id2hrn.get( idA );
1092 hrnB.setAlpha( hrnB.getAlpha().union( hrnA.getAlpha() ) );
1096 // now add any label nodes that are in graph B but
1098 sA = og.td2ln.entrySet();
1100 while( iA.hasNext() ) {
1101 Map.Entry meA = (Map.Entry) iA.next();
1102 TempDescriptor tdA = (TempDescriptor) meA.getKey();
1103 LabelNode lnA = (LabelNode) meA.getValue();
1105 // if the label doesn't exist in B, allocate and add it
1106 LabelNode lnB = getLabelNodeFromTemp( tdA );
1110 protected void mergeReferenceEdges( OwnershipGraph og ) {
1111 // there is a data structure for storing label nodes
1112 // retireved by temp descriptors, and a data structure
1113 // for stroing heap region nodes retrieved by integer
1114 // ids. Because finding edges requires interacting
1115 // with these disparate data structures frequently the
1116 // process is nearly duplicated, one for each structure
1117 // that stores edges
1120 Set sA = og.id2hrn.entrySet();
1121 Iterator iA = sA.iterator();
1122 while( iA.hasNext() ) {
1123 Map.Entry meA = (Map.Entry) iA.next();
1124 Integer idA = (Integer) meA.getKey();
1125 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1127 HeapRegionNode hrnChildA = null;
1128 Iterator heapRegionsItrA = hrnA.setIteratorToReferencedRegions();
1129 while( heapRegionsItrA.hasNext() ) {
1130 Map.Entry me = (Map.Entry) heapRegionsItrA.next();
1131 hrnChildA = (HeapRegionNode) me.getKey();
1132 ReferenceEdgeProperties repA = (ReferenceEdgeProperties) me.getValue();
1134 Integer idChildA = hrnChildA.getID();
1136 // at this point we know an edge in graph A exists
1137 // idA -> idChildA, does this exist in B?
1138 boolean edgeFound = false;
1139 assert id2hrn.containsKey( idA );
1140 HeapRegionNode hrnB = id2hrn.get( idA );
1142 HeapRegionNode hrnChildB = null;
1143 ReferenceEdgeProperties repB = null;
1144 Iterator heapRegionsItrB = hrnB.setIteratorToReferencedRegions();
1145 while( heapRegionsItrB.hasNext() ) {
1146 Map.Entry meC = (Map.Entry) heapRegionsItrB.next();
1147 hrnChildB = (HeapRegionNode) meC.getKey();
1148 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) meC.getValue();
1150 if( hrnChildB.equals( idChildA ) ) {
1156 // if the edge from A was not found in B,
1159 assert id2hrn.containsKey( idChildA );
1160 hrnChildB = id2hrn.get( idChildA );
1162 addReferenceEdge( hrnB, hrnChildB, repB );
1164 // otherwise, the edge already existed in both graphs
1165 // so merge their reachability sets
1167 // just replace this beta set with the union
1168 assert repB != null;
1169 repB.setBeta( repB.getBeta().union( repA.getBeta() ) );
1174 // and then again with label nodes
1175 sA = og.td2ln.entrySet();
1177 while( iA.hasNext() ) {
1178 Map.Entry meA = (Map.Entry) iA.next();
1179 TempDescriptor tdA = (TempDescriptor) meA.getKey();
1180 LabelNode lnA = (LabelNode) meA.getValue();
1182 HeapRegionNode hrnChildA = null;
1183 Iterator heapRegionsItrA = lnA.setIteratorToReferencedRegions();
1184 while( heapRegionsItrA.hasNext() ) {
1185 Map.Entry meH = (Map.Entry) heapRegionsItrA.next();
1186 hrnChildA = (HeapRegionNode) meH.getKey();
1187 ReferenceEdgeProperties repA = (ReferenceEdgeProperties) meH.getValue();
1189 Integer idChildA = hrnChildA.getID();
1191 // at this point we know an edge in graph A exists
1192 // tdA -> idChildA, does this exist in B?
1193 boolean edgeFound = false;
1194 assert td2ln.containsKey( tdA );
1195 LabelNode lnB = td2ln.get( tdA );
1197 HeapRegionNode hrnChildB = null;
1198 ReferenceEdgeProperties repB = null;
1199 Iterator heapRegionsItrB = lnB.setIteratorToReferencedRegions();
1200 while( heapRegionsItrB.hasNext() ) {
1201 Map.Entry meC = (Map.Entry) heapRegionsItrB.next();
1202 hrnChildB = (HeapRegionNode) meC.getKey();
1203 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) meC.getValue();
1205 if( hrnChildB.equals( idChildA ) ) {
1211 // if the edge from A was not found in B,
1214 assert id2hrn.containsKey( idChildA );
1215 hrnChildB = id2hrn.get( idChildA );
1217 addReferenceEdge( lnB, hrnChildB, repB );
1219 // otherwise, the edge already existed in both graphs
1220 // so merge the reachability sets
1222 // just replace this beta set with the union
1223 assert repB != null;
1224 repB.setBeta( repB.getBeta().union( repA.getBeta() ) );
1230 // you should only merge ownership graphs that have the
1231 // same number of parameters, or if one or both parameter
1232 // index tables are empty
1233 protected void mergeId2paramIndex( OwnershipGraph og ) {
1234 if( id2paramIndex.size() == 0 ) {
1235 id2paramIndex = og.id2paramIndex;
1236 paramIndex2id = og.paramIndex2id;
1240 if( og.id2paramIndex.size() == 0 ) {
1244 assert id2paramIndex.size() == og.id2paramIndex.size();
1247 protected void mergeAllocationSites( OwnershipGraph og ) {
1248 allocationSites.addAll( og.allocationSites );
1253 // it is necessary in the equals() member functions
1254 // to "check both ways" when comparing the data
1255 // structures of two graphs. For instance, if all
1256 // edges between heap region nodes in graph A are
1257 // present and equal in graph B it is not sufficient
1258 // to say the graphs are equal. Consider that there
1259 // may be edges in graph B that are not in graph A.
1260 // the only way to know that all edges in both graphs
1261 // are equally present is to iterate over both data
1262 // structures and compare against the other graph.
1263 public boolean equals( OwnershipGraph og ) {
1269 if( !areHeapRegionNodesEqual( og ) ) {
1273 if( !areHeapRegionToHeapRegionEdgesEqual( og ) ) {
1277 if( !areLabelNodesEqual( og ) ) {
1281 if( !areLabelToHeapRegionEdgesEqual( og ) ) {
1285 if( !areId2paramIndexEqual( og ) ) {
1289 // if everything is equal up to this point,
1290 // assert that allocationSites is also equal--
1291 // this data is redundant and kept for efficiency
1292 assert allocationSites.equals( og.allocationSites );
1297 protected boolean areHeapRegionNodesEqual( OwnershipGraph og ) {
1298 // check all nodes in A for presence in graph B
1299 Set sA = og.id2hrn.entrySet();
1300 Iterator iA = sA.iterator();
1301 while( iA.hasNext() ) {
1302 Map.Entry meA = (Map.Entry) iA.next();
1303 Integer idA = (Integer) meA.getKey();
1304 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1306 if( !id2hrn.containsKey( idA ) ) {
1310 //HeapRegionNode hrnB = og.id2hrn.get( idA );
1311 HeapRegionNode hrnB = id2hrn.get( idA );
1312 if( !hrnA.equals( hrnB ) ) {
1317 // then check all nodes in B verses graph A
1318 Set sB = id2hrn.entrySet();
1319 Iterator iB = sB.iterator();
1320 while( iB.hasNext() ) {
1321 Map.Entry meB = (Map.Entry) iB.next();
1322 Integer idB = (Integer) meB.getKey();
1323 HeapRegionNode hrnB = (HeapRegionNode) meB.getValue();
1325 if( !og.id2hrn.containsKey( idB ) ) {
1329 // we should have already checked the equality
1330 // of this pairing in the last pass if they both
1331 // exist so assert that they are equal now
1332 HeapRegionNode hrnA = og.id2hrn.get( idB );
1333 assert hrnB.equals( hrnA );
1339 protected boolean areHeapRegionToHeapRegionEdgesEqual( OwnershipGraph og ) {
1340 Set sA = og.id2hrn.entrySet();
1341 Iterator iA = sA.iterator();
1342 while( iA.hasNext() ) {
1343 Map.Entry meA = (Map.Entry) iA.next();
1344 Integer idA = (Integer) meA.getKey();
1345 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1347 // we should have already checked that the same
1348 // heap regions exist in both graphs
1349 assert id2hrn.containsKey( idA );
1351 // and are their edges the same? first check every
1352 // edge in A for presence and equality in B
1353 HeapRegionNode hrnChildA = null;
1354 Iterator heapRegionsItrA = hrnA.setIteratorToReferencedRegions();
1355 while( heapRegionsItrA.hasNext() ) {
1356 Map.Entry me = (Map.Entry) heapRegionsItrA.next();
1357 hrnChildA = (HeapRegionNode) me.getKey();
1358 ReferenceEdgeProperties repA = (ReferenceEdgeProperties) me.getValue();
1360 Integer idChildA = hrnChildA.getID();
1361 assert id2hrn.containsKey( idChildA );
1363 // at this point we know an edge in graph A exists
1364 // idA -> idChildA, does this edge exist in B?
1365 boolean edgeFound = false;
1366 HeapRegionNode hrnB = id2hrn.get( idA );
1368 HeapRegionNode hrnChildB = null;
1369 Iterator heapRegionsItrB = hrnB.setIteratorToReferencedRegions();
1370 while( heapRegionsItrB.hasNext() ) {
1371 Map.Entry meH = (Map.Entry) heapRegionsItrB.next();
1372 hrnChildB = (HeapRegionNode) meH.getKey();
1373 ReferenceEdgeProperties repB = (ReferenceEdgeProperties) meH.getValue();
1375 if( idChildA.equals( hrnChildB.getID() ) ) {
1376 if( !repA.equals( repB ) ) {
1388 // then check every edge in B for presence in A, starting
1389 // from the same parent HeapRegionNode
1390 HeapRegionNode hrnB = id2hrn.get( idA );
1392 HeapRegionNode hrnChildB = null;
1393 Iterator heapRegionsItrB = hrnB.setIteratorToReferencedRegions();
1394 while( heapRegionsItrB.hasNext() ) {
1395 Map.Entry me = (Map.Entry) heapRegionsItrB.next();
1396 hrnChildB = (HeapRegionNode) me.getKey();
1397 ReferenceEdgeProperties repB = (ReferenceEdgeProperties) me.getValue();
1399 Integer idChildB = hrnChildB.getID();
1401 // at this point we know an edge in graph B exists
1402 // idB -> idChildB, does this edge exist in A?
1403 boolean edgeFound = false;
1406 heapRegionsItrA = hrnA.setIteratorToReferencedRegions();
1407 while( heapRegionsItrA.hasNext() ) {
1408 Map.Entry meH = (Map.Entry) heapRegionsItrA.next();
1409 hrnChildA = (HeapRegionNode) meH.getKey();
1410 ReferenceEdgeProperties repA = (ReferenceEdgeProperties) meH.getValue();
1412 if( idChildB.equals( hrnChildA.getID() ) ) {
1413 assert repB.equals( repA );
1427 protected boolean areLabelNodesEqual( OwnershipGraph og ) {
1428 // are all label nodes in A also in graph B?
1429 Set sA = og.td2ln.entrySet();
1430 Iterator iA = sA.iterator();
1431 while( iA.hasNext() ) {
1432 Map.Entry meA = (Map.Entry) iA.next();
1433 TempDescriptor tdA = (TempDescriptor) meA.getKey();
1435 if( !td2ln.containsKey( tdA ) ) {
1440 // are all label nodes in B also in A?
1441 Set sB = td2ln.entrySet();
1442 Iterator iB = sB.iterator();
1443 while( iB.hasNext() ) {
1444 Map.Entry meB = (Map.Entry) iB.next();
1445 TempDescriptor tdB = (TempDescriptor) meB.getKey();
1447 if( !og.td2ln.containsKey( tdB ) ) {
1455 protected boolean areLabelToHeapRegionEdgesEqual( OwnershipGraph og ) {
1456 Set sA = og.td2ln.entrySet();
1457 Iterator iA = sA.iterator();
1458 while( iA.hasNext() ) {
1459 Map.Entry meA = (Map.Entry) iA.next();
1460 TempDescriptor tdA = (TempDescriptor) meA.getKey();
1461 LabelNode lnA = (LabelNode) meA.getValue();
1463 // we should have already checked that the same
1464 // label nodes exist in both graphs
1465 assert td2ln.containsKey( tdA );
1467 // and are their edges the same? first check every
1468 // edge in A for presence and equality in B
1469 HeapRegionNode hrnChildA = null;
1470 Iterator heapRegionsItrA = lnA.setIteratorToReferencedRegions();
1471 while( heapRegionsItrA.hasNext() ) {
1472 Map.Entry me = (Map.Entry) heapRegionsItrA.next();
1473 hrnChildA = (HeapRegionNode) me.getKey();
1474 ReferenceEdgeProperties repA = (ReferenceEdgeProperties) me.getValue();
1476 Integer idChildA = hrnChildA.getID();
1477 assert id2hrn.containsKey( idChildA );
1479 // at this point we know an edge in graph A exists
1480 // tdA -> idChildA, does this edge exist in B?
1481 boolean edgeFound = false;
1482 LabelNode lnB = td2ln.get( tdA );
1484 HeapRegionNode hrnChildB = null;
1485 Iterator heapRegionsItrB = lnB.setIteratorToReferencedRegions();
1486 while( heapRegionsItrB.hasNext() ) {
1487 Map.Entry meH = (Map.Entry) heapRegionsItrB.next();
1488 hrnChildB = (HeapRegionNode) meH.getKey();
1489 ReferenceEdgeProperties repB = (ReferenceEdgeProperties) meH.getValue();
1491 if( idChildA.equals( hrnChildB.getID() ) ) {
1492 if( !repA.equals( repB ) ) {
1504 // then check every edge in B for presence in A, starting
1505 // from the same parent LabelNode
1506 LabelNode lnB = td2ln.get( tdA );
1508 HeapRegionNode hrnChildB = null;
1509 Iterator heapRegionsItrB = lnB.setIteratorToReferencedRegions();
1510 while( heapRegionsItrB.hasNext() ) {
1511 Map.Entry me = (Map.Entry) heapRegionsItrB.next();
1512 hrnChildB = (HeapRegionNode) me.getKey();
1513 ReferenceEdgeProperties repB = (ReferenceEdgeProperties) me.getValue();
1515 Integer idChildB = hrnChildB.getID();
1517 // at this point we know an edge in graph B exists
1518 // tdB -> idChildB, does this edge exist in A?
1519 boolean edgeFound = false;
1522 heapRegionsItrA = lnA.setIteratorToReferencedRegions();
1523 while( heapRegionsItrA.hasNext() ) {
1524 Map.Entry meH = (Map.Entry) heapRegionsItrA.next();
1525 hrnChildA = (HeapRegionNode) meH.getKey();
1526 ReferenceEdgeProperties repA = (ReferenceEdgeProperties) meH.getValue();
1528 if( idChildB.equals( hrnChildA.getID() ) ) {
1529 assert repB.equals( repA );
1544 protected boolean areId2paramIndexEqual( OwnershipGraph og ) {
1545 return id2paramIndex.size() == og.id2paramIndex.size();
1550 // given a set B of heap region node ID's, return the set of heap
1551 // region node ID's that is reachable from B
1552 public HashSet<Integer> getReachableSet( HashSet<Integer> idSetB ) {
1554 HashSet<HeapRegionNode> toVisit = new HashSet<HeapRegionNode>();
1555 HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
1557 // initial nodes to visit are from set B
1558 Iterator initialItr = idSetB.iterator();
1559 while( initialItr.hasNext() ) {
1560 Integer idInitial = (Integer) initialItr.next();
1561 assert id2hrn.contains( idInitial );
1562 HeapRegionNode hrnInitial = id2hrn.get( idInitial );
1563 toVisit.add( hrnInitial );
1566 HashSet<Integer> idSetReachableFromB = new HashSet<Integer>();
1568 // do a heap traversal
1569 while( !toVisit.isEmpty() ) {
1570 HeapRegionNode hrnVisited = (HeapRegionNode) toVisit.iterator().next();
1571 toVisit.remove( hrnVisited );
1572 visited.add ( hrnVisited );
1574 // for every node visited, add it to the total
1576 idSetReachableFromB.add( hrnVisited.getID() );
1578 // find other reachable nodes
1579 Iterator referenceeItr = hrnVisited.setIteratorToReferencedRegions();
1580 while( referenceeItr.hasNext() ) {
1581 Map.Entry me = (Map.Entry) referenceeItr.next();
1582 HeapRegionNode hrnReferencee = (HeapRegionNode) me.getKey();
1583 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
1585 if( !visited.contains( hrnReferencee ) ) {
1586 toVisit.add( hrnReferencee );
1591 return idSetReachableFromB;
1595 // used to find if a heap region can possibly have a reference to
1596 // any of the heap regions in the given set
1597 // if the id supplied is in the set, then a self-referencing edge
1598 // would return true, but that special case is specifically allowed
1599 // meaning that it isn't an external alias
1600 public boolean canIdReachSet( Integer id, HashSet<Integer> idSet ) {
1602 assert id2hrn.contains( id );
1603 HeapRegionNode hrn = id2hrn.get( id );
1606 HashSet<HeapRegionNode> hrnSet = new HashSet<HeapRegionNode>();
1608 Iterator i = idSet.iterator();
1609 while( i.hasNext() ) {
1610 Integer idFromSet = (Integer) i.next();
1611 assert id2hrn.contains( idFromSet );
1612 hrnSet.add( id2hrn.get( idFromSet ) );
1616 // do a traversal from hrn and see if any of the
1617 // heap regions from the set come up during that
1618 HashSet<HeapRegionNode> toVisit = new HashSet<HeapRegionNode>();
1619 HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
1622 while( !toVisit.isEmpty() ) {
1623 HeapRegionNode hrnVisited = (HeapRegionNode) toVisit.iterator().next();
1624 toVisit.remove( hrnVisited );
1625 visited.add ( hrnVisited );
1627 Iterator referenceeItr = hrnVisited.setIteratorToReferencedRegions();
1628 while( referenceeItr.hasNext() ) {
1629 Map.Entry me = (Map.Entry) referenceeItr.next();
1630 HeapRegionNode hrnReferencee = (HeapRegionNode) me.getKey();
1631 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
1633 if( idSet.contains( hrnReferencee.getID() ) ) {
1634 if( !id.equals( hrnReferencee.getID() ) ) {
1639 if( !visited.contains( hrnReferencee ) ) {
1640 toVisit.add( hrnReferencee );
1650 // for writing ownership graphs to dot files
1651 public void writeGraph( Descriptor methodDesc,
1653 boolean writeLabels,
1654 boolean labelSelect,
1655 boolean pruneGarbage,
1656 boolean writeReferencers
1657 ) throws java.io.IOException {
1659 methodDesc.getSymbol() +
1660 methodDesc.getNum() +
1669 public void writeGraph( Descriptor methodDesc,
1671 boolean writeLabels,
1672 boolean writeReferencers
1673 ) throws java.io.IOException {
1675 methodDesc.getSymbol() +
1676 methodDesc.getNum() +
1685 public void writeGraph( Descriptor methodDesc,
1686 boolean writeLabels,
1687 boolean writeReferencers
1688 ) throws java.io.IOException {
1690 methodDesc.getSymbol() +
1691 methodDesc.getNum() +
1700 public void writeGraph( Descriptor methodDesc,
1701 boolean writeLabels,
1702 boolean labelSelect,
1703 boolean pruneGarbage,
1704 boolean writeReferencers
1705 ) throws java.io.IOException {
1707 methodDesc.getSymbol() +
1708 methodDesc.getNum() +
1717 public void writeGraph( String graphName,
1718 boolean writeLabels,
1719 boolean labelSelect,
1720 boolean pruneGarbage,
1721 boolean writeReferencers
1722 ) throws java.io.IOException {
1724 // remove all non-word characters from the graph name so
1725 // the filename and identifier in dot don't cause errors
1726 graphName = graphName.replaceAll( "[\\W]", "" );
1728 BufferedWriter bw = new BufferedWriter( new FileWriter( graphName+".dot" ) );
1729 bw.write( "digraph "+graphName+" {\n" );
1730 //bw.write( " size=\"7.5,10\";\n" );
1732 HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
1734 // then visit every heap region node
1735 if( !pruneGarbage ) {
1736 Set s = id2hrn.entrySet();
1737 Iterator i = s.iterator();
1738 while( i.hasNext() ) {
1739 Map.Entry me = (Map.Entry) i.next();
1740 HeapRegionNode hrn = (HeapRegionNode) me.getValue();
1741 if( !visited.contains( hrn ) ) {
1742 traverseHeapRegionNodes( VISIT_HRN_WRITE_FULL,
1752 bw.write( " graphTitle[label=\""+graphName+"\",shape=box];\n" );
1755 // then visit every label node, useful for debugging
1757 Set s = td2ln.entrySet();
1758 Iterator i = s.iterator();
1759 while( i.hasNext() ) {
1760 Map.Entry me = (Map.Entry) i.next();
1761 LabelNode ln = (LabelNode) me.getValue();
1764 String labelStr = ln.getTempDescriptorString();
1765 if( labelStr.startsWith( "___temp" ) ||
1766 labelStr.startsWith( "___dst" ) ||
1767 labelStr.startsWith( "___srctmp" ) ||
1768 labelStr.startsWith( "___neverused" ) ) {
1773 HeapRegionNode hrn = null;
1774 Iterator heapRegionsItr = ln.setIteratorToReferencedRegions();
1775 while( heapRegionsItr.hasNext() ) {
1776 Map.Entry meH = (Map.Entry) heapRegionsItr.next();
1777 hrn = (HeapRegionNode) meH.getKey();
1778 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) meH.getValue();
1780 if( pruneGarbage && !visited.contains( hrn ) ) {
1781 traverseHeapRegionNodes( VISIT_HRN_WRITE_FULL,
1789 bw.write( " " + ln.toString() +
1790 " -> " + hrn.toString() +
1791 "[label=\"" + rep.toEdgeLabelString() +
1792 "\",decorate];\n" );
1802 protected void traverseHeapRegionNodes( int mode,
1806 HashSet<HeapRegionNode> visited,
1807 boolean writeReferencers
1808 ) throws java.io.IOException {
1810 if( visited.contains( hrn ) ) {
1816 case VISIT_HRN_WRITE_FULL:
1818 String attributes = "[";
1820 if( hrn.isSingleObject() ) {
1821 attributes += "shape=box";
1823 attributes += "shape=Msquare";
1826 if( hrn.isFlagged() ) {
1827 attributes += ",style=filled,fillcolor=lightgrey";
1830 attributes += ",label=\"ID" +
1833 hrn.getDescription() +
1835 hrn.getAlphaString() +
1838 bw.write( " " + hrn.toString() + attributes + ";\n" );
1843 // useful for debugging
1844 if( writeReferencers ) {
1845 OwnershipNode onRef = null;
1846 Iterator refItr = hrn.iteratorToReferencers();
1847 while( refItr.hasNext() ) {
1848 onRef = (OwnershipNode) refItr.next();
1851 case VISIT_HRN_WRITE_FULL:
1852 bw.write( " " + hrn.toString() +
1853 " -> " + onRef.toString() +
1854 "[color=lightgray];\n" );
1861 HeapRegionNode hrnChild = null;
1862 Iterator childRegionsItr = hrn.setIteratorToReferencedRegions();
1863 while( childRegionsItr.hasNext() ) {
1864 Map.Entry me = (Map.Entry) childRegionsItr.next();
1865 hrnChild = (HeapRegionNode) me.getKey();
1866 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
1869 case VISIT_HRN_WRITE_FULL:
1870 bw.write( " " + hrn.toString() +
1871 " -> " + hrnChild.toString() +
1872 "[label=\"" + rep.toEdgeLabelString() +
1873 "\",decorate];\n" );
1877 traverseHeapRegionNodes( mode,