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
84 protected Taint e_taint;
88 // a static debug flag for higher abstraction code
89 // to enable debug info at this level
90 public static boolean debug = false;
93 // to make the true predicate
94 public static ExistPred factory() {
95 ExistPred out = new ExistPred();
96 out = (ExistPred) Canonical.makeCanonical(out);
100 protected ExistPred() {
101 this.predType = TYPE_TRUE;
110 e_srcOutCalleeContext = false;
111 e_srcOutCallerContext = false;
115 public static ExistPred factory(Integer hrnID,
118 ExistPred out = new ExistPred(hrnID, state);
120 out = (ExistPred) Canonical.makeCanonical(out);
124 protected ExistPred(Integer hrnID,
126 assert hrnID != null;
127 this.n_hrnID = hrnID;
128 this.ne_state = removePreds( state );
129 this.predType = TYPE_NODE;
136 e_srcOutCalleeContext = false;
137 e_srcOutCallerContext = false;
141 public static ExistPred factory(TempDescriptor tdSrc,
148 boolean srcOutCalleeContext,
149 boolean srcOutCallerContext) {
151 ExistPred out = new ExistPred(tdSrc,
159 srcOutCallerContext);
161 out = (ExistPred) Canonical.makeCanonical(out);
165 protected ExistPred(TempDescriptor tdSrc,
172 boolean srcOutCalleeContext,
173 boolean srcOutCallerContext) {
175 assert(tdSrc == null) || (hrnSrcID == null);
176 assert hrnDstID != null;
178 assert(state == null) || (taint == null);
180 // fields can be null when the edge is from
181 // a variable node to a heap region!
183 this.e_srcOutCalleeContext = srcOutCalleeContext;
184 this.e_srcOutCallerContext = srcOutCallerContext;
186 assert !(e_srcOutCalleeContext && e_srcOutCallerContext);
188 this.e_tdSrc = tdSrc;
189 this.e_hrnSrcID = hrnSrcID;
190 this.e_hrnDstID = hrnDstID;
192 this.e_field = field;
193 this.ne_state = removePreds( state );
194 this.e_taint = taint;
195 this.predType = TYPE_EDGE;
199 // for node or edge, check inputs
200 public static ExistPred factory(Integer hrnID,
201 TempDescriptor tdSrc,
208 boolean srcOutCalleeContext,
209 boolean srcOutCallerContext) {
212 if( hrnID != null ) {
213 out = new ExistPred(hrnID, state);
216 out = new ExistPred(tdSrc,
224 srcOutCallerContext);
227 out = (ExistPred) Canonical.makeCanonical(out);
233 private ReachState removePreds( ReachState state ) {
234 return state == null ? null : Canonical.attach( state, ExistPredSet.factory() );
239 // only consider the subest of the caller elements that
240 // are reachable by callee when testing predicates--if THIS
241 // predicate is satisfied, return the predicate set of the
242 // element that satisfied it, or null for false
243 public ExistPredSet isSatisfiedBy(ReachGraph rg,
244 Set<Integer> calleeReachableNodes,
245 Set<RefSrcNode> callerSrcMatches
247 if( predType == TYPE_TRUE ) {
248 return ExistPredSet.factory(ExistPred.factory() );
251 if( predType == TYPE_NODE ) {
253 HeapRegionNode hrn = rg.id2hrn.get(n_hrnID);
258 if( !calleeReachableNodes.contains(n_hrnID) ) {
262 // when the state is null we're done!
263 if( ne_state == null ) {
264 return hrn.getPreds();
267 // otherwise look for state too
269 // TODO: contains OR containsSuperSet OR containsWithZeroes??
270 ReachState stateCaller = hrn.getAlpha().containsIgnorePreds(ne_state);
272 if( stateCaller == null ) {
276 // it was here, return the predicates on the state!!
277 return stateCaller.getPreds();
281 // unreachable program point!
284 if( predType == TYPE_EDGE ) {
286 // first establish whether the source of the
287 // reference edge exists
288 VariableNode vnSrc = null;
289 if( e_tdSrc != null ) {
290 vnSrc = rg.td2vn.get(e_tdSrc);
292 HeapRegionNode hrnSrc = null;
293 if( e_hrnSrcID != null ) {
294 hrnSrc = rg.id2hrn.get(e_hrnSrcID);
296 assert(vnSrc == null) || (hrnSrc == null);
298 // the source is not present in graph
299 if( vnSrc == null && hrnSrc == null ) {
304 if( vnSrc != null ) {
306 assert e_srcOutCalleeContext;
307 assert !e_srcOutCallerContext;
311 assert !(e_srcOutCalleeContext && e_srcOutCallerContext);
313 if( e_srcOutCalleeContext ) {
314 if( calleeReachableNodes.contains(e_hrnSrcID) ) {
318 } else if( e_srcOutCallerContext ) {
319 if( !hrnSrc.isOutOfContext() ) {
325 if( !calleeReachableNodes.contains(e_hrnSrcID) ) {
328 if( hrnSrc.isOutOfContext() ) {
337 // is the destination present?
338 HeapRegionNode hrnDst = rg.id2hrn.get(e_hrnDstID);
339 if( hrnDst == null ) {
343 if( !calleeReachableNodes.contains(e_hrnDstID) ) {
347 // is there an edge between them with the given
349 // TODO: type OR a subtype?
350 RefEdge edge = rsn.getReferenceTo(hrnDst,
357 // when the state and taint are null we're done!
358 if( ne_state == null &&
361 if( callerSrcMatches != null ) {
362 callerSrcMatches.add( rsn );
365 return edge.getPreds();
368 } else if( ne_state != null ) {
369 // otherwise look for state too
371 // TODO: contains OR containsSuperSet OR containsWithZeroes??
372 ReachState stateCaller = edge.getBeta().containsIgnorePreds(ne_state);
374 if( stateCaller == null ) {
378 // it was here, return the predicates on the state!!
379 return stateCaller.getPreds();
383 // otherwise look for taint
385 Taint tCaller = edge.getTaints().containsIgnorePreds(e_taint);
387 if( tCaller == null ) {
391 // it was here, return the predicates on the taint!!
392 if( callerSrcMatches != null ) {
393 callerSrcMatches.add( rsn );
396 return tCaller.getPreds();
400 // unreachable program point!
403 throw new Error("Unknown predicate type");
408 // if this pred is an edge type pred, then given
409 // a reach graph, find the element of the graph that
410 // may exist and represents the source of the edge
411 public RefSrcNode getEdgeSource( ReachGraph rg ) {
412 if( predType != TYPE_EDGE ) {
416 if( e_tdSrc != null ) {
417 // variable node is the source, look for it in the graph
418 return rg.getVariableNodeNoMutation( e_tdSrc );
421 // otherwise a heap region node is the source, look for it
422 assert e_hrnDstID != null;
423 return rg.id2hrn.get( e_hrnDstID );
428 public boolean equalsSpecific(Object o) {
433 if( !(o instanceof ExistPred) ) {
437 ExistPred pred = (ExistPred) o;
439 if( this.predType != pred.predType ) {
443 if( ne_state == null ) {
444 if( pred.ne_state != null ) {
447 } else if( !ne_state.equalsIgnorePreds(pred.ne_state) ) {
451 if( n_hrnID == null ) {
452 if( pred.n_hrnID != null ) {
455 } else if( !n_hrnID.equals(pred.n_hrnID) ) {
459 if( e_tdSrc == null ) {
460 if( pred.e_tdSrc != null ) {
463 } else if( !e_tdSrc.equals(pred.e_tdSrc) ) {
467 if( e_hrnSrcID == null ) {
468 if( pred.e_hrnSrcID != null ) {
472 if( !e_hrnSrcID.equals(pred.e_hrnSrcID) ) {
475 if( e_srcOutCalleeContext != pred.e_srcOutCalleeContext ) {
478 if( e_srcOutCallerContext != pred.e_srcOutCallerContext ) {
483 if( e_hrnDstID == null ) {
484 if( pred.e_hrnDstID != null ) {
487 } else if( !e_hrnDstID.equals(pred.e_hrnDstID) ) {
491 if( e_type == null ) {
492 if( pred.e_type != null ) {
495 } else if( !e_type.equals(pred.e_type) ) {
499 if( e_field == null ) {
500 if( pred.e_field != null ) {
503 } else if( !e_field.equals(pred.e_field) ) {
507 if( e_taint == null ) {
508 if( pred.e_taint != null ) {
511 } else if( !e_taint.equals(pred.e_taint) ) {
519 public int hashCodeSpecific() {
521 if( predType == TYPE_TRUE ) {
525 if( predType == TYPE_NODE ) {
526 int hash = n_hrnID.intValue()*17;
528 if( ne_state != null ) {
529 hash ^= ne_state.hashCodeNoPreds();
535 if( predType == TYPE_EDGE ) {
538 hash += e_type.hashCode()*17;
540 if( e_field != null ) {
541 hash += e_field.hashCode()*7;
544 if( e_tdSrc != null ) {
545 hash ^= e_tdSrc.hashCode()*11;
547 hash ^= e_hrnSrcID.hashCode()*11;
548 if( e_srcOutCalleeContext ) {
551 if( e_srcOutCallerContext ) {
556 hash += e_hrnDstID.hashCode();
558 if( ne_state != null ) {
559 hash ^= ne_state.hashCodeNoPreds();
562 if( e_taint != null ) {
563 hash ^= e_taint.hashCode();
569 throw new Error("Unknown predicate type");
573 public String toString() {
574 if( predType == TYPE_TRUE ) {
578 if( predType == TYPE_NODE ) {
579 String s = n_hrnID.toString();
580 if( ne_state != null ) {
586 if( predType == TYPE_EDGE ) {
589 if( e_tdSrc != null ) {
590 s += e_tdSrc.toString();
592 s += e_hrnSrcID.toString();
595 if( e_srcOutCalleeContext ) {
599 if( e_srcOutCallerContext ) {
603 s += "-->"+e_hrnDstID+")";
605 if( ne_state != null ) {
609 if( e_taint != null ) {
616 throw new Error("Unknown predicate type");