typo
[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
93             } else
94               tempset.add(tnp);
95             throw new Error();
96           } else
97             tempset.add(tnp);
98         }
99       }
100       if (isatomic) {
101         /* If this is in an atomic block, record temps that
102          * are written to.*/
103
104         /* NOTE: If this compiler is changed to maintain
105          * OID/Ptr's in variables, then we need to use all
106          * global temps that could be read and not just the
107          * ones converted by globalconvnode*/
108
109         if (fn.kind()!=FKind.FlatGlobalConvNode||
110             ((FlatGlobalConvNode)fn).getLocality()==lb) {
111           /*If globalconvnode, make sure we have the right
112            * locality. */
113           for(Iterator<TempDescriptor> writeit=writes.iterator(); writeit.hasNext();) {
114             TempDescriptor wrtmp=writeit.next();
115             if (nodetemptab.get(wrtmp)==LocalityAnalysis.GLOBAL) {
116               TempNodePair tnp=new TempNodePair(wrtmp);
117               tempset.add(tnp);
118             }
119           }
120         }
121       }
122       if (!nodetotnpair.containsKey(fn)||!nodetotnpair.get(fn).equals(tempset)) {
123         //changes to set, so enqueue next nodes
124         nodetotnpair.put(fn, tempset);         //update set
125         for(int i=0; i<fn.numNext(); i++) {
126           toprocess.add(fn.getNext(i));
127         }
128       }
129     }
130     //Place Convert to Oid nodes
131     toprocess=fm.getNodeSet();
132     for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext();) {
133       FlatNode fn=it.next();
134       if (atomictab.get(fn).intValue()==0&&fn.numPrev()>0&&
135           atomictab.get(fn.getPrev(0)).intValue()>0) {
136         //sanity check
137         assert(fn.kind()==FKind.FlatAtomicExitNode);
138         //insert calls here...
139         Set<TempDescriptor> tempset=nodetoconvs2.get(fn);
140         for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext();) {
141           TempDescriptor tmpd=tempit.next();
142           FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tmpd, lb, false, nodetoconvs.get(fn).contains(tmpd));
143           atomictab.put(fgcn, atomictab.get(fn));
144           temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>)temptab.get(fn).clone());
145
146           for(int i=0; i<fn.numPrev(); i++) {
147             FlatNode fnprev=fn.getPrev(i);
148             for(int j=0; j<fnprev.numNext(); j++) {
149               if (fnprev.getNext(j)==fn) {
150                 //found index, change node
151                 fnprev.setNext(j, fgcn);
152                 break;
153               }
154             }
155           }
156           fgcn.addNext(fn);
157         }
158       }
159     }
160   }
161
162   /* At the beginning of an atomic block, we need to convert any
163    * OID's that will be used in the atomic block to pointers */
164
165   private void converttoPtr(LocalityBinding lb) {
166     Hashtable<FlatNode, Set<TempDescriptor>> nodetotranstemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
167     Hashtable<FlatNode, Integer> atomictab=locality.getAtomic(lb);
168     Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=locality.getNodeTempInfo(lb);
169     MethodDescriptor md=lb.getMethod();
170     FlatMethod fm=state.getMethodFlat(md);
171     Set<FlatNode> toprocess=fm.getNodeSet();
172
173     while(!toprocess.isEmpty()) {
174       FlatNode fn=toprocess.iterator().next();
175       toprocess.remove(fn);
176
177       if (atomictab.get(fn).intValue()>0) {
178         //build set of transaction temps use by next nodes
179         HashSet<TempDescriptor> transtemps=new HashSet<TempDescriptor>();
180         for(int i=0; i<fn.numNext(); i++) {
181           FlatNode fnnext=fn.getNext(i);
182           if (nodetotranstemps.containsKey(fnnext))
183             transtemps.addAll(nodetotranstemps.get(fnnext));
184         }
185         //subtract out the ones we write to
186         transtemps.removeAll(Arrays.asList(fn.writesTemps()));
187         //add in the globals we read from
188         Hashtable<TempDescriptor, Integer> pretemptab=locality.getNodePreTempInfo(lb, fn);
189         TempDescriptor [] readtemps=fn.readsTemps();
190         for(int i=0; i<readtemps.length; i++) {
191           TempDescriptor tmp=readtemps[i];
192           if (pretemptab.get(tmp).intValue()==LocalityAnalysis.GLOBAL) {
193             transtemps.add(tmp);
194           }
195         }
196         if (!nodetotranstemps.containsKey(fn)||!nodetotranstemps.get(fn).equals(transtemps)) {
197           nodetotranstemps.put(fn, transtemps);
198           for(int i=0; i<fn.numPrev(); i++)
199             toprocess.add(fn.getPrev(i));
200         }
201       }
202     }
203     toprocess=fm.getNodeSet();
204     for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext();) {
205       FlatNode fn=it.next();
206       if (atomictab.get(fn).intValue()>0&&
207           atomictab.get(fn.getPrev(0)).intValue()==0) {
208         //sanity check
209         assert(fn.kind()==FKind.FlatAtomicEnterNode);
210
211         //insert calls here...
212         Set<TempDescriptor> tempset=nodetotranstemps.get(fn);
213         for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext();) {
214           FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, true);
215           atomictab.put(fgcn, atomictab.get(fn));
216           temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>)temptab.get(fn).clone());
217           fgcn.addNext(fn.getNext(0));
218           fn.setNext(0, fgcn);
219         }
220       }
221     }
222   }
223 }