add lookup tables for effects
[IRC.git] / Robust / src / Analysis / OoOJava / VarSrcTokTable.java
1 package Analysis.OoOJava;
2
3 import IR.*;
4 import IR.Flat.*;
5 import java.util.*;
6 import java.io.*;
7
8 // This class formerly had lazy consistency properties, but
9 // it is being changed so that the full set and the extra
10 // hash tables to access the full set efficiently by different
11 // elements will be consistent after EVERY operation.  Also,
12 // a consistent assert method allows a debugger to ask whether
13 // an operation has produced an inconsistent VarSrcTokTable.
14
15 // in an effort to make sure operations keep the table consistent,
16 // all public methods that are also used by other methods for
17 // intermediate results (add and remove are used in other methods)
18 // there should be a public version that calls the private version
19 // so consistency is checked after public ops, but not private ops
20 public class VarSrcTokTable {
21
22   // a set of every token in the table
23   private HashSet<VariableSourceToken> trueSet;
24
25   // these hashtables provide an efficient retreival from the true set
26   private Hashtable< TempDescriptor,    Set<VariableSourceToken> >  var2vst;
27   private Hashtable< FlatSESEEnterNode, Set<VariableSourceToken> > sese2vst;
28   private Hashtable< SVKey,             Set<VariableSourceToken> >   sv2vst;
29
30   // maximum age from aging operation
31   private static final Integer MAX_AGE = new Integer( 2 );
32   
33   public static final Integer SrcType_READY   = new Integer( 34 );
34   public static final Integer SrcType_STATIC  = new Integer( 35 );
35   public static final Integer SrcType_DYNAMIC = new Integer( 36 );
36
37   public static RBlockRelationAnalysis rblockRel;
38
39
40
41   public VarSrcTokTable() {
42     trueSet  = new HashSet<VariableSourceToken>();
43
44     sese2vst = new Hashtable< FlatSESEEnterNode, Set<VariableSourceToken> >();
45     var2vst  = new Hashtable< TempDescriptor,    Set<VariableSourceToken> >();
46     sv2vst   = new Hashtable< SVKey,             Set<VariableSourceToken> >();
47
48     assertConsistency();
49   }
50
51
52   // make a deep copy of the in table
53   public VarSrcTokTable( VarSrcTokTable in ) {
54     this();
55     merge( in );
56     assertConsistency();
57   }
58
59
60   public void add( VariableSourceToken vst ) {
61     addPrivate( vst );
62     assertConsistency();
63   }
64
65   private void addPrivate( VariableSourceToken vst ) {
66
67     // make sure we aren't clobbering anything!
68     if( trueSet.contains( vst ) ) {
69       // if something with the same hashcode is in the true set, they might
70       // have different reference variable sets because that set is not considered
71       // in a token's equality, so make sure we smooth that out right here
72       Iterator<VariableSourceToken> vstItr = trueSet.iterator();
73       while( vstItr.hasNext() ) {
74         VariableSourceToken vstAlready = vstItr.next();
75
76         if( vstAlready.equals( vst ) ) {    
77
78           // take out the one that is in (we dont' want collisions in
79           // any of the other hash map sets either)
80           removePrivate( vstAlready );
81
82           // combine reference variable sets
83           vst.getRefVars().addAll( vstAlready.getRefVars() );
84
85           // now jump back as we are adding in a brand new token
86           break;
87         }
88       }
89     }
90
91     trueSet.add( vst );
92
93     Set<VariableSourceToken> s;
94
95     s = sese2vst.get( vst.getSESE() );
96     if( s == null ) {
97       s = new HashSet<VariableSourceToken>();
98     }
99     s.add( vst );
100     sese2vst.put( vst.getSESE(), s );
101
102     Iterator<TempDescriptor> refVarItr = vst.getRefVars().iterator();
103     while( refVarItr.hasNext() ) {
104       TempDescriptor refVar = refVarItr.next();
105       s = var2vst.get( refVar );
106       if( s == null ) {
107         s = new HashSet<VariableSourceToken>();
108       }
109       s.add( vst );
110       var2vst.put( refVar, s );
111
112       SVKey key = new SVKey( vst.getSESE(), refVar );
113       s = sv2vst.get( key );
114       if( s == null ) {
115         s = new HashSet<VariableSourceToken>();
116       }
117       s.add( vst );
118       sv2vst.put( key, s );
119     }
120   }
121
122   public void addAll( Set<VariableSourceToken> s ) {
123     Iterator<VariableSourceToken> itr = s.iterator();
124     while( itr.hasNext() ) {
125       addPrivate( itr.next() );
126     }
127     assertConsistency();
128   }
129
130
131   public Set<VariableSourceToken> get() {
132     return trueSet;
133   }
134
135   public Set<VariableSourceToken> get( FlatSESEEnterNode sese ) {
136     Set<VariableSourceToken> s = sese2vst.get( sese );
137     if( s == null ) {
138       s = new HashSet<VariableSourceToken>();      
139       sese2vst.put( sese, s );
140     }
141     return s;
142   }
143
144   public Set<VariableSourceToken> get( TempDescriptor refVar ) {
145     Set<VariableSourceToken> s = var2vst.get( refVar );
146     if( s == null ) {
147       s = new HashSet<VariableSourceToken>();
148       var2vst.put( refVar, s );
149     }
150     return s;
151   }
152
153   public Set<VariableSourceToken> get( FlatSESEEnterNode sese,
154                                        TempDescriptor    refVar ) {
155     SVKey key = new SVKey( sese, refVar );
156     Set<VariableSourceToken> s = sv2vst.get( key );
157     if( s == null ) {
158       s = new HashSet<VariableSourceToken>();
159       sv2vst.put( key, s );
160     }
161     return s;
162   }
163
164   public Set<VariableSourceToken> get( FlatSESEEnterNode sese,
165                                        Integer           age ) {
166
167     HashSet<VariableSourceToken> s0 = (HashSet<VariableSourceToken>) sese2vst.get( sese );
168     if( s0 == null ) {
169       s0 = new HashSet<VariableSourceToken>();      
170       sese2vst.put( sese, s0 );
171     }
172
173     Set<VariableSourceToken> s = (Set<VariableSourceToken>) s0.clone();
174     Iterator<VariableSourceToken> sItr = s.iterator();
175     while( sItr.hasNext() ) {
176       VariableSourceToken vst = sItr.next();
177       if( !vst.getAge().equals( age ) ) {
178         s.remove( vst );
179       }
180     }
181
182     return s;
183   }
184
185
186   // merge now makes a deep copy of incoming stuff because tokens may
187   // be modified (reference var sets) by later ops that change more
188   // than one table, causing inconsistency
189   public void merge( VarSrcTokTable in ) {
190
191     if( in == null ) {
192       return;
193     }
194
195     Iterator<VariableSourceToken> vstItr = in.trueSet.iterator();
196     while( vstItr.hasNext() ) {
197       VariableSourceToken vst = vstItr.next();
198       this.addPrivate( vst.copy() );
199     }
200
201     assertConsistency();
202   }
203
204
205   // remove operations must leave the trueSet 
206   // and the hash maps consistent
207   public void remove( VariableSourceToken vst ) {
208     removePrivate( vst );
209     assertConsistency();
210   }
211
212   private void removePrivate( VariableSourceToken vst ) {
213     trueSet.remove( vst );
214     
215     Set<VariableSourceToken> s;
216
217     s = get( vst.getSESE() );
218     if( s != null ) { s.remove( vst ); }
219
220     Iterator<TempDescriptor> refVarItr = vst.getRefVars().iterator();
221     while( refVarItr.hasNext() ) {
222       TempDescriptor refVar = refVarItr.next();
223
224       s = get( refVar );
225       if( s != null ) { 
226         s.remove( vst );
227         if( s.isEmpty() ) {
228           var2vst.remove( refVar );
229         }
230       }
231       
232       s = get( vst.getSESE(), refVar );
233       if( s != null ) { 
234         s.remove( vst );
235         if( s.isEmpty() ) {
236           sv2vst.remove( new SVKey( vst.getSESE(), refVar ) );
237         }
238       }
239     }
240   }
241
242
243   public void remove( FlatSESEEnterNode sese ) {
244     removePrivate( sese );
245     assertConsistency();
246   }
247
248   public void removePrivate( FlatSESEEnterNode sese ) {
249     Set<VariableSourceToken> s = sese2vst.get( sese );
250     if( s == null ) {
251       return;
252     }
253
254     Iterator<VariableSourceToken> itr = s.iterator();
255     while( itr.hasNext() ) {
256       VariableSourceToken vst = itr.next();
257       removePrivate( vst );
258     }
259
260     sese2vst.remove( sese );
261   }
262
263
264   public void remove( TempDescriptor refVar ) {
265     removePrivate( refVar );
266     assertConsistency();
267   }
268
269   private void removePrivate( TempDescriptor refVar ) {
270     Set<VariableSourceToken> s = var2vst.get( refVar );
271     if( s == null ) {
272       return;
273     }
274     
275     Set<VariableSourceToken> forRemoval = new HashSet<VariableSourceToken>();
276
277     // iterate over tokens that this temp can reference, make a set
278     // of tokens that need this temp stripped out of them
279     Iterator<VariableSourceToken> itr = s.iterator();
280     while( itr.hasNext() ) {
281       VariableSourceToken vst = itr.next();
282       Set<TempDescriptor> refVars = vst.getRefVars();
283       assert refVars.contains( refVar );
284       forRemoval.add( vst );
285     }
286
287     itr = forRemoval.iterator();
288     while( itr.hasNext() ) {
289
290       // here's a token marked for removal
291       VariableSourceToken vst = itr.next();
292       Set<TempDescriptor> refVars = vst.getRefVars();
293
294       // if there was only one one variable
295       // referencing this token, just take it
296       // out of the table all together
297       if( refVars.size() == 1 ) {
298         removePrivate( vst );
299       }
300
301       sv2vst.remove( new SVKey( vst.getSESE(), refVar ) );
302
303       refVars.remove( refVar );      
304     }
305
306     var2vst.remove( refVar );    
307   }
308
309
310   public void remove( FlatSESEEnterNode sese,
311                       TempDescriptor    var  ) {
312
313     // don't seem to need this, don't bother maintaining
314     // until its clear we need it
315     assert false;
316   }
317
318
319   // age tokens with respect to SESE curr, where
320   // any curr tokens increase age by 1
321   public void age( FlatSESEEnterNode curr ) {
322
323     Set<VariableSourceToken> forRemoval =
324       new HashSet<VariableSourceToken>();
325
326     Set<VariableSourceToken> forAddition =
327       new HashSet<VariableSourceToken>();
328
329     Iterator<VariableSourceToken> itr = trueSet.iterator();
330     while( itr.hasNext() ) {
331       VariableSourceToken vst = itr.next();
332
333       if( vst.getSESE().equals( curr ) ) {
334
335         // only age if the token isn't already the maximum age
336         if( vst.getAge() < MAX_AGE ) {
337         
338           forRemoval.add( vst );
339
340           forAddition.add( new VariableSourceToken( vst.getRefVars(), 
341                                                     curr,                                           
342                                                     vst.getAge() + 1,
343                                                     vst.getAddrVar()
344                                                     )
345                            );
346         }
347       } 
348     }
349     
350     itr = forRemoval.iterator();
351     while( itr.hasNext() ) {
352       VariableSourceToken vst = itr.next();
353       remove( vst );
354     }
355     
356     itr = forRemoval.iterator();
357     while( itr.hasNext() ) {
358       VariableSourceToken vst = itr.next();
359       add( vst );
360     }
361
362     assertConsistency();
363   }
364
365
366   // at an SESE enter node, all ref vars in the SESE's in-set will
367   // be copied into the SESE's local scope, change source to itself
368   public void ownInSet( FlatSESEEnterNode curr ) {
369     Iterator<TempDescriptor> inVarItr = curr.getInVarSet().iterator();
370     while( inVarItr.hasNext() ) {
371       TempDescriptor inVar = inVarItr.next();
372
373       remove( inVar );
374       assertConsistency();
375
376       Set<TempDescriptor> refVars = new HashSet<TempDescriptor>();
377       refVars.add( inVar );
378       add( new VariableSourceToken( refVars,
379                                     curr,
380                                     new Integer( 0 ),
381                                     inVar
382                                     )
383            );
384       assertConsistency();
385     }
386   }
387
388   
389   // for the given SESE, change child tokens into this parent
390   public void remapChildTokens( FlatSESEEnterNode curr ) {
391
392     Iterator<FlatSESEEnterNode> childItr = curr.getLocalChildren().iterator();
393     if( childItr.hasNext() ) {
394       FlatSESEEnterNode child = childItr.next();
395       
396       // set of VSTs for removal
397       HashSet<VariableSourceToken> removalSet=new HashSet<VariableSourceToken>();
398       // set of VSTs for additon
399       HashSet<VariableSourceToken> additionSet=new HashSet<VariableSourceToken>();
400       
401       Iterator<VariableSourceToken> vstItr = get( child ).iterator();
402       while( vstItr.hasNext() ) {
403         VariableSourceToken vst = vstItr.next();
404         removalSet.add(vst);
405         additionSet.add(new VariableSourceToken( vst.getRefVars(),
406                               curr,
407                               new Integer( 0 ),
408                               vst.getAddrVar()
409                                   ));
410       }
411       
412       // remove( eah item in forremoval )
413       vstItr = removalSet.iterator();
414       while( vstItr.hasNext() ) {
415         VariableSourceToken vst = vstItr.next();
416         remove( vst );
417       }
418       // add( each  ite inm for additon _
419       vstItr = additionSet.iterator();
420       while( vstItr.hasNext() ) {
421         VariableSourceToken vst = vstItr.next();
422         add( vst );
423       }
424     }
425
426     assertConsistency();
427   }   
428   
429
430   // this method is called at the SESE exit of SESE 'curr'
431   // if the sources for a variable written by curr can also
432   // come from curr's parent or curr's siblings then we're not
433   // sure that curr will actually modify the variable.  There are
434   // many ways to handle this, but for now, mark the variable as
435   // virtually read so curr insists on having ownership of it
436   // whether it ends up writing to it or not.  It will always, then,
437   // appear in curr's out-set.
438   public Set<TempDescriptor>
439     calcVirtReadsAndPruneParentAndSiblingTokens( FlatSESEEnterNode   exiter,
440                                                  Set<TempDescriptor> liveVars ) {
441
442     Set<TempDescriptor> virtReadSet = new HashSet<TempDescriptor>();
443
444     // this calculation is unneeded for the main task, just return an
445     // empty set of virtual reads
446     if( rblockRel.getMainSESE() == exiter ) {
447       return virtReadSet;
448     }
449
450     // who are the parent and siblings?
451     Set<FlatSESEEnterNode> alternateSESEs = new HashSet<FlatSESEEnterNode>();
452     Iterator<FlatSESEEnterNode> childItr;
453
454     FlatSESEEnterNode parent = exiter.getLocalParent();
455
456     if( parent == null ) {
457       // when some caller task is the exiter's parent, the siblings
458       // of the exiter are other local root tasks
459       parent = rblockRel.getCallerProxySESE();      
460       childItr = rblockRel.getLocalRootSESEs( exiter.getfmEnclosing() ).iterator();
461       
462     } else {
463       // otherwise, the siblings are locally-defined
464       childItr = parent.getLocalChildren().iterator();
465     }
466
467     alternateSESEs.add( parent );
468     while( childItr.hasNext() ) {
469       FlatSESEEnterNode sibling = childItr.next();      
470       if( !sibling.equals( exiter ) ) {
471         alternateSESEs.add( sibling );
472       }
473     }
474
475
476     
477     // VSTs to remove if they are alternate sources for exiter VSTs
478     // whose variables will become virtual reads
479     Set<VariableSourceToken> forRemoval = new HashSet<VariableSourceToken>();
480
481     // look at all of this SESE's VSTs at exit...
482     Iterator<VariableSourceToken> vstItr = get( exiter ).iterator();
483     while( vstItr.hasNext() ) {
484       VariableSourceToken vstExiterSrc = vstItr.next();
485
486       // only interested in tokens that come from our current instance
487       if( vstExiterSrc.getAge() != 0 ) {
488         continue;
489       }
490
491       // for each variable that might come from those sources...
492       Iterator<TempDescriptor> refVarItr = vstExiterSrc.getRefVars().iterator();
493       while( refVarItr.hasNext() ) {
494         TempDescriptor refVar = refVarItr.next();
495
496         // only matters for live variables at SESE exit program point
497         if( !liveVars.contains( refVar ) ) {
498           continue;
499         }
500
501         // examine other sources for a variable...
502         Iterator<VariableSourceToken> srcItr = get( refVar ).iterator();
503         while( srcItr.hasNext() ) {
504           VariableSourceToken vstPossibleOtherSrc = srcItr.next();
505
506           if( vstPossibleOtherSrc.getSESE().equals( exiter ) &&
507               vstPossibleOtherSrc.getAge() > 0 
508             ) {
509             // this is an alternate source if its 
510             // an older instance of this SESE               
511             virtReadSet.add( refVar );
512             forRemoval.add( vstPossibleOtherSrc );
513             
514           } else if( alternateSESEs.contains( vstPossibleOtherSrc.getSESE() ) ) {
515             // this is an alternate source from parent or sibling
516             virtReadSet.add( refVar );
517             forRemoval.add( vstPossibleOtherSrc );  
518
519           } else {
520             if( !vstPossibleOtherSrc.getSESE().equals( exiter ) ||
521                 !vstPossibleOtherSrc.getAge().equals( 0 )
522                 ) {
523               System.out.println( "For refVar="+refVar+" at exit of "+exiter+
524                                   ", unexpected possible variable source "+vstPossibleOtherSrc );
525               assert false;
526             }
527           }
528         }
529       }
530     }
531
532     vstItr = forRemoval.iterator();
533     while( vstItr.hasNext() ) {
534       VariableSourceToken vst = vstItr.next();
535       remove( vst );
536     }
537     assertConsistency();
538     
539     return virtReadSet;
540   }
541   
542
543   // given a table from a subsequent program point, decide
544   // which variables are going from a non-dynamic to a
545   // dynamic source and return them
546   public Hashtable<TempDescriptor, VSTWrapper> 
547     getReadyOrStatic2DynamicSet( VarSrcTokTable nextTable,
548                                  Set<TempDescriptor> nextLiveIn,
549                                  FlatSESEEnterNode current
550                                  ) {
551     
552     Hashtable<TempDescriptor, VSTWrapper> out = 
553       new Hashtable<TempDescriptor, VSTWrapper>();
554     
555     Iterator itr = var2vst.entrySet().iterator();
556     while( itr.hasNext() ) {
557       Map.Entry                    me  = (Map.Entry)                    itr.next();
558       TempDescriptor               var = (TempDescriptor)               me.getKey();
559       HashSet<VariableSourceToken> s1  = (HashSet<VariableSourceToken>) me.getValue();      
560
561       // only worth tracking if live
562       if( nextLiveIn.contains( var ) ) {
563         
564         VSTWrapper vstIfStaticBefore = new VSTWrapper();
565         VSTWrapper vstIfStaticAfter  = new VSTWrapper();
566
567         Integer srcTypeBefore =      this.getRefVarSrcType( var, current, vstIfStaticBefore );
568         Integer srcTypeAfter  = nextTable.getRefVarSrcType( var, current, vstIfStaticAfter  );
569
570         if( !srcTypeBefore.equals( SrcType_DYNAMIC ) &&
571               srcTypeAfter.equals( SrcType_DYNAMIC )       
572           ) {
573           // remember the variable and a source
574           // it had before crossing the transition
575           // 1) if it was ready, vstIfStatic.vst is null
576           // 2) if is was static, use vstIfStatic.vst
577           out.put( var, vstIfStaticBefore );
578         }
579       }
580     }
581
582     return out;
583   }
584
585
586   // for some reference variable, return the type of source
587   // it might have in this table, which might be:
588   // 1. Ready -- this variable is
589   //      definitely available when you are issued.
590   // 2. Static -- there is definitely one child SESE with
591   //      a known age that will produce the value
592   // 3. Dynamic -- we don't know where the value will come
593   //      from statically, so we'll track it dynamically
594   public Integer getRefVarSrcType( TempDescriptor    refVar,
595                                    FlatSESEEnterNode currentSESE,
596                                    VSTWrapper        vstIfStatic ) {
597     assert refVar      != null;
598     assert vstIfStatic != null;
599
600     vstIfStatic.vst = null;
601    
602     // when the current SESE is null, that simply means it is
603     // an unknown placeholder, in which case the system will
604     // ensure that any variables are READY
605     if( currentSESE == null ) {
606       return SrcType_READY;
607     }
608
609     // if there appear to be no sources, it means this variable
610     // comes from outside of any statically-known SESE scope,
611     // which means the system guarantees its READY, so jump over
612     // while loop
613     Set<VariableSourceToken>      srcs    = get( refVar );
614     Iterator<VariableSourceToken> itrSrcs = srcs.iterator();
615     while( itrSrcs.hasNext() ) {
616       VariableSourceToken vst = itrSrcs.next();
617
618       // to make the refVar non-READY we have to find at least
619       // one child token, there are two cases
620       //  1. if the current task invoked the local method context,
621       //     its children are the locally-defined root tasks
622       boolean case1 = 
623         currentSESE.getIsCallerProxySESE() &&
624         rblockRel.getLocalRootSESEs().contains( vst.getSESE() );
625
626       //  2. if the child task is a locally-defined child of the current task
627       boolean case2 = currentSESE.getLocalChildren().contains( vst.getSESE() );
628             
629       if( case1 || case2 ) {
630       
631         // if we ever have at least one child source with an
632         // unknown age, have to treat var as dynamic
633         if( vst.getAge().equals( OoOJavaAnalysis.maxSESEage ) ) {
634           return SrcType_DYNAMIC;
635         }
636
637         // if we have a known-age child source, this var is
638         // either static or dynamic now: it's static if this
639         // source is the only source, otherwise dynamic
640         if( srcs.size() > 1 ) {
641           return SrcType_DYNAMIC;
642         }
643         
644         vstIfStatic.vst = vst;
645         return SrcType_STATIC;
646       }
647     }
648
649     // if we never found a child source, all other
650     // sources must be READY before we could even
651     // begin executing!
652     return SrcType_READY;
653   }
654
655
656   // any reference variables that are not live can be pruned
657   // from the table, and if any VSTs are then no longer 
658   // referenced, they can be dropped as well
659   // THIS CAUSES INCONSISTENCY, FIX LATER, NOT REQUIRED
660   public void pruneByLiveness( Set<TempDescriptor> rootLiveSet ) {
661     
662     // the set of reference variables in the table minus the
663     // live set gives the set of reference variables to remove
664     Set<TempDescriptor> deadRefVars = new HashSet<TempDescriptor>();
665     deadRefVars.addAll( var2vst.keySet() );
666
667     if( rootLiveSet != null ) {
668       deadRefVars.removeAll( rootLiveSet );
669     }
670
671     // just use the remove operation to prune the table now
672     Iterator<TempDescriptor> deadItr = deadRefVars.iterator();
673     while( deadItr.hasNext() ) {
674       TempDescriptor dead = deadItr.next();
675       removePrivate( dead );
676     }
677
678     assertConsistency();
679   }
680  
681
682
683   // use as an aid for debugging, where true-set is checked
684   // against the alternate mappings: assert that nothing is
685   // missing or extra in the alternates
686   public void assertConsistency() {
687
688     Iterator itr; 
689     Set s;
690
691     Set<VariableSourceToken> trueSetByAlts = new HashSet<VariableSourceToken>();
692     itr = sese2vst.entrySet().iterator();
693     while( itr.hasNext() ) {
694       Map.Entry                    me   = (Map.Entry)                    itr.next();
695       FlatSESEEnterNode            sese = (FlatSESEEnterNode)            me.getKey();
696       HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
697       assert s1 != null;
698       
699       // the trueSet should have all entries in s1
700       assert trueSet.containsAll( s1 );
701
702       // s1 should not have anything that doesn't appear in trueset
703       Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
704       sInt.removeAll( trueSet );
705
706       assert sInt.isEmpty();
707
708       // add s1 to a running union--at the end check if trueSet has extra
709       trueSetByAlts.addAll( s1 );
710     }
711     // make sure trueSet isn't too big
712     assert trueSetByAlts.containsAll( trueSet );
713
714
715     trueSetByAlts = new HashSet<VariableSourceToken>();
716     itr = var2vst.entrySet().iterator();
717     while( itr.hasNext() ) {
718       Map.Entry                    me   = (Map.Entry)                    itr.next();
719       TempDescriptor               var  = (TempDescriptor)               me.getKey();
720       HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
721       assert s1 != null;
722       
723       // the trueSet should have all entries in s1
724       assert trueSet.containsAll( s1 );
725
726       // s1 should not have anything that doesn't appear in trueset
727       Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
728       sInt.removeAll( trueSet );
729
730       assert sInt.isEmpty();
731
732       // add s1 to a running union--at the end check if trueSet has extra
733       trueSetByAlts.addAll( s1 );
734     }
735     // make sure trueSet isn't too big
736     assert trueSetByAlts.containsAll( trueSet );
737
738
739     trueSetByAlts = new HashSet<VariableSourceToken>();
740     itr = sv2vst.entrySet().iterator();
741     while( itr.hasNext() ) {
742       Map.Entry                    me   = (Map.Entry)                    itr.next();
743       SVKey                        key  = (SVKey)                        me.getKey();
744       HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
745       assert s1 != null;
746       
747       // the trueSet should have all entries in s1
748       assert trueSet.containsAll( s1 );
749
750       // s1 should not have anything that doesn't appear in trueset
751       Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
752       sInt.removeAll( trueSet );
753
754       assert sInt.isEmpty();
755
756       // add s1 to a running union--at the end check if trueSet has extra
757       trueSetByAlts.addAll( s1 );
758     }
759     // make sure trueSet isn't too big
760     assert trueSetByAlts.containsAll( trueSet );
761
762
763     // also check that the reference var sets are consistent
764     Hashtable<VariableSourceToken, Set<TempDescriptor> > vst2refVars =
765       new Hashtable<VariableSourceToken, Set<TempDescriptor> >();
766     itr = var2vst.entrySet().iterator();
767     while( itr.hasNext() ) {
768       Map.Entry                     me     = (Map.Entry)                    itr.next();
769       TempDescriptor                refVar = (TempDescriptor)               me.getKey();
770       HashSet<VariableSourceToken>  s1     = (HashSet<VariableSourceToken>) me.getValue();      
771       Iterator<VariableSourceToken> vstItr = s1.iterator();
772       while( vstItr.hasNext() ) {
773         VariableSourceToken vst = vstItr.next();
774         assert vst.getRefVars().contains( refVar );
775
776         Set<TempDescriptor> refVarsPart = vst2refVars.get( vst );
777         if( refVarsPart == null ) {
778           refVarsPart = new HashSet<TempDescriptor>();
779         }
780         refVarsPart.add( refVar );
781         vst2refVars.put( vst, refVarsPart );
782       }
783     }
784     itr = vst2refVars.entrySet().iterator();
785     while( itr.hasNext() ) {
786       Map.Entry           me  = (Map.Entry)           itr.next();
787       VariableSourceToken vst = (VariableSourceToken) me.getKey();
788       Set<TempDescriptor> s1  = (Set<TempDescriptor>) me.getValue();
789
790       assert vst.getRefVars().equals( s1 );
791     }    
792   }
793
794
795   public boolean equals( Object o ) {
796     if( o == null ) {
797       return false;
798     }
799
800     if( !(o instanceof VarSrcTokTable) ) {
801       return false;
802     }
803
804     VarSrcTokTable table = (VarSrcTokTable) o;
805     return trueSet.equals( table.trueSet );
806   }
807
808   public int hashCode() {
809     return trueSet.hashCode();
810   }
811
812   public Iterator<VariableSourceToken> iterator() {
813     return trueSet.iterator();
814   }
815
816   public String toString() {
817     return toStringPretty();
818   }
819
820   public String toStringVerbose() {
821     return "trueSet ="+trueSet.toString()+"\n"+
822            "sese2vst="+sese2vst.toString()+"\n"+
823            "var2vst ="+var2vst.toString()+"\n"+
824            "sv2vst  ="+sv2vst.toString();
825   }
826
827   public String toStringPretty() {
828     String tokHighlighter = "o";
829
830     String str = "VarSrcTokTable\n";
831     Iterator<VariableSourceToken> vstItr = trueSet.iterator();    
832     while( vstItr.hasNext() ) {
833       str += "   "+tokHighlighter+" "+vstItr.next()+"\n";
834     }
835     return str;
836   }
837
838   public String toStringPrettyVerbose() {
839     String tokHighlighter = "o";
840
841     String str = "VarSrcTokTable\n";
842
843     Set s;
844     Iterator itr; 
845     Iterator<VariableSourceToken> vstItr;
846
847     str += "  trueSet\n";
848     vstItr = trueSet.iterator();    
849     while( vstItr.hasNext() ) {
850       str += "     "+tokHighlighter+" "+vstItr.next()+"\n";
851     }
852
853     str += "  sese2vst\n";
854     itr = sese2vst.entrySet().iterator();
855     while( itr.hasNext() ) {
856       Map.Entry                    me   = (Map.Entry)                    itr.next();
857       FlatSESEEnterNode            sese = (FlatSESEEnterNode)            me.getKey();
858       HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
859       assert s1 != null;
860
861       str += "    "+sese.getPrettyIdentifier()+" -> \n";
862
863       vstItr = s1.iterator();
864       while( vstItr.hasNext() ) {
865         str += "       "+tokHighlighter+" "+vstItr.next()+"\n";
866       }
867     }
868
869     str += "  var2vst\n";
870     itr = var2vst.entrySet().iterator();
871     while( itr.hasNext() ) {
872       Map.Entry                me  = (Map.Entry)                itr.next();
873       TempDescriptor           var = (TempDescriptor)           me.getKey();
874       Set<VariableSourceToken> s1  = (Set<VariableSourceToken>) me.getValue();
875       assert s1 != null;
876
877       str += "    "+var+" -> \n";
878
879       vstItr = s1.iterator();
880       while( vstItr.hasNext() ) {
881         str += "       "+tokHighlighter+" "+vstItr.next()+"\n";
882       }
883     }
884
885     str += "  sv2vst\n";
886     itr = sv2vst.entrySet().iterator();
887     while( itr.hasNext() ) {
888       Map.Entry                me  = (Map.Entry)                itr.next();
889       SVKey                    key = (SVKey)                    me.getKey();
890       Set<VariableSourceToken> s1  = (Set<VariableSourceToken>) me.getValue();
891       assert s1 != null;
892
893       str += "    "+key+" -> \n";
894
895       vstItr = s1.iterator();
896       while( vstItr.hasNext() ) {
897         str += "       "+tokHighlighter+" "+vstItr.next()+"\n";
898       }
899     }
900
901     return str;
902   }
903 }