Fix tabbing.... Please fix your editors so they do tabbing correctly!!! (Spaces...
[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     Hashtable<FlatNode, Set<TempNodePair>> nodetotnpair=new Hashtable<FlatNode, Set<TempNodePair>>();
42     Hashtable<FlatNode, Set<TempDescriptor>> nodetoconvs=new Hashtable<FlatNode, Set<TempDescriptor>>();
43     Hashtable<FlatNode, Set<TempDescriptor>> nodetoconvs2=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
52       Hashtable<TempDescriptor, Integer> nodetemptab=temptab.get(fn);
53
54       List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
55       List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
56
57       if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode
58           &&!nodetoconvs.containsKey(fn)) {
59         nodetoconvs.put(fn, new HashSet<TempDescriptor>());
60         nodetoconvs2.put(fn, new HashSet<TempDescriptor>());
61       }
62
63       HashSet<TempNodePair> tempset=new HashSet<TempNodePair>();
64
65       for(int i=0; i<fn.numPrev(); i++) {
66         FlatNode fnprev=fn.getPrev(i);
67         if (!nodetotnpair.containsKey(fnprev))
68           continue;
69
70         Set<TempNodePair> prevset=nodetotnpair.get(fnprev);
71         for(Iterator<TempNodePair> it=prevset.iterator(); it.hasNext(); ) {
72           TempNodePair tnp=it.next();
73           if (fn.kind()==FKind.FlatGlobalConvNode&&
74               ((FlatGlobalConvNode)fn).getLocality()!=lb) {
75             //ignore this node
76             tempset.add(tnp);
77             continue;
78           }
79           if (reads.contains(tnp.getTemp())&&tnp.getNode()!=null) {
80             //Value actually is read...
81             nodetoconvs.get(tnp.getNode()).add(tnp.getTemp());
82           }
83
84           if (writes.contains(tnp.getTemp()))           //value overwritten
85             continue;
86           if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode) {
87             //Create new node and tag it with this exit
88             if (tnp.getNode()==null) {
89               TempNodePair tnp2=new TempNodePair(tnp.getTemp());
90               tnp2.setNode(fn);
91               tempset.add(tnp2);
92               nodetoconvs2.get(fn).add(tnp.getTemp());  //have to hide cached copies from gc -- add unused converted temps
93             } else
94               tempset.add(tnp);
95           } else
96             tempset.add(tnp);
97         }
98       }
99       if (isatomic) {
100         /* If this is in an atomic block, record temps that
101          * are written to.*/
102
103         /* NOTE: If this compiler is changed to maintain
104          * OID/Ptr's in variables, then we need to use all
105          * global temps that could be read and not just the
106          * ones converted by globalconvnode*/
107
108         if (fn.kind()!=FKind.FlatGlobalConvNode||
109             ((FlatGlobalConvNode)fn).getLocality()==lb) {
110           /*If globalconvnode, make sure we have the right
111            * locality. */
112           for(Iterator<TempDescriptor> writeit=writes.iterator(); writeit.hasNext(); ) {
113             TempDescriptor wrtmp=writeit.next();
114             if (state.SINGLETM) {
115               if (wrtmp.getType().isPtr()&&
116                   (nodetemptab.get(wrtmp)!=LocalityAnalysis.SCRATCH)) {
117                 TempNodePair tnp=new TempNodePair(wrtmp);
118                 tempset.add(tnp);
119               }
120             } else if (nodetemptab.get(wrtmp)==LocalityAnalysis.GLOBAL) {
121               TempNodePair tnp=new TempNodePair(wrtmp);
122               tempset.add(tnp);
123             }
124           }
125         }
126       }
127       if (!nodetotnpair.containsKey(fn)||!nodetotnpair.get(fn).equals(tempset)) {
128         //changes to set, so enqueue next nodes
129         nodetotnpair.put(fn, tempset);         //update set
130         for(int i=0; i<fn.numNext(); i++) {
131           toprocess.add(fn.getNext(i));
132         }
133       }
134     }
135     //Place Convert to Oid nodes
136     toprocess=fm.getNodeSet();
137     for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext(); ) {
138       FlatNode fn=it.next();
139       if (atomictab.get(fn).intValue()==0&&fn.numPrev()>0&&
140           atomictab.get(fn.getPrev(0)).intValue()>0) {
141         //sanity check
142         assert(fn.kind()==FKind.FlatAtomicExitNode);
143         //insert calls here...
144         Set<TempDescriptor> tempset=nodetoconvs2.get(fn);
145         for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext(); ) {
146           TempDescriptor tmpd=tempit.next();
147           FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tmpd, lb, false, nodetoconvs.get(fn).contains(tmpd));
148
149           //This loop makes sure that we have accurate atomic information for the new node
150           for(Iterator<LocalityBinding> lbit=locality.getMethodBindings(lb.getMethod()).iterator(); lbit.hasNext(); ) {
151             LocalityBinding fixlb=lbit.next();
152             locality.getAtomic(fixlb).put(fgcn, locality.getAtomic(fixlb).get(fn.getPrev(0)));
153             locality.getNodeTempInfo(fixlb).put(fgcn, (Hashtable<TempDescriptor, Integer>)locality.getNodeTempInfo(fixlb).get(fn).clone());
154           }
155
156           fgcn.setAtomicEnter(((FlatAtomicExitNode)fn).getAtomicEnter());
157
158           FlatNode[] prevarray=new FlatNode[fn.numPrev()];
159           for(int i=0; i<fn.numPrev(); i++) {
160             FlatNode fnprev=fn.getPrev(i);
161             prevarray[i]=fnprev;
162           }
163           for(int i=0; i<prevarray.length; i++) {
164             for(int j=0; j<prevarray[i].numNext(); j++) {
165               if (prevarray[i].getNext(j)==fn) {
166                 //found index, change node
167                 prevarray[i].setNext(j, fgcn);
168                 break;
169               }
170             }
171           }
172           fgcn.addNext(fn);
173         }
174       }
175     }
176   }
177
178   /* At the beginning of an atomic block, we need to convert any
179    * OID's that will be used in the atomic block to pointers */
180
181   private void converttoPtr(LocalityBinding lb) {
182     Hashtable<FlatNode, Set<TempDescriptor>> nodetotranstemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
183     Hashtable<FlatNode, Integer> atomictab=locality.getAtomic(lb);
184     Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=locality.getNodeTempInfo(lb);
185     MethodDescriptor md=lb.getMethod();
186     FlatMethod fm=state.getMethodFlat(md);
187     Set<FlatNode> toprocess=fm.getNodeSet();
188
189     while(!toprocess.isEmpty()) {
190       FlatNode fn=toprocess.iterator().next();
191       toprocess.remove(fn);
192
193       if (atomictab.get(fn).intValue()>0) {
194         //build set of transaction temps use by next nodes
195         HashSet<TempDescriptor> transtemps=new HashSet<TempDescriptor>();
196         for(int i=0; i<fn.numNext(); i++) {
197           FlatNode fnnext=fn.getNext(i);
198           if (nodetotranstemps.containsKey(fnnext))
199             transtemps.addAll(nodetotranstemps.get(fnnext));
200         }
201         //subtract out the ones we write to
202         transtemps.removeAll(Arrays.asList(fn.writesTemps()));
203         //add in the globals we read from
204         Hashtable<TempDescriptor, Integer> pretemptab=locality.getNodePreTempInfo(lb, fn);
205         if (state.SINGLETM) {
206           TempDescriptor [] readtemps=fn.readsTemps();
207           for(int i=0; i<readtemps.length; i++) {
208             TempDescriptor tmp=readtemps[i];
209             if (tmp.getType().isPtr()&&
210                 pretemptab.get(tmp).intValue()!=LocalityAnalysis.SCRATCH) {
211               transtemps.add(tmp);
212             }
213           }
214         } else {
215           TempDescriptor [] readtemps=fn.readsTemps();
216           for(int i=0; i<readtemps.length; i++) {
217             TempDescriptor tmp=readtemps[i];
218             if (pretemptab.get(tmp).intValue()==LocalityAnalysis.GLOBAL) {
219               transtemps.add(tmp);
220             }
221           }
222         }
223         if (!nodetotranstemps.containsKey(fn)||!nodetotranstemps.get(fn).equals(transtemps)) {
224           nodetotranstemps.put(fn, transtemps);
225           for(int i=0; i<fn.numPrev(); i++)
226             toprocess.add(fn.getPrev(i));
227         }
228       }
229     }
230     toprocess=fm.getNodeSet();
231     for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext(); ) {
232       FlatNode fn=it.next();
233       if (atomictab.get(fn).intValue()>0&&
234           atomictab.get(fn.getPrev(0)).intValue()==0) {
235         //sanity check
236         assert(fn.kind()==FKind.FlatAtomicEnterNode);
237
238         //insert calls here...
239         Set<TempDescriptor> tempset=nodetotranstemps.get(fn);
240         for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext(); ) {
241           FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, true);
242           fgcn.setAtomicEnter((FlatAtomicEnterNode)fn);
243           //This loop makes sure that we have accurate atomic information for the new node
244           for(Iterator<LocalityBinding> lbit=locality.getMethodBindings(lb.getMethod()).iterator(); lbit.hasNext(); ) {
245             LocalityBinding fixlb=lbit.next();
246             locality.getAtomic(fixlb).put(fgcn, locality.getAtomic(fixlb).get(fn));
247             locality.getNodeTempInfo(fixlb).put(fgcn, (Hashtable<TempDescriptor, Integer>)locality.getNodeTempInfo(fixlb).get(fn).clone());
248           }
249           fgcn.addNext(fn.getNext(0));
250           fn.setNext(0, fgcn);
251         }
252       }
253     }
254   }
255 }