protected boolean isFlagged;
protected boolean isNewSummary;
- // clean means that the node existed
- // before the current analysis context
- protected boolean isClean;
-
// special nodes that represent heap parts
// outside of the current method context
protected boolean isOutOfContext;
boolean isSingleObject,
boolean isFlagged,
boolean isNewSummary,
- boolean isClean,
boolean isOutOfContext,
TypeDescriptor type,
AllocSite allocSite,
this.isSingleObject = isSingleObject;
this.isFlagged = isFlagged;
this.isNewSummary = isNewSummary;
- this.isClean = isClean;
this.isOutOfContext = isOutOfContext;
this.type = type;
this.allocSite = allocSite;
isSingleObject,
isFlagged,
isNewSummary,
- isClean,
isOutOfContext,
type,
allocSite,
assert isSingleObject == hrn.isSingleObject();
assert isFlagged == hrn.isFlagged();
assert isNewSummary == hrn.isNewSummary();
- assert isClean == hrn.isClean();
assert isOutOfContext == hrn.isOutOfContext();
assert description.equals( hrn.getDescription() );
return isOutOfContext;
}
- public boolean isClean() {
- return isClean;
- }
-
- public void setIsClean( boolean isClean ) {
- this.isClean = isClean;
- }
-
public Iterator<RefEdge> iteratorToReferencers() {
return referencers.iterator();
}
+ public ExistPredSet getPreds() {
+ return preds;
+ }
+
+ public void setPreds( ExistPredSet preds ) {
+ this.preds = preds;
+ }
+
+
public String getIDString() {
String s;
return s;
}
- public String getAlphaString( boolean hideSubsetReachability ) {
- return alpha.toStringEscapeNewline( hideSubsetReachability );
- }
+ public String getDescription() {
+ return description;
+ }
+
+ public String toStringDOT( boolean hideSubsetReach ) {
+ String attributes = "";
+
+ if( isSingleObject ) {
+ attributes += "shape=box";
+ } else {
+ attributes += "shape=Msquare";
+ }
- public String getPredString() {
- return preds.toString();
+ if( isFlagged ) {
+ attributes += ",style=filled,fillcolor=lightgrey";
+ }
+
+ return new String( "["+attributes+
+ ",label=\"ID"+getIDString()+"\\n"+
+ type.toPrettyString()+"\\n"+
+ description+"\\n"+
+ alpha.toStringEscNewline( hideSubsetReach )+"\\n"+
+ preds+"\"]"
+ );
}
public String toString() {
return "HRN"+getIDString();
}
-
- public String getDescription() {
- return description;
- }
}
protected static final ReachSet rsetWithEmptyState = new ReachSet( rstateEmpty ).makeCanonical();
// predicate constants
- protected static final ExistPredSet predsEmpty = new ExistPredSet().makeCanonical();
+ protected static final ExistPredTrue predTrue = new ExistPredTrue();
+ protected static final ExistPredSet predsEmpty = new ExistPredSet().makeCanonical();
+ protected static final ExistPredSet predsTrue = new ExistPredSet( predTrue ).makeCanonical();
// from DisjointAnalysis for convenience
boolean isSingleObject,
boolean isNewSummary,
boolean isFlagged,
- boolean isClean,
boolean isOutOfContext,
TypeDescriptor type,
AllocSite allocSite,
}
if( preds == null ) {
- // TODO: do this right?
+ // TODO: do this right? For out-of-context nodes?
preds = new ExistPredSet().makeCanonical();
}
isSingleObject,
markForAnalysis,
isNewSummary,
- isClean,
isOutOfContext,
typeToUse,
allocSite,
hrnHrn,
tdNewEdge,
null,
- false,
betaY.intersection( betaHrn ),
- predsEmpty
+ predsTrue
);
addRefEdge( lnX, hrnHrn, edgeNew );
hrnY,
tdNewEdge,
f.getSymbol(),
- false,
edgeY.getBeta().pruneBy( hrnX.getAlpha() ),
- predsEmpty
+ predsTrue
);
// look to see if an edge with same field exists
edgeExisting.setBeta(
edgeExisting.getBeta().union( edgeNew.getBeta() )
);
- // we touched this edge in the current context
- // so dirty it
- edgeExisting.setIsClean( false );
+ edgeExisting.setPreds(
+ edgeExisting.getPreds().join( edgeNew.getPreds() )
+ );
} else {
addRefEdge( hrnX, hrnY, edgeNew );
hrnNewest, // dest
type, // type
null, // field name
- false, // is initial param
hrnNewest.getAlpha(), // beta
- predsEmpty // predicates
+ predsTrue // predicates
);
addRefEdge( lnX, hrnNewest, edgeNew );
// after tokens have been aged, reset newest node's reachability
+ // and a brand new node has a "true" predicate
hrn0.setAlpha( hrn0.getInherent() );
+ hrn0.setPreds( predsTrue );
}
false, // single object?
true, // summary?
hasFlags, // flagged?
- false, // clean?
false, // out-of-context?
as.getType(), // type
as, // allocation site
true, // single object?
false, // summary?
hasFlags, // flagged?
- false, // clean?
false, // out-of-context?
as.getType(), // type
as, // allocation site
false, // single object?
true, // summary?
hasFlags, // flagged?
- false, // clean?
false, // out-of-context?
as.getType(), // type
as, // allocation site
true, // single object?
false, // summary?
hasFlags, // flagged?
- false, // clean?
false, // out-of-context?
as.getType(), // type
as, // allocation site
// otherwise an edge from the referencer to hrnSummary exists already
// and the edge referencer->hrn should be merged with it
edgeMerged.setBeta( edgeMerged.getBeta().union( edgeSummary.getBeta() ) );
+ edgeMerged.setPreds( edgeMerged.getPreds().join( edgeSummary.getPreds() ) );
}
addRefEdge( hrnSummary, hrnReferencee, edgeMerged );
// otherwise an edge from the referencer to alpha_S exists already
// and the edge referencer->alpha_K should be merged with it
edgeMerged.setBeta( edgeMerged.getBeta().union( edgeSummary.getBeta() ) );
+ edgeMerged.setPreds( edgeMerged.getPreds().join( edgeSummary.getPreds() ) );
}
addRefEdge( onReferencer, hrnSummary, edgeMerged );
addRefEdge( onReferencer, hrnB, edgeNew );
}
- // replace hrnB reachability with hrnA's
+ // replace hrnB reachability and preds with hrnA's
hrnB.setAlpha( hrnA.getAlpha() );
+ hrnB.setPreds( hrnA.getPreds() );
}
VariableNode vnCaller = this.getVariableNodeFromTemp( tdArg );
VariableNode vnCallee = rg.getVariableNodeFromTemp( tdParam );
- // now traverse the caller view using the argument to
- // build the callee view which has the parameter symbol
+ // now traverse the calleR view using the argument to
+ // build the calleE view which has the parameter symbol
Set<RefSrcNode> toVisitInCaller = new HashSet<RefSrcNode>();
Set<RefSrcNode> visitedInCaller = new HashSet<RefSrcNode>();
toVisitInCaller.add( vnCaller );
toVisitInCaller.remove( rsnCaller );
visitedInCaller.add( rsnCaller );
- // FIRST - setup the source end of an edge
+ // FIRST - setup the source end of an edge, and
+ // remember the identifying info of the source
+ // to build predicates
+ TempDescriptor tdSrc = null;
+ Integer hrnSrcID = null;
if( rsnCaller == vnCaller ) {
// if the caller node is the param symbol, we
// have to do this translation for the callee
rsnCallee = vnCallee;
+ tdSrc = tdArg;
+
} else {
// otherwise the callee-view node is a heap
// region with the same ID, that may or may
// not have been created already
assert rsnCaller instanceof HeapRegionNode;
- HeapRegionNode hrnSrcCaller = (HeapRegionNode) rsnCaller;
+ HeapRegionNode hrnSrcCaller = (HeapRegionNode) rsnCaller; hrnSrcID = hrnSrcCaller.getID();
if( !callerNodesCopiedToCallee.contains( rsnCaller ) ) {
+
+ ExistPredNode pred =
+ new ExistPredNode( hrnSrcID, null );
+
+ ExistPredSet preds = new ExistPredSet();
+ preds.add( pred );
+
rsnCallee =
rg.createNewHeapRegionNode( hrnSrcCaller.getID(),
hrnSrcCaller.isSingleObject(),
hrnSrcCaller.isNewSummary(),
hrnSrcCaller.isFlagged(),
- true, // clean?
false, // out-of-context?
hrnSrcCaller.getType(),
hrnSrcCaller.getAllocSite(),
toShadowTokens( this, hrnSrcCaller.getInherent() ),
toShadowTokens( this, hrnSrcCaller.getAlpha() ),
- predsEmpty,
+ preds,
hrnSrcCaller.getDescription()
);
callerNodesCopiedToCallee.add( rsnCaller );
+
} else {
- rsnCallee = rg.id2hrn.get( hrnSrcCaller.getID() );
+ rsnCallee = rg.id2hrn.get( hrnSrcID );
}
}
HeapRegionNode hrnCallee;
// THIRD - setup destination ends of edges
+ Integer hrnDstID = hrnCaller.getID();
if( !callerNodesCopiedToCallee.contains( hrnCaller ) ) {
+
+ ExistPredNode pred =
+ new ExistPredNode( hrnDstID, null );
+
+ ExistPredSet preds = new ExistPredSet();
+ preds.add( pred );
+
hrnCallee =
rg.createNewHeapRegionNode( hrnCaller.getID(),
hrnCaller.isSingleObject(),
hrnCaller.isNewSummary(),
hrnCaller.isFlagged(),
- true, // clean?
false, // out-of-context?
hrnCaller.getType(),
hrnCaller.getAllocSite(),
toShadowTokens( this, hrnCaller.getInherent() ),
toShadowTokens( this, hrnCaller.getAlpha() ),
- predsEmpty,
+ preds,
hrnCaller.getDescription()
);
callerNodesCopiedToCallee.add( hrnCaller );
} else {
- hrnCallee = rg.id2hrn.get( hrnCaller.getID() );
+ hrnCallee = rg.id2hrn.get( hrnDstID );
}
// FOURTH - copy edge over if needed
if( !callerEdgesCopiedToCallee.contains( reCaller ) ) {
+
+ ExistPredEdge pred =
+ new ExistPredEdge( tdSrc,
+ hrnSrcID,
+ hrnDstID,
+ reCaller.getType(),
+ reCaller.getField(),
+ null );
+
+ ExistPredSet preds = new ExistPredSet();
+ preds.add( pred );
+
rg.addRefEdge( rsnCallee,
hrnCallee,
new RefEdge( rsnCallee,
hrnCallee,
reCaller.getType(),
reCaller.getField(),
- true, // clean?
toShadowTokens( this, reCaller.getBeta() ),
- predsEmpty
+ preds
)
);
callerEdgesCopiedToCallee.add( reCaller );
false, // single object?
false, // new summary?
false, // flagged?
- true, // clean?
true, // out-of-context?
hrnCallerAndOutContext.getType(),
null, // alloc site, shouldn't be used
hrnCalleeAndInContext,
edgeMightCross.getType(),
edgeMightCross.getField(),
- true, // clean?
toShadowTokens( this, edgeMightCross.getBeta() ),
predsEmpty
)
rg.writeGraph( "calleeview", true, true, true, false, true, true );
} catch( IOException e ) {}
- if( fc.getMethod().getSymbol().equals( "f1" ) ) {
+ if( fc.getMethod().getSymbol().equals( "addSomething" ) ) {
System.exit( 0 );
}
hrnB.setAlpha( hrnB.getAlpha().union( hrnA.getAlpha() ) );
// if hrnB is already dirty or hrnA is dirty,
- // the hrnB should end up dirty
+ // the hrnB should end up dirty: TODO
+ /*
if( !hrnA.isClean() ) {
hrnB.setIsClean( false );
}
+ */
}
}
edgeToMerge.setBeta(
edgeToMerge.getBeta().union( edgeA.getBeta() )
);
+ // TODO: what?
+ /*
if( !edgeA.isClean() ) {
edgeToMerge.setIsClean( false );
}
+ */
}
}
}
edgeToMerge.setBeta(
edgeToMerge.getBeta().union( edgeA.getBeta() )
);
+ // TODO: what?
+ /*
if( !edgeA.isClean() ) {
edgeToMerge.setIsClean( false );
}
+ */
}
}
}
continue;
}
}
-
- //bw.write(" "+vn.toString() + ";\n");
Iterator<RefEdge> heapRegionsItr = vn.iteratorToReferencees();
while( heapRegionsItr.hasNext() ) {
hideEdgeTaints );
}
- bw.write( " " + vn.toString() +
- " -> " + hrn.toString() +
- "[label=\"" + edge.toGraphEdgeString( hideSubsetReachability ) +
- "\",decorate];\n" );
+ bw.write( " "+vn.toString()+
+ " -> "+hrn.toString()+
+ edge.toStringDOT( hideSubsetReachability )+
+ ";\n" );
}
}
}
}
visited.add( hrn );
- String attributes = "[";
-
- if( hrn.isSingleObject() ) {
- attributes += "shape=box";
- } else {
- attributes += "shape=Msquare";
- }
-
- if( hrn.isFlagged() ) {
- attributes += ",style=filled,fillcolor=lightgrey";
- }
-
- attributes += ",label=\"ID" +
- hrn.getID() +
- "\\n";
-
- if( hrn.getType() != null ) {
- attributes += hrn.getType().toPrettyString()+"\\n";
- }
-
- attributes += hrn.getDescription()+
- "\\n"+hrn.getAlphaString( hideSubsetReachability )+
- "\\n"+hrn.getPredString()+
- "\"]";
-
- bw.write( " "+hrn.toString()+attributes+";\n" );
-
+ bw.write( " "+hrn.toString()+
+ hrn.toStringDOT( hideSubsetReachability )+
+ ";\n" );
Iterator<RefEdge> childRegionsItr = hrn.iteratorToReferencees();
while( childRegionsItr.hasNext() ) {
RefEdge edge = childRegionsItr.next();
HeapRegionNode hrnChild = edge.getDst();
- bw.write( " " +hrn.toString()+
- " -> " +hrnChild.toString()+
- "[label=\""+edge.toGraphEdgeString( hideSubsetReachability )+
- "\",decorate];\n");
+ bw.write( " "+hrn.toString()+
+ " -> "+hrnChild.toString()+
+ edge.toStringDOT( hideSubsetReachability )+
+ ";\n");
traverseHeapRegionNodes( hrnChild,
bw,