1 package Analysis.Disjoint;
10 public class DefiniteReachState {
14 // Maps two variables to an edge (x, y, e) to an unused value when the
15 // object of x is already reachable from the object of y, and the
16 // set of edges conservatively gives the path.
17 // NOTE: Use EdgeKey instead of edges because this analysis's
18 // scope is beyond the scope of a single reach graph.
19 private static MultiViewMapBuilder<Object> RBuilder;
20 private static BitSet viewR0;
21 private static BitSet viewR1;
22 private static BitSet viewR01;
23 private MultiViewMap<Object> R;
27 // Tracks whether the analysis must know the definite reachability
28 // information of a given variable.
29 //private enum DefReachKnown {
33 //private Map<TempDescriptor, DefReachKnown> Rs;
38 // Maps a variable that points to object o0 to the
39 // set of variables that point to objects o1...oN
40 // that have a reference to o0.
41 //private static MultiViewMapBuilder<Object> FuBuilder;
42 //private static BitSet viewFu0;
43 //private static BitSet viewFu1;
44 //private MultiViewMap<Object> Fu;
54 // call before instantiating this class
55 static public void initBuilders() {
57 new MultiViewMapBuilder<Object>( new Class[] {
62 viewR0 = RBuilder.addPartialView( 0 );
63 viewR1 = RBuilder.addPartialView( 1 );
64 viewR01 = RBuilder.addPartialView( 0, 1 );
65 RBuilder.setCheckTypes( true );
66 RBuilder.setCheckConsistency( true );
69 // new MultiViewMapBuilder<Object>( new Class[] {
70 // TempDescriptor.class,
71 // DefReachFuVal.class},
73 //viewFu0 = FuBuilder.addPartialView( 0 );
74 //viewFu1 = FuBuilder.addPartialView( 1 );
75 //FuBuilder.setCheckTypes( true );
76 //FuBuilder.setCheckConsistency( true );
83 public DefiniteReachState() {
85 //Rs = new HashMap<TempDescriptor, DefReachKnown>();
86 //Fu = FuBuilder.build();
90 public void methodEntry( Set<TempDescriptor> parameters ) {
91 methodEntryR( parameters );
94 //for( TempDescriptor p : parameters ) {
95 // Rs.put( p, DefReachKnown.UNKNOWN );
98 //Fu = FuBuilder.build();
101 public void copy( TempDescriptor x,
105 // Rs' := (Rs - <x,*>) U {<x,v> | <y,v> in Rs}
106 //DefReachKnown valRs = Rs.get( y );
107 //assert( valRs != null );
108 //Rs.put( x, valRs );
110 // Fu' := (Fu - <x, *> - <*, x>) U
111 // {<x,v> | <y,v> in Fu} U
112 // {<v,x> | <v,y> in Fu} U
113 // {<z, unknown> | <z,<x>> in Fu}
114 //Fu.remove( viewFu0, MultiKey.factory( x ) );
115 //Fu.remove( viewFu1, MultiKey.factory( x ) );
116 //for( MultiKey key : Fu.get( viewFu0, MultiKey.factory( y ) ).keySet() ) {
117 // DefReachFuVal val = (DefReachFuVal) key.get( 1 );
118 // Fu.put( MultiKey.factory( x, val ), dummy );
120 //for( MultiKey key : Fu.get( viewFu1, MultiKey.factory( y ) ).keySet() ) {
121 // TempDescriptor v = (TempDescriptor) key.get( 0 );
122 // Fu.put( MultiKey.factory( v, DefReachFuVal.factory( x ) ), dummy );
124 //for( MultiKey key :
126 // MultiKey.factory( DefReachFuVal.factory( DefReachFuVal.Val.UNKNOWN ) )
129 // TempDescriptor z = (TempDescriptor) key.get( 0 );
130 // Fu.put( MultiKey.factory( z, DefReachFuVal.factory( x ) ), dummy );
134 public void load( TempDescriptor x,
137 Set<EdgeKey> edgeKeysForLoad ) {
139 loadR( x, y, f, edgeKeysForLoad );
140 // Rs' := (Rs - <x,*>) U {<x, unknown>}
141 //Rs.put( x, DefReachKnown.UNKNOWN );
144 public void store( TempDescriptor x,
147 Set<EdgeKey> edgeKeysRemoved,
148 Set<EdgeKey> edgeKeysAdded ) {
150 storeR( x, f, y, edgeKeysRemoved, edgeKeysAdded );
154 public void newObject( TempDescriptor x ) {
157 // Rs' := (Rs - <x,*>) U {<x, new>}
158 //Rs.put( x, DefReachKnown.KNOWN );
162 public void methodCall( TempDescriptor retVal ) {
163 methodCallR( retVal );
165 // Rs' := (Rs - <x,*>) U {<x, unknown>}
166 //Rs.put( x, DefReachKnown.UNKNOWN );
169 public void merge( DefiniteReachState that ) {
172 // Rs' := <x, new> iff in all incoming edges, otherwie <x, unknown>
181 public void methodEntryR( Set<TempDescriptor> parameters ) {
185 public void copyR( TempDescriptor x,
187 // consider that x and y can be the same, so do the
188 // parts of the update in the right order:
190 // first get all info for update
191 MultiKey keyY = MultiKey.factory( y );
192 Map<MultiKey, Object> mapY0 = R.get( viewR0, keyY );
193 Map<MultiKey, Object> mapY1 = R.get( viewR1, keyY );
195 // then remove anything
196 MultiKey keyX = MultiKey.factory( x );
197 R.remove( viewR0, keyX );
198 R.remove( viewR1, keyX );
200 // then insert new stuff
201 for( MultiKey fullKeyY : mapY0.keySet() ) {
202 MultiKey fullKeyX = MultiKey.factory( x,
205 R.put( fullKeyX, MultiViewMap.dummyValue );
207 for( MultiKey fullKeyY : mapY1.keySet() ) {
208 MultiKey fullKeyX = MultiKey.factory( fullKeyY.get( 0 ),
211 R.put( fullKeyX, MultiViewMap.dummyValue );
215 public void loadR( TempDescriptor x,
218 Set<EdgeKey> edgeKeysForLoad ) {
219 // consider that x and y can be the same, so do the
220 // parts of the update in the right order:
222 // first get all info for update
223 MultiKey keyY = MultiKey.factory( y );
224 Map<MultiKey, Object> mapY0 = R.get( viewR0, keyY );
226 // then remove anything
227 MultiKey keyX = MultiKey.factory( x );
228 R.remove( viewR0, keyX );
229 R.remove( viewR1, keyX );
231 // then insert new stuff
232 for( EdgeKey e : edgeKeysForLoad ) {
233 R.put( MultiKey.factory( x, y, e ), MultiViewMap.dummyValue );
235 for( MultiKey fullKeyY : mapY0.keySet() ) {
236 R.put( MultiKey.factory( x,
239 MultiViewMap.dummyValue );
241 R.put( MultiKey.factory( x,
244 MultiViewMap.dummyValue );
249 public void storeR( TempDescriptor x,
252 Set<EdgeKey> edgeKeysRemoved,
253 Set<EdgeKey> edgeKeysAdded ) {
254 // I think this should be if there is ANY <w,z>->e' IN Eremove, then kill all <w,z>
255 // R' := (R - {<w,z>->e | <w,z>->e in R, A<w,z>->e' in R, e' notin Eremove}) U
256 // {<y,x>->e | e in E(x) x {f} x E(y)}
258 // R'.remove(?); some e's...
259 // R'.put(<y,x>, E(x) x {f} x E(y));
262 public void newObjectR( TempDescriptor x ) {
263 // R' := (R - <x,*> - <*,x>)
265 // R'.remove(view0, x);
266 // R'.remove(view1, x);
269 public void methodCallR( TempDescriptor retVal ) {
270 // R' := (R - <x,*> - <*,x>)
272 // R'.remove(view0, x);
273 // R'.remove(view1, x);
276 public void mergeR( DefiniteReachState that ) {
277 // R' := <x,y>->e iff its in all incoming edges
283 ///////////////////////////////////////////////////////////
287 // It definitely tests the current R as well as Rs
289 // but also be careful what null means, is it actually
290 // equivalent to UNKOWN? I'd rather put nothing, meaning
291 // we have to do an analysis pass over all the incoming edges
292 // before there is a sensical answer. I think...
293 private void mergeRs( DefiniteReachState that ) {
294 // merge "that" into "this" and leave "that" unchanged
295 //Set<TempDescriptor> allVars = new HashSet<TempDescriptor>();
296 //allVars.addAll( this.Rs.keySet() );
297 //allVars.addAll( that.Rs.keySet() );
298 //for( TempDescriptor x : allVars ) {
299 // DefReachKnown vThis = this.Rs.get( x );
300 // DefReachKnown vThat = that.Rs.get( x );
301 // if( vThis != null && vThis.equals( DefReachKnown.KNOWN ) &&
302 // vThat != null && vThat.equals( DefReachKnown.KNOWN ) ) {
303 // this.Rs.put( x, DefReachKnown.KNOWN );
305 // this.Rs.put( x, DefReachKnown.UNKNOWN );
312 public boolean equals( Object o ) {
319 if( !(o instanceof DefiniteReachState) ) {
322 DefiniteReachState that = (DefiniteReachState) o;
329 public int hashCode() {
336 public String toString() {
337 StringBuilder s = new StringBuilder( "R_s = {" );
338 //for( TempDescriptor x : Rs.keySet() ) {
339 // s.append( " "+x+"->"+Rs.get( x ) );