// in the merge() operation) or to create new heap
// regions with a new unique ID.
protected HeapRegionNode
- createNewHeapRegionNode( Integer id,
- boolean isSingleObject,
- boolean isFlagged,
- boolean isNewSummary,
- AllocationSite allocSite,
- String description ) {
+ createNewHeapRegionNode( Integer id,
+ boolean isSingleObject,
+ boolean isFlagged,
+ boolean isNewSummary,
+ boolean isParameter,
+ AllocationSite allocSite,
+ ReachabilitySet alpha,
+ String description ) {
if( id == null ) {
id = OwnershipAnalysis.generateUniqueHeapRegionNodeID();
}
+ if( alpha == null ) {
+ if( isFlagged || isParameter ) {
+ alpha = new ReachabilitySet( new TokenTuple( id,
+ isNewSummary,
+ TokenTuple.ARITY_ONE ) );
+ } else {
+ alpha = new ReachabilitySet();
+ }
+ }
+
HeapRegionNode hrn = new HeapRegionNode( id,
isSingleObject,
isFlagged,
isNewSummary,
allocSite,
+ alpha,
description );
id2hrn.put( id, hrn );
return hrn;
assert rep != null;
referencer.addReferencedRegion( referencee, rep );
referencee.addReferencer( referencer );
+ rep.setSrc( referencer );
+ rep.setDst( referencee );
}
protected void removeReferenceEdge( OwnershipNode referencer,
}
}
+ protected void propagateTokens( HeapRegionNode nPrime,
+ ChangeTupleSet c0,
+ HashSet<HeapRegionNode> nodesWithNewAlpha,
+ HashSet<ReferenceEdgeProperties> edgesWithNewBeta ) {
+
+ HashSet<HeapRegionNode> todoNodes
+ = new HashSet<HeapRegionNode>();
+ todoNodes.add( nPrime );
+
+ HashSet<ReferenceEdgeProperties> todoEdges
+ = new HashSet<ReferenceEdgeProperties>();
+
+ Hashtable<HeapRegionNode, ChangeTupleSet> nodePlannedChanges
+ = new Hashtable<HeapRegionNode, ChangeTupleSet>();
+ nodePlannedChanges.put( nPrime, c0 );
+
+ Hashtable<ReferenceEdgeProperties, ChangeTupleSet> edgePlannedChanges
+ = new Hashtable<ReferenceEdgeProperties, ChangeTupleSet>();
+
+ Hashtable<HeapRegionNode, ChangeTupleSet> nodeChangesMade
+ = new Hashtable<HeapRegionNode, ChangeTupleSet>();
+
+ while( !todoNodes.isEmpty() ) {
+ HeapRegionNode n = todoNodes.iterator().next();
+ todoNodes.remove( n );
+
+ ChangeTupleSet C = nodePlannedChanges.get( n );
+
+ if( !nodeChangesMade.containsKey( n ) ) {
+ nodeChangesMade.put( n, new ChangeTupleSet().makeCanonical() );
+ }
+
+ Iterator itrC = C.iterator();
+ while( itrC.hasNext() ) {
+ ChangeTuple c = (ChangeTuple) itrC.next();
+
+ if( n.getAlpha().contains( c.getSetToMatch() ) ) {
+ ReachabilitySet withChange = n.getAlpha().union( c.getSetToAdd() );
+ n.setAlphaNew( n.getAlphaNew().union( withChange ) );
+ nodesWithNewAlpha.add( n );
+ nodeChangesMade.put( n, nodeChangesMade.get( n ).union( c ) );
+ }
+ }
+
+ ChangeTupleSet Cprime = nodeChangesMade.get( n );
+
+ Iterator referItr = n.iteratorToReferencers();
+ while( referItr.hasNext() ) {
+ OwnershipNode on = (OwnershipNode) referItr.next();
+ ReferenceEdgeProperties rep = on.getReferenceTo( n );
+ todoEdges.add( rep );
+
+ if( !edgePlannedChanges.containsKey( rep ) ) {
+ edgePlannedChanges.put( rep, new ChangeTupleSet().makeCanonical() );
+ }
+
+ edgePlannedChanges.put( rep, edgePlannedChanges.get( rep ).union( Cprime ) );
+ }
+
+ HeapRegionNode m = null;
+ ReferenceEdgeProperties f = null;
+ Iterator refeeItr = n.setIteratorToReferencedRegions();
+ while( refeeItr.hasNext() ) {
+ Map.Entry me = (Map.Entry) refeeItr.next();
+ m = (HeapRegionNode) me.getKey();
+ f = (ReferenceEdgeProperties) me.getValue();
+
+ ChangeTupleSet changesToPass = new ChangeTupleSet().makeCanonical();
+
+ Iterator itrCprime = Cprime.iterator();
+ while( itrCprime.hasNext() ) {
+ ChangeTuple c = (ChangeTuple) itrCprime.next();
+ if( f.getBeta().contains( c.getSetToMatch() ) ) {
+ changesToPass = changesToPass.union( c );
+ }
+ }
+
+ if( !changesToPass.isEmpty() ) {
+ if( !nodePlannedChanges.containsKey( m ) ) {
+ nodePlannedChanges.put( m, new ChangeTupleSet().makeCanonical() );
+ }
+
+ ChangeTupleSet currentChanges = nodePlannedChanges.get( m );
+
+ if( !changesToPass.isSubset( currentChanges ) ) {
+ todoNodes.add( m );
+ nodePlannedChanges.put( m, currentChanges.union( changesToPass ) );
+ }
+ }
+ }
+ }
+
+
+ while( !todoEdges.isEmpty() ) {
+ ReferenceEdgeProperties e = todoEdges.iterator().next();
+ todoEdges.remove( e );
+
+ if( !edgePlannedChanges.containsKey( e ) ) {
+ edgePlannedChanges.put( e, new ChangeTupleSet().makeCanonical() );
+ }
+
+ ChangeTupleSet C = edgePlannedChanges.get( e );
+
+ ChangeTupleSet changesToPass = new ChangeTupleSet().makeCanonical();
+
+ Iterator itrC = C.iterator();
+ while( itrC.hasNext() ) {
+ ChangeTuple c = (ChangeTuple) itrC.next();
+ if( e.getBeta().contains( c.getSetToMatch() ) ) {
+ ReachabilitySet withChange = e.getBeta().union( c.getSetToAdd() );
+ e.setBetaNew( e.getBetaNew().union( withChange ) );
+ edgesWithNewBeta.add( e );
+ changesToPass = changesToPass.union( c );
+ }
+ }
+
+ OwnershipNode onSrc = e.getSrc();
+
+ if( !changesToPass.isEmpty() && onSrc instanceof HeapRegionNode ) {
+ HeapRegionNode n = (HeapRegionNode) onSrc;
+ Iterator referItr = n.iteratorToReferencers();
+
+ while( referItr.hasNext() ) {
+ OwnershipNode onRef = (OwnershipNode) referItr.next();
+ ReferenceEdgeProperties f = onRef.getReferenceTo( n );
+
+ if( !edgePlannedChanges.containsKey( f ) ) {
+ edgePlannedChanges.put( f, new ChangeTupleSet().makeCanonical() );
+ }
+
+ ChangeTupleSet currentChanges = edgePlannedChanges.get( f );
+
+ if( !changesToPass.isSubset( currentChanges ) ) {
+ todoEdges.add( f );
+ edgePlannedChanges.put( f, currentChanges.union( changesToPass ) );
+ }
+ }
+ }
+ }
+ }
+
////////////////////////////////////////////////////
//
LabelNode dstln = getLabelNodeFromTemp( dst );
clearReferenceEdgesFrom( dstln );
+
HeapRegionNode newReferencee = null;
- Iterator srcRegionsItr = srcln.setIteratorToReferencedRegions();
+ Iterator srcRegionsItr = srcln.setIteratorToReferencedRegions();
while( srcRegionsItr.hasNext() ) {
- Map.Entry me = (Map.Entry) srcRegionsItr.next();
- newReferencee = (HeapRegionNode) me.getKey();
+ Map.Entry me = (Map.Entry) srcRegionsItr.next();
+ newReferencee = (HeapRegionNode) me.getKey();
+ ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
- ReferenceEdgeProperties rep = new ReferenceEdgeProperties();
- addReferenceEdge( dstln, newReferencee, rep );
+ addReferenceEdge( dstln, newReferencee, rep.copy() );
}
}
- public void assignTempToField( TempDescriptor src,
- TempDescriptor dst,
+ public void assignTempToField( TempDescriptor src,
+ TempDescriptor dst,
FieldDescriptor fd ) {
LabelNode srcln = getLabelNodeFromTemp( src );
LabelNode dstln = getLabelNodeFromTemp( dst );
clearReferenceEdgesFrom( dstln );
- HeapRegionNode hrn = null;
- Iterator srcRegionsItr = srcln.setIteratorToReferencedRegions();
+ HeapRegionNode hrn = null;
+ Iterator srcRegionsItr = srcln.setIteratorToReferencedRegions();
while( srcRegionsItr.hasNext() ) {
- Map.Entry me = (Map.Entry) srcRegionsItr.next();
- hrn = (HeapRegionNode) me.getKey();
+ Map.Entry me = (Map.Entry) srcRegionsItr.next();
+ hrn = (HeapRegionNode) me.getKey();
+ ReferenceEdgeProperties rep1 = (ReferenceEdgeProperties) me.getValue();
+ ReachabilitySet beta1 = rep1.getBeta();
HeapRegionNode hrnOneHop = null;
Iterator hrnRegionsItr = hrn.setIteratorToReferencedRegions();
while( hrnRegionsItr.hasNext() ) {
- Map.Entry meH = (Map.Entry) hrnRegionsItr.next();
- hrnOneHop = (HeapRegionNode) meH.getKey();
+ Map.Entry meH = (Map.Entry) hrnRegionsItr.next();
+ hrnOneHop = (HeapRegionNode) meH.getKey();
+ ReferenceEdgeProperties rep2 = (ReferenceEdgeProperties) meH.getValue();
+ ReachabilitySet beta2 = rep2.getBeta();
+
+ ReferenceEdgeProperties rep = rep2.copy();
+ rep.setIsInitialParamReflexive( false );
+ rep.setBeta( beta1.intersection( beta2 ) );
- ReferenceEdgeProperties rep = new ReferenceEdgeProperties();
addReferenceEdge( dstln, hrnOneHop, rep );
}
}
}
- public void assignFieldToTemp( TempDescriptor src,
- TempDescriptor dst,
+ public void assignFieldToTemp( TempDescriptor src,
+ TempDescriptor dst,
FieldDescriptor fd ) {
+
+ // I think my use of src and dst are actually backwards in this method!
+ // acccording to the Reachability Notes, think of dst at N and src as N prime
+
LabelNode srcln = getLabelNodeFromTemp( src );
LabelNode dstln = getLabelNodeFromTemp( dst );
- HeapRegionNode hrn = null;
+ HashSet<HeapRegionNode> nodesWithNewAlpha = new HashSet<HeapRegionNode>();
+ HashSet<ReferenceEdgeProperties> edgesWithNewBeta = new HashSet<ReferenceEdgeProperties>();
+
+ HeapRegionNode hrn = null;
+ ReferenceEdgeProperties rep = null;
Iterator dstRegionsItr = dstln.setIteratorToReferencedRegions();
while( dstRegionsItr.hasNext() ) {
- Map.Entry me = (Map.Entry) dstRegionsItr.next();
- hrn = (HeapRegionNode) me.getKey();
+ Map.Entry me = (Map.Entry) dstRegionsItr.next();
+ hrn = (HeapRegionNode) me.getKey();
+ rep = (ReferenceEdgeProperties) me.getValue();
- HeapRegionNode hrnSrc = null;
+ ReachabilitySet R = hrn.getAlpha().intersection( rep.getBeta() );
+
+ HeapRegionNode hrnSrc = null;
+ ReferenceEdgeProperties repSrc = null;
Iterator srcRegionsItr = srcln.setIteratorToReferencedRegions();
while( srcRegionsItr.hasNext() ) {
- Map.Entry meS = (Map.Entry) srcRegionsItr.next();
- hrnSrc = (HeapRegionNode) meS.getKey();
+ Map.Entry meS = (Map.Entry) srcRegionsItr.next();
+ hrnSrc = (HeapRegionNode) meS.getKey();
+ repSrc = (ReferenceEdgeProperties) meS.getValue();
+
+ ReachabilitySet O = srcln.getReferenceTo( hrnSrc ).getBeta();
+
+ ChangeTupleSet Cy = O.unionUpArityToChangeSet( R );
+ ChangeTupleSet Cx = R.unionUpArityToChangeSet( O );
- ReferenceEdgeProperties rep = new ReferenceEdgeProperties();
- addReferenceEdge( hrn, hrnSrc, rep );
+ propagateTokens( hrnSrc, Cy, nodesWithNewAlpha, edgesWithNewBeta );
+ propagateTokens( hrn, Cx, nodesWithNewAlpha, edgesWithNewBeta );
+
+ // note that this picks up the beta after the propogation has
+ // been applied
+ ReferenceEdgeProperties repNew
+ = new ReferenceEdgeProperties( false, false, repSrc.getBetaNew() );
+
+ addReferenceEdge( hrn, hrnSrc, repNew );
}
}
+
+ Iterator nodeItr = nodesWithNewAlpha.iterator();
+ while( nodeItr.hasNext() ) {
+ ((HeapRegionNode) nodeItr.next()).applyAlphaNew();
+ }
+
+ Iterator edgeItr = edgesWithNewBeta.iterator();
+ while( edgeItr.hasNext() ) {
+ ((ReferenceEdgeProperties) edgeItr.next()).applyBetaNew();
+ }
}
public void assignTempToParameterAllocation( boolean isTask,
false,
isTask,
false,
+ true,
+ null,
null,
"param" + paramIndex );
id2paramIndex.put( newID, paramIndex );
paramIndex2id.put( paramIndex, newID );
+ ReachabilitySet beta = new ReachabilitySet( new TokenTuple( newID,
+ false,
+ TokenTuple.ARITY_ONE ) );
+
// heap regions for parameters are always multiple object (see above)
// and have a reference to themselves, because we can't know the
// structure of memory that is passed into the method. We're assuming
// the worst here.
- addReferenceEdge( lnParam, hrn, new ReferenceEdgeProperties( false ) );
- addReferenceEdge( hrn, hrn, new ReferenceEdgeProperties( false, true ) );
+ addReferenceEdge( lnParam, hrn, new ReferenceEdgeProperties( false, false, beta ) );
+ addReferenceEdge( hrn, hrn, new ReferenceEdgeProperties( false, true, beta ) );
}
public void assignTempToNewAllocation( TempDescriptor td,
age( as );
+
// after the age operation the newest (or zero-ith oldest)
// node associated with the allocation site should have
// no references to it as if it were a newly allocated
// heap region, so make a reference to it to complete
// this operation
- Integer id = as.getIthOldest( 0 );
- HeapRegionNode hrnNewest = id2hrn.get( id );
+ Integer idNewest = as.getIthOldest( 0 );
+ HeapRegionNode hrnNewest = id2hrn.get( idNewest );
assert hrnNewest != null;
LabelNode dst = getLabelNodeFromTemp( td );
clearReferenceEdgesFrom( dst );
- addReferenceEdge( dst, hrnNewest, new ReferenceEdgeProperties( false ) );
+
+ addReferenceEdge( dst, hrnNewest, new ReferenceEdgeProperties( false, false, hrnNewest.getAlpha() ) );
}
boolean hasFlags = false;
if( as.getType().isClass() ) {
- hasFlags = as.getType().getClassDesc().hasFlags();
+ hasFlags = as.getType().getClassDesc().hasFlags();
}
hrnSummary = createNewHeapRegionNode( idSummary,
false,
hasFlags,
true,
+ false,
as,
+ null,
as + "\\n" + as.getType() + "\\nsummary" );
for( int i = 0; i < as.getAllocationDepth(); ++i ) {
true,
hasFlags,
false,
+ false,
as,
+ null,
as + "\\n" + as.getType() + "\\n" + i + " oldest" );
}
}
onReferencer = (OwnershipNode) itrReferencer.next();
ReferenceEdgeProperties rep = onReferencer.getReferenceTo( hrnK );
- assert rep != null;
-
- addReferenceEdge( onReferencer, hrnSummary, rep.copy() );
+ assert rep != null;
+ ReferenceEdgeProperties repSummary = onReferencer.getReferenceTo( hrnSummary );
+ ReferenceEdgeProperties repMerged = rep.copy();
+
+ if( repSummary == null ) {
+ // the merge is trivial, nothing to be done
+ } else {
+ // otherwise an edge from the referencer to alpha_S exists already
+ // and the edge referencer->alpha_K should be merged with it
+ repMerged.setBeta( repMerged.getBeta().union( repSummary.getBeta() ) );
+ }
+
+ addReferenceEdge( onReferencer, hrnSummary, repMerged );
}
clearReferenceEdgesTo ( hrn0 );
}
-
// some notes:
// the heap regions that are specially allocated as multiple-object
// in merge() and equals() methods the suffix A
// represents the passed in graph and the suffix
// B refers to the graph in this object
+ // Merging means to take the incoming graph A and
+ // merge it into B, so after the operation graph B
+ // is the final result.
////////////////////////////////////////////////////
public void merge( OwnershipGraph og ) {
mergeAllocationSites( og );
}
+
protected void mergeOwnershipNodes( OwnershipGraph og ) {
Set sA = og.id2hrn.entrySet();
Iterator iA = sA.iterator();
if( !id2hrn.containsKey( idA ) ) {
HeapRegionNode hrnB = hrnA.copy();
id2hrn.put( idA, hrnB );
+
+ } else {
+ // otherwise this is a node present in both graphs
+ // so make the new reachability set a union of the
+ // nodes' reachability sets
+ HeapRegionNode hrnB = id2hrn.get( idA );
+ hrnB.setAlpha( hrnB.getAlpha().union( hrnA.getAlpha() ) );
}
}
// for stroing heap region nodes retrieved by integer
// ids. Because finding edges requires interacting
// with these disparate data structures frequently the
- // process is nearly duplicated, one for each
+ // process is nearly duplicated, one for each structure
+ // that stores edges
// heap regions
Set sA = og.id2hrn.entrySet();
assert id2hrn.containsKey( idA );
HeapRegionNode hrnB = id2hrn.get( idA );
- HeapRegionNode hrnChildB = null;
+ HeapRegionNode hrnChildB = null;
+ ReferenceEdgeProperties repB = null;
Iterator heapRegionsItrB = hrnB.setIteratorToReferencedRegions();
while( heapRegionsItrB.hasNext() ) {
- Map.Entry meC = (Map.Entry) heapRegionsItrB.next();
- hrnChildB = (HeapRegionNode) meC.getKey();
+ Map.Entry meC = (Map.Entry) heapRegionsItrB.next();
+ hrnChildB = (HeapRegionNode) meC.getKey();
+ ReferenceEdgeProperties rep = (ReferenceEdgeProperties) meC.getValue();
if( hrnChildB.equals( idChildA ) ) {
edgeFound = true;
+ repB = rep;
}
}
if( !edgeFound ) {
assert id2hrn.containsKey( idChildA );
hrnChildB = id2hrn.get( idChildA );
- ReferenceEdgeProperties repB = repA.copy();
+ repB = repA.copy();
addReferenceEdge( hrnB, hrnChildB, repB );
}
- // otherwise, the edge already existed in both graphs.
- // if this is the case, check to see whether the isUnique
- // predicate of the edges might change
- else
- {
-
+ // otherwise, the edge already existed in both graphs
+ // so merge their reachability sets
+ else {
+ // just replace this beta set with the union
+ assert repB != null;
+ repB.setBeta( repB.getBeta().union( repA.getBeta() ) );
}
}
}
assert td2ln.containsKey( tdA );
LabelNode lnB = td2ln.get( tdA );
- HeapRegionNode hrnChildB = null;
+ HeapRegionNode hrnChildB = null;
+ ReferenceEdgeProperties repB = null;
Iterator heapRegionsItrB = lnB.setIteratorToReferencedRegions();
while( heapRegionsItrB.hasNext() ) {
- Map.Entry meC = (Map.Entry) heapRegionsItrB.next();
- hrnChildB = (HeapRegionNode) meC.getKey();
+ Map.Entry meC = (Map.Entry) heapRegionsItrB.next();
+ hrnChildB = (HeapRegionNode) meC.getKey();
+ ReferenceEdgeProperties rep = (ReferenceEdgeProperties) meC.getValue();
if( hrnChildB.equals( idChildA ) ) {
edgeFound = true;
+ repB = rep;
}
}
if( !edgeFound ) {
assert id2hrn.containsKey( idChildA );
hrnChildB = id2hrn.get( idChildA );
- ReferenceEdgeProperties repB = repA.copy();
+ repB = repA.copy();
addReferenceEdge( lnB, hrnChildB, repB );
}
- // otherwise, the edge already existed in both graphs.
- // if this is the case, check to see whether the isUnique
- // predicate of the edges might change
- else
- {
-
+ // otherwise, the edge already existed in both graphs
+ // so merge the reachability sets
+ else {
+ // just replace this beta set with the union
+ assert repB != null;
+ repB.setBeta( repB.getBeta().union( repA.getBeta() ) );
}
}
}
}
+
// it is necessary in the equals() member functions
// to "check both ways" when comparing the data
// structures of two graphs. For instance, if all
return false;
}
- HeapRegionNode hrnB = og.id2hrn.get( idA );
+ //HeapRegionNode hrnB = og.id2hrn.get( idA );
+ HeapRegionNode hrnB = id2hrn.get( idA );
if( !hrnA.equals( hrnB ) ) {
return false;
}
hrn = (HeapRegionNode) meH.getKey();
ReferenceEdgeProperties rep = (ReferenceEdgeProperties) meH.getValue();
- String edgeLabel = "";
- if( rep.isUnique() ) {
- edgeLabel = "Unique";
- }
bw.write( " " + ln.toString() +
" -> " + hrn.toString() +
- "[label=\"" + edgeLabel +
- "\"];\n" );
+ "[label=\"" + rep.toEdgeLabelString() +
+ "\",decorate];\n" );
}
}
}
hrn.getID() +
"\\n" +
hrn.getDescription() +
+ "\\n" +
+ hrn.getAlphaString() +
"\"]";
bw.write( " " + hrn.toString() + attributes + ";\n" );
switch( mode ) {
case VISIT_HRN_WRITE_FULL:
- String edgeLabel = "";
- if( rep.isUnique() ) {
- edgeLabel += "Unq";
- }
- if( rep.isInitialParamReflexive() ) {
- edgeLabel += "Rfx";
- }
bw.write( " " + hrn.toString() +
" -> " + hrnChild.toString() +
- "[label=\"" + edgeLabel +
- "\"];\n" );
+ "[label=\"" + rep.toEdgeLabelString() +
+ "\",decorate];\n" );
break;
}