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;
24 public Hashtable<Integer, TempDescriptor> paramIndex2tdQ;
26 public HashSet<AllocationSite> allocationSites;
29 public OwnershipGraph(int allocationDepth) {
30 this.allocationDepth = allocationDepth;
32 id2hrn = new Hashtable<Integer, HeapRegionNode>();
33 td2ln = new Hashtable<TempDescriptor, LabelNode >();
34 id2paramIndex = new Hashtable<Integer, Integer >();
35 paramIndex2id = new Hashtable<Integer, Integer >();
36 paramIndex2tdQ = new Hashtable<Integer, TempDescriptor>();
38 allocationSites = new HashSet <AllocationSite>();
42 // label nodes are much easier to deal with than
43 // heap region nodes. Whenever there is a request
44 // for the label node that is associated with a
45 // temp descriptor we can either find it or make a
46 // new one and return it. This is because temp
47 // descriptors are globally unique and every label
48 // node is mapped to exactly one temp descriptor.
49 protected LabelNode getLabelNodeFromTemp(TempDescriptor td) {
52 if( !td2ln.containsKey(td) ) {
53 td2ln.put(td, new LabelNode(td) );
60 // the reason for this method is to have the option
61 // creating new heap regions with specific IDs, or
62 // duplicating heap regions with specific IDs (especially
63 // in the merge() operation) or to create new heap
64 // regions with a new unique ID.
65 protected HeapRegionNode
66 createNewHeapRegionNode(Integer id,
67 boolean isSingleObject,
71 AllocationSite allocSite,
72 ReachabilitySet alpha,
76 id = OwnershipAnalysis.generateUniqueHeapRegionNodeID();
80 if( isFlagged || isParameter ) {
81 alpha = new ReachabilitySet(new TokenTuple(id,
86 alpha = new ReachabilitySet(new TokenTupleSet()
91 HeapRegionNode hrn = new HeapRegionNode(id,
104 ////////////////////////////////////////////////
106 // Low-level referencee and referencer methods
108 // These methods provide the lowest level for
109 // creating references between ownership nodes
110 // and handling the details of maintaining both
111 // list of referencers and referencees.
113 ////////////////////////////////////////////////
114 protected void addReferenceEdge(OwnershipNode referencer,
115 HeapRegionNode referencee,
116 ReferenceEdge edge) {
117 assert referencer != null;
118 assert referencee != null;
120 assert edge.getSrc() == referencer;
121 assert edge.getDst() == referencee;
123 referencer.addReferencee(edge);
124 referencee.addReferencer(edge);
127 protected void removeReferenceEdge(OwnershipNode referencer,
128 HeapRegionNode referencee,
129 FieldDescriptor fieldDesc) {
130 assert referencer != null;
131 assert referencee != null;
133 ReferenceEdge edge = referencer.getReferenceTo(referencee,
136 assert edge == referencee.getReferenceFrom(referencer,
139 referencer.removeReferencee(edge);
140 referencee.removeReferencer(edge);
143 protected void clearReferenceEdgesFrom(OwnershipNode referencer,
144 FieldDescriptor fieldDesc,
146 assert referencer != null;
148 // get a copy of the set to iterate over, otherwise
149 // we will be trying to take apart the set as we
150 // are iterating over it, which won't work
151 Iterator<ReferenceEdge> i = referencer.iteratorToReferenceesClone();
152 while( i.hasNext() ) {
153 ReferenceEdge edge = i.next();
155 if( removeAll || edge.getFieldDesc() == fieldDesc ) {
156 HeapRegionNode referencee = edge.getDst();
158 removeReferenceEdge(referencer,
160 edge.getFieldDesc() );
165 protected void clearReferenceEdgesTo(HeapRegionNode referencee,
166 FieldDescriptor fieldDesc,
168 assert referencee != null;
170 // get a copy of the set to iterate over, otherwise
171 // we will be trying to take apart the set as we
172 // are iterating over it, which won't work
173 Iterator<ReferenceEdge> i = referencee.iteratorToReferencersClone();
174 while( i.hasNext() ) {
175 ReferenceEdge edge = i.next();
177 if( removeAll || edge.getFieldDesc() == fieldDesc ) {
178 OwnershipNode referencer = edge.getSrc();
179 removeReferenceEdge(referencer,
181 edge.getFieldDesc() );
187 protected void propagateTokensOverNodes(HeapRegionNode nPrime,
189 HashSet<HeapRegionNode> nodesWithNewAlpha,
190 HashSet<ReferenceEdge> edgesWithNewBeta) {
192 HashSet<HeapRegionNode> todoNodes
193 = new HashSet<HeapRegionNode>();
194 todoNodes.add(nPrime);
196 HashSet<ReferenceEdge> todoEdges
197 = new HashSet<ReferenceEdge>();
199 Hashtable<HeapRegionNode, ChangeTupleSet> nodePlannedChanges
200 = new Hashtable<HeapRegionNode, ChangeTupleSet>();
201 nodePlannedChanges.put(nPrime, c0);
203 Hashtable<ReferenceEdge, ChangeTupleSet> edgePlannedChanges
204 = new Hashtable<ReferenceEdge, ChangeTupleSet>();
207 while( !todoNodes.isEmpty() ) {
208 HeapRegionNode n = todoNodes.iterator().next();
209 ChangeTupleSet C = nodePlannedChanges.get(n);
211 Iterator itrC = C.iterator();
212 while( itrC.hasNext() ) {
213 ChangeTuple c = (ChangeTuple) itrC.next();
215 if( n.getAlpha().contains(c.getSetToMatch() ) ) {
216 ReachabilitySet withChange = n.getAlpha().union(c.getSetToAdd() );
217 n.setAlphaNew(n.getAlphaNew().union(withChange) );
218 nodesWithNewAlpha.add(n);
222 Iterator<ReferenceEdge> referItr = n.iteratorToReferencers();
223 while( referItr.hasNext() ) {
224 ReferenceEdge edge = referItr.next();
227 if( !edgePlannedChanges.containsKey(edge) ) {
228 edgePlannedChanges.put(edge, new ChangeTupleSet().makeCanonical() );
231 edgePlannedChanges.put(edge, edgePlannedChanges.get(edge).union(C) );
234 Iterator<ReferenceEdge> refeeItr = n.iteratorToReferencees();
235 while( refeeItr.hasNext() ) {
236 ReferenceEdge edgeF = refeeItr.next();
237 HeapRegionNode m = edgeF.getDst();
239 ChangeTupleSet changesToPass = new ChangeTupleSet().makeCanonical();
241 Iterator<ChangeTuple> itrCprime = C.iterator();
242 while( itrCprime.hasNext() ) {
243 ChangeTuple c = itrCprime.next();
244 if( edgeF.getBeta().contains(c.getSetToMatch() ) ) {
245 changesToPass = changesToPass.union(c);
249 if( !changesToPass.isEmpty() ) {
250 if( !nodePlannedChanges.containsKey(m) ) {
251 nodePlannedChanges.put(m, new ChangeTupleSet().makeCanonical() );
254 ChangeTupleSet currentChanges = nodePlannedChanges.get(m);
256 if( !changesToPass.isSubset(currentChanges) ) {
258 nodePlannedChanges.put(m, currentChanges.union(changesToPass) );
267 propagateTokensOverEdges(todoEdges, edgePlannedChanges, edgesWithNewBeta);
271 protected void propagateTokensOverEdges(
272 HashSet<ReferenceEdge> todoEdges,
273 Hashtable<ReferenceEdge, ChangeTupleSet> edgePlannedChanges,
274 HashSet<ReferenceEdge> edgesWithNewBeta) {
277 while( !todoEdges.isEmpty() ) {
278 ReferenceEdge edgeE = todoEdges.iterator().next();
279 todoEdges.remove(edgeE);
281 if( !edgePlannedChanges.containsKey(edgeE) ) {
282 edgePlannedChanges.put(edgeE, new ChangeTupleSet().makeCanonical() );
285 ChangeTupleSet C = edgePlannedChanges.get(edgeE);
287 ChangeTupleSet changesToPass = new ChangeTupleSet().makeCanonical();
289 Iterator<ChangeTuple> itrC = C.iterator();
290 while( itrC.hasNext() ) {
291 ChangeTuple c = itrC.next();
292 if( edgeE.getBeta().contains(c.getSetToMatch() ) ) {
293 ReachabilitySet withChange = edgeE.getBeta().union(c.getSetToAdd() );
294 edgeE.setBetaNew(edgeE.getBetaNew().union(withChange) );
295 edgesWithNewBeta.add(edgeE);
296 changesToPass = changesToPass.union(c);
300 OwnershipNode onSrc = edgeE.getSrc();
302 if( !changesToPass.isEmpty() && onSrc instanceof HeapRegionNode ) {
303 HeapRegionNode n = (HeapRegionNode) onSrc;
305 Iterator<ReferenceEdge> referItr = n.iteratorToReferencers();
306 while( referItr.hasNext() ) {
307 ReferenceEdge edgeF = referItr.next();
309 if( !edgePlannedChanges.containsKey(edgeF) ) {
310 edgePlannedChanges.put(edgeF, new ChangeTupleSet().makeCanonical() );
313 ChangeTupleSet currentChanges = edgePlannedChanges.get(edgeF);
315 if( !changesToPass.isSubset(currentChanges) ) {
316 todoEdges.add(edgeF);
317 edgePlannedChanges.put(edgeF, currentChanges.union(changesToPass) );
325 ////////////////////////////////////////////////////
327 // Assignment Operation Methods
329 // These methods are high-level operations for
330 // modeling program assignment statements using
331 // the low-level reference create/remove methods
334 // The destination in an assignment statement is
335 // going to have new references. The method of
336 // determining the references depends on the type
337 // of the FlatNode assignment and the predicates
338 // of the nodes and edges involved.
340 ////////////////////////////////////////////////////
341 public void assignTempYToTempX(TempDescriptor y,
344 LabelNode lnX = getLabelNodeFromTemp(x);
345 LabelNode lnY = getLabelNodeFromTemp(y);
347 clearReferenceEdgesFrom(lnX, null, true);
349 Iterator<ReferenceEdge> itrYhrn = lnY.iteratorToReferencees();
350 while( itrYhrn.hasNext() ) {
351 ReferenceEdge edgeY = itrYhrn.next();
352 HeapRegionNode referencee = edgeY.getDst();
353 ReferenceEdge edgeNew = edgeY.copy();
356 addReferenceEdge(lnX, referencee, edgeNew);
361 public void assignTempYFieldFToTempX(TempDescriptor y,
365 LabelNode lnX = getLabelNodeFromTemp(x);
366 LabelNode lnY = getLabelNodeFromTemp(y);
368 clearReferenceEdgesFrom(lnX, null, true);
370 Iterator<ReferenceEdge> itrYhrn = lnY.iteratorToReferencees();
371 while( itrYhrn.hasNext() ) {
372 ReferenceEdge edgeY = itrYhrn.next();
373 HeapRegionNode hrnY = edgeY.getDst();
374 ReachabilitySet betaY = edgeY.getBeta();
376 Iterator<ReferenceEdge> itrHrnFhrn = hrnY.iteratorToReferencees();
377 while( itrHrnFhrn.hasNext() ) {
378 ReferenceEdge edgeHrn = itrHrnFhrn.next();
379 HeapRegionNode hrnHrn = edgeHrn.getDst();
380 ReachabilitySet betaHrn = edgeHrn.getBeta();
382 if( edgeHrn.getFieldDesc() == null ||
383 edgeHrn.getFieldDesc() == f ) {
385 ReferenceEdge edgeNew = new ReferenceEdge(lnX,
389 betaY.intersection(betaHrn) );
391 addReferenceEdge(lnX, hrnHrn, edgeNew);
398 public void assignTempYToTempXFieldF(TempDescriptor y,
402 LabelNode lnX = getLabelNodeFromTemp(x);
403 LabelNode lnY = getLabelNodeFromTemp(y);
405 HashSet<HeapRegionNode> nodesWithNewAlpha = new HashSet<HeapRegionNode>();
406 HashSet<ReferenceEdge> edgesWithNewBeta = new HashSet<ReferenceEdge>();
408 Iterator<ReferenceEdge> itrXhrn = lnX.iteratorToReferencees();
409 while( itrXhrn.hasNext() ) {
410 ReferenceEdge edgeX = itrXhrn.next();
411 HeapRegionNode hrnX = edgeX.getDst();
412 ReachabilitySet betaX = edgeX.getBeta();
414 ReachabilitySet R = hrnX.getAlpha().intersection(edgeX.getBeta() );
416 Iterator<ReferenceEdge> itrYhrn = lnY.iteratorToReferencees();
417 while( itrYhrn.hasNext() ) {
418 ReferenceEdge edgeY = itrYhrn.next();
419 HeapRegionNode hrnY = edgeY.getDst();
420 ReachabilitySet O = edgeY.getBeta();
423 // propagate tokens over nodes starting from hrnSrc, and it will
424 // take care of propagating back up edges from any touched nodes
425 ChangeTupleSet Cy = O.unionUpArityToChangeSet(R);
426 propagateTokensOverNodes(hrnY, Cy, nodesWithNewAlpha, edgesWithNewBeta);
429 // then propagate back just up the edges from hrn
430 ChangeTupleSet Cx = R.unionUpArityToChangeSet(O);
432 HashSet<ReferenceEdge> todoEdges = new HashSet<ReferenceEdge>();
434 Hashtable<ReferenceEdge, ChangeTupleSet> edgePlannedChanges =
435 new Hashtable<ReferenceEdge, ChangeTupleSet>();
437 Iterator<ReferenceEdge> referItr = hrnX.iteratorToReferencers();
438 while( referItr.hasNext() ) {
439 ReferenceEdge edgeUpstream = referItr.next();
440 todoEdges.add(edgeUpstream);
441 edgePlannedChanges.put(edgeUpstream, Cx);
444 propagateTokensOverEdges(todoEdges,
450 //System.out.println( edgeY.getBetaNew() + "\nbeing pruned by\n" + hrnX.getAlpha() );
452 // create the actual reference edge hrnX.f -> hrnY
453 ReferenceEdge edgeNew = new ReferenceEdge(hrnX,
457 edgeY.getBetaNew().pruneBy(hrnX.getAlpha() )
458 //edgeY.getBeta().pruneBy( hrnX.getAlpha() )
460 addReferenceEdge(hrnX, hrnY, edgeNew);
464 // we can do a strong update here if one of two cases holds
465 // SAVE FOR LATER, WITHOUT STILL CORRECT
466 if( (hrnX.getNumReferencers() == 1) ||
467 ( lnX.getNumReferencees() == 1 && hrnX.isSingleObject() )
469 clearReferenceEdgesFrom( hrnX, f, false );
472 addReferenceEdge( hrnX, hrnY, edgeNew );
475 // if the field is null, or "any" field, then
476 // look to see if an any field already exists
477 // and merge with it, otherwise just add the edge
478 ReferenceEdge edgeExisting = hrnX.getReferenceTo( hrnY, f );
480 if( edgeExisting != null ) {
481 edgeExisting.setBetaNew(
482 edgeExisting.getBetaNew().union( edgeNew.getBeta() )
484 // a new edge here cannot be reflexive, so existing will
485 // always be also not reflexive anymore
486 edgeExisting.setIsInitialParamReflexive( false );
489 addReferenceEdge( hrnX, hrnY, edgeNew );
496 Iterator<HeapRegionNode> nodeItr = nodesWithNewAlpha.iterator();
497 while( nodeItr.hasNext() ) {
498 nodeItr.next().applyAlphaNew();
501 Iterator<ReferenceEdge> edgeItr = edgesWithNewBeta.iterator();
502 while( edgeItr.hasNext() ) {
503 edgeItr.next().applyBetaNew();
508 public void assignParameterAllocationToTemp(boolean isTask,
510 Integer paramIndex) {
513 LabelNode lnParam = getLabelNodeFromTemp(td);
514 HeapRegionNode hrn = createNewHeapRegionNode(null,
521 "param" + paramIndex);
523 // this is a non-program-accessible label that picks up beta
524 // info to be used for fixing a caller of this method
525 TempDescriptor tdParamQ = new TempDescriptor(td+"specialQ");
526 LabelNode lnParamQ = getLabelNodeFromTemp(tdParamQ);
528 // keep track of heap regions that were created for
529 // parameter labels, the index of the parameter they
530 // are for is important when resolving method calls
531 Integer newID = hrn.getID();
532 assert !id2paramIndex.containsKey(newID);
533 assert !id2paramIndex.containsValue(paramIndex);
534 id2paramIndex.put(newID, paramIndex);
535 paramIndex2id.put(paramIndex, newID);
536 paramIndex2tdQ.put(paramIndex, tdParamQ);
538 ReachabilitySet beta = new ReachabilitySet(new TokenTuple(newID,
540 TokenTuple.ARITY_ONE) );
542 // heap regions for parameters are always multiple object (see above)
543 // and have a reference to themselves, because we can't know the
544 // structure of memory that is passed into the method. We're assuming
547 ReferenceEdge edgeFromLabel =
548 new ReferenceEdge(lnParam, hrn, null, false, beta);
550 ReferenceEdge edgeFromLabelQ =
551 new ReferenceEdge(lnParamQ, hrn, null, false, beta);
553 ReferenceEdge edgeReflexive =
554 new ReferenceEdge(hrn, hrn, null, true, beta);
556 addReferenceEdge(lnParam, hrn, edgeFromLabel);
557 addReferenceEdge(lnParamQ, hrn, edgeFromLabelQ);
558 addReferenceEdge(hrn, hrn, edgeReflexive);
562 public void assignNewAllocationToTempX(TempDescriptor x,
569 // after the age operation the newest (or zero-ith oldest)
570 // node associated with the allocation site should have
571 // no references to it as if it were a newly allocated
572 // heap region, so make a reference to it to complete
575 Integer idNewest = as.getIthOldest(0);
576 HeapRegionNode hrnNewest = id2hrn.get(idNewest);
577 assert hrnNewest != null;
579 LabelNode lnX = getLabelNodeFromTemp(x);
580 clearReferenceEdgesFrom(lnX, null, true);
582 ReferenceEdge edgeNew =
583 new ReferenceEdge(lnX, hrnNewest, null, false, hrnNewest.getAlpha() );
585 addReferenceEdge(lnX, hrnNewest, edgeNew);
589 // use the allocation site (unique to entire analysis) to
590 // locate the heap region nodes in this ownership graph
591 // that should be aged. The process models the allocation
592 // of new objects and collects all the oldest allocations
593 // in a summary node to allow for a finite analysis
595 // There is an additional property of this method. After
596 // running it on a particular ownership graph (many graphs
597 // may have heap regions related to the same allocation site)
598 // the heap region node objects in this ownership graph will be
599 // allocated. Therefore, after aging a graph for an allocation
600 // site, attempts to retrieve the heap region nodes using the
601 // integer id's contained in the allocation site should always
602 // return non-null heap regions.
603 public void age(AllocationSite as) {
605 // aging adds this allocation site to the graph's
606 // list of sites that exist in the graph, or does
607 // nothing if the site is already in the list
608 allocationSites.add(as);
610 // get the summary node for the allocation site in the context
611 // of this particular ownership graph
612 HeapRegionNode hrnSummary = getSummaryNode(as);
614 // merge oldest node into summary
615 Integer idK = as.getOldest();
616 HeapRegionNode hrnK = id2hrn.get(idK);
617 mergeIntoSummary(hrnK, hrnSummary);
619 // move down the line of heap region nodes
620 // clobbering the ith and transferring all references
621 // to and from i-1 to node i. Note that this clobbers
622 // the oldest node (hrnK) that was just merged into
624 for( int i = allocationDepth - 1; i > 0; --i ) {
626 // move references from the i-1 oldest to the ith oldest
627 Integer idIth = as.getIthOldest(i);
628 HeapRegionNode hrnI = id2hrn.get(idIth);
629 Integer idImin1th = as.getIthOldest(i - 1);
630 HeapRegionNode hrnImin1 = id2hrn.get(idImin1th);
632 transferOnto(hrnImin1, hrnI);
635 // as stated above, the newest node should have had its
636 // references moved over to the second oldest, so we wipe newest
637 // in preparation for being the new object to assign something to
638 Integer id0th = as.getIthOldest(0);
639 HeapRegionNode hrn0 = id2hrn.get(id0th);
642 // clear all references in and out of newest node
643 clearReferenceEdgesFrom(hrn0, null, true);
644 clearReferenceEdgesTo(hrn0, null, true);
647 // now tokens in reachability sets need to "age" also
648 Iterator itrAllLabelNodes = td2ln.entrySet().iterator();
649 while( itrAllLabelNodes.hasNext() ) {
650 Map.Entry me = (Map.Entry)itrAllLabelNodes.next();
651 LabelNode ln = (LabelNode) me.getValue();
653 Iterator<ReferenceEdge> itrEdges = ln.iteratorToReferencees();
654 while( itrEdges.hasNext() ) {
655 ageTokens(as, itrEdges.next() );
659 Iterator itrAllHRNodes = id2hrn.entrySet().iterator();
660 while( itrAllHRNodes.hasNext() ) {
661 Map.Entry me = (Map.Entry)itrAllHRNodes.next();
662 HeapRegionNode hrnToAge = (HeapRegionNode) me.getValue();
664 ageTokens(as, hrnToAge);
666 Iterator<ReferenceEdge> itrEdges = hrnToAge.iteratorToReferencees();
667 while( itrEdges.hasNext() ) {
668 ageTokens(as, itrEdges.next() );
673 // after tokens have been aged, reset newest node's reachability
674 if( hrn0.isFlagged() ) {
675 hrn0.setAlpha(new ReachabilitySet(new TokenTupleSet(
681 hrn0.setAlpha(new ReachabilitySet(new TokenTupleSet()
688 protected HeapRegionNode getSummaryNode(AllocationSite as) {
690 Integer idSummary = as.getSummary();
691 HeapRegionNode hrnSummary = id2hrn.get(idSummary);
693 // If this is null then we haven't touched this allocation site
694 // in the context of the current ownership graph, so allocate
695 // heap region nodes appropriate for the entire allocation site.
696 // This should only happen once per ownership graph per allocation site,
697 // and a particular integer id can be used to locate the heap region
698 // in different ownership graphs that represents the same part of an
700 if( hrnSummary == null ) {
702 boolean hasFlags = false;
703 if( as.getType().isClass() ) {
704 hasFlags = as.getType().getClassDesc().hasFlags();
707 hrnSummary = createNewHeapRegionNode(idSummary,
714 as + "\\n" + as.getType() + "\\nsummary");
716 for( int i = 0; i < as.getAllocationDepth(); ++i ) {
717 Integer idIth = as.getIthOldest(i);
718 assert !id2hrn.containsKey(idIth);
719 createNewHeapRegionNode(idIth,
726 as + "\\n" + as.getType() + "\\n" + i + " oldest");
734 protected HeapRegionNode getShadowSummaryNode(AllocationSite as) {
736 Integer idShadowSummary = as.getSummaryShadow();
737 HeapRegionNode hrnShadowSummary = id2hrn.get(idShadowSummary);
739 if( hrnShadowSummary == null ) {
741 boolean hasFlags = false;
742 if( as.getType().isClass() ) {
743 hasFlags = as.getType().getClassDesc().hasFlags();
746 hrnShadowSummary = createNewHeapRegionNode(idShadowSummary,
753 as + "\\n" + as.getType() + "\\nshadowSum");
755 for( int i = 0; i < as.getAllocationDepth(); ++i ) {
756 Integer idShadowIth = as.getIthOldestShadow(i);
757 assert !id2hrn.containsKey(idShadowIth);
758 createNewHeapRegionNode(idShadowIth,
765 as + "\\n" + as.getType() + "\\n" + i + " shadow");
769 return hrnShadowSummary;
773 protected void mergeIntoSummary(HeapRegionNode hrn, HeapRegionNode hrnSummary) {
774 assert hrnSummary.isNewSummary();
776 // transfer references _from_ hrn over to hrnSummary
777 Iterator<ReferenceEdge> itrReferencee = hrn.iteratorToReferencees();
778 while( itrReferencee.hasNext() ) {
779 ReferenceEdge edge = itrReferencee.next();
780 ReferenceEdge edgeMerged = edge.copy();
781 edgeMerged.setSrc(hrnSummary);
783 HeapRegionNode hrnReferencee = edge.getDst();
784 ReferenceEdge edgeSummary = hrnSummary.getReferenceTo(hrnReferencee, edge.getFieldDesc() );
786 if( edgeSummary == null ) {
787 // the merge is trivial, nothing to be done
789 // otherwise an edge from the referencer to hrnSummary exists already
790 // and the edge referencer->hrn should be merged with it
791 edgeMerged.setBeta(edgeMerged.getBeta().union(edgeSummary.getBeta() ) );
794 addReferenceEdge(hrnSummary, hrnReferencee, edgeMerged);
797 // next transfer references _to_ hrn over to hrnSummary
798 Iterator<ReferenceEdge> itrReferencer = hrn.iteratorToReferencers();
799 while( itrReferencer.hasNext() ) {
800 ReferenceEdge edge = itrReferencer.next();
801 ReferenceEdge edgeMerged = edge.copy();
802 edgeMerged.setDst(hrnSummary);
804 OwnershipNode onReferencer = edge.getSrc();
805 ReferenceEdge edgeSummary = onReferencer.getReferenceTo(hrnSummary, edge.getFieldDesc() );
807 if( edgeSummary == null ) {
808 // the merge is trivial, nothing to be done
810 // otherwise an edge from the referencer to alpha_S exists already
811 // and the edge referencer->alpha_K should be merged with it
812 edgeMerged.setBeta(edgeMerged.getBeta().union(edgeSummary.getBeta() ) );
815 addReferenceEdge(onReferencer, hrnSummary, edgeMerged);
818 // then merge hrn reachability into hrnSummary
819 hrnSummary.setAlpha(hrnSummary.getAlpha().union(hrn.getAlpha() ) );
823 protected void transferOnto(HeapRegionNode hrnA, HeapRegionNode hrnB) {
825 // clear references in and out of node i
826 clearReferenceEdgesFrom(hrnB, null, true);
827 clearReferenceEdgesTo(hrnB, null, true);
829 // copy each edge in and out of A to B
830 Iterator<ReferenceEdge> itrReferencee = hrnA.iteratorToReferencees();
831 while( itrReferencee.hasNext() ) {
832 ReferenceEdge edge = itrReferencee.next();
833 HeapRegionNode hrnReferencee = edge.getDst();
834 ReferenceEdge edgeNew = edge.copy();
835 edgeNew.setSrc(hrnB);
837 addReferenceEdge(hrnB, hrnReferencee, edgeNew);
840 Iterator<ReferenceEdge> itrReferencer = hrnA.iteratorToReferencers();
841 while( itrReferencer.hasNext() ) {
842 ReferenceEdge edge = itrReferencer.next();
843 OwnershipNode onReferencer = edge.getSrc();
844 ReferenceEdge edgeNew = edge.copy();
845 edgeNew.setDst(hrnB);
847 addReferenceEdge(onReferencer, hrnB, edgeNew);
850 // replace hrnB reachability with hrnA's
851 hrnB.setAlpha(hrnA.getAlpha() );
855 protected void ageTokens(AllocationSite as, ReferenceEdge edge) {
856 edge.setBeta(edge.getBeta().ageTokens(as) );
859 protected void ageTokens(AllocationSite as, HeapRegionNode hrn) {
860 hrn.setAlpha(hrn.getAlpha().ageTokens(as) );
864 public void resolveMethodCall(FlatCall fc,
867 OwnershipGraph ogCallee) {
870 // define rewrite rules and other structures to organize
871 // data by parameter/argument index
872 Hashtable<Integer, ReachabilitySet> paramIndex2rewriteH =
873 new Hashtable<Integer, ReachabilitySet>();
875 Hashtable<Integer, ReachabilitySet> paramIndex2rewriteJ =
876 new Hashtable<Integer, ReachabilitySet>();
878 Hashtable<Integer, ReachabilitySet> paramIndex2rewriteK =
879 new Hashtable<Integer, ReachabilitySet>();
881 Hashtable<Integer, ReachabilitySet> paramIndex2rewriteD =
882 new Hashtable<Integer, ReachabilitySet>();
884 // helpful structures
885 Hashtable<TokenTuple, Integer> paramToken2paramIndex =
886 new Hashtable<TokenTuple, Integer>();
888 Hashtable<Integer, TokenTuple> paramIndex2paramToken =
889 new Hashtable<Integer, TokenTuple>();
891 Hashtable<TokenTuple, Integer> paramTokenStar2paramIndex =
892 new Hashtable<TokenTuple, Integer>();
894 Hashtable<Integer, TokenTuple> paramIndex2paramTokenStar =
895 new Hashtable<Integer, TokenTuple>();
897 Hashtable<Integer, LabelNode> paramIndex2ln =
898 new Hashtable<Integer, LabelNode>();
900 Hashtable<Integer, HashSet<HeapRegionNode> > paramIndex2reachableCallerNodes =
901 new Hashtable<Integer, HashSet<HeapRegionNode> >();
904 // add a bogus entry with the identity rule for easy rewrite
905 // of new callee nodes and edges, doesn't belong to any parameter
906 Integer bogusID = new Integer( -1 );
907 Integer bogusIndex = new Integer( -1 );
908 TokenTuple bogusToken = new TokenTuple( bogusID, true, TokenTuple.ARITY_ONE );
909 TokenTuple bogusTokenStar = new TokenTuple( bogusID, true, TokenTuple.ARITY_MANY );
910 ReachabilitySet rsIdentity =
911 new ReachabilitySet( new TokenTupleSet( bogusToken ).makeCanonical() ).makeCanonical();
913 paramIndex2rewriteH.put( bogusIndex, rsIdentity );
914 paramIndex2rewriteJ.put( bogusIndex, rsIdentity );
915 paramToken2paramIndex.put( bogusToken, bogusIndex );
916 paramIndex2paramToken.put( bogusIndex, bogusToken );
917 paramTokenStar2paramIndex.put( bogusTokenStar, bogusIndex );
918 paramIndex2paramTokenStar.put( bogusIndex, bogusTokenStar );
921 for( int i = 0; i < fm.numParameters(); ++i ) {
922 Integer paramIndex = new Integer( i );
924 assert ogCallee.paramIndex2id.containsKey( paramIndex );
925 Integer idParam = ogCallee.paramIndex2id.get( paramIndex );
927 assert ogCallee.id2hrn.containsKey( idParam );
928 HeapRegionNode hrnParam = ogCallee.id2hrn.get( idParam );
929 assert hrnParam != null;
930 paramIndex2rewriteH.put( paramIndex,
931 toShadowTokens( ogCallee, hrnParam.getAlpha() )
934 ReferenceEdge edgeReflexive_i = hrnParam.getReferenceTo( hrnParam, null );
935 assert edgeReflexive_i != null;
936 paramIndex2rewriteJ.put( paramIndex,
937 toShadowTokens( ogCallee, edgeReflexive_i.getBeta() )
940 TempDescriptor tdParamQ = ogCallee.paramIndex2tdQ.get( paramIndex );
941 assert tdParamQ != null;
942 LabelNode lnParamQ = ogCallee.td2ln.get( tdParamQ );
943 assert lnParamQ != null;
944 ReferenceEdge edgeSpecialQ_i = lnParamQ.getReferenceTo( hrnParam, null );
945 assert edgeSpecialQ_i != null;
946 paramIndex2rewriteK.put( paramIndex,
947 toShadowTokens( ogCallee, edgeSpecialQ_i.getBeta() )
950 TokenTuple p_i = new TokenTuple( hrnParam.getID(),
952 TokenTuple.ARITY_ONE ).makeCanonical();
953 paramToken2paramIndex.put( p_i, paramIndex );
954 paramIndex2paramToken.put( paramIndex, p_i );
956 TokenTuple p_i_star = new TokenTuple( hrnParam.getID(),
958 TokenTuple.ARITY_MANY ).makeCanonical();
959 paramTokenStar2paramIndex.put( p_i_star, paramIndex );
960 paramIndex2paramTokenStar.put( paramIndex, p_i_star );
962 // now depending on whether the callee is static or not
963 // we need to account for a "this" argument in order to
964 // find the matching argument in the caller context
965 TempDescriptor argTemp_i;
967 argTemp_i = fc.getArg( paramIndex );
969 if( paramIndex == 0 ) {
970 argTemp_i = fc.getThis();
972 argTemp_i = fc.getArg( paramIndex - 1 );
976 // in non-static methods there is a "this" pointer
977 // that should be taken into account
979 assert fc.numArgs() == fm.numParameters();
981 assert fc.numArgs() + 1 == fm.numParameters();
984 LabelNode argLabel_i = getLabelNodeFromTemp( argTemp_i );
985 paramIndex2ln.put( paramIndex, argLabel_i );
987 ReachabilitySet D_i = new ReachabilitySet().makeCanonical();
988 Iterator<ReferenceEdge> edgeItr = argLabel_i.iteratorToReferencees();
989 while( edgeItr.hasNext() ) {
990 ReferenceEdge edge = edgeItr.next();
991 D_i = D_i.union( edge.getBeta() );
993 D_i = D_i.exhaustiveArityCombinations();
994 paramIndex2rewriteD.put( paramIndex, D_i );
998 HashSet<HeapRegionNode> nodesWithNewAlpha = new HashSet<HeapRegionNode>();
999 HashSet<ReferenceEdge> edgesWithNewBeta = new HashSet<ReferenceEdge>();
1001 HashSet<ReferenceEdge> edgesReachable = new HashSet<ReferenceEdge>();
1002 HashSet<ReferenceEdge> edgesUpstream = new HashSet<ReferenceEdge>();
1004 Iterator lnArgItr = paramIndex2ln.entrySet().iterator();
1005 while( lnArgItr.hasNext() ) {
1006 Map.Entry me = (Map.Entry) lnArgItr.next();
1007 Integer index = (Integer) me.getKey();
1008 LabelNode lnArg_i = (LabelNode) me.getValue();
1010 // rewrite alpha for the nodes reachable from argument label i
1011 HashSet<HeapRegionNode> reachableNodes = new HashSet<HeapRegionNode>();
1012 HashSet<HeapRegionNode> todoNodes = new HashSet<HeapRegionNode>();
1014 // to find all reachable nodes, start with label referencees
1015 Iterator<ReferenceEdge> edgeArgItr = lnArg_i.iteratorToReferencees();
1016 while( edgeArgItr.hasNext() ) {
1017 ReferenceEdge edge = edgeArgItr.next();
1018 todoNodes.add( edge.getDst() );
1021 // then follow links until all reachable nodes have been found
1022 while( !todoNodes.isEmpty() ) {
1023 HeapRegionNode hrn = todoNodes.iterator().next();
1024 todoNodes.remove( hrn );
1025 reachableNodes.add( hrn );
1027 Iterator<ReferenceEdge> edgeItr = hrn.iteratorToReferencees();
1028 while( edgeItr.hasNext() ) {
1029 ReferenceEdge edge = edgeItr.next();
1031 if( !reachableNodes.contains( edge.getDst() ) ) {
1032 todoNodes.add( edge.getDst() );
1038 paramIndex2reachableCallerNodes.put( index, reachableNodes );
1040 // now iterate over reachable nodes to update their alpha, and
1041 // classify edges found as "argument reachable" or "upstream"
1042 Iterator<HeapRegionNode> hrnItr = reachableNodes.iterator();
1043 while( hrnItr.hasNext() ) {
1044 HeapRegionNode hrn = hrnItr.next();
1046 rewriteCallerNodeAlpha( fm.numParameters(),
1049 paramIndex2rewriteH,
1050 paramIndex2rewriteD,
1051 paramIndex2paramToken,
1052 paramIndex2paramTokenStar );
1054 nodesWithNewAlpha.add( hrn );
1056 // look at all incoming edges to the reachable nodes
1057 // and sort them as edges reachable from the argument
1058 // label node, or upstream edges
1059 Iterator<ReferenceEdge> edgeItr = hrn.iteratorToReferencers();
1060 while( edgeItr.hasNext() ) {
1061 ReferenceEdge edge = edgeItr.next();
1063 OwnershipNode on = edge.getSrc();
1065 if( on instanceof LabelNode ) {
1067 LabelNode ln0 = (LabelNode) on;
1068 if( ln0.equals( lnArg_i ) ) {
1069 edgesReachable.add( edge );
1071 edgesUpstream.add( edge );
1076 HeapRegionNode hrn0 = (HeapRegionNode) on;
1077 if( reachableNodes.contains( hrn0 ) ) {
1078 edgesReachable.add( edge );
1080 edgesUpstream.add( edge );
1087 // update reachable edges
1088 Iterator<ReferenceEdge> edgeReachableItr = edgesReachable.iterator();
1089 while( edgeReachableItr.hasNext() ) {
1090 ReferenceEdge edgeReachable = edgeReachableItr.next();
1092 rewriteCallerEdgeBeta( fm.numParameters(),
1095 paramIndex2rewriteJ,
1096 paramIndex2rewriteD,
1097 paramIndex2paramToken,
1098 paramIndex2paramTokenStar,
1102 edgesWithNewBeta.add( edgeReachable );
1106 // update upstream edges
1107 Hashtable<ReferenceEdge, ChangeTupleSet> edgeUpstreamPlannedChanges
1108 = new Hashtable<ReferenceEdge, ChangeTupleSet>();
1110 Iterator<ReferenceEdge> edgeUpstreamItr = edgesUpstream.iterator();
1111 while( edgeUpstreamItr.hasNext() ) {
1112 ReferenceEdge edgeUpstream = edgeUpstreamItr.next();
1114 rewriteCallerEdgeBeta( fm.numParameters(),
1117 paramIndex2rewriteK,
1118 paramIndex2rewriteD,
1119 paramIndex2paramToken,
1120 paramIndex2paramTokenStar,
1122 edgeUpstreamPlannedChanges );
1124 edgesWithNewBeta.add( edgeUpstream );
1127 propagateTokensOverEdges( edgesUpstream,
1128 edgeUpstreamPlannedChanges,
1133 // commit changes to alpha and beta
1134 Iterator<HeapRegionNode> nodeItr = nodesWithNewAlpha.iterator();
1135 while( nodeItr.hasNext() ) {
1136 nodeItr.next().applyAlphaNew();
1139 Iterator<ReferenceEdge> edgeItr = edgesWithNewBeta.iterator();
1140 while( edgeItr.hasNext() ) {
1141 edgeItr.next().applyBetaNew();
1146 // verify the existence of allocation sites and their
1147 // shadows from the callee in the context of this caller graph
1148 // then map allocated nodes of callee onto the caller shadows
1150 Iterator<AllocationSite> asItr = ogCallee.allocationSites.iterator();
1151 while( asItr.hasNext() ) {
1152 AllocationSite allocSite = asItr.next();
1153 HeapRegionNode hrnSummary = getSummaryNode( allocSite );
1155 // assert that the shadow nodes have no reference edges
1156 // because they're brand new to the graph, or last time
1157 // they were used they should have been cleared of edges
1158 HeapRegionNode hrnShadowSummary = getShadowSummaryNode( allocSite );
1159 assert hrnShadowSummary.getNumReferencers() == 0;
1160 assert hrnShadowSummary.getNumReferencees() == 0;
1162 // then bring g_ij onto g'_ij and rewrite
1163 transferOnto( hrnSummary, hrnShadowSummary );
1165 HeapRegionNode hrnSummaryCallee = ogCallee.getSummaryNode( allocSite );
1166 hrnShadowSummary.setAlpha( toShadowTokens( ogCallee, hrnSummaryCallee.getAlpha() ) );
1168 // shadow nodes only are touched by a rewrite one time,
1169 // so rewrite and immediately commit--and they don't belong
1170 // to a particular parameter, so use a bogus param index
1171 // that pulls a self-rewrite out of H
1172 rewriteCallerNodeAlpha( fm.numParameters(),
1175 paramIndex2rewriteH,
1176 paramIndex2rewriteD,
1177 paramIndex2paramToken,
1178 paramIndex2paramTokenStar );
1180 hrnShadowSummary.applyAlphaNew();
1183 for( int i = 0; i < allocSite.getAllocationDepth(); ++i ) {
1184 Integer idIth = allocSite.getIthOldest(i);
1185 assert id2hrn.containsKey(idIth);
1186 HeapRegionNode hrnIth = id2hrn.get(idIth);
1188 Integer idShadowIth = -(allocSite.getIthOldest(i));
1189 assert id2hrn.containsKey(idShadowIth);
1190 HeapRegionNode hrnIthShadow = id2hrn.get(idShadowIth);
1191 assert hrnIthShadow.getNumReferencers() == 0;
1192 assert hrnIthShadow.getNumReferencees() == 0;
1194 transferOnto( hrnIth, hrnIthShadow );
1196 assert ogCallee.id2hrn.containsKey(idIth);
1197 HeapRegionNode hrnIthCallee = ogCallee.id2hrn.get(idIth);
1198 hrnIthShadow.setAlpha( toShadowTokens( ogCallee, hrnIthCallee.getAlpha() ) );
1200 rewriteCallerNodeAlpha( fm.numParameters(),
1203 paramIndex2rewriteH,
1204 paramIndex2rewriteD,
1205 paramIndex2paramToken,
1206 paramIndex2paramTokenStar );
1208 hrnIthShadow.applyAlphaNew();
1214 writeGraph("test",true,true,true,false);
1215 } catch(Exception e){}
1218 // for every heap region->heap region edge in the
1219 // callee graph, create the matching edge or edges
1220 // in the caller graph
1221 Set sCallee = ogCallee.id2hrn.entrySet();
1222 Iterator iCallee = sCallee.iterator();
1223 while( iCallee.hasNext() ) {
1224 Map.Entry meCallee = (Map.Entry) iCallee.next();
1225 Integer idCallee = (Integer) meCallee.getKey();
1226 HeapRegionNode hrnCallee = (HeapRegionNode) meCallee.getValue();
1228 Iterator<ReferenceEdge> heapRegionsItrCallee = hrnCallee.iteratorToReferencees();
1229 while( heapRegionsItrCallee.hasNext() ) {
1230 ReferenceEdge edgeCallee = heapRegionsItrCallee.next();
1231 HeapRegionNode hrnChildCallee = edgeCallee.getDst();
1232 Integer idChildCallee = hrnChildCallee.getID();
1234 // only address this edge if it is not a special reflexive edge
1235 if( !edgeCallee.isInitialParamReflexive() ) {
1237 // now we know that in the callee method's ownership graph
1238 // there is a heap region->heap region reference edge given
1239 // by heap region pointers:
1240 // hrnCallee -> heapChildCallee
1242 // or by the ownership-graph independent ID's:
1243 // idCallee -> idChildCallee
1245 // make the edge with src and dst so beta info is
1246 // calculated once, then copy it for each new edge in caller
1247 ReferenceEdge edgeNewInCallerTemplate = new ReferenceEdge( null,
1249 edgeCallee.getFieldDesc(),
1251 toShadowTokens( ogCallee, edgeCallee.getBeta() )
1253 rewriteCallerEdgeBeta( fm.numParameters(),
1255 edgeNewInCallerTemplate,
1256 paramIndex2rewriteJ,
1257 paramIndex2rewriteD,
1258 paramIndex2paramToken,
1259 paramIndex2paramTokenStar,
1263 edgeNewInCallerTemplate.applyBetaNew();
1267 // So now make a set of possible source heaps in the caller graph
1268 // and a set of destination heaps in the caller graph, and make
1269 // a reference edge in the caller for every possible (src,dst) pair
1270 HashSet<HeapRegionNode> possibleCallerSrcs =
1271 getHRNSetThatPossiblyMapToCalleeHRN( ogCallee,
1274 paramIndex2reachableCallerNodes );
1276 HashSet<HeapRegionNode> possibleCallerDsts =
1277 getHRNSetThatPossiblyMapToCalleeHRN( ogCallee,
1280 paramIndex2reachableCallerNodes );
1282 // make every possible pair of {srcSet} -> {dstSet} edges in the caller
1283 Iterator srcItr = possibleCallerSrcs.iterator();
1284 while( srcItr.hasNext() ) {
1285 HeapRegionNode src = (HeapRegionNode) srcItr.next();
1287 Iterator dstItr = possibleCallerDsts.iterator();
1288 while( dstItr.hasNext() ) {
1289 HeapRegionNode dst = (HeapRegionNode) dstItr.next();
1291 ReferenceEdge edgeNewInCaller = edgeNewInCallerTemplate.copy();
1292 edgeNewInCaller.setSrc( src );
1293 edgeNewInCaller.setDst( dst );
1295 ReferenceEdge edgeExisting = src.getReferenceTo( dst, edgeNewInCaller.getFieldDesc() );
1296 if( edgeExisting == null ) {
1297 // if this edge doesn't exist in the caller, create it
1298 addReferenceEdge( src, dst, edgeNewInCaller );
1300 // if it already exists, merge with it
1301 edgeExisting.setBeta( edgeExisting.getBeta().union( edgeNewInCaller.getBeta() ) );
1310 // merge the shadow nodes of allocation sites back down to normal capacity
1311 Iterator<AllocationSite> allocItr = ogCallee.allocationSites.iterator();
1312 while( allocItr.hasNext() ) {
1313 AllocationSite as = allocItr.next();
1315 // first age each allocation site enough times to make room for the shadow nodes
1316 for( int i = 0; i < as.getAllocationDepth(); ++i ) {
1320 // then merge the shadow summary into the normal summary
1321 HeapRegionNode hrnSummary = getSummaryNode( as );
1322 assert hrnSummary != null;
1324 HeapRegionNode hrnSummaryShadow = getShadowSummaryNode( as );
1325 assert hrnSummaryShadow != null;
1327 mergeIntoSummary( hrnSummaryShadow, hrnSummary );
1329 // then transplant shadow nodes onto the now clean normal nodes
1330 for( int i = 0; i < as.getAllocationDepth(); ++i ) {
1332 Integer idIth = as.getIthOldest(i);
1333 HeapRegionNode hrnIth = id2hrn.get(idIth);
1335 Integer idIthShadow = as.getIthOldestShadow(i);
1336 HeapRegionNode hrnIthShadow = id2hrn.get(idIthShadow);
1338 transferOnto(hrnIthShadow, hrnIth);
1340 // clear off shadow nodes after transfer
1341 clearReferenceEdgesFrom(hrnIthShadow, null, true);
1342 clearReferenceEdgesTo(hrnIthShadow, null, true);
1343 hrnIthShadow.setAlpha( new ReachabilitySet().makeCanonical() );
1346 // finally, globally change shadow tokens into normal tokens
1347 Iterator itrAllLabelNodes = td2ln.entrySet().iterator();
1348 while( itrAllLabelNodes.hasNext() ) {
1349 Map.Entry me = (Map.Entry)itrAllLabelNodes.next();
1350 LabelNode ln = (LabelNode) me.getValue();
1352 Iterator<ReferenceEdge> itrEdges = ln.iteratorToReferencees();
1353 while( itrEdges.hasNext() ) {
1354 unshadowTokens(as, itrEdges.next() );
1358 Iterator itrAllHRNodes = id2hrn.entrySet().iterator();
1359 while( itrAllHRNodes.hasNext() ) {
1360 Map.Entry me = (Map.Entry)itrAllHRNodes.next();
1361 HeapRegionNode hrnToAge = (HeapRegionNode) me.getValue();
1363 unshadowTokens(as, hrnToAge);
1365 Iterator<ReferenceEdge> itrEdges = hrnToAge.iteratorToReferencees();
1366 while( itrEdges.hasNext() ) {
1367 unshadowTokens(as, itrEdges.next() );
1374 protected void unshadowTokens(AllocationSite as, ReferenceEdge edge) {
1375 edge.setBeta(edge.getBeta().unshadowTokens(as) );
1378 protected void unshadowTokens(AllocationSite as, HeapRegionNode hrn) {
1379 hrn.setAlpha(hrn.getAlpha().unshadowTokens(as) );
1383 private ReachabilitySet toShadowTokens( OwnershipGraph ogCallee,
1384 ReachabilitySet rsIn ) {
1386 ReachabilitySet rsOut = new ReachabilitySet( rsIn );
1388 Iterator<AllocationSite> allocItr = ogCallee.allocationSites.iterator();
1389 while( allocItr.hasNext() ) {
1390 AllocationSite as = allocItr.next();
1392 rsOut = rsOut.toShadowTokens( as );
1395 return rsOut.makeCanonical();
1399 private void rewriteCallerNodeAlpha( int numParameters,
1402 Hashtable<Integer, ReachabilitySet> paramIndex2rewriteH,
1403 Hashtable<Integer, ReachabilitySet> paramIndex2rewriteD,
1404 Hashtable<Integer, TokenTuple> paramIndex2paramToken,
1405 Hashtable<Integer, TokenTuple> paramIndex2paramTokenStar ) {
1407 ReachabilitySet rules = paramIndex2rewriteH.get( paramIndex );
1408 assert rules != null;
1410 TokenTuple tokenToRewrite = paramIndex2paramToken.get( paramIndex );
1411 assert tokenToRewrite != null;
1413 ReachabilitySet r0 = new ReachabilitySet().makeCanonical();
1414 Iterator<TokenTupleSet> ttsItr = rules.iterator();
1415 while( ttsItr.hasNext() ) {
1416 TokenTupleSet tts = ttsItr.next();
1417 r0 = r0.union( tts.rewriteToken( tokenToRewrite,
1423 ReachabilitySet r1 = new ReachabilitySet().makeCanonical();
1424 ttsItr = r0.iterator();
1425 while( ttsItr.hasNext() ) {
1426 TokenTupleSet tts = ttsItr.next();
1427 r1 = r1.union( rewriteDpass( numParameters,
1430 paramIndex2rewriteD,
1431 paramIndex2paramToken,
1432 paramIndex2paramTokenStar ) );
1435 hrn.setAlphaNew( hrn.getAlphaNew().union( r1 ) );
1439 private void rewriteCallerEdgeBeta( int numParameters,
1442 Hashtable<Integer, ReachabilitySet> paramIndex2rewriteJorK,
1443 Hashtable<Integer, ReachabilitySet> paramIndex2rewriteD,
1444 Hashtable<Integer, TokenTuple> paramIndex2paramToken,
1445 Hashtable<Integer, TokenTuple> paramIndex2paramTokenStar,
1446 boolean makeChangeSet,
1447 Hashtable<ReferenceEdge, ChangeTupleSet> edgePlannedChanges) {
1449 ReachabilitySet rules = paramIndex2rewriteJorK.get( paramIndex );
1450 assert rules != null;
1452 TokenTuple tokenToRewrite = paramIndex2paramToken.get( paramIndex );
1453 assert tokenToRewrite != null;
1455 ChangeTupleSet cts0 = new ChangeTupleSet().makeCanonical();
1457 Iterator<TokenTupleSet> ttsItr = rules.iterator();
1458 while( ttsItr.hasNext() ) {
1459 TokenTupleSet tts = ttsItr.next();
1461 Hashtable<TokenTupleSet, TokenTupleSet> forChangeSet =
1462 new Hashtable<TokenTupleSet, TokenTupleSet>();
1464 ReachabilitySet rTemp = tts.rewriteToken( tokenToRewrite,
1469 Iterator fcsItr = forChangeSet.entrySet().iterator();
1470 while( fcsItr.hasNext() ) {
1471 Map.Entry me = (Map.Entry) fcsItr.next();
1472 TokenTupleSet ttsMatch = (TokenTupleSet) me.getKey();
1473 TokenTupleSet ttsAdd = (TokenTupleSet) me.getValue();
1475 ChangeTuple ct = new ChangeTuple( ttsMatch,
1479 cts0 = cts0.union( ct );
1484 ReachabilitySet r1 = new ReachabilitySet().makeCanonical();
1485 ChangeTupleSet cts1 = new ChangeTupleSet().makeCanonical();
1487 Iterator<ChangeTuple> ctItr = cts0.iterator();
1488 while( ctItr.hasNext() ) {
1489 ChangeTuple ct = ctItr.next();
1491 ReachabilitySet rTemp = rewriteDpass( numParameters,
1494 paramIndex2rewriteD,
1495 paramIndex2paramToken,
1496 paramIndex2paramTokenStar
1498 r1 = r1.union( rTemp );
1500 if( makeChangeSet ) {
1501 assert edgePlannedChanges != null;
1503 Iterator<TokenTupleSet> ttsTempItr = rTemp.iterator();
1504 while( ttsTempItr.hasNext() ) {
1505 TokenTupleSet tts = ttsTempItr.next();
1507 ChangeTuple ctFinal = new ChangeTuple( ct.getSetToMatch(),
1511 cts1 = cts1.union( ctFinal );
1516 if( makeChangeSet ) {
1517 edgePlannedChanges.put( edge, cts1 );
1520 edge.setBetaNew( edge.getBetaNew().union( r1 ) );
1524 private ReachabilitySet rewriteDpass( int numParameters,
1526 TokenTupleSet ttsIn,
1527 Hashtable<Integer, ReachabilitySet> paramIndex2rewriteD,
1528 Hashtable<Integer, TokenTuple> paramIndex2paramToken,
1529 Hashtable<Integer, TokenTuple> paramIndex2paramTokenStar ) {
1531 ReachabilitySet rsOut = new ReachabilitySet().makeCanonical();
1533 boolean rewritten = false;
1535 for( int j = 0; j < numParameters; ++j ) {
1536 Integer paramIndexJ = new Integer( j );
1537 ReachabilitySet D_j = paramIndex2rewriteD.get( paramIndexJ );
1540 if( paramIndexJ != paramIndex ) {
1541 TokenTuple tokenToRewriteJ = paramIndex2paramToken.get( paramIndexJ );
1542 assert tokenToRewriteJ != null;
1543 if( ttsIn.containsTuple( tokenToRewriteJ ) ) {
1544 ReachabilitySet r = ttsIn.rewriteToken( tokenToRewriteJ,
1548 Iterator<TokenTupleSet> ttsItr = r.iterator();
1549 while( ttsItr.hasNext() ) {
1550 TokenTupleSet tts = ttsItr.next();
1551 rsOut = rsOut.union( rewriteDpass( numParameters,
1554 paramIndex2rewriteD,
1555 paramIndex2paramToken,
1556 paramIndex2paramTokenStar ) );
1562 TokenTuple tokenStarToRewriteJ = paramIndex2paramTokenStar.get( paramIndexJ );
1563 assert tokenStarToRewriteJ != null;
1564 if( ttsIn.containsTuple( tokenStarToRewriteJ ) ) {
1565 ReachabilitySet r = ttsIn.rewriteToken( tokenStarToRewriteJ,
1569 Iterator<TokenTupleSet> ttsItr = r.iterator();
1570 while( ttsItr.hasNext() ) {
1571 TokenTupleSet tts = ttsItr.next();
1572 rsOut = rsOut.union( rewriteDpass( numParameters,
1575 paramIndex2rewriteD,
1576 paramIndex2paramToken,
1577 paramIndex2paramTokenStar ) );
1584 rsOut = rsOut.union( ttsIn );
1591 private HashSet<HeapRegionNode>
1592 getHRNSetThatPossiblyMapToCalleeHRN( OwnershipGraph ogCallee,
1593 ReferenceEdge edgeCallee,
1595 Hashtable<Integer, HashSet<HeapRegionNode> > paramIndex2reachableCallerNodes
1598 HashSet<HeapRegionNode> possibleCallerHRNs = new HashSet<HeapRegionNode>();
1600 HeapRegionNode hrnCallee;
1602 OwnershipNode on = edgeCallee.getSrc();
1603 assert on instanceof HeapRegionNode;
1604 hrnCallee = (HeapRegionNode) on;
1606 hrnCallee = edgeCallee.getDst();
1609 Integer paramIndexCallee = ogCallee.id2paramIndex.get( hrnCallee.getID() );
1611 if( paramIndexCallee == null ) {
1612 // this is a node allocated in the callee then and it has
1613 // exactly one shadow node in the caller to map to
1614 AllocationSite as = hrnCallee.getAllocationSite();
1617 int age = as.getAgeCategory( hrnCallee.getID() );
1618 assert age != AllocationSite.AGE_notInThisSite;
1621 if( age == AllocationSite.AGE_summary ) {
1622 idCaller = as.getSummaryShadow();
1623 } else if( age == AllocationSite.AGE_oldest ) {
1624 idCaller = as.getOldestShadow();
1626 assert age == AllocationSite.AGE_in_I;
1628 Integer I = as.getAge( hrnCallee.getID() );
1631 idCaller = as.getIthOldestShadow( I );
1634 assert id2hrn.containsKey( idCaller );
1635 HeapRegionNode hrnCaller = id2hrn.get( idCaller );
1636 possibleCallerHRNs.add( hrnCaller );
1639 // this is a node that was created to represent a parameter
1640 // so it maps to a whole mess of heap regions
1641 assert paramIndex2reachableCallerNodes.containsKey( paramIndexCallee );
1642 possibleCallerHRNs = paramIndex2reachableCallerNodes.get( paramIndexCallee );
1644 // TODO PRUNE BY TYPE/FIELD NAME!!
1647 return possibleCallerHRNs;
1652 ////////////////////////////////////////////////////
1653 // in merge() and equals() methods the suffix A
1654 // represents the passed in graph and the suffix
1655 // B refers to the graph in this object
1656 // Merging means to take the incoming graph A and
1657 // merge it into B, so after the operation graph B
1658 // is the final result.
1659 ////////////////////////////////////////////////////
1660 public void merge(OwnershipGraph og) {
1666 mergeOwnershipNodes(og);
1667 mergeReferenceEdges(og);
1668 mergeId2paramIndex(og);
1669 mergeAllocationSites(og);
1673 protected void mergeOwnershipNodes(OwnershipGraph og) {
1674 Set sA = og.id2hrn.entrySet();
1675 Iterator iA = sA.iterator();
1676 while( iA.hasNext() ) {
1677 Map.Entry meA = (Map.Entry)iA.next();
1678 Integer idA = (Integer) meA.getKey();
1679 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1681 // if this graph doesn't have a node the
1682 // incoming graph has, allocate it
1683 if( !id2hrn.containsKey(idA) ) {
1684 HeapRegionNode hrnB = hrnA.copy();
1685 id2hrn.put(idA, hrnB);
1688 // otherwise this is a node present in both graphs
1689 // so make the new reachability set a union of the
1690 // nodes' reachability sets
1691 HeapRegionNode hrnB = id2hrn.get(idA);
1692 hrnB.setAlpha(hrnB.getAlpha().union(hrnA.getAlpha() ) );
1696 // now add any label nodes that are in graph B but
1698 sA = og.td2ln.entrySet();
1700 while( iA.hasNext() ) {
1701 Map.Entry meA = (Map.Entry)iA.next();
1702 TempDescriptor tdA = (TempDescriptor) meA.getKey();
1703 LabelNode lnA = (LabelNode) meA.getValue();
1705 // if the label doesn't exist in B, allocate and add it
1706 LabelNode lnB = getLabelNodeFromTemp(tdA);
1710 protected void mergeReferenceEdges(OwnershipGraph og) {
1713 Set sA = og.id2hrn.entrySet();
1714 Iterator iA = sA.iterator();
1715 while( iA.hasNext() ) {
1716 Map.Entry meA = (Map.Entry)iA.next();
1717 Integer idA = (Integer) meA.getKey();
1718 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1720 Iterator<ReferenceEdge> heapRegionsItrA = hrnA.iteratorToReferencees();
1721 while( heapRegionsItrA.hasNext() ) {
1722 ReferenceEdge edgeA = heapRegionsItrA.next();
1723 HeapRegionNode hrnChildA = edgeA.getDst();
1724 Integer idChildA = hrnChildA.getID();
1726 // at this point we know an edge in graph A exists
1727 // idA -> idChildA, does this exist in B?
1728 assert id2hrn.containsKey(idA);
1729 HeapRegionNode hrnB = id2hrn.get(idA);
1730 ReferenceEdge edgeToMerge = null;
1732 Iterator<ReferenceEdge> heapRegionsItrB = hrnB.iteratorToReferencees();
1733 while( heapRegionsItrB.hasNext() &&
1734 edgeToMerge == null ) {
1736 ReferenceEdge edgeB = heapRegionsItrB.next();
1737 HeapRegionNode hrnChildB = edgeB.getDst();
1738 Integer idChildB = hrnChildB.getID();
1740 // don't use the ReferenceEdge.equals() here because
1741 // we're talking about existence between graphs
1742 if( idChildB.equals(idChildA) &&
1743 edgeB.getFieldDesc() == edgeA.getFieldDesc() ) {
1744 edgeToMerge = edgeB;
1748 // if the edge from A was not found in B,
1750 if( edgeToMerge == null ) {
1751 assert id2hrn.containsKey(idChildA);
1752 HeapRegionNode hrnChildB = id2hrn.get(idChildA);
1753 edgeToMerge = edgeA.copy();
1754 edgeToMerge.setSrc(hrnB);
1755 edgeToMerge.setDst(hrnChildB);
1756 addReferenceEdge(hrnB, hrnChildB, edgeToMerge);
1758 // otherwise, the edge already existed in both graphs
1759 // so merge their reachability sets
1761 // just replace this beta set with the union
1762 assert edgeToMerge != null;
1763 edgeToMerge.setBeta(
1764 edgeToMerge.getBeta().union(edgeA.getBeta() )
1766 if( !edgeA.isInitialParamReflexive() ) {
1767 edgeToMerge.setIsInitialParamReflexive(false);
1773 // and then again with label nodes
1774 sA = og.td2ln.entrySet();
1776 while( iA.hasNext() ) {
1777 Map.Entry meA = (Map.Entry)iA.next();
1778 TempDescriptor tdA = (TempDescriptor) meA.getKey();
1779 LabelNode lnA = (LabelNode) meA.getValue();
1781 Iterator<ReferenceEdge> heapRegionsItrA = lnA.iteratorToReferencees();
1782 while( heapRegionsItrA.hasNext() ) {
1783 ReferenceEdge edgeA = heapRegionsItrA.next();
1784 HeapRegionNode hrnChildA = edgeA.getDst();
1785 Integer idChildA = hrnChildA.getID();
1787 // at this point we know an edge in graph A exists
1788 // tdA -> idChildA, does this exist in B?
1789 assert td2ln.containsKey(tdA);
1790 LabelNode lnB = td2ln.get(tdA);
1791 ReferenceEdge edgeToMerge = null;
1793 // labels never have edges with a field
1794 //assert edgeA.getFieldDesc() == null;
1796 Iterator<ReferenceEdge> heapRegionsItrB = lnB.iteratorToReferencees();
1797 while( heapRegionsItrB.hasNext() &&
1798 edgeToMerge == null ) {
1800 ReferenceEdge edgeB = heapRegionsItrB.next();
1801 HeapRegionNode hrnChildB = edgeB.getDst();
1802 Integer idChildB = hrnChildB.getID();
1804 // labels never have edges with a field
1805 //assert edgeB.getFieldDesc() == null;
1807 // don't use the ReferenceEdge.equals() here because
1808 // we're talking about existence between graphs
1809 if( idChildB.equals(idChildA) &&
1810 edgeB.getFieldDesc() == edgeA.getFieldDesc() ) {
1811 edgeToMerge = edgeB;
1815 // if the edge from A was not found in B,
1817 if( edgeToMerge == null ) {
1818 assert id2hrn.containsKey(idChildA);
1819 HeapRegionNode hrnChildB = id2hrn.get(idChildA);
1820 edgeToMerge = edgeA.copy();
1821 edgeToMerge.setSrc(lnB);
1822 edgeToMerge.setDst(hrnChildB);
1823 addReferenceEdge(lnB, hrnChildB, edgeToMerge);
1825 // otherwise, the edge already existed in both graphs
1826 // so merge their reachability sets
1828 // just replace this beta set with the union
1829 edgeToMerge.setBeta(
1830 edgeToMerge.getBeta().union(edgeA.getBeta() )
1832 if( !edgeA.isInitialParamReflexive() ) {
1833 edgeToMerge.setIsInitialParamReflexive(false);
1840 // you should only merge ownership graphs that have the
1841 // same number of parameters, or if one or both parameter
1842 // index tables are empty
1843 protected void mergeId2paramIndex(OwnershipGraph og) {
1844 if( id2paramIndex.size() == 0 ) {
1845 id2paramIndex = og.id2paramIndex;
1846 paramIndex2id = og.paramIndex2id;
1847 paramIndex2tdQ = og.paramIndex2tdQ;
1851 if( og.id2paramIndex.size() == 0 ) {
1855 assert id2paramIndex.size() == og.id2paramIndex.size();
1858 protected void mergeAllocationSites(OwnershipGraph og) {
1859 allocationSites.addAll(og.allocationSites);
1864 // it is necessary in the equals() member functions
1865 // to "check both ways" when comparing the data
1866 // structures of two graphs. For instance, if all
1867 // edges between heap region nodes in graph A are
1868 // present and equal in graph B it is not sufficient
1869 // to say the graphs are equal. Consider that there
1870 // may be edges in graph B that are not in graph A.
1871 // the only way to know that all edges in both graphs
1872 // are equally present is to iterate over both data
1873 // structures and compare against the other graph.
1874 public boolean equals(OwnershipGraph og) {
1880 if( !areHeapRegionNodesEqual(og) ) {
1884 if( !areLabelNodesEqual(og) ) {
1888 if( !areReferenceEdgesEqual(og) ) {
1892 if( !areId2paramIndexEqual(og) ) {
1896 // if everything is equal up to this point,
1897 // assert that allocationSites is also equal--
1898 // this data is redundant and kept for efficiency
1899 assert allocationSites.equals(og.allocationSites);
1904 protected boolean areHeapRegionNodesEqual(OwnershipGraph og) {
1906 if( !areallHRNinAalsoinBandequal(this, og) ) {
1910 if( !areallHRNinAalsoinBandequal(og, this) ) {
1917 static protected boolean areallHRNinAalsoinBandequal(OwnershipGraph ogA,
1918 OwnershipGraph ogB) {
1919 Set sA = ogA.id2hrn.entrySet();
1920 Iterator iA = sA.iterator();
1921 while( iA.hasNext() ) {
1922 Map.Entry meA = (Map.Entry)iA.next();
1923 Integer idA = (Integer) meA.getKey();
1924 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1926 if( !ogB.id2hrn.containsKey(idA) ) {
1930 HeapRegionNode hrnB = ogB.id2hrn.get(idA);
1931 if( !hrnA.equalsIncludingAlpha(hrnB) ) {
1940 protected boolean areLabelNodesEqual(OwnershipGraph og) {
1942 if( !areallLNinAalsoinBandequal(this, og) ) {
1946 if( !areallLNinAalsoinBandequal(og, this) ) {
1953 static protected boolean areallLNinAalsoinBandequal(OwnershipGraph ogA,
1954 OwnershipGraph ogB) {
1955 Set sA = ogA.td2ln.entrySet();
1956 Iterator iA = sA.iterator();
1957 while( iA.hasNext() ) {
1958 Map.Entry meA = (Map.Entry)iA.next();
1959 TempDescriptor tdA = (TempDescriptor) meA.getKey();
1961 if( !ogB.td2ln.containsKey(tdA) ) {
1970 protected boolean areReferenceEdgesEqual(OwnershipGraph og) {
1971 if( !areallREinAandBequal(this, og) ) {
1978 static protected boolean areallREinAandBequal(OwnershipGraph ogA,
1979 OwnershipGraph ogB) {
1981 // check all the heap region->heap region edges
1982 Set sA = ogA.id2hrn.entrySet();
1983 Iterator iA = sA.iterator();
1984 while( iA.hasNext() ) {
1985 Map.Entry meA = (Map.Entry)iA.next();
1986 Integer idA = (Integer) meA.getKey();
1987 HeapRegionNode hrnA = (HeapRegionNode) meA.getValue();
1989 // we should have already checked that the same
1990 // heap regions exist in both graphs
1991 assert ogB.id2hrn.containsKey(idA);
1993 if( !areallREfromAequaltoB(ogA, hrnA, ogB) ) {
1997 // then check every edge in B for presence in A, starting
1998 // from the same parent HeapRegionNode
1999 HeapRegionNode hrnB = ogB.id2hrn.get(idA);
2001 if( !areallREfromAequaltoB(ogB, hrnB, ogA) ) {
2006 // then check all the label->heap region edges
2007 sA = ogA.td2ln.entrySet();
2009 while( iA.hasNext() ) {
2010 Map.Entry meA = (Map.Entry)iA.next();
2011 TempDescriptor tdA = (TempDescriptor) meA.getKey();
2012 LabelNode lnA = (LabelNode) meA.getValue();
2014 // we should have already checked that the same
2015 // label nodes exist in both graphs
2016 assert ogB.td2ln.containsKey(tdA);
2018 if( !areallREfromAequaltoB(ogA, lnA, ogB) ) {
2022 // then check every edge in B for presence in A, starting
2023 // from the same parent LabelNode
2024 LabelNode lnB = ogB.td2ln.get(tdA);
2026 if( !areallREfromAequaltoB(ogB, lnB, ogA) ) {
2035 static protected boolean areallREfromAequaltoB(OwnershipGraph ogA,
2037 OwnershipGraph ogB) {
2039 Iterator<ReferenceEdge> itrA = onA.iteratorToReferencees();
2040 while( itrA.hasNext() ) {
2041 ReferenceEdge edgeA = itrA.next();
2042 HeapRegionNode hrnChildA = edgeA.getDst();
2043 Integer idChildA = hrnChildA.getID();
2045 assert ogB.id2hrn.containsKey(idChildA);
2047 // at this point we know an edge in graph A exists
2048 // onA -> idChildA, does this exact edge exist in B?
2049 boolean edgeFound = false;
2051 OwnershipNode onB = null;
2052 if( onA instanceof HeapRegionNode ) {
2053 HeapRegionNode hrnA = (HeapRegionNode) onA;
2054 onB = ogB.id2hrn.get(hrnA.getID() );
2056 LabelNode lnA = (LabelNode) onA;
2057 onB = ogB.td2ln.get(lnA.getTempDescriptor() );
2060 Iterator<ReferenceEdge> itrB = onB.iteratorToReferencees();
2061 while( itrB.hasNext() ) {
2062 ReferenceEdge edgeB = itrB.next();
2063 HeapRegionNode hrnChildB = edgeB.getDst();
2064 Integer idChildB = hrnChildB.getID();
2066 if( idChildA.equals(idChildB) &&
2067 edgeA.getFieldDesc() == edgeB.getFieldDesc() ) {
2069 // there is an edge in the right place with the right field,
2070 // but do they have the same attributes?
2071 if( edgeA.getBeta().equals(edgeB.getBeta() ) ) {
2089 protected boolean areId2paramIndexEqual(OwnershipGraph og) {
2090 return id2paramIndex.size() == og.id2paramIndex.size();
2095 // given a set B of heap region node ID's, return the set of heap
2096 // region node ID's that is reachable from B
2097 public HashSet<Integer> getReachableSet( HashSet<Integer> idSetB ) {
2099 HashSet<HeapRegionNode> toVisit = new HashSet<HeapRegionNode>();
2100 HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
2102 // initial nodes to visit are from set B
2103 Iterator initialItr = idSetB.iterator();
2104 while( initialItr.hasNext() ) {
2105 Integer idInitial = (Integer) initialItr.next();
2106 assert id2hrn.contains( idInitial );
2107 HeapRegionNode hrnInitial = id2hrn.get( idInitial );
2108 toVisit.add( hrnInitial );
2111 HashSet<Integer> idSetReachableFromB = new HashSet<Integer>();
2113 // do a heap traversal
2114 while( !toVisit.isEmpty() ) {
2115 HeapRegionNode hrnVisited = (HeapRegionNode) toVisit.iterator().next();
2116 toVisit.remove( hrnVisited );
2117 visited.add ( hrnVisited );
2119 // for every node visited, add it to the total
2121 idSetReachableFromB.add( hrnVisited.getID() );
2123 // find other reachable nodes
2124 Iterator referenceeItr = hrnVisited.setIteratorToReferencedRegions();
2125 while( referenceeItr.hasNext() ) {
2126 Map.Entry me = (Map.Entry) referenceeItr.next();
2127 HeapRegionNode hrnReferencee = (HeapRegionNode) me.getKey();
2128 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
2130 if( !visited.contains( hrnReferencee ) ) {
2131 toVisit.add( hrnReferencee );
2136 return idSetReachableFromB;
2140 // used to find if a heap region can possibly have a reference to
2141 // any of the heap regions in the given set
2142 // if the id supplied is in the set, then a self-referencing edge
2143 // would return true, but that special case is specifically allowed
2144 // meaning that it isn't an external alias
2145 public boolean canIdReachSet( Integer id, HashSet<Integer> idSet ) {
2147 assert id2hrn.contains( id );
2148 HeapRegionNode hrn = id2hrn.get( id );
2151 //HashSet<HeapRegionNode> hrnSet = new HashSet<HeapRegionNode>();
2153 //Iterator i = idSet.iterator();
2154 //while( i.hasNext() ) {
2155 // Integer idFromSet = (Integer) i.next();
2156 // assert id2hrn.contains( idFromSet );
2157 // hrnSet.add( id2hrn.get( idFromSet ) );
2161 // do a traversal from hrn and see if any of the
2162 // heap regions from the set come up during that
2163 HashSet<HeapRegionNode> toVisit = new HashSet<HeapRegionNode>();
2164 HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
2167 while( !toVisit.isEmpty() ) {
2168 HeapRegionNode hrnVisited = (HeapRegionNode) toVisit.iterator().next();
2169 toVisit.remove( hrnVisited );
2170 visited.add ( hrnVisited );
2172 Iterator referenceeItr = hrnVisited.setIteratorToReferencedRegions();
2173 while( referenceeItr.hasNext() ) {
2174 Map.Entry me = (Map.Entry) referenceeItr.next();
2175 HeapRegionNode hrnReferencee = (HeapRegionNode) me.getKey();
2176 ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
2178 if( idSet.contains( hrnReferencee.getID() ) ) {
2179 if( !id.equals( hrnReferencee.getID() ) ) {
2184 if( !visited.contains( hrnReferencee ) ) {
2185 toVisit.add( hrnReferencee );
2195 // for writing ownership graphs to dot files
2196 public void writeGraph(Descriptor methodDesc,
2198 boolean writeLabels,
2199 boolean labelSelect,
2200 boolean pruneGarbage,
2201 boolean writeReferencers
2202 ) throws java.io.IOException {
2204 methodDesc.getSymbol() +
2205 methodDesc.getNum() +
2214 public void writeGraph(Descriptor methodDesc,
2216 boolean writeLabels,
2217 boolean writeReferencers
2218 ) throws java.io.IOException {
2220 methodDesc.getSymbol() +
2221 methodDesc.getNum() +
2230 public void writeGraph(Descriptor methodDesc,
2231 boolean writeLabels,
2232 boolean writeReferencers
2233 ) throws java.io.IOException {
2235 methodDesc.getSymbol() +
2236 methodDesc.getNum() +
2245 public void writeGraph(Descriptor methodDesc,
2246 boolean writeLabels,
2247 boolean labelSelect,
2248 boolean pruneGarbage,
2249 boolean writeReferencers
2250 ) throws java.io.IOException {
2252 methodDesc.getSymbol() +
2253 methodDesc.getNum() +
2262 public void writeGraph(String graphName,
2263 boolean writeLabels,
2264 boolean labelSelect,
2265 boolean pruneGarbage,
2266 boolean writeReferencers
2267 ) throws java.io.IOException {
2269 // remove all non-word characters from the graph name so
2270 // the filename and identifier in dot don't cause errors
2271 graphName = graphName.replaceAll("[\\W]", "");
2273 BufferedWriter bw = new BufferedWriter(new FileWriter(graphName+".dot") );
2274 bw.write("digraph "+graphName+" {\n");
2275 //bw.write( " size=\"7.5,10\";\n" );
2277 HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
2279 // then visit every heap region node
2280 if( !pruneGarbage ) {
2281 Set s = id2hrn.entrySet();
2282 Iterator i = s.iterator();
2283 while( i.hasNext() ) {
2284 Map.Entry me = (Map.Entry)i.next();
2285 HeapRegionNode hrn = (HeapRegionNode) me.getValue();
2286 if( !visited.contains(hrn) ) {
2287 traverseHeapRegionNodes(VISIT_HRN_WRITE_FULL,
2297 bw.write(" graphTitle[label=\""+graphName+"\",shape=box];\n");
2300 // then visit every label node, useful for debugging
2302 Set s = td2ln.entrySet();
2303 Iterator i = s.iterator();
2304 while( i.hasNext() ) {
2305 Map.Entry me = (Map.Entry)i.next();
2306 LabelNode ln = (LabelNode) me.getValue();
2309 String labelStr = ln.getTempDescriptorString();
2310 if( labelStr.startsWith("___temp") ||
2311 labelStr.startsWith("___dst") ||
2312 labelStr.startsWith("___srctmp") ||
2313 labelStr.startsWith("___neverused") ) {
2318 bw.write(ln.toString() + ";\n");
2320 Iterator<ReferenceEdge> heapRegionsItr = ln.iteratorToReferencees();
2321 while( heapRegionsItr.hasNext() ) {
2322 ReferenceEdge edge = heapRegionsItr.next();
2323 HeapRegionNode hrn = edge.getDst();
2325 if( pruneGarbage && !visited.contains(hrn) ) {
2326 traverseHeapRegionNodes(VISIT_HRN_WRITE_FULL,
2334 bw.write(" " + ln.toString() +
2335 " -> " + hrn.toString() +
2336 "[label=\"" + edge.toGraphEdgeString() +
2347 protected void traverseHeapRegionNodes(int mode,
2351 HashSet<HeapRegionNode> visited,
2352 boolean writeReferencers
2353 ) throws java.io.IOException {
2355 if( visited.contains(hrn) ) {
2361 case VISIT_HRN_WRITE_FULL:
2363 String attributes = "[";
2365 if( hrn.isSingleObject() ) {
2366 attributes += "shape=box";
2368 attributes += "shape=Msquare";
2371 if( hrn.isFlagged() ) {
2372 attributes += ",style=filled,fillcolor=lightgrey";
2375 attributes += ",label=\"ID" +
2378 hrn.getDescription() +
2380 hrn.getAlphaString() +
2383 bw.write(" " + hrn.toString() + attributes + ";\n");
2388 // useful for debugging
2389 if( writeReferencers ) {
2390 OwnershipNode onRef = null;
2391 Iterator refItr = hrn.iteratorToReferencers();
2392 while( refItr.hasNext() ) {
2393 onRef = (OwnershipNode) refItr.next();
2396 case VISIT_HRN_WRITE_FULL:
2397 bw.write(" " + hrn.toString() +
2398 " -> " + onRef.toString() +
2399 "[color=lightgray];\n");
2405 Iterator<ReferenceEdge> childRegionsItr = hrn.iteratorToReferencees();
2406 while( childRegionsItr.hasNext() ) {
2407 ReferenceEdge edge = childRegionsItr.next();
2408 HeapRegionNode hrnChild = edge.getDst();
2411 case VISIT_HRN_WRITE_FULL:
2412 bw.write(" " + hrn.toString() +
2413 " -> " + hrnChild.toString() +
2414 "[label=\"" + edge.toGraphEdgeString() +
2419 traverseHeapRegionNodes(mode,