out.reachTuples.addAll( rs.reachTuples );
out.preds = Canonical.join( rs.preds,
preds );
-
+
out = (ReachState) makeCanonical( out );
op2result.put( op, out );
return out;
}
+ // NOTE: when taking the intersection of two reach sets it
+ // is possible for a reach state to be in both sets, but
+ // have different predicates. Conceptully the best new
+ // predicate is an AND of the source predicates, but to
+ // avoid eploding states we'll take an overapproximation
+ // by preferring the predicates from the state in the FIRST
+ // set, so order of arguments matters
public static ReachSet intersection( ReachSet rs1,
ReachSet rs2 ) {
assert rs1 != null;
ReachSet out = new ReachSet();
Iterator<ReachState> itr = rs1.iterator();
while( itr.hasNext() ) {
- ReachState state = (ReachState) itr.next();
- if( rs2.reachStates.contains( state ) ) {
- out.reachStates.add( state );
+ ReachState state1 = (ReachState) itr.next();
+ ReachState state2 = rs2.containsIgnorePreds( state1 );
+ if( state2 != null ) {
+ // prefer the predicates on state1, an overapproximation
+ // of state1 preds AND state2 preds
+ out.reachStates.add( state1 );
}
}
Iterator<ReachState> stateItr = rs.iterator();
while( stateItr.hasNext() ) {
- ReachState state = stateItr.next();
+ ReachState stateOrig = stateItr.next();
boolean changeFound = false;
while( ctItr.hasNext() ) {
ChangeTuple ct = ctItr.next();
- if( state.equals( ct.getSetToMatch() ) ) {
- out.reachStates.add( ct.getSetToAdd() );
+ if( stateOrig.equalsIgnorePreds( ct.getStateToMatch() ) ) {
+ // use the new state, but the original predicates
+ ReachState stateNew =
+ ReachState.factory( ct.getStateToAdd().reachTuples,
+ stateOrig.preds
+ );
+ out.reachStates.add( stateNew );
changeFound = true;
}
}
if( keepSourceState || !changeFound ) {
- out.reachStates.add( state );
+ out.reachStates.add( stateOrig );
}
}
return out;
}
- public static ChangeSet union( ChangeSet cs,
- ChangeTuple ct ) {
+ public static ChangeSet add( ChangeSet cs,
+ ChangeTuple ct ) {
assert cs != null;
assert ct != null;
assert cs.isCanonical();
}
-
-
-
-
-
-
-
public static ReachSet unshadow( ReachSet rs,
AllocSite as ) {
assert rs != null;
public static ChangeTuple factory( ReachState toMatch,
ReachState toAdd ) {
- ChangeTuple out = new ChangeTuple( toMatch,
- toAdd );
+ // we don't care about the predicates hanging on
+ // change tuple states, so always set them to empty
+ // to ensure change tuple sets work out
+ ReachState toMatchNoPreds =
+ ReachState.factory( toMatch.reachTuples,
+ ExistPredSet.factory()
+ );
+ ReachState toAddNoPreds =
+ ReachState.factory( toAdd.reachTuples,
+ ExistPredSet.factory()
+ );
+ ChangeTuple out = new ChangeTuple( toMatchNoPreds,
+ toAddNoPreds );
out = (ChangeTuple) Canonical.makeCanonical( out );
return out;
}
this.toAdd = toAdd;
}
- public ReachState getSetToMatch() {
+ public ReachState getStateToMatch() {
return toMatch;
}
- public ReachState getSetToAdd() {
+ public ReachState getStateToAdd() {
return toAdd;
}
preds = new HashSet<ExistPred>();
}
+
+ public Iterator<ExistPred> iterator() {
+ return preds.iterator();
+ }
+
// only consider the subest of the caller elements that
// are reachable by callee when testing predicates
Iterator<ChangeTuple> itrCprime = C.iterator();
while( itrCprime.hasNext() ) {
ChangeTuple c = itrCprime.next();
- if( edgeF.getBeta().contains( c.getSetToMatch() ) ) {
- changesToPass = Canonical.union( changesToPass, c );
+ if( edgeF.getBeta().containsIgnorePreds( c.getStateToMatch() )
+ != null
+ ) {
+ changesToPass = Canonical.add( changesToPass, c );
}
}
Iterator<ChangeTuple> itrC = C.iterator();
while( itrC.hasNext() ) {
ChangeTuple c = itrC.next();
- if( edgeE.getBeta().contains( c.getSetToMatch() ) ) {
- changesToPass = Canonical.union( changesToPass, c );
+ if( edgeE.getBeta().containsIgnorePreds( c.getStateToMatch() )
+ != null
+ ) {
+ changesToPass = Canonical.add( changesToPass, c );
}
}
ChangeSet cs = ChangeSet.factory();
Iterator<ReachState> rsItr = reCaller.getBeta().iterator();
while( rsItr.hasNext() ) {
- ReachState state = rsItr.next();
- ExistPredSet preds2 = state.getPreds();
- assert preds2.preds.size() == 1;
+ ReachState state = rsItr.next();
+ ExistPredSet predsPreCallee = state.getPreds();
if( state.isEmpty() ) {
continue;
}
- ExistPred pred = preds2.preds.iterator().next();
- ReachState old = pred.ne_state;
-
- if( old == null ) {
- old = rstateEmpty;
- }
+ Iterator<ExistPred> predItr = predsPreCallee.iterator();
+ while( predItr.hasNext() ) {
+ ExistPred pred = predItr.next();
+ ReachState old = pred.ne_state;
- assert old != null;
+ if( old == null ) {
+ old = rstateEmpty;
+ }
- cs = Canonical.union( cs,
+ cs = Canonical.add( cs,
ChangeTuple.factory( old,
state
)
);
+ }
}
// look to see if an edge with same field exists
if( prevResult == null ||
Canonical.unionORpreds( prevResult,
- intersection ).size() > prevResult.size() ) {
+ intersection ).size()
+ > prevResult.size()
+ ) {
if( prevResult == null ) {
boldB_f.put( edgePrime,
Canonical.unionORpreds( edgePrime.getBeta(),
- intersection
- )
+ intersection
+ )
);
} else {
boldB_f.put( edgePrime,
Canonical.unionORpreds( prevResult,
- intersection
- )
+ intersection
+ )
);
}
workSetEdges.add( edgePrime );
// if there is nothing marked, just move on
if( markedHrnIDs.isEmpty() ) {
hrn.setAlphaNew( Canonical.add( hrn.getAlphaNew(),
- stateOld
- )
+ stateOld
+ )
);
continue;
}
assert !stateOld.equals( statePruned );
hrn.setAlphaNew( Canonical.add( hrn.getAlphaNew(),
- statePruned
- )
+ statePruned
+ )
);
ChangeTuple ct = ChangeTuple.factory( stateOld,
statePruned
);
- cts = Canonical.union( cts, ct );
+ cts = Canonical.add( cts, ct );
}
// throw change tuple set on all incident edges
if( Canonical.unionORpreds( prevResult,
intersection
- ).size() > prevResult.size() ) {
+ ).size()
+ > prevResult.size()
+ ) {
+
edge.setBetaNew(
Canonical.unionORpreds( prevResult,
intersection
}
}
- Set<HeapRegionNode> intersection = new HashSet<HeapRegionNode>(
- reachableNodes1);
+ Set<HeapRegionNode> intersection =
+ new HashSet<HeapRegionNode>( reachableNodes1 );
- intersection.retainAll(reachableNodes2);
+ intersection.retainAll( reachableNodes2 );
return intersection;
}