1 package Analysis.OwnershipAnalysis;
9 public class TokenTupleSet extends Canonical {
11 private HashSet<TokenTuple> tokenTuples;
14 public TokenTupleSet() {
15 tokenTuples = new HashSet<TokenTuple>();
18 public TokenTupleSet(TokenTuple tt) {
24 public TokenTupleSet(TokenTupleSet tts) {
26 // okay to clone, TokenTuple and TokenTupleSet should be canonical
27 tokenTuples = (HashSet<TokenTuple>)tts.tokenTuples.clone();
31 public TokenTupleSet makeCanonical() {
32 return (TokenTupleSet) Canonical.makeCanonical(this);
35 public Iterator iterator() {
36 return tokenTuples.iterator();
39 public boolean isEmpty() {
40 return tokenTuples.isEmpty();
43 public boolean isSubset(TokenTupleSet ttsIn) {
45 return ttsIn.tokenTuples.containsAll(this.tokenTuples);
48 public boolean containsTuple(TokenTuple tt) {
50 return tokenTuples.contains(tt);
53 public boolean containsWithZeroes(TokenTupleSet tts) {
56 // first establish that every token tuple from tts is
58 Iterator<TokenTuple> ttItrIn = tts.iterator();
59 while( ttItrIn.hasNext() ) {
60 TokenTuple ttIn = ttItrIn.next();
61 TokenTuple ttThis = this.containsToken(ttIn.getToken() );
63 if( ttThis == null ) {
68 // then establish that anything in this set that is
69 // not in tts is a zero-arity token tuple, which is okay
70 Iterator<TokenTuple> ttItrThis = this.iterator();
71 while( ttItrThis.hasNext() ) {
72 TokenTuple ttThis = ttItrThis.next();
73 TokenTuple ttIn = tts.containsToken(ttThis.getToken() );
76 ttThis.getArity() != TokenTuple.ARITY_ZEROORMORE ) {
81 // if so this set contains tts with zeroes
85 public TokenTupleSet union(TokenTuple ttIn) {
87 TokenTupleSet ttsOut = new TokenTupleSet(this);
88 ttsOut.tokenTuples.add(ttIn);
89 return ttsOut.makeCanonical();
92 public TokenTupleSet union(TokenTupleSet ttsIn) {
94 TokenTupleSet ttsOut = new TokenTupleSet(this);
95 ttsOut.tokenTuples.addAll(ttsIn.tokenTuples);
96 return ttsOut.makeCanonical();
100 public TokenTupleSet unionUpArity(TokenTupleSet ttsIn) {
101 assert ttsIn != null;
102 TokenTupleSet ttsOut = new TokenTupleSet();
104 Iterator<TokenTuple> ttItr = this.iterator();
105 while( ttItr.hasNext() ) {
106 TokenTuple ttThis = ttItr.next();
107 TokenTuple ttIn = ttsIn.containsToken(ttThis.getToken() );
110 ttsOut.tokenTuples.add(ttThis.unionArity(ttIn) );
112 ttsOut.tokenTuples.add(ttThis);
116 ttItr = ttsIn.iterator();
117 while( ttItr.hasNext() ) {
118 TokenTuple ttIn = ttItr.next();
119 TokenTuple ttThis = ttsOut.containsToken(ttIn.getToken() );
121 if( ttThis == null ) {
122 ttsOut.tokenTuples.add(ttIn);
126 return ttsOut.makeCanonical();
130 public TokenTupleSet add(TokenTuple tt) {
132 TokenTupleSet ttsOut = new TokenTupleSet(tt);
133 return ttsOut.union(this);
137 public boolean equals(Object o) {
142 if( !(o instanceof TokenTupleSet) ) {
146 TokenTupleSet tts = (TokenTupleSet) o;
147 return tokenTuples.equals(tts.tokenTuples);
152 private boolean oldHashSet = false;
153 private int oldHash = 0;
154 public int hashCode() {
155 int currentHash = tokenTuples.hashCode();
157 if( oldHashSet == false ) {
158 oldHash = currentHash;
161 if( oldHash != currentHash ) {
162 System.out.println("IF YOU SEE THIS A CANONICAL TokenTupleSet CHANGED");
172 // this should be a hash table so we can do this by key
173 public TokenTuple containsToken(Integer token) {
174 assert token != null;
176 Iterator itr = tokenTuples.iterator();
177 while( itr.hasNext() ) {
178 TokenTuple tt = (TokenTuple) itr.next();
179 if( token.equals(tt.getToken() ) ) {
187 public TokenTupleSet ageTokens(AllocationSite as) {
190 TokenTupleSet ttsOut = new TokenTupleSet();
192 TokenTuple ttSummary = null;
193 TokenTuple ttOldest = null;
195 Iterator itrT = this.iterator();
196 while( itrT.hasNext() ) {
197 TokenTuple tt = (TokenTuple) itrT.next();
199 Integer token = tt.getToken();
200 int age = as.getAgeCategory(token);
202 // tokens not associated with
203 // the site should be left alone
204 if( age == AllocationSite.AGE_notInThisSite ) {
205 ttsOut.tokenTuples.add(tt);
207 } else if( age == AllocationSite.AGE_summary ) {
208 // remember the summary tuple, but don't add it
209 // we may combine it with the oldest tuple
212 } else if( age == AllocationSite.AGE_oldest ) {
213 // found an oldest token, again just remember
218 assert age == AllocationSite.AGE_in_I;
220 Integer I = as.getAge(token);
223 // otherwise, we change this token to the
225 Integer tokenToChangeTo = as.getIthOldest(I + 1);
226 TokenTuple ttAged = tt.changeTokenTo(tokenToChangeTo);
227 ttsOut.tokenTuples.add(ttAged);
231 // there are four cases to consider here
232 // 1. we found a summary tuple and no oldest tuple
233 // Here we just pass the summary unchanged
234 // 2. we found an oldest tuple, no summary
235 // Make a new, arity-one summary tuple
236 // 3. we found both a summary and an oldest
237 // Merge them by arity
238 // 4. (not handled) we found neither, do nothing
239 if ( ttSummary != null && ttOldest == null ) {
240 ttsOut.tokenTuples.add(ttSummary);
242 } else if( ttSummary == null && ttOldest != null ) {
243 ttsOut.tokenTuples.add(new TokenTuple(as.getSummary(),
249 } else if( ttSummary != null && ttOldest != null ) {
250 ttsOut.tokenTuples.add(ttSummary.unionArity(new TokenTuple(as.getSummary(),
258 return ttsOut.makeCanonical();
262 public TokenTupleSet unshadowTokens(AllocationSite as) {
265 TokenTupleSet ttsOut = new TokenTupleSet();
267 TokenTuple ttSummary = null;
268 TokenTuple ttShadowSummary = null;
270 Iterator itrT = this.iterator();
271 while( itrT.hasNext() ) {
272 TokenTuple tt = (TokenTuple) itrT.next();
274 Integer token = tt.getToken();
275 int shadowAge = as.getShadowAgeCategory(token);
277 if( shadowAge == AllocationSite.AGE_summary ) {
278 // remember the summary tuple, but don't add it
279 // we may combine it with the oldest tuple
282 } else if( shadowAge == AllocationSite.SHADOWAGE_notInThisSite ) {
283 ttsOut.tokenTuples.add(tt);
285 } else if( shadowAge == AllocationSite.SHADOWAGE_summary ) {
286 // found the shadow summary token, again just remember
288 ttShadowSummary = tt;
290 } else if( shadowAge == AllocationSite.SHADOWAGE_oldest ) {
291 Integer tokenToChangeTo = as.getOldest();
292 TokenTuple ttNormal = tt.changeTokenTo(tokenToChangeTo);
293 ttsOut.tokenTuples.add(ttNormal);
296 assert shadowAge == AllocationSite.SHADOWAGE_in_I;
298 Integer I = as.getShadowAge(token);
301 Integer tokenToChangeTo = as.getIthOldest(-I);
302 TokenTuple ttNormal = tt.changeTokenTo(tokenToChangeTo);
303 ttsOut.tokenTuples.add(ttNormal);
307 if ( ttSummary != null && ttShadowSummary == null ) {
308 ttsOut.tokenTuples.add(ttSummary);
310 } else if( ttSummary == null && ttShadowSummary != null ) {
311 ttsOut.tokenTuples.add(new TokenTuple(as.getSummary(),
313 ttShadowSummary.getArity()
317 } else if( ttSummary != null && ttShadowSummary != null ) {
318 ttsOut.tokenTuples.add(ttSummary.unionArity(new TokenTuple(as.getSummary(),
320 ttShadowSummary.getArity()
326 return ttsOut.makeCanonical();
330 public TokenTupleSet toShadowTokens(AllocationSite as) {
333 TokenTupleSet ttsOut = new TokenTupleSet().makeCanonical();
335 Iterator itrT = this.iterator();
336 while( itrT.hasNext() ) {
337 TokenTuple tt = (TokenTuple) itrT.next();
339 Integer token = tt.getToken();
340 int age = as.getAgeCategory(token);
342 // summary tokens and tokens not associated with
343 // the site should be left alone
344 if( age == AllocationSite.AGE_notInThisSite ) {
345 ttsOut = ttsOut.union(tt);
347 } else if( age == AllocationSite.AGE_summary ) {
348 ttsOut = ttsOut.union(tt.changeTokenTo(as.getSummaryShadow() ));
350 } else if( age == AllocationSite.AGE_oldest ) {
351 ttsOut = ttsOut.union(tt.changeTokenTo(as.getOldestShadow() ));
354 assert age == AllocationSite.AGE_in_I;
356 Integer I = as.getAge(token);
359 ttsOut = ttsOut.union(tt.changeTokenTo(as.getIthOldestShadow(I) ));
363 return ttsOut.makeCanonical();
367 public ReachabilitySet rewriteToken(TokenTuple tokenToRewrite,
368 ReachabilitySet replacements,
369 boolean makeChangeSet,
370 Hashtable<TokenTupleSet, HashSet<TokenTupleSet> > forChangeSet) {
372 ReachabilitySet rsOut = new ReachabilitySet().makeCanonical();
374 if( !tokenTuples.contains(tokenToRewrite) ) {
375 rsOut = rsOut.add(this);
378 TokenTupleSet ttsMinusToken = new TokenTupleSet(this);
379 ttsMinusToken.tokenTuples.remove(tokenToRewrite);
381 Iterator<TokenTupleSet> replaceItr = replacements.iterator();
382 while( replaceItr.hasNext() ) {
383 TokenTupleSet replacement = replaceItr.next();
384 TokenTupleSet replaced = new TokenTupleSet(ttsMinusToken).makeCanonical();
385 replaced = replaced.unionUpArity(replacement);
386 rsOut = rsOut.add(replaced);
388 if( makeChangeSet ) {
389 assert forChangeSet != null;
391 if( forChangeSet.get(this) == null ) {
392 forChangeSet.put(this, new HashSet<TokenTupleSet>() );
395 forChangeSet.get(this).add(replaced);
400 return rsOut.makeCanonical();
404 public TokenTupleSet makeArityZeroOrMore() {
405 TokenTupleSet ttsOut = new TokenTupleSet().makeCanonical();
407 Iterator<TokenTuple> itrThis = this.iterator();
408 while( itrThis.hasNext() ) {
409 TokenTuple tt = itrThis.next();
411 ttsOut = ttsOut.union(new TokenTuple(tt.getToken(),
413 TokenTuple.ARITY_ZEROORMORE
418 return ttsOut.makeCanonical();
421 public String toString() {
422 return tokenTuples.toString();