improve performance
[IRC.git] / Robust / src / Analysis / OwnershipAnalysis / TokenTupleSet.java
1 package Analysis.OwnershipAnalysis;
2
3 import IR.*;
4 import IR.Flat.*;
5 import java.util.*;
6 import java.io.*;
7
8
9 public class TokenTupleSet extends Canonical {
10
11   private HashSet<TokenTuple> tokenTuples;
12
13
14   public TokenTupleSet() {
15     tokenTuples = new HashSet<TokenTuple>();
16   }
17
18   public TokenTupleSet(TokenTuple tt) {
19     this();
20     assert tt != null;
21     tokenTuples.add(tt);
22   }
23
24   public TokenTupleSet(TokenTupleSet tts) {
25     assert tts != null;
26     // okay to clone, TokenTuple and TokenTupleSet should be canonical
27     tokenTuples = (HashSet<TokenTuple>)tts.tokenTuples.clone();
28   }
29
30
31   public TokenTupleSet makeCanonical() {
32     return (TokenTupleSet) Canonical.makeCanonical(this);
33   }
34
35   public Iterator iterator() {
36     return tokenTuples.iterator();
37   }
38
39   public boolean isEmpty() {
40     return tokenTuples.isEmpty();
41   }
42
43   public boolean isSubset(TokenTupleSet ttsIn) {
44     assert ttsIn != null;
45     return ttsIn.tokenTuples.containsAll(this.tokenTuples);
46   }
47
48   public boolean containsTuple(TokenTuple tt) {
49     assert tt != null;
50     return tokenTuples.contains(tt);
51   }
52
53   public boolean containsBoth(TokenTuple tt1, TokenTuple tt2) {
54     return containsTuple(tt1) && containsTuple(tt2);
55   }
56
57   public boolean containsWithZeroes(TokenTupleSet tts) {
58     assert tts != null;
59
60     // first establish that every token tuple from tts is
61     // also in this set
62     Iterator<TokenTuple> ttItrIn = tts.iterator();
63     while( ttItrIn.hasNext() ) {
64       TokenTuple ttIn   = ttItrIn.next();
65       TokenTuple ttThis = this.containsToken(ttIn.getToken() );
66
67       if( ttThis == null ) {
68         return false;
69       }
70     }    
71     
72     // then establish that anything in this set that is
73     // not in tts is a zero-arity token tuple, which is okay    
74     Iterator<TokenTuple> ttItrThis = this.iterator();
75     while( ttItrThis.hasNext() ) {
76       TokenTuple ttThis = ttItrThis.next();
77       TokenTuple ttIn   = tts.containsToken(ttThis.getToken() );
78
79       if( ttIn == null && 
80           ttThis.getArity() != TokenTuple.ARITY_ZEROORMORE ) {
81         return false;
82       }
83     }    
84
85     // if so this set contains tts with zeroes
86     return true;
87   }
88
89   public TokenTupleSet union(TokenTuple ttIn) {
90     assert ttIn != null;
91     TokenTupleSet ttsOut = new TokenTupleSet(this);
92     ttsOut.tokenTuples.add(ttIn);
93     return ttsOut.makeCanonical();
94   }
95
96   public TokenTupleSet union(TokenTupleSet ttsIn) {
97     assert ttsIn != null;
98     TokenTupleSet ttsOut = new TokenTupleSet(this);
99     ttsOut.tokenTuples.addAll(ttsIn.tokenTuples);
100     return ttsOut.makeCanonical();
101   }
102
103
104   public TokenTupleSet unionUpArity(TokenTupleSet ttsIn) {
105     assert ttsIn != null;
106     TokenTupleSet ttsOut = new TokenTupleSet();
107
108     Iterator<TokenTuple> ttItr = this.iterator();
109     while( ttItr.hasNext() ) {
110       TokenTuple ttThis = ttItr.next();
111       TokenTuple ttIn   = ttsIn.containsToken(ttThis.getToken() );
112
113       if( ttIn != null ) {
114         ttsOut.tokenTuples.add(ttThis.unionArity(ttIn) );
115       } else {
116         ttsOut.tokenTuples.add(ttThis);
117       }
118     }
119
120     ttItr = ttsIn.iterator();
121     while( ttItr.hasNext() ) {
122       TokenTuple ttIn   = ttItr.next();
123       TokenTuple ttThis = ttsOut.containsToken(ttIn.getToken() );
124
125       if( ttThis == null ) {
126         ttsOut.tokenTuples.add(ttIn);
127       }
128     }
129
130     return ttsOut.makeCanonical();
131   }
132
133
134   public TokenTupleSet add(TokenTuple tt) {
135     assert tt != null;
136     TokenTupleSet ttsOut = new TokenTupleSet(tt);
137     return ttsOut.union(this);
138   }
139
140
141   public TokenTupleSet remove(TokenTuple tt) {
142     assert tt != null;
143     TokenTupleSet ttsOut = new TokenTupleSet(this);
144     ttsOut.tokenTuples.remove(tt);
145     return ttsOut.makeCanonical();
146   }
147
148
149   public boolean equals(Object o) {
150     if( o == null ) {
151       return false;
152     }
153
154     if( !(o instanceof TokenTupleSet) ) {
155       return false;
156     }
157
158     TokenTupleSet tts = (TokenTupleSet) o;
159     return tokenTuples.equals(tts.tokenTuples);
160   }
161
162     boolean hashcodecomputed;
163     int ourhashcode;
164
165
166   public int hashCode() {
167       if (hashcodecomputed)
168           return ourhashcode;
169       else {
170           ourhashcode=tokenTuples.hashCode();
171           return ourhashcode;
172       }
173   }
174
175
176   // this should be a hash table so we can do this by key
177   public TokenTuple containsToken(Integer token) {
178     assert token != null;
179
180     Iterator itr = tokenTuples.iterator();
181     while( itr.hasNext() ) {
182       TokenTuple tt = (TokenTuple) itr.next();
183       if( token.equals(tt.getToken() ) ) {
184         return tt;
185       }
186     }
187     return null;
188   }
189
190
191   public TokenTupleSet ageTokens(AllocationSite as) {
192     assert as != null;
193
194     TokenTupleSet ttsOut = new TokenTupleSet();
195
196     TokenTuple ttSummary = null;
197     TokenTuple ttOldest  = null;
198
199     Iterator itrT = this.iterator();
200     while( itrT.hasNext() ) {
201       TokenTuple tt = (TokenTuple) itrT.next();
202
203       Integer token = tt.getToken();
204       int age = as.getAgeCategory(token);
205
206       // tokens not associated with
207       // the site should be left alone
208       if( age == AllocationSite.AGE_notInThisSite ) {
209         ttsOut.tokenTuples.add(tt);
210
211       } else if( age == AllocationSite.AGE_summary ) {
212         // remember the summary tuple, but don't add it
213         // we may combine it with the oldest tuple
214         ttSummary = tt;
215
216       } else if( age == AllocationSite.AGE_oldest ) {
217         // found an oldest token, again just remember
218         // for later
219         ttOldest = tt;
220
221       } else {
222         assert age == AllocationSite.AGE_in_I;
223
224         Integer I = as.getAge(token);
225         assert I != null;
226
227         // otherwise, we change this token to the
228         // next older token
229         Integer tokenToChangeTo = as.getIthOldest(I + 1);
230         TokenTuple ttAged       = tt.changeTokenTo(tokenToChangeTo);
231         ttsOut.tokenTuples.add(ttAged);
232       }
233     }
234
235     // there are four cases to consider here
236     // 1. we found a summary tuple and no oldest tuple
237     //    Here we just pass the summary unchanged
238     // 2. we found an oldest tuple, no summary
239     //    Make a new, arity-one summary tuple
240     // 3. we found both a summary and an oldest
241     //    Merge them by arity
242     // 4. (not handled) we found neither, do nothing
243     if       ( ttSummary != null && ttOldest == null ) {
244       ttsOut.tokenTuples.add(ttSummary);
245
246     } else if( ttSummary == null && ttOldest != null ) {
247       ttsOut.tokenTuples.add(new TokenTuple(as.getSummary(),
248                                             true,
249                                             ttOldest.getArity()
250                                             ).makeCanonical()
251                              );
252
253     } else if( ttSummary != null && ttOldest != null ) {
254       ttsOut.tokenTuples.add(ttSummary.unionArity(new TokenTuple(as.getSummary(),
255                                                                  true,
256                                                                  ttOldest.getArity()
257                                                                  ).makeCanonical()
258                                                   )
259                              );
260     }
261
262     return ttsOut.makeCanonical();
263   }
264
265
266   public TokenTupleSet unshadowTokens(AllocationSite as) {
267     assert as != null;
268
269     TokenTupleSet ttsOut = new TokenTupleSet();
270
271     TokenTuple ttSummary       = null;
272     TokenTuple ttShadowSummary = null;
273
274     Iterator itrT = this.iterator();
275     while( itrT.hasNext() ) {
276       TokenTuple tt = (TokenTuple) itrT.next();
277
278       Integer token = tt.getToken();
279       int shadowAge = as.getShadowAgeCategory(token);
280
281       if( shadowAge == AllocationSite.AGE_summary ) {
282         // remember the summary tuple, but don't add it
283         // we may combine it with the oldest tuple
284         ttSummary = tt;
285
286       } else if( shadowAge == AllocationSite.SHADOWAGE_notInThisSite ) {
287         ttsOut.tokenTuples.add(tt);
288
289       } else if( shadowAge == AllocationSite.SHADOWAGE_summary ) {
290         // found the shadow summary token, again just remember
291         // for later
292         ttShadowSummary = tt;
293
294       } else if( shadowAge == AllocationSite.SHADOWAGE_oldest ) {
295         Integer tokenToChangeTo = as.getOldest();
296         TokenTuple ttNormal = tt.changeTokenTo(tokenToChangeTo);
297         ttsOut.tokenTuples.add(ttNormal);
298
299       } else {
300         assert shadowAge == AllocationSite.SHADOWAGE_in_I;
301
302         Integer I = as.getShadowAge(token);
303         assert I != null;
304
305         Integer tokenToChangeTo = as.getIthOldest(-I);
306         TokenTuple ttNormal = tt.changeTokenTo(tokenToChangeTo);
307         ttsOut.tokenTuples.add(ttNormal);
308       }
309     }
310
311     if       ( ttSummary != null && ttShadowSummary == null ) {
312       ttsOut.tokenTuples.add(ttSummary);
313
314     } else if( ttSummary == null && ttShadowSummary != null ) {
315       ttsOut.tokenTuples.add(new TokenTuple(as.getSummary(),
316                                             true,
317                                             ttShadowSummary.getArity()
318                                             ).makeCanonical()
319                              );
320
321     } else if( ttSummary != null && ttShadowSummary != null ) {
322       ttsOut.tokenTuples.add(ttSummary.unionArity(new TokenTuple(as.getSummary(),
323                                                                  true,
324                                                                  ttShadowSummary.getArity()
325                                                                  ).makeCanonical()
326                                                   )
327                              );
328     }
329
330     return ttsOut.makeCanonical();
331   }
332
333
334   public TokenTupleSet toShadowTokens(AllocationSite as) {
335     assert as != null;
336
337     TokenTupleSet ttsOut = new TokenTupleSet().makeCanonical();
338
339     Iterator itrT = this.iterator();
340     while( itrT.hasNext() ) {
341       TokenTuple tt = (TokenTuple) itrT.next();
342
343       Integer token = tt.getToken();
344       int age = as.getAgeCategory(token);
345
346       // summary tokens and tokens not associated with
347       // the site should be left alone
348       if( age == AllocationSite.AGE_notInThisSite ) {
349         ttsOut = ttsOut.union(tt);
350
351       } else if( age == AllocationSite.AGE_summary ) {
352         ttsOut = ttsOut.union(tt.changeTokenTo(as.getSummaryShadow() ));
353
354       } else if( age == AllocationSite.AGE_oldest ) {
355         ttsOut = ttsOut.union(tt.changeTokenTo(as.getOldestShadow() ));
356
357       } else {
358         assert age == AllocationSite.AGE_in_I;
359
360         Integer I = as.getAge(token);
361         assert I != null;
362
363         ttsOut = ttsOut.union(tt.changeTokenTo(as.getIthOldestShadow(I) ));
364       }
365     }
366
367     return ttsOut.makeCanonical();
368   }
369
370
371   public ReachabilitySet rewriteToken(TokenTuple tokenToRewrite,
372                                       ReachabilitySet replacements,
373                                       boolean makeChangeSet,
374                                       Hashtable<TokenTupleSet, HashSet<TokenTupleSet> > forChangeSet) {
375
376     ReachabilitySet rsOut = new ReachabilitySet().makeCanonical();
377
378     if( !tokenTuples.contains(tokenToRewrite) ) {
379       rsOut = rsOut.add(this);
380
381     } else {
382       TokenTupleSet ttsMinusToken = new TokenTupleSet(this);
383       ttsMinusToken.tokenTuples.remove(tokenToRewrite);
384
385       Iterator<TokenTupleSet> replaceItr = replacements.iterator();
386       while( replaceItr.hasNext() ) {
387         TokenTupleSet replacement = replaceItr.next();
388         TokenTupleSet replaced = new TokenTupleSet(ttsMinusToken).makeCanonical();
389         replaced = replaced.unionUpArity(replacement);
390         rsOut = rsOut.add(replaced);
391
392         if( makeChangeSet ) {
393           assert forChangeSet != null;
394
395           if( forChangeSet.get(this) == null ) {
396             forChangeSet.put(this, new HashSet<TokenTupleSet>() );
397           }
398
399           forChangeSet.get(this).add(replaced);
400         }
401       }
402     }
403
404     return rsOut.makeCanonical();
405   }
406
407
408   public TokenTupleSet makeArityZeroOrMore() {
409     TokenTupleSet ttsOut = new TokenTupleSet().makeCanonical();
410
411     Iterator<TokenTuple> itrThis = this.iterator();
412     while( itrThis.hasNext() ) {
413       TokenTuple tt = itrThis.next();
414
415       ttsOut = ttsOut.union(new TokenTuple(tt.getToken(),
416                                            tt.isMultiObject(),
417                                            TokenTuple.ARITY_ZEROORMORE
418                                            ).makeCanonical()
419                             );
420     }
421
422     return ttsOut.makeCanonical();
423   }
424
425   public String toString() {
426     return tokenTuples.toString();
427   }
428 }