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 ReferenceEdge edge ) {
113 assert referencer != null;
114 assert referencee != null;
116 assert edge.getSrc() == referencer;
117 assert edge.getDst() == referencee;
119 referencer.addReferencee( edge );
120 referencee.addReferencer( edge );
123 protected void removeReferenceEdge( OwnershipNode referencer,
124 HeapRegionNode referencee,
125 FieldDescriptor fieldDesc ) {
126 assert referencer != null;
127 assert referencee != null;
129 ReferenceEdge edge = referencer.getReferenceTo( referencee,
132 assert edge == referencee.getReferenceFrom( referencer,
135 referencer.removeReferencee( edge );
136 referencee.removeReferencer( edge );
139 protected void clearReferenceEdgesFrom( OwnershipNode referencer,
140 FieldDescriptor fieldDesc,
141 boolean removeAll ) {
142 assert referencer != null;
144 // get a copy of the set to iterate over, otherwise
145 // we will be trying to take apart the set as we
146 // are iterating over it, which won't work
147 Iterator<ReferenceEdge> i = referencer.iteratorToReferenceesClone();
148 while( i.hasNext() ) {
149 ReferenceEdge edge = i.next();
151 if( removeAll || edge.getFieldDesc() == fieldDesc ) {
152 HeapRegionNode referencee = edge.getDst();
154 removeReferenceEdge( referencer,
156 edge.getFieldDesc() );
161 protected void clearReferenceEdgesTo( HeapRegionNode referencee,
162 FieldDescriptor fieldDesc,
163 boolean removeAll ) {
164 assert referencee != null;
166 // get a copy of the set to iterate over, otherwise
167 // we will be trying to take apart the set as we
168 // are iterating over it, which won't work
169 Iterator<ReferenceEdge> i = referencee.iteratorToReferencersClone();
170 while( i.hasNext() ) {
171 ReferenceEdge edge = i.next();
173 if( removeAll || edge.getFieldDesc() == fieldDesc ) {
174 OwnershipNode referencer = edge.getSrc();
175 removeReferenceEdge( referencer,
177 edge.getFieldDesc() );
183 protected void propagateTokensOverNodes( HeapRegionNode nPrime,
185 HashSet<HeapRegionNode> nodesWithNewAlpha,
186 HashSet<ReferenceEdge> edgesWithNewBeta ) {
188 HashSet<HeapRegionNode> todoNodes
189 = new HashSet<HeapRegionNode>();
190 todoNodes.add( nPrime );
192 HashSet<ReferenceEdge> todoEdges
193 = new HashSet<ReferenceEdge>();
195 Hashtable<HeapRegionNode, ChangeTupleSet> nodePlannedChanges
196 = new Hashtable<HeapRegionNode, ChangeTupleSet>();
197 nodePlannedChanges.put( nPrime, c0 );
199 Hashtable<ReferenceEdge, ChangeTupleSet> edgePlannedChanges
200 = new Hashtable<ReferenceEdge, ChangeTupleSet>();
203 while( !todoNodes.isEmpty() ) {
204 HeapRegionNode n = todoNodes.iterator().next();
205 ChangeTupleSet C = nodePlannedChanges.get( n );
207 Iterator itrC = C.iterator();
208 while( itrC.hasNext() ) {
209 ChangeTuple c = (ChangeTuple) itrC.next();
211 if( n.getAlpha().contains( c.getSetToMatch() ) ) {
212 ReachabilitySet withChange = n.getAlpha().union( c.getSetToAdd() );
213 n.setAlphaNew( n.getAlphaNew().union( withChange ) );
214 nodesWithNewAlpha.add( n );
218 Iterator<ReferenceEdge> referItr = n.iteratorToReferencers();
219 while( referItr.hasNext() ) {
220 ReferenceEdge edge = referItr.next();
221 todoEdges.add( edge );
223 if( !edgePlannedChanges.containsKey( edge ) ) {
224 edgePlannedChanges.put( edge, new ChangeTupleSet().makeCanonical() );
227 edgePlannedChanges.put( edge, edgePlannedChanges.get( edge ).union( C ) );
230 Iterator<ReferenceEdge> refeeItr = n.iteratorToReferencees();
231 while( refeeItr.hasNext() ) {
232 ReferenceEdge edgeF = refeeItr.next();
233 HeapRegionNode m = edgeF.getDst();
235 ChangeTupleSet changesToPass = new ChangeTupleSet().makeCanonical();
237 Iterator<ChangeTuple> itrCprime = C.iterator();
238 while( itrCprime.hasNext() ) {
239 ChangeTuple c = itrCprime.next();
240 if( edgeF.getBeta().contains( c.getSetToMatch() ) ) {
241 changesToPass = changesToPass.union( c );
245 if( !changesToPass.isEmpty() ) {
246 if( !nodePlannedChanges.containsKey( m ) ) {
247 nodePlannedChanges.put( m, new ChangeTupleSet().makeCanonical() );
250 ChangeTupleSet currentChanges = nodePlannedChanges.get( m );
252 if( !changesToPass.isSubset( currentChanges ) ) {
254 nodePlannedChanges.put( m, currentChanges.union( changesToPass ) );
260 todoNodes.remove( n );
263 propagateTokensOverEdges( todoEdges, edgePlannedChanges, nodesWithNewAlpha, edgesWithNewBeta );
267 protected void propagateTokensOverEdges(
268 HashSet<ReferenceEdge> todoEdges,
269 Hashtable<ReferenceEdge, ChangeTupleSet> edgePlannedChanges,
270 HashSet<HeapRegionNode> nodesWithNewAlpha,
271 HashSet<ReferenceEdge> edgesWithNewBeta ) {
274 while( !todoEdges.isEmpty() ) {
275 ReferenceEdge edgeE = todoEdges.iterator().next();
276 todoEdges.remove( edgeE );
278 if( !edgePlannedChanges.containsKey( edgeE ) ) {
279 edgePlannedChanges.put( edgeE, new ChangeTupleSet().makeCanonical() );
282 ChangeTupleSet C = edgePlannedChanges.get( edgeE );
284 ChangeTupleSet changesToPass = new ChangeTupleSet().makeCanonical();
286 Iterator<ChangeTuple> itrC = C.iterator();
287 while( itrC.hasNext() ) {
288 ChangeTuple c = itrC.next();
289 if( edgeE.getBeta().contains( c.getSetToMatch() ) ) {
290 ReachabilitySet withChange = edgeE.getBeta().union( c.getSetToAdd() );
291 edgeE.setBetaNew( edgeE.getBetaNew().union( withChange ) );
292 edgesWithNewBeta.add( edgeE );
293 changesToPass = changesToPass.union( c );
297 OwnershipNode onSrc = edgeE.getSrc();
299 if( !changesToPass.isEmpty() && onSrc instanceof HeapRegionNode ) {
300 HeapRegionNode n = (HeapRegionNode) onSrc;
302 Iterator<ReferenceEdge> referItr = n.iteratorToReferencers();
303 while( referItr.hasNext() ) {
304 ReferenceEdge edgeF = referItr.next();
306 if( !edgePlannedChanges.containsKey( edgeF ) ) {
307 edgePlannedChanges.put( edgeF, new ChangeTupleSet().makeCanonical() );
310 ChangeTupleSet currentChanges = edgePlannedChanges.get( edgeF );
312 if( !changesToPass.isSubset( currentChanges ) ) {
313 todoEdges.add( edgeF );
314 edgePlannedChanges.put( edgeF, currentChanges.union( changesToPass ) );
322 ////////////////////////////////////////////////////
324 // Assignment Operation Methods
326 // These methods are high-level operations for
327 // modeling program assignment statements using
328 // the low-level reference create/remove methods
331 // The destination in an assignment statement is
332 // going to have new references. The method of
333 // determining the references depends on the type
334 // of the FlatNode assignment and the predicates
335 // of the nodes and edges involved.
337 ////////////////////////////////////////////////////
338 public void assignTempYToTempX( TempDescriptor y,
341 LabelNode lnX = getLabelNodeFromTemp( x );
342 LabelNode lnY = getLabelNodeFromTemp( y );
344 clearReferenceEdgesFrom( lnX, null, true );
346 Iterator<ReferenceEdge> itrYhrn = lnY.iteratorToReferencees();
347 while( itrYhrn.hasNext() ) {
348 ReferenceEdge edgeY = itrYhrn.next();
349 HeapRegionNode referencee = edgeY.getDst();
350 ReferenceEdge edgeNew = edgeY.copy();
351 edgeNew.setSrc( lnX );
353 addReferenceEdge( lnX, referencee, edgeNew );
358 public void assignTempYFieldFToTempX( TempDescriptor y,
362 LabelNode lnX = getLabelNodeFromTemp( x );
363 LabelNode lnY = getLabelNodeFromTemp( y );
365 clearReferenceEdgesFrom( lnX, null, true );
367 Iterator<ReferenceEdge> itrYhrn = lnY.iteratorToReferencees();
368 while( itrYhrn.hasNext() ) {
369 ReferenceEdge edgeY = itrYhrn.next();
370 HeapRegionNode hrnY = edgeY.getDst();
371 ReachabilitySet betaY = edgeY.getBeta();
373 Iterator<ReferenceEdge> itrHrnFhrn = hrnY.iteratorToReferencees();
374 while( itrHrnFhrn.hasNext() ) {
375 ReferenceEdge edgeHrn = itrHrnFhrn.next();
376 HeapRegionNode hrnHrn = edgeHrn.getDst();
377 ReachabilitySet betaHrn = edgeHrn.getBeta();
379 if( edgeHrn.getFieldDesc() == null ||
380 edgeHrn.getFieldDesc() == f ) {
382 ReferenceEdge edgeNew = new ReferenceEdge( lnX,
386 betaY.intersection( betaHrn ) );
388 addReferenceEdge( lnX, hrnHrn, edgeNew );
395 public void assignTempYToTempXFieldF( TempDescriptor y,
397 FieldDescriptor f ) {
399 LabelNode lnX = getLabelNodeFromTemp( x );
400 LabelNode lnY = getLabelNodeFromTemp( y );
402 HashSet<HeapRegionNode> nodesWithNewAlpha = new HashSet<HeapRegionNode>();
403 HashSet<ReferenceEdge> edgesWithNewBeta = new HashSet<ReferenceEdge>();
405 Iterator<ReferenceEdge> itrXhrn = lnX.iteratorToReferencees();
406 while( itrXhrn.hasNext() ) {
407 ReferenceEdge edgeX = itrXhrn.next();
408 HeapRegionNode hrnX = edgeX.getDst();
409 ReachabilitySet betaX = edgeX.getBeta();
411 ReachabilitySet R = hrnX.getAlpha().intersection( edgeX.getBeta() );
413 Iterator<ReferenceEdge> itrYhrn = lnY.iteratorToReferencees();
414 while( itrYhrn.hasNext() ) {
415 ReferenceEdge edgeY = itrYhrn.next();
416 HeapRegionNode hrnY = edgeY.getDst();
417 ReachabilitySet O = edgeY.getBeta();
419 // propagate tokens over nodes starting from hrnSrc, and it will
420 // take care of propagating back up edges from any touched nodes
421 ChangeTupleSet Cy = O.unionUpArityToChangeSet( R );
422 propagateTokensOverNodes( hrnY, Cy, nodesWithNewAlpha, edgesWithNewBeta );
425 // then propagate back just up the edges from hrn
426 ChangeTupleSet Cx = R.unionUpArityToChangeSet( O );
428 HashSet<ReferenceEdge> todoEdges = new HashSet<ReferenceEdge>();
430 Hashtable<ReferenceEdge, ChangeTupleSet> edgePlannedChanges =
431 new Hashtable<ReferenceEdge, ChangeTupleSet>();
433 Iterator<ReferenceEdge> referItr = hrnX.iteratorToReferencers();
434 while( referItr.hasNext() ) {
435 ReferenceEdge edgeUpstream = referItr.next();
436 todoEdges.add( edgeUpstream );
437 edgePlannedChanges.put( edgeUpstream, Cx );
440 propagateTokensOverEdges( todoEdges,
445 // finally, create the actual reference edge hrnX.f -> hrnY
446 ReferenceEdge edgeNew = new ReferenceEdge( hrnX,
450 edgeY.getBetaNew().pruneBy( hrnX.getAlpha() )
453 // we can do a strong update here if one of two cases holds
454 if( (hrnX.getNumReferencers() == 1) ||
455 ( lnX.getNumReferencees() == 1 && hrnX.isSingleObject() )
457 clearReferenceEdgesFrom( hrnX, f, false );
460 addReferenceEdge( hrnX, hrnY, edgeNew );
463 // if the field is null, or "any" field, then
464 // look to see if an any field already exists
465 // and merge with it, otherwise just add the edge
466 ReferenceEdge edgeExisting = hrnX.getReferenceTo( hrnY, f );
468 if( edgeExisting != null ) {
469 edgeExisting.setBetaNew(
470 edgeExisting.getBetaNew().union( edgeNew.getBeta() )
472 // a new edge here cannot be reflexive, so existing will
473 // always be also not reflexive anymore
474 edgeExisting.setIsInitialParamReflexive( false );
477 addReferenceEdge( hrnX, hrnY, edgeNew );
483 Iterator<HeapRegionNode> nodeItr = nodesWithNewAlpha.iterator();
484 while( nodeItr.hasNext() ) {
485 nodeItr.next().applyAlphaNew();
488 Iterator<ReferenceEdge> edgeItr = edgesWithNewBeta.iterator();
489 while( edgeItr.hasNext() ) {
490 edgeItr.next().applyBetaNew();
495 public void assignParameterAllocationToTemp( boolean isTask,
497 Integer paramIndex ) {
500 LabelNode lnParam = getLabelNodeFromTemp( td );
501 HeapRegionNode hrn = createNewHeapRegionNode( null,
508 "param" + paramIndex );
510 // keep track of heap regions that were created for
511 // parameter labels, the index of the parameter they
512 // are for is important when resolving method calls
513 Integer newID = hrn.getID();
514 assert !id2paramIndex.containsKey ( newID );
515 assert !id2paramIndex.containsValue( paramIndex );
516 id2paramIndex.put( newID, paramIndex );
517 paramIndex2id.put( paramIndex, newID );
519 ReachabilitySet beta = new ReachabilitySet( new TokenTuple( newID,
521 TokenTuple.ARITY_ONE ) );
523 // heap regions for parameters are always multiple object (see above)
524 // and have a reference to themselves, because we can't know the
525 // structure of memory that is passed into the method. We're assuming
528 ReferenceEdge edgeFromLabel =
529 new ReferenceEdge( lnParam, hrn, null, false, beta );
531 ReferenceEdge edgeReflexive =
532 new ReferenceEdge( hrn, hrn, null, true, beta );
534 addReferenceEdge( lnParam, hrn, edgeFromLabel );
535 addReferenceEdge( hrn, hrn, edgeReflexive );
539 public void assignNewAllocationToTempX( TempDescriptor x,
540 AllocationSite as ) {
546 // after the age operation the newest (or zero-ith oldest)
547 // node associated with the allocation site should have
548 // no references to it as if it were a newly allocated
549 // heap region, so make a reference to it to complete
552 Integer idNewest = as.getIthOldest( 0 );
553 HeapRegionNode hrnNewest = id2hrn.get( idNewest );
554 assert hrnNewest != null;
556 LabelNode lnX = getLabelNodeFromTemp( x );
557 clearReferenceEdgesFrom( lnX, null, true );
559 ReferenceEdge edgeNew =
560 new ReferenceEdge( lnX, hrnNewest, null, false, hrnNewest.getAlpha() );
562 addReferenceEdge( lnX, hrnNewest, edgeNew );
566 // use the allocation site (unique to entire analysis) to
567 // locate the heap region nodes in this ownership graph
568 // that should be aged. The process models the allocation
569 // of new objects and collects all the oldest allocations
570 // in a summary node to allow for a finite analysis
572 // There is an additional property of this method. After
573 // running it on a particular ownership graph (many graphs
574 // may have heap regions related to the same allocation site)
575 // the heap region node objects in this ownership graph will be
576 // allocated. Therefore, after aging a graph for an allocation
577 // site, attempts to retrieve the heap region nodes using the
578 // integer id's contained in the allocation site should always
579 // return non-null heap regions.
580 public void age( AllocationSite as ) {
582 // aging adds this allocation site to the graph's
583 // list of sites that exist in the graph, or does
584 // nothing if the site is already in the list
585 allocationSites.add( as );
587 // get the summary node for the allocation site in the context
588 // of this particular ownership graph
589 HeapRegionNode hrnSummary = getSummaryNode( as );
591 // merge oldest node into summary
592 Integer idK = as.getOldest();
593 HeapRegionNode hrnK = id2hrn.get( idK );
594 mergeIntoSummary( hrnK, hrnSummary );
596 // move down the line of heap region nodes
597 // clobbering the ith and transferring all references
598 // to and from i-1 to node i. Note that this clobbers
599 // the oldest node (hrnK) that was just merged into
601 for( int i = allocationDepth - 1; i > 0; --i ) {
603 // move references from the i-1 oldest to the ith oldest
604 Integer idIth = as.getIthOldest( i );
605 HeapRegionNode hrnI = id2hrn.get( idIth );
606 Integer idImin1th = as.getIthOldest( i - 1 );
607 HeapRegionNode hrnImin1 = id2hrn.get( idImin1th );
609 transferOnto( hrnImin1, hrnI );
612 // as stated above, the newest node should have had its
613 // references moved over to the second oldest, so we wipe newest
614 // in preparation for being the new object to assign something to
615 Integer id0th = as.getIthOldest( 0 );
616 HeapRegionNode hrn0 = id2hrn.get( id0th );
619 // clear all references in and out of newest node
620 clearReferenceEdgesFrom( hrn0, null, true );
621 clearReferenceEdgesTo ( hrn0, null, true );
624 // now tokens in reachability sets need to "age" also
625 Iterator itrAllLabelNodes = td2ln.entrySet().iterator();
626 while( itrAllLabelNodes.hasNext() ) {
627 Map.Entry me = (Map.Entry) itrAllLabelNodes.next();
628 LabelNode ln = (LabelNode) me.getValue();
630 Iterator<ReferenceEdge> itrEdges = ln.iteratorToReferencees();
631 while( itrEdges.hasNext() ) {
632 ageTokens( as, itrEdges.next() );
636 Iterator itrAllHRNodes = id2hrn.entrySet().iterator();
637 while( itrAllHRNodes.hasNext() ) {
638 Map.Entry me = (Map.Entry) itrAllHRNodes.next();
639 HeapRegionNode hrnToAge = (HeapRegionNode) me.getValue();
641 ageTokens( as, hrnToAge );
643 Iterator<ReferenceEdge> itrEdges = hrnToAge.iteratorToReferencees();
644 while( itrEdges.hasNext() ) {
645 ageTokens( as, itrEdges.next() );
650 // after tokens have been aged, reset newest node's reachability
651 hrn0.setAlpha( new ReachabilitySet(
653 new TokenTuple( hrn0 )
660 protected HeapRegionNode getSummaryNode( AllocationSite as ) {
662 Integer idSummary = as.getSummary();
663 HeapRegionNode hrnSummary = id2hrn.get( idSummary );
665 // If this is null then we haven't touched this allocation site
666 // in the context of the current ownership graph, so allocate
667 // heap region nodes appropriate for the entire allocation site.
668 // This should only happen once per ownership graph per allocation site,
669 // and a particular integer id can be used to locate the heap region
670 // in different ownership graphs that represents the same part of an
672 if( hrnSummary == null ) {
674 boolean hasFlags = false;
675 if( as.getType().isClass() ) {
676 hasFlags = as.getType().getClassDesc().hasFlags();
679 hrnSummary = createNewHeapRegionNode( idSummary,
686 as + "\\n" + as.getType() + "\\nsummary" );
688 for( int i = 0; i < as.getAllocationDepth(); ++i ) {
689 Integer idIth = as.getIthOldest( i );
690 assert !id2hrn.containsKey( idIth );
691 createNewHeapRegionNode( idIth,
698 as + "\\n" + as.getType() + "\\n" + i + " oldest" );
706 protected HeapRegionNode getShadowSummaryNode( AllocationSite as ) {
708 Integer idShadowSummary = -(as.getSummary());
709 HeapRegionNode hrnShadowSummary = id2hrn.get( idShadowSummary );
711 if( hrnShadowSummary == null ) {
713 boolean hasFlags = false;
714 if( as.getType().isClass() ) {
715 hasFlags = as.getType().getClassDesc().hasFlags();
718 hrnShadowSummary = createNewHeapRegionNode( idShadowSummary,
725 as + "\\n" + as.getType() + "\\nshadowSum" );
727 for( int i = 0; i < as.getAllocationDepth(); ++i ) {
728 Integer idShadowIth = -(as.getIthOldest( i ));
729 assert !id2hrn.containsKey( idShadowIth );
730 createNewHeapRegionNode( idShadowIth,
737 as + "\\n" + as.getType() + "\\n" + i + " shadow" );
741 return hrnShadowSummary;
745 protected void mergeIntoSummary( HeapRegionNode hrn, HeapRegionNode hrnSummary ) {
746 assert hrnSummary.isNewSummary();
748 // transfer references _from_ hrn over to hrnSummary
749 Iterator<ReferenceEdge> itrReferencee = hrn.iteratorToReferencees();
750 while( itrReferencee.hasNext() ) {
751 ReferenceEdge edge = itrReferencee.next();
752 ReferenceEdge edgeMerged = edge.copy();
753 edgeMerged.setSrc( hrnSummary );
755 HeapRegionNode hrnReferencee = edge.getDst();
756 ReferenceEdge edgeSummary = hrnSummary.getReferenceTo( hrnReferencee, edge.getFieldDesc() );
758 if( edgeSummary == null ) {
759 // the merge is trivial, nothing to be done
761 // otherwise an edge from the referencer to hrnSummary exists already
762 // and the edge referencer->hrn should be merged with it
763 edgeMerged.setBeta( edgeMerged.getBeta().union( edgeSummary.getBeta() ) );
766 addReferenceEdge( hrnSummary, hrnReferencee, edgeMerged );
769 // next transfer references _to_ hrn over to hrnSummary
770 Iterator<ReferenceEdge> itrReferencer = hrn.iteratorToReferencers();
771 while( itrReferencer.hasNext() ) {
772 ReferenceEdge edge = itrReferencer.next();
773 ReferenceEdge edgeMerged = edge.copy();
774 edgeMerged.setDst( hrnSummary );
776 OwnershipNode onReferencer = edge.getSrc();
777 ReferenceEdge edgeSummary = onReferencer.getReferenceTo( hrnSummary, edge.getFieldDesc() );
779 if( edgeSummary == null ) {
780 // the merge is trivial, nothing to be done
782 // otherwise an edge from the referencer to alpha_S exists already
783 // and the edge referencer->alpha_K should be merged with it
784 edgeMerged.setBeta( edgeMerged.getBeta().union( edgeSummary.getBeta() ) );
787 addReferenceEdge( onReferencer, hrnSummary, edgeMerged );
790 // then merge hrn reachability into hrnSummary
791 hrnSummary.setAlpha( hrnSummary.getAlpha().union( hrn.getAlpha() ) );
795 protected void transferOnto( HeapRegionNode hrnA, HeapRegionNode hrnB ) {
797 // clear references in and out of node i
798 clearReferenceEdgesFrom( hrnB, null, true );
799 clearReferenceEdgesTo ( hrnB, null, true );
801 // copy each edge in and out of A to B
802 Iterator<ReferenceEdge> itrReferencee = hrnA.iteratorToReferencees();
803 while( itrReferencee.hasNext() ) {
804 ReferenceEdge edge = itrReferencee.next();
805 HeapRegionNode hrnReferencee = edge.getDst();
806 ReferenceEdge edgeNew = edge.copy();
807 edgeNew.setSrc( hrnB );
809 addReferenceEdge( hrnB, hrnReferencee, edgeNew );
812 Iterator<ReferenceEdge> itrReferencer = hrnA.iteratorToReferencers();
813 while( itrReferencer.hasNext() ) {
814 ReferenceEdge edge = itrReferencer.next();
815 OwnershipNode onReferencer = edge.getSrc();
816 ReferenceEdge edgeNew = edge.copy();
817 edgeNew.setDst( hrnB );
819 addReferenceEdge( onReferencer, hrnB, edgeNew );
822 // replace hrnB reachability with hrnA's
823 hrnB.setAlpha( hrnA.getAlpha() );
827 protected void ageTokens( AllocationSite as, ReferenceEdge edge ) {
828 edge.setBeta( edge.getBeta().ageTokens( as ) );
831 protected void ageTokens( AllocationSite as, HeapRegionNode hrn ) {
832 hrn.setAlpha( hrn.getAlpha().ageTokens( as ) );
835 protected void majorAgeTokens( AllocationSite as, ReferenceEdge edge ) {
836 //edge.setBeta( edge.getBeta().majorAgeTokens( as ) );
839 protected void majorAgeTokens( AllocationSite as, HeapRegionNode hrn ) {
840 //hrn.setAlpha( hrn.getAlpha().majorAgeTokens( as ) );
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 ) {
1113 Set sA = og.id2hrn.entrySet();
1114 Iterator iA = sA.iterator();
1115 while( iA.hasNext() ) {
1116 Map.Entry meA = (Map.Entry) iA.next();
1117 Integer idA = (Integer) meA.getKey();
1118 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1120 Iterator<ReferenceEdge> heapRegionsItrA = hrnA.iteratorToReferencees();
1121 while( heapRegionsItrA.hasNext() ) {
1122 ReferenceEdge edgeA = heapRegionsItrA.next();
1123 HeapRegionNode hrnChildA = edgeA.getDst();
1124 Integer idChildA = hrnChildA.getID();
1126 // at this point we know an edge in graph A exists
1127 // idA -> idChildA, does this exist in B?
1128 assert id2hrn.containsKey( idA );
1129 HeapRegionNode hrnB = id2hrn.get( idA );
1130 ReferenceEdge edgeToMerge = null;
1132 Iterator<ReferenceEdge> heapRegionsItrB = hrnB.iteratorToReferencees();
1133 while( heapRegionsItrB.hasNext() &&
1134 edgeToMerge == null ) {
1136 ReferenceEdge edgeB = heapRegionsItrB.next();
1137 HeapRegionNode hrnChildB = edgeB.getDst();
1138 Integer idChildB = hrnChildB.getID();
1140 // don't use the ReferenceEdge.equals() here because
1141 // we're talking about existence between graphs
1142 if( idChildB.equals( idChildA ) &&
1143 edgeB.getFieldDesc() == edgeA.getFieldDesc() ) {
1144 edgeToMerge = edgeB;
1148 // if the edge from A was not found in B,
1150 if( edgeToMerge == null ) {
1151 assert id2hrn.containsKey( idChildA );
1152 HeapRegionNode hrnChildB = id2hrn.get( idChildA );
1153 edgeToMerge = edgeA.copy();
1154 edgeToMerge.setSrc( hrnB );
1155 edgeToMerge.setDst( hrnChildB );
1156 addReferenceEdge( hrnB, hrnChildB, edgeToMerge );
1158 // otherwise, the edge already existed in both graphs
1159 // so merge their reachability sets
1161 // just replace this beta set with the union
1162 assert edgeToMerge != null;
1163 edgeToMerge.setBeta(
1164 edgeToMerge.getBeta().union( edgeA.getBeta() )
1166 if( !edgeA.isInitialParamReflexive() ) {
1167 edgeToMerge.setIsInitialParamReflexive( false );
1173 // and then again with label nodes
1174 sA = og.td2ln.entrySet();
1176 while( iA.hasNext() ) {
1177 Map.Entry meA = (Map.Entry) iA.next();
1178 TempDescriptor tdA = (TempDescriptor) meA.getKey();
1179 LabelNode lnA = (LabelNode) meA.getValue();
1181 Iterator<ReferenceEdge> heapRegionsItrA = lnA.iteratorToReferencees();
1182 while( heapRegionsItrA.hasNext() ) {
1183 ReferenceEdge edgeA = heapRegionsItrA.next();
1184 HeapRegionNode hrnChildA = edgeA.getDst();
1185 Integer idChildA = hrnChildA.getID();
1187 // at this point we know an edge in graph A exists
1188 // tdA -> idChildA, does this exist in B?
1189 assert td2ln.containsKey( tdA );
1190 LabelNode lnB = td2ln.get( tdA );
1191 ReferenceEdge edgeToMerge = null;
1193 // labels never have edges with a field
1194 //assert edgeA.getFieldDesc() == null;
1196 Iterator<ReferenceEdge> heapRegionsItrB = lnB.iteratorToReferencees();
1197 while( heapRegionsItrB.hasNext() &&
1198 edgeToMerge == null ) {
1200 ReferenceEdge edgeB = heapRegionsItrB.next();
1201 HeapRegionNode hrnChildB = edgeB.getDst();
1202 Integer idChildB = hrnChildB.getID();
1204 // labels never have edges with a field
1205 //assert edgeB.getFieldDesc() == null;
1207 // don't use the ReferenceEdge.equals() here because
1208 // we're talking about existence between graphs
1209 if( idChildB.equals( idChildA ) &&
1210 edgeB.getFieldDesc() == edgeA.getFieldDesc() ) {
1211 edgeToMerge = edgeB;
1215 // if the edge from A was not found in B,
1217 if( edgeToMerge == null ) {
1218 assert id2hrn.containsKey( idChildA );
1219 HeapRegionNode hrnChildB = id2hrn.get( idChildA );
1220 edgeToMerge = edgeA.copy();
1221 edgeToMerge.setSrc( lnB );
1222 edgeToMerge.setDst( hrnChildB );
1223 addReferenceEdge( lnB, hrnChildB, edgeToMerge );
1225 // otherwise, the edge already existed in both graphs
1226 // so merge their reachability sets
1228 // just replace this beta set with the union
1229 edgeToMerge.setBeta(
1230 edgeToMerge.getBeta().union( edgeA.getBeta() )
1232 if( !edgeA.isInitialParamReflexive() ) {
1233 edgeToMerge.setIsInitialParamReflexive( false );
1240 // you should only merge ownership graphs that have the
1241 // same number of parameters, or if one or both parameter
1242 // index tables are empty
1243 protected void mergeId2paramIndex( OwnershipGraph og ) {
1244 if( id2paramIndex.size() == 0 ) {
1245 id2paramIndex = og.id2paramIndex;
1246 paramIndex2id = og.paramIndex2id;
1250 if( og.id2paramIndex.size() == 0 ) {
1254 assert id2paramIndex.size() == og.id2paramIndex.size();
1257 protected void mergeAllocationSites( OwnershipGraph og ) {
1258 allocationSites.addAll( og.allocationSites );
1263 // it is necessary in the equals() member functions
1264 // to "check both ways" when comparing the data
1265 // structures of two graphs. For instance, if all
1266 // edges between heap region nodes in graph A are
1267 // present and equal in graph B it is not sufficient
1268 // to say the graphs are equal. Consider that there
1269 // may be edges in graph B that are not in graph A.
1270 // the only way to know that all edges in both graphs
1271 // are equally present is to iterate over both data
1272 // structures and compare against the other graph.
1273 public boolean equals( OwnershipGraph og ) {
1279 if( !areHeapRegionNodesEqual( og ) ) {
1283 if( !areLabelNodesEqual( og ) ) {
1287 if( !areReferenceEdgesEqual( og ) ) {
1291 if( !areId2paramIndexEqual( og ) ) {
1295 // if everything is equal up to this point,
1296 // assert that allocationSites is also equal--
1297 // this data is redundant and kept for efficiency
1298 assert allocationSites.equals( og.allocationSites );
1303 protected boolean areHeapRegionNodesEqual( OwnershipGraph og ) {
1305 if( !areallHRNinAalsoinBandequal( this, og ) ) {
1309 if( !areallHRNinAalsoinBandequal( og, this ) ) {
1316 static protected boolean areallHRNinAalsoinBandequal( OwnershipGraph ogA,
1317 OwnershipGraph ogB ) {
1318 Set sA = ogA.id2hrn.entrySet();
1319 Iterator iA = sA.iterator();
1320 while( iA.hasNext() ) {
1321 Map.Entry meA = (Map.Entry) iA.next();
1322 Integer idA = (Integer) meA.getKey();
1323 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1325 if( !ogB.id2hrn.containsKey( idA ) ) {
1329 HeapRegionNode hrnB = ogB.id2hrn.get( idA );
1330 if( !hrnA.equalsIncludingAlpha( hrnB ) ) {
1339 protected boolean areLabelNodesEqual( OwnershipGraph og ) {
1341 if( !areallLNinAalsoinBandequal( this, og ) ) {
1345 if( !areallLNinAalsoinBandequal( og, this ) ) {
1352 static protected boolean areallLNinAalsoinBandequal( OwnershipGraph ogA,
1353 OwnershipGraph ogB ) {
1354 Set sA = ogA.td2ln.entrySet();
1355 Iterator iA = sA.iterator();
1356 while( iA.hasNext() ) {
1357 Map.Entry meA = (Map.Entry) iA.next();
1358 TempDescriptor tdA = (TempDescriptor) meA.getKey();
1360 if( !ogB.td2ln.containsKey( tdA ) ) {
1369 protected boolean areReferenceEdgesEqual( OwnershipGraph og ) {
1370 if( !areallREinAandBequal( this, og ) ) {
1377 static protected boolean areallREinAandBequal( OwnershipGraph ogA,
1378 OwnershipGraph ogB ) {
1380 // check all the heap region->heap region edges
1381 Set sA = ogA.id2hrn.entrySet();
1382 Iterator iA = sA.iterator();
1383 while( iA.hasNext() ) {
1384 Map.Entry meA = (Map.Entry) iA.next();
1385 Integer idA = (Integer) meA.getKey();
1386 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1388 // we should have already checked that the same
1389 // heap regions exist in both graphs
1390 assert ogB.id2hrn.containsKey( idA );
1392 if( !areallREfromAequaltoB( ogA, hrnA, ogB ) ) {
1396 // then check every edge in B for presence in A, starting
1397 // from the same parent HeapRegionNode
1398 HeapRegionNode hrnB = ogB.id2hrn.get( idA );
1400 if( !areallREfromAequaltoB( ogB, hrnB, ogA ) ) {
1405 // then check all the label->heap region edges
1406 sA = ogA.td2ln.entrySet();
1408 while( iA.hasNext() ) {
1409 Map.Entry meA = (Map.Entry) iA.next();
1410 TempDescriptor tdA = (TempDescriptor) meA.getKey();
1411 LabelNode lnA = (LabelNode) meA.getValue();
1413 // we should have already checked that the same
1414 // label nodes exist in both graphs
1415 assert ogB.td2ln.containsKey( tdA );
1417 if( !areallREfromAequaltoB( ogA, lnA, ogB ) ) {
1421 // then check every edge in B for presence in A, starting
1422 // from the same parent LabelNode
1423 LabelNode lnB = ogB.td2ln.get( tdA );
1425 if( !areallREfromAequaltoB( ogB, lnB, ogA ) ) {
1434 static protected boolean areallREfromAequaltoB( OwnershipGraph ogA,
1436 OwnershipGraph ogB ) {
1438 Iterator<ReferenceEdge> itrA = onA.iteratorToReferencees();
1439 while( itrA.hasNext() ) {
1440 ReferenceEdge edgeA = itrA.next();
1441 HeapRegionNode hrnChildA = edgeA.getDst();
1442 Integer idChildA = hrnChildA.getID();
1444 assert ogB.id2hrn.containsKey( idChildA );
1446 // at this point we know an edge in graph A exists
1447 // onA -> idChildA, does this exact edge exist in B?
1448 boolean edgeFound = false;
1450 OwnershipNode onB = null;
1451 if( onA instanceof HeapRegionNode ) {
1452 HeapRegionNode hrnA = (HeapRegionNode) onA;
1453 onB = ogB.id2hrn.get( hrnA.getID() );
1455 LabelNode lnA = (LabelNode) onA;
1456 onB = ogB.td2ln.get( lnA.getTempDescriptor() );
1459 Iterator<ReferenceEdge> itrB = onB.iteratorToReferencees();
1460 while( itrB.hasNext() ) {
1461 ReferenceEdge edgeB = itrB.next();
1462 HeapRegionNode hrnChildB = edgeB.getDst();
1463 Integer idChildB = hrnChildB.getID();
1465 if( idChildA.equals( idChildB ) &&
1466 edgeA.getFieldDesc() == edgeB.getFieldDesc() ) {
1468 // there is an edge in the right place with the right field,
1469 // but do they have the same attributes?
1470 if( edgeA.isInitialParamReflexive() == edgeB.isInitialParamReflexive() &&
1471 edgeA.getBeta().equals( edgeB.getBeta() ) ) {
1489 protected boolean areId2paramIndexEqual( OwnershipGraph og ) {
1490 return id2paramIndex.size() == og.id2paramIndex.size();
1495 // given a set B of heap region node ID's, return the set of heap
1496 // region node ID's that is reachable from B
1497 public HashSet<Integer> getReachableSet( HashSet<Integer> idSetB ) {
1499 HashSet<HeapRegionNode> toVisit = new HashSet<HeapRegionNode>();
1500 HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
1502 // initial nodes to visit are from set B
1503 Iterator initialItr = idSetB.iterator();
1504 while( initialItr.hasNext() ) {
1505 Integer idInitial = (Integer) initialItr.next();
1506 assert id2hrn.contains( idInitial );
1507 HeapRegionNode hrnInitial = id2hrn.get( idInitial );
1508 toVisit.add( hrnInitial );
1511 HashSet<Integer> idSetReachableFromB = new HashSet<Integer>();
1513 // do a heap traversal
1514 while( !toVisit.isEmpty() ) {
1515 HeapRegionNode hrnVisited = (HeapRegionNode) toVisit.iterator().next();
1516 toVisit.remove( hrnVisited );
1517 visited.add ( hrnVisited );
1519 // for every node visited, add it to the total
1521 idSetReachableFromB.add( hrnVisited.getID() );
1523 // find other reachable nodes
1524 Iterator referenceeItr = hrnVisited.setIteratorToReferencedRegions();
1525 while( referenceeItr.hasNext() ) {
1526 Map.Entry me = (Map.Entry) referenceeItr.next();
1527 HeapRegionNode hrnReferencee = (HeapRegionNode) me.getKey();
1528 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
1530 if( !visited.contains( hrnReferencee ) ) {
1531 toVisit.add( hrnReferencee );
1536 return idSetReachableFromB;
1540 // used to find if a heap region can possibly have a reference to
1541 // any of the heap regions in the given set
1542 // if the id supplied is in the set, then a self-referencing edge
1543 // would return true, but that special case is specifically allowed
1544 // meaning that it isn't an external alias
1545 public boolean canIdReachSet( Integer id, HashSet<Integer> idSet ) {
1547 assert id2hrn.contains( id );
1548 HeapRegionNode hrn = id2hrn.get( id );
1551 //HashSet<HeapRegionNode> hrnSet = new HashSet<HeapRegionNode>();
1553 //Iterator i = idSet.iterator();
1554 //while( i.hasNext() ) {
1555 // Integer idFromSet = (Integer) i.next();
1556 // assert id2hrn.contains( idFromSet );
1557 // hrnSet.add( id2hrn.get( idFromSet ) );
1561 // do a traversal from hrn and see if any of the
1562 // heap regions from the set come up during that
1563 HashSet<HeapRegionNode> toVisit = new HashSet<HeapRegionNode>();
1564 HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
1567 while( !toVisit.isEmpty() ) {
1568 HeapRegionNode hrnVisited = (HeapRegionNode) toVisit.iterator().next();
1569 toVisit.remove( hrnVisited );
1570 visited.add ( hrnVisited );
1572 Iterator referenceeItr = hrnVisited.setIteratorToReferencedRegions();
1573 while( referenceeItr.hasNext() ) {
1574 Map.Entry me = (Map.Entry) referenceeItr.next();
1575 HeapRegionNode hrnReferencee = (HeapRegionNode) me.getKey();
1576 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
1578 if( idSet.contains( hrnReferencee.getID() ) ) {
1579 if( !id.equals( hrnReferencee.getID() ) ) {
1584 if( !visited.contains( hrnReferencee ) ) {
1585 toVisit.add( hrnReferencee );
1595 // for writing ownership graphs to dot files
1596 public void writeGraph( Descriptor methodDesc,
1598 boolean writeLabels,
1599 boolean labelSelect,
1600 boolean pruneGarbage,
1601 boolean writeReferencers
1602 ) throws java.io.IOException {
1604 methodDesc.getSymbol() +
1605 methodDesc.getNum() +
1614 public void writeGraph( Descriptor methodDesc,
1616 boolean writeLabels,
1617 boolean writeReferencers
1618 ) throws java.io.IOException {
1620 methodDesc.getSymbol() +
1621 methodDesc.getNum() +
1630 public void writeGraph( Descriptor methodDesc,
1631 boolean writeLabels,
1632 boolean writeReferencers
1633 ) throws java.io.IOException {
1635 methodDesc.getSymbol() +
1636 methodDesc.getNum() +
1645 public void writeGraph( Descriptor methodDesc,
1646 boolean writeLabels,
1647 boolean labelSelect,
1648 boolean pruneGarbage,
1649 boolean writeReferencers
1650 ) throws java.io.IOException {
1652 methodDesc.getSymbol() +
1653 methodDesc.getNum() +
1662 public void writeGraph( String graphName,
1663 boolean writeLabels,
1664 boolean labelSelect,
1665 boolean pruneGarbage,
1666 boolean writeReferencers
1667 ) throws java.io.IOException {
1669 // remove all non-word characters from the graph name so
1670 // the filename and identifier in dot don't cause errors
1671 graphName = graphName.replaceAll( "[\\W]", "" );
1673 BufferedWriter bw = new BufferedWriter( new FileWriter( graphName+".dot" ) );
1674 bw.write( "digraph "+graphName+" {\n" );
1675 //bw.write( " size=\"7.5,10\";\n" );
1677 HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
1679 // then visit every heap region node
1680 if( !pruneGarbage ) {
1681 Set s = id2hrn.entrySet();
1682 Iterator i = s.iterator();
1683 while( i.hasNext() ) {
1684 Map.Entry me = (Map.Entry) i.next();
1685 HeapRegionNode hrn = (HeapRegionNode) me.getValue();
1686 if( !visited.contains( hrn ) ) {
1687 traverseHeapRegionNodes( VISIT_HRN_WRITE_FULL,
1697 bw.write( " graphTitle[label=\""+graphName+"\",shape=box];\n" );
1700 // then visit every label node, useful for debugging
1702 Set s = td2ln.entrySet();
1703 Iterator i = s.iterator();
1704 while( i.hasNext() ) {
1705 Map.Entry me = (Map.Entry) i.next();
1706 LabelNode ln = (LabelNode) me.getValue();
1709 String labelStr = ln.getTempDescriptorString();
1710 if( labelStr.startsWith( "___temp" ) ||
1711 labelStr.startsWith( "___dst" ) ||
1712 labelStr.startsWith( "___srctmp" ) ||
1713 labelStr.startsWith( "___neverused" ) ) {
1718 bw.write( ln.toString() + ";\n" );
1720 Iterator<ReferenceEdge> heapRegionsItr = ln.iteratorToReferencees();
1721 while( heapRegionsItr.hasNext() ) {
1722 ReferenceEdge edge = heapRegionsItr.next();
1723 HeapRegionNode hrn = edge.getDst();
1725 if( pruneGarbage && !visited.contains( hrn ) ) {
1726 traverseHeapRegionNodes( VISIT_HRN_WRITE_FULL,
1734 bw.write( " " + ln.toString() +
1735 " -> " + hrn.toString() +
1736 "[label=\"" + edge.toGraphEdgeString() +
1737 "\",decorate];\n" );
1747 protected void traverseHeapRegionNodes( int mode,
1751 HashSet<HeapRegionNode> visited,
1752 boolean writeReferencers
1753 ) throws java.io.IOException {
1755 if( visited.contains( hrn ) ) {
1761 case VISIT_HRN_WRITE_FULL:
1763 String attributes = "[";
1765 if( hrn.isSingleObject() ) {
1766 attributes += "shape=box";
1768 attributes += "shape=Msquare";
1771 if( hrn.isFlagged() ) {
1772 attributes += ",style=filled,fillcolor=lightgrey";
1775 attributes += ",label=\"ID" +
1778 hrn.getDescription() +
1780 hrn.getAlphaString() +
1783 bw.write( " " + hrn.toString() + attributes + ";\n" );
1788 // useful for debugging
1789 if( writeReferencers ) {
1790 OwnershipNode onRef = null;
1791 Iterator refItr = hrn.iteratorToReferencers();
1792 while( refItr.hasNext() ) {
1793 onRef = (OwnershipNode) refItr.next();
1796 case VISIT_HRN_WRITE_FULL:
1797 bw.write( " " + hrn.toString() +
1798 " -> " + onRef.toString() +
1799 "[color=lightgray];\n" );
1805 Iterator<ReferenceEdge> childRegionsItr = hrn.iteratorToReferencees();
1806 while( childRegionsItr.hasNext() ) {
1807 ReferenceEdge edge = childRegionsItr.next();
1808 HeapRegionNode hrnChild = edge.getDst();
1811 case VISIT_HRN_WRITE_FULL:
1812 bw.write( " " + hrn.toString() +
1813 " -> " + hrnChild.toString() +
1814 "[label=\"" + edge.toGraphEdgeString() +
1815 "\",decorate];\n" );
1819 traverseHeapRegionNodes( mode,