public class OwnershipGraph {
private int allocationDepth;
+ private TypeUtil typeUtil;
// there was already one other very similar reason
// for traversing heap nodes that is no longer needed
- public OwnershipGraph(int allocationDepth) {
+ public OwnershipGraph(int allocationDepth, TypeUtil typeUtil) {
this.allocationDepth = allocationDepth;
+ this.typeUtil = typeUtil;
id2hrn = new Hashtable<Integer, HeapRegionNode>();
td2ln = new Hashtable<TempDescriptor, LabelNode >();
FlatMethod fm,
OwnershipGraph ogCallee) {
-
// define rewrite rules and other structures to organize
// data by parameter/argument index
Hashtable<Integer, ReachabilitySet> paramIndex2rewriteH =
Iterator<ReferenceEdge> edgeItr = argLabel_i.iteratorToReferencees();
while( edgeItr.hasNext() ) {
ReferenceEdge edge = edgeItr.next();
- D_i = D_i.union(edge.getBeta() );
+ D_i = D_i.union(edge.getBeta());
}
+
D_i = D_i.exhaustiveArityCombinations();
+
paramIndex2rewriteD.put(paramIndex, D_i);
}
}
}
-
// update reachable edges
Iterator<ReferenceEdge> edgeReachableItr = edgesReachable.iterator();
while( edgeReachableItr.hasNext() ) {
edgesWithNewBeta.add(edgeReachable);
}
-
// update upstream edges
Hashtable<ReferenceEdge, ChangeTupleSet> edgeUpstreamPlannedChanges
= new Hashtable<ReferenceEdge, ChangeTupleSet>();
}
-
// verify the existence of allocation sites and their
// shadows from the callee in the context of this caller graph
// then map allocated nodes of callee onto the caller shadows
edgeNewInCallerTemplate.applyBetaNew();
-
// So now make a set of possible source heaps in the caller graph
// and a set of destination heaps in the caller graph, and make
// a reference edge in the caller for every possible (src,dst) pair
HashSet<HeapRegionNode> possibleCallerSrcs =
getHRNSetThatPossiblyMapToCalleeHRN(ogCallee,
(HeapRegionNode) edgeCallee.getSrc(),
- true,
paramIndex2reachableCallerNodes);
HashSet<HeapRegionNode> possibleCallerDsts =
getHRNSetThatPossiblyMapToCalleeHRN(ogCallee,
edgeCallee.getDst(),
- false,
paramIndex2reachableCallerNodes);
+
// make every possible pair of {srcSet} -> {dstSet} edges in the caller
Iterator srcItr = possibleCallerSrcs.iterator();
while( srcItr.hasNext() ) {
HeapRegionNode src = (HeapRegionNode) srcItr.next();
+ if( !hasMatchingField(src, edgeCallee) ) {
+ // prune this source node possibility
+ continue;
+ }
+
Iterator dstItr = possibleCallerDsts.iterator();
while( dstItr.hasNext() ) {
HeapRegionNode dst = (HeapRegionNode) dstItr.next();
+ if( !hasMatchingType(edgeCallee, dst) ) {
+ // prune
+ continue;
+ }
+
+ // otherwise the caller src and dst pair can match the edge, so make it
ReferenceEdge edgeNewInCaller = edgeNewInCallerTemplate.copy();
edgeNewInCaller.setSrc(src);
edgeNewInCaller.setDst(dst);
}
-
// return value may need to be assigned in caller
- if( fc.getReturnTemp() != null ) {
+ TempDescriptor returnTemp = fc.getReturnTemp();
+ if( returnTemp != null && !returnTemp.getType().isImmutable() ) {
- LabelNode lnLhsCaller = getLabelNodeFromTemp(fc.getReturnTemp() );
+ LabelNode lnLhsCaller = getLabelNodeFromTemp(returnTemp);
clearReferenceEdgesFrom(lnLhsCaller, null, true);
LabelNode lnReturnCallee = ogCallee.getLabelNodeFromTemp(tdReturn);
ReferenceEdge edgeCallee = edgeCalleeItr.next();
ReferenceEdge edgeNewInCallerTemplate = new ReferenceEdge(null,
- null,
- edgeCallee.getFieldDesc(),
- false,
- toShadowTokens(ogCallee, edgeCallee.getBeta() )
- );
+ null,
+ edgeCallee.getFieldDesc(),
+ false,
+ toShadowTokens(ogCallee, edgeCallee.getBeta() )
+ );
rewriteCallerEdgeBeta(fm.numParameters(),
- bogusIndex,
- edgeNewInCallerTemplate,
- paramIndex2rewriteJ,
- paramIndex2rewriteD,
- paramIndex2paramToken,
- paramIndex2paramTokenStar,
- false,
- null);
-
+ bogusIndex,
+ edgeNewInCallerTemplate,
+ paramIndex2rewriteJ,
+ paramIndex2rewriteD,
+ paramIndex2paramToken,
+ paramIndex2paramTokenStar,
+ false,
+ null);
+
edgeNewInCallerTemplate.applyBetaNew();
HashSet<HeapRegionNode> assignCallerRhs =
getHRNSetThatPossiblyMapToCalleeHRN(ogCallee,
edgeCallee.getDst(),
- false,
paramIndex2reachableCallerNodes);
Iterator<HeapRegionNode> itrHrn = assignCallerRhs.iterator();
while( itrHrn.hasNext() ) {
HeapRegionNode hrnCaller = itrHrn.next();
-
+
+ if( !hasMatchingType(edgeCallee, hrnCaller) ) {
+ // prune
+ continue;
+ }
+
+ // otherwise caller node can match callee edge, so make it
ReferenceEdge edgeNewInCaller = edgeNewInCallerTemplate.copy();
edgeNewInCaller.setSrc(lnLhsCaller);
edgeNewInCaller.setDst(hrnCaller);
ReferenceEdge edgeExisting = lnLhsCaller.getReferenceTo(hrnCaller, edgeNewInCaller.getFieldDesc() );
if( edgeExisting == null ) {
+
// if this edge doesn't exist in the caller, create it
addReferenceEdge(lnLhsCaller, hrnCaller, edgeNewInCaller);
} else {
// if it already exists, merge with it
edgeExisting.setBeta(edgeExisting.getBeta().union(edgeNewInCaller.getBeta() ) );
- }
+ }
}
}
}
-
// merge the shadow nodes of allocation sites back down to normal capacity
Iterator<AllocationSite> allocItr = ogCallee.allocationSites.iterator();
while( allocItr.hasNext() ) {
}
+ protected boolean hasMatchingField(HeapRegionNode src, ReferenceEdge edge) {
+
+ // if no allocation site, then it's a match-everything region
+ AllocationSite asSrc = src.getAllocationSite();
+ if( asSrc == null ) {
+ return true;
+ }
+
+ TypeDescriptor tdSrc = asSrc.getType();
+ assert tdSrc != null;
+
+ // if it's not a class, it doesn't have any fields to match
+ if( !tdSrc.isClass() ) {
+ return false;
+ }
+
+ Iterator fieldsSrcItr = tdSrc.getClassDesc().getFields();
+ while( fieldsSrcItr.hasNext() ) {
+ FieldDescriptor fd = (FieldDescriptor) fieldsSrcItr.next();
+ if( fd == edge.getFieldDesc() ) {
+ return true;
+ }
+ }
+
+ // otherwise it is a class with fields
+ // but we didn't find a match
+ return false;
+ }
+
+
+ protected boolean hasMatchingType(ReferenceEdge edge, HeapRegionNode dst) {
+
+ // if the region has no type, matches everything
+ AllocationSite asDst = dst.getAllocationSite();
+ if( asDst == null ) {
+ return true;
+ }
+
+ TypeDescriptor tdDst = asDst.getType();
+ assert tdDst != null;
+
+ // if the type is not a class don't match because
+ // primitives are copied, no memory aliases
+ ClassDescriptor cdDst = tdDst.getClassDesc();
+ if( cdDst == null ) {
+ return false;
+ }
+
+ // if the field is null, it matches everything
+ FieldDescriptor fd = edge.getFieldDesc();
+ if( fd == null ) {
+ return true;
+ }
+ TypeDescriptor tdFd = fd.getType();
+ assert tdFd != null;
+
+ return typeUtil.isSuperorType(tdFd, tdDst);
+ }
+
+
+
protected void unshadowTokens(AllocationSite as, ReferenceEdge edge) {
edge.setBeta(edge.getBeta().unshadowTokens(as) );
}
while( ttsItr.hasNext() ) {
TokenTupleSet tts = ttsItr.next();
- Hashtable<TokenTupleSet, TokenTupleSet> forChangeSet =
- new Hashtable<TokenTupleSet, TokenTupleSet>();
+ Hashtable<TokenTupleSet, HashSet<TokenTupleSet> > forChangeSet =
+ new Hashtable<TokenTupleSet, HashSet<TokenTupleSet> >();
ReachabilitySet rTemp = tts.rewriteToken(tokenToRewrite,
edge.getBeta(),
while( fcsItr.hasNext() ) {
Map.Entry me = (Map.Entry)fcsItr.next();
TokenTupleSet ttsMatch = (TokenTupleSet) me.getKey();
- TokenTupleSet ttsAdd = (TokenTupleSet) me.getValue();
+ HashSet<TokenTupleSet> ttsAddSet = (HashSet<TokenTupleSet>) me.getValue();
+ Iterator<TokenTupleSet> ttsAddItr = ttsAddSet.iterator();
+ while( ttsAddItr.hasNext() ) {
+ TokenTupleSet ttsAdd = ttsAddItr.next();
- ChangeTuple ct = new ChangeTuple(ttsMatch,
- ttsAdd
- ).makeCanonical();
+ ChangeTuple ct = new ChangeTuple(ttsMatch,
+ ttsAdd
+ ).makeCanonical();
- cts0 = cts0.union(ct);
+ cts0 = cts0.union(ct);
+ }
}
}
private HashSet<HeapRegionNode>
getHRNSetThatPossiblyMapToCalleeHRN(OwnershipGraph ogCallee,
HeapRegionNode hrnCallee,
- boolean mapFromSrc,
Hashtable<Integer, HashSet<HeapRegionNode> > paramIndex2reachableCallerNodes
) {
// so it maps to a whole mess of heap regions
assert paramIndex2reachableCallerNodes.containsKey(paramIndexCallee);
possibleCallerHRNs = paramIndex2reachableCallerNodes.get(paramIndexCallee);
-
- // TODO PRUNE BY TYPE/FIELD NAME!!
}
return possibleCallerHRNs;
}
- /*
- // given a set B of heap region node ID's, return the set of heap
- // region node ID's that is reachable from B
- public HashSet<Integer> getReachableSet( HashSet<Integer> idSetB ) {
+ public boolean hasPotentialAlias(Integer paramIndex1, Integer paramIndex2) {
- HashSet<HeapRegionNode> toVisit = new HashSet<HeapRegionNode>();
- HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
+ // get parameter's heap region
+ assert paramIndex2id.containsKey(paramIndex1);
+ Integer idParam1 = paramIndex2id.get(paramIndex1);
- // initial nodes to visit are from set B
- Iterator initialItr = idSetB.iterator();
- while( initialItr.hasNext() ) {
- Integer idInitial = (Integer) initialItr.next();
- assert id2hrn.contains( idInitial );
- HeapRegionNode hrnInitial = id2hrn.get( idInitial );
- toVisit.add( hrnInitial );
- }
+ assert id2hrn.containsKey(idParam1);
+ HeapRegionNode hrnParam1 = id2hrn.get(idParam1);
+ assert hrnParam1 != null;
+
+ // get tokens for this parameter
+ TokenTuple p1 = new TokenTuple(hrnParam1.getID(),
+ true,
+ TokenTuple.ARITY_ONE).makeCanonical();
+
+ TokenTuple pStar1 = new TokenTuple(hrnParam1.getID(),
+ true,
+ TokenTuple.ARITY_MANY).makeCanonical();
+
+
+ // get tokens for the other parameter
+ assert paramIndex2id.containsKey(paramIndex2);
+ Integer idParam2 = paramIndex2id.get(paramIndex2);
+
+ assert id2hrn.containsKey(idParam2);
+ HeapRegionNode hrnParam2 = id2hrn.get(idParam2);
+ assert hrnParam2 != null;
+
+ TokenTuple p2 = new TokenTuple(hrnParam2.getID(),
+ true,
+ TokenTuple.ARITY_ONE).makeCanonical();
+
+ TokenTuple pStar2 = new TokenTuple(hrnParam2.getID(),
+ true,
+ TokenTuple.ARITY_MANY).makeCanonical();
+
+
+ // get special label p_q for first parameter
+ TempDescriptor tdParamQ1 = paramIndex2tdQ.get(paramIndex1);
+ assert tdParamQ1 != null;
+ LabelNode lnParamQ1 = td2ln.get(tdParamQ1);
+ assert lnParamQ1 != null;
+
+ // then get the edge from label q to parameter's hrn
+ ReferenceEdge edgeSpecialQ1 = lnParamQ1.getReferenceTo(hrnParam1, null);
+ assert edgeSpecialQ1 != null;
+
+ // if the beta of this edge has tokens from both parameters in one
+ // token tuple set, then there is a potential alias between them
+ ReachabilitySet beta1 = edgeSpecialQ1.getBeta();
+ assert beta1 != null;
+
+ if( beta1.containsTupleSetWithBoth(p1, p2) ) {
+ return true;
+ }
+ if( beta1.containsTupleSetWithBoth(pStar1, p2) ) {
+ return true;
+ }
+ if( beta1.containsTupleSetWithBoth(p1, pStar2) ) {
+ return true;
+ }
+ if( beta1.containsTupleSetWithBoth(pStar1, pStar2) ) {
+ return true;
+ }
+
+ return false;
+ }
- HashSet<Integer> idSetReachableFromB = new HashSet<Integer>();
- // do a heap traversal
- while( !toVisit.isEmpty() ) {
- HeapRegionNode hrnVisited = (HeapRegionNode) toVisit.iterator().next();
- toVisit.remove( hrnVisited );
- visited.add ( hrnVisited );
+ public boolean hasPotentialAlias(Integer paramIndex, AllocationSite as) {
- // for every node visited, add it to the total
- // reachable set
- idSetReachableFromB.add( hrnVisited.getID() );
+ // get parameter's heap region
+ assert paramIndex2id.containsKey(paramIndex);
+ Integer idParam = paramIndex2id.get(paramIndex);
- // find other reachable nodes
- Iterator referenceeItr = hrnVisited.setIteratorToReferencedRegions();
- while( referenceeItr.hasNext() ) {
- Map.Entry me = (Map.Entry) referenceeItr.next();
- HeapRegionNode hrnReferencee = (HeapRegionNode) me.getKey();
- ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
+ assert id2hrn.containsKey(idParam);
+ HeapRegionNode hrnParam = id2hrn.get(idParam);
+ assert hrnParam != null;
- if( !visited.contains( hrnReferencee ) ) {
- toVisit.add( hrnReferencee );
- }
- }
+ // get tokens for this parameter
+ TokenTuple p = new TokenTuple(hrnParam.getID(),
+ true,
+ TokenTuple.ARITY_ONE).makeCanonical();
+
+ TokenTuple pStar = new TokenTuple(hrnParam.getID(),
+ true,
+ TokenTuple.ARITY_MANY).makeCanonical();
+
+ // get special label p_q
+ TempDescriptor tdParamQ = paramIndex2tdQ.get(paramIndex);
+ assert tdParamQ != null;
+ LabelNode lnParamQ = td2ln.get(tdParamQ);
+ assert lnParamQ != null;
+
+ // then get the edge from label q to parameter's hrn
+ ReferenceEdge edgeSpecialQ = lnParamQ.getReferenceTo(hrnParam, null);
+ assert edgeSpecialQ != null;
+
+ // look through this beta set for potential aliases
+ ReachabilitySet beta = edgeSpecialQ.getBeta();
+ assert beta != null;
+
+
+ // get tokens for summary node
+ TokenTuple gs = new TokenTuple(as.getSummary(),
+ true,
+ TokenTuple.ARITY_ONE).makeCanonical();
+
+ TokenTuple gsStar = new TokenTuple(as.getSummary(),
+ true,
+ TokenTuple.ARITY_MANY).makeCanonical();
+
+ if( beta.containsTupleSetWithBoth(p, gs) ) {
+ return true;
+ }
+ if( beta.containsTupleSetWithBoth(pStar, gs) ) {
+ return true;
+ }
+ if( beta.containsTupleSetWithBoth(p, gsStar) ) {
+ return true;
+ }
+ if( beta.containsTupleSetWithBoth(pStar, gsStar) ) {
+ return true;
+ }
+
+ // check for other nodes
+ for( int i = 0; i < as.getAllocationDepth(); ++i ) {
+
+ // the other nodes of an allocation site are single, no stars
+ TokenTuple gi = new TokenTuple(as.getIthOldest(i),
+ false,
+ TokenTuple.ARITY_ONE).makeCanonical();
+
+ if( beta.containsTupleSetWithBoth(p, gi) ) {
+ return true;
}
+ if( beta.containsTupleSetWithBoth(pStar, gi) ) {
+ return true;
+ }
+ }
- return idSetReachableFromB;
- }
+ return false;
+ }
+
+
+ public boolean hasPotentialAlias(AllocationSite as1, AllocationSite as2) {
+ // get tokens for summary nodes
+ TokenTuple gs1 = new TokenTuple(as1.getSummary(),
+ true,
+ TokenTuple.ARITY_ONE).makeCanonical();
- // used to find if a heap region can possibly have a reference to
- // any of the heap regions in the given set
- // if the id supplied is in the set, then a self-referencing edge
- // would return true, but that special case is specifically allowed
- // meaning that it isn't an external alias
- public boolean canIdReachSet( Integer id, HashSet<Integer> idSet ) {
+ TokenTuple gsStar1 = new TokenTuple(as1.getSummary(),
+ true,
+ TokenTuple.ARITY_MANY).makeCanonical();
- assert id2hrn.contains( id );
- HeapRegionNode hrn = id2hrn.get( id );
+ // get summary node's alpha
+ Integer idSum1 = as1.getSummary();
+ assert id2hrn.containsKey(idSum1);
+ HeapRegionNode hrnSum1 = id2hrn.get(idSum1);
+ assert hrnSum1 != null;
+ ReachabilitySet alphaSum1 = hrnSum1.getAlpha();
+ assert alphaSum1 != null;
- //HashSet<HeapRegionNode> hrnSet = new HashSet<HeapRegionNode>();
+ // and for the other one
+ TokenTuple gs2 = new TokenTuple(as2.getSummary(),
+ true,
+ TokenTuple.ARITY_ONE).makeCanonical();
- //Iterator i = idSet.iterator();
- //while( i.hasNext() ) {
- // Integer idFromSet = (Integer) i.next();
- // assert id2hrn.contains( idFromSet );
- // hrnSet.add( id2hrn.get( idFromSet ) );
- //}
+ TokenTuple gsStar2 = new TokenTuple(as2.getSummary(),
+ true,
+ TokenTuple.ARITY_MANY).makeCanonical();
+ // get summary node's alpha
+ Integer idSum2 = as2.getSummary();
+ assert id2hrn.containsKey(idSum2);
+ HeapRegionNode hrnSum2 = id2hrn.get(idSum2);
+ assert hrnSum2 != null;
+ ReachabilitySet alphaSum2 = hrnSum2.getAlpha();
+ assert alphaSum2 != null;
- // do a traversal from hrn and see if any of the
- // heap regions from the set come up during that
- HashSet<HeapRegionNode> toVisit = new HashSet<HeapRegionNode>();
- HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
+ // does either one report reachability from the other tokens?
+ if( alphaSum1.containsTuple(gsStar2) ) {
+ return true;
+ }
+ if( alphaSum2.containsTuple(gsStar1) ) {
+ return true;
+ }
+
+ // only check non-star token if they are different sites
+ if( as1 != as2 ) {
+ if( alphaSum1.containsTuple(gs2) ) {
+ return true;
+ }
+ if( alphaSum2.containsTuple(gs1) ) {
+ return true;
+ }
+ }
- toVisit.add( hrn );
- while( !toVisit.isEmpty() ) {
- HeapRegionNode hrnVisited = (HeapRegionNode) toVisit.iterator().next();
- toVisit.remove( hrnVisited );
- visited.add ( hrnVisited );
- Iterator referenceeItr = hrnVisited.setIteratorToReferencedRegions();
- while( referenceeItr.hasNext() ) {
- Map.Entry me = (Map.Entry) referenceeItr.next();
- HeapRegionNode hrnReferencee = (HeapRegionNode) me.getKey();
- ReferenceEdgeProperties rep = (ReferenceEdgeProperties) me.getValue();
+ // check sum2 against alloc1 nodes
+ for( int i = 0; i < as1.getAllocationDepth(); ++i ) {
+ Integer idI1 = as1.getIthOldest(i);
+ assert id2hrn.containsKey(idI1);
+ HeapRegionNode hrnI1 = id2hrn.get(idI1);
+ assert hrnI1 != null;
+ ReachabilitySet alphaI1 = hrnI1.getAlpha();
+ assert alphaI1 != null;
- if( idSet.contains( hrnReferencee.getID() ) ) {
- if( !id.equals( hrnReferencee.getID() ) ) {
- return true;
- }
- }
+ // the other nodes of an allocation site are single, no stars
+ TokenTuple gi1 = new TokenTuple(as1.getIthOldest(i),
+ false,
+ TokenTuple.ARITY_ONE).makeCanonical();
- if( !visited.contains( hrnReferencee ) ) {
- toVisit.add( hrnReferencee );
- }
- }
+ if( alphaSum2.containsTuple(gi1) ) {
+ return true;
+ }
+ if( alphaI1.containsTuple(gs2) ) {
+ return true;
+ }
+ if( alphaI1.containsTuple(gsStar2) ) {
+ return true;
}
+ }
- return false;
- }
- */
+ // check sum1 against alloc2 nodes
+ for( int i = 0; i < as2.getAllocationDepth(); ++i ) {
+ Integer idI2 = as2.getIthOldest(i);
+ assert id2hrn.containsKey(idI2);
+ HeapRegionNode hrnI2 = id2hrn.get(idI2);
+ assert hrnI2 != null;
+ ReachabilitySet alphaI2 = hrnI2.getAlpha();
+ assert alphaI2 != null;
+
+ TokenTuple gi2 = new TokenTuple(as2.getIthOldest(i),
+ false,
+ TokenTuple.ARITY_ONE).makeCanonical();
+
+ if( alphaSum1.containsTuple(gi2) ) {
+ return true;
+ }
+ if( alphaI2.containsTuple(gs1) ) {
+ return true;
+ }
+ if( alphaI2.containsTuple(gsStar1) ) {
+ return true;
+ }
+
+ // while we're at it, do an inner loop for alloc2 vs alloc1 nodes
+ for( int j = 0; j < as1.getAllocationDepth(); ++j ) {
+ Integer idI1 = as1.getIthOldest(j);
+
+ // if these are the same site, don't look for the same token, no alias
+ // different tokens of the same site could alias together though
+ if( idI1 == idI2 ) {
+ continue;
+ }
+
+ HeapRegionNode hrnI1 = id2hrn.get(idI1);
+ ReachabilitySet alphaI1 = hrnI1.getAlpha();
+ TokenTuple gi1 = new TokenTuple(as1.getIthOldest(j),
+ false,
+ TokenTuple.ARITY_ONE).makeCanonical();
+ if( alphaI2.containsTuple(gi1) ) {
+ return true;
+ }
+ if( alphaI1.containsTuple(gi2) ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
// for writing ownership graphs to dot files
boolean writeLabels,
boolean labelSelect,
boolean pruneGarbage,
- boolean writeReferencers
+ boolean writeReferencers,
+ boolean writeParamMappings
) throws java.io.IOException {
writeGraph(
methodDesc.getSymbol() +
writeLabels,
labelSelect,
pruneGarbage,
- writeReferencers
+ writeReferencers,
+ writeParamMappings
);
}
- /*
- public void writeGraph(Descriptor methodDesc,
- FlatNode fn,
+ public void writeGraph(Descriptor methodDesc,
boolean writeLabels,
- boolean writeReferencers
+ boolean labelSelect,
+ boolean pruneGarbage,
+ boolean writeReferencers,
+ boolean writeParamMappings
) throws java.io.IOException {
- writeGraph(
- methodDesc.getSymbol() +
- methodDesc.getNum() +
- fn.toString(),
- writeLabels,
- false,
- false,
- writeReferencers
- );
- }
- public void writeGraph(Descriptor methodDesc,
- boolean writeLabels,
- boolean writeReferencers
- ) throws java.io.IOException {
- writeGraph(
- methodDesc.getSymbol() +
- methodDesc.getNum() +
- "COMPLETE",
- writeLabels,
- false,
- false,
- writeReferencers
- );
- }
- */
+ writeGraph(methodDesc+"COMPLETE",
+ writeLabels,
+ labelSelect,
+ pruneGarbage,
+ writeReferencers,
+ writeParamMappings
+ );
+ }
public void writeGraph(Descriptor methodDesc,
+ Integer numUpdate,
boolean writeLabels,
boolean labelSelect,
boolean pruneGarbage,
- boolean writeReferencers
+ boolean writeReferencers,
+ boolean writeParamMappings
) throws java.io.IOException {
- writeGraph(methodDesc+"COMPLETE",
+ writeGraph(methodDesc+"COMPLETE"+String.format("%05d", numUpdate),
writeLabels,
labelSelect,
pruneGarbage,
- writeReferencers
+ writeReferencers,
+ writeParamMappings
);
}
boolean writeLabels,
boolean labelSelect,
boolean pruneGarbage,
- boolean writeReferencers
+ boolean writeReferencers,
+ boolean writeParamMappings
) throws java.io.IOException {
// remove all non-word characters from the graph name so
BufferedWriter bw = new BufferedWriter(new FileWriter(graphName+".dot") );
bw.write("digraph "+graphName+" {\n");
- //bw.write( " size=\"7.5,10\";\n" );
HashSet<HeapRegionNode> visited = new HashSet<HeapRegionNode>();
bw.write(" graphTitle[label=\""+graphName+"\",shape=box];\n");
+ if( writeParamMappings ) {
+ Set df = paramIndex2id.entrySet();
+ Iterator ih = df.iterator();
+ while( ih.hasNext() ) {
+ Map.Entry meh = (Map.Entry)ih.next();
+ Integer pi = (Integer) meh.getKey();
+ Integer id = (Integer) meh.getValue();
+ bw.write(" pindex"+pi+"[label=\""+pi+" to "+id+"\",shape=box];\n");
+ }
+ }
// then visit every label node, useful for debugging
if( writeLabels ) {