1 package Analysis.Locality;
4 import Analysis.CallGraph.CallGraph;
8 import IR.MethodDescriptor;
10 import Analysis.Liveness;
11 import IR.ClassDescriptor;
13 public class LocalityAnalysis {
16 Hashtable<LocalityBinding,LocalityBinding> discovered;
17 Hashtable<LocalityBinding, Set<LocalityBinding>> dependence;
18 Hashtable<LocalityBinding, Set<LocalityBinding>> calldep;
19 Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>> temptab;
20 Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>> atomictab;
21 Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>> tempstosave;
22 Hashtable<ClassDescriptor, Set<LocalityBinding>> classtolb;
23 Hashtable<MethodDescriptor, Set<LocalityBinding>> methodtolb;
24 private LocalityBinding lbmain;
25 private LocalityBinding lbrun;
29 public static final Integer LOCAL=new Integer(0);
30 public static final Integer GLOBAL=new Integer(1);
31 public static final Integer EITHER=new Integer(2);
32 public static final Integer CONFLICT=new Integer(3);
34 public static final Integer STMEITHER=new Integer(0);
35 public static final Integer SCRATCH=new Integer(4);
36 public static final Integer NORMAL=new Integer(8);
37 public static final Integer STMCONFLICT=new Integer(12);
39 public LocalityAnalysis(State state, CallGraph callgraph, TypeUtil typeutil) {
40 this.typeutil=typeutil;
42 this.discovered=new Hashtable<LocalityBinding,LocalityBinding>();
43 this.dependence=new Hashtable<LocalityBinding, Set<LocalityBinding>>();
44 this.calldep=new Hashtable<LocalityBinding, Set<LocalityBinding>>();
45 this.temptab=new Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>>();
46 this.atomictab=new Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>>();
47 this.lbtovisit=new Stack();
48 this.callgraph=callgraph;
49 this.tempstosave=new Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>>();
50 this.classtolb=new Hashtable<ClassDescriptor, Set<LocalityBinding>>();
51 this.methodtolb=new Hashtable<MethodDescriptor, Set<LocalityBinding>>();
55 public LocalityBinding getMain() {
59 /** This method returns the set of LocalityBindings that a given
60 * flatcall could invoke */
62 public LocalityBinding getBinding(LocalityBinding currlb, FlatCall fc) {
63 boolean isatomic=getAtomic(currlb).get(fc).intValue()>0;
64 Hashtable<TempDescriptor, Integer> currtable=getNodePreTempInfo(currlb,fc);
65 MethodDescriptor md=fc.getMethod();
67 boolean isnative=md.getModifiers().isNative();
69 LocalityBinding lb=new LocalityBinding(md, isatomic);
71 for(int i=0; i<fc.numArgs(); i++) {
72 TempDescriptor arg=fc.getArg(i);
73 lb.setGlobal(i,currtable.get(arg));
76 if (state.DSM&&fc.getThis()!=null) {
77 Integer thistype=currtable.get(fc.getThis());
80 lb.setGlobalThis(thistype);
81 } else if (state.SINGLETM&&fc.getThis()!=null) {
82 Integer thistype=currtable.get(fc.getThis());
85 lb.setGlobalThis(thistype);
88 // lb.setGlobalThis(EITHER);//default value
89 if (discovered.containsKey(lb))
90 lb=discovered.get(lb);
91 else throw new Error();
96 /** This method returns a set of LocalityBindings for the parameter class. */
97 public Set<LocalityBinding> getClassBindings(ClassDescriptor cd) {
98 return classtolb.get(cd);
101 /** This method returns a set of LocalityBindings for the parameter method. */
103 public Set<LocalityBinding> getMethodBindings(MethodDescriptor md) {
104 return methodtolb.get(md);
107 public Set<MethodDescriptor> getMethods() {
108 return methodtolb.keySet();
111 /** This method returns a set of LocalityBindings. A
112 * LocalityBinding specifies a context a method can be invoked in.
113 * It specifies whether the method is in a transaction and whether
114 * its parameter objects are locals or globals. */
116 public Set<LocalityBinding> getLocalityBindings() {
117 return discovered.keySet();
120 /** This method returns a hashtable for a given LocalityBinding
121 * that tells the current local/global status of temps at the each
122 * node in the flat representation. */
124 public Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> getNodeTempInfo(LocalityBinding lb) {
125 return temptab.get(lb);
128 /** This method returns a hashtable for a given LocalityBinding
129 * that tells the current local/global status of temps at the
130 * beginning of each node in the flat representation. */
132 public Hashtable<TempDescriptor, Integer> getNodePreTempInfo(LocalityBinding lb, FlatNode fn) {
133 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
134 Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable=getNodeTempInfo(lb);
136 for(int i=0; i<fn.numPrev(); i++) {
137 FlatNode prevnode=fn.getPrev(i);
138 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
139 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator(); tempit.hasNext();) {
140 TempDescriptor temp=tempit.next();
141 Integer tmpint=prevtable.get(temp);
142 Integer oldint=currtable.containsKey(temp) ? currtable.get(temp) : (state.DSM?EITHER:STMEITHER);
143 Integer newint=state.DSM?merge(tmpint, oldint):mergestm(tmpint, oldint);
144 currtable.put(temp, newint);
150 /** This method returns an hashtable for a given LocalitBinding
151 * that tells whether a node in the flat represenation is in a
152 * transaction or not. Integer values greater than 0 indicate
153 * that the node is in a transaction and give the nesting depth.
154 * The outermost AtomicEnterNode will have a value of 1 and the
155 * outermost AtomicExitNode will have a value of 0. */
157 public Hashtable<FlatNode, Integer> getAtomic(LocalityBinding lb) {
158 return atomictab.get(lb);
161 /** This methods returns a hashtable for a given LocalityBinding
162 * that tells which temps needs to be saved for each
163 * AtomicEnterNode. */
165 public Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> getTemps(LocalityBinding lb) {
166 return tempstosave.get(lb);
169 public Set<TempDescriptor> getTempSet(LocalityBinding lb) {
170 HashSet<TempDescriptor> set=new HashSet<TempDescriptor>();
171 Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> table=getTemps(lb);
173 for(Iterator<FlatAtomicEnterNode> faenit=table.keySet().iterator(); faenit.hasNext();) {
174 FlatAtomicEnterNode faen=faenit.next();
175 set.addAll(table.get(faen));
180 private void doAnalysis() {
182 computeLocalityBindingsSTM();
184 computeLocalityBindings();
185 computeTempstoSave();
189 private void cleanSets() {
190 HashSet<LocalityBinding> lbset=new HashSet<LocalityBinding>();
191 Stack<LocalityBinding> lbstack=new Stack<LocalityBinding>();
196 while(!lbstack.isEmpty()) {
197 LocalityBinding lb=lbstack.pop();
198 if (calldep.containsKey(lb)) {
199 Set<LocalityBinding> set=new HashSet<LocalityBinding>();
200 set.addAll(calldep.get(lb));
201 set.removeAll(lbset);
206 for(Iterator<LocalityBinding> lbit=discovered.keySet().iterator(); lbit.hasNext();) {
207 LocalityBinding lb=lbit.next();
208 if (!lbset.contains(lb)) {
210 classtolb.get(lb.getMethod().getClassDesc()).remove(lb);
211 methodtolb.get(lb.getMethod()).remove(lb);
216 public MethodDescriptor getStart() {
217 ClassDescriptor cd=typeutil.getClass(TypeUtil.ThreadClass);
218 for(Iterator methodit=cd.getMethodTable().getSet("staticStart").iterator(); methodit
220 MethodDescriptor md=(MethodDescriptor) methodit.next();
221 if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).getSymbol().equals(TypeUtil.ThreadClass))
225 throw new Error("Can't find Thread.run");
229 private void computeLocalityBindingsSTM() {
230 lbmain=new LocalityBinding(typeutil.getMain(), false);
231 lbmain.setGlobalReturn(STMEITHER);
232 lbmain.setGlobal(0, NORMAL);
233 lbtovisit.add(lbmain);
234 discovered.put(lbmain, lbmain);
235 if (!classtolb.containsKey(lbmain.getMethod().getClassDesc()))
236 classtolb.put(lbmain.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
237 classtolb.get(lbmain.getMethod().getClassDesc()).add(lbmain);
239 if (!methodtolb.containsKey(lbmain.getMethod()))
240 methodtolb.put(lbmain.getMethod(), new HashSet<LocalityBinding>());
241 methodtolb.get(lbmain.getMethod()).add(lbmain);
243 //Do this to force a virtual table number for the run method
244 lbrun=new LocalityBinding(getStart(), false);
245 lbrun.setGlobalReturn(STMEITHER);
246 lbrun.setGlobal(0,NORMAL);
247 lbtovisit.add(lbrun);
248 discovered.put(lbrun, lbrun);
249 if (!classtolb.containsKey(lbrun.getMethod().getClassDesc()))
250 classtolb.put(lbrun.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
251 classtolb.get(lbrun.getMethod().getClassDesc()).add(lbrun);
253 if (!methodtolb.containsKey(lbrun.getMethod()))
254 methodtolb.put(lbrun.getMethod(), new HashSet<LocalityBinding>());
255 methodtolb.get(lbrun.getMethod()).add(lbrun);
257 while(!lbtovisit.empty()) {
258 LocalityBinding lb=(LocalityBinding) lbtovisit.pop();
259 Integer returnglobal=lb.getGlobalReturn();
260 MethodDescriptor md=lb.getMethod();
261 Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>> temptable=new Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>();
262 Hashtable<FlatNode, Integer> atomictable=new Hashtable<FlatNode, Integer>();
265 computeCallsFlagsSTM(md, lb, temptable, atomictable);
267 System.out.println("Error in "+md+" context "+lb);
271 temptab.put(lb, temptable);
272 atomictab.put(lb, atomictable);
274 if (md.getReturnType()!=null&&!returnglobal.equals(lb.getGlobalReturn())) {
275 //return type is more precise now
276 //rerun everything that call us
277 lbtovisit.addAll(dependence.get(lb));
282 private static Integer mergestm(Integer a, Integer b) {
283 if (a==null||a.equals(STMEITHER))
285 if (b==null||b.equals(STMEITHER))
292 public void computeCallsFlagsSTM(MethodDescriptor md, LocalityBinding lb, Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable, Hashtable<FlatNode, Integer> atomictable) {
293 FlatMethod fm=state.getMethodFlat(md);
294 HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
295 tovisit.add(fm.getNext(0));
297 // Build table for initial node
298 Hashtable<TempDescriptor,Integer> table=new Hashtable<TempDescriptor,Integer>();
299 temptable.put(fm, table);
300 atomictable.put(fm, lb.isAtomic() ? 1 : 0);
301 int offset=md.isStatic() ? 0 : 1;
302 if (!md.isStatic()) {
303 table.put(fm.getParameter(0), lb.getGlobalThis());
305 for(int i=offset; i<fm.numParameters(); i++) {
306 TempDescriptor temp=fm.getParameter(i);
307 Integer b=lb.isGlobal(i-offset);
312 while(!tovisit.isEmpty()) {
313 FlatNode fn=tovisit.iterator().next();
315 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
317 for(int i=0; i<fn.numPrev(); i++) {
318 FlatNode prevnode=fn.getPrev(i);
319 if (atomictable.containsKey(prevnode)) {
320 atomicstate=atomictable.get(prevnode).intValue();
322 if (!temptable.containsKey(prevnode))
324 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
325 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator(); tempit.hasNext();) {
326 TempDescriptor temp=tempit.next();
327 Integer tmpint=prevtable.get(temp);
328 Integer oldint=currtable.containsKey(temp) ? currtable.get(temp) : STMEITHER;
329 Integer newint=mergestm(tmpint, oldint);
330 currtable.put(temp, newint);
333 atomictable.put(fn, atomicstate);
337 case FKind.FlatAtomicEnterNode:
338 processAtomicEnterNode((FlatAtomicEnterNode)fn, atomictable);
343 case FKind.FlatAtomicExitNode:
344 processAtomicExitNode((FlatAtomicExitNode)fn, atomictable);
348 processCallNodeSTM(lb, (FlatCall)fn, isAtomic(atomictable, fn), currtable, temptable.get(fn));
352 processNewSTM(lb, (FlatNew) fn, currtable);
355 case FKind.FlatFieldNode:
356 processFieldNodeSTM(lb, (FlatFieldNode) fn, currtable);
359 case FKind.FlatSetFieldNode:
360 processSetFieldNodeSTM(lb, (FlatSetFieldNode) fn, currtable);
363 case FKind.FlatSetElementNode:
364 processSetElementNodeSTM(lb, (FlatSetElementNode) fn, currtable);
367 case FKind.FlatElementNode:
368 processElementNodeSTM(lb, (FlatElementNode) fn, currtable);
371 case FKind.FlatOpNode:
372 processOpNodeSTM((FlatOpNode)fn, currtable);
375 case FKind.FlatCastNode:
376 processCastNodeSTM((FlatCastNode)fn, currtable);
379 case FKind.FlatReturnNode:
380 processReturnNodeSTM(lb, (FlatReturnNode)fn, currtable);
383 case FKind.FlatLiteralNode:
384 processLiteralNodeSTM((FlatLiteralNode)fn, currtable);
387 case FKind.FlatMethod:
388 case FKind.FlatOffsetNode:
389 case FKind.FlatInstanceOfNode:
390 case FKind.FlatCondBranch:
391 case FKind.FlatBackEdge:
393 case FKind.FlatPrefetchNode:
395 //No action needed for these
398 case FKind.FlatFlagActionNode:
399 case FKind.FlatCheckNode:
400 case FKind.FlatTagDeclaration:
401 throw new Error("Incompatible with tasks!");
404 throw new Error("In finding fn.kind()= " + fn.kind());
409 Hashtable<TempDescriptor,Integer> oldtable=temptable.get(fn);
410 if (oldtable==null||!oldtable.equals(currtable)) {
411 // Update table for this node
412 temptable.put(fn, currtable);
413 for(int i=0; i<fn.numNext(); i++) {
414 tovisit.add(fn.getNext(i));
420 void processNewSTM(LocalityBinding lb, FlatNew fn, Hashtable<TempDescriptor, Integer> currtable) {
422 currtable.put(fn.getDst(), SCRATCH);
424 currtable.put(fn.getDst(), NORMAL);
427 void processCallNodeSTM(LocalityBinding currlb, FlatCall fc, boolean isatomic, Hashtable<TempDescriptor, Integer> currtable, Hashtable<TempDescriptor, Integer> oldtable) {
428 MethodDescriptor nodemd=fc.getMethod();
430 Set runmethodset=null;
432 if (nodemd.isStatic()||nodemd.getReturnType()==null) {
433 methodset=new HashSet();
434 methodset.add(nodemd);
436 methodset=callgraph.getMethods(nodemd, fc.getThis().getType());
437 // Build start -> run link
438 if (nodemd.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&
439 nodemd.getSymbol().equals("start")&&!nodemd.getModifiers().isStatic()&&
440 nodemd.numParameters()==0) {
441 assert(nodemd.getModifiers().isNative());
443 MethodDescriptor runmd=null;
444 for(Iterator methodit=nodemd.getClassDesc().getMethodTable().getSet("staticStart").iterator(); methodit.hasNext();) {
445 MethodDescriptor md=(MethodDescriptor) methodit.next();
446 if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).getSymbol().equals(TypeUtil.ThreadClass))
452 runmethodset=callgraph.getMethods(runmd,fc.getThis().getType());
453 methodset.addAll(runmethodset);
454 } else throw new Error("Can't find run method");
458 Integer currreturnval=STMEITHER; //Start off with the either value
459 if (oldtable!=null&&fc.getReturnTemp()!=null&&
460 oldtable.get(fc.getReturnTemp())!=null) {
462 currreturnval=mergestm(currreturnval, oldtable.get(fc.getReturnTemp()));
465 for(Iterator methodit=methodset.iterator(); methodit.hasNext();) {
466 MethodDescriptor md=(MethodDescriptor) methodit.next();
468 boolean isnative=md.getModifiers().isNative();
469 boolean isjoin = md.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&!nodemd.getModifiers().isStatic()&&nodemd.numParameters()==0&&md.getSymbol().equals("join");
470 boolean isObjectgetType = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("getType");
471 boolean isObjecthashCode = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("nativehashCode");
473 LocalityBinding lb=new LocalityBinding(md, isatomic);
474 if (isnative&&isatomic) {
475 System.out.println("Don't call native methods in atomic blocks!"+currlb.getMethod());
478 if (runmethodset==null||!runmethodset.contains(md)) {
479 for(int i=0; i<fc.numArgs(); i++) {
480 TempDescriptor arg=fc.getArg(i);
481 lb.setGlobal(i,currtable.get(arg));
483 if (fc.getThis()!=null) {
484 Integer thistype=currtable.get(fc.getThis());
488 if(thistype.equals(STMCONFLICT))
489 throw new Error("Using type that can be either normal or scratch in context:\n"+currlb.getExplanation());
490 lb.setGlobalThis(thistype);
493 Integer thistype=currtable.get(fc.getThis());
494 if (!thistype.equals(NORMAL)) {
495 throw new Error("Called start on possible scratch object");
497 lb.setGlobal(0,currtable.get(fc.getThis()));
500 if (!discovered.containsKey(lb)) {
502 if (nodemd.getReturnType()==null||!nodemd.getReturnType().isPtr())
503 lb.setGlobalReturn(SCRATCH);
505 lb.setGlobalReturn(NORMAL);
507 lb.setGlobalReturn(STMEITHER);
509 lb.setParent(currlb);
511 discovered.put(lb, lb);
512 if (!classtolb.containsKey(lb.getMethod().getClassDesc()))
513 classtolb.put(lb.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
514 classtolb.get(lb.getMethod().getClassDesc()).add(lb);
515 if (!methodtolb.containsKey(lb.getMethod()))
516 methodtolb.put(lb.getMethod(), new HashSet<LocalityBinding>());
517 methodtolb.get(lb.getMethod()).add(lb);
519 lb=discovered.get(lb);
520 Integer returnval=lb.getGlobalReturn();
521 currreturnval=mergestm(returnval, currreturnval);
522 if (!dependence.containsKey(lb))
523 dependence.put(lb, new HashSet<LocalityBinding>());
524 dependence.get(lb).add(currlb);
526 if (!calldep.containsKey(currlb))
527 calldep.put(currlb, new HashSet<LocalityBinding>());
528 calldep.get(currlb).add(lb);
530 if (fc.getReturnTemp()!=null) {
531 currtable.put(fc.getReturnTemp(), currreturnval);
535 void processFieldNodeSTM(LocalityBinding lb, FlatFieldNode ffn, Hashtable<TempDescriptor, Integer> currtable) {
536 Integer type=currtable.get(ffn.getSrc());
537 TempDescriptor dst=ffn.getDst();
538 if (type.equals(SCRATCH)) {
539 currtable.put(dst,SCRATCH);
540 } else if (type.equals(NORMAL)) {
541 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
542 currtable.put(dst, SCRATCH); // primitives are local
544 currtable.put(dst, NORMAL);
545 } else if (type.equals(STMEITHER)) {
546 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
547 currtable.put(dst, SCRATCH); // primitives are local
549 currtable.put(dst, STMEITHER);
550 } else if (type.equals(STMCONFLICT)) {
551 throw new Error("Access to object that could be either normal or scratch in context:\n"+ffn+" "+lb.getExplanation());
555 //need to handle primitives
556 void processSetFieldNodeSTM(LocalityBinding lb, FlatSetFieldNode fsfn, Hashtable<TempDescriptor, Integer> currtable) {
557 Integer srctype=currtable.get(fsfn.getSrc());
558 Integer dsttype=currtable.get(fsfn.getDst());
560 System.out.println(fsfn);
561 if (dsttype.equals(SCRATCH)) {
562 if (srctype.equals(SCRATCH) && fsfn.getField().getType().isPrimitive() && !fsfn.getField().getType().isArray())
564 if (!(srctype.equals(SCRATCH)||srctype.equals(STMEITHER)))
565 throw new Error("Writing possible normal reference to scratch object in context: \n"+lb.getExplanation());
566 } else if (dsttype.equals(NORMAL)) {
567 //okay to store primitives in global object
568 if (srctype.equals(SCRATCH) && fsfn.getField().getType().isPrimitive() && !fsfn.getField().getType().isArray())
570 if (!(srctype.equals(NORMAL)||srctype.equals(STMEITHER)))
571 throw new Error("Writing possible scratch reference to normal object in context:\n"+lb.getExplanation()+" for FlatFieldNode "+fsfn);
572 } else if (dsttype.equals(STMEITHER)) {
573 if (srctype.equals(STMCONFLICT))
574 throw new Error("Using reference that could be scratch or normal in context:\n"+lb.getExplanation());
575 } else if (dsttype.equals(STMCONFLICT)) {
576 throw new Error("Access to object that could be either scratch or normal in context:\n"+lb.getExplanation());
580 void processSetElementNodeSTM(LocalityBinding lb, FlatSetElementNode fsen, Hashtable<TempDescriptor, Integer> currtable) {
581 Integer srctype=currtable.get(fsen.getSrc());
582 Integer dsttype=currtable.get(fsen.getDst());
584 if (dsttype.equals(SCRATCH)) {
585 if (!(srctype.equals(SCRATCH)||srctype.equals(STMEITHER)))
586 throw new Error("Writing possible normal reference to scratch object in context:\n"+lb.getExplanation()+fsen);
587 } else if (dsttype.equals(NORMAL)) {
588 if (srctype.equals(SCRATCH) && fsen.getDst().getType().dereference().isPrimitive() && !fsen.getDst().getType().dereference().isArray())
590 if (!(srctype.equals(NORMAL)||srctype.equals(STMEITHER)))
591 throw new Error("Writing possible scratch reference to normal object in context:\n"+lb.getExplanation());
592 } else if (dsttype.equals(STMEITHER)) {
593 if (srctype.equals(STMCONFLICT))
594 throw new Error("Using reference that could be scratch or normal in context:\n"+lb.getExplanation());
595 } else if (dsttype.equals(STMCONFLICT)) {
596 throw new Error("Access to object that could be either normal or scratch in context:\n"+lb.getExplanation());
600 void processOpNodeSTM(FlatOpNode fon, Hashtable<TempDescriptor, Integer> currtable) {
601 /* Just propagate value */
602 Integer srcvalue=currtable.get(fon.getLeft());
604 if (srcvalue==null) {
605 if (!fon.getLeft().getType().isPtr()) {
608 throw new Error(fon.getLeft()+" is undefined!");
610 currtable.put(fon.getDest(), srcvalue);
613 void processCastNodeSTM(FlatCastNode fcn, Hashtable<TempDescriptor, Integer> currtable) {
614 currtable.put(fcn.getDst(), currtable.get(fcn.getSrc()));
617 void processReturnNodeSTM(LocalityBinding lb, FlatReturnNode frn, Hashtable<TempDescriptor, Integer> currtable) {
618 if(frn.getReturnTemp()!=null) {
619 Integer returntype=currtable.get(frn.getReturnTemp());
620 lb.setGlobalReturn(mergestm(returntype, lb.getGlobalReturn()));
624 void processLiteralNodeSTM(FlatLiteralNode fln, Hashtable<TempDescriptor, Integer> currtable) {
626 if (fln.getType().isNull())
627 currtable.put(fln.getDst(), STMEITHER);
628 else if (fln.getType().isPtr())
629 currtable.put(fln.getDst(), NORMAL);
631 currtable.put(fln.getDst(), SCRATCH);
634 void processElementNodeSTM(LocalityBinding lb, FlatElementNode fen, Hashtable<TempDescriptor, Integer> currtable) {
635 Integer type=currtable.get(fen.getSrc());
636 TempDescriptor dst=fen.getDst();
639 System.out.println(fen +" in "+lb+" may access undefined variable");
641 } else if (type.equals(SCRATCH)) {
642 currtable.put(dst,SCRATCH);
643 } else if (type.equals(NORMAL)) {
644 if(fen.getSrc().getType().dereference().isPrimitive()&&
645 !fen.getSrc().getType().dereference().isArray())
646 currtable.put(dst, SCRATCH);
648 currtable.put(dst, NORMAL);
649 } else if (type.equals(STMEITHER)) {
650 if(fen.getSrc().getType().dereference().isPrimitive()&&
651 !fen.getSrc().getType().dereference().isArray())
652 currtable.put(dst, SCRATCH);
654 currtable.put(dst, STMEITHER);
655 } else if (type.equals(STMCONFLICT)) {
656 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
660 private void computeLocalityBindings() {
661 lbmain=new LocalityBinding(typeutil.getMain(), false);
662 lbmain.setGlobalReturn(EITHER);
663 lbmain.setGlobal(0, LOCAL);
664 lbtovisit.add(lbmain);
665 discovered.put(lbmain, lbmain);
666 if (!classtolb.containsKey(lbmain.getMethod().getClassDesc()))
667 classtolb.put(lbmain.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
668 classtolb.get(lbmain.getMethod().getClassDesc()).add(lbmain);
670 if (!methodtolb.containsKey(lbmain.getMethod()))
671 methodtolb.put(lbmain.getMethod(), new HashSet<LocalityBinding>());
672 methodtolb.get(lbmain.getMethod()).add(lbmain);
674 //Do this to force a virtual table number for the run method
675 lbrun=new LocalityBinding(typeutil.getRun(), false);
676 lbrun.setGlobalReturn(EITHER);
677 lbrun.setGlobalThis(GLOBAL);
678 lbtovisit.add(lbrun);
679 discovered.put(lbrun, lbrun);
680 if (!classtolb.containsKey(lbrun.getMethod().getClassDesc()))
681 classtolb.put(lbrun.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
682 classtolb.get(lbrun.getMethod().getClassDesc()).add(lbrun);
684 if (!methodtolb.containsKey(lbrun.getMethod()))
685 methodtolb.put(lbrun.getMethod(), new HashSet<LocalityBinding>());
686 methodtolb.get(lbrun.getMethod()).add(lbrun);
688 while(!lbtovisit.empty()) {
689 LocalityBinding lb=(LocalityBinding) lbtovisit.pop();
690 Integer returnglobal=lb.getGlobalReturn();
691 MethodDescriptor md=lb.getMethod();
692 Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>> temptable=new Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>();
693 Hashtable<FlatNode, Integer> atomictable=new Hashtable<FlatNode, Integer>();
696 computeCallsFlags(md, lb, temptable, atomictable);
698 System.out.println("Error in "+md+" context "+lb);
702 temptab.put(lb, temptable);
703 atomictab.put(lb, atomictable);
705 if (md.getReturnType()!=null&&!returnglobal.equals(lb.getGlobalReturn())) {
706 //return type is more precise now
707 //rerun everything that call us
708 lbtovisit.addAll(dependence.get(lb));
716 public void computeCallsFlags(MethodDescriptor md, LocalityBinding lb, Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable, Hashtable<FlatNode, Integer> atomictable) {
717 FlatMethod fm=state.getMethodFlat(md);
718 HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
719 tovisit.add(fm.getNext(0));
721 // Build table for initial node
722 Hashtable<TempDescriptor,Integer> table=new Hashtable<TempDescriptor,Integer>();
723 temptable.put(fm, table);
724 atomictable.put(fm, lb.isAtomic() ? 1 : 0);
725 int offset=md.isStatic() ? 0 : 1;
726 if (!md.isStatic()) {
727 table.put(fm.getParameter(0), lb.getGlobalThis());
729 for(int i=offset; i<fm.numParameters(); i++) {
730 TempDescriptor temp=fm.getParameter(i);
731 Integer b=lb.isGlobal(i-offset);
736 while(!tovisit.isEmpty()) {
737 FlatNode fn=tovisit.iterator().next();
739 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
741 for(int i=0; i<fn.numPrev(); i++) {
742 FlatNode prevnode=fn.getPrev(i);
743 if (atomictable.containsKey(prevnode)) {
744 atomicstate=atomictable.get(prevnode).intValue();
746 if (!temptable.containsKey(prevnode))
748 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
749 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator(); tempit.hasNext();) {
750 TempDescriptor temp=tempit.next();
751 Integer tmpint=prevtable.get(temp);
752 Integer oldint=currtable.containsKey(temp) ? currtable.get(temp) : EITHER;
753 Integer newint=merge(tmpint, oldint);
754 currtable.put(temp, newint);
757 atomictable.put(fn, atomicstate);
760 case FKind.FlatAtomicEnterNode:
761 processAtomicEnterNode((FlatAtomicEnterNode)fn, atomictable);
766 case FKind.FlatAtomicExitNode:
767 processAtomicExitNode((FlatAtomicExitNode)fn, atomictable);
771 processCallNode(lb, (FlatCall)fn, currtable, isAtomic(atomictable, fn));
774 case FKind.FlatFieldNode:
775 processFieldNode(lb, (FlatFieldNode)fn, isAtomic(atomictable, fn), currtable);
778 case FKind.FlatSetFieldNode:
779 processSetFieldNode(lb, (FlatSetFieldNode)fn, isAtomic(atomictable,fn), currtable);
783 processNew(lb, (FlatNew)fn, isAtomic(atomictable, fn), currtable);
786 case FKind.FlatOpNode:
787 processOpNode((FlatOpNode)fn, currtable);
790 case FKind.FlatCastNode:
791 processCastNode((FlatCastNode)fn, currtable);
794 case FKind.FlatLiteralNode:
795 processLiteralNode((FlatLiteralNode)fn, currtable);
798 case FKind.FlatReturnNode:
799 processReturnNode(lb, (FlatReturnNode)fn, currtable);
802 case FKind.FlatSetElementNode:
803 processSetElementNode(lb, (FlatSetElementNode)fn, currtable, isAtomic(atomictable, fn));
806 case FKind.FlatElementNode:
807 processElementNode(lb, (FlatElementNode)fn, currtable, isAtomic(atomictable, fn));
810 case FKind.FlatInstanceOfNode:
811 case FKind.FlatCondBranch:
812 case FKind.FlatBackEdge:
815 case FKind.FlatPrefetchNode:
816 //No action needed for these
819 case FKind.FlatFlagActionNode:
820 case FKind.FlatCheckNode:
821 case FKind.FlatTagDeclaration:
822 throw new Error("Incompatible with tasks!");
824 case FKind.FlatMethod:
827 case FKind.FlatOffsetNode:
828 processOffsetNode((FlatOffsetNode)fn, currtable);
832 throw new Error("In finding fn.kind()= " + fn.kind());
834 Hashtable<TempDescriptor,Integer> oldtable=temptable.get(fn);
835 if (oldtable==null||!oldtable.equals(currtable)) {
836 // Update table for this node
837 temptable.put(fn, currtable);
838 for(int i=0; i<fn.numNext(); i++) {
839 tovisit.add(fn.getNext(i));
845 private static boolean isAtomic(Hashtable<FlatNode, Integer> atomictable, FlatNode fn) {
846 return atomictable.get(fn).intValue()>0;
849 private static Integer merge(Integer a, Integer b) {
850 if (a==null||a.equals(EITHER))
852 if (b==null||b.equals(EITHER))
859 void processCallNode(LocalityBinding currlb, FlatCall fc, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
860 MethodDescriptor nodemd=fc.getMethod();
862 Set runmethodset=null;
864 if (nodemd.isStatic()||nodemd.getReturnType()==null) {
865 methodset=new HashSet();
866 methodset.add(nodemd);
868 methodset=callgraph.getMethods(nodemd, fc.getThis().getType());
869 // Build start -> run link
870 if (nodemd.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&
871 nodemd.getSymbol().equals("start")&&!nodemd.getModifiers().isStatic()&&
872 nodemd.numParameters()==1&&nodemd.getParamType(0).isInt()) {
873 assert(nodemd.getModifiers().isNative());
875 MethodDescriptor runmd=null;
876 for(Iterator methodit=nodemd.getClassDesc().getMethodTable().getSet("run").iterator(); methodit.hasNext();) {
877 MethodDescriptor md=(MethodDescriptor) methodit.next();
878 if (md.numParameters()!=0||md.getModifiers().isStatic())
884 runmethodset=callgraph.getMethods(runmd,fc.getThis().getType());
885 methodset.addAll(runmethodset);
886 } else throw new Error("Can't find run method");
890 Integer currreturnval=EITHER; //Start off with the either value
891 for(Iterator methodit=methodset.iterator(); methodit.hasNext();) {
892 MethodDescriptor md=(MethodDescriptor) methodit.next();
894 boolean isnative=md.getModifiers().isNative();
895 boolean isjoin = md.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&!nodemd.getModifiers().isStatic()&&nodemd.numParameters()==0&&md.getSymbol().equals("join");
896 boolean isObjectgetType = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("getType");
897 boolean isObjecthashCode = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("nativehashCode");
899 LocalityBinding lb=new LocalityBinding(md, isatomic);
900 if (isnative&&isatomic) {
901 System.out.println("Don't call native methods in atomic blocks!"+currlb.getMethod());
903 if (runmethodset==null||!runmethodset.contains(md)) {
904 //Skip this part if it is a run method
905 for(int i=0; i<fc.numArgs(); i++) {
906 TempDescriptor arg=fc.getArg(i);
907 if(isnative&&(currtable.get(arg).equals(GLOBAL)||
908 currtable.get(arg).equals(CONFLICT))&& !(nodemd.getSymbol().equals("rangePrefetch"))) {
909 throw new Error("Potential call to native method "+md+" with global parameter:\n"+currlb.getExplanation());
911 lb.setGlobal(i,currtable.get(arg));
915 if (fc.getThis()!=null) {
916 Integer thistype=currtable.get(fc.getThis());
920 if(runmethodset!=null&&runmethodset.contains(md)&&thistype.equals(LOCAL))
921 throw new Error("Starting thread on local object not allowed in context:\n"+currlb.getExplanation());
922 if(isjoin&&thistype.equals(LOCAL))
923 throw new Error("Joining thread on local object not allowed in context:\n"+currlb.getExplanation());
924 if(thistype.equals(CONFLICT))
925 throw new Error("Using type that can be either local or global in context:\n"+currlb.getExplanation());
926 if(runmethodset==null&&thistype.equals(GLOBAL)&&!isatomic && !isjoin)
927 throw new Error("Using global object outside of transaction in context:\n"+currlb.getExplanation());
928 if (runmethodset==null&&isnative&&thistype.equals(GLOBAL) && !isjoin && !isObjectgetType && !isObjecthashCode)
929 throw new Error("Potential call to native method "+md+" on global objects:\n"+currlb.getExplanation());
930 lb.setGlobalThis(thistype);
933 if (!discovered.containsKey(lb)) {
935 lb.setGlobalReturn(LOCAL);
937 lb.setGlobalReturn(EITHER);
938 lb.setParent(currlb);
940 discovered.put(lb, lb);
941 if (!classtolb.containsKey(lb.getMethod().getClassDesc()))
942 classtolb.put(lb.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
943 classtolb.get(lb.getMethod().getClassDesc()).add(lb);
944 if (!methodtolb.containsKey(lb.getMethod()))
945 methodtolb.put(lb.getMethod(), new HashSet<LocalityBinding>());
946 methodtolb.get(lb.getMethod()).add(lb);
948 lb=discovered.get(lb);
949 Integer returnval=lb.getGlobalReturn();
950 currreturnval=merge(returnval, currreturnval);
951 if (!dependence.containsKey(lb))
952 dependence.put(lb, new HashSet<LocalityBinding>());
953 dependence.get(lb).add(currlb);
955 if (!calldep.containsKey(currlb))
956 calldep.put(currlb, new HashSet<LocalityBinding>());
957 calldep.get(currlb).add(lb);
959 if (fc.getReturnTemp()!=null) {
960 currtable.put(fc.getReturnTemp(), currreturnval);
964 void processFieldNode(LocalityBinding lb, FlatFieldNode ffn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
965 Integer type=currtable.get(ffn.getSrc());
966 TempDescriptor dst=ffn.getDst();
967 if (type.equals(LOCAL)) {
968 if (ffn.getField().isGlobal())
969 currtable.put(dst,GLOBAL);
971 currtable.put(dst,LOCAL);
972 } else if (type.equals(GLOBAL)) {
974 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
975 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
976 currtable.put(dst, LOCAL); // primitives are local
978 currtable.put(dst, GLOBAL);
979 } else if (type.equals(EITHER)) {
980 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
981 currtable.put(dst, LOCAL); // primitives are local
982 else if (ffn.getField().isGlobal())
983 currtable.put(dst, GLOBAL);
985 currtable.put(dst, EITHER);
986 } else if (type.equals(CONFLICT)) {
987 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
991 //need to handle primitives
992 void processSetFieldNode(LocalityBinding lb, FlatSetFieldNode fsfn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
993 Integer srctype=currtable.get(fsfn.getSrc());
994 Integer dsttype=currtable.get(fsfn.getDst());
996 if (dsttype.equals(LOCAL)) {
997 if (fsfn.getField().isGlobal()) {
998 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
999 throw new Error("Writing possible local reference to global field in context: \n"+lb.getExplanation());
1001 if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
1002 throw new Error("Writing possible global reference to local object in context: \n"+lb.getExplanation());
1004 } else if (dsttype.equals(GLOBAL)) {
1006 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
1007 //okay to store primitives in global object
1008 if (srctype.equals(LOCAL) && fsfn.getField().getType().isPrimitive() && !fsfn.getField().getType().isArray())
1010 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
1011 throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation()+" for FlatFieldNode "+fsfn);
1012 } else if (dsttype.equals(EITHER)) {
1013 if (srctype.equals(CONFLICT))
1014 throw new Error("Using reference that could be local or global in context:\n"+lb.getExplanation());
1015 } else if (dsttype.equals(CONFLICT)) {
1016 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
1020 void processNew(LocalityBinding lb, FlatNew fn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
1021 if (fn.isGlobal()&&!transaction) {
1022 throw new Error("Allocating global object outside of transaction in context:"+lb.getExplanation());
1025 currtable.put(fn.getDst(), GLOBAL);
1027 currtable.put(fn.getDst(), LOCAL);
1030 void processOpNode(FlatOpNode fon, Hashtable<TempDescriptor, Integer> currtable) {
1031 /* Just propagate value */
1032 Integer srcvalue=currtable.get(fon.getLeft());
1034 if (srcvalue==null) {
1035 if (!fon.getLeft().getType().isPtr()) {
1038 throw new Error(fon.getLeft()+" is undefined!");
1040 currtable.put(fon.getDest(), srcvalue);
1043 void processCastNode(FlatCastNode fcn, Hashtable<TempDescriptor, Integer> currtable) {
1044 currtable.put(fcn.getDst(), currtable.get(fcn.getSrc()));
1047 void processLiteralNode(FlatLiteralNode fln, Hashtable<TempDescriptor, Integer> currtable) {
1049 if (fln.getValue()==null)
1050 currtable.put(fln.getDst(), EITHER);
1052 currtable.put(fln.getDst(), LOCAL);
1055 void processOffsetNode(FlatOffsetNode fln, Hashtable<TempDescriptor, Integer> currtable) {
1056 currtable.put(fln.getDst(), LOCAL);
1059 void processReturnNode(LocalityBinding lb, FlatReturnNode frn, Hashtable<TempDescriptor, Integer> currtable) {
1060 if(frn.getReturnTemp()!=null) {
1061 Integer returntype=currtable.get(frn.getReturnTemp());
1062 lb.setGlobalReturn(merge(returntype, lb.getGlobalReturn()));
1066 void processSetElementNode(LocalityBinding lb, FlatSetElementNode fsen, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
1067 Integer srctype=currtable.get(fsen.getSrc());
1068 Integer dsttype=currtable.get(fsen.getDst());
1070 if (dsttype.equals(LOCAL)) {
1071 if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
1072 throw new Error("Writing possible global reference to local object in context:\n"+lb.getExplanation()+fsen);
1073 } else if (dsttype.equals(GLOBAL)) {
1074 if (srctype.equals(LOCAL) && fsen.getDst().getType().dereference().isPrimitive() && !fsen.getDst().getType().dereference().isArray())
1076 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
1077 throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation());
1079 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
1080 } else if (dsttype.equals(EITHER)) {
1081 if (srctype.equals(CONFLICT))
1082 throw new Error("Using reference that could be local or global in context:\n"+lb.getExplanation());
1083 } else if (dsttype.equals(CONFLICT)) {
1084 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
1088 void processElementNode(LocalityBinding lb, FlatElementNode fen, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
1089 Integer type=currtable.get(fen.getSrc());
1090 TempDescriptor dst=fen.getDst();
1091 if (type.equals(LOCAL)) {
1092 currtable.put(dst,LOCAL);
1093 } else if (type.equals(GLOBAL)) {
1095 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
1096 if(fen.getSrc().getType().dereference().isPrimitive()&&
1097 !fen.getSrc().getType().dereference().isArray())
1098 currtable.put(dst, LOCAL);
1100 currtable.put(dst, GLOBAL);
1101 } else if (type.equals(EITHER)) {
1102 if(fen.getSrc().getType().dereference().isPrimitive()&&
1103 !fen.getSrc().getType().dereference().isArray())
1104 currtable.put(dst, LOCAL);
1106 currtable.put(dst, EITHER);
1107 } else if (type.equals(CONFLICT)) {
1108 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
1112 void processAtomicEnterNode(FlatAtomicEnterNode fen, Hashtable<FlatNode, Integer> atomictable) {
1113 int atomic=atomictable.get(fen).intValue();
1114 atomictable.put(fen, new Integer(atomic+1));
1117 void processAtomicExitNode(FlatAtomicExitNode fen, Hashtable<FlatNode, Integer> atomictable) {
1118 int atomic=atomictable.get(fen).intValue();
1119 atomictable.put(fen, new Integer(atomic-1));
1122 Hashtable<FlatNode, Set<TempDescriptor>> computeLiveTemps(FlatMethod fm) {
1123 return Liveness.computeLiveTemps(fm);
1126 private void computeTempstoSave() {
1127 for(Iterator<LocalityBinding> lbit=getLocalityBindings().iterator(); lbit.hasNext();) {
1128 LocalityBinding lb=lbit.next();
1129 computeTempstoSave(lb);
1133 /* Need to checkpoint all temps that could be read from along any
1134 * path that are either:
1135 1) Written to by any assignment inside the transaction
1136 2) Read from a global temp.
1138 Generate tempstosave map from
1139 localitybinding->flatatomicenternode->Set<TempDescriptors>
1142 private void computeTempstoSave(LocalityBinding lb) {
1145 Hashtable<FlatNode, Integer> atomictab=getAtomic(lb);
1146 Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=getNodeTempInfo(lb);
1147 MethodDescriptor md=lb.getMethod();
1148 FlatMethod fm=state.getMethodFlat(md);
1149 Hashtable<FlatNode, Set<TempDescriptor>> nodetotemps=computeLiveTemps(fm);
1150 Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> nodetosavetemps=new Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>();
1151 tempstosave.put(lb, nodetosavetemps);
1152 Hashtable<FlatNode, FlatAtomicEnterNode> nodemap=new Hashtable<FlatNode, FlatAtomicEnterNode>();
1153 HashSet<FlatNode> toprocess=new HashSet<FlatNode>();
1154 HashSet<FlatNode> discovered=new HashSet<FlatNode>();
1157 while(!toprocess.isEmpty()) {
1158 FlatNode fn=toprocess.iterator().next();
1159 toprocess.remove(fn);
1160 boolean isatomic=atomictab.get(fn).intValue()>0;
1162 atomictab.get(fn.getPrev(0)).intValue()==0) {
1163 assert(fn.getPrev(0).kind()==FKind.FlatAtomicEnterNode);
1164 nodemap.put(fn, (FlatAtomicEnterNode)fn);
1165 nodetosavetemps.put((FlatAtomicEnterNode)fn, new HashSet<TempDescriptor>());
1166 } else if (isatomic) {
1167 FlatAtomicEnterNode atomicnode=nodemap.get(fn);
1168 Set<TempDescriptor> livetemps=nodetotemps.get(fn);
1169 List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
1170 List<TempDescriptor> writes=Arrays.asList(fn.readsTemps());
1172 for(Iterator<TempDescriptor> tempit=livetemps.iterator(); tempit.hasNext();) {
1173 TempDescriptor tmp=tempit.next();
1174 if (writes.contains(tmp)) {
1175 nodetosavetemps.get(atomicnode).add(tmp);
1176 } else if (state.DSM) {
1177 if (reads.contains(tmp)&&temptab.get(fn).get(tmp)==GLOBAL) {
1178 nodetosavetemps.get(atomicnode).add(tmp);
1180 } else if (state.SINGLETM) {
1181 if (reads.contains(tmp)&&tmp.getType().isPtr()&&temptab.get(fn).get(tmp)==NORMAL) {
1182 nodetosavetemps.get(atomicnode).add(tmp);
1187 for(int i=0; i<fn.numNext(); i++) {
1188 FlatNode fnnext=fn.getNext(i);
1189 if (!discovered.contains(fnnext)) {
1190 discovered.add(fnnext);
1191 toprocess.add(fnnext);
1193 nodemap.put(fnnext, nodemap.get(fn));