Bug fix, subtle errors in exist pred hashcode, and a cycle pred.hashCode to state...
[IRC.git] / Robust / src / Analysis / Disjoint / RefEdge.java
1 package Analysis.Disjoint;
2
3 import IR.*;
4 import IR.Flat.*;
5 import java.util.*;
6
7
8 public class RefEdge {
9
10   // all edges should have a non-null
11   // TypeDescriptor now
12   protected TypeDescriptor type;
13
14   // the field name may be null if this
15   // edge models a variable reference
16   protected String field;
17
18   protected ReachSet beta;
19   protected ReachSet betaNew;
20
21   protected RefSrcNode src;
22   protected HeapRegionNode dst;
23
24   // existence predicates must be true in a caller
25   // context for this edge to transfer from this
26   // callee to that context--NOTE, existence predicates
27   // do not factor into edge comparisons
28   protected ExistPredSet preds;
29
30   // taint sets indicate which heap roots have
31   // tainted this edge-->meaning which heap roots
32   // code must have had access to in order to
33   // read or write through this edge
34   protected TaintSet taints;
35
36
37   public RefEdge(RefSrcNode src,
38                  HeapRegionNode dst,
39                  TypeDescriptor type,
40                  String field,
41                  ReachSet beta,
42                  ExistPredSet preds,
43                  TaintSet taints) {
44
45     assert src  != null;
46     assert dst  != null;
47     assert type != null;
48
49     this.src     = src;
50     this.dst     = dst;
51     this.type    = type;
52     this.field   = field;
53
54     if( preds != null ) {
55       this.preds = preds;
56     } else {
57       this.preds = ExistPredSet.factory();
58     }
59
60     if( beta != null ) {
61       this.beta = beta;
62     } else {
63       this.beta = ReachSet.factory();
64     }
65
66     // when edges are not undergoing an operation that
67     // is changing beta info, betaNew is always empty
68     betaNew = ReachSet.factory();
69
70     if( taints != null ) {
71       this.taints = taints;
72     } else {
73       this.taints = TaintSet.factory();
74     }
75   }
76
77
78   public RefEdge copy() {
79     RefEdge copy = new RefEdge(src,
80                                dst,
81                                type,
82                                field,
83                                beta,
84                                preds,
85                                taints);
86     return copy;
87   }
88
89
90   public boolean equals(Object o) {
91     if( o == null ) {
92       return false;
93     }
94
95     if( !(o instanceof RefEdge) ) {
96       return false;
97     }
98
99     RefEdge edge = (RefEdge) o;
100
101     if( !typeEquals(edge.type) ) {
102       return false;
103     }
104
105     if( !fieldEquals(edge.field) ) {
106       return false;
107     }
108
109     if( src instanceof VariableNode ) {
110       VariableNode vsrc = (VariableNode) src;
111       if( !vsrc.equals( (VariableNode) edge.src ) ) {
112         return false;
113       }
114     } else {
115       HeapRegionNode hsrc = (HeapRegionNode) src;
116       if( !hsrc.equalsIncludingAlphaAndPreds( (HeapRegionNode) edge.src ) ) {
117         return false;
118       }
119     }
120     
121     if( !dst.equalsIncludingAlphaAndPreds( edge.dst ) ) {
122       return false;
123     }
124
125     return true;
126   }
127
128
129   // beta and preds contribute towards reaching the
130   // fixed point, so use this method to determine if
131   // an edge is "equal" to some previous visit, basically
132   // and taints!
133   public boolean equalsIncludingBetaPredsTaints(RefEdge edge) {
134     return equals(edge) &&
135            beta.equals(edge.beta) &&
136            preds.equals(edge.preds) &&
137            taints.equals(edge.taints);
138   }
139
140   public boolean equalsPreds(RefEdge edge) {
141     return preds.equals(edge.preds);
142   }
143
144
145   // this method SPECIFICALLY does not use the
146   // beta/preds/taints in the hash code--it uses
147   // the same fields as normal equals.  Again,
148   // there are two meanings of equality for edges,
149   // one is "this edge is the same edge object" like when
150   // deciding if an edge is already in a set, which
151   // is represented by this hashcode.  The other
152   // meaning is "this edge equals an edge from another
153   // graph that is abstractly the same edge"
154   public int hashCode() {
155     int hash = 0;
156
157     hash += type.hashCode()*17;
158
159     if( field != null ) {
160       hash += field.hashCode()*7;
161     }
162
163     hash += src.hashCode()*11;
164     hash += dst.hashCode();
165
166     return hash;
167   }
168
169
170   public RefSrcNode getSrc() {
171     return src;
172   }
173
174   public void setSrc(RefSrcNode rsn) {
175     assert rsn != null;
176     src = rsn;
177   }
178
179   public HeapRegionNode getDst() {
180     return dst;
181   }
182
183   public void setDst(HeapRegionNode hrn) {
184     assert hrn != null;
185     dst = hrn;
186   }
187
188
189   public TypeDescriptor getType() {
190     return type;
191   }
192
193   public void setType(TypeDescriptor td) {
194     assert td != null;
195     type = td;
196   }
197
198   public String getField() {
199     return field;
200   }
201
202   public void setField(String s) {
203     field = s;
204   }
205
206
207   public boolean typeEquals(TypeDescriptor td) {
208     return type.equals(td);
209   }
210
211   public boolean fieldEquals(String s) {
212     if( field == null && s == null ) {
213       return true;
214     }
215     if( field == null ) {
216       return false;
217     }
218     return field.equals(s);
219   }
220
221   public boolean typeAndFieldEquals(RefEdge e) {
222     return typeEquals(e.getType()  ) &&
223            fieldEquals(e.getField() );
224   }
225
226
227   public ReachSet getBeta() {
228     return beta;
229   }
230
231   public void setBeta(ReachSet beta) {
232     assert beta != null;
233     this.beta = beta;
234   }
235
236   public ReachSet getBetaNew() {
237     return betaNew;
238   }
239
240   public void setBetaNew(ReachSet beta) {
241     assert beta != null;
242     this.betaNew = beta;
243   }
244
245   public void applyBetaNew() {
246     assert betaNew != null;
247     beta    = betaNew;
248     betaNew = ReachSet.factory();
249   }
250
251
252   public ExistPredSet getPreds() {
253     return preds;
254   }
255
256   public void setPreds(ExistPredSet preds) {
257     this.preds = preds;
258   }
259
260
261   public TaintSet getTaints() {
262     return taints;
263   }
264
265   public void setTaints(TaintSet taints) {
266     this.taints = taints;
267   }
268
269
270   public String toStringDOT(boolean hideReach,
271                             boolean hideSubsetReach,
272                             boolean hidePreds,
273                             boolean hideEdgeTaints,
274                             String otherAttributes) {
275     String s =
276       "[label=\""+
277       type.toPrettyString()+"\\n"+
278       field;
279     if( !hideReach ) {
280       s += "\\n"+beta.toStringEscNewline(hideSubsetReach, hidePreds);
281     }
282
283     if( !hidePreds ) {
284       s += "\\n"+preds.toStringEscNewline();
285     }
286
287     if( !hideEdgeTaints ) {
288       if( !taints.isEmpty() ) {
289         s += "\\n"+taints.toStringEscNewline( hidePreds );
290       }
291     }
292
293     return s+"\",decorate"+otherAttributes+"]";
294   }
295
296   public String toString() {
297     return new String("("+src+
298                       "->"+type.toPrettyString()+
299                       " "+field+
300                       "->"+dst+")"
301                       );
302   }
303
304   public String toStringAndBeta() {
305     return toString()+beta.toString();
306   }
307 }