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;
52 // the preds on this state are irrelevant, so always strip them off
53 // when we store it in this ExistPred to make sure it equals other
54 // ExistPred objects with the same ne_state, preds ignored.
55 protected ReachState ne_state;
57 // An edge existence predicate is satisfied if the elements
58 // defining an edge are part of the given graph.
59 // The reach state may be null--if not the predicate is
60 // satisfied when the edge exists AND it has the state.
61 // the source of an edge is *either* a variable
62 // node or a heap region node
63 protected TempDescriptor e_tdSrc;
64 protected Integer e_hrnSrcID;
66 // the source of an edge might be out of the callee
67 // context but in the caller graph, a normal caller
68 // heap region or variable, OR it might be out of the
69 // caller context ALSO: an ooc node in the caller
70 protected boolean e_srcOutCalleeContext;
71 protected boolean e_srcOutCallerContext;
73 // dst is always a heap region
74 protected Integer e_hrnDstID;
76 // a reference has a field name and type
77 protected TypeDescriptor e_type;
78 protected String e_field;
80 // if the taint is non-null then the predicate
81 // is true only if the edge exists AND has the
82 // taint--ONLY ONE of the ne_state or e_taint
83 // may be non-null for an edge predicate, AND
84 // like the ne_state above, strip preds off this
85 // taint within a pred itself
86 protected Taint e_taint;
90 // a static debug flag for higher abstraction code
91 // to enable debug info at this level
92 public static boolean debug = false;
95 // to make the true predicate
96 public static ExistPred factory() {
97 ExistPred out = new ExistPred();
98 out = (ExistPred) Canonical.makeCanonical(out);
102 protected ExistPred() {
103 this.predType = TYPE_TRUE;
112 e_srcOutCalleeContext = false;
113 e_srcOutCallerContext = false;
117 public static ExistPred factory(Integer hrnID,
120 ExistPred out = new ExistPred(hrnID, state);
122 out = (ExistPred) Canonical.makeCanonical(out);
126 protected ExistPred(Integer hrnID,
128 assert hrnID != null;
129 this.n_hrnID = hrnID;
130 this.ne_state = removePreds( state );
131 this.predType = TYPE_NODE;
138 e_srcOutCalleeContext = false;
139 e_srcOutCallerContext = false;
143 public static ExistPred factory(TempDescriptor tdSrc,
150 boolean srcOutCalleeContext,
151 boolean srcOutCallerContext) {
153 ExistPred out = new ExistPred(tdSrc,
161 srcOutCallerContext);
163 out = (ExistPred) Canonical.makeCanonical(out);
167 protected ExistPred(TempDescriptor tdSrc,
174 boolean srcOutCalleeContext,
175 boolean srcOutCallerContext) {
177 assert(tdSrc == null) || (hrnSrcID == null);
178 assert hrnDstID != null;
180 assert(state == null) || (taint == null);
182 // fields can be null when the edge is from
183 // a variable node to a heap region!
185 this.e_srcOutCalleeContext = srcOutCalleeContext;
186 this.e_srcOutCallerContext = srcOutCallerContext;
188 assert !(e_srcOutCalleeContext && e_srcOutCallerContext);
190 this.e_tdSrc = tdSrc;
191 this.e_hrnSrcID = hrnSrcID;
192 this.e_hrnDstID = hrnDstID;
194 this.e_field = field;
195 this.ne_state = removePreds( state );
196 this.e_taint = removePreds( taint );
197 this.predType = TYPE_EDGE;
201 // for node or edge, check inputs
202 public static ExistPred factory(Integer hrnID,
203 TempDescriptor tdSrc,
210 boolean srcOutCalleeContext,
211 boolean srcOutCallerContext) {
214 if( hrnID != null ) {
215 out = new ExistPred(hrnID, state);
218 out = new ExistPred(tdSrc,
226 srcOutCallerContext);
229 out = (ExistPred) Canonical.makeCanonical(out);
235 private ReachState removePreds( ReachState state ) {
236 return state == null ? null : Canonical.attach( state, ExistPredSet.factory() );
239 private Taint removePreds( Taint taint ) {
240 return taint == null ? null : Canonical.attach( taint, ExistPredSet.factory() );
245 // only consider the subest of the caller elements that
246 // are reachable by callee when testing predicates--if THIS
247 // predicate is satisfied, return the predicate set of the
248 // element that satisfied it, or null for false
249 public ExistPredSet isSatisfiedBy(ReachGraph rg,
250 Set<Integer> calleeReachableNodes,
251 Set<RefSrcNode> callerSrcMatches
253 if( predType == TYPE_TRUE ) {
254 return ExistPredSet.factory(ExistPred.factory() );
257 if( predType == TYPE_NODE ) {
259 HeapRegionNode hrn = rg.id2hrn.get(n_hrnID);
264 if( !calleeReachableNodes.contains(n_hrnID) ) {
268 // when the state is null we're done!
269 if( ne_state == null ) {
270 return hrn.getPreds();
273 // otherwise look for state too
275 // TODO: contains OR containsSuperSet OR containsWithZeroes??
276 ReachState stateCaller = hrn.getAlpha().containsIgnorePreds(ne_state);
278 if( stateCaller == null ) {
282 // it was here, return the predicates on the state!!
283 return stateCaller.getPreds();
287 // unreachable program point!
290 if( predType == TYPE_EDGE ) {
292 // first establish whether the source of the
293 // reference edge exists
294 VariableNode vnSrc = null;
295 if( e_tdSrc != null ) {
296 vnSrc = rg.td2vn.get(e_tdSrc);
298 HeapRegionNode hrnSrc = null;
299 if( e_hrnSrcID != null ) {
300 hrnSrc = rg.id2hrn.get(e_hrnSrcID);
302 assert(vnSrc == null) || (hrnSrc == null);
304 // the source is not present in graph
305 if( vnSrc == null && hrnSrc == null ) {
310 if( vnSrc != null ) {
312 assert e_srcOutCalleeContext;
313 assert !e_srcOutCallerContext;
317 assert !(e_srcOutCalleeContext && e_srcOutCallerContext);
319 if( e_srcOutCalleeContext ) {
320 if( calleeReachableNodes.contains(e_hrnSrcID) ) {
324 } else if( e_srcOutCallerContext ) {
325 if( !hrnSrc.isOutOfContext() ) {
331 if( !calleeReachableNodes.contains(e_hrnSrcID) ) {
334 if( hrnSrc.isOutOfContext() ) {
343 // is the destination present?
344 HeapRegionNode hrnDst = rg.id2hrn.get(e_hrnDstID);
345 if( hrnDst == null ) {
349 if( !calleeReachableNodes.contains(e_hrnDstID) ) {
353 // is there an edge between them with the given
355 // TODO: type OR a subtype?
356 RefEdge edge = rsn.getReferenceTo(hrnDst,
363 // when the state and taint are null we're done!
364 if( ne_state == null &&
367 if( callerSrcMatches != null ) {
368 callerSrcMatches.add( rsn );
371 return edge.getPreds();
374 } else if( ne_state != null ) {
375 // otherwise look for state too
377 // TODO: contains OR containsSuperSet OR containsWithZeroes??
378 ReachState stateCaller = edge.getBeta().containsIgnorePreds(ne_state);
380 if( stateCaller == null ) {
384 // it was here, return the predicates on the state!!
385 return stateCaller.getPreds();
389 // otherwise look for taint
391 Taint tCaller = edge.getTaints().containsIgnorePreds(e_taint);
393 if( tCaller == null ) {
397 // it was here, return the predicates on the taint!!
398 if( callerSrcMatches != null ) {
399 callerSrcMatches.add( rsn );
402 return tCaller.getPreds();
406 // unreachable program point!
409 throw new Error("Unknown predicate type");
414 // if this pred is an edge type pred, then given
415 // a reach graph, find the element of the graph that
416 // may exist and represents the source of the edge
417 public RefSrcNode getEdgeSource( ReachGraph rg ) {
418 if( predType != TYPE_EDGE ) {
422 if( e_tdSrc != null ) {
423 // variable node is the source, look for it in the graph
424 return rg.getVariableNodeNoMutation( e_tdSrc );
427 // otherwise a heap region node is the source, look for it
428 assert e_hrnDstID != null;
429 return rg.id2hrn.get( e_hrnDstID );
434 public boolean equalsSpecific(Object o) {
439 if( !(o instanceof ExistPred) ) {
443 ExistPred pred = (ExistPred) o;
445 if( this.predType != pred.predType ) {
449 if( ne_state == null ) {
450 if( pred.ne_state != null ) {
453 } else if( !ne_state.equalsIgnorePreds(pred.ne_state) ) {
457 if( n_hrnID == null ) {
458 if( pred.n_hrnID != null ) {
461 } else if( !n_hrnID.equals(pred.n_hrnID) ) {
465 if( e_tdSrc == null ) {
466 if( pred.e_tdSrc != null ) {
469 } else if( !e_tdSrc.equals(pred.e_tdSrc) ) {
473 if( e_hrnSrcID == null ) {
474 if( pred.e_hrnSrcID != null ) {
478 if( !e_hrnSrcID.equals(pred.e_hrnSrcID) ) {
481 if( e_srcOutCalleeContext != pred.e_srcOutCalleeContext ) {
484 if( e_srcOutCallerContext != pred.e_srcOutCallerContext ) {
489 if( e_hrnDstID == null ) {
490 if( pred.e_hrnDstID != null ) {
493 } else if( !e_hrnDstID.equals(pred.e_hrnDstID) ) {
497 if( e_type == null ) {
498 if( pred.e_type != null ) {
501 } else if( !e_type.equals(pred.e_type) ) {
505 if( e_field == null ) {
506 if( pred.e_field != null ) {
509 } else if( !e_field.equals(pred.e_field) ) {
513 if( e_taint == null ) {
514 if( pred.e_taint != null ) {
517 } else if( !e_taint.equalsIgnorePreds(pred.e_taint) ) {
525 public int hashCodeSpecific() {
527 if( predType == TYPE_TRUE ) {
531 if( predType == TYPE_NODE ) {
532 int hash = n_hrnID.intValue()*17;
534 if( ne_state != null ) {
535 hash ^= ne_state.hashCodeNoPreds();
541 if( predType == TYPE_EDGE ) {
544 hash += e_type.hashCode()*17;
546 if( e_field != null ) {
547 hash += e_field.hashCode()*7;
550 if( e_tdSrc != null ) {
551 hash ^= e_tdSrc.hashCode()*11;
553 hash ^= e_hrnSrcID.hashCode()*11;
554 if( e_srcOutCalleeContext ) {
557 if( e_srcOutCallerContext ) {
562 hash += e_hrnDstID.hashCode();
564 if( ne_state != null ) {
565 hash ^= ne_state.hashCodeNoPreds();
568 if( e_taint != null ) {
569 hash ^= e_taint.hashCodeNoPreds();
575 throw new Error("Unknown predicate type");
579 public String toString() {
580 if( predType == TYPE_TRUE ) {
584 if( predType == TYPE_NODE ) {
585 String s = n_hrnID.toString();
586 if( ne_state != null ) {
592 if( predType == TYPE_EDGE ) {
595 if( e_tdSrc != null ) {
596 s += e_tdSrc.toString();
598 s += e_hrnSrcID.toString();
601 if( e_srcOutCalleeContext ) {
605 if( e_srcOutCallerContext ) {
609 s += "-->"+e_hrnDstID+")";
611 if( ne_state != null ) {
615 if( e_taint != null ) {
622 throw new Error("Unknown predicate type");