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.
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 {
22 // a set of every token in the table
23 private HashSet<VariableSourceToken> trueSet;
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;
30 // maximum age from aging operation
31 private static final Integer MAX_AGE = new Integer( 2 );
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 );
38 public VarSrcTokTable() {
39 trueSet = new HashSet<VariableSourceToken>();
41 sese2vst = new Hashtable< FlatSESEEnterNode, Set<VariableSourceToken> >();
42 var2vst = new Hashtable< TempDescriptor, Set<VariableSourceToken> >();
43 sv2vst = new Hashtable< SVKey, Set<VariableSourceToken> >();
49 // make a deep copy of the in table
50 public VarSrcTokTable( VarSrcTokTable in ) {
57 public void add( VariableSourceToken vst ) {
62 private void addPrivate( VariableSourceToken vst ) {
64 // make sure we aren't clobbering anything!
65 if( trueSet.contains( vst ) ) {
66 // if something with the same hashcode is in the true set, they might
67 // have different reference variable sets because that set is not considered
68 // in a token's equality, so make sure we smooth that out right here
69 Iterator<VariableSourceToken> vstItr = trueSet.iterator();
70 while( vstItr.hasNext() ) {
71 VariableSourceToken vstAlready = vstItr.next();
73 if( vstAlready.equals( vst ) ) {
75 // take out the one that is in (we dont' want collisions in
76 // any of the other hash map sets either)
77 removePrivate( vstAlready );
79 // combine reference variable sets
80 vst.getRefVars().addAll( vstAlready.getRefVars() );
82 // now jump back as we are adding in a brand new token
90 Set<VariableSourceToken> s;
92 s = sese2vst.get( vst.getSESE() );
94 s = new HashSet<VariableSourceToken>();
97 sese2vst.put( vst.getSESE(), s );
99 Iterator<TempDescriptor> refVarItr = vst.getRefVars().iterator();
100 while( refVarItr.hasNext() ) {
101 TempDescriptor refVar = refVarItr.next();
102 s = var2vst.get( refVar );
104 s = new HashSet<VariableSourceToken>();
107 var2vst.put( refVar, s );
109 SVKey key = new SVKey( vst.getSESE(), refVar );
110 s = sv2vst.get( key );
112 s = new HashSet<VariableSourceToken>();
115 sv2vst.put( key, s );
119 public void addAll( Set<VariableSourceToken> s ) {
120 Iterator<VariableSourceToken> itr = s.iterator();
121 while( itr.hasNext() ) {
122 addPrivate( itr.next() );
128 public Set<VariableSourceToken> get() {
132 public Set<VariableSourceToken> get( FlatSESEEnterNode sese ) {
133 Set<VariableSourceToken> s = sese2vst.get( sese );
135 s = new HashSet<VariableSourceToken>();
136 sese2vst.put( sese, s );
141 public Set<VariableSourceToken> get( TempDescriptor refVar ) {
142 Set<VariableSourceToken> s = var2vst.get( refVar );
144 s = new HashSet<VariableSourceToken>();
145 var2vst.put( refVar, s );
150 public Set<VariableSourceToken> get( FlatSESEEnterNode sese,
151 TempDescriptor refVar ) {
152 SVKey key = new SVKey( sese, refVar );
153 Set<VariableSourceToken> s = sv2vst.get( key );
155 s = new HashSet<VariableSourceToken>();
156 sv2vst.put( key, s );
161 public Set<VariableSourceToken> get( FlatSESEEnterNode sese,
164 HashSet<VariableSourceToken> s0 = (HashSet<VariableSourceToken>) sese2vst.get( sese );
166 s0 = new HashSet<VariableSourceToken>();
167 sese2vst.put( sese, s0 );
170 Set<VariableSourceToken> s = (Set<VariableSourceToken>) s0.clone();
171 Iterator<VariableSourceToken> sItr = s.iterator();
172 while( sItr.hasNext() ) {
173 VariableSourceToken vst = sItr.next();
174 if( !vst.getAge().equals( age ) ) {
183 // merge now makes a deep copy of incoming stuff because tokens may
184 // be modified (reference var sets) by later ops that change more
185 // than one table, causing inconsistency
186 public void merge( VarSrcTokTable in ) {
192 Iterator<VariableSourceToken> vstItr = in.trueSet.iterator();
193 while( vstItr.hasNext() ) {
194 VariableSourceToken vst = vstItr.next();
195 this.addPrivate( vst.copy() );
202 // remove operations must leave the trueSet
203 // and the hash maps consistent
204 public void remove( VariableSourceToken vst ) {
205 removePrivate( vst );
209 private void removePrivate( VariableSourceToken vst ) {
210 trueSet.remove( vst );
212 Set<VariableSourceToken> s;
214 s = get( vst.getSESE() );
215 if( s != null ) { s.remove( vst ); }
217 Iterator<TempDescriptor> refVarItr = vst.getRefVars().iterator();
218 while( refVarItr.hasNext() ) {
219 TempDescriptor refVar = refVarItr.next();
222 if( s != null ) { s.remove( vst ); }
224 s = get( vst.getSESE(), refVar );
225 if( s != null ) { s.remove( vst ); }
230 public void remove( FlatSESEEnterNode sese ) {
231 removePrivate( sese );
235 public void removePrivate( FlatSESEEnterNode sese ) {
236 Set<VariableSourceToken> s = sese2vst.get( sese );
241 Iterator<VariableSourceToken> itr = s.iterator();
242 while( itr.hasNext() ) {
243 VariableSourceToken vst = itr.next();
244 removePrivate( vst );
247 sese2vst.remove( sese );
251 public void remove( TempDescriptor refVar ) {
252 removePrivate( refVar );
256 private void removePrivate( TempDescriptor refVar ) {
257 Set<VariableSourceToken> s = var2vst.get( refVar );
262 Set<VariableSourceToken> forRemoval = new HashSet<VariableSourceToken>();
264 // iterate over tokens that this temp can reference, make a set
265 // of tokens that need this temp stripped out of them
266 Iterator<VariableSourceToken> itr = s.iterator();
267 while( itr.hasNext() ) {
268 VariableSourceToken vst = itr.next();
269 Set<TempDescriptor> refVars = vst.getRefVars();
270 assert refVars.contains( refVar );
271 forRemoval.add( vst );
274 itr = forRemoval.iterator();
275 while( itr.hasNext() ) {
277 // here's a token marked for removal
278 VariableSourceToken vst = itr.next();
279 Set<TempDescriptor> refVars = vst.getRefVars();
281 // if there was only one one variable
282 // referencing this token, just take it
283 // out of the table all together
284 if( refVars.size() == 1 ) {
285 removePrivate( vst );
288 refVars.remove( refVar );
291 var2vst.remove( refVar );
295 public void remove( FlatSESEEnterNode sese,
296 TempDescriptor var ) {
298 // don't seem to need this, don't bother maintaining
299 // until its clear we need it
304 // age tokens with respect to SESE curr, where
305 // any curr tokens increase age by 1
306 public void age( FlatSESEEnterNode curr ) {
308 Iterator<VariableSourceToken> itr = trueSet.iterator();
309 while( itr.hasNext() ) {
310 VariableSourceToken vst = itr.next();
312 if( vst.getSESE().equals( curr ) ) {
314 Integer newAge = vst.getAge()+1;
315 if( newAge > MAX_AGE ) {
321 add( new VariableSourceToken( vst.getRefVars(),
334 // at an SESE enter node, all ref vars in the SESE's in-set will
335 // be copied into the SESE's local scope, change source to itself
336 public void ownInSet( FlatSESEEnterNode curr ) {
337 Iterator<TempDescriptor> inVarItr = curr.getInVarSet().iterator();
338 while( inVarItr.hasNext() ) {
339 TempDescriptor inVar = inVarItr.next();
344 Set<TempDescriptor> refVars = new HashSet<TempDescriptor>();
345 refVars.add( inVar );
346 add( new VariableSourceToken( refVars,
357 // for the given SESE, change child tokens into this parent
358 public void remapChildTokens( FlatSESEEnterNode curr ) {
360 Iterator<FlatSESEEnterNode> childItr = curr.getChildren().iterator();
361 if( childItr.hasNext() ) {
362 FlatSESEEnterNode child = childItr.next();
364 Iterator<VariableSourceToken> vstItr = get( child ).iterator();
365 while( vstItr.hasNext() ) {
366 VariableSourceToken vst = vstItr.next();
370 add( new VariableSourceToken( vst.getRefVars(),
383 // if we can get a value from the current SESE and the parent
384 // or a sibling, just getting from the current SESE suffices now
385 // return a set of temps that are virtually read
386 public Set<TempDescriptor> removeParentAndSiblingTokens( FlatSESEEnterNode curr,
387 Set<TempDescriptor> liveIn ) {
389 HashSet<TempDescriptor> virtualLiveIn = new HashSet<TempDescriptor>();
391 FlatSESEEnterNode parent = curr.getParent();
392 if( parent == null ) {
393 // have no parent or siblings
394 return virtualLiveIn;
397 remove_A_if_B( parent, curr, liveIn, virtualLiveIn );
399 Iterator<FlatSESEEnterNode> childItr = parent.getChildren().iterator();
400 if( childItr.hasNext() ) {
401 FlatSESEEnterNode child = childItr.next();
403 if( !child.equals( curr ) ) {
404 remove_A_if_B( child, curr, liveIn, virtualLiveIn );
409 return virtualLiveIn;
412 // if B is also a source for some variable, remove all entries
413 // of A as a source for that variable: s is virtual reads
414 protected void remove_A_if_B( FlatSESEEnterNode a,
416 Set<TempDescriptor> liveInCurrentSESE,
417 Set<TempDescriptor> virtualLiveIn ) {
419 Set<VariableSourceToken> forRemoval = new HashSet<VariableSourceToken>();
421 Iterator<VariableSourceToken> vstItr = get( a ).iterator();
422 while( vstItr.hasNext() ) {
423 VariableSourceToken vst = vstItr.next();
424 Iterator<TempDescriptor> refVarItr = vst.getRefVars().iterator();
425 while( refVarItr.hasNext() ) {
426 TempDescriptor refVar = refVarItr.next();
427 Set<VariableSourceToken> bSet = get( b, refVar );
429 if( !bSet.isEmpty() ) {
430 forRemoval.add( vst );
432 // mark this variable as a virtual read as well
433 virtualLiveIn.add( refVar );
438 vstItr = forRemoval.iterator();
439 while( vstItr.hasNext() ) {
440 VariableSourceToken vst = vstItr.next();
448 // get the set of VST's that come from a child
449 public Set<VariableSourceToken> getChildrenVSTs( FlatSESEEnterNode curr ) {
451 Set<VariableSourceToken> out = new HashSet<VariableSourceToken>();
453 Iterator<FlatSESEEnterNode> cItr = curr.getChildren().iterator();
454 while( cItr.hasNext() ) {
455 FlatSESEEnterNode child = cItr.next();
456 out.addAll( get( child ) );
463 // get the set of variables that have exactly one source
464 // from the static perspective
465 public Set<VariableSourceToken> getStaticSet() {
467 Set<VariableSourceToken> out = new HashSet<VariableSourceToken>();
469 Iterator itr = var2vst.entrySet().iterator();
470 while( itr.hasNext() ) {
471 Map.Entry me = (Map.Entry) itr.next();
472 TempDescriptor var = (TempDescriptor) me.getKey();
473 HashSet<VariableSourceToken> s1 = (HashSet<VariableSourceToken>) me.getValue();
475 if( s1.size() == 1 ) {
484 // given a table from a subsequent program point, decide
485 // which variables are going from a static source to a
486 // dynamic source and return them
487 public Hashtable<TempDescriptor, VariableSourceToken> getStatic2DynamicSet( VarSrcTokTable next ) {
489 Hashtable<TempDescriptor, VariableSourceToken> out =
490 new Hashtable<TempDescriptor, VariableSourceToken>();
492 Iterator itr = var2vst.entrySet().iterator();
493 while( itr.hasNext() ) {
494 Map.Entry me = (Map.Entry) itr.next();
495 TempDescriptor var = (TempDescriptor) me.getKey();
496 HashSet<VariableSourceToken> s1 = (HashSet<VariableSourceToken>) me.getValue();
498 // this is a variable with a static source if it
499 // currently has one vst
500 if( s1.size() == 1 ) {
501 Set<VariableSourceToken> s2 = next.get( var );
503 // and if in the next table, it is dynamic, then
504 // this is a transition point, so
505 if( s2.size() > 1 ) {
507 // remember the variable and the only source
508 // it had before crossing the transition
509 out.put( var, s1.iterator().next() );
518 // for some reference variable, return the type of source
519 // it might have in this table, which might be:
520 // 1. Ready -- this variable comes from your parent and is
521 // definitely available when you are issued.
522 // 2. Static -- there is definitely one SESE that will
523 // produce the value for this variable
524 // 3. Dynamic -- we don't know where the value will come
525 // from, so we'll track it dynamically
526 public Integer getRefVarSrcType( TempDescriptor refVar,
527 FlatSESEEnterNode current,
528 FlatSESEEnterNode parent ) {
529 assert refVar != null;
531 // if you have no parent (root) and the variable in
532 // question is in your in-set, it's a command line
533 // argument and it is definitely available
534 if( parent == null &&
535 current.getInVarSet().contains( refVar ) ) {
536 return SrcType_READY;
539 Set<VariableSourceToken> srcs = get( refVar );
540 assert !srcs.isEmpty();
542 // if the variable may have more than one source, or that
543 // source is at the summary age, it must be tracked dynamically
544 if( srcs.size() > 1 ||
545 srcs.iterator().next().getAge() == MLPAnalysis.maxSESEage ) {
546 return SrcType_DYNAMIC;
549 // if it has one source that comes from the parent, it's ready
550 if( srcs.iterator().next().getSESE() == parent ) {
551 return SrcType_READY;
554 // otherwise it comes from one source not the parent (sibling)
555 // and we know exactly which static SESE/age it will come from
556 return SrcType_STATIC;
560 // any reference variables that are not live can be pruned
561 // from the table, and if any VSTs are then no longer
562 // referenced, they can be dropped as well
563 /* THIS CAUSES INCONSISTENCY, FIX LATER, NOT REQUIRED
564 public void pruneByLiveness( Set<TempDescriptor> rootLiveSet ) {
566 // the set of reference variables in the table minus the
567 // live set gives the set of reference variables to remove
568 Set<TempDescriptor> deadRefVars = new HashSet<TempDescriptor>();
569 deadRefVars.addAll( var2vst.keySet() );
571 if( rootLiveSet != null ) {
572 deadRefVars.removeAll( rootLiveSet );
575 // just use the remove operation to prune the table now
576 Iterator<TempDescriptor> deadItr = deadRefVars.iterator();
577 while( deadItr.hasNext() ) {
578 TempDescriptor dead = deadItr.next();
579 removePrivate( dead );
587 // use as an aid for debugging, where true-set is checked
588 // against the alternate mappings: assert that nothing is
589 // missing or extra in the alternates
590 public void assertConsistency() {
595 Set<VariableSourceToken> trueSetByAlts = new HashSet<VariableSourceToken>();
596 itr = sese2vst.entrySet().iterator();
597 while( itr.hasNext() ) {
598 Map.Entry me = (Map.Entry) itr.next();
599 FlatSESEEnterNode sese = (FlatSESEEnterNode) me.getKey();
600 HashSet<VariableSourceToken> s1 = (HashSet<VariableSourceToken>) me.getValue();
603 // the trueSet should have all entries in s1
604 assert trueSet.containsAll( s1 );
606 // s1 should not have anything that doesn't appear in trueset
607 Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
608 sInt.removeAll( trueSet );
610 assert sInt.isEmpty();
612 // add s1 to a running union--at the end check if trueSet has extra
613 trueSetByAlts.addAll( s1 );
615 // make sure trueSet isn't too big
616 assert trueSetByAlts.containsAll( trueSet );
619 trueSetByAlts = new HashSet<VariableSourceToken>();
620 itr = var2vst.entrySet().iterator();
621 while( itr.hasNext() ) {
622 Map.Entry me = (Map.Entry) itr.next();
623 TempDescriptor var = (TempDescriptor) me.getKey();
624 HashSet<VariableSourceToken> s1 = (HashSet<VariableSourceToken>) me.getValue();
627 // the trueSet should have all entries in s1
628 assert trueSet.containsAll( s1 );
630 // s1 should not have anything that doesn't appear in trueset
631 Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
632 sInt.removeAll( trueSet );
634 assert sInt.isEmpty();
636 // add s1 to a running union--at the end check if trueSet has extra
637 trueSetByAlts.addAll( s1 );
639 // make sure trueSet isn't too big
640 assert trueSetByAlts.containsAll( trueSet );
643 trueSetByAlts = new HashSet<VariableSourceToken>();
644 itr = sv2vst.entrySet().iterator();
645 while( itr.hasNext() ) {
646 Map.Entry me = (Map.Entry) itr.next();
647 SVKey key = (SVKey) me.getKey();
648 HashSet<VariableSourceToken> s1 = (HashSet<VariableSourceToken>) me.getValue();
651 // the trueSet should have all entries in s1
652 assert trueSet.containsAll( s1 );
654 // s1 should not have anything that doesn't appear in trueset
655 Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
656 sInt.removeAll( trueSet );
658 assert sInt.isEmpty();
660 // add s1 to a running union--at the end check if trueSet has extra
661 trueSetByAlts.addAll( s1 );
663 // make sure trueSet isn't too big
664 assert trueSetByAlts.containsAll( trueSet );
667 // also check that the reference var sets are consistent
668 Hashtable<VariableSourceToken, Set<TempDescriptor> > vst2refVars =
669 new Hashtable<VariableSourceToken, Set<TempDescriptor> >();
670 itr = var2vst.entrySet().iterator();
671 while( itr.hasNext() ) {
672 Map.Entry me = (Map.Entry) itr.next();
673 TempDescriptor refVar = (TempDescriptor) me.getKey();
674 HashSet<VariableSourceToken> s1 = (HashSet<VariableSourceToken>) me.getValue();
675 Iterator<VariableSourceToken> vstItr = s1.iterator();
676 while( vstItr.hasNext() ) {
677 VariableSourceToken vst = vstItr.next();
678 assert vst.getRefVars().contains( refVar );
680 Set<TempDescriptor> refVarsPart = vst2refVars.get( vst );
681 if( refVarsPart == null ) {
682 refVarsPart = new HashSet<TempDescriptor>();
684 refVarsPart.add( refVar );
685 vst2refVars.put( vst, refVarsPart );
688 itr = vst2refVars.entrySet().iterator();
689 while( itr.hasNext() ) {
690 Map.Entry me = (Map.Entry) itr.next();
691 VariableSourceToken vst = (VariableSourceToken) me.getKey();
692 Set<TempDescriptor> s1 = (Set<TempDescriptor>) me.getValue();
694 assert vst.getRefVars().equals( s1 );
699 public boolean equals( Object o ) {
704 if( !(o instanceof VarSrcTokTable) ) {
708 VarSrcTokTable table = (VarSrcTokTable) o;
709 return trueSet.equals( table.trueSet );
712 public int hashCode() {
713 return trueSet.hashCode();
716 public Iterator<VariableSourceToken> iterator() {
717 return trueSet.iterator();
720 public String toString() {
721 return toStringPretty();
724 public String toStringVerbose() {
725 return "trueSet ="+trueSet.toString()+"\n"+
726 "sese2vst="+sese2vst.toString()+"\n"+
727 "var2vst ="+var2vst.toString()+"\n"+
728 "sv2vst ="+sv2vst.toString();
731 public String toStringPretty() {
732 String tokHighlighter = "o";
734 String str = "VarSrcTokTable\n";
735 Iterator<VariableSourceToken> vstItr = trueSet.iterator();
736 while( vstItr.hasNext() ) {
737 str += " "+tokHighlighter+" "+vstItr.next()+"\n";
742 public String toStringPrettyVerbose() {
743 String tokHighlighter = "o";
745 String str = "VarSrcTokTable\n";
749 Iterator<VariableSourceToken> vstItr;
752 vstItr = trueSet.iterator();
753 while( vstItr.hasNext() ) {
754 str += " "+tokHighlighter+" "+vstItr.next()+"\n";
757 str += " sese2vst\n";
758 itr = sese2vst.entrySet().iterator();
759 while( itr.hasNext() ) {
760 Map.Entry me = (Map.Entry) itr.next();
761 FlatSESEEnterNode sese = (FlatSESEEnterNode) me.getKey();
762 HashSet<VariableSourceToken> s1 = (HashSet<VariableSourceToken>) me.getValue();
765 str += " "+sese.getPrettyIdentifier()+" -> \n";
767 vstItr = s1.iterator();
768 while( vstItr.hasNext() ) {
769 str += " "+tokHighlighter+" "+vstItr.next()+"\n";
774 itr = var2vst.entrySet().iterator();
775 while( itr.hasNext() ) {
776 Map.Entry me = (Map.Entry) itr.next();
777 TempDescriptor var = (TempDescriptor) me.getKey();
778 Set<VariableSourceToken> s1 = (Set<VariableSourceToken>) me.getValue();
781 str += " "+var+" -> \n";
783 vstItr = s1.iterator();
784 while( vstItr.hasNext() ) {
785 str += " "+tokHighlighter+" "+vstItr.next()+"\n";
790 itr = sv2vst.entrySet().iterator();
791 while( itr.hasNext() ) {
792 Map.Entry me = (Map.Entry) itr.next();
793 SVKey key = (SVKey) me.getKey();
794 Set<VariableSourceToken> s1 = (Set<VariableSourceToken>) me.getValue();
797 str += " "+key+" -> \n";
799 vstItr = s1.iterator();
800 while( vstItr.hasNext() ) {
801 str += " "+tokHighlighter+" "+vstItr.next()+"\n";