//
// Entries <x, f, y> mean x.f points directly at what
// y points at.
+ public class FdEntry {
+ TempDescriptor y;
+ FieldDescriptor f0;
+ TempDescriptor z;
+ public FdEntry( TempDescriptor y,
+ FieldDescriptor f0,
+ TempDescriptor z ) {
+ this.y = y;
+ this.f0 = f0;
+ this.z = z;
+ }
+ }
private static MultiViewMapBuilder<Object> FdBuilder;
private static BitSet viewFd0;
private static BitSet viewFd2;
}
+ public Set<FdEntry> edgesToElidePropagation( TempDescriptor x,
+ TempDescriptor y ) {
+ // return the set of edges that definite reach analysis tells
+ // us we can elide propagating reach info across during the
+ // store: x.f = y
+
+ Set<FdEntry> out = new HashSet<FdEntry>();
+
+ // we have to know something about y
+ DefReachKnown known = Rs.get( y );
+ if( known == null || known == DefReachKnown.UNKNOWN ) {
+ return out;
+ }
+
+ // find all 'y points at' entries in Fd
+ MultiKey keyY = MultiKey.factory( y );
+ Map<MultiKey, Object> mapY0 = Fd.get( viewFd0, keyY );
+
+ for( MultiKey fullKeyY : mapY0.keySet() ) {
+ // if y.f0 points at z, and z is already reachable from x,
+ // include the edge y.f0->z
+ FieldDescriptor f0 = (FieldDescriptor) fullKeyY.get( 1 );
+ TempDescriptor z = (TempDescriptor) fullKeyY.get( 2 );
+
+ if( isAlreadyReachable( z, x ) ) {
+ out.add( new FdEntry( y, f0, z ) );
+ }
+ }
+
+ return out;
+ }
+
+
public void methodEntry( Set<TempDescriptor> parameters ) {
Set<EdgeKey> edgeKeysForLoad;
Set<EdgeKey> edgeKeysRemoved;
Set<EdgeKey> edgeKeysAdded;
+ Set<DefiniteReachState.FdEntry> edgesToElideFromProp;
//Stores the flatnode's reach graph at enter
ReachGraph rgOnEnter = new ReachGraph();
boolean strongUpdate = false;
- alreadyReachable = false;
- edgeKeysRemoved = null;
- edgeKeysAdded = null;
+ alreadyReachable = false;
+ edgeKeysRemoved = null;
+ edgeKeysAdded = null;
+ edgesToElideFromProp = null;
if( doDefiniteReachAnalysis ) {
- alreadyReachable = definiteReachAnalysis.isAlreadyReachable( rhs, lhs, fn );
- edgeKeysRemoved = new HashSet<EdgeKey>();
- edgeKeysAdded = new HashSet<EdgeKey>();
+ alreadyReachable = definiteReachAnalysis.isAlreadyReachable( rhs, lhs, fn );
+ edgeKeysRemoved = new HashSet<EdgeKey>();
+ edgeKeysAdded = new HashSet<EdgeKey>();
+ edgesToElideFromProp = definiteReachAnalysis.edgesToElidePropagation( lhs, rhs, fn );
}
// before transfer func, possibly inject
fn,
alreadyReachable,
edgeKeysRemoved,
- edgeKeysAdded );
+ edgeKeysAdded,
+ edgesToElideFromProp );
if( doDefiniteReachAnalysis ) {
definiteReachAnalysis.store( fn,
lhs,
tdElement = lhs.getType().dereference();
fdElement = getArrayField(tdElement);
- alreadyReachable = false;
- edgeKeysRemoved = null;
- edgeKeysAdded = null;
+ alreadyReachable = false;
+ edgeKeysRemoved = null;
+ edgeKeysAdded = null;
+ edgesToElideFromProp = null;
if( doDefiniteReachAnalysis ) {
- alreadyReachable = definiteReachAnalysis.isAlreadyReachable( rhs, lhs, fn );
- edgeKeysRemoved = new HashSet<EdgeKey>();
- edgeKeysAdded = new HashSet<EdgeKey>();
+ alreadyReachable = definiteReachAnalysis.isAlreadyReachable( rhs, lhs, fn );
+ edgeKeysRemoved = new HashSet<EdgeKey>();
+ edgeKeysAdded = new HashSet<EdgeKey>();
+ edgesToElideFromProp = definiteReachAnalysis.edgesToElidePropagation( lhs, rhs, fn );
}
// before transfer func, possibly inject
fn,
alreadyReachable,
edgeKeysRemoved,
- edgeKeysAdded );
+ edgeKeysAdded,
+ edgesToElideFromProp );
}
if( doDefiniteReachAnalysis ) {
null,
false,
null,
+ null,
null );
}
FlatNode currentProgramPoint,
boolean alreadyReachable,
Set<EdgeKey> edgeKeysRemoved,
- Set<EdgeKey> edgeKeysAdded
+ Set<EdgeKey> edgeKeysAdded,
+ Set<DefiniteReachState.FdEntry> edgesToElideFromPropFd
) {
VariableNode lnX = getVariableNodeFromTemp(x);
}
+ // definite reachability analysis can elide some edges from
+ // propagating reach information
+ Set<RefEdge> edgesToElideFromProp = null;
+ if( edgesToElideFromPropFd != null ) {
+ edgesToElideFromProp = new HashSet<RefEdge>();
+ Iterator<RefEdge> itrY = lnY.iteratorToReferencees();
+ while( itrY.hasNext() ) {
+ HeapRegionNode hrnSrc = itrY.next().getDst();
+
+ Iterator<RefEdge> itrhrn = hrnSrc.iteratorToReferencees();
+ while( itrhrn.hasNext() ) {
+ RefEdge edgeToElide = itrhrn.next();
+ String f0 = edgeToElide.getField();
+ HeapRegionNode hrnDst = edgeToElide.getDst();
+
+ // does this graph edge match a statically-named edge
+ // that def reach says we don't have to prop over?
+ for( DefiniteReachState.FdEntry entry : edgesToElideFromPropFd ) {
+ if( !entry.f0.getSymbol().equals( f0 ) ) {
+ continue;
+ }
+ boolean refByZ = false;
+ Iterator<RefEdge> itrRef = hrnDst.iteratorToReferencers();
+ while( itrRef.hasNext() ) {
+ RefEdge edgeZ = itrRef.next();
+ if( edgeZ.getSrc() instanceof VariableNode ) {
+ VariableNode vnZ = (VariableNode) edgeZ.getSrc();
+ if( vnZ.getTempDescriptor().equals( entry.z ) ) {
+ refByZ = true;
+ break;
+ }
+ }
+ }
+ if( refByZ ) {
+ // this graph edge matches the def reach edge, mark it for
+ // no propagation
+ edgesToElideFromProp.add( edgeToElide );
+ }
+ }
+ }
+ }
+ }
+
+
+
// definite reachability analysis can elide reachability propagation
if( !alreadyReachable ) {
// propagate tokens over nodes starting from hrnSrc, and it will
// take care of propagating back up edges from any touched nodes
ChangeSet Cy = Canonical.unionUpArityToChangeSet(O, R);
- propagateTokensOverNodes(hrnY, Cy, nodesWithNewAlpha, edgesWithNewBeta);
+ propagateTokensOverNodes( hrnY,
+ Cy,
+ nodesWithNewAlpha,
+ edgesWithNewBeta,
+ edgesToElideFromProp );
// then propagate back just up the edges from hrn
ChangeSet Cx = Canonical.unionUpArityToChangeSet(R, O);
edgePlannedChanges.put(edgeUpstream, Cx);
}
- propagateTokensOverEdges(todoEdges,
- edgePlannedChanges,
- edgesWithNewBeta);
+ propagateTokensOverEdges( todoEdges,
+ edgePlannedChanges,
+ edgesWithNewBeta,
+ edgesToElideFromProp );
}
}
}
protected void propagateTokensOverNodes(HeapRegionNode nPrime,
ChangeSet c0,
HashSet<HeapRegionNode> nodesWithNewAlpha,
- HashSet<RefEdge> edgesWithNewBeta) {
+ HashSet<RefEdge> edgesWithNewBeta,
+ Set<RefEdge> edgesToElideProp ) {
HashSet<HeapRegionNode> todoNodes
= new HashSet<HeapRegionNode>();
Iterator<RefEdge> referItr = n.iteratorToReferencers();
while( referItr.hasNext() ) {
RefEdge edge = referItr.next();
+
+ if( edgesToElideProp != null && edgesToElideProp.contains( edge ) ) {
+ continue;
+ }
todoEdges.add(edge);
if( !edgePlannedChanges.containsKey(edge) ) {
Iterator<RefEdge> refeeItr = n.iteratorToReferencees();
while( refeeItr.hasNext() ) {
RefEdge edgeF = refeeItr.next();
+
+ if( edgesToElideProp != null && edgesToElideProp.contains( edgeF ) ) {
+ continue;
+ }
+
HeapRegionNode m = edgeF.getDst();
ChangeSet changesToPass = ChangeSet.factory();
propagateTokensOverEdges(todoEdges,
edgePlannedChanges,
- edgesWithNewBeta
- );
+ edgesWithNewBeta,
+ edgesToElideProp);
}
protected void propagateTokensOverEdges(HashSet <RefEdge> todoEdges,
Hashtable<RefEdge, ChangeSet> edgePlannedChanges,
- HashSet <RefEdge> edgesWithNewBeta) {
+ HashSet <RefEdge> edgesWithNewBeta,
+ Set<RefEdge> edgesToElideProp ) {
// first propagate all change tuples everywhere they can go
while( !todoEdges.isEmpty() ) {
while( referItr.hasNext() ) {
RefEdge edgeF = referItr.next();
+ if( edgesToElideProp != null && edgesToElideProp.contains( edgeF ) ) {
+ continue;
+ }
+
if( !edgePlannedChanges.containsKey(edgeF) ) {
edgePlannedChanges.put(edgeF,
ChangeSet.factory()
// of the caller graph edges
HashSet<RefEdge> edgesUpdated = new HashSet<RefEdge>();
- propagateTokensOverEdges(edgesForPropagation, // source edges
- edgePlannedChanges, // map src edge to change set
- edgesUpdated); // list of updated edges
+ propagateTokensOverEdges( edgesForPropagation, // source edges
+ edgePlannedChanges, // map src edge to change set
+ edgesUpdated, // list of updated edges
+ null );
// commit beta' (beta<-betaNew)
Iterator<RefEdge> edgeItr = edgesUpdated.iterator();
propagateTokensOverEdges(edgesForPropagation,
edgePlannedChanges,
- edgesUpdated);
+ edgesUpdated,
+ null);
// at the end of the 1st phase reference edges have
// beta, betaNew that correspond to beta and betaR