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
44     Set<FlatNode> toprocess=fm.getNodeSet();
45
46     while(!toprocess.isEmpty()) {
47       FlatNode fn=toprocess.iterator().next();
48       toprocess.remove(fn);
49       boolean isatomic=atomictab.get(fn).intValue()>0;
50       if (!isatomic && fn.kind()!=FKind.FlatAtomicExitNode)//Don't process past the bounds of a transaction
51         continue;
52
53       Hashtable<TempDescriptor, Integer> nodetemptab=temptab.get(fn);
54
55       List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
56       List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
57
58       if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode
59           &&!nodetoconvs.containsKey(fn))
60         nodetoconvs.put(fn, new HashSet<TempDescriptor>());
61
62       HashSet<TempNodePair> tempset=new HashSet<TempNodePair>();
63
64       for(int i=0; i<fn.numPrev(); i++) {
65         FlatNode fnprev=fn.getPrev(i);
66         if (!nodetotnpair.containsKey(fnprev))
67           continue;
68
69         Set<TempNodePair> prevset=nodetotnpair.get(fnprev);
70         for(Iterator<TempNodePair> it=prevset.iterator(); it.hasNext();) {
71           TempNodePair tnp=it.next();
72           if (fn.kind()==FKind.FlatGlobalConvNode&&
73               ((FlatGlobalConvNode)fn).getLocality()!=lb) {
74             //ignore this node
75             tempset.add(tnp);
76             continue;
77           }
78           if (writes.contains(tnp.getTemp()))           //value overwritten
79             continue;
80           if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode) {
81             //Create new node and tag it with this exit
82             if (tnp.getNode()==null) {
83               nodetoconvs.get(fn).add(tnp.getTemp());//have to hide cached copies from gc
84             } else
85               throw new Error();
86           } else
87             tempset.add(tnp);
88         }
89       }
90       if (isatomic) {
91         /* If this is in an atomic block, record temps that
92          * are written to.*/
93
94         /* NOTE: If this compiler is changed to maintain
95          * OID/Ptr's in variables, then we need to use all
96          * global temps that could be read and not just the
97          * ones converted by globalconvnode*/
98
99         if (fn.kind()!=FKind.FlatGlobalConvNode||
100             ((FlatGlobalConvNode)fn).getLocality()==lb) {
101           /*If globalconvnode, make sure we have the right
102            * locality. */
103           for(Iterator<TempDescriptor> writeit=writes.iterator(); writeit.hasNext();) {
104             TempDescriptor wrtmp=writeit.next();
105             if (nodetemptab.get(wrtmp)==LocalityAnalysis.GLOBAL) {
106               TempNodePair tnp=new TempNodePair(wrtmp);
107               tempset.add(tnp);
108             }
109           }
110         }
111       }
112       if (!nodetotnpair.containsKey(fn)||!nodetotnpair.get(fn).equals(tempset)) {
113         //changes to set, so enqueue next nodes
114         nodetotnpair.put(fn, tempset);         //update set
115         for(int i=0; i<fn.numNext(); i++) {
116           toprocess.add(fn.getNext(i));
117         }
118       }
119     }
120     //Place Convert to Oid nodes
121     toprocess=fm.getNodeSet();
122     for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext();) {
123       FlatNode fn=it.next();
124       if (atomictab.get(fn).intValue()==0&&fn.numPrev()>0&&
125           atomictab.get(fn.getPrev(0)).intValue()>0) {
126         //sanity check
127         assert(fn.kind()==FKind.FlatAtomicExitNode);
128         //insert calls here...
129         Set<TempDescriptor> tempset=nodetoconvs.get(fn);
130         for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext();) {
131           FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, false);
132           atomictab.put(fgcn, atomictab.get(fn));
133           temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>)temptab.get(fn).clone());
134
135           for(int i=0; i<fn.numPrev(); i++) {
136             FlatNode fnprev=fn.getPrev(i);
137             for(int j=0; j<fnprev.numNext(); j++) {
138               if (fnprev.getNext(j)==fn) {
139                 //found index, change node
140                 fnprev.setNext(j, fgcn);
141                 break;
142               }
143             }
144           }
145           fgcn.addNext(fn);
146         }
147       }
148     }
149   }
150
151   /* At the beginning of an atomic block, we need to convert any
152    * OID's that will be used in the atomic block to pointers */
153
154   private void converttoPtr(LocalityBinding lb) {
155     Hashtable<FlatNode, Set<TempDescriptor>> nodetotranstemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
156     Hashtable<FlatNode, Integer> atomictab=locality.getAtomic(lb);
157     Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=locality.getNodeTempInfo(lb);
158     MethodDescriptor md=lb.getMethod();
159     FlatMethod fm=state.getMethodFlat(md);
160     Set<FlatNode> toprocess=fm.getNodeSet();
161
162     while(!toprocess.isEmpty()) {
163       FlatNode fn=toprocess.iterator().next();
164       toprocess.remove(fn);
165
166       if (atomictab.get(fn).intValue()>0) {
167         //build set of transaction temps use by next nodes
168         HashSet<TempDescriptor> transtemps=new HashSet<TempDescriptor>();
169         for(int i=0; i<fn.numNext(); i++) {
170           FlatNode fnnext=fn.getNext(i);
171           if (nodetotranstemps.containsKey(fnnext))
172             transtemps.addAll(nodetotranstemps.get(fnnext));
173         }
174         //subtract out the ones we write to
175         transtemps.removeAll(Arrays.asList(fn.writesTemps()));
176         //add in the globals we read from
177         Hashtable<TempDescriptor, Integer> pretemptab=locality.getNodePreTempInfo(lb, fn);
178         TempDescriptor [] readtemps=fn.readsTemps();
179         for(int i=0; i<readtemps.length; i++) {
180           TempDescriptor tmp=readtemps[i];
181           if (pretemptab.get(tmp).intValue()==LocalityAnalysis.GLOBAL) {
182             transtemps.add(tmp);
183           }
184         }
185         if (!nodetotranstemps.containsKey(fn)||!nodetotranstemps.get(fn).equals(transtemps)) {
186           nodetotranstemps.put(fn, transtemps);
187           for(int i=0; i<fn.numPrev(); i++)
188             toprocess.add(fn.getPrev(i));
189         }
190       }
191     }
192     toprocess=fm.getNodeSet();
193     for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext();) {
194       FlatNode fn=it.next();
195       if (atomictab.get(fn).intValue()>0&&
196           atomictab.get(fn.getPrev(0)).intValue()==0) {
197         //sanity check
198         assert(fn.kind()==FKind.FlatAtomicEnterNode);
199
200         //insert calls here...
201         Set<TempDescriptor> tempset=nodetotranstemps.get(fn);
202         for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext();) {
203           FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, true);
204           atomictab.put(fgcn, atomictab.get(fn));
205           temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>)temptab.get(fn).clone());
206           fgcn.addNext(fn.getNext(0));
207           fn.setNext(0, fgcn);
208         }
209       }
210     }
211   }
212 }