1 package Analysis.Disjoint;
8 ///////////////////////////////////////////
10 // This class is an immutable Canonical, so
12 // 0) construct them with a factory pattern
13 // to ensure only canonical versions escape
15 // 1) any operation that modifies a Canonical
16 // is a static method in the Canonical class
18 // 2) operations that just read this object
19 // should be defined here
21 // 3) every Canonical subclass hashCode should
22 // throw an error if the hash ever changes
24 ///////////////////////////////////////////
26 // Existence predicates in the callee final-result
27 // graph are relevant on the caller's callee-reachable
28 // graph parts. Any callee result elements with
29 // predicates not satisfied in the caller are not
30 // mapped in the call site transfer function
32 public class ExistPred extends Canonical {
34 // there are several types of predicates, note that
35 // there are not subclasses of the ExistPred class
36 // because they must be Canonical, no multiple inheritence
38 // types: true, node, edge
39 public static final int TYPE_TRUE = 0xa501;
40 public static final int TYPE_NODE = 0x02fd;
41 public static final int TYPE_EDGE = 0x414b;
42 protected int predType;
44 // true predicates always evaluate to true
46 // A node existence predicate is satisfied if the heap
47 // region ID defining a node is part of the given graph
48 // The reach state may be null--if not the predicate is
49 // satisfied when the edge exists AND it has the state.
50 protected Integer n_hrnID;
51 protected ReachState ne_state;
53 // An edge existence predicate is satisfied if the elements
54 // defining an edge are part of the given graph.
55 // The reach state may be null--if not the predicate is
56 // satisfied when the edge exists AND it has the state.
57 // the source of an edge is *either* a variable
58 // node or a heap region node
59 protected TempDescriptor e_tdSrc;
60 protected Integer e_hrnSrcID;
62 // the source of an edge might be out of the callee
63 // context but in the caller graph, a normal caller
64 // heap region or variable, OR it might be out of the
65 // caller context ALSO: an ooc node in the caller
66 protected boolean e_srcOutCalleeContext;
67 protected boolean e_srcOutCallerContext;
69 // dst is always a heap region
70 protected Integer e_hrnDstID;
72 // a reference has a field name and type
73 protected TypeDescriptor e_type;
74 protected String e_field;
76 // edge uses same ReachState ne_state as node type above
79 // a static debug flag for higher abstraction code
80 // to enable debug info at this level
81 public static boolean debug = false;
84 // to make the true predicate
85 public static ExistPred factory() {
86 ExistPred out = new ExistPred();
87 out = (ExistPred) Canonical.makeCanonical( out );
91 protected ExistPred() {
92 this.predType = TYPE_TRUE;
100 e_srcOutCalleeContext = false;
101 e_srcOutCallerContext = false;
105 public static ExistPred factory( Integer hrnID,
108 ExistPred out = new ExistPred( hrnID, state );
110 out = (ExistPred) Canonical.makeCanonical( out );
114 protected ExistPred( Integer hrnID,
116 assert hrnID != null;
117 this.n_hrnID = hrnID;
118 this.ne_state = state;
119 this.predType = TYPE_NODE;
125 e_srcOutCalleeContext = false;
126 e_srcOutCallerContext = false;
130 public static ExistPred factory( TempDescriptor tdSrc,
136 boolean srcOutCalleeContext,
137 boolean srcOutCallerContext ) {
139 ExistPred out = new ExistPred( tdSrc,
146 srcOutCallerContext );
148 out = (ExistPred) Canonical.makeCanonical( out );
152 protected ExistPred( TempDescriptor tdSrc,
158 boolean srcOutCalleeContext,
159 boolean srcOutCallerContext ) {
161 assert (tdSrc == null) || (hrnSrcID == null);
162 assert hrnDstID != null;
165 // fields can be null when the edge is from
166 // a variable node to a heap region!
167 // assert field != null;
169 this.e_srcOutCalleeContext = srcOutCalleeContext;
170 this.e_srcOutCallerContext = srcOutCallerContext;
172 assert !(e_srcOutCalleeContext && e_srcOutCallerContext);
174 this.e_tdSrc = tdSrc;
175 this.e_hrnSrcID = hrnSrcID;
176 this.e_hrnDstID = hrnDstID;
178 this.e_field = field;
179 this.ne_state = state;
180 this.predType = TYPE_EDGE;
185 // only consider the subest of the caller elements that
186 // are reachable by callee when testing predicates--if THIS
187 // predicate is satisfied, return the predicate set of the
188 // element that satisfied it, or null for false
189 public ExistPredSet isSatisfiedBy( ReachGraph rg,
190 Set<Integer> calleeReachableNodes
192 if( predType == TYPE_TRUE ) {
193 return ExistPredSet.factory( ExistPred.factory() );
196 if( predType == TYPE_NODE ) {
199 HeapRegionNode hrn = rg.id2hrn.get( n_hrnID );
204 if( !calleeReachableNodes.contains( n_hrnID ) ) {
208 // when the state is null it is not part of the
209 // predicate, so we've already satisfied
210 if( ne_state == null ) {
211 return hrn.getPreds();
214 // otherwise look for state too
215 // TODO: contains OR containsSuperSet OR containsWithZeroes??
216 if( hrn.getAlpha().containsIgnorePreds( ne_state )
218 return hrn.getPreds();
224 if( predType == TYPE_EDGE ) {
226 // first establish whether the source of the
227 // reference edge exists
228 VariableNode vnSrc = null;
229 if( e_tdSrc != null ) {
230 vnSrc = rg.td2vn.get( e_tdSrc );
232 HeapRegionNode hrnSrc = null;
233 if( e_hrnSrcID != null ) {
234 hrnSrc = rg.id2hrn.get( e_hrnSrcID );
236 assert (vnSrc == null) || (hrnSrc == null);
238 // the source is not present in graph
239 if( vnSrc == null && hrnSrc == null ) {
244 if( vnSrc != null ) {
246 assert e_srcOutCalleeContext;
247 assert !e_srcOutCallerContext;
251 assert !(e_srcOutCalleeContext && e_srcOutCallerContext);
253 if( e_srcOutCalleeContext ) {
254 if( calleeReachableNodes.contains( e_hrnSrcID ) ) {
258 } else if( e_srcOutCallerContext ) {
259 if( !hrnSrc.isOutOfContext() ) {
265 if( !calleeReachableNodes.contains( e_hrnSrcID ) ) {
268 if( hrnSrc.isOutOfContext() ) {
277 // is the destination present?
278 HeapRegionNode hrnDst = rg.id2hrn.get( e_hrnDstID );
279 if( hrnDst == null ) {
283 if( !calleeReachableNodes.contains( e_hrnDstID ) ) {
287 // is there an edge between them with the given
289 // TODO: type OR a subtype?
290 RefEdge edge = rsn.getReferenceTo( hrnDst,
297 // when state is null it is not part of the predicate
298 // so we've satisfied the edge existence
299 if( ne_state == null ) {
300 return edge.getPreds();
303 // otherwise look for state too
304 // TODO: contains OR containsSuperSet OR containsWithZeroes??
305 if( hrnDst.getAlpha().containsIgnorePreds( ne_state )
307 return edge.getPreds();
313 throw new Error( "Unknown predicate type" );
318 public boolean equalsSpecific( Object o ) {
323 if( !(o instanceof ExistPred) ) {
327 ExistPred pred = (ExistPred) o;
329 if( this.predType != pred.predType ) {
333 if( ne_state == null ) {
334 if( pred.ne_state != null ) {
337 } else if( !ne_state.equals( pred.ne_state ) ) {
341 if( n_hrnID == null ) {
342 if( pred.n_hrnID != null ) {
345 } else if( !n_hrnID.equals( pred.n_hrnID ) ) {
349 if( e_tdSrc == null ) {
350 if( pred.e_tdSrc != null ) {
353 } else if( !e_tdSrc.equals( pred.e_tdSrc ) ) {
357 if( e_hrnSrcID == null ) {
358 if( pred.e_hrnSrcID != null ) {
362 if( !e_hrnSrcID.equals( pred.e_hrnSrcID ) ) {
365 if( e_srcOutCalleeContext != pred.e_srcOutCalleeContext ) {
368 if( e_srcOutCallerContext != pred.e_srcOutCallerContext ) {
373 if( e_hrnDstID == null ) {
374 if( pred.e_hrnDstID != null ) {
377 } else if( !e_hrnDstID.equals( pred.e_hrnDstID ) ) {
381 if( e_type == null ) {
382 if( pred.e_type != null ) {
385 } else if( !e_type.equals( pred.e_type ) ) {
389 if( e_field == null ) {
390 if( pred.e_field != null ) {
393 } else if( !e_field.equals( pred.e_field ) ) {
401 public int hashCodeSpecific() {
402 if( predType == TYPE_TRUE ) {
406 if( predType == TYPE_NODE ) {
407 int hash = n_hrnID.intValue()*17;
409 if( ne_state != null ) {
410 hash ^= ne_state.hashCode();
416 if( predType == TYPE_EDGE ) {
419 hash += e_type.hashCode()*17;
421 if( e_field != null ) {
422 hash += e_field.hashCode()*7;
425 if( e_tdSrc != null ) {
426 hash ^= e_tdSrc.hashCode()*11;
428 hash ^= e_hrnSrcID.hashCode()*11;
429 if( e_srcOutCalleeContext ) {
432 if( e_srcOutCallerContext ) {
437 hash += e_hrnDstID.hashCode();
439 if( ne_state != null ) {
440 hash ^= ne_state.hashCode();
446 throw new Error( "Unknown predicate type" );
450 public String toString() {
451 if( predType == TYPE_TRUE ) {
455 if( predType == TYPE_NODE ) {
456 String s = n_hrnID.toString();
457 if( ne_state != null ) {
463 if( predType == TYPE_EDGE ) {
466 if( e_tdSrc != null ) {
467 s += e_tdSrc.toString();
469 s += e_hrnSrcID.toString();
472 if( e_srcOutCalleeContext ) {
476 if( e_srcOutCallerContext ) {
480 s += "-->"+e_hrnDstID+")";
482 if( ne_state != null ) {
489 throw new Error( "Unknown predicate type" );