7e16c100d8a8926870eee9caf9f0b2a501130497
[IRC.git] / Robust / src / Analysis / MLP / VarSrcTokTable.java
1 package Analysis.MLP;
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 Integer MAX_AGE = new Integer( 2 );
32
33
34   public VarSrcTokTable() {
35     trueSet  = new HashSet<VariableSourceToken>();
36
37     sese2vst = new Hashtable< FlatSESEEnterNode, Set<VariableSourceToken> >();
38     var2vst  = new Hashtable< TempDescriptor,    Set<VariableSourceToken> >();
39     sv2vst   = new Hashtable< SVKey,             Set<VariableSourceToken> >();
40
41     assertConsistency();
42   }
43
44
45   // make a deep copy of the in table
46   public VarSrcTokTable( VarSrcTokTable in ) {
47     this();
48     merge( in );
49     assertConsistency();
50   }
51
52
53   public void add( VariableSourceToken vst ) {
54     addPrivate( vst );
55     assertConsistency();
56   }
57
58   private void addPrivate( VariableSourceToken vst ) {
59
60     // make sure we aren't clobbering anything!
61     if( trueSet.contains( vst ) ) {
62       // if something with the same hashcode is in the true set, they might
63       // have different reference variable sets because that set is not considered
64       // in a token's equality, so make sure we smooth that out right here
65       Iterator<VariableSourceToken> vstItr = trueSet.iterator();
66       while( vstItr.hasNext() ) {
67         VariableSourceToken vstAlready = vstItr.next();
68
69         if( vstAlready.equals( vst ) ) {    
70
71           // take out the one that is in (we dont' want collisions in
72           // any of the other hash map sets either)
73           removePrivate( vstAlready );
74
75           // combine reference variable sets
76           vst.getRefVars().addAll( vstAlready.getRefVars() );
77
78           // now jump back as we are adding in a brand new token
79           break;
80         }
81       }
82     }
83
84     trueSet.add( vst );
85
86     Set<VariableSourceToken> s;
87
88     s = sese2vst.get( vst.getSESE() );
89     if( s == null ) {
90       s = new HashSet<VariableSourceToken>();
91     }
92     s.add( vst );
93     sese2vst.put( vst.getSESE(), s );
94
95     Iterator<TempDescriptor> refVarItr = vst.getRefVars().iterator();
96     while( refVarItr.hasNext() ) {
97       TempDescriptor refVar = refVarItr.next();
98       s = var2vst.get( refVar );
99       if( s == null ) {
100         s = new HashSet<VariableSourceToken>();
101       }
102       s.add( vst );
103       var2vst.put( refVar, s );
104
105       SVKey key = new SVKey( vst.getSESE(), refVar );
106       s = sv2vst.get( key );
107       if( s == null ) {
108         s = new HashSet<VariableSourceToken>();
109       }
110       s.add( vst );
111       sv2vst.put( key, s );
112     }
113   }
114
115   public void addAll( Set<VariableSourceToken> s ) {
116     Iterator<VariableSourceToken> itr = s.iterator();
117     while( itr.hasNext() ) {
118       addPrivate( itr.next() );
119     }
120     assertConsistency();
121   }
122
123
124   public Set<VariableSourceToken> get() {
125     return trueSet;
126   }
127
128   public Set<VariableSourceToken> get( FlatSESEEnterNode sese ) {
129     Set<VariableSourceToken> s = sese2vst.get( sese );
130     if( s == null ) {
131       s = new HashSet<VariableSourceToken>();      
132       sese2vst.put( sese, s );
133     }
134     return s;
135   }
136
137   public Set<VariableSourceToken> get( TempDescriptor var ) {
138     Set<VariableSourceToken> s = var2vst.get( var );
139     if( s == null ) {
140       s = new HashSet<VariableSourceToken>();
141       var2vst.put( var, s );
142     }
143     return s;
144   }
145
146   public Set<VariableSourceToken> get( FlatSESEEnterNode sese,
147                                        TempDescriptor    refVar ) {
148     SVKey key = new SVKey( sese, refVar );
149     Set<VariableSourceToken> s = sv2vst.get( key );
150     if( s == null ) {
151       s = new HashSet<VariableSourceToken>();
152       sv2vst.put( key, s );
153     }
154     return s;
155   }
156
157   public Set<VariableSourceToken> get( FlatSESEEnterNode sese,
158                                        Integer           age ) {
159
160     HashSet<VariableSourceToken> s0 = (HashSet<VariableSourceToken>) sese2vst.get( sese );
161     if( s0 == null ) {
162       s0 = new HashSet<VariableSourceToken>();      
163       sese2vst.put( sese, s0 );
164     }
165
166     Set<VariableSourceToken> s = (Set<VariableSourceToken>) s0.clone();
167     Iterator<VariableSourceToken> sItr = s.iterator();
168     while( sItr.hasNext() ) {
169       VariableSourceToken vst = sItr.next();
170       if( !vst.getAge().equals( age ) ) {
171         s.remove( vst );
172       }
173     }
174
175     return s;
176   }
177
178
179   // merge now makes a deep copy of incoming stuff because tokens may
180   // be modified (reference var sets) by later ops that change more
181   // than one table, causing inconsistency
182   public void merge( VarSrcTokTable in ) {
183
184     if( in == null ) {
185       return;
186     }
187
188     Iterator<VariableSourceToken> vstItr = in.trueSet.iterator();
189     while( vstItr.hasNext() ) {
190       VariableSourceToken vst = vstItr.next();
191       this.addPrivate( vst.copy() );
192     }
193
194     assertConsistency();
195   }
196
197
198   // remove operations must leave the trueSet 
199   // and the hash maps consistent
200   public void remove( VariableSourceToken vst ) {
201     removePrivate( vst );
202     assertConsistency();
203   }
204
205   private void removePrivate( VariableSourceToken vst ) {
206     trueSet.remove( vst );
207     
208     Set<VariableSourceToken> s;
209
210     s = get( vst.getSESE() );
211     if( s != null ) { s.remove( vst ); }
212
213     Iterator<TempDescriptor> refVarItr = vst.getRefVars().iterator();
214     while( refVarItr.hasNext() ) {
215       TempDescriptor refVar = refVarItr.next();
216
217       s = get( refVar );
218       if( s != null ) { s.remove( vst ); }
219       
220       s = get( vst.getSESE(), refVar );
221       if( s != null ) { s.remove( vst ); }
222     }
223   }
224
225
226   public void remove( FlatSESEEnterNode sese ) {
227     removePrivate( sese );
228     assertConsistency();
229   }
230
231   public void removePrivate( FlatSESEEnterNode sese ) {
232     Set<VariableSourceToken> s = sese2vst.get( sese );
233     if( s == null ) {
234       return;
235     }
236
237     Iterator<VariableSourceToken> itr = s.iterator();
238     while( itr.hasNext() ) {
239       VariableSourceToken vst = itr.next();
240       removePrivate( vst );
241     }
242
243     sese2vst.remove( sese );
244   }
245
246
247   public void remove( TempDescriptor refVar ) {
248     removePrivate( refVar );
249     assertConsistency();
250   }
251
252   private void removePrivate( TempDescriptor refVar ) {
253     Set<VariableSourceToken> s = var2vst.get( refVar );
254     if( s == null ) {
255       return;
256     }
257     
258     Set<VariableSourceToken> forRemoval = new HashSet<VariableSourceToken>();
259
260     // iterate over tokens that this temp can reference, make a set
261     // of tokens that need this temp stripped out of them
262     Iterator<VariableSourceToken> itr = s.iterator();
263     while( itr.hasNext() ) {
264       VariableSourceToken vst = itr.next();
265       Set<TempDescriptor> refVars = vst.getRefVars();
266       assert refVars.contains( refVar );
267       forRemoval.add( vst );
268     }
269
270     itr = forRemoval.iterator();
271     while( itr.hasNext() ) {
272
273       // here's a token marked for removal
274       VariableSourceToken vst = itr.next();
275       Set<TempDescriptor> refVars = vst.getRefVars();
276
277       // if there was only one one variable
278       // referencing this token, just take it
279       // out of the table all together
280       if( refVars.size() == 1 ) {
281         removePrivate( vst );
282       }
283
284       refVars.remove( refVar );
285     }
286
287     var2vst.remove( refVar );
288   }
289
290
291   public void remove( FlatSESEEnterNode sese,
292                       TempDescriptor    var  ) {
293
294     // don't seem to need this, don't bother maintaining
295     // until its clear we need it
296     assert false;
297   }
298
299
300   // age tokens with respect to SESE curr, where
301   // any curr tokens increase age by 1
302   public void age( FlatSESEEnterNode curr ) {
303
304     Iterator<VariableSourceToken> itr = trueSet.iterator();
305     while( itr.hasNext() ) {
306       VariableSourceToken vst = itr.next();
307
308       if( vst.getSESE().equals( curr ) ) {
309
310         Integer newAge = vst.getAge()+1;
311         if( newAge > MAX_AGE ) {
312           newAge = MAX_AGE;
313         }
314         
315         remove( vst );
316
317         add( new VariableSourceToken( vst.getRefVars(), 
318                                       curr,                                           
319                                       newAge,
320                                       vst.getAddrVar()
321                                       )
322              );
323       } 
324     }
325     
326     assertConsistency();
327   }
328
329   
330   // for the given SESE, change child tokens into this parent
331   public void remapChildTokens( FlatSESEEnterNode curr ) {
332
333     Iterator<FlatSESEEnterNode> childItr = curr.getChildren().iterator();
334     if( childItr.hasNext() ) {
335       FlatSESEEnterNode child = childItr.next();
336       
337       Iterator<VariableSourceToken> vstItr = get( child ).iterator();
338       while( vstItr.hasNext() ) {
339         VariableSourceToken vst = vstItr.next();
340
341         remove( vst );
342         
343         add( new VariableSourceToken( vst.getRefVars(),
344                                       curr,
345                                       new Integer( 0 ),
346                                       vst.getAddrVar()
347                                       )
348              );
349       }
350     }
351
352     assertConsistency();
353   }   
354   
355
356   // if we can get a value from the current SESE and the parent
357   // or a sibling, just getting from the current SESE suffices now
358   // return a set of temps that are virtually read
359   public Set<TempDescriptor> removeParentAndSiblingTokens( FlatSESEEnterNode curr,
360                                                            Set<TempDescriptor> liveIn ) {
361     
362     HashSet<TempDescriptor> virtualLiveIn = new HashSet<TempDescriptor>();
363     
364     FlatSESEEnterNode parent = curr.getParent();
365     if( parent == null ) {
366       // have no parent or siblings
367       return virtualLiveIn;
368     }      
369     
370     remove_A_if_B( parent, curr, liveIn, virtualLiveIn );
371
372     Iterator<FlatSESEEnterNode> childItr = parent.getChildren().iterator();
373     if( childItr.hasNext() ) {
374       FlatSESEEnterNode child = childItr.next();
375       
376       if( !child.equals( curr ) ) {
377         remove_A_if_B( child, curr, liveIn, virtualLiveIn );
378       }
379     }
380     
381     assertConsistency();
382     return virtualLiveIn;
383   }
384   
385   // if B is also a source for some variable, remove all entries
386   // of A as a source for that variable: s is virtual reads
387   protected void remove_A_if_B( FlatSESEEnterNode a, 
388                                 FlatSESEEnterNode b,
389                                 Set<TempDescriptor> liveInCurrentSESE,
390                                 Set<TempDescriptor> virtualLiveIn ) {
391
392     Set<VariableSourceToken> forRemoval = new HashSet<VariableSourceToken>();
393
394     Iterator<VariableSourceToken> vstItr = get( a ).iterator();
395     while( vstItr.hasNext() ) {
396       VariableSourceToken      vst       = vstItr.next();
397       Iterator<TempDescriptor> refVarItr = vst.getRefVars().iterator();
398       while( refVarItr.hasNext() ) {
399         TempDescriptor           refVar = refVarItr.next();
400         Set<VariableSourceToken> bSet   = get( b, refVar );
401       
402         if( !bSet.isEmpty() ) {
403           forRemoval.add( vst );
404
405           // mark this variable as a virtual read as well
406           virtualLiveIn.add( refVar );
407         }
408       }
409     }
410
411     vstItr = forRemoval.iterator();
412     while( vstItr.hasNext() ) {
413       VariableSourceToken vst = vstItr.next();
414       remove( vst );
415     }
416
417     assertConsistency();
418   }
419
420   
421   // get the set of VST's that come from a child
422   public Set<VariableSourceToken> getChildrenVSTs( FlatSESEEnterNode curr ) {
423     
424     Set<VariableSourceToken> out = new HashSet<VariableSourceToken>();
425     
426     Iterator<FlatSESEEnterNode> cItr = curr.getChildren().iterator();
427     while( cItr.hasNext() ) {
428       FlatSESEEnterNode child = cItr.next();
429       out.addAll( get( child ) );
430     }
431
432     return out;
433   }
434
435
436   // get the set of variables that have exactly one source
437   // from the static perspective
438   public Set<VariableSourceToken> getStaticSet() {
439     
440     Set<VariableSourceToken> out = new HashSet<VariableSourceToken>();
441     
442     Iterator itr = var2vst.entrySet().iterator();
443     while( itr.hasNext() ) {
444       Map.Entry                    me  = (Map.Entry)                    itr.next();
445       TempDescriptor               var = (TempDescriptor)               me.getKey();
446       HashSet<VariableSourceToken> s1  = (HashSet<VariableSourceToken>) me.getValue();      
447     
448       if( s1.size() == 1 ) {
449         out.addAll( s1 );
450       }
451     }
452
453     return out;
454   }
455
456
457   // given a table from a subsequent program point, decide
458   // which variables are going from a static source to a
459   // dynamic source and return them
460   public Set<VariableSourceToken> getStatic2DynamicSet( VarSrcTokTable next ) {
461     
462     Set<VariableSourceToken> out = new HashSet<VariableSourceToken>();
463     
464     Iterator itr = var2vst.entrySet().iterator();
465     while( itr.hasNext() ) {
466       Map.Entry                    me  = (Map.Entry)                    itr.next();
467       TempDescriptor               var = (TempDescriptor)               me.getKey();
468       HashSet<VariableSourceToken> s1  = (HashSet<VariableSourceToken>) me.getValue();      
469     
470       if( s1.size() == 1 ) {
471         // this is a variable with a static source
472         Set<VariableSourceToken> s2 = next.get( var );
473         
474         if( s2.size() > 1 ) {
475           // and in the next table, it is dynamic
476           out.addAll( s1 );
477         }
478       }
479     }
480
481     return out;
482   }
483
484
485   // use as an aid for debugging, where true-set is checked
486   // against the alternate mappings: assert that nothing is
487   // missing or extra in the alternates
488   public void assertConsistency() {
489
490     Iterator itr; 
491     Set s;
492
493     Set<VariableSourceToken> trueSetByAlts = new HashSet<VariableSourceToken>();
494     itr = sese2vst.entrySet().iterator();
495     while( itr.hasNext() ) {
496       Map.Entry                    me   = (Map.Entry)                    itr.next();
497       FlatSESEEnterNode            sese = (FlatSESEEnterNode)            me.getKey();
498       HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
499       assert s1 != null;
500       
501       // the trueSet should have all entries in s1
502       assert trueSet.containsAll( s1 );
503
504       // s1 should not have anything that doesn't appear in trueset
505       Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
506       sInt.removeAll( trueSet );
507
508       assert sInt.isEmpty();
509
510       // add s1 to a running union--at the end check if trueSet has extra
511       trueSetByAlts.addAll( s1 );
512     }
513     // make sure trueSet isn't too big
514     assert trueSetByAlts.containsAll( trueSet );
515
516
517     trueSetByAlts = new HashSet<VariableSourceToken>();
518     itr = var2vst.entrySet().iterator();
519     while( itr.hasNext() ) {
520       Map.Entry                    me   = (Map.Entry)                    itr.next();
521       TempDescriptor               var  = (TempDescriptor)               me.getKey();
522       HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
523       assert s1 != null;
524       
525       // the trueSet should have all entries in s1
526       assert trueSet.containsAll( s1 );
527
528       // s1 should not have anything that doesn't appear in trueset
529       Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
530       sInt.removeAll( trueSet );
531
532       assert sInt.isEmpty();
533
534       // add s1 to a running union--at the end check if trueSet has extra
535       trueSetByAlts.addAll( s1 );
536     }
537     // make sure trueSet isn't too big
538     assert trueSetByAlts.containsAll( trueSet );
539
540
541     trueSetByAlts = new HashSet<VariableSourceToken>();
542     itr = sv2vst.entrySet().iterator();
543     while( itr.hasNext() ) {
544       Map.Entry                    me   = (Map.Entry)                    itr.next();
545       SVKey                        key  = (SVKey)                        me.getKey();
546       HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
547       assert s1 != null;
548       
549       // the trueSet should have all entries in s1
550       assert trueSet.containsAll( s1 );
551
552       // s1 should not have anything that doesn't appear in trueset
553       Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
554       sInt.removeAll( trueSet );
555
556       assert sInt.isEmpty();
557
558       // add s1 to a running union--at the end check if trueSet has extra
559       trueSetByAlts.addAll( s1 );
560     }
561     // make sure trueSet isn't too big
562     assert trueSetByAlts.containsAll( trueSet );
563
564
565     // also check that the reference var sets are consistent
566     Hashtable<VariableSourceToken, Set<TempDescriptor> > vst2refVars =
567       new Hashtable<VariableSourceToken, Set<TempDescriptor> >();
568     itr = var2vst.entrySet().iterator();
569     while( itr.hasNext() ) {
570       Map.Entry                     me     = (Map.Entry)                    itr.next();
571       TempDescriptor                refVar = (TempDescriptor)               me.getKey();
572       HashSet<VariableSourceToken>  s1     = (HashSet<VariableSourceToken>) me.getValue();      
573       Iterator<VariableSourceToken> vstItr = s1.iterator();
574       while( vstItr.hasNext() ) {
575         VariableSourceToken vst = vstItr.next();
576         assert vst.getRefVars().contains( refVar );
577
578         Set<TempDescriptor> refVarsPart = vst2refVars.get( vst );
579         if( refVarsPart == null ) {
580           refVarsPart = new HashSet<TempDescriptor>();
581         }
582         refVarsPart.add( refVar );
583         vst2refVars.put( vst, refVarsPart );
584       }
585     }
586     itr = vst2refVars.entrySet().iterator();
587     while( itr.hasNext() ) {
588       Map.Entry           me  = (Map.Entry)           itr.next();
589       VariableSourceToken vst = (VariableSourceToken) me.getKey();
590       Set<TempDescriptor> s1  = (Set<TempDescriptor>) me.getValue();
591
592       assert vst.getRefVars().equals( s1 );
593     }    
594   }
595
596
597   public boolean equals( Object o ) {
598     if( o == null ) {
599       return false;
600     }
601
602     if( !(o instanceof VarSrcTokTable) ) {
603       return false;
604     }
605
606     VarSrcTokTable table = (VarSrcTokTable) o;
607     return trueSet.equals( table.trueSet );
608   }
609
610   public int hashCode() {
611     return trueSet.hashCode();
612   }
613
614   public Iterator<VariableSourceToken> iterator() {
615     return trueSet.iterator();
616   }
617
618   public String toString() {
619     //return "trueSet ="+trueSet.toString();
620     return toStringPretty();
621   }
622
623   public String toStringVerbose() {
624     return "trueSet ="+trueSet.toString()+"\n"+
625            "sese2vst="+sese2vst.toString()+"\n"+
626            "var2vst ="+var2vst.toString()+"\n"+
627            "sv2vst  ="+sv2vst.toString();
628   }
629
630   public String toStringPretty() {
631     String tokHighlighter = "o";
632
633     String str = "VarSrcTokTable\n";
634     Iterator<VariableSourceToken> vstItr = trueSet.iterator();    
635     while( vstItr.hasNext() ) {
636       str += "   "+tokHighlighter+" "+vstItr.next()+"\n";
637     }
638     return str;
639   }
640
641   public String toStringPrettyVerbose() {
642     String tokHighlighter = "o";
643
644     String str = "VarSrcTokTable\n";
645
646     Set s;
647     Iterator itr; 
648     Iterator<VariableSourceToken> vstItr;
649
650     str += "  trueSet\n";
651     vstItr = trueSet.iterator();    
652     while( vstItr.hasNext() ) {
653       str += "     "+tokHighlighter+" "+vstItr.next()+"\n";
654     }
655
656     str += "  sese2vst\n";
657     itr = sese2vst.entrySet().iterator();
658     while( itr.hasNext() ) {
659       Map.Entry                    me   = (Map.Entry)                    itr.next();
660       FlatSESEEnterNode            sese = (FlatSESEEnterNode)            me.getKey();
661       HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
662       assert s1 != null;
663
664       str += "    "+sese.getPrettyIdentifier()+" -> \n";
665
666       vstItr = s1.iterator();
667       while( vstItr.hasNext() ) {
668         str += "       "+tokHighlighter+" "+vstItr.next()+"\n";
669       }
670     }
671
672     str += "  var2vst\n";
673     itr = var2vst.entrySet().iterator();
674     while( itr.hasNext() ) {
675       Map.Entry                me  = (Map.Entry)                itr.next();
676       TempDescriptor           var = (TempDescriptor)           me.getKey();
677       Set<VariableSourceToken> s1  = (Set<VariableSourceToken>) me.getValue();
678       assert s1 != null;
679
680       str += "    "+var+" -> \n";
681
682       vstItr = s1.iterator();
683       while( vstItr.hasNext() ) {
684         str += "       "+tokHighlighter+" "+vstItr.next()+"\n";
685       }
686     }
687
688     str += "  sv2vst\n";
689     itr = sv2vst.entrySet().iterator();
690     while( itr.hasNext() ) {
691       Map.Entry                me  = (Map.Entry)                itr.next();
692       SVKey                    key = (SVKey)                    me.getKey();
693       Set<VariableSourceToken> s1  = (Set<VariableSourceToken>) me.getValue();
694       assert s1 != null;
695
696       str += "    "+key+" -> \n";
697
698       vstItr = s1.iterator();
699       while( vstItr.hasNext() ) {
700         str += "       "+tokHighlighter+" "+vstItr.next()+"\n";
701       }
702     }
703
704     return str;
705   }
706 }