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
80 // a static debug flag for higher abstraction code
81 // to enable debug info at this level
82 public static boolean debug = false;
85 // to make the true predicate
86 public static ExistPred factory() {
87 ExistPred out = new ExistPred();
88 out = (ExistPred) Canonical.makeCanonical( out );
92 protected ExistPred() {
93 this.predType = TYPE_TRUE;
101 e_srcOutCalleeContext = false;
102 e_srcOutCallerContext = false;
106 public static ExistPred factory( Integer hrnID,
109 ExistPred out = new ExistPred( hrnID, state );
111 out = (ExistPred) Canonical.makeCanonical( out );
115 protected ExistPred( Integer hrnID,
117 assert hrnID != null;
118 this.n_hrnID = hrnID;
119 this.ne_state = state;
120 this.predType = TYPE_NODE;
126 e_srcOutCalleeContext = false;
127 e_srcOutCallerContext = false;
131 public static ExistPred factory( TempDescriptor tdSrc,
137 boolean srcOutCalleeContext,
138 boolean srcOutCallerContext ) {
140 ExistPred out = new ExistPred( tdSrc,
147 srcOutCallerContext );
149 out = (ExistPred) Canonical.makeCanonical( out );
153 protected ExistPred( TempDescriptor tdSrc,
159 boolean srcOutCalleeContext,
160 boolean srcOutCallerContext ) {
162 assert (tdSrc == null) || (hrnSrcID == null);
163 assert hrnDstID != null;
166 // fields can be null when the edge is from
167 // a variable node to a heap region!
168 // assert field != null;
170 this.e_srcOutCalleeContext = srcOutCalleeContext;
171 this.e_srcOutCallerContext = srcOutCallerContext;
173 assert !(e_srcOutCalleeContext && e_srcOutCallerContext);
175 this.e_tdSrc = tdSrc;
176 this.e_hrnSrcID = hrnSrcID;
177 this.e_hrnDstID = hrnDstID;
179 this.e_field = field;
180 this.ne_state = state;
181 this.predType = TYPE_EDGE;
186 // only consider the subest of the caller elements that
187 // are reachable by callee when testing predicates--if THIS
188 // predicate is satisfied, return the predicate set of the
189 // element that satisfied it, or null for false
190 public ExistPredSet isSatisfiedBy( ReachGraph rg,
191 Set<Integer> calleeReachableNodes
193 if( predType == TYPE_TRUE ) {
194 return ExistPredSet.factory( ExistPred.factory() );
197 if( predType == TYPE_NODE ) {
200 HeapRegionNode hrn = rg.id2hrn.get( n_hrnID );
205 if( !calleeReachableNodes.contains( n_hrnID ) ) {
209 // when the state is null it is not part of the
210 // predicate, so we've already satisfied
211 if( ne_state == null ) {
212 return hrn.getPreds();
215 // otherwise look for state too
216 // TODO: contains OR containsSuperSet OR containsWithZeroes??
217 if( hrn.getAlpha().containsIgnorePreds( ne_state )
219 return hrn.getPreds();
225 if( predType == TYPE_EDGE ) {
227 // first establish whether the source of the
228 // reference edge exists
229 VariableNode vnSrc = null;
230 if( e_tdSrc != null ) {
231 vnSrc = rg.td2vn.get( e_tdSrc );
233 HeapRegionNode hrnSrc = null;
234 if( e_hrnSrcID != null ) {
235 hrnSrc = rg.id2hrn.get( e_hrnSrcID );
237 assert (vnSrc == null) || (hrnSrc == null);
239 // the source is not present in graph
240 if( vnSrc == null && hrnSrc == null ) {
245 if( vnSrc != null ) {
247 assert e_srcOutCalleeContext;
248 assert !e_srcOutCallerContext;
252 assert !(e_srcOutCalleeContext && e_srcOutCallerContext);
254 if( e_srcOutCalleeContext ) {
255 if( calleeReachableNodes.contains( e_hrnSrcID ) ) {
259 } else if( e_srcOutCallerContext ) {
260 if( !hrnSrc.isOutOfContext() ) {
266 if( !calleeReachableNodes.contains( e_hrnSrcID ) ) {
269 if( hrnSrc.isOutOfContext() ) {
278 // is the destination present?
279 HeapRegionNode hrnDst = rg.id2hrn.get( e_hrnDstID );
280 if( hrnDst == null ) {
284 if( !calleeReachableNodes.contains( e_hrnDstID ) ) {
288 // is there an edge between them with the given
290 // TODO: type OR a subtype?
291 RefEdge edge = rsn.getReferenceTo( hrnDst,
298 // only check state as part of the predicate if it
300 if( ne_state != null &&
301 // TODO: contains OR containsSuperSet OR containsWithZeroes??
302 hrnDst.getAlpha().containsIgnorePreds( ne_state ) != null
307 // predicate satisfied
308 return edge.getPreds();
311 throw new Error( "Unknown predicate type" );
316 public boolean equalsSpecific( Object o ) {
321 if( !(o instanceof ExistPred) ) {
325 ExistPred pred = (ExistPred) o;
327 if( this.predType != pred.predType ) {
331 if( ne_state == null ) {
332 if( pred.ne_state != null ) {
335 } else if( !ne_state.equals( pred.ne_state ) ) {
339 if( n_hrnID == null ) {
340 if( pred.n_hrnID != null ) {
343 } else if( !n_hrnID.equals( pred.n_hrnID ) ) {
347 if( e_tdSrc == null ) {
348 if( pred.e_tdSrc != null ) {
351 } else if( !e_tdSrc.equals( pred.e_tdSrc ) ) {
355 if( e_hrnSrcID == null ) {
356 if( pred.e_hrnSrcID != null ) {
360 if( !e_hrnSrcID.equals( pred.e_hrnSrcID ) ) {
363 if( e_srcOutCalleeContext != pred.e_srcOutCalleeContext ) {
366 if( e_srcOutCallerContext != pred.e_srcOutCallerContext ) {
371 if( e_hrnDstID == null ) {
372 if( pred.e_hrnDstID != null ) {
375 } else if( !e_hrnDstID.equals( pred.e_hrnDstID ) ) {
379 if( e_type == null ) {
380 if( pred.e_type != null ) {
383 } else if( !e_type.equals( pred.e_type ) ) {
387 if( e_field == null ) {
388 if( pred.e_field != null ) {
391 } else if( !e_field.equals( pred.e_field ) ) {
399 public int hashCodeSpecific() {
400 if( predType == TYPE_TRUE ) {
404 if( predType == TYPE_NODE ) {
405 int hash = n_hrnID.intValue()*17;
407 if( ne_state != null ) {
408 hash ^= ne_state.hashCode();
414 if( predType == TYPE_EDGE ) {
417 hash += e_type.hashCode()*17;
419 if( e_field != null ) {
420 hash += e_field.hashCode()*7;
423 if( e_tdSrc != null ) {
424 hash ^= e_tdSrc.hashCode()*11;
426 hash ^= e_hrnSrcID.hashCode()*11;
427 if( e_srcOutCalleeContext ) {
430 if( e_srcOutCallerContext ) {
435 hash += e_hrnDstID.hashCode();
437 if( ne_state != null ) {
438 hash ^= ne_state.hashCode();
444 throw new Error( "Unknown predicate type" );
448 public String toString() {
449 if( predType == TYPE_TRUE ) {
453 if( predType == TYPE_NODE ) {
454 String s = n_hrnID.toString();
455 if( ne_state != null ) {
461 if( predType == TYPE_EDGE ) {
464 if( e_tdSrc != null ) {
465 s += e_tdSrc.toString();
467 s += e_hrnSrcID.toString();
470 if( e_srcOutCalleeContext ) {
474 if( e_srcOutCallerContext ) {
478 s += "-->"+e_hrnDstID+")";
480 if( ne_state != null ) {
487 throw new Error( "Unknown predicate type" );