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