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;
52 // for MultiViewMaps that don't need to use the value,
53 // always map to this dummy
54 private static Object dummy = new Integer( -12345 );
57 // call before instantiating this class
58 static public void initBuilders() {
60 new MultiViewMapBuilder<Object>( new Class[] {
65 viewR0 = RBuilder.addPartialView( 0 );
66 viewR1 = RBuilder.addPartialView( 1 );
67 viewR01 = RBuilder.addPartialView( 0, 1 );
68 RBuilder.setCheckTypes( true );
69 RBuilder.setCheckConsistency( true );
72 // new MultiViewMapBuilder<Object>( new Class[] {
73 // TempDescriptor.class,
74 // DefReachFuVal.class},
76 //viewFu0 = FuBuilder.addPartialView( 0 );
77 //viewFu1 = FuBuilder.addPartialView( 1 );
78 //FuBuilder.setCheckTypes( true );
79 //FuBuilder.setCheckConsistency( true );
86 public DefiniteReachState() {
87 //Rs = new HashMap<TempDescriptor, DefReachKnown>();
88 //Fu = FuBuilder.build();
93 public void methodEntry(Set<TempDescriptor> parameters) {
98 //for( TempDescriptor p : parameters ) {
99 // Rs.put( p, DefReachKnown.UNKNOWN );
102 //Fu = FuBuilder.build();
105 public void copy(TempDescriptor x,
107 // R' := (R - <x,*> - <*,x>) U
108 // {<x,z>->e | <y,z>->e in R} U
109 // {<z,x>->e | <z,y>->e in R}
111 // R'.remove(view0, x);
112 // R'.remove(view1, x);
113 // setYs = R.get(view0, y);
114 // for each <y,z>->e: R'.put(<x,z>, e);
115 // setYs = R.get(view1, y);
116 // for each <z,y>->e: R'.put(<z,x>, e);
118 // Rs' := (Rs - <x,*>) U {<x,v> | <y,v> in Rs}
119 //DefReachKnown valRs = Rs.get( y );
120 //assert( valRs != null );
121 //Rs.put( x, valRs );
123 // Fu' := (Fu - <x, *> - <*, x>) U
124 // {<x,v> | <y,v> in Fu} U
125 // {<v,x> | <v,y> in Fu} U
126 // {<z, unknown> | <z,<x>> in Fu}
127 //Fu.remove( viewFu0, MultiKey.factory( x ) );
128 //Fu.remove( viewFu1, MultiKey.factory( x ) );
129 //for( MultiKey key : Fu.get( viewFu0, MultiKey.factory( y ) ).keySet() ) {
130 // DefReachFuVal val = (DefReachFuVal) key.get( 1 );
131 // Fu.put( MultiKey.factory( x, val ), dummy );
133 //for( MultiKey key : Fu.get( viewFu1, MultiKey.factory( y ) ).keySet() ) {
134 // TempDescriptor v = (TempDescriptor) key.get( 0 );
135 // Fu.put( MultiKey.factory( v, DefReachFuVal.factory( x ) ), dummy );
137 //for( MultiKey key :
139 // MultiKey.factory( DefReachFuVal.factory( DefReachFuVal.Val.UNKNOWN ) )
142 // TempDescriptor z = (TempDescriptor) key.get( 0 );
143 // Fu.put( MultiKey.factory( z, DefReachFuVal.factory( x ) ), dummy );
147 public void load(TempDescriptor x,
150 // R' := (R - <x,*> - <*,x>) U
151 // ({<x,y>} x Eo(y,f)) U
152 // U {<x,z>} x (Eo(y,f)U{e})
155 // R'.remove(view0, x);
156 // R'.remove(view1, x);
157 // R'.put(<x,y>, eee!);
158 // setYs = R.get(view0, y);
159 // for each <y,z>->e: R'.put(<x,z>, eee!Ue);
161 // Rs' := (Rs - <x,*>) U {<x, unknown>}
162 //Rs.put( x, DefReachKnown.UNKNOWN );
165 public void store(TempDescriptor x,
168 Set<EdgeKey> edgeKeysRemoved) {
169 // I think this should be if there is ANY <w,z>->e' IN Eremove, then kill all <w,z>
170 // R' := (R - {<w,z>->e | <w,z>->e in R, A<w,z>->e' in R, e' notin Eremove}) U
171 // {<y,x>->e | e in E(x) x {f} x E(y)}
173 // R'.remove(?); some e's...
174 // R'.put(<y,x>, E(x) x {f} x E(y));
179 public void newObject(TempDescriptor x) {
180 // R' := (R - <x,*> - <*,x>)
182 // R'.remove(view0, x);
183 // R'.remove(view1, x);
185 // Rs' := (Rs - <x,*>) U {<x, new>}
186 //Rs.put( x, DefReachKnown.KNOWN );
190 // x is the return value, x = foo(...);
191 public void methodCall(TempDescriptor x) {
192 // R' := (R - <x,*> - <*,x>)
194 // R'.remove(view0, x);
195 // R'.remove(view1, x);
197 // Rs' := (Rs - <x,*>) U {<x, unknown>}
198 //Rs.put( x, DefReachKnown.UNKNOWN );
201 public void merge( DefiniteReachState that ) {
202 // R' := <x,y>->e iff its in all incoming edges
204 // Rs' := <x, new> iff in all incoming edges, otherwie <x, unknown>
209 ///////////////////////////////////////////////////////////
213 // It definitely tests the current R as well as Rs
215 // but also be careful what null means, is it actually
216 // equivalent to UNKOWN? I'd rather put nothing, meaning
217 // we have to do an analysis pass over all the incoming edges
218 // before there is a sensical answer. I think...
219 private void mergeRs( DefiniteReachState that ) {
220 // merge "that" into "this" and leave "that" unchanged
221 //Set<TempDescriptor> allVars = new HashSet<TempDescriptor>();
222 //allVars.addAll( this.Rs.keySet() );
223 //allVars.addAll( that.Rs.keySet() );
224 //for( TempDescriptor x : allVars ) {
225 // DefReachKnown vThis = this.Rs.get( x );
226 // DefReachKnown vThat = that.Rs.get( x );
227 // if( vThis != null && vThis.equals( DefReachKnown.KNOWN ) &&
228 // vThat != null && vThat.equals( DefReachKnown.KNOWN ) ) {
229 // this.Rs.put( x, DefReachKnown.KNOWN );
231 // this.Rs.put( x, DefReachKnown.UNKNOWN );
238 public boolean equals( Object o ) {
245 if( !(o instanceof DefiniteReachState) ) {
248 DefiniteReachState that = (DefiniteReachState) o;
255 public int hashCode() {
262 public String toString() {
263 StringBuilder s = new StringBuilder( "R_s = {" );
264 //for( TempDescriptor x : Rs.keySet() ) {
265 // s.append( " "+x+"->"+Rs.get( x ) );