more fixes
[IRC.git] / Robust / src / Analysis / Locality / GenerateConversions.java
1 package Analysis.Locality;
2 import IR.State;
3 import IR.Flat.*;
4 import java.util.*;
5 import IR.MethodDescriptor;
6
7
8 public class GenerateConversions {
9     LocalityAnalysis locality;
10     State state;
11
12     /** Warning: This class modifies the code in place.  */
13
14     public GenerateConversions(LocalityAnalysis la, State state) {
15         locality=la;
16         this.state=state;
17         doConversion();
18     }
19     
20     private void doConversion() {
21         Set<LocalityBinding> bindings=locality.getLocalityBindings();
22         Iterator<LocalityBinding> bindit=bindings.iterator();
23         while(bindit.hasNext()) {
24             LocalityBinding lb=bindit.next();
25             //Don't need to do conversion if it is already atomic
26             if (lb.isAtomic())
27                 continue;
28             converttoPtr(lb);
29             converttoOid(lb);
30         }
31     }
32
33     /* At the end of an atomic block, we need to convert any global
34      * references that will be used again into OID's */
35
36     private void converttoOid(LocalityBinding lb) {
37         Hashtable<FlatNode, Integer> atomictab=locality.getAtomic(lb);
38         Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=locality.getNodeTempInfo(lb);
39         MethodDescriptor md=lb.getMethod();
40         FlatMethod fm=state.getMethodFlat(md);
41                 
42         Hashtable<FlatNode, Set<TempNodePair>> nodetotnpair=new Hashtable<FlatNode, Set<TempNodePair>>();       
43         Hashtable<FlatNode, Set<TempDescriptor>> nodetoconvs=new Hashtable<FlatNode, Set<TempDescriptor>>();
44
45         Set<FlatNode> toprocess=fm.getNodeSet();
46
47         while(!toprocess.isEmpty()) {
48             FlatNode fn=toprocess.iterator().next();
49             toprocess.remove(fn);
50             boolean isatomic=atomictab.get(fn).intValue()>0;
51             Hashtable<TempDescriptor, Integer> nodetemptab=temptab.get(fn);
52             
53             List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
54             List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
55
56             if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode
57                 &&!nodetoconvs.containsKey(fn))
58                 nodetoconvs.put(fn, new HashSet<TempDescriptor>());
59
60
61             HashSet<TempNodePair> tempset=new HashSet<TempNodePair>();
62             for(int i=0;i<fn.numPrev();i++) {
63                 FlatNode fnprev=fn.getPrev(i);
64                 if (!nodetotnpair.containsKey(fnprev))
65                     continue;
66                 Set<TempNodePair> prevset=nodetotnpair.get(fnprev);
67                 for(Iterator<TempNodePair> it=prevset.iterator();it.hasNext();) {
68                     TempNodePair tnp=it.next();
69                     if (reads.contains(tnp.getTemp())&&tnp.getNode()!=null) {
70                         //Value actually is read...
71                         nodetoconvs.get(tnp.getNode()).add(tnp.getTemp());
72                     }
73                     if (writes.contains(tnp.getTemp())) //value overwritten
74                         continue;
75                     if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode) {
76                         //Create new node and tag it with this exit
77                         if (tnp.getNode()==null) {
78                             TempNodePair tnp2=new TempNodePair(tnp.getTemp());
79                             tnp2.setNode(fn);
80                             tempset.add(tnp2);
81                         } else
82                             tempset.add(tnp);
83                     } else
84                         tempset.add(tnp);
85                 }
86             }
87             if (isatomic) {
88                 //if this is in an atomic block, record temps that are written to
89
90                 /* NOTE: If this compiler is changed to maintain
91                  * OID/Ptr's in variables, then we need to use all
92                  * global temps that could be read and not just the
93                  * ones converted by globalconvnode*/
94
95                 if (fn.kind()!=FKind.FlatGlobalConvNode||
96                     ((FlatGlobalConvNode)fn).getLocality()==lb)
97                     //If globalconvnode, make sure we have the right locality
98                     for(Iterator<TempDescriptor> writeit=writes.iterator();writeit.hasNext();) {
99                         TempDescriptor wrtmp=writeit.next();
100                         if (nodetemptab.get(wrtmp)==LocalityAnalysis.GLOBAL) {
101                             TempNodePair tnp=new TempNodePair(wrtmp);
102                             tempset.add(tnp);
103                         }
104                     }
105             }
106             if (!nodetotnpair.containsKey(fn)||!nodetotnpair.get(fn).equals(tempset)) {
107                 //changes to set, so enqueue next nodes
108                 nodetotnpair.put(fn, tempset); //update set
109                 for(int i=0;i<fn.numNext();i++) {
110                     toprocess.add(fn.getNext(i));
111                 }
112             }
113         }
114         //Place Convert to Oid nodes
115         toprocess=fm.getNodeSet();
116         for(Iterator<FlatNode> it=toprocess.iterator();it.hasNext();) {
117             FlatNode fn=it.next();
118             if (atomictab.get(fn).intValue()==0&&fn.numPrev()>0&&
119                 atomictab.get(fn.getPrev(0)).intValue()>0) {
120                 //sanity check
121                 assert(fn.kind()==FKind.FlatAtomicExitNode);
122                 //insert calls here...
123                 Set<TempDescriptor> tempset=nodetoconvs.get(fn);
124                 for(Iterator<TempDescriptor> tempit=tempset.iterator();tempit.hasNext();) {
125                     FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, false);
126                     atomictab.put(fgcn, atomictab.get(fn));
127                     temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>) temptab.get(fn).clone());
128                     for(int i=0;i<fn.numPrev();i++) {
129                         FlatNode fnprev=fn.getPrev(i);
130                         for(int j=0;j<fnprev.numNext();j++) {
131                             if (fnprev.getNext(j)==fn) {
132                                 //found index, change node
133                                 fnprev.setNext(j, fgcn);
134                                 break;
135                             }
136                         }
137                     }
138                     fgcn.addNext(fn);
139                 }
140             }
141         }
142     }
143     
144     /* At the beginning of an atomic block, we need to convert any
145      * OID's that will be used in the atomic block to pointers */
146
147     private void converttoPtr(LocalityBinding lb) {
148         Hashtable<FlatNode, Set<TempDescriptor>> nodetotranstemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
149         Hashtable<FlatNode, Integer> atomictab=locality.getAtomic(lb);
150         Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=locality.getNodeTempInfo(lb);
151         MethodDescriptor md=lb.getMethod();
152         FlatMethod fm=state.getMethodFlat(md);
153         Set<FlatNode> toprocess=fm.getNodeSet();
154
155         while(!toprocess.isEmpty()) {
156             FlatNode fn=toprocess.iterator().next();
157             toprocess.remove(fn);
158             
159             if (atomictab.get(fn).intValue()>0) {
160                 //build set of transaction temps use by next nodes
161                 HashSet<TempDescriptor> transtemps=new HashSet<TempDescriptor>();
162                 for(int i=0;i<fn.numNext();i++) {
163                     FlatNode fnnext=fn.getNext(i);
164                     if (nodetotranstemps.containsKey(fnnext))
165                         transtemps.addAll(nodetotranstemps.get(fnnext));
166                 }
167                 //subtract out the ones we write to
168                 transtemps.removeAll(Arrays.asList(fn.writesTemps()));
169                 //add in the globals we read from
170                 Hashtable<TempDescriptor, Integer> pretemptab=locality.getNodePreTempInfo(lb, fn);
171                 TempDescriptor []readtemps=fn.readsTemps();
172                 for(int i=0;i<readtemps.length;i++) {
173                     TempDescriptor tmp=readtemps[i];
174                     if (pretemptab.get(tmp).intValue()==LocalityAnalysis.GLOBAL) {
175                         transtemps.add(tmp);
176                     }
177                 }
178                 if (!nodetotranstemps.containsKey(fn)||!nodetotranstemps.get(fn).equals(transtemps)) {
179                     nodetotranstemps.put(fn, transtemps);
180                     for(int i=0;i<fn.numPrev();i++)
181                         toprocess.add(fn.getPrev(i));
182                 }
183             }
184         }
185         toprocess=fm.getNodeSet();
186         for(Iterator<FlatNode> it=toprocess.iterator();it.hasNext();) {
187             FlatNode fn=it.next();
188             if (atomictab.get(fn).intValue()>0&&
189                 atomictab.get(fn.getPrev(0)).intValue()==0) {
190                 //sanity check
191                 assert(fn.kind()==FKind.FlatAtomicEnterNode);
192
193                 //insert calls here...
194                 Set<TempDescriptor> tempset=nodetotranstemps.get(fn);
195                 for(Iterator<TempDescriptor> tempit=tempset.iterator();tempit.hasNext();) {
196                     FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, true);
197                     atomictab.put(fgcn, atomictab.get(fn));
198                     temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>) temptab.get(fn).clone());
199                     fgcn.addNext(fn.getNext(0));
200                     fn.setNext(0, fgcn);
201                 }       
202             }
203         }
204     }
205 }