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 boolean e_srcOutContext;
61 protected TempDescriptor e_tdSrc;
62 protected Integer e_hrnSrcID;
64 // dst is always a heap region
65 protected Integer e_hrnDstID;
67 // a reference has a field name and type
68 protected TypeDescriptor e_type;
69 protected String e_field;
71 // edge uses same ReachState ne_state as node type above
74 // to make the true predicate
75 public static ExistPred factory() {
76 ExistPred out = new ExistPred();
77 out = (ExistPred) Canonical.makeCanonical( out );
81 protected ExistPred() {
82 this.predType = TYPE_TRUE;
90 e_srcOutContext = false;
94 public static ExistPred factory( Integer hrnID,
97 ExistPred out = new ExistPred( hrnID, state );
99 out = (ExistPred) Canonical.makeCanonical( out );
103 protected ExistPred( Integer hrnID,
105 assert hrnID != null;
106 this.n_hrnID = hrnID;
107 this.ne_state = state;
108 this.predType = TYPE_NODE;
114 e_srcOutContext = false;
118 public static ExistPred factory( TempDescriptor tdSrc,
124 boolean srcOutContext ) {
126 ExistPred out = new ExistPred( tdSrc,
134 out = (ExistPred) Canonical.makeCanonical( out );
138 protected ExistPred( TempDescriptor tdSrc,
144 boolean srcOutContext ) {
146 assert (tdSrc == null) || (hrnSrcID == null);
147 assert hrnDstID != null;
150 // fields can be null when the edge is from
151 // a variable node to a heap region!
152 // assert field != null;
153 this.e_srcOutContext = srcOutContext;
155 this.e_tdSrc = tdSrc;
156 this.e_hrnSrcID = hrnSrcID;
157 this.e_hrnDstID = hrnDstID;
159 this.e_field = field;
160 this.ne_state = state;
161 this.predType = TYPE_EDGE;
166 // only consider the subest of the caller elements that
167 // are reachable by callee when testing predicates--if THIS
168 // predicate is satisfied, return the predicate set of the
169 // element that satisfied it, or null for false
170 public ExistPredSet isSatisfiedBy( ReachGraph rg,
171 Set<Integer> calleeReachableNodes
174 if( predType == TYPE_TRUE ) {
175 return ExistPredSet.factory( ExistPred.factory() );
178 if( predType == TYPE_NODE ) {
180 HeapRegionNode hrn = rg.id2hrn.get( n_hrnID );
185 if( !calleeReachableNodes.contains( n_hrnID ) ) {
189 // when the state is null it is not part of the
190 // predicate, so we've already satisfied
191 if( ne_state == null ) {
192 return hrn.getPreds();
195 // otherwise look for state too
196 // TODO: contains OR containsSuperSet OR containsWithZeroes??
197 if( hrn.getAlpha().contains( ne_state ) ) {
198 return hrn.getPreds();
204 if( predType == TYPE_EDGE ) {
205 // first establish whether the source of the
206 // reference edge exists
207 VariableNode vnSrc = null;
208 if( e_tdSrc != null ) {
209 vnSrc = rg.td2vn.get( e_tdSrc );
211 HeapRegionNode hrnSrc = null;
212 if( e_hrnSrcID != null ) {
213 hrnSrc = rg.id2hrn.get( e_hrnSrcID );
215 assert (vnSrc == null) || (hrnSrc == null);
217 // the source is not present in graph
218 if( vnSrc == null && hrnSrc == null ) {
223 if( vnSrc != null ) {
226 if( !calleeReachableNodes.contains( e_hrnSrcID ) && !e_srcOutContext ) {
229 if( calleeReachableNodes.contains( e_hrnSrcID ) && e_srcOutContext ) {
235 // is the destination present?
236 HeapRegionNode hrnDst = rg.id2hrn.get( e_hrnDstID );
237 if( hrnDst == null ) {
241 if( !calleeReachableNodes.contains( e_hrnDstID ) ) {
245 // is there an edge between them with the given
247 // TODO: type OR a subtype?
248 RefEdge edge = rsn.getReferenceTo( hrnDst,
255 // when state is null it is not part of the predicate
256 // so we've satisfied the edge existence
257 if( ne_state == null ) {
258 return edge.getPreds();
261 // otherwise look for state too
262 // TODO: contains OR containsSuperSet OR containsWithZeroes??
263 if( hrnDst.getAlpha().contains( ne_state ) ) {
264 return edge.getPreds();
270 throw new Error( "Unknown predicate type" );
275 public boolean equals( Object o ) {
280 if( !(o instanceof ExistPred) ) {
284 ExistPred pred = (ExistPred) o;
286 if( this.predType != pred.predType ) {
290 if( ne_state == null ) {
291 if( pred.ne_state != null ) {
294 } else if( !ne_state.equals( pred.ne_state ) ) {
298 if( n_hrnID == null ) {
299 if( pred.n_hrnID != null ) {
302 } else if( !n_hrnID.equals( pred.n_hrnID ) ) {
306 if( e_tdSrc == null ) {
307 if( pred.e_tdSrc != null ) {
310 } else if( !e_tdSrc.equals( pred.e_tdSrc ) ) {
314 if( e_hrnSrcID == null ) {
315 if( pred.e_hrnSrcID != null ) {
318 } else if( !e_hrnSrcID.equals( pred.e_hrnSrcID ) ) {
322 if( e_hrnDstID == null ) {
323 if( pred.e_hrnDstID != null ) {
326 } else if( !e_hrnDstID.equals( pred.e_hrnDstID ) ) {
330 if( e_type == null ) {
331 if( pred.e_type != null ) {
334 } else if( !e_type.equals( pred.e_type ) ) {
338 if( e_field == null ) {
339 if( pred.e_field != null ) {
342 } else if( !e_field.equals( pred.e_field ) ) {
346 // if the identifiers match, this should
348 assert e_srcOutContext == pred.e_srcOutContext;
354 public int hashCodeSpecific() {
355 if( predType == TYPE_TRUE ) {
359 if( predType == TYPE_NODE ) {
360 int hash = n_hrnID.intValue()*17;
362 if( ne_state != null ) {
363 hash += ne_state.hashCode();
369 if( predType == TYPE_EDGE ) {
372 hash += e_type.hashCode()*17;
374 if( e_field != null ) {
375 hash += e_field.hashCode()*7;
378 if( e_tdSrc != null ) {
379 hash += e_tdSrc.hashCode()*11;
381 hash += e_hrnSrcID.hashCode()*11;
384 hash += e_hrnDstID.hashCode();
386 if( ne_state != null ) {
387 hash += ne_state.hashCode();
393 throw new Error( "Unknown predicate type" );
397 public String toString() {
398 if( predType == TYPE_TRUE ) {
402 if( predType == TYPE_NODE ) {
403 String s = n_hrnID.toString();
404 if( ne_state != null ) {
410 if( predType == TYPE_EDGE ) {
413 if( e_tdSrc != null ) {
414 s += e_tdSrc.toString();
416 s += e_hrnSrcID.toString();
419 if( e_srcOutContext ) {
423 s += "-->"+e_hrnDstID+")";
425 if( ne_state != null ) {
432 throw new Error( "Unknown predicate type" );