fix a bug for Taint similar to ReachState, when either is an element of an ExistPred...
[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     setTaints( taints != null ? taints : TaintSet.factory() );
71   }
72
73
74   public RefEdge copy() {
75     RefEdge copy = new RefEdge(src,
76                                dst,
77                                type,
78                                field,
79                                beta,
80                                preds,
81                                taints);
82     return copy;
83   }
84
85
86   public boolean equals(Object o) {
87     if( o == null ) {
88       return false;
89     }
90
91     if( !(o instanceof RefEdge) ) {
92       return false;
93     }
94
95     RefEdge edge = (RefEdge) o;
96
97     if( !typeEquals(edge.type) ) {
98       return false;
99     }
100
101     if( !fieldEquals(edge.field) ) {
102       return false;
103     }
104
105     if( src instanceof VariableNode ) {
106       VariableNode vsrc = (VariableNode) src;
107       if( !vsrc.equals( (VariableNode) edge.src ) ) {
108         return false;
109       }
110     } else {
111       HeapRegionNode hsrc = (HeapRegionNode) src;
112       if( !hsrc.equalsIncludingAlphaAndPreds( (HeapRegionNode) edge.src ) ) {
113         return false;
114       }
115     }
116     
117     if( !dst.equalsIncludingAlphaAndPreds( edge.dst ) ) {
118       return false;
119     }
120
121     return true;
122   }
123
124
125   // beta and preds contribute towards reaching the
126   // fixed point, so use this method to determine if
127   // an edge is "equal" to some previous visit, basically
128   // and taints!
129   public boolean equalsIncludingBetaPredsTaints(RefEdge edge) {
130     return equals(edge) &&
131            beta.equals(edge.beta) &&
132            preds.equals(edge.preds) &&
133            taints.equals(edge.taints);
134   }
135
136   public boolean equalsPreds(RefEdge edge) {
137     return preds.equals(edge.preds);
138   }
139
140
141   // this method SPECIFICALLY does not use the
142   // beta/preds/taints in the hash code--it uses
143   // the same fields as normal equals.  Again,
144   // there are two meanings of equality for edges,
145   // one is "this edge is the same edge object" like when
146   // deciding if an edge is already in a set, which
147   // is represented by this hashcode.  The other
148   // meaning is "this edge equals an edge from another
149   // graph that is abstractly the same edge"
150   public int hashCode() {
151     int hash = 0;
152
153     hash += type.hashCode()*17;
154
155     if( field != null ) {
156       hash += field.hashCode()*7;
157     }
158
159     hash += src.hashCode()*11;
160     hash += dst.hashCode();
161
162     return hash;
163   }
164
165
166   public RefSrcNode getSrc() {
167     return src;
168   }
169
170   public void setSrc(RefSrcNode rsn) {
171     assert rsn != null;
172     src = rsn;
173   }
174
175   public HeapRegionNode getDst() {
176     return dst;
177   }
178
179   public void setDst(HeapRegionNode hrn) {
180     assert hrn != null;
181     dst = hrn;
182   }
183
184
185   public TypeDescriptor getType() {
186     return type;
187   }
188
189   public void setType(TypeDescriptor td) {
190     assert td != null;
191     type = td;
192   }
193
194   public String getField() {
195     return field;
196   }
197
198   public void setField(String s) {
199     field = s;
200   }
201
202
203   public boolean typeEquals(TypeDescriptor td) {
204     return type.equals(td);
205   }
206
207   public boolean fieldEquals(String s) {
208     if( field == null && s == null ) {
209       return true;
210     }
211     if( field == null ) {
212       return false;
213     }
214     return field.equals(s);
215   }
216
217   public boolean typeAndFieldEquals(RefEdge e) {
218     return typeEquals(e.getType()  ) &&
219            fieldEquals(e.getField() );
220   }
221
222
223   public ReachSet getBeta() {
224     return beta;
225   }
226
227   public void setBeta(ReachSet beta) {
228     assert beta != null;
229     this.beta = beta;
230   }
231
232   public ReachSet getBetaNew() {
233     return betaNew;
234   }
235
236   public void setBetaNew(ReachSet beta) {
237     assert beta != null;
238     this.betaNew = beta;
239   }
240
241   public void applyBetaNew() {
242     assert betaNew != null;
243     beta    = betaNew;
244     betaNew = ReachSet.factory();
245   }
246
247
248   public ExistPredSet getPreds() {
249     return preds;
250   }
251
252   public void setPreds(ExistPredSet preds) {
253     this.preds = preds;
254   }
255
256
257   public TaintSet getTaints() {
258     return taints;
259   }
260
261   public void setTaints(TaintSet taints) {
262     this.taints = taints;
263   }
264
265
266   public String toStringDOT(boolean hideReach,
267                             boolean hideSubsetReach,
268                             boolean hidePreds,
269                             boolean hideEdgeTaints,
270                             String otherAttributes) {
271     String s =
272       "[label=\""+
273       type.toPrettyString()+"\\n"+
274       field;
275     if( !hideReach ) {
276       s += "\\n"+beta.toStringEscNewline(hideSubsetReach, hidePreds);
277     }
278
279     if( !hidePreds ) {
280       s += "\\n"+preds.toStringEscNewline();
281     }
282
283     if( !hideEdgeTaints ) {
284       if( !taints.isEmpty() ) {
285         s += "\\n"+taints.toStringEscNewline( hidePreds );
286       }
287     }
288
289     return s+"\",decorate"+otherAttributes+"]";
290   }
291
292   public String toString() {
293     return new String("("+src+
294                       "->"+type.toPrettyString()+
295                       " "+field+
296                       "->"+dst+")"
297                       );
298   }
299
300   public String toStringAndBeta() {
301     return toString()+beta.toString();
302   }
303 }