more changes
[IRC.git] / Robust / src / Analysis / Locality / LocalityAnalysis.java
1 package Analysis.Locality;
2
3 import java.util.*;
4 import Analysis.CallGraph.CallGraph;
5 import IR.SymbolTable;
6 import IR.State;
7 import IR.TypeUtil;
8 import IR.MethodDescriptor;
9 import IR.Flat.*;
10 import IR.ClassDescriptor;
11
12 public class LocalityAnalysis {
13     State state;
14     Stack lbtovisit;
15     Hashtable<LocalityBinding,LocalityBinding> discovered;
16     Hashtable<LocalityBinding, Set<LocalityBinding>> dependence;
17     Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>> temptab;
18     Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>> atomictab;
19     Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>> tempstosave;
20     Hashtable<ClassDescriptor, Set<LocalityBinding>> classtolb;
21
22     CallGraph callgraph;
23     TypeUtil typeutil;
24     public static final Integer LOCAL=new Integer(0);
25     public static final Integer GLOBAL=new Integer(1);
26     public static final Integer EITHER=new Integer(2);
27     public static final Integer CONFLICT=new Integer(3);
28
29     public LocalityAnalysis(State state, CallGraph callgraph, TypeUtil typeutil) {
30         this.typeutil=typeutil;
31         this.state=state;
32         this.discovered=new Hashtable<LocalityBinding,LocalityBinding>();
33         this.dependence=new Hashtable<LocalityBinding, Set<LocalityBinding>>();
34         this.temptab=new Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>>();
35         this.atomictab=new Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>>();
36         this.lbtovisit=new Stack();
37         this.callgraph=callgraph;
38         this.tempstosave=new Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>>();
39         this.classtolb=new Hashtable<ClassDescriptor, Set<LocalityBinding>>();
40         doAnalysis();
41     }
42
43     /** This method returns a set of LocalityBindings for the parameter class. */
44         
45     public Set<LocalityBinding> getClassBindings(ClassDescriptor cd) {
46         return classtolb.get(cd);
47     }
48
49     /** This method returns a set of LocalityBindings.  A
50      * LocalityBinding specifies a context a method can be invoked in.
51      * It specifies whether the method is in a transaction and whether
52      * its parameter objects are locals or globals.  */
53
54     public Set<LocalityBinding> getLocalityBindings() {
55         return discovered.keySet();
56     }
57
58     /** This method returns a hashtable for a given LocalityBinding
59      * that tells the current local/global status of temps at the each
60      * node in the flat representation. */
61
62     public Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> getNodeTempInfo(LocalityBinding lb) {
63         return temptab.get(lb);
64     }
65
66     /** This method returns an hashtable for a given LocalitBinding
67      * that tells whether a node in the flat represenation is in a
68      * transaction or not.  Integer values greater than 0 indicate
69      * that the node is in a transaction and give the nesting depth.
70      * The outermost AtomicEnterNode will have a value of 1 and the
71      * outermost AtomicExitNode will have a value of 0. */
72     
73     public Hashtable<FlatNode, Integer> getAtomic(LocalityBinding lb) {
74         return atomictab.get(lb);
75     }
76
77     /** This methods returns a hashtable for a given LocalityBinding
78      * that tells which temps needs to be saved for each
79      * AtomicEnterNode.  */
80
81     public Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> getTemps(LocalityBinding lb) {
82         return tempstosave.get(lb);
83     }
84
85     public Set<TempDescriptor> getTempSet(LocalityBinding lb) {
86         HashSet<TempDescriptor> set=new HashSet<TempDescriptor>();
87         Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> table=getTemps(lb);
88         for(Iterator<FlatAtomicEnterNode> faenit=table.keySet().iterator();faenit.hasNext();) {
89             FlatAtomicEnterNode faen=faenit.next();
90             set.addAll(table.get(faen));
91         }
92         return set;
93     }
94
95     private void doAnalysis() {
96         computeLocalityBindings();
97         computeTempstoSave();
98     }
99     
100     private void computeLocalityBindings() {
101         LocalityBinding lbmain=new LocalityBinding(typeutil.getMain(), false);
102         lbmain.setGlobal(0, LOCAL);
103         lbtovisit.add(lbmain);
104         discovered.put(lbmain, lbmain);
105         if (!classtolb.containsKey(lbmain.getMethod().getClassDesc()))
106             classtolb.put(lbmain.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
107         classtolb.get(lbmain.getMethod().getClassDesc()).add(lbmain);
108
109         while(!lbtovisit.empty()) {
110             LocalityBinding lb=(LocalityBinding) lbtovisit.pop();
111             Integer returnglobal=lb.getGlobalReturn();
112             MethodDescriptor md=lb.getMethod();
113             Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>> temptable=new Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>();
114             Hashtable<FlatNode, Integer> atomictable=new Hashtable<FlatNode, Integer>();
115             computeCallsFlags(md, lb, temptable, atomictable);
116             atomictab.put(lb, atomictable);
117             temptab.put(lb, temptable);
118
119             if (!md.isStatic()&&!returnglobal.equals(lb.getGlobalReturn())) {
120                 //return type is more precise now
121                 //rerun everything that call us
122                 lbtovisit.addAll(dependence.get(lb));
123             }
124         }
125     }
126
127
128     public void computeCallsFlags(MethodDescriptor md, LocalityBinding lb, Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable, Hashtable<FlatNode, Integer> atomictable) {
129         FlatMethod fm=state.getMethodFlat(md);
130         HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
131         tovisit.add(fm.getNext(0));
132         {
133             // Build table for initial node
134             Hashtable<TempDescriptor,Integer> table=new Hashtable<TempDescriptor,Integer>();
135             temptable.put(fm, table);
136             atomictable.put(fm, lb.isAtomic()?1:0);
137             int offset=md.isStatic()?0:1;
138             if (!md.isStatic()) {
139                 table.put(fm.getParameter(0), lb.getGlobalThis());
140             }
141             for(int i=offset;i<fm.numParameters();i++) {
142                 TempDescriptor temp=fm.getParameter(i);
143                 Integer b=lb.isGlobal(i-offset);
144                 table.put(temp,b);
145             }
146         }
147
148         while(!tovisit.isEmpty()) {
149             FlatNode fn=tovisit.iterator().next();
150             tovisit.remove(fn);
151             Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
152             int atomicstate=0;
153             for(int i=0;i<fn.numPrev();i++) {
154                 FlatNode prevnode=fn.getPrev(i);
155                 if (atomictable.containsKey(prevnode)) {
156                     atomicstate=atomictable.get(prevnode).intValue();
157                 }
158                 if (!temptable.containsKey(prevnode))
159                     continue;
160                 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
161                 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator();tempit.hasNext();) {
162                     TempDescriptor temp=tempit.next();
163                     Integer tmpint=prevtable.get(temp);
164                     Integer oldint=currtable.containsKey(temp)?currtable.get(temp):EITHER;
165                     Integer newint=merge(tmpint, oldint);
166                     currtable.put(temp, newint);
167                 }
168             }
169             atomictable.put(fn, atomicstate);
170             // Process this node
171             switch(fn.kind()) {
172             case FKind.FlatAtomicEnterNode:
173                 processAtomicEnterNode((FlatAtomicEnterNode)fn, atomictable);
174                 if (!lb.isAtomic())
175                     lb.setHasAtomic();
176                 break;
177             case FKind.FlatAtomicExitNode:
178                 processAtomicExitNode((FlatAtomicExitNode)fn, atomictable);
179                 break;
180             case FKind.FlatCall:
181                 processCallNode(lb, (FlatCall)fn, currtable, isAtomic(atomictable, fn));
182                 break;
183             case FKind.FlatFieldNode:
184                 processFieldNode(lb, (FlatFieldNode)fn, isAtomic(atomictable, fn), currtable);
185                 break;
186             case FKind.FlatSetFieldNode:
187                 processSetFieldNode(lb, (FlatSetFieldNode)fn, isAtomic(atomictable,fn), currtable);
188                 break;
189             case FKind.FlatNew:
190                 processNew(lb, (FlatNew)fn, isAtomic(atomictable, fn), currtable);
191                 break;
192             case FKind.FlatOpNode:
193                 processOpNode((FlatOpNode)fn, currtable);
194                 break;
195             case FKind.FlatCastNode:
196                 processCastNode((FlatCastNode)fn, currtable);
197                 break;
198             case FKind.FlatLiteralNode:
199                 processLiteralNode((FlatLiteralNode)fn, currtable);
200                 break;
201             case FKind.FlatReturnNode:
202                 processReturnNode(lb, (FlatReturnNode)fn, currtable);
203                 break;
204             case FKind.FlatSetElementNode:
205                 processSetElementNode(lb, (FlatSetElementNode)fn, currtable, isAtomic(atomictable, fn));
206                 break;
207             case FKind.FlatElementNode:
208                 processElementNode(lb, (FlatElementNode)fn, currtable, isAtomic(atomictable, fn));
209                 break;
210             case FKind.FlatCondBranch:
211             case FKind.FlatBackEdge:
212             case FKind.FlatNop:
213                 //No action needed for these
214                 break;
215             case FKind.FlatFlagActionNode:
216             case FKind.FlatCheckNode:
217             case FKind.FlatTagDeclaration:
218                 throw new Error("Incompatible with tasks!");
219             case FKind.FlatMethod:
220             default:
221                 throw new Error();
222             }
223             Hashtable<TempDescriptor,Integer> oldtable=temptable.get(fn);
224             if (oldtable==null||!oldtable.equals(currtable)) {
225                 // Update table for this node
226                 temptable.put(fn, currtable);
227                 for(int i=0;i<fn.numNext();i++) {
228                     tovisit.add(fn.getNext(i));
229                 }
230             }
231         }
232     }
233
234     private static boolean isAtomic(Hashtable<FlatNode, Integer> atomictable, FlatNode fn) {
235         return atomictable.get(fn).intValue()>0;
236     }
237
238     private static Integer merge(Integer a, Integer b) {
239         if (a==null||a.equals(EITHER))
240             return b;
241         if (b==null||b.equals(EITHER))
242             return a;
243         if (a.equals(b))
244             return a;
245         return CONFLICT;
246     }
247
248     void processCallNode(LocalityBinding currlb, FlatCall fc, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
249         MethodDescriptor nodemd=fc.getMethod();
250         Set methodset=fc.getThis()==null?callgraph.getMethods(nodemd):
251             callgraph.getMethods(nodemd, fc.getThis().getType());
252         Integer currreturnval=EITHER; //Start off with the either value
253         for(Iterator methodit=methodset.iterator();methodit.hasNext();) {
254             MethodDescriptor md=(MethodDescriptor) methodit.next();
255             boolean isnative=md.getModifiers().isNative();
256
257             LocalityBinding lb=new LocalityBinding(md, isatomic);
258             if (isnative&&isatomic) {
259                 System.out.println("Don't call native methods in atomic blocks!");
260             }
261             for(int i=0;i<fc.numArgs();i++) {
262                 TempDescriptor arg=fc.getArg(i);
263                 if(isnative&&(currtable.get(arg).equals(GLOBAL)||
264                               currtable.get(arg).equals(CONFLICT)))
265                    throw new Error("Potential call to native method "+md+" with global parameter:\n"+currlb.getExplanation());
266                 lb.setGlobal(i,currtable.get(arg));
267             }
268             if (fc.getThis()!=null) {
269                 Integer thistype=currtable.get(fc.getThis());
270                 if (thistype==null)
271                     thistype=EITHER;
272                 if(thistype.equals(CONFLICT))
273                     throw new Error("Using type that can be either local or global in context:\n"+currlb.getExplanation());
274                 if(thistype.equals(GLOBAL)&&!isatomic)
275                     throw new Error("Using global object outside of transaction in context:\n"+currlb.getExplanation());
276                 if (isnative&&thistype.equals(GLOBAL))
277                     throw new Error("Potential call to native method "+md+" on global objects:\n"+currlb.getExplanation());
278                 lb.setGlobalThis(thistype);
279             } else
280                 lb.setGlobalThis(EITHER);//default value
281                 
282             //lb is built
283             if (!discovered.containsKey(lb)) {
284                 if (isnative)
285                     lb.setGlobalReturn(LOCAL);
286                 else
287                     lb.setGlobalReturn(EITHER);
288                 lb.setParent(currlb);
289                 lbtovisit.add(lb);
290                 discovered.put(lb, lb);
291                 if (!classtolb.containsKey(lb.getMethod().getClassDesc()))
292                     classtolb.put(lb.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
293                 classtolb.get(lb.getMethod().getClassDesc()).add(lb);
294             } else
295                 lb=discovered.get(lb);
296             Integer returnval=lb.getGlobalReturn();
297             currreturnval=merge(returnval, currreturnval);
298             if (!dependence.containsKey(lb))
299                 dependence.put(lb, new HashSet<LocalityBinding>());
300             dependence.get(lb).add(currlb);
301         }
302         if (fc.getReturnTemp()!=null) {
303             currtable.put(fc.getReturnTemp(), currreturnval);
304         }
305     }
306
307     void processFieldNode(LocalityBinding lb, FlatFieldNode ffn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
308         Integer type=currtable.get(ffn.getSrc());
309         TempDescriptor dst=ffn.getDst();
310         if (type.equals(LOCAL)) {
311             if (ffn.getField().isGlobal())
312                 currtable.put(dst,GLOBAL);
313             else
314                 currtable.put(dst,LOCAL);
315         } else if (type.equals(GLOBAL)) {
316             if (!transaction)
317                 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
318             if (ffn.getField().getType().isPrimitive())
319                 currtable.put(dst, LOCAL); // primitives are local
320             else
321                 currtable.put(dst, GLOBAL);
322         } else if (type.equals(EITHER)) {
323             if (ffn.getField().getType().isPrimitive())
324                 currtable.put(dst, LOCAL); // primitives are local
325             else if (ffn.getField().isGlobal())
326                 currtable.put(dst, GLOBAL);
327             else
328                 currtable.put(dst, EITHER);
329         } else if (type.equals(CONFLICT)) {
330             throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
331         }
332     }
333
334     //need to handle primitives
335     void processSetFieldNode(LocalityBinding lb, FlatSetFieldNode fsfn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
336         Integer srctype=currtable.get(fsfn.getSrc());
337         Integer dsttype=currtable.get(fsfn.getDst());
338         
339         if (dsttype.equals(LOCAL)) {
340             if (fsfn.getField().isGlobal()) {
341                 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
342                     throw new Error("Writing possible local reference to global field in context: \n"+lb.getExplanation());
343             } else {
344                 if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
345                     throw new Error("Writing possible global reference to local object in context: \n"+lb.getExplanation());
346             }
347         } else if (dsttype.equals(GLOBAL)) {
348             if (!transaction)
349                 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
350             //okay to store primitives in global object
351             if (srctype.equals(LOCAL) && fsfn.getField().getType().isPrimitive())
352                 return;
353             if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
354                 throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation());
355         } else if (dsttype.equals(EITHER)) {
356             if (srctype.equals(CONFLICT))
357                 throw new Error("Using reference that could be local or global in context:\n"+lb.getExplanation());
358         } else if (dsttype.equals(CONFLICT)) {
359             throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
360         }
361     }
362
363     void processNew(LocalityBinding lb, FlatNew fn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
364         if (fn.isGlobal()&&!transaction) {
365             throw new Error("Allocating global object outside of transaction in context:"+lb.getExplanation());
366         }
367         if (fn.isGlobal())
368             currtable.put(fn.getDst(), GLOBAL);
369         else
370             currtable.put(fn.getDst(), LOCAL);
371     }
372
373     void processOpNode(FlatOpNode fon, Hashtable<TempDescriptor, Integer> currtable) {
374         /* Just propagate value */
375         currtable.put(fon.getDest(), currtable.get(fon.getLeft()));
376     }
377
378     void processCastNode(FlatCastNode fcn, Hashtable<TempDescriptor, Integer> currtable) {
379         currtable.put(fcn.getDst(), currtable.get(fcn.getSrc()));
380     }
381
382     void processLiteralNode(FlatLiteralNode fln, Hashtable<TempDescriptor, Integer> currtable) {
383         //null is either
384         if (fln.getValue()==null)
385             currtable.put(fln.getDst(), EITHER);
386         else
387             currtable.put(fln.getDst(), LOCAL);
388     }
389
390     void processReturnNode(LocalityBinding lb, FlatReturnNode frn, Hashtable<TempDescriptor, Integer> currtable) {
391         if(frn.getReturnTemp()!=null) {
392             Integer returntype=currtable.get(frn.getReturnTemp());
393             lb.setGlobalReturn(merge(returntype, lb.getGlobalReturn()));
394         }
395     }
396
397     void processSetElementNode(LocalityBinding lb, FlatSetElementNode fsen, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
398         Integer srctype=currtable.get(fsen.getSrc());
399         Integer dsttype=currtable.get(fsen.getDst());
400
401         if (dsttype.equals(LOCAL)) {
402             if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
403                 throw new Error("Writing possible global reference to local object in context:\n"+lb.getExplanation());
404         } else if (dsttype.equals(GLOBAL)) {
405             if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
406                 throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation());
407             if (!isatomic)
408                 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
409         } else if (dsttype.equals(EITHER)) {
410             if (srctype.equals(CONFLICT))
411                 throw new Error("Using reference that could be local or global in context:\n"+lb.getExplanation());
412         } else if (dsttype.equals(CONFLICT)) {
413             throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
414         }
415     }
416
417     void processElementNode(LocalityBinding lb, FlatElementNode fen, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
418         Integer type=currtable.get(fen.getSrc());
419         TempDescriptor dst=fen.getDst();
420         if (type.equals(LOCAL)) {
421             currtable.put(dst,LOCAL);
422         } else if (type.equals(GLOBAL)) {
423             if (!isatomic)
424                 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
425             currtable.put(dst, GLOBAL);
426         } else if (type.equals(EITHER)) {
427             currtable.put(dst, EITHER);
428         } else if (type.equals(CONFLICT)) {
429             throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
430         }
431     }
432
433     void processAtomicEnterNode(FlatAtomicEnterNode fen, Hashtable<FlatNode, Integer> atomictable) {
434         int atomic=atomictable.get(fen).intValue();
435         atomictable.put(fen, new Integer(atomic+1));
436     }
437
438     void processAtomicExitNode(FlatAtomicExitNode fen, Hashtable<FlatNode, Integer> atomictable) {
439         int atomic=atomictable.get(fen).intValue();
440         atomictable.put(fen, new Integer(atomic-1));
441     }
442
443     private Hashtable<FlatNode, Set<TempDescriptor>> computeLiveTemps(FlatMethod fm) {
444         Hashtable<FlatNode, Set<TempDescriptor>> nodetotemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
445
446         Set<FlatNode> toprocess=fm.getNodeSet();
447
448         while(!toprocess.isEmpty()) {
449             FlatNode fn=toprocess.iterator().next();
450             toprocess.remove(fn);
451
452             List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
453             List<TempDescriptor> writes=Arrays.asList(fn.readsTemps());
454
455             HashSet<TempDescriptor> tempset=new HashSet<TempDescriptor>();
456             for(int i=0;i<fn.numNext();i++) {
457                 FlatNode fnnext=fn.getNext(i);
458                 if (nodetotemps.containsKey(fnnext))
459                     tempset.addAll(nodetotemps.get(fnnext));
460             }
461             tempset.removeAll(writes);
462             tempset.addAll(reads);
463             if (!nodetotemps.containsKey(fn)||
464                 nodetotemps.get(fn).equals(tempset)) {
465                 nodetotemps.put(fn, tempset);
466                 for(int i=0;i<fn.numPrev();i++)
467                     toprocess.add(fn.getPrev(i));
468             }
469         }
470         return nodetotemps;
471     }
472
473     private void computeTempstoSave() {
474         for(Iterator<LocalityBinding> lbit=getLocalityBindings().iterator();lbit.hasNext();) {
475             LocalityBinding lb=lbit.next();
476             computeTempstoSave(lb);
477         }
478     }
479
480     /* Need to checkpoint all temps that could be read from along any
481      * path that are either:
482        1) Written to by any assignment inside the transaction
483        2) Read from a global temp.
484
485        Generate tempstosave map from
486        localitybinding->flatatomicenternode->Set<TempDescriptors>
487     */
488
489     private void computeTempstoSave(LocalityBinding lb) {
490         if (lb.isAtomic())
491             return;
492         Hashtable<FlatNode, Integer> atomictab=getAtomic(lb);
493         Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=getNodeTempInfo(lb);
494         MethodDescriptor md=lb.getMethod();
495         FlatMethod fm=state.getMethodFlat(md);
496
497         Hashtable<FlatNode, Set<TempDescriptor>> nodetotemps=computeLiveTemps(fm);
498         Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> nodetosavetemps=new Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>();
499         tempstosave.put(lb, nodetosavetemps);
500
501         Hashtable<FlatNode, FlatAtomicEnterNode> nodemap=new Hashtable<FlatNode, FlatAtomicEnterNode>();
502         
503         HashSet<FlatNode> toprocess=new HashSet<FlatNode>();
504         HashSet<FlatNode> discovered=new HashSet<FlatNode>();
505         toprocess.add(fm);
506         discovered.add(fm);
507         while(!toprocess.isEmpty()) {
508             FlatNode fn=toprocess.iterator().next();
509             toprocess.remove(fn);
510             boolean isatomic=atomictab.get(fn).intValue()>0;
511             if (isatomic&&
512                 atomictab.get(fn.getPrev(0)).intValue()==0) {
513                 assert(fn.getPrev(0).kind()==FKind.FlatAtomicEnterNode);
514                 nodemap.put(fn, (FlatAtomicEnterNode)fn);
515                 nodetosavetemps.put((FlatAtomicEnterNode)fn, new HashSet<TempDescriptor>());
516             } else if (isatomic) {
517                 FlatAtomicEnterNode atomicnode=nodemap.get(fn);
518                 Set<TempDescriptor> livetemps=nodetotemps.get(fn);
519                 List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
520                 List<TempDescriptor> writes=Arrays.asList(fn.readsTemps());
521
522                 for(Iterator<TempDescriptor> tempit=livetemps.iterator();tempit.hasNext();) {
523                     TempDescriptor tmp=tempit.next();
524                     if (writes.contains(tmp)) {
525                         nodetosavetemps.get(fn).add(tmp);
526                     } else if (reads.contains(tmp)&&temptab.get(fn).get(tmp)==GLOBAL) {
527                         nodetosavetemps.get(fn).add(tmp);
528                     }
529                 }
530             }
531             for(int i=0;i<fn.numNext();i++) {
532                 FlatNode fnnext=fn.getNext(i);
533                 if (!discovered.contains(fnnext)) {
534                     discovered.add(fnnext);
535                     toprocess.add(fnnext);
536                     if(isatomic) {
537                         nodemap.put(fnnext, nodemap.get(fn));
538                     }
539                 }
540             }
541         }
542     }
543 }