More pieces for new version of analysis
[IRC.git] / Robust / src / Analysis / Locality / DiscoverConflicts.java
1 package Analysis.Locality;
2
3 import IR.Flat.*;
4 import java.util.Set;
5 import java.util.Arrays;
6 import java.util.HashSet;
7 import java.util.Iterator;
8 import java.util.Hashtable;
9 import IR.State;
10 import IR.Operation;
11 import IR.TypeDescriptor;
12 import IR.MethodDescriptor;
13 import IR.FieldDescriptor;
14 import Analysis.Liveness;
15 import Analysis.Loops.GlobalFieldType;
16
17 public class DiscoverConflicts {
18   Set<FieldDescriptor> fields;
19   Set<TypeDescriptor> arrays;
20   LocalityAnalysis locality;
21   State state;
22   Hashtable<LocalityBinding, Set<FlatNode>> treadmap;
23   Hashtable<LocalityBinding, Set<TempFlatPair>> transreadmap;
24   Hashtable<LocalityBinding, Set<FlatNode>> twritemap;
25   Hashtable<LocalityBinding, Set<TempFlatPair>> writemap;
26   Hashtable<LocalityBinding, Set<FlatNode>> getmap;
27
28   Hashtable<LocalityBinding, Set<FlatNode>> srcmap;
29   Hashtable<LocalityBinding, Set<FlatNode>> leftsrcmap;
30   Hashtable<LocalityBinding, Set<FlatNode>> rightsrcmap;
31   TypeAnalysis typeanalysis;
32   Hashtable<LocalityBinding, HashSet<FlatNode>>cannotdelaymap;
33   Hashtable<LocalityBinding, Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>>> lbtofnmap;
34   boolean inclusive=false;
35   boolean normalassign=false;
36   GlobalFieldType gft;
37
38   public DiscoverConflicts(LocalityAnalysis locality, State state, TypeAnalysis typeanalysis, GlobalFieldType gft) {
39     this.locality=locality;
40     this.fields=new HashSet<FieldDescriptor>();
41     this.arrays=new HashSet<TypeDescriptor>();
42     this.state=state;
43     this.typeanalysis=typeanalysis;
44     transreadmap=new Hashtable<LocalityBinding, Set<TempFlatPair>>();
45     treadmap=new Hashtable<LocalityBinding, Set<FlatNode>>();
46     srcmap=new Hashtable<LocalityBinding, Set<FlatNode>>();
47     leftsrcmap=new Hashtable<LocalityBinding, Set<FlatNode>>();
48     rightsrcmap=new Hashtable<LocalityBinding, Set<FlatNode>>();
49     lbtofnmap=new Hashtable<LocalityBinding, Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>>>();
50     if (gft!=null) {
51       twritemap=new Hashtable<LocalityBinding, Set<FlatNode>>();
52       writemap=new Hashtable<LocalityBinding, Set<TempFlatPair>>();
53     }
54     getmap=new Hashtable<LocalityBinding, Set<FlatNode>>();
55     this.gft=gft;
56   }
57
58   public DiscoverConflicts(LocalityAnalysis locality, State state, TypeAnalysis typeanalysis, Hashtable<LocalityBinding, HashSet<FlatNode>> cannotdelaymap, boolean inclusive, boolean normalassign, GlobalFieldType gft) {
59     this.locality=locality;
60     this.fields=new HashSet<FieldDescriptor>();
61     this.arrays=new HashSet<TypeDescriptor>();
62     this.state=state;
63     this.typeanalysis=typeanalysis;
64     this.cannotdelaymap=cannotdelaymap;
65     transreadmap=new Hashtable<LocalityBinding, Set<TempFlatPair>>();
66     treadmap=new Hashtable<LocalityBinding, Set<FlatNode>>();
67     srcmap=new Hashtable<LocalityBinding, Set<FlatNode>>();
68     leftsrcmap=new Hashtable<LocalityBinding, Set<FlatNode>>();
69     rightsrcmap=new Hashtable<LocalityBinding, Set<FlatNode>>();
70     lbtofnmap=new Hashtable<LocalityBinding, Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>>>();
71     this.inclusive=inclusive;
72     this.normalassign=normalassign;
73     if (gft!=null) {
74       twritemap=new Hashtable<LocalityBinding, Set<FlatNode>>();
75       writemap=new Hashtable<LocalityBinding, Set<TempFlatPair>>();
76     }
77     getmap=new Hashtable<LocalityBinding, Set<FlatNode>>();
78     this.gft=gft;
79   }
80
81   public Set<FieldDescriptor> getFields() {
82     return fields;
83   }
84
85   public Set<TypeDescriptor> getArrays() {
86     return arrays;
87   }
88   
89   public void doAnalysis() {
90     //Compute fields and arrays for all transactions.  Note that we
91     //only look at changes to old objects
92
93     Set<LocalityBinding> localityset=locality.getLocalityBindings();
94     for(Iterator<LocalityBinding> lb=localityset.iterator();lb.hasNext();) {
95       computeModified(lb.next());
96     }
97     expandTypes();
98     //Compute set of nodes that need transread
99     for(Iterator<LocalityBinding> lb=localityset.iterator();lb.hasNext();) {
100       LocalityBinding l=lb.next();
101       analyzeLocality(l);
102     }
103   }
104
105   //Change flatnode/temp pairs to just flatnodes that need transactional reads
106
107   private void setNeedReadTrans(LocalityBinding lb) {
108     HashSet<FlatNode> set=new HashSet<FlatNode>();
109     for(Iterator<TempFlatPair> it=transreadmap.get(lb).iterator();it.hasNext();) {
110       TempFlatPair tfp=it.next();
111       set.add(tfp.f);
112     }
113     treadmap.put(lb, set);
114     if (gft!=null) {
115       //need to translate write map set
116       set=new HashSet<FlatNode>();
117       for(Iterator<TempFlatPair> it=writemap.get(lb).iterator();it.hasNext();) {
118         TempFlatPair tfp=it.next();
119         set.add(tfp.f);
120       }
121       twritemap.put(lb, set);
122     }
123   }
124   
125   private void computeneedsarrayget(LocalityBinding lb, Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>> fnmap) {
126     //    Set<FlatNode> gwriteset=(state.READSET&&gft!=null)?twritemap.get(lb):treadmap.get(lb);
127     if (state.READSET&&gft!=null) {
128       if (twritemap.get(lb).size()==0) {
129         getmap.put(lb, new HashSet<FlatNode>());
130         return;
131       }
132     }
133
134     Set<FlatNode> gwriteset=treadmap.get(lb);
135     FlatMethod fm=state.getMethodFlat(lb.getMethod());
136     HashSet<FlatNode> needsget=new HashSet<FlatNode>();
137     for(Iterator<FlatNode> fnit=fm.getNodeSet().iterator();fnit.hasNext();) {
138       FlatNode fn=fnit.next();
139       Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
140       if (atomictable.get(fn).intValue()>0&&fn.kind()==FKind.FlatElementNode) {
141         FlatElementNode fen=(FlatElementNode)fn;
142         Set<TempFlatPair> tfpset=fnmap.get(fen).get(fen.getSrc());
143         if (tfpset!=null) {
144           for(Iterator<TempFlatPair> tfpit=tfpset.iterator();tfpit.hasNext();) {
145             TempFlatPair tfp=tfpit.next();
146             if (gwriteset.contains(tfp.f)) {
147               needsget.add(fen);
148               break;
149             }
150           }
151         }
152       }
153     }
154     getmap.put(lb, needsget);
155   }
156
157   //We have a set of things we write to, figure out what things this
158   //could effect.
159   public void expandTypes() {
160     Set<TypeDescriptor> expandedarrays=new HashSet<TypeDescriptor>();
161     for(Iterator<TypeDescriptor> it=arrays.iterator();it.hasNext();) {
162       TypeDescriptor td=it.next();
163       expandedarrays.addAll(typeanalysis.expand(td));
164     }
165     arrays=expandedarrays;
166   }
167
168   Hashtable<TempDescriptor, Set<TempFlatPair>> doMerge(FlatNode fn, Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>> tmptofnset) {
169     Hashtable<TempDescriptor, Set<TempFlatPair>> table=new Hashtable<TempDescriptor, Set<TempFlatPair>>();
170     for(int i=0;i<fn.numPrev();i++) {
171       FlatNode fprev=fn.getPrev(i);
172       Hashtable<TempDescriptor, Set<TempFlatPair>> tabset=tmptofnset.get(fprev);
173       if (tabset!=null) {
174         for(Iterator<TempDescriptor> tmpit=tabset.keySet().iterator();tmpit.hasNext();) {
175           TempDescriptor td=tmpit.next();
176           Set<TempFlatPair> fnset=tabset.get(td);
177           if (!table.containsKey(td))
178             table.put(td, new HashSet<TempFlatPair>());
179           table.get(td).addAll(fnset);
180         }
181       }
182     }
183     return table;
184   }
185   
186   public Set<FlatNode> getNeedSrcTrans(LocalityBinding lb) {
187     return srcmap.get(lb);
188   }
189
190   public boolean getNeedSrcTrans(LocalityBinding lb, FlatNode fn) {
191     return srcmap.get(lb).contains(fn);
192   }
193
194   public boolean getNeedLeftSrcTrans(LocalityBinding lb, FlatNode fn) {
195     return leftsrcmap.get(lb).contains(fn);
196   }
197
198   public boolean getNeedRightSrcTrans(LocalityBinding lb, FlatNode fn) {
199     return rightsrcmap.get(lb).contains(fn);
200   }
201
202   public boolean getNeedTrans(LocalityBinding lb, FlatNode fn) {
203     return treadmap.get(lb).contains(fn);
204   }
205
206   public boolean getNeedGet(LocalityBinding lb, FlatNode fn) {
207     if (gft!=null)
208       return getmap.get(lb).contains(fn);
209     else throw new Error();
210   }
211
212   public boolean getNeedWriteTrans(LocalityBinding lb, FlatNode fn) {
213     if (gft!=null)
214       return twritemap.get(lb).contains(fn);
215     else throw new Error();
216   }
217
218   public Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>> getMap(LocalityBinding lb) {
219     return lbtofnmap.get(lb);
220   }
221
222   private void analyzeLocality(LocalityBinding lb) {
223     MethodDescriptor md=lb.getMethod();
224     FlatMethod fm=state.getMethodFlat(md);
225
226     //Compute map from flatnode -> (temps -> source of value)
227     Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>> fnmap=computeTempSets(lb);
228     lbtofnmap.put(lb,fnmap);
229     HashSet<TempFlatPair> writeset=null;
230     if (gft!=null) {
231       writeset=new HashSet<TempFlatPair>();
232     }
233     HashSet<TempFlatPair> tfset=computeTranslationSet(lb, fm, fnmap, writeset);
234     if (gft!=null) {
235       writemap.put(lb, writeset);
236     }
237
238     HashSet<FlatNode> srctrans=new HashSet<FlatNode>();
239     HashSet<FlatNode> leftsrctrans=new HashSet<FlatNode>();
240     HashSet<FlatNode> rightsrctrans=new HashSet<FlatNode>();
241     transreadmap.put(lb, tfset);
242     srcmap.put(lb,srctrans);
243     leftsrcmap.put(lb,leftsrctrans);
244     rightsrcmap.put(lb,rightsrctrans);
245
246     //compute writes that need translation on source
247     for(Iterator<FlatNode> fnit=fm.getNodeSet().iterator();fnit.hasNext();) {
248       FlatNode fn=fnit.next();
249       Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
250       if (atomictable.get(fn).intValue()>0) {
251         Hashtable<TempDescriptor, Set<TempFlatPair>> tmap=fnmap.get(fn);
252         switch(fn.kind()) {
253           //We might need to translate arguments to pointer comparison
254           
255         case FKind.FlatOpNode: { 
256           FlatOpNode fon=(FlatOpNode)fn;
257           if (fon.getOp().getOp()==Operation.EQUAL||
258               fon.getOp().getOp()==Operation.NOTEQUAL) {
259             if (!fon.getLeft().getType().isPtr())
260               break;
261             Set<TempFlatPair> lefttfpset=tmap.get(fon.getLeft());
262             Set<TempFlatPair> righttfpset=tmap.get(fon.getRight());
263             //handle left operand
264             if (lefttfpset!=null) {
265               for(Iterator<TempFlatPair> tfpit=lefttfpset.iterator();tfpit.hasNext();) {
266                 TempFlatPair tfp=tfpit.next();
267                 if (tfset.contains(tfp)||outofscope(tfp)) {
268                   leftsrctrans.add(fon);
269                   break;
270                 }
271               }
272             }
273             //handle right operand
274             if (righttfpset!=null) {
275               for(Iterator<TempFlatPair> tfpit=righttfpset.iterator();tfpit.hasNext();) {
276                 TempFlatPair tfp=tfpit.next();
277                 if (tfset.contains(tfp)||outofscope(tfp)) {
278                   rightsrctrans.add(fon);
279                   break;
280                 }
281               }
282             }
283           }
284           break;
285         }
286
287         case FKind.FlatGlobalConvNode: { 
288           //need to translate these if the value we read from may be a
289           //shadow...  check this by seeing if any of the values we
290           //may read are in the transread set or came from our caller
291           //or a method we called
292
293           FlatGlobalConvNode fgcn=(FlatGlobalConvNode)fn;
294           if (fgcn.getLocality()!=lb||
295               fgcn.getMakePtr())
296             break;
297
298           Set<TempFlatPair> tfpset=tmap.get(fgcn.getSrc());
299
300           if (tfpset!=null) {
301             for(Iterator<TempFlatPair> tfpit=tfpset.iterator();tfpit.hasNext();) {
302               TempFlatPair tfp=tfpit.next();
303               if (tfset.contains(tfp)||outofscope(tfp)) {
304                 srctrans.add(fgcn);
305                 break;
306               }
307             }
308           }
309           break;
310         }
311
312         case FKind.FlatSetFieldNode: { 
313           //need to translate these if the value we read from may be a
314           //shadow...  check this by seeing if any of the values we
315           //may read are in the transread set or came from our caller
316           //or a method we called
317
318           FlatSetFieldNode fsfn=(FlatSetFieldNode)fn;
319           if (!fsfn.getField().getType().isPtr())
320             break;
321           Set<TempFlatPair> tfpset=tmap.get(fsfn.getSrc());
322           if (tfpset!=null) {
323             for(Iterator<TempFlatPair> tfpit=tfpset.iterator();tfpit.hasNext();) {
324               TempFlatPair tfp=tfpit.next();
325               if (tfset.contains(tfp)||outofscope(tfp)) {
326                 srctrans.add(fsfn);
327                 break;
328               }
329             }
330           }
331           break;
332         }
333         case FKind.FlatSetElementNode: { 
334           //need to translate these if the value we read from may be a
335           //shadow...  check this by seeing if any of the values we
336           //may read are in the transread set or came from our caller
337           //or a method we called
338
339           FlatSetElementNode fsen=(FlatSetElementNode)fn;
340           if (!fsen.getSrc().getType().isPtr())
341             break;
342           Set<TempFlatPair> tfpset=tmap.get(fsen.getSrc());
343           if (tfpset!=null) {
344             for(Iterator<TempFlatPair> tfpit=tfpset.iterator();tfpit.hasNext();) {
345               TempFlatPair tfp=tfpit.next();
346               if (tfset.contains(tfp)||outofscope(tfp)) {
347                 srctrans.add(fsen);
348                 break;
349               }
350             }
351           }
352           break;
353         }
354         default:
355         }
356       }
357     }
358     //Update results
359     setNeedReadTrans(lb);
360     computeneedsarrayget(lb, fnmap);
361   }
362
363   public boolean outofscope(TempFlatPair tfp) {
364     FlatNode fn=tfp.f;
365     return fn.kind()==FKind.FlatCall||fn.kind()==FKind.FlatMethod;
366   }
367
368   private void computeReadOnly(LocalityBinding lb, Hashtable<FlatNode, Set<TypeDescriptor>> updatedtypemap, Hashtable<FlatNode, Set<FieldDescriptor>> updatedfieldmap) {
369     //inside of transaction, try to convert rw access to ro access
370     MethodDescriptor md=lb.getMethod();
371     FlatMethod fm=state.getMethodFlat(md);
372     Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
373
374     HashSet<FlatNode> toanalyze=new HashSet<FlatNode>();
375     toanalyze.addAll(fm.getNodeSet());
376     
377     while(!toanalyze.isEmpty()) {
378       FlatNode fn=toanalyze.iterator().next();
379       toanalyze.remove(fn);
380       HashSet<TypeDescriptor> updatetypeset=new HashSet<TypeDescriptor>();
381       HashSet<FieldDescriptor> updatefieldset=new HashSet<FieldDescriptor>();
382       
383       //Stop if we aren't in a transaction
384       if (atomictable.get(fn).intValue()==0)
385         continue;
386       
387       //Do merge of all exits
388       for(int i=0;i<fn.numNext();i++) {
389         FlatNode fnnext=fn.getNext(i);
390         if (updatedtypemap.containsKey(fnnext)) {
391           updatetypeset.addAll(updatedtypemap.get(fnnext));
392         }
393         if (updatedfieldmap.containsKey(fnnext)) {
394           updatefieldset.addAll(updatedfieldmap.get(fnnext));
395         }
396       }
397       
398       //process this node
399       if (cannotdelaymap!=null&&cannotdelaymap.containsKey(lb)&&cannotdelaymap.get(lb).contains(fn)!=inclusive) {
400         switch(fn.kind()) {
401         case FKind.FlatSetFieldNode: {
402           FlatSetFieldNode fsfn=(FlatSetFieldNode)fn;
403           updatefieldset.add(fsfn.getField());
404           break;
405         }
406         case FKind.FlatSetElementNode: {
407           FlatSetElementNode fsen=(FlatSetElementNode)fn;
408           updatetypeset.addAll(typeanalysis.expand(fsen.getDst().getType()));
409           break;
410         }
411         case FKind.FlatCall: {
412           FlatCall fcall=(FlatCall)fn;
413           MethodDescriptor mdfc=fcall.getMethod();
414           
415           //get modified fields
416           Set<FieldDescriptor> fields=gft.getFieldsAll(mdfc);
417           updatefieldset.addAll(fields);
418           
419           //get modified arrays
420           Set<TypeDescriptor> arrays=gft.getArraysAll(mdfc);
421           updatetypeset.addAll(typeanalysis.expandSet(arrays));
422           break;
423         }
424         }
425       }
426       
427       if (!updatedtypemap.containsKey(fn)||!updatedfieldmap.containsKey(fn)||
428           !updatedtypemap.get(fn).equals(updatetypeset)||!updatedfieldmap.get(fn).equals(updatefieldset)) {
429         updatedtypemap.put(fn, updatetypeset);
430         updatedfieldmap.put(fn, updatefieldset);
431         for(int i=0;i<fn.numPrev();i++) {
432           toanalyze.add(fn.getPrev(i));
433         }
434       }
435     }
436   }
437
438
439   /** Need to figure out which nodes need a transread to make local
440   copies.  Transread conceptually tracks conflicts.  This depends on
441   what fields/elements are accessed We iterate over all flatnodes that
442   access fields...If these accesses could conflict, we mark the source
443   tempflat pair as needing a transread */
444
445   
446   HashSet<TempFlatPair> computeTranslationSet(LocalityBinding lb, FlatMethod fm, Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>> fnmap, Set<TempFlatPair> writeset) {
447     HashSet<TempFlatPair> tfset=new HashSet<TempFlatPair>();
448
449     //Compute maps from flatnodes -> sets of things that may be updated after this node
450     Hashtable<FlatNode, Set<TypeDescriptor>> updatedtypemap=null;
451     Hashtable<FlatNode, Set<FieldDescriptor>> updatedfieldmap=null;
452
453     if (writeset!=null&&!lb.isAtomic()) {
454       updatedtypemap=new Hashtable<FlatNode, Set<TypeDescriptor>>();
455       updatedfieldmap=new Hashtable<FlatNode, Set<FieldDescriptor>>();
456       computeReadOnly(lb, updatedtypemap, updatedfieldmap);
457     }
458
459     for(Iterator<FlatNode> fnit=fm.getNodeSet().iterator();fnit.hasNext();) {
460       FlatNode fn=fnit.next();
461       //Check whether this node matters for cannot delayed computation
462       if (cannotdelaymap!=null&&cannotdelaymap.containsKey(lb)&&cannotdelaymap.get(lb).contains(fn)==inclusive)
463         continue;
464
465       Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
466       if (atomictable.get(fn).intValue()>0) {
467         Hashtable<TempDescriptor, Set<TempFlatPair>> tmap=fnmap.get(fn);
468         switch(fn.kind()) {
469         case FKind.FlatElementNode: {
470           FlatElementNode fen=(FlatElementNode)fn;
471           if (arrays.contains(fen.getSrc().getType())) {
472             //this could cause conflict...figure out conflict set
473             Set<TempFlatPair> tfpset=tmap.get(fen.getSrc());
474             if (tfpset!=null)
475               tfset.addAll(tfpset);
476           }
477           if (updatedtypemap!=null&&updatedtypemap.get(fen).contains(fen.getSrc().getType())) {
478             //this could cause conflict...figure out conflict set
479             Set<TempFlatPair> tfpset=tmap.get(fen.getSrc());
480             if (tfpset!=null)
481               tfset.addAll(tfpset);
482           }
483           break;
484         }
485         case FKind.FlatFieldNode: { 
486           FlatFieldNode ffn=(FlatFieldNode)fn;
487           if (fields.contains(ffn.getField())) {
488             //this could cause conflict...figure out conflict set
489             Set<TempFlatPair> tfpset=tmap.get(ffn.getSrc());
490             if (tfpset!=null)
491               tfset.addAll(tfpset);
492           }
493           if (updatedfieldmap!=null&&updatedfieldmap.get(ffn).contains(ffn.getField())) {
494             //this could cause conflict...figure out conflict set
495             Set<TempFlatPair> tfpset=tmap.get(ffn.getSrc());
496             if (tfpset!=null)
497               tfset.addAll(tfpset);
498           }
499           break;
500         }
501         case FKind.FlatSetFieldNode: { 
502           //definitely need to translate these
503           FlatSetFieldNode fsfn=(FlatSetFieldNode)fn;
504           Set<TempFlatPair> tfpset=tmap.get(fsfn.getDst());
505           if (tfpset!=null)
506             tfset.addAll(tfpset);
507           if (writeset!=null) {
508             if (tfpset!=null)
509               writeset.addAll(tfpset);
510           }
511           break;
512         }
513         case FKind.FlatSetElementNode: { 
514           //definitely need to translate these
515           FlatSetElementNode fsen=(FlatSetElementNode)fn;
516           Set<TempFlatPair> tfpset=tmap.get(fsen.getDst());
517           if (tfpset!=null)
518             tfset.addAll(tfpset);
519           if (writeset!=null) {
520             if (tfpset!=null)
521               writeset.addAll(tfpset);
522           }
523           break;
524         }
525         case FKind.FlatCall: //assume pessimistically that calls do bad things
526         case FKind.FlatReturnNode: {
527           TempDescriptor []readarray=fn.readsTemps();
528           for(int i=0;i<readarray.length;i++) {
529             TempDescriptor rtmp=readarray[i];
530             Set<TempFlatPair> tfpset=tmap.get(rtmp);
531             if (tfpset!=null)
532               tfset.addAll(tfpset);
533             if (writeset!=null) {
534               if (tfpset!=null)
535                 writeset.addAll(tfpset);
536             }
537           }
538           break;
539         }
540         default:
541           //do nothing
542         }
543       }
544     }   
545     return tfset;
546   }
547
548
549   //This method generates as output for each node
550   //A map from from temps to a set of temp/flat pairs that the
551   //original temp points to
552   //A temp/flat pair gives the flatnode that the value was created at
553   //and the original temp
554
555   Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>> computeTempSets(LocalityBinding lb) {
556     Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>> tmptofnset=new Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>>();
557     HashSet<FlatNode> discovered=new HashSet<FlatNode>();
558     HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
559     MethodDescriptor md=lb.getMethod();
560     FlatMethod fm=state.getMethodFlat(md);
561     Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
562     Hashtable<FlatNode, Set<TempDescriptor>> livetemps=Liveness.computeLiveTemps(fm);
563     tovisit.add(fm);
564     discovered.add(fm);
565     
566     while(!tovisit.isEmpty()) {
567       FlatNode fn=tovisit.iterator().next();
568       tovisit.remove(fn);
569       for(int i=0;i<fn.numNext();i++) {
570         FlatNode fnext=fn.getNext(i);
571         if (!discovered.contains(fnext)) {
572           discovered.add(fnext);
573           tovisit.add(fnext);
574         }
575       }
576       Hashtable<TempDescriptor, Set<TempFlatPair>> ttofn=null;
577       if (atomictable.get(fn).intValue()!=0) {
578         if ((fn.numPrev()>0)&&atomictable.get(fn.getPrev(0)).intValue()==0) {
579           //atomic node, start with new set
580           ttofn=new Hashtable<TempDescriptor, Set<TempFlatPair>>();
581         } else {
582           ttofn=doMerge(fn, tmptofnset);
583           switch(fn.kind()) {
584           case FKind.FlatGlobalConvNode: {
585             FlatGlobalConvNode fgcn=(FlatGlobalConvNode)fn;
586             if (lb==fgcn.getLocality()&&
587                 fgcn.getMakePtr()) {
588               TempDescriptor[] writes=fn.writesTemps();
589               for(int i=0;i<writes.length;i++) {
590                 TempDescriptor wtmp=writes[i];
591                 HashSet<TempFlatPair> set=new HashSet<TempFlatPair>();
592                 set.add(new TempFlatPair(wtmp, fn));
593                 ttofn.put(wtmp, set);
594               }
595             }
596             break;
597           }
598           case FKind.FlatFieldNode:
599           case FKind.FlatElementNode: {
600             TempDescriptor[] writes=fn.writesTemps();
601             for(int i=0;i<writes.length;i++) {
602               TempDescriptor wtmp=writes[i];
603               HashSet<TempFlatPair> set=new HashSet<TempFlatPair>();
604               set.add(new TempFlatPair(wtmp, fn));
605               ttofn.put(wtmp, set);
606             }
607             break;
608           }
609           case FKind.FlatCall:
610           case FKind.FlatMethod: {
611             TempDescriptor[] writes=fn.writesTemps();
612             for(int i=0;i<writes.length;i++) {
613               TempDescriptor wtmp=writes[i];
614               HashSet<TempFlatPair> set=new HashSet<TempFlatPair>();
615               set.add(new TempFlatPair(wtmp, fn));
616               ttofn.put(wtmp, set);
617             }
618             break;
619           }
620           case FKind.FlatCastNode:
621           case FKind.FlatOpNode: 
622             if (fn.kind()==FKind.FlatCastNode) {
623               FlatCastNode fcn=(FlatCastNode)fn;
624               if (fcn.getDst().getType().isPtr()) {
625                 HashSet<TempFlatPair> set=new HashSet<TempFlatPair>();
626                 if (ttofn.containsKey(fcn.getSrc()))
627                   set.addAll(ttofn.get(fcn.getSrc()));
628                 if (normalassign)
629                   set.add(new TempFlatPair(fcn.getDst(), fn));
630                 ttofn.put(fcn.getDst(), set);
631                 break;
632               }
633             } else if (fn.kind()==FKind.FlatOpNode) {
634               FlatOpNode fon=(FlatOpNode)fn;
635               if (fon.getOp().getOp()==Operation.ASSIGN&&fon.getDest().getType().isPtr()) {
636                 HashSet<TempFlatPair> set=new HashSet<TempFlatPair>();
637                 if (ttofn.containsKey(fon.getLeft()))
638                   set.addAll(ttofn.get(fon.getLeft()));
639                 if (normalassign)
640                   set.add(new TempFlatPair(fon.getDest(), fn));
641                 ttofn.put(fon.getDest(), set);
642                 break;
643               }
644             }
645           default:
646             //Do kill computation
647             TempDescriptor[] writes=fn.writesTemps();
648             for(int i=0;i<writes.length;i++) {
649               TempDescriptor wtmp=writes[i];
650               ttofn.remove(writes[i]);
651             }
652           }
653         }
654         if (ttofn!=null) {
655           if (!tmptofnset.containsKey(fn)||
656               !tmptofnset.get(fn).equals(ttofn)) {
657             //enqueue nodes to process
658             tmptofnset.put(fn, ttofn);
659             for(int i=0;i<fn.numNext();i++) {
660               FlatNode fnext=fn.getNext(i);
661               tovisit.add(fnext);
662             }
663           }
664         }
665       }
666     }
667     return tmptofnset;
668   }
669   
670   /* See what fields and arrays transactions might modify.  We only
671    * look at changes to old objects. */
672
673   //Bug fix: original version forget to check if object is new and
674   //could be optimized
675
676   public void computeModified(LocalityBinding lb) {
677     MethodDescriptor md=lb.getMethod();
678     FlatMethod fm=state.getMethodFlat(md);
679     Hashtable<FlatNode, Set<TempDescriptor>> oldtemps=computeOldTemps(lb);
680     for(Iterator<FlatNode> fnit=fm.getNodeSet().iterator();fnit.hasNext();) {
681       FlatNode fn=fnit.next();
682       Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
683       if (atomictable.get(fn).intValue()>0) {
684         Set<TempDescriptor> oldtemp=oldtemps.get(fn);
685         switch (fn.kind()) {
686         case FKind.FlatSetFieldNode:
687           FlatSetFieldNode fsfn=(FlatSetFieldNode) fn;
688           if (oldtemp.contains(fsfn.getDst()))
689             fields.add(fsfn.getField());
690           break;
691         case FKind.FlatSetElementNode:
692           FlatSetElementNode fsen=(FlatSetElementNode) fn;
693           if (oldtemp.contains(fsen.getDst()))
694             arrays.add(fsen.getDst().getType());
695           break;
696         default:
697         }
698       }
699     }
700   }
701     
702
703   //Returns a table that maps a flatnode to a set of temporaries
704   //This set of temporaries is old (meaning they may point to object
705   //allocated before the beginning of the current transaction
706
707   Hashtable<FlatNode, Set<TempDescriptor>> computeOldTemps(LocalityBinding lb) {
708     Hashtable<FlatNode, Set<TempDescriptor>> fntooldtmp=new Hashtable<FlatNode, Set<TempDescriptor>>();
709     HashSet<FlatNode> discovered=new HashSet<FlatNode>();
710     HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
711     MethodDescriptor md=lb.getMethod();
712     FlatMethod fm=state.getMethodFlat(md);
713     Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
714     Hashtable<FlatNode, Set<TempDescriptor>> livetemps=Liveness.computeLiveTemps(fm);
715     tovisit.add(fm);
716     discovered.add(fm);
717     
718     while(!tovisit.isEmpty()) {
719       FlatNode fn=tovisit.iterator().next();
720       tovisit.remove(fn);
721       for(int i=0;i<fn.numNext();i++) {
722         FlatNode fnext=fn.getNext(i);
723         if (!discovered.contains(fnext)) {
724           discovered.add(fnext);
725           tovisit.add(fnext);
726         }
727       }
728       HashSet<TempDescriptor> oldtemps=null;
729       if (atomictable.get(fn).intValue()!=0) {
730         if ((fn.numPrev()>0)&&atomictable.get(fn.getPrev(0)).intValue()==0) {
731           //Everything live is old
732           Set<TempDescriptor> lives=livetemps.get(fn);
733           oldtemps=new HashSet<TempDescriptor>();
734           
735           for(Iterator<TempDescriptor> it=lives.iterator();it.hasNext();) {
736             TempDescriptor tmp=it.next();
737             if (tmp.getType().isPtr()) {
738               oldtemps.add(tmp);
739             }
740           }
741         } else {
742           oldtemps=new HashSet<TempDescriptor>();
743           //Compute union of old temporaries
744           for(int i=0;i<fn.numPrev();i++) {
745             Set<TempDescriptor> pset=fntooldtmp.get(fn.getPrev(i));
746             if (pset!=null)
747               oldtemps.addAll(pset);
748           }
749           
750           switch (fn.kind()) {
751           case FKind.FlatNew:
752             oldtemps.removeAll(Arrays.asList(fn.readsTemps()));
753             break;
754           case FKind.FlatOpNode:
755           case FKind.FlatCastNode: 
756             if (fn.kind()==FKind.FlatCastNode) {
757               FlatCastNode fcn=(FlatCastNode)fn;
758               if (fcn.getDst().getType().isPtr()) {
759                 if (oldtemps.contains(fcn.getSrc()))
760                   oldtemps.add(fcn.getDst());
761                 else
762                   oldtemps.remove(fcn.getDst());
763                 break;
764               }
765             } else if (fn.kind()==FKind.FlatOpNode) {
766               FlatOpNode fon=(FlatOpNode)fn;
767               if (fon.getOp().getOp()==Operation.ASSIGN&&fon.getDest().getType().isPtr()) {
768                 if (oldtemps.contains(fon.getLeft()))
769                   oldtemps.add(fon.getDest());
770                 else
771                   oldtemps.remove(fon.getDest());
772                 break;
773               }
774             }
775           default: {
776             TempDescriptor[] writes=fn.writesTemps();
777             for(int i=0;i<writes.length;i++) {
778               TempDescriptor wtemp=writes[i];
779               if (wtemp.getType().isPtr())
780                 oldtemps.add(wtemp);
781             }
782           }
783           }
784         }
785       }
786       
787       if (oldtemps!=null) {
788         if (!fntooldtmp.containsKey(fn)||!fntooldtmp.get(fn).equals(oldtemps)) {
789           fntooldtmp.put(fn, oldtemps);
790           //propagate changes
791           for(int i=0;i<fn.numNext();i++) {
792             FlatNode fnext=fn.getNext(i);
793             tovisit.add(fnext);
794           }
795         }
796       }
797     }
798     return fntooldtmp;
799   }
800 }
801
802 class TempFlatPair {
803   FlatNode f;
804   TempDescriptor t;
805   TempFlatPair(TempDescriptor t, FlatNode f) {
806     this.t=t;
807     this.f=f;
808   }
809   
810   public int hashCode() {
811     return f.hashCode()^t.hashCode();
812   }
813   public boolean equals(Object o) {
814     TempFlatPair tf=(TempFlatPair)o;
815     return t.equals(tf.t)&&f.equals(tf.f);
816   }
817   public String toString() {
818     return f.toString()+" "+t.toString();
819   }
820 }