1 package Analysis.Locality;
3 import Analysis.Liveness;
5 import Analysis.CallGraph.CallGraph;
9 import IR.MethodDescriptor;
11 import Analysis.Liveness;
12 import IR.ClassDescriptor;
14 public class LocalityAnalysis {
17 Hashtable<LocalityBinding,LocalityBinding> discovered;
18 Hashtable<LocalityBinding, Set<LocalityBinding>> dependence;
19 Hashtable<LocalityBinding, Set<LocalityBinding>> calldep;
20 Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>> temptab;
21 Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>> atomictab;
22 Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>> tempstosave;
23 Hashtable<ClassDescriptor, Set<LocalityBinding>> classtolb;
24 Hashtable<MethodDescriptor, Set<LocalityBinding>> methodtolb;
25 private LocalityBinding lbmain;
26 private LocalityBinding lbrun;
30 public static final Integer LOCAL=new Integer(0);
31 public static final Integer GLOBAL=new Integer(1);
32 public static final Integer EITHER=new Integer(2);
33 public static final Integer CONFLICT=new Integer(3);
35 public static final Integer STMEITHER=new Integer(0);
36 public static final Integer SCRATCH=new Integer(4);
37 public static final Integer NORMAL=new Integer(8);
38 public static final Integer STMCONFLICT=new Integer(12);
40 public LocalityAnalysis(State state, CallGraph callgraph, TypeUtil typeutil) {
41 this.typeutil=typeutil;
43 this.discovered=new Hashtable<LocalityBinding,LocalityBinding>();
44 this.dependence=new Hashtable<LocalityBinding, Set<LocalityBinding>>();
45 this.calldep=new Hashtable<LocalityBinding, Set<LocalityBinding>>();
46 this.temptab=new Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>>();
47 this.atomictab=new Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>>();
48 this.lbtovisit=new HashSet();
49 this.callgraph=callgraph;
50 this.tempstosave=new Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>>();
51 this.classtolb=new Hashtable<ClassDescriptor, Set<LocalityBinding>>();
52 this.methodtolb=new Hashtable<MethodDescriptor, Set<LocalityBinding>>();
56 public LocalityBinding getMain() {
60 /** This method returns the set of LocalityBindings that a given
61 * flatcall could invoke */
63 public LocalityBinding getBinding(LocalityBinding currlb, FlatCall fc) {
64 boolean isatomic=getAtomic(currlb).get(fc).intValue()>0;
65 Hashtable<TempDescriptor, Integer> currtable=getNodePreTempInfo(currlb,fc);
66 MethodDescriptor md=fc.getMethod();
68 boolean isnative=md.getModifiers().isNative();
70 LocalityBinding lb=new LocalityBinding(md, isatomic);
72 for(int i=0; i<fc.numArgs(); i++) {
73 TempDescriptor arg=fc.getArg(i);
74 lb.setGlobal(i,currtable.get(arg));
77 if (state.DSM&&fc.getThis()!=null) {
78 Integer thistype=currtable.get(fc.getThis());
81 lb.setGlobalThis(thistype);
82 } else if (state.SINGLETM&&fc.getThis()!=null) {
83 Integer thistype=currtable.get(fc.getThis());
86 lb.setGlobalThis(thistype);
89 // lb.setGlobalThis(EITHER);//default value
90 if (discovered.containsKey(lb))
91 lb=discovered.get(lb);
92 else throw new Error();
97 /** This method returns a set of LocalityBindings for the parameter class. */
98 public Set<LocalityBinding> getClassBindings(ClassDescriptor cd) {
99 return classtolb.get(cd);
102 /** This method returns a set of LocalityBindings for the parameter method. */
104 public Set<LocalityBinding> getMethodBindings(MethodDescriptor md) {
105 return methodtolb.get(md);
108 public Set<MethodDescriptor> getMethods() {
109 return methodtolb.keySet();
112 /** This method returns a set of LocalityBindings. A
113 * LocalityBinding specifies a context a method can be invoked in.
114 * It specifies whether the method is in a transaction and whether
115 * its parameter objects are locals or globals. */
117 public Set<LocalityBinding> getLocalityBindings() {
118 return discovered.keySet();
121 /** This method returns a hashtable for a given LocalityBinding
122 * that tells the current local/global status of temps at the each
123 * node in the flat representation. */
125 public Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> getNodeTempInfo(LocalityBinding lb) {
126 return temptab.get(lb);
129 /** This method returns a hashtable for a given LocalityBinding
130 * that tells the current local/global status of temps at the
131 * beginning of each node in the flat representation. */
133 public Hashtable<TempDescriptor, Integer> getNodePreTempInfo(LocalityBinding lb, FlatNode fn) {
134 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
135 Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable=getNodeTempInfo(lb);
137 for(int i=0; i<fn.numPrev(); i++) {
138 FlatNode prevnode=fn.getPrev(i);
139 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
140 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator(); tempit.hasNext();) {
141 TempDescriptor temp=tempit.next();
142 Integer tmpint=prevtable.get(temp);
143 Integer oldint=currtable.containsKey(temp) ? currtable.get(temp) : (state.DSM?EITHER:STMEITHER);
144 Integer newint=state.DSM?merge(tmpint, oldint):mergestm(tmpint, oldint);
145 currtable.put(temp, newint);
151 /** This method returns an hashtable for a given LocalitBinding
152 * that tells whether a node in the flat represenation is in a
153 * transaction or not. Integer values greater than 0 indicate
154 * that the node is in a transaction and give the nesting depth.
155 * The outermost AtomicEnterNode will have a value of 1 and the
156 * outermost AtomicExitNode will have a value of 0. */
158 public Hashtable<FlatNode, Integer> getAtomic(LocalityBinding lb) {
159 return atomictab.get(lb);
162 /** This methods returns a hashtable for a given LocalityBinding
163 * that tells which temps needs to be saved for each
164 * AtomicEnterNode. */
166 public Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> getTemps(LocalityBinding lb) {
167 return tempstosave.get(lb);
170 public Set<TempDescriptor> getTempSet(LocalityBinding lb) {
171 HashSet<TempDescriptor> set=new HashSet<TempDescriptor>();
172 Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> table=getTemps(lb);
174 for(Iterator<FlatAtomicEnterNode> faenit=table.keySet().iterator(); faenit.hasNext();) {
175 FlatAtomicEnterNode faen=faenit.next();
176 set.addAll(table.get(faen));
181 private void doAnalysis() {
183 computeLocalityBindingsSTM();
185 computeLocalityBindings();
186 computeTempstoSave();
190 private void cleanSets() {
191 HashSet<LocalityBinding> lbset=new HashSet<LocalityBinding>();
192 Stack<LocalityBinding> lbstack=new Stack<LocalityBinding>();
197 while(!lbstack.isEmpty()) {
198 LocalityBinding lb=lbstack.pop();
199 if (calldep.containsKey(lb)) {
200 Set<LocalityBinding> set=new HashSet<LocalityBinding>();
201 set.addAll(calldep.get(lb));
202 set.removeAll(lbset);
207 for(Iterator<LocalityBinding> lbit=discovered.keySet().iterator(); lbit.hasNext();) {
208 LocalityBinding lb=lbit.next();
209 if (!lbset.contains(lb)) {
211 classtolb.get(lb.getMethod().getClassDesc()).remove(lb);
212 methodtolb.get(lb.getMethod()).remove(lb);
217 public MethodDescriptor getStart() {
218 ClassDescriptor cd=typeutil.getClass(TypeUtil.ThreadClass);
219 for(Iterator methodit=cd.getMethodTable().getSet("staticStart").iterator(); methodit
221 MethodDescriptor md=(MethodDescriptor) methodit.next();
222 if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).getSymbol().equals(TypeUtil.ThreadClass))
226 throw new Error("Can't find Thread.run");
230 private void computeLocalityBindingsSTM() {
231 lbmain=new LocalityBinding(typeutil.getMain(), false);
232 lbmain.setGlobalReturn(STMEITHER);
233 lbmain.setGlobal(0, NORMAL);
234 lbtovisit.add(lbmain);
235 discovered.put(lbmain, lbmain);
236 if (!classtolb.containsKey(lbmain.getMethod().getClassDesc()))
237 classtolb.put(lbmain.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
238 classtolb.get(lbmain.getMethod().getClassDesc()).add(lbmain);
240 if (!methodtolb.containsKey(lbmain.getMethod()))
241 methodtolb.put(lbmain.getMethod(), new HashSet<LocalityBinding>());
242 methodtolb.get(lbmain.getMethod()).add(lbmain);
244 //Do this to force a virtual table number for the run method
245 lbrun=new LocalityBinding(getStart(), false);
246 lbrun.setGlobalReturn(STMEITHER);
247 lbrun.setGlobal(0,NORMAL);
248 lbtovisit.add(lbrun);
249 discovered.put(lbrun, lbrun);
250 if (!classtolb.containsKey(lbrun.getMethod().getClassDesc()))
251 classtolb.put(lbrun.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
252 classtolb.get(lbrun.getMethod().getClassDesc()).add(lbrun);
254 if (!methodtolb.containsKey(lbrun.getMethod()))
255 methodtolb.put(lbrun.getMethod(), new HashSet<LocalityBinding>());
256 methodtolb.get(lbrun.getMethod()).add(lbrun);
258 while(!lbtovisit.isEmpty()) {
259 LocalityBinding lb=(LocalityBinding) lbtovisit.iterator().next();
260 lbtovisit.remove(lb);
262 System.out.println("Analyzing "+lb);
264 Integer returnglobal=lb.getGlobalReturn();
265 MethodDescriptor md=lb.getMethod();
266 Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>> temptable=new Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>();
267 Hashtable<FlatNode, Integer> atomictable=new Hashtable<FlatNode, Integer>();
270 computeCallsFlagsSTM(md, lb, temptable, atomictable);
272 System.out.println("Error in "+md+" context "+lb);
276 temptab.put(lb, temptable);
277 atomictab.put(lb, atomictable);
279 if (md.getReturnType()!=null&&md.getReturnType().isPtr()&&!returnglobal.equals(lb.getGlobalReturn())) {
280 //return type is more precise now
281 //rerun everything that call us
282 lbtovisit.addAll(dependence.get(lb));
287 private static Integer mergestm(Integer a, Integer b) {
288 if (a==null||a.equals(STMEITHER))
290 if (b==null||b.equals(STMEITHER))
297 public void computeCallsFlagsSTM(MethodDescriptor md, LocalityBinding lb, Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable, Hashtable<FlatNode, Integer> atomictable) {
298 FlatMethod fm=state.getMethodFlat(md);
299 HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
300 tovisit.add(fm.getNext(0));
303 // Build table for initial node
304 Hashtable<TempDescriptor,Integer> table=new Hashtable<TempDescriptor,Integer>();
305 temptable.put(fm, table);
306 atomictable.put(fm, lb.isAtomic() ? 1 : 0);
307 int offset=md.isStatic() ? 0 : 1;
308 if (!md.isStatic()) {
309 table.put(fm.getParameter(0), lb.getGlobalThis());
311 for(int i=offset; i<fm.numParameters(); i++) {
312 TempDescriptor temp=fm.getParameter(i);
313 Integer b=lb.isGlobal(i-offset);
319 Hashtable<FlatNode, Set<TempDescriptor>> livemap=Liveness.computeLiveTemps(fm);
321 while(!tovisit.isEmpty()) {
322 FlatNode fn=tovisit.iterator().next();
324 Set<TempDescriptor> liveset=livemap.get(fn);
325 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
327 for(int i=0; i<fn.numPrev(); i++) {
328 FlatNode prevnode=fn.getPrev(i);
329 if (atomictable.containsKey(prevnode)) {
330 atomicstate=atomictable.get(prevnode).intValue();
332 if (!temptable.containsKey(prevnode))
334 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
335 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator(); tempit.hasNext();) {
336 TempDescriptor temp=tempit.next();
337 if (!liveset.contains(temp))
339 Integer tmpint=prevtable.get(temp);
340 Integer oldint=currtable.containsKey(temp) ? currtable.get(temp) : STMEITHER;
341 Integer newint=mergestm(tmpint, oldint);
342 currtable.put(temp, newint);
345 atomictable.put(fn, atomicstate);
349 case FKind.FlatAtomicEnterNode:
350 processAtomicEnterNode((FlatAtomicEnterNode)fn, atomictable);
355 case FKind.FlatAtomicExitNode:
356 processAtomicExitNode((FlatAtomicExitNode)fn, atomictable);
360 processCallNodeSTM(lb, (FlatCall)fn, isAtomic(atomictable, fn), currtable, temptable.get(fn));
364 processNewSTM(lb, (FlatNew) fn, currtable);
367 case FKind.FlatFieldNode:
368 processFieldNodeSTM(lb, (FlatFieldNode) fn, currtable);
371 case FKind.FlatSetFieldNode:
372 processSetFieldNodeSTM(lb, (FlatSetFieldNode) fn, currtable);
375 case FKind.FlatSetElementNode:
376 processSetElementNodeSTM(lb, (FlatSetElementNode) fn, currtable);
379 case FKind.FlatElementNode:
380 processElementNodeSTM(lb, (FlatElementNode) fn, currtable);
383 case FKind.FlatOpNode:
384 processOpNodeSTM(lb, (FlatOpNode)fn, currtable);
387 case FKind.FlatCastNode:
388 processCastNodeSTM((FlatCastNode)fn, currtable);
391 case FKind.FlatReturnNode:
392 processReturnNodeSTM(lb, (FlatReturnNode)fn, currtable);
395 case FKind.FlatLiteralNode:
396 processLiteralNodeSTM((FlatLiteralNode)fn, currtable);
399 case FKind.FlatMethod:
400 case FKind.FlatOffsetNode:
401 case FKind.FlatInstanceOfNode:
402 case FKind.FlatCondBranch:
403 case FKind.FlatBackEdge:
405 case FKind.FlatPrefetchNode:
407 //No action needed for these
410 case FKind.FlatFlagActionNode:
411 case FKind.FlatCheckNode:
412 case FKind.FlatTagDeclaration:
413 throw new Error("Incompatible with tasks!");
416 throw new Error("In finding fn.kind()= " + fn.kind());
421 Hashtable<TempDescriptor,Integer> oldtable=temptable.get(fn);
422 if (oldtable==null||!oldtable.equals(currtable)) {
423 // Update table for this node
424 temptable.put(fn, currtable);
425 for(int i=0; i<fn.numNext(); i++) {
426 tovisit.add(fn.getNext(i));
432 void processNewSTM(LocalityBinding lb, FlatNew fn, Hashtable<TempDescriptor, Integer> currtable) {
434 currtable.put(fn.getDst(), SCRATCH);
436 currtable.put(fn.getDst(), NORMAL);
439 void processCallNodeSTM(LocalityBinding currlb, FlatCall fc, boolean isatomic, Hashtable<TempDescriptor, Integer> currtable, Hashtable<TempDescriptor, Integer> oldtable) {
440 MethodDescriptor nodemd=fc.getMethod();
442 Set runmethodset=null;
444 if (nodemd.isStatic()||nodemd.getReturnType()==null) {
445 methodset=new HashSet();
446 methodset.add(nodemd);
448 methodset=callgraph.getMethods(nodemd, fc.getThis().getType());
449 // Build start -> run link
450 if (nodemd.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&
451 nodemd.getSymbol().equals("start")&&!nodemd.getModifiers().isStatic()&&
452 nodemd.numParameters()==0) {
453 assert(nodemd.getModifiers().isNative());
455 MethodDescriptor runmd=null;
456 for(Iterator methodit=nodemd.getClassDesc().getMethodTable().getSet("staticStart").iterator(); methodit.hasNext();) {
457 MethodDescriptor md=(MethodDescriptor) methodit.next();
458 if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).getSymbol().equals(TypeUtil.ThreadClass))
464 runmethodset=callgraph.getMethods(runmd,fc.getThis().getType());
465 methodset.addAll(runmethodset);
466 } else throw new Error("Can't find run method");
470 Integer currreturnval=STMEITHER; //Start off with the either value
471 if (oldtable!=null&&fc.getReturnTemp()!=null&&
472 oldtable.get(fc.getReturnTemp())!=null) {
474 currreturnval=mergestm(currreturnval, oldtable.get(fc.getReturnTemp()));
477 for(Iterator methodit=methodset.iterator(); methodit.hasNext();) {
478 MethodDescriptor md=(MethodDescriptor) methodit.next();
480 boolean isnative=md.getModifiers().isNative();
481 boolean isjoin = md.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&!nodemd.getModifiers().isStatic()&&nodemd.numParameters()==0&&md.getSymbol().equals("join");
482 boolean isObjectgetType = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("getType");
483 boolean isObjecthashCode = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("nativehashCode");
485 LocalityBinding lb=new LocalityBinding(md, isatomic);
486 if (isnative&&isatomic) {
487 System.out.println("Don't call native methods in atomic blocks!"+currlb.getMethod());
490 if (runmethodset==null||!runmethodset.contains(md)) {
491 for(int i=0; i<fc.numArgs(); i++) {
492 TempDescriptor arg=fc.getArg(i);
493 if (currtable.containsKey(arg))
494 lb.setGlobal(i,currtable.get(arg));
496 if (fc.getThis()!=null) {
497 Integer thistype=currtable.get(fc.getThis());
501 if(thistype.equals(STMCONFLICT))
502 throw new Error("Using type that can be either normal or scratch in context:\n"+currlb.getExplanation());
503 lb.setGlobalThis(thistype);
506 Integer thistype=currtable.get(fc.getThis());
507 if (!thistype.equals(NORMAL)&&!thistype.equals(STMEITHER)) {
508 throw new Error("Called start on possible scratch object"+thistype);
510 lb.setGlobal(0,currtable.get(fc.getThis()));
513 if (!discovered.containsKey(lb)) {
515 if (nodemd.getReturnType()!=null&&nodemd.getReturnType().isPtr())
516 lb.setGlobalReturn(NORMAL);
518 lb.setGlobalReturn(STMEITHER);
520 lb.setParent(currlb);
522 System.out.println("New lb:"+lb);
523 discovered.put(lb, lb);
524 if (!classtolb.containsKey(lb.getMethod().getClassDesc()))
525 classtolb.put(lb.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
526 classtolb.get(lb.getMethod().getClassDesc()).add(lb);
527 if (!methodtolb.containsKey(lb.getMethod()))
528 methodtolb.put(lb.getMethod(), new HashSet<LocalityBinding>());
529 methodtolb.get(lb.getMethod()).add(lb);
531 lb=discovered.get(lb);
532 Integer returnval=lb.getGlobalReturn();
533 currreturnval=mergestm(returnval, currreturnval);
534 if (!dependence.containsKey(lb))
535 dependence.put(lb, new HashSet<LocalityBinding>());
536 dependence.get(lb).add(currlb);
538 if (!calldep.containsKey(currlb))
539 calldep.put(currlb, new HashSet<LocalityBinding>());
540 calldep.get(currlb).add(lb);
542 if (fc.getReturnTemp()!=null&&fc.getReturnTemp().getType().isPtr()) {
543 currtable.put(fc.getReturnTemp(), currreturnval);
547 void processFieldNodeSTM(LocalityBinding lb, FlatFieldNode ffn, Hashtable<TempDescriptor, Integer> currtable) {
548 Integer type=currtable.get(ffn.getSrc());
549 TempDescriptor dst=ffn.getDst();
550 if (!ffn.getDst().getType().isPtr())
553 if (type.equals(SCRATCH)) {
554 currtable.put(dst,SCRATCH);
555 } else if (type.equals(NORMAL)) {
556 currtable.put(dst, NORMAL);
557 } else if (type.equals(STMEITHER)) {
558 currtable.put(dst, STMEITHER);
559 } else if (type.equals(STMCONFLICT)) {
560 throw new Error("Access to object that could be either normal or scratch in context:\n"+ffn+" "+lb.getExplanation());
564 //need to handle primitives
565 void processSetFieldNodeSTM(LocalityBinding lb, FlatSetFieldNode fsfn, Hashtable<TempDescriptor, Integer> currtable) {
566 Integer srctype=currtable.get(fsfn.getSrc());
567 Integer dsttype=currtable.get(fsfn.getDst());
568 if (!fsfn.getSrc().getType().isPtr())
572 System.out.println(fsfn);
573 if (dsttype.equals(SCRATCH)) {
574 if (!(srctype.equals(SCRATCH)||srctype.equals(STMEITHER)))
575 throw new Error("Writing possible normal reference to scratch object in context: \n"+lb.getExplanation());
576 } else if (dsttype.equals(NORMAL)) {
577 //okay to store primitives in global object
578 if (!(srctype.equals(NORMAL)||srctype.equals(STMEITHER)))
579 throw new Error("Writing possible scratch reference to normal object in context:\n"+lb.getExplanation()+" for FlatFieldNode "+fsfn);
580 } else if (dsttype.equals(STMEITHER)) {
581 if (srctype.equals(STMCONFLICT))
582 throw new Error("Using reference that could be scratch or normal in context:\n"+lb.getExplanation());
583 } else if (dsttype.equals(STMCONFLICT)) {
584 throw new Error("Access to object that could be either scratch or normal in context:\n"+lb.getExplanation());
588 void processSetElementNodeSTM(LocalityBinding lb, FlatSetElementNode fsen, Hashtable<TempDescriptor, Integer> currtable) {
589 Integer srctype=currtable.get(fsen.getSrc());
590 Integer dsttype=currtable.get(fsen.getDst());
591 if (!fsen.getSrc().getType().isPtr())
594 if (dsttype.equals(SCRATCH)) {
595 if (!(srctype.equals(SCRATCH)||srctype.equals(STMEITHER)))
596 throw new Error("Writing possible normal reference to scratch object in context:\n"+lb.getExplanation()+fsen);
597 } else if (dsttype.equals(NORMAL)) {
598 if (!(srctype.equals(NORMAL)||srctype.equals(STMEITHER)))
599 throw new Error("Writing possible scratch reference to normal object in context:\n"+lb.getExplanation());
600 } else if (dsttype.equals(STMEITHER)) {
601 if (srctype.equals(STMCONFLICT))
602 throw new Error("Using reference that could be scratch or normal in context:\n"+lb.getExplanation());
603 } else if (dsttype.equals(STMCONFLICT)) {
604 throw new Error("Access to object that could be either normal or scratch in context:\n"+lb.getExplanation());
608 void processOpNodeSTM(LocalityBinding lb, FlatOpNode fon, Hashtable<TempDescriptor, Integer> currtable) {
609 /* Just propagate value */
610 if (!fon.getLeft().getType().isPtr())
613 Integer srcvalue=currtable.get(fon.getLeft());
615 if (srcvalue==null) {
616 System.out.println(fon);
617 MethodDescriptor md=lb.getMethod();
618 FlatMethod fm=state.getMethodFlat(md);
619 System.out.println(fm.printMethod());
620 throw new Error(fon.getLeft()+" is undefined!");
622 currtable.put(fon.getDest(), srcvalue);
625 void processCastNodeSTM(FlatCastNode fcn, Hashtable<TempDescriptor, Integer> currtable) {
626 if (currtable.containsKey(fcn.getSrc()))
627 currtable.put(fcn.getDst(), currtable.get(fcn.getSrc()));
630 void processReturnNodeSTM(LocalityBinding lb, FlatReturnNode frn, Hashtable<TempDescriptor, Integer> currtable) {
631 if(frn.getReturnTemp()!=null&&frn.getReturnTemp().getType().isPtr()) {
632 Integer returntype=currtable.get(frn.getReturnTemp());
633 lb.setGlobalReturn(mergestm(returntype, lb.getGlobalReturn()));
637 void processLiteralNodeSTM(FlatLiteralNode fln, Hashtable<TempDescriptor, Integer> currtable) {
639 if (fln.getType().isNull())
640 currtable.put(fln.getDst(), STMEITHER);
641 else if (fln.getType().isPtr())
642 currtable.put(fln.getDst(), NORMAL);
645 void processElementNodeSTM(LocalityBinding lb, FlatElementNode fen, Hashtable<TempDescriptor, Integer> currtable) {
646 Integer type=currtable.get(fen.getSrc());
647 TempDescriptor dst=fen.getDst();
648 if (!fen.getDst().getType().isPtr())
652 System.out.println(fen +" in "+lb+" may access undefined variable");
653 MethodDescriptor md=lb.getMethod();
654 FlatMethod fm=state.getMethodFlat(md);
655 System.out.println(fm.printMethod());
657 } else if (type.equals(SCRATCH)) {
658 currtable.put(dst,SCRATCH);
659 } else if (type.equals(NORMAL)) {
660 currtable.put(dst, NORMAL);
661 } else if (type.equals(STMEITHER)) {
662 currtable.put(dst, STMEITHER);
663 } else if (type.equals(STMCONFLICT)) {
664 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
668 private void computeLocalityBindings() {
669 lbmain=new LocalityBinding(typeutil.getMain(), false);
670 lbmain.setGlobalReturn(EITHER);
671 lbmain.setGlobal(0, LOCAL);
672 lbtovisit.add(lbmain);
673 discovered.put(lbmain, lbmain);
674 if (!classtolb.containsKey(lbmain.getMethod().getClassDesc()))
675 classtolb.put(lbmain.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
676 classtolb.get(lbmain.getMethod().getClassDesc()).add(lbmain);
678 if (!methodtolb.containsKey(lbmain.getMethod()))
679 methodtolb.put(lbmain.getMethod(), new HashSet<LocalityBinding>());
680 methodtolb.get(lbmain.getMethod()).add(lbmain);
682 //Do this to force a virtual table number for the run method
683 lbrun=new LocalityBinding(typeutil.getRun(), false);
684 lbrun.setGlobalReturn(EITHER);
685 lbrun.setGlobalThis(GLOBAL);
686 lbtovisit.add(lbrun);
687 discovered.put(lbrun, lbrun);
688 if (!classtolb.containsKey(lbrun.getMethod().getClassDesc()))
689 classtolb.put(lbrun.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
690 classtolb.get(lbrun.getMethod().getClassDesc()).add(lbrun);
692 if (!methodtolb.containsKey(lbrun.getMethod()))
693 methodtolb.put(lbrun.getMethod(), new HashSet<LocalityBinding>());
694 methodtolb.get(lbrun.getMethod()).add(lbrun);
696 while(!lbtovisit.isEmpty()) {
697 LocalityBinding lb=(LocalityBinding) lbtovisit.iterator().next();
698 lbtovisit.remove(lb);
699 Integer returnglobal=lb.getGlobalReturn();
700 MethodDescriptor md=lb.getMethod();
701 Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>> temptable=new Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>();
702 Hashtable<FlatNode, Integer> atomictable=new Hashtable<FlatNode, Integer>();
705 computeCallsFlags(md, lb, temptable, atomictable);
707 System.out.println("Error in "+md+" context "+lb);
711 temptab.put(lb, temptable);
712 atomictab.put(lb, atomictable);
714 if (md.getReturnType()!=null&&!returnglobal.equals(lb.getGlobalReturn())) {
715 //return type is more precise now
716 //rerun everything that call us
717 lbtovisit.addAll(dependence.get(lb));
725 public void computeCallsFlags(MethodDescriptor md, LocalityBinding lb, Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable, Hashtable<FlatNode, Integer> atomictable) {
726 FlatMethod fm=state.getMethodFlat(md);
727 HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
728 tovisit.add(fm.getNext(0));
730 // Build table for initial node
731 Hashtable<TempDescriptor,Integer> table=new Hashtable<TempDescriptor,Integer>();
732 temptable.put(fm, table);
733 atomictable.put(fm, lb.isAtomic() ? 1 : 0);
734 int offset=md.isStatic() ? 0 : 1;
735 if (!md.isStatic()) {
736 table.put(fm.getParameter(0), lb.getGlobalThis());
738 for(int i=offset; i<fm.numParameters(); i++) {
739 TempDescriptor temp=fm.getParameter(i);
740 Integer b=lb.isGlobal(i-offset);
745 while(!tovisit.isEmpty()) {
746 FlatNode fn=tovisit.iterator().next();
748 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
750 for(int i=0; i<fn.numPrev(); i++) {
751 FlatNode prevnode=fn.getPrev(i);
752 if (atomictable.containsKey(prevnode)) {
753 atomicstate=atomictable.get(prevnode).intValue();
755 if (!temptable.containsKey(prevnode))
757 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
758 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator(); tempit.hasNext();) {
759 TempDescriptor temp=tempit.next();
760 Integer tmpint=prevtable.get(temp);
761 Integer oldint=currtable.containsKey(temp) ? currtable.get(temp) : EITHER;
762 Integer newint=merge(tmpint, oldint);
763 currtable.put(temp, newint);
766 atomictable.put(fn, atomicstate);
769 case FKind.FlatAtomicEnterNode:
770 processAtomicEnterNode((FlatAtomicEnterNode)fn, atomictable);
775 case FKind.FlatAtomicExitNode:
776 processAtomicExitNode((FlatAtomicExitNode)fn, atomictable);
780 processCallNode(lb, (FlatCall)fn, currtable, isAtomic(atomictable, fn));
783 case FKind.FlatFieldNode:
784 processFieldNode(lb, (FlatFieldNode)fn, isAtomic(atomictable, fn), currtable);
787 case FKind.FlatSetFieldNode:
788 processSetFieldNode(lb, (FlatSetFieldNode)fn, isAtomic(atomictable,fn), currtable);
792 processNew(lb, (FlatNew)fn, isAtomic(atomictable, fn), currtable);
795 case FKind.FlatOpNode:
796 processOpNode((FlatOpNode)fn, currtable);
799 case FKind.FlatCastNode:
800 processCastNode((FlatCastNode)fn, currtable);
803 case FKind.FlatLiteralNode:
804 processLiteralNode((FlatLiteralNode)fn, currtable);
807 case FKind.FlatReturnNode:
808 processReturnNode(lb, (FlatReturnNode)fn, currtable);
811 case FKind.FlatSetElementNode:
812 processSetElementNode(lb, (FlatSetElementNode)fn, currtable, isAtomic(atomictable, fn));
815 case FKind.FlatElementNode:
816 processElementNode(lb, (FlatElementNode)fn, currtable, isAtomic(atomictable, fn));
819 case FKind.FlatInstanceOfNode:
820 case FKind.FlatCondBranch:
821 case FKind.FlatBackEdge:
824 case FKind.FlatPrefetchNode:
825 //No action needed for these
828 case FKind.FlatFlagActionNode:
829 case FKind.FlatCheckNode:
830 case FKind.FlatTagDeclaration:
831 throw new Error("Incompatible with tasks!");
833 case FKind.FlatMethod:
836 case FKind.FlatOffsetNode:
837 processOffsetNode((FlatOffsetNode)fn, currtable);
841 throw new Error("In finding fn.kind()= " + fn.kind());
843 Hashtable<TempDescriptor,Integer> oldtable=temptable.get(fn);
844 if (oldtable==null||!oldtable.equals(currtable)) {
845 // Update table for this node
846 temptable.put(fn, currtable);
847 for(int i=0; i<fn.numNext(); i++) {
848 tovisit.add(fn.getNext(i));
854 private static boolean isAtomic(Hashtable<FlatNode, Integer> atomictable, FlatNode fn) {
855 return atomictable.get(fn).intValue()>0;
858 private static Integer merge(Integer a, Integer b) {
859 if (a==null||a.equals(EITHER))
861 if (b==null||b.equals(EITHER))
868 void processCallNode(LocalityBinding currlb, FlatCall fc, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
869 MethodDescriptor nodemd=fc.getMethod();
871 Set runmethodset=null;
873 if (nodemd.isStatic()||nodemd.getReturnType()==null) {
874 methodset=new HashSet();
875 methodset.add(nodemd);
877 methodset=callgraph.getMethods(nodemd, fc.getThis().getType());
878 // Build start -> run link
879 if (nodemd.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&
880 nodemd.getSymbol().equals("start")&&!nodemd.getModifiers().isStatic()&&
881 nodemd.numParameters()==1&&nodemd.getParamType(0).isInt()) {
882 assert(nodemd.getModifiers().isNative());
884 MethodDescriptor runmd=null;
885 for(Iterator methodit=nodemd.getClassDesc().getMethodTable().getSet("run").iterator(); methodit.hasNext();) {
886 MethodDescriptor md=(MethodDescriptor) methodit.next();
887 if (md.numParameters()!=0||md.getModifiers().isStatic())
893 runmethodset=callgraph.getMethods(runmd,fc.getThis().getType());
894 methodset.addAll(runmethodset);
895 } else throw new Error("Can't find run method");
899 Integer currreturnval=EITHER; //Start off with the either value
900 for(Iterator methodit=methodset.iterator(); methodit.hasNext();) {
901 MethodDescriptor md=(MethodDescriptor) methodit.next();
903 boolean isnative=md.getModifiers().isNative();
904 boolean isjoin = md.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&!nodemd.getModifiers().isStatic()&&nodemd.numParameters()==0&&md.getSymbol().equals("join");
905 boolean isObjectgetType = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("getType");
906 boolean isObjecthashCode = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("nativehashCode");
908 LocalityBinding lb=new LocalityBinding(md, isatomic);
909 if (isnative&&isatomic) {
910 System.out.println("Don't call native methods in atomic blocks!"+currlb.getMethod());
912 if (runmethodset==null||!runmethodset.contains(md)) {
913 //Skip this part if it is a run method
914 for(int i=0; i<fc.numArgs(); i++) {
915 TempDescriptor arg=fc.getArg(i);
916 if(isnative&&(currtable.get(arg).equals(GLOBAL)||
917 currtable.get(arg).equals(CONFLICT))&& !(nodemd.getSymbol().equals("rangePrefetch"))) {
918 throw new Error("Potential call to native method "+md+" with global parameter:\n"+currlb.getExplanation());
920 lb.setGlobal(i,currtable.get(arg));
924 if (fc.getThis()!=null) {
925 Integer thistype=currtable.get(fc.getThis());
929 if(runmethodset!=null&&runmethodset.contains(md)&&thistype.equals(LOCAL))
930 throw new Error("Starting thread on local object not allowed in context:\n"+currlb.getExplanation());
931 if(isjoin&&thistype.equals(LOCAL))
932 throw new Error("Joining thread on local object not allowed in context:\n"+currlb.getExplanation());
933 if(thistype.equals(CONFLICT))
934 throw new Error("Using type that can be either local or global in context:\n"+currlb.getExplanation());
935 if(runmethodset==null&&thistype.equals(GLOBAL)&&!isatomic && !isjoin)
936 throw new Error("Using global object outside of transaction in context:\n"+currlb.getExplanation());
937 if (runmethodset==null&&isnative&&thistype.equals(GLOBAL) && !isjoin && !isObjectgetType && !isObjecthashCode)
938 throw new Error("Potential call to native method "+md+" on global objects:\n"+currlb.getExplanation());
939 lb.setGlobalThis(thistype);
942 if (!discovered.containsKey(lb)) {
944 lb.setGlobalReturn(LOCAL);
946 lb.setGlobalReturn(EITHER);
947 lb.setParent(currlb);
949 discovered.put(lb, lb);
950 if (!classtolb.containsKey(lb.getMethod().getClassDesc()))
951 classtolb.put(lb.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
952 classtolb.get(lb.getMethod().getClassDesc()).add(lb);
953 if (!methodtolb.containsKey(lb.getMethod()))
954 methodtolb.put(lb.getMethod(), new HashSet<LocalityBinding>());
955 methodtolb.get(lb.getMethod()).add(lb);
957 lb=discovered.get(lb);
958 Integer returnval=lb.getGlobalReturn();
959 currreturnval=merge(returnval, currreturnval);
960 if (!dependence.containsKey(lb))
961 dependence.put(lb, new HashSet<LocalityBinding>());
962 dependence.get(lb).add(currlb);
964 if (!calldep.containsKey(currlb))
965 calldep.put(currlb, new HashSet<LocalityBinding>());
966 calldep.get(currlb).add(lb);
968 if (fc.getReturnTemp()!=null) {
969 currtable.put(fc.getReturnTemp(), currreturnval);
973 void processFieldNode(LocalityBinding lb, FlatFieldNode ffn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
974 Integer type=currtable.get(ffn.getSrc());
975 TempDescriptor dst=ffn.getDst();
976 if (type.equals(LOCAL)) {
977 if (ffn.getField().isGlobal())
978 currtable.put(dst,GLOBAL);
980 currtable.put(dst,LOCAL);
981 } else if (type.equals(GLOBAL)) {
983 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
984 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
985 currtable.put(dst, LOCAL); // primitives are local
987 currtable.put(dst, GLOBAL);
988 } else if (type.equals(EITHER)) {
989 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
990 currtable.put(dst, LOCAL); // primitives are local
991 else if (ffn.getField().isGlobal())
992 currtable.put(dst, GLOBAL);
994 currtable.put(dst, EITHER);
995 } else if (type.equals(CONFLICT)) {
996 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
1000 //need to handle primitives
1001 void processSetFieldNode(LocalityBinding lb, FlatSetFieldNode fsfn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
1002 Integer srctype=currtable.get(fsfn.getSrc());
1003 Integer dsttype=currtable.get(fsfn.getDst());
1005 if (dsttype.equals(LOCAL)) {
1006 if (fsfn.getField().isGlobal()) {
1007 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
1008 throw new Error("Writing possible local reference to global field in context: \n"+lb.getExplanation());
1010 if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
1011 throw new Error("Writing possible global reference to local object in context: \n"+lb.getExplanation());
1013 } else if (dsttype.equals(GLOBAL)) {
1015 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
1016 //okay to store primitives in global object
1017 if (srctype.equals(LOCAL) && fsfn.getField().getType().isPrimitive() && !fsfn.getField().getType().isArray())
1019 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
1020 throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation()+" for FlatFieldNode "+fsfn);
1021 } else if (dsttype.equals(EITHER)) {
1022 if (srctype.equals(CONFLICT))
1023 throw new Error("Using reference that could be local or global in context:\n"+lb.getExplanation());
1024 } else if (dsttype.equals(CONFLICT)) {
1025 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
1029 void processNew(LocalityBinding lb, FlatNew fn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
1030 if (fn.isGlobal()&&!transaction) {
1031 throw new Error("Allocating global object outside of transaction in context:"+lb.getExplanation());
1034 currtable.put(fn.getDst(), GLOBAL);
1036 currtable.put(fn.getDst(), LOCAL);
1039 void processOpNode(FlatOpNode fon, Hashtable<TempDescriptor, Integer> currtable) {
1040 /* Just propagate value */
1041 Integer srcvalue=currtable.get(fon.getLeft());
1043 if (srcvalue==null) {
1044 if (!fon.getLeft().getType().isPtr()) {
1047 throw new Error(fon.getLeft()+" is undefined!");
1049 currtable.put(fon.getDest(), srcvalue);
1052 void processCastNode(FlatCastNode fcn, Hashtable<TempDescriptor, Integer> currtable) {
1053 currtable.put(fcn.getDst(), currtable.get(fcn.getSrc()));
1056 void processLiteralNode(FlatLiteralNode fln, Hashtable<TempDescriptor, Integer> currtable) {
1058 if (fln.getValue()==null)
1059 currtable.put(fln.getDst(), EITHER);
1061 currtable.put(fln.getDst(), LOCAL);
1064 void processOffsetNode(FlatOffsetNode fln, Hashtable<TempDescriptor, Integer> currtable) {
1065 currtable.put(fln.getDst(), LOCAL);
1068 void processReturnNode(LocalityBinding lb, FlatReturnNode frn, Hashtable<TempDescriptor, Integer> currtable) {
1069 if(frn.getReturnTemp()!=null) {
1070 Integer returntype=currtable.get(frn.getReturnTemp());
1071 lb.setGlobalReturn(merge(returntype, lb.getGlobalReturn()));
1075 void processSetElementNode(LocalityBinding lb, FlatSetElementNode fsen, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
1076 Integer srctype=currtable.get(fsen.getSrc());
1077 Integer dsttype=currtable.get(fsen.getDst());
1079 if (dsttype.equals(LOCAL)) {
1080 if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
1081 throw new Error("Writing possible global reference to local object in context:\n"+lb.getExplanation()+fsen);
1082 } else if (dsttype.equals(GLOBAL)) {
1083 if (srctype.equals(LOCAL) && fsen.getDst().getType().dereference().isPrimitive() && !fsen.getDst().getType().dereference().isArray())
1085 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
1086 throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation());
1088 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
1089 } else if (dsttype.equals(EITHER)) {
1090 if (srctype.equals(CONFLICT))
1091 throw new Error("Using reference that could be local or global in context:\n"+lb.getExplanation());
1092 } else if (dsttype.equals(CONFLICT)) {
1093 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
1097 void processElementNode(LocalityBinding lb, FlatElementNode fen, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
1098 Integer type=currtable.get(fen.getSrc());
1099 TempDescriptor dst=fen.getDst();
1100 if (type.equals(LOCAL)) {
1101 currtable.put(dst,LOCAL);
1102 } else if (type.equals(GLOBAL)) {
1104 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
1105 if(fen.getSrc().getType().dereference().isPrimitive()&&
1106 !fen.getSrc().getType().dereference().isArray())
1107 currtable.put(dst, LOCAL);
1109 currtable.put(dst, GLOBAL);
1110 } else if (type.equals(EITHER)) {
1111 if(fen.getSrc().getType().dereference().isPrimitive()&&
1112 !fen.getSrc().getType().dereference().isArray())
1113 currtable.put(dst, LOCAL);
1115 currtable.put(dst, EITHER);
1116 } else if (type.equals(CONFLICT)) {
1117 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
1121 void processAtomicEnterNode(FlatAtomicEnterNode fen, Hashtable<FlatNode, Integer> atomictable) {
1122 int atomic=atomictable.get(fen).intValue();
1123 atomictable.put(fen, new Integer(atomic+1));
1126 void processAtomicExitNode(FlatAtomicExitNode fen, Hashtable<FlatNode, Integer> atomictable) {
1127 int atomic=atomictable.get(fen).intValue();
1128 atomictable.put(fen, new Integer(atomic-1));
1131 private void computeTempstoSave() {
1132 for(Iterator<LocalityBinding> lbit=getLocalityBindings().iterator(); lbit.hasNext();) {
1133 LocalityBinding lb=lbit.next();
1134 computeTempstoSave(lb);
1138 /* Need to checkpoint all temps that could be read from along any
1139 * path that are either:
1140 1) Written to by any assignment inside the transaction
1141 2) Read from a global temp.
1143 Generate tempstosave map from
1144 localitybinding->flatatomicenternode->Set<TempDescriptors>
1147 private void computeTempstoSave(LocalityBinding lb) {
1150 Hashtable<FlatNode, Integer> atomictab=getAtomic(lb);
1151 Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=getNodeTempInfo(lb);
1152 MethodDescriptor md=lb.getMethod();
1153 FlatMethod fm=state.getMethodFlat(md);
1154 Hashtable<FlatNode, Set<TempDescriptor>> nodetotemps=Liveness.computeLiveTemps(fm);
1155 Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> nodetosavetemps=new Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>();
1156 tempstosave.put(lb, nodetosavetemps);
1157 Hashtable<FlatNode, FlatAtomicEnterNode> nodemap=new Hashtable<FlatNode, FlatAtomicEnterNode>();
1158 HashSet<FlatNode> toprocess=new HashSet<FlatNode>();
1159 HashSet<FlatNode> discovered=new HashSet<FlatNode>();
1162 while(!toprocess.isEmpty()) {
1163 FlatNode fn=toprocess.iterator().next();
1164 toprocess.remove(fn);
1165 boolean isatomic=atomictab.get(fn).intValue()>0;
1167 atomictab.get(fn.getPrev(0)).intValue()==0) {
1168 assert(fn.getPrev(0).kind()==FKind.FlatAtomicEnterNode);
1169 nodemap.put(fn, (FlatAtomicEnterNode)fn);
1170 nodetosavetemps.put((FlatAtomicEnterNode)fn, new HashSet<TempDescriptor>());
1171 } else if (isatomic) {
1172 FlatAtomicEnterNode atomicnode=nodemap.get(fn);
1173 Set<TempDescriptor> livetemps=nodetotemps.get(atomicnode);
1174 List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
1175 List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
1177 for(Iterator<TempDescriptor> tempit=livetemps.iterator(); tempit.hasNext();) {
1178 TempDescriptor tmp=tempit.next();
1179 if (writes.contains(tmp)) {
1180 nodetosavetemps.get(atomicnode).add(tmp);
1181 } else if (state.DSM) {
1182 if (reads.contains(tmp)&&temptab.get(fn).get(tmp)==GLOBAL) {
1183 nodetosavetemps.get(atomicnode).add(tmp);
1185 } else if (state.SINGLETM) {
1186 if (reads.contains(tmp)&&tmp.getType().isPtr()&&temptab.get(fn).get(tmp)==NORMAL) {
1187 nodetosavetemps.get(atomicnode).add(tmp);
1192 for(int i=0; i<fn.numNext(); i++) {
1193 FlatNode fnnext=fn.getNext(i);
1194 if (!discovered.contains(fnnext)) {
1195 discovered.add(fnnext);
1196 toprocess.add(fnnext);
1198 nodemap.put(fnnext, nodemap.get(fn));