// not weighty, don't bother with caching
- public static ReachTuple unionArity( ReachTuple rt1,
- ReachTuple rt2 ) {
+ public static ReachTuple unionUpArity( ReachTuple rt1,
+ ReachTuple rt2 ) {
assert rt1 != null;
assert rt2 != null;
assert rt1.isCanonical();
}
- public static ReachState union( ReachState rs1,
- ReachState rs2 ) {
- assert rs1 != null;
- assert rs2 != null;
- assert rs1.isCanonical();
- assert rs2.isCanonical();
-
- CanonicalOp op =
- new CanonicalOp( CanonicalOp.REACHSTATE_UNION_REACHSTATE,
- rs1,
- rs2 );
-
- Canonical result = op2result.get( op );
- if( result != null ) {
- return (ReachState) result;
- }
-
- // otherwise, no cached result...
- ReachState out = new ReachState();
- out.reachTuples.addAll( rs1.reachTuples );
- out.reachTuples.addAll( rs2.reachTuples );
- out.preds = Canonical.join( rs1.getPreds(),
- rs2.getPreds()
- );
-
- out = (ReachState) makeCanonical( out );
- op2result.put( op, out );
- return out;
- }
-
- // this is just a convenience version of above
- public static ReachState union( ReachState rs,
- ReachTuple rt ) {
+ public static ReachState add( ReachState rs,
+ ReachTuple rt ) {
assert rs != null;
assert rt != null;
+ // this is only safe if we are certain the new tuple's
+ // ID doesn't already appear in the reach state
+ assert rs.containsHrnID( rt.getHrnID(),
+ rt.isOutOfContext() ) == null;
+
CanonicalOp op =
- new CanonicalOp( CanonicalOp.REACHSTATE_UNION_REACHTUPLE,
+ new CanonicalOp( CanonicalOp.REACHSTATE_ADD_REACHTUPLE,
rs,
rt );
// otherwise, no cached result...
ReachState out = new ReachState();
+ // first add everything from 1, and if it is
+ // also in 2 take the union of the tuple arities
Iterator<ReachTuple> rtItr = rs1.iterator();
while( rtItr.hasNext() ) {
ReachTuple rt1 = rtItr.next();
rt1.isOutOfContext()
);
if( rt2 != null ) {
- out.reachTuples.add( unionArity( rt1, rt2 ) );
+ out.reachTuples.add( unionUpArity( rt1, rt2 ) );
} else {
out.reachTuples.add( rt1 );
}
}
+ // then add everything in 2 that wasn't in 1
rtItr = rs2.iterator();
while( rtItr.hasNext() ) {
ReachTuple rt2 = rtItr.next();
- ReachTuple rto = out.containsHrnID( rt2.getHrnID(),
+ ReachTuple rt1 = rs1.containsHrnID( rt2.getHrnID(),
rt2.isOutOfContext()
);
- if( rto == null ) {
- out.reachTuples.add( rto );
+ if( rt1 == null ) {
+ out.reachTuples.add( rt2 );
}
}
return out;
}
- public static ReachState add( ReachState rs, ReachTuple rt ) {
- return union( rs, rt );
- }
public static ReachState remove( ReachState rs, ReachTuple rt ) {
assert rs != null;
);
} else if( rtSummary != null && rtOldest != null ) {
- out.reachTuples.add( Canonical.unionArity( rtSummary,
- ReachTuple.factory( as.getSummary(),
- true, // muli
- rtOldest.getArity(),
- false // out-of-context
- )
- )
+ out.reachTuples.add( Canonical.unionUpArity( rtSummary,
+ ReachTuple.factory( as.getSummary(),
+ true, // muli
+ rtOldest.getArity(),
+ false // out-of-context
+ )
+ )
);
}
- public static ReachSet union( ReachSet rs1,
- ReachSet rs2 ) {
+ public static ReachSet unionORpreds( ReachSet rs1,
+ ReachSet rs2 ) {
assert rs1 != null;
assert rs2 != null;
assert rs1.isCanonical();
assert rs2.isCanonical();
CanonicalOp op =
- new CanonicalOp( CanonicalOp.REACHSET_UNION_REACHSET,
+ new CanonicalOp( CanonicalOp.REACHSET_UNIONORPREDS_REACHSET,
rs1,
rs2 );
// otherwise, no cached result...
ReachSet out = new ReachSet();
- out.reachStates.addAll( rs1.reachStates );
- out.reachStates.addAll( rs2.reachStates );
- out = (ReachSet) makeCanonical( out );
- op2result.put( op, out );
- return out;
- }
-
- public static ReachSet union( ReachSet rs,
- ReachState state ) {
+ // first add everything from 1, and if it was also in 2
+ // take the OR of the predicates
+ Iterator<ReachState> stateItr = rs1.iterator();
+ while( stateItr.hasNext() ) {
+ ReachState state1 = stateItr.next();
+ ReachState state2 = rs2.containsIgnorePreds( state1 );
+
+ if( state2 != null ) {
+ out.reachStates.add( ReachState.factory( state1.reachTuples,
+ Canonical.join( state1.preds,
+ state2.preds
+ )
+ ) );
+ } else {
+ out.reachStates.add( state1 );
+ }
+ }
- assert rs != null;
- assert state != null;
- assert rs.isCanonical();
- assert state.isCanonical();
+ // then add everything in 2 that wasn't in 1
+ stateItr = rs2.iterator();
+ while( stateItr.hasNext() ) {
+ ReachState state2 = stateItr.next();
+ ReachState state1 = rs1.containsIgnorePreds( state2 );
- CanonicalOp op =
- new CanonicalOp( CanonicalOp.REACHSET_UNION_REACHSTATE,
- rs,
- state );
-
- Canonical result = op2result.get( op );
- if( result != null ) {
- return (ReachSet) result;
+ if( state1 == null ) {
+ out.reachStates.add( state2 );
+ }
}
- // otherwise, no cached result...
- ReachSet out = new ReachSet();
- out.reachStates.addAll( rs.reachStates );
- out.reachStates.add( state );
-
out = (ReachSet) makeCanonical( out );
op2result.put( op, out );
return out;
}
+
public static ReachSet intersection( ReachSet rs1,
ReachSet rs2 ) {
assert rs1 != null;
public static ReachSet add( ReachSet rs,
ReachState state ) {
- return union( rs, state );
+ return unionORpreds( rs,
+ ReachSet.factory( state )
+ );
}
public static ReachSet remove( ReachSet rs,
rtR.isOutOfContext()
);
if( rtO != null ) {
- theUnion = Canonical.union( theUnion,
- Canonical.unionArity( rtR,
+ theUnion = Canonical.add( theUnion,
+ Canonical.unionUpArity( rtR,
rtO
)
- );
+ );
} else {
- theUnion = Canonical.union( theUnion,
- rtR
- );
+ theUnion = Canonical.add( theUnion,
+ rtR
+ );
}
}
rtO.isOutOfContext()
);
if( rtR == null ) {
- theUnion = Canonical.union( theUnion,
- rtO
- );
+ theUnion = Canonical.add( theUnion,
+ rtO
+ );
}
}
Iterator<ReachState> itr = rs.iterator();
while( itr.hasNext() ) {
ReachState state = itr.next();
- out = Canonical.union( out,
- Canonical.toCallerContext( state, as )
- );
+ out = Canonical.unionORpreds( out,
+ Canonical.toCallerContext( state, as )
+ );
}
assert out.isCanonical();
if( age == AllocSite.AGE_notInThisSite ) {
// things not from the site just go back in
- baseState = Canonical.union( baseState, rt );
+ baseState = Canonical.add( baseState, rt );
} else if( age == AllocSite.AGE_summary ) {
// arity, if ARITY-ONE we'll branch the base state after the loop
if( rt.getArity() == ReachTuple.ARITY_ZEROORMORE ) {
// add two overly conservative symbols to reach state (PUNTING)
- baseState = Canonical.union( baseState,
- ReachTuple.factory( as.getSummary(),
- true, // multi
- ReachTuple.ARITY_ZEROORMORE,
- false // out-of-context
- )
- );
- baseState = Canonical.union( baseState,
- ReachTuple.factory( as.getSummary(),
- true, // multi
- ReachTuple.ARITY_ZEROORMORE,
- true // out-of-context
- )
+ baseState = Canonical.add( baseState,
+ ReachTuple.factory( as.getSummary(),
+ true, // multi
+ ReachTuple.ARITY_ZEROORMORE,
+ false // out-of-context
+ )
);
+ baseState = Canonical.add( baseState,
+ ReachTuple.factory( as.getSummary(),
+ true, // multi
+ ReachTuple.ARITY_ZEROORMORE,
+ true // out-of-context
+ )
+ );
} else {
assert rt.getArity() == ReachTuple.ARITY_ONE;
found2Sooc = true;
} else {
// the in-context just becomes shadow
- baseState = Canonical.union( baseState,
- ReachTuple.factory( as.getSummaryShadow(),
- true, // multi
- rt.getArity(),
- false // out-of-context
- )
- );
+ baseState = Canonical.add( baseState,
+ ReachTuple.factory( as.getSummaryShadow(),
+ true, // multi
+ rt.getArity(),
+ false // out-of-context
+ )
+ );
}
if( rt.isOutOfContext() ) {
// becomes the in-context version
- baseState = Canonical.union( baseState,
- ReachTuple.factory( rt.getHrnID(),
- false, // multi
- ReachTuple.ARITY_ONE,
- false // out-of-context
- )
- );
+ baseState = Canonical.add( baseState,
+ ReachTuple.factory( rt.getHrnID(),
+ false, // multi
+ ReachTuple.ARITY_ONE,
+ false // out-of-context
+ )
+ );
} else {
// otherwise the ith symbol becomes shadowed
- baseState = Canonical.union( baseState,
- ReachTuple.factory( -rt.getHrnID(),
- false, // multi
- ReachTuple.ARITY_ONE,
- false // out-of-context
- )
- );
+ baseState = Canonical.add( baseState,
+ ReachTuple.factory( -rt.getHrnID(),
+ false, // multi
+ ReachTuple.ARITY_ONE,
+ false // out-of-context
+ )
+ );
}
}
}
if( found2Sooc ) {
// make a branch with every possibility of the one-to-many
// mapping for 2S? appended to the baseState
- out = Canonical.union( out,
- Canonical.union( baseState,
- ReachTuple.factory( as.getSummary(),
- true, // multi
- ReachTuple.ARITY_ONE,
- false // out-of-context
- )
- )
- );
+ out = Canonical.add( out,
+ Canonical.add( baseState,
+ ReachTuple.factory( as.getSummary(),
+ true, // multi
+ ReachTuple.ARITY_ONE,
+ false // out-of-context
+ )
+ )
+ );
- out = Canonical.union( out,
- Canonical.union( baseState,
- ReachTuple.factory( as.getSummary(),
- true, // multi
- ReachTuple.ARITY_ONE,
- true // out-of-context
- )
- )
- );
+ out = Canonical.add( out,
+ Canonical.add( baseState,
+ ReachTuple.factory( as.getSummary(),
+ true, // multi
+ ReachTuple.ARITY_ONE,
+ true // out-of-context
+ )
+ )
+ );
for( int i = 0; i < as.getAllocationDepth(); ++i ) {
- out = Canonical.union( out,
- Canonical.union( baseState,
- ReachTuple.factory( as.getIthOldest( i ),
- false, // multi
- ReachTuple.ARITY_ONE,
- true // out-of-context
- )
- )
- );
+ out = Canonical.add( out,
+ Canonical.add( baseState,
+ ReachTuple.factory( as.getIthOldest( i ),
+ false, // multi
+ ReachTuple.ARITY_ONE,
+ true // out-of-context
+ )
+ )
+ );
}
} else {
// just use current baseState
- out = Canonical.union( out,
- baseState );
+ out = Canonical.add( out,
+ baseState );
}
if( age == AllocSite.SHADOWAGE_notInThisSite ) {
// things not from the site just go back in
- out = Canonical.union( out, rt );
+ out = Canonical.add( out, rt );
} else {
assert !rt.isOutOfContext();
// otherwise unshadow it
- out = Canonical.union( out,
- ReachTuple.factory( -rt.getHrnID(),
- rt.isMultiObject(),
- rt.getArity(),
- false
- )
- );
+ out = Canonical.add( out,
+ ReachTuple.factory( -rt.getHrnID(),
+ rt.isMultiObject(),
+ rt.getArity(),
+ false
+ )
+ );
}
}
if( edgeExisting != null ) {
edgeExisting.setBeta(
- Canonical.union( edgeExisting.getBeta(),
+ Canonical.unionORpreds( edgeExisting.getBeta(),
edgeNew.getBeta()
)
);
// otherwise an edge from the referencer to hrnSummary exists already
// and the edge referencer->hrn should be merged with it
edgeSummary.setBeta(
- Canonical.union( edgeMerged.getBeta(),
+ Canonical.unionORpreds( edgeMerged.getBeta(),
edgeSummary.getBeta()
)
);
// otherwise an edge from the referencer to alpha_S exists already
// and the edge referencer->alpha_K should be merged with it
edgeSummary.setBeta(
- Canonical.union( edgeMerged.getBeta(),
+ Canonical.unionORpreds( edgeMerged.getBeta(),
edgeSummary.getBeta()
)
);
// then merge hrn reachability into hrnSummary
hrnSummary.setAlpha(
- Canonical.union( hrnSummary.getAlpha(),
+ Canonical.unionORpreds( hrnSummary.getAlpha(),
hrn.getAlpha()
)
);
// but this propagation may be only one of many concurrent
// possible changes, so keep a running union with the node's
// partially updated new alpha set
- n.setAlphaNew( Canonical.union( n.getAlphaNew(),
+ n.setAlphaNew( Canonical.unionORpreds( n.getAlphaNew(),
localDelta
)
);
// but this propagation may be only one of many concurrent
// possible changes, so keep a running union with the edge's
// partially updated new beta set
- e.setBetaNew( Canonical.union( e.getBetaNew(),
+ e.setBetaNew( Canonical.unionORpreds( e.getBetaNew(),
localDelta
)
);
// only translate this tuple if it is in the out-context bag
if( !oocTuples.contains( rt ) ) {
- stateNew = Canonical.union( stateNew, rt );
+ stateNew = Canonical.add( stateNew, rt );
continue;
}
if( age == AllocSite.AGE_notInThisSite ) {
// things not from the site just go back in
- stateNew = Canonical.union( stateNew, rt );
+ stateNew = Canonical.add( stateNew, rt );
} else if( age == AllocSite.AGE_summary ||
rt.isOutOfContext()
) {
// the in-context summary and all existing out-of-context
// stuff all become
- stateNew = Canonical.union( stateNew,
- ReachTuple.factory( as.getSummary(),
- true, // multi
- rt.getArity(),
- true // out-of-context
- )
- );
+ stateNew = Canonical.add( stateNew,
+ ReachTuple.factory( as.getSummary(),
+ true, // multi
+ rt.getArity(),
+ true // out-of-context
+ )
+ );
} else {
// otherwise everything else just goes to an out-of-context
// version, everything else the same
assert !rt.isMultiObject();
- stateNew = Canonical.union( stateNew,
- ReachTuple.factory( rt.getHrnID(),
- rt.isMultiObject(),
- rt.getArity(),
- true // out-of-context
- )
- );
+ stateNew = Canonical.add( stateNew,
+ ReachTuple.factory( rt.getHrnID(),
+ rt.isMultiObject(),
+ rt.getArity(),
+ true // out-of-context
+ )
+ );
}
}
stateCaller = Canonical.attach( stateCaller,
calleeStatesSatisfied.get( stateCallee )
);
- out = Canonical.union( out,
+ out = Canonical.add( out,
stateCaller
);
}
} else {
// the out-of-context edge already exists
- oocEdgeExisting.setBeta( Canonical.union( oocEdgeExisting.getBeta(),
+ oocEdgeExisting.setBeta( Canonical.unionORpreds( oocEdgeExisting.getBeta(),
toCalleeContext( oocTuples,
reCaller.getBeta(), // in state
null, // node pred
);
if( edgeExisting != null ) {
edgeExisting.setBeta(
- Canonical.union( edgeExisting.getBeta(),
+ Canonical.unionORpreds( edgeExisting.getBeta(),
reCaller.getBeta()
)
);
);
if( prevResult == null ||
- Canonical.union( prevResult,
+ Canonical.unionORpreds( prevResult,
intersection ).size() > prevResult.size() ) {
if( prevResult == null ) {
boldB_f.put( edgePrime,
- Canonical.union( edgePrime.getBeta(),
+ Canonical.unionORpreds( edgePrime.getBeta(),
intersection
)
);
} else {
boldB_f.put( edgePrime,
- Canonical.union( prevResult,
+ Canonical.unionORpreds( prevResult,
intersection
)
);
// if there is nothing marked, just move on
if( markedHrnIDs.isEmpty() ) {
- hrn.setAlphaNew( Canonical.union( hrn.getAlphaNew(),
+ hrn.setAlphaNew( Canonical.add( hrn.getAlphaNew(),
stateOld
)
);
ReachTuple rtOld = rtItr.next();
if( !markedHrnIDs.containsTuple( rtOld ) ) {
- statePruned = Canonical.union( statePruned, rtOld );
+ statePruned = Canonical.add( statePruned, rtOld );
}
}
assert !stateOld.equals( statePruned );
- hrn.setAlphaNew( Canonical.union( hrn.getAlphaNew(),
+ hrn.setAlphaNew( Canonical.add( hrn.getAlphaNew(),
statePruned
)
);
edgePrime.getBetaNew()
);
- if( Canonical.union( prevResult,
- intersection
- ).size() > prevResult.size() ) {
+ if( Canonical.unionORpreds( prevResult,
+ intersection
+ ).size() > prevResult.size() ) {
edge.setBetaNew(
- Canonical.union( prevResult,
- intersection
- )
+ Canonical.unionORpreds( prevResult,
+ intersection
+ )
);
edgeWorkSet.add( edge );
}
// so make the new reachability set a union of the
// nodes' reachability sets
HeapRegionNode hrnB = id2hrn.get( idA );
- hrnB.setAlpha( Canonical.union( hrnB.getAlpha(),
+ hrnB.setAlpha( Canonical.unionORpreds( hrnB.getAlpha(),
hrnA.getAlpha()
)
);
// just replace this beta set with the union
assert edgeToMerge != null;
edgeToMerge.setBeta(
- Canonical.union( edgeToMerge.getBeta(),
+ Canonical.unionORpreds( edgeToMerge.getBeta(),
edgeA.getBeta()
)
);
// so merge their reachability sets
else {
// just replace this beta set with the union
- edgeToMerge.setBeta( Canonical.union( edgeToMerge.getBeta(),
+ edgeToMerge.setBeta( Canonical.unionORpreds( edgeToMerge.getBeta(),
edgeA.getBeta()
)
);
Iterator<RefEdge> itrEdge = hrn1.iteratorToReferencees();
while (itrEdge.hasNext()) {
RefEdge edge = itrEdge.next();
- beta1 = Canonical.union(beta1, edge.getBeta());
+ beta1 = Canonical.unionORpreds(beta1, edge.getBeta());
}
ReachSet beta2 = ReachSet.factory();
itrEdge = hrn2.iteratorToReferencees();
while (itrEdge.hasNext()) {
RefEdge edge = itrEdge.next();
- beta2 = Canonical.union(beta2, edge.getBeta());
+ beta2 = Canonical.unionORpreds(beta2, edge.getBeta());
}
boolean aliasDetected = false;