// used below to convert a ReachSet to its caller-context
// equivalent with respect to allocation sites in this graph
- protected ReachSet toCallerContext( ReachSet rs ) {
- ReachSet out = rs;
- Iterator<AllocSite> asItr = allocSites.iterator();
- while( asItr.hasNext() ) {
- AllocSite as = asItr.next();
- out = Canonical.toCallerContext( out, as );
+ protected ReachSet
+ toCallerContext( ReachSet rs,
+ Hashtable<ReachState, ExistPredSet> calleeStatesSatisfied
+ ) {
+ ReachSet out = ReachSet.factory();
+
+ Iterator<ReachState> itr = rs.iterator();
+ while( itr.hasNext() ) {
+ ReachState stateCallee = itr.next();
+
+ if( calleeStatesSatisfied.containsKey( stateCallee ) ) {
+
+ // starting from one callee state...
+ ReachSet rsCaller = ReachSet.factory( stateCallee );
+
+ // possibly branch it into many states, which any
+ // allocation site might do, so lots of derived states
+ Iterator<AllocSite> asItr = allocSites.iterator();
+ while( asItr.hasNext() ) {
+ AllocSite as = asItr.next();
+ rsCaller = Canonical.toCallerContext( rs, as );
+ }
+
+ // then before adding each derived, now caller-context
+ // states to the output, attach the appropriate pred
+ // based on the source callee state
+ Iterator<ReachState> stateItr = rsCaller.iterator();
+ while( stateItr.hasNext() ) {
+ ReachState stateCaller = stateItr.next();
+ stateCaller = Canonical.attach( stateCaller,
+ calleeStatesSatisfied.get( stateCallee )
+ );
+ out = Canonical.union( out,
+ stateCaller
+ );
+ }
+ }
}
+
assert out.isCanonical();
return out;
}
Hashtable<RefEdge, ExistPredSet> calleeEdgesSatisfied =
new Hashtable<RefEdge, ExistPredSet>();
+ Hashtable<ReachState, ExistPredSet> calleeStatesSatisfied =
+ new Hashtable<ReachState, ExistPredSet>();
+
Hashtable< RefEdge, Set<RefSrcNode> > calleeEdges2oocCallerSrcMatches =
new Hashtable< RefEdge, Set<RefSrcNode> >();
// otherwise don't bother looking at edges to this node
continue;
}
+
+ // since the node is coming over, find out which reach
+ // states on it should come over, too
+ Iterator<ReachState> stateItr = hrnCallee.getAlpha().iterator();
+ while( stateItr.hasNext() ) {
+ ReachState stateCallee = stateItr.next();
+
+ predsIfSatis =
+ stateCallee.getPreds().isSatisfiedBy( this,
+ callerNodeIDsCopiedToCallee
+ );
+ if( predsIfSatis != null ) {
+ calleeStatesSatisfied.put( stateCallee, predsIfSatis );
+ }
+ }
+ // then look at edges to the node
Iterator<RefEdge> reItr = hrnCallee.iteratorToReferencers();
while( reItr.hasNext() ) {
RefEdge reCallee = reItr.next();
);
if( predsIfSatis != null ) {
calleeEdgesSatisfied.put( reCallee, predsIfSatis );
+
+ // since the edge is coming over, find out which reach
+ // states on it should come over, too
+ stateItr = reCallee.getBeta().iterator();
+ while( stateItr.hasNext() ) {
+ ReachState stateCallee = stateItr.next();
+
+ predsIfSatis =
+ stateCallee.getPreds().isSatisfiedBy( this,
+ callerNodeIDsCopiedToCallee
+ );
+ if( predsIfSatis != null ) {
+ calleeStatesSatisfied.put( stateCallee, predsIfSatis );
+ }
+ }
+
}
}
);
if( predsIfSatis != null ) {
calleeEdgesSatisfied.put( reCallee, predsIfSatis );
+
+ // since the edge is coming over, find out which reach
+ // states on it should come over, too
+ Iterator<ReachState> stateItr = reCallee.getBeta().iterator();
+ while( stateItr.hasNext() ) {
+ ReachState stateCallee = stateItr.next();
+
+ predsIfSatis =
+ stateCallee.getPreds().isSatisfiedBy( this,
+ callerNodeIDsCopiedToCallee
+ );
+ if( predsIfSatis != null ) {
+ calleeStatesSatisfied.put( stateCallee, predsIfSatis );
+ }
+ }
+
}
}
}
false, // out-of-context?
hrnCallee.getType(), // type
hrnCallee.getAllocSite(), // allocation site
- toCallerContext( hrnCallee.getInherent() ), // inherent reach
+ toCallerContext( hrnCallee.getInherent(),
+ calleeStatesSatisfied ), // inherent reach
null, // current reach
predsEmpty, // predicates
hrnCallee.getDescription() // description
assert hrnCaller.isWiped();
}
- // TODO: alpha should be some rewritten version of callee in caller context
- hrnCaller.setAlpha( toCallerContext( hrnCallee.getAlpha() ) );
+ hrnCaller.setAlpha( toCallerContext( hrnCallee.getAlpha(),
+ calleeStatesSatisfied
+ )
+ );
hrnCaller.setPreds( preds );
}
false, // out-of-context?
hrnSrcCallee.getType(), // type
hrnSrcCallee.getAllocSite(), // allocation site
- toCallerContext( hrnSrcCallee.getInherent() ), // inherent reach
- toCallerContext( hrnSrcCallee.getAlpha() ), // current reach
+ toCallerContext( hrnSrcCallee.getInherent(),
+ calleeStatesSatisfied ), // inherent reach
+ toCallerContext( hrnSrcCallee.getAlpha(),
+ calleeStatesSatisfied ), // current reach
predsEmpty, // predicates
hrnSrcCallee.getDescription() // description
);
hrnDstCaller,
reCallee.getType(),
reCallee.getField(),
- toCallerContext( reCallee.getBeta() ),
+ toCallerContext( reCallee.getBeta(),
+ calleeStatesSatisfied ),
preds
);
false, // out-of-context?
hrnDstCallee.getType(), // type
hrnDstCallee.getAllocSite(), // allocation site
- toCallerContext( hrnDstCallee.getInherent() ), // inherent reach
- toCallerContext( hrnDstCallee.getAlpha() ), // current reach
+ toCallerContext( hrnDstCallee.getInherent(),
+ calleeStatesSatisfied ), // inherent reach
+ toCallerContext( hrnDstCallee.getAlpha(),
+ calleeStatesSatisfied ), // current reach
predsTrue, // predicates
hrnDstCallee.getDescription() // description
);
hrnDstCaller,
tdNewEdge,
null,
- toCallerContext( reCallee.getBeta() ),
+ toCallerContext( reCallee.getBeta(),
+ calleeStatesSatisfied ),
predsTrue
);