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