1 package Analysis.Locality;
5 import IR.MethodDescriptor;
8 public class GenerateConversions {
9 LocalityAnalysis locality;
12 /** Warning: This class modifies the code in place. */
14 public GenerateConversions(LocalityAnalysis la, State state) {
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
33 /* At the end of an atomic block, we need to convert any global
34 * references that will be used again into OID's. */
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>>();
44 Set<FlatNode> toprocess=fm.getNodeSet();
46 while(!toprocess.isEmpty()) {
47 FlatNode fn=toprocess.iterator().next();
49 boolean isatomic=atomictab.get(fn).intValue()>0;
50 if (!isatomic && fn.kind()!=FKind.FlatAtomicExitNode)//Don't process past the bounds of a transaction
53 Hashtable<TempDescriptor, Integer> nodetemptab=temptab.get(fn);
55 List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
56 List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
58 if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode
59 &&!nodetoconvs.containsKey(fn))
60 nodetoconvs.put(fn, new HashSet<TempDescriptor>());
62 HashSet<TempNodePair> tempset=new HashSet<TempNodePair>();
64 for(int i=0; i<fn.numPrev(); i++) {
65 FlatNode fnprev=fn.getPrev(i);
66 if (!nodetotnpair.containsKey(fnprev))
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) {
78 if (writes.contains(tnp.getTemp())) //value overwritten
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
91 /* If this is in an atomic block, record temps that
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*/
99 if (fn.kind()!=FKind.FlatGlobalConvNode||
100 ((FlatGlobalConvNode)fn).getLocality()==lb) {
101 /*If globalconvnode, make sure we have the right
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);
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));
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) {
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());
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);
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 */
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();
162 while(!toprocess.isEmpty()) {
163 FlatNode fn=toprocess.iterator().next();
164 toprocess.remove(fn);
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));
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) {
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));
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) {
198 assert(fn.kind()==FKind.FlatAtomicEnterNode);
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));