protected boolean isFlagged;
protected boolean isNewSummary;
+ // clean means that the node existed
+ // before the current analysis context
+ protected boolean isClean;
+
protected HashSet<RefEdge> referencers;
protected TypeDescriptor type;
protected AllocSite allocSite;
+ // some reachability states are inherent
+ // to a node by its definition
+ protected ReachSet inherent;
+
+ // use alpha for the current reach states
+ // and alphaNew during iterative calculations
+ // to update alpha
protected ReachSet alpha;
protected ReachSet alphaNew;
boolean isSingleObject,
boolean isFlagged,
boolean isNewSummary,
+ boolean isClean,
TypeDescriptor type,
AllocSite allocSite,
+ ReachSet inherent,
ReachSet alpha,
String description
) {
this.isSingleObject = isSingleObject;
this.isFlagged = isFlagged;
this.isNewSummary = isNewSummary;
+ this.isClean = isClean;
this.type = type;
this.allocSite = allocSite;
+ this.inherent = inherent;
this.alpha = alpha;
this.description = description;
isSingleObject,
isFlagged,
isNewSummary,
+ isClean,
type,
allocSite,
+ inherent,
alpha,
description );
}
assert isSingleObject == hrn.isSingleObject();
assert isFlagged == hrn.isFlagged();
assert isNewSummary == hrn.isNewSummary();
+ assert isClean == hrn.isClean();
assert description.equals( hrn.getDescription() );
return true;
return isNewSummary;
}
+ public boolean isClean() {
+ return isClean();
+ }
+
+ public void setIsClean( boolean isClean ) {
+ this.isClean = isClean;
+ }
+
public Iterator<RefEdge> iteratorToReferencers() {
return referencers.iterator();
return allocSite;
}
+
+ public ReachSet getInherent() {
+ return inherent;
+ }
+
public ReachSet getAlpha() {
return alpha;
}
}
public String getDescription() {
- //return new String(description);
return description;
}
}
boolean isSingleObject,
boolean isNewSummary,
boolean isFlagged,
+ boolean isClean,
TypeDescriptor type,
AllocSite allocSite,
+ ReachSet inherent,
ReachSet alpha,
String description
) {
id = DisjointAnalysis.generateUniqueHeapRegionNodeID();
}
- if( alpha == null ) {
+ if( inherent == null ) {
if( markForAnalysis ) {
- alpha = new ReachSet(
- new ReachTuple( id,
- !isSingleObject,
- ReachTuple.ARITY_ONE
- ).makeCanonical()
- ).makeCanonical();
+ inherent = new ReachSet(
+ new ReachTuple( id,
+ !isSingleObject,
+ ReachTuple.ARITY_ONE
+ ).makeCanonical()
+ ).makeCanonical();
} else {
- alpha = rsetWithEmptyState;
+ inherent = rsetWithEmptyState;
}
}
+
+ if( alpha == null ) {
+ alpha = inherent;
+ }
HeapRegionNode hrn = new HeapRegionNode( id,
isSingleObject,
markForAnalysis,
isNewSummary,
+ isClean,
typeToUse,
allocSite,
+ inherent,
alpha,
description );
id2hrn.put( id, hrn );
edgeExisting.setBeta(
edgeExisting.getBeta().union( edgeNew.getBeta() )
);
- // a new edge here cannot be reflexive, so existing will
- // always be also not reflexive anymore
- edgeExisting.setIsInitialParam( false );
+ // we touched this edge in the current context
+ // so dirty it
+ edgeExisting.setIsClean( false );
} else {
addRefEdge( hrnX, hrnY, edgeNew );
false, // single object?
true, // summary?
hasFlags, // flagged?
+ false, // dirty?
as.getType(), // type
as, // allocation site
- null, // reachability set
+ null, // inherent reach
+ null, // current reach
strDesc // description
);
true, // single object?
false, // summary?
hasFlags, // flagged?
+ false, // dirty?
as.getType(), // type
as, // allocation site
- null, // reachability set
+ null, // inherent reach
+ null, // current reach
strDesc // description
);
}
false, // single object?
true, // summary?
hasFlags, // flagged?
+ false, // dirty?
as.getType(), // type
as, // allocation site
- null, // reachability set
+ null, // inherent reach
+ null, // current reach
strDesc // description
);
createNewHeapRegionNode( idShadowIth, // id or null to generate a new one
true, // single object?
false, // summary?
- hasFlags, // flagged?
+ hasFlags, // flagged?
+ false, // dirty?
as.getType(), // type
as, // allocation site
- null, // reachability set
+ null, // inherent reach
+ null, // current reach
strDesc // description
);
}
// nodes' reachability sets
HeapRegionNode hrnB = id2hrn.get( idA );
hrnB.setAlpha( hrnB.getAlpha().union( hrnA.getAlpha() ) );
+
+ // if hrnB is already dirty or hrnA is dirty,
+ // the hrnB should end up dirty
+ if( !hrnA.isClean() ) {
+ hrnB.setIsClean( false );
+ }
}
}
edgeToMerge.setBeta(
edgeToMerge.getBeta().union( edgeA.getBeta() )
);
- if( !edgeA.isInitialParam() ) {
- edgeToMerge.setIsInitialParam( false );
+ if( !edgeA.isClean() ) {
+ edgeToMerge.setIsClean( false );
}
}
}
edgeToMerge.setBeta(
edgeToMerge.getBeta().union( edgeA.getBeta() )
);
- if( !edgeA.isInitialParam() ) {
- edgeToMerge.setIsInitialParam( false );
+ if( !edgeA.isClean() ) {
+ edgeToMerge.setIsClean( false );
}
}
}
hrnSrcCaller.isSingleObject(),
hrnSrcCaller.isNewSummary(),
hrnSrcCaller.isFlagged(),
+ true, // clean
hrnSrcCaller.getType(),
hrnSrcCaller.getAllocSite(),
+ hrnSrcCaller.getInherent(),
hrnSrcCaller.getAlpha(),
hrnSrcCaller.getDescription()
);
hrnCaller.isSingleObject(),
hrnCaller.isNewSummary(),
hrnCaller.isFlagged(),
+ true, // clean
hrnCaller.getType(),
hrnCaller.getAllocSite(),
+ hrnCaller.getInherent(),
hrnCaller.getAlpha(),
hrnCaller.getDescription()
);
// edge models a variable reference
protected String field;
- protected boolean isInitialParam;
+ // clean means that the reference existed
+ // before the current analysis context
+ protected boolean isClean;
protected ReachSet beta;
protected ReachSet betaNew;
HeapRegionNode dst,
TypeDescriptor type,
String field,
- boolean isInitialParam,
+ boolean isClean,
ReachSet beta ) {
assert type != null;
- this.src = src;
- this.dst = dst;
- this.type = type;
- this.field = field;
- this.isInitialParam = isInitialParam;
+ this.src = src;
+ this.dst = dst;
+ this.type = type;
+ this.field = field;
+ this.isClean = isClean;
if( beta != null ) {
this.beta = beta;
dst,
type,
field,
- isInitialParam,
+ isClean,
beta );
return copy;
}
return false;
}
+ assert isClean == edge.isClean;
+
return true;
}
}
- public boolean isInitialParam() {
- return isInitialParam;
+ public boolean isClean() {
+ return isClean;
}
- public void setIsInitialParam( boolean isInitialParam ) {
- this.isInitialParam = isInitialParam;
+ public void setIsClean( boolean isClean ) {
+ this.isClean = isClean;
}
edgeLabel += field + "\\n";
}
- if( isInitialParam ) {
- edgeLabel += "*init*\\n";
+ if( isClean ) {
+ edgeLabel += "*clean*\\n";
}
edgeLabel += beta.toStringEscapeNewline( hideSubsetReachability );