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 // dst is always a heap region
63 protected Integer e_hrnDstID;
65 // a reference has a field name and type
66 protected TypeDescriptor e_type;
67 protected String e_field;
69 // edge uses same ReachState ne_state as node type above
72 // to make the true predicate
73 public static ExistPred factory() {
74 ExistPred out = new ExistPred();
75 out = (ExistPred) Canonical.makeCanonical( out );
79 protected ExistPred() {
80 this.predType = TYPE_TRUE;
91 public static ExistPred factory( Integer hrnID,
94 ExistPred out = new ExistPred( hrnID, state );
96 out = (ExistPred) Canonical.makeCanonical( out );
100 protected ExistPred( Integer hrnID,
102 assert hrnID != null;
103 this.n_hrnID = hrnID;
104 this.ne_state = state;
105 this.predType = TYPE_NODE;
114 public static ExistPred factory( TempDescriptor tdSrc,
121 ExistPred out = new ExistPred( tdSrc,
128 out = (ExistPred) Canonical.makeCanonical( out );
132 protected ExistPred( TempDescriptor tdSrc,
139 assert (tdSrc == null) || (hrnSrcID == null);
140 assert hrnDstID != null;
143 // fields can be null when the edge is from
144 // a variable node to a heap region!
145 // assert field != null;
147 this.e_tdSrc = tdSrc;
148 this.e_hrnSrcID = hrnSrcID;
149 this.e_hrnDstID = hrnDstID;
151 this.e_field = field;
152 this.ne_state = state;
153 this.predType = TYPE_EDGE;
158 // only consider the subest of the caller elements that
159 // are reachable by callee when testing predicates
160 public boolean isSatisfiedBy( ReachGraph rg,
161 Set<HeapRegionNode> calleeReachableNodes,
162 Set<RefEdge> calleeReachableEdges
165 if( predType == TYPE_TRUE ) {
169 if( predType == TYPE_NODE ) {
171 HeapRegionNode hrn = rg.id2hrn.get( n_hrnID );
176 if( !calleeReachableNodes.contains( hrn ) ) {
180 // when the state is null it is not part of the
181 // predicate, so we've already satisfied
182 if( ne_state == null ) {
186 // otherwise look for state too
187 // TODO: contains OR containsSuperSet OR containsWithZeroes??
188 return hrn.getAlpha().contains( ne_state );
191 if( predType == TYPE_EDGE ) {
192 // first establish whether the source of the
193 // reference edge exists
194 VariableNode vnSrc = null;
195 if( e_tdSrc != null ) {
196 vnSrc = rg.td2vn.get( e_tdSrc );
198 HeapRegionNode hrnSrc = null;
199 if( e_hrnSrcID != null ) {
200 hrnSrc = rg.id2hrn.get( e_hrnSrcID );
202 assert (vnSrc == null) || (hrnSrc == null);
204 // the source is not present in graph
205 if( vnSrc == null && hrnSrc == null ) {
210 if( vnSrc != null ) {
213 if( !calleeReachableNodes.contains( hrnSrc ) ) {
219 // is the destination present?
220 HeapRegionNode hrnDst = rg.id2hrn.get( e_hrnDstID );
221 if( hrnDst == null ) {
225 if( !calleeReachableNodes.contains( hrnDst ) ) {
229 // is there an edge between them with the given
231 // TODO: type OR a subtype?
232 RefEdge edge = rsn.getReferenceTo( hrnDst,
239 if( !calleeReachableEdges.contains( edge ) ) {
243 // when state is null it is not part of the predicate
244 // so we've satisfied the edge existence
245 if( ne_state == null ) {
249 // otherwise look for state too
250 // TODO: contains OR containsSuperSet OR containsWithZeroes??
251 return hrnDst.getAlpha().contains( ne_state );
254 throw new Error( "Unknown predicate type" );
259 public boolean equals( Object o ) {
264 if( !(o instanceof ExistPred) ) {
268 ExistPred pred = (ExistPred) o;
270 if( this.predType != pred.predType ) {
274 if( ne_state == null ) {
275 if( pred.ne_state != null ) {
278 } else if( !ne_state.equals( pred.ne_state ) ) {
282 if( n_hrnID == null ) {
283 if( pred.n_hrnID != null ) {
286 } else if( !n_hrnID.equals( pred.n_hrnID ) ) {
290 if( e_tdSrc == null ) {
291 if( pred.e_tdSrc != null ) {
294 } else if( !e_tdSrc.equals( pred.e_tdSrc ) ) {
298 if( e_hrnSrcID == null ) {
299 if( pred.e_hrnSrcID != null ) {
302 } else if( !e_hrnSrcID.equals( pred.e_hrnSrcID ) ) {
306 if( e_hrnDstID == null ) {
307 if( pred.e_hrnDstID != null ) {
310 } else if( !e_hrnDstID.equals( pred.e_hrnDstID ) ) {
314 if( e_type == null ) {
315 if( pred.e_type != null ) {
318 } else if( !e_type.equals( pred.e_type ) ) {
322 if( e_field == null ) {
323 if( pred.e_field != null ) {
326 } else if( !e_field.equals( pred.e_field ) ) {
334 public int hashCodeSpecific() {
335 if( predType == TYPE_TRUE ) {
339 if( predType == TYPE_NODE ) {
340 int hash = n_hrnID.intValue()*17;
342 if( ne_state != null ) {
343 hash += ne_state.hashCode();
349 if( predType == TYPE_EDGE ) {
352 hash += e_type.hashCode()*17;
354 if( e_field != null ) {
355 hash += e_field.hashCode()*7;
358 if( e_tdSrc != null ) {
359 hash += e_tdSrc.hashCode()*11;
361 hash += e_hrnSrcID.hashCode()*11;
364 hash += e_hrnDstID.hashCode();
366 if( ne_state != null ) {
367 hash += ne_state.hashCode();
373 throw new Error( "Unknown predicate type" );
377 public String toString() {
378 if( predType == TYPE_TRUE ) {
382 if( predType == TYPE_NODE ) {
383 String s = n_hrnID.toString();
384 if( ne_state != null ) {
390 if( predType == TYPE_EDGE ) {
393 if( e_tdSrc != null ) {
394 s += e_tdSrc.toString();
396 s += e_hrnSrcID.toString();
399 s += "-->"+e_hrnDstID+")";
401 if( ne_state != null ) {
408 throw new Error( "Unknown predicate type" );