1 package Analysis.Locality;
4 import Analysis.CallGraph.CallGraph;
8 import IR.MethodDescriptor;
10 import IR.ClassDescriptor;
12 public class LocalityAnalysis {
15 Hashtable<LocalityBinding,LocalityBinding> discovered;
16 Hashtable<LocalityBinding, Set<LocalityBinding>> dependence;
17 Hashtable<LocalityBinding, Set<LocalityBinding>> calldep;
18 Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>> temptab;
19 Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>> atomictab;
20 Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>> tempstosave;
21 Hashtable<ClassDescriptor, Set<LocalityBinding>> classtolb;
22 Hashtable<MethodDescriptor, Set<LocalityBinding>> methodtolb;
23 private LocalityBinding lbmain;
24 private LocalityBinding lbrun;
28 public static final Integer LOCAL=new Integer(0);
29 public static final Integer GLOBAL=new Integer(1);
30 public static final Integer EITHER=new Integer(2);
31 public static final Integer CONFLICT=new Integer(3);
33 public static final Integer STMEITHER=new Integer(0);
34 public static final Integer SCRATCH=new Integer(4);
35 public static final Integer NORMAL=new Integer(8);
36 public static final Integer STMCONFLICT=new Integer(12);
38 public LocalityAnalysis(State state, CallGraph callgraph, TypeUtil typeutil) {
39 this.typeutil=typeutil;
41 this.discovered=new Hashtable<LocalityBinding,LocalityBinding>();
42 this.dependence=new Hashtable<LocalityBinding, Set<LocalityBinding>>();
43 this.calldep=new Hashtable<LocalityBinding, Set<LocalityBinding>>();
44 this.temptab=new Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>>();
45 this.atomictab=new Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>>();
46 this.lbtovisit=new Stack();
47 this.callgraph=callgraph;
48 this.tempstosave=new Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>>();
49 this.classtolb=new Hashtable<ClassDescriptor, Set<LocalityBinding>>();
50 this.methodtolb=new Hashtable<MethodDescriptor, Set<LocalityBinding>>();
54 public LocalityBinding getMain() {
58 /** This method returns the set of LocalityBindings that a given
59 * flatcall could invoke */
61 public LocalityBinding getBinding(LocalityBinding currlb, FlatCall fc) {
62 boolean isatomic=getAtomic(currlb).get(fc).intValue()>0;
63 Hashtable<TempDescriptor, Integer> currtable=getNodePreTempInfo(currlb,fc);
64 MethodDescriptor md=fc.getMethod();
66 boolean isnative=md.getModifiers().isNative();
68 LocalityBinding lb=new LocalityBinding(md, isatomic);
70 for(int i=0; i<fc.numArgs(); i++) {
71 TempDescriptor arg=fc.getArg(i);
72 lb.setGlobal(i,currtable.get(arg));
75 if (state.DSM&&fc.getThis()!=null) {
76 Integer thistype=currtable.get(fc.getThis());
79 lb.setGlobalThis(thistype);
80 } else if (state.SINGLETM&&fc.getThis()!=null) {
81 Integer thistype=currtable.get(fc.getThis());
84 lb.setGlobalThis(thistype);
87 // lb.setGlobalThis(EITHER);//default value
88 if (discovered.containsKey(lb))
89 lb=discovered.get(lb);
90 else throw new Error();
95 /** This method returns a set of LocalityBindings for the parameter class. */
96 public Set<LocalityBinding> getClassBindings(ClassDescriptor cd) {
97 return classtolb.get(cd);
100 /** This method returns a set of LocalityBindings for the parameter method. */
102 public Set<LocalityBinding> getMethodBindings(MethodDescriptor md) {
103 return methodtolb.get(md);
106 public Set<MethodDescriptor> getMethods() {
107 return methodtolb.keySet();
110 /** This method returns a set of LocalityBindings. A
111 * LocalityBinding specifies a context a method can be invoked in.
112 * It specifies whether the method is in a transaction and whether
113 * its parameter objects are locals or globals. */
115 public Set<LocalityBinding> getLocalityBindings() {
116 return discovered.keySet();
119 /** This method returns a hashtable for a given LocalityBinding
120 * that tells the current local/global status of temps at the each
121 * node in the flat representation. */
123 public Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> getNodeTempInfo(LocalityBinding lb) {
124 return temptab.get(lb);
127 /** This method returns a hashtable for a given LocalityBinding
128 * that tells the current local/global status of temps at the
129 * beginning of each node in the flat representation. */
131 public Hashtable<TempDescriptor, Integer> getNodePreTempInfo(LocalityBinding lb, FlatNode fn) {
132 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
133 Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable=getNodeTempInfo(lb);
135 for(int i=0; i<fn.numPrev(); i++) {
136 FlatNode prevnode=fn.getPrev(i);
137 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
138 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator(); tempit.hasNext();) {
139 TempDescriptor temp=tempit.next();
140 Integer tmpint=prevtable.get(temp);
141 Integer oldint=currtable.containsKey(temp) ? currtable.get(temp) : (state.DSM?EITHER:STMEITHER);
142 Integer newint=state.DSM?merge(tmpint, oldint):mergestm(tmpint, oldint);
143 currtable.put(temp, newint);
149 /** This method returns an hashtable for a given LocalitBinding
150 * that tells whether a node in the flat represenation is in a
151 * transaction or not. Integer values greater than 0 indicate
152 * that the node is in a transaction and give the nesting depth.
153 * The outermost AtomicEnterNode will have a value of 1 and the
154 * outermost AtomicExitNode will have a value of 0. */
156 public Hashtable<FlatNode, Integer> getAtomic(LocalityBinding lb) {
157 return atomictab.get(lb);
160 /** This methods returns a hashtable for a given LocalityBinding
161 * that tells which temps needs to be saved for each
162 * AtomicEnterNode. */
164 public Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> getTemps(LocalityBinding lb) {
165 return tempstosave.get(lb);
168 public Set<TempDescriptor> getTempSet(LocalityBinding lb) {
169 HashSet<TempDescriptor> set=new HashSet<TempDescriptor>();
170 Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> table=getTemps(lb);
172 for(Iterator<FlatAtomicEnterNode> faenit=table.keySet().iterator(); faenit.hasNext();) {
173 FlatAtomicEnterNode faen=faenit.next();
174 set.addAll(table.get(faen));
179 private void doAnalysis() {
181 computeLocalityBindingsSTM();
183 computeLocalityBindings();
184 computeTempstoSave();
188 private void cleanSets() {
189 HashSet<LocalityBinding> lbset=new HashSet<LocalityBinding>();
190 Stack<LocalityBinding> lbstack=new Stack<LocalityBinding>();
195 while(!lbstack.isEmpty()) {
196 LocalityBinding lb=lbstack.pop();
197 if (calldep.containsKey(lb)) {
198 Set<LocalityBinding> set=new HashSet<LocalityBinding>();
199 set.addAll(calldep.get(lb));
200 set.removeAll(lbset);
205 for(Iterator<LocalityBinding> lbit=discovered.keySet().iterator(); lbit.hasNext();) {
206 LocalityBinding lb=lbit.next();
207 if (!lbset.contains(lb)) {
209 classtolb.get(lb.getMethod().getClassDesc()).remove(lb);
210 methodtolb.get(lb.getMethod()).remove(lb);
215 public MethodDescriptor getStart() {
216 ClassDescriptor cd=typeutil.getClass(TypeUtil.ThreadClass);
217 for(Iterator methodit=cd.getMethodTable().getSet("staticStart").iterator(); methodit
219 MethodDescriptor md=(MethodDescriptor) methodit.next();
220 if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).getSymbol().equals(TypeUtil.ThreadClass))
224 throw new Error("Can't find Thread.run");
228 private void computeLocalityBindingsSTM() {
229 lbmain=new LocalityBinding(typeutil.getMain(), false);
230 lbmain.setGlobalReturn(STMEITHER);
231 lbmain.setGlobal(0, NORMAL);
232 lbtovisit.add(lbmain);
233 discovered.put(lbmain, lbmain);
234 if (!classtolb.containsKey(lbmain.getMethod().getClassDesc()))
235 classtolb.put(lbmain.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
236 classtolb.get(lbmain.getMethod().getClassDesc()).add(lbmain);
238 if (!methodtolb.containsKey(lbmain.getMethod()))
239 methodtolb.put(lbmain.getMethod(), new HashSet<LocalityBinding>());
240 methodtolb.get(lbmain.getMethod()).add(lbmain);
242 //Do this to force a virtual table number for the run method
243 lbrun=new LocalityBinding(getStart(), false);
244 lbrun.setGlobalReturn(STMEITHER);
245 lbrun.setGlobal(0,NORMAL);
246 lbtovisit.add(lbrun);
247 discovered.put(lbrun, lbrun);
248 if (!classtolb.containsKey(lbrun.getMethod().getClassDesc()))
249 classtolb.put(lbrun.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
250 classtolb.get(lbrun.getMethod().getClassDesc()).add(lbrun);
252 if (!methodtolb.containsKey(lbrun.getMethod()))
253 methodtolb.put(lbrun.getMethod(), new HashSet<LocalityBinding>());
254 methodtolb.get(lbrun.getMethod()).add(lbrun);
256 while(!lbtovisit.empty()) {
257 LocalityBinding lb=(LocalityBinding) lbtovisit.pop();
258 Integer returnglobal=lb.getGlobalReturn();
259 MethodDescriptor md=lb.getMethod();
260 Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>> temptable=new Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>();
261 Hashtable<FlatNode, Integer> atomictable=new Hashtable<FlatNode, Integer>();
264 computeCallsFlagsSTM(md, lb, temptable, atomictable);
266 System.out.println("Error in "+md+" context "+lb);
270 temptab.put(lb, temptable);
271 atomictab.put(lb, atomictable);
273 if (md.getReturnType()!=null&&!returnglobal.equals(lb.getGlobalReturn())) {
274 //return type is more precise now
275 //rerun everything that call us
276 lbtovisit.addAll(dependence.get(lb));
281 private static Integer mergestm(Integer a, Integer b) {
282 if (a==null||a.equals(STMEITHER))
284 if (b==null||b.equals(STMEITHER))
291 public void computeCallsFlagsSTM(MethodDescriptor md, LocalityBinding lb, Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable, Hashtable<FlatNode, Integer> atomictable) {
292 FlatMethod fm=state.getMethodFlat(md);
293 HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
294 tovisit.add(fm.getNext(0));
296 // Build table for initial node
297 Hashtable<TempDescriptor,Integer> table=new Hashtable<TempDescriptor,Integer>();
298 temptable.put(fm, table);
299 atomictable.put(fm, lb.isAtomic() ? 1 : 0);
300 int offset=md.isStatic() ? 0 : 1;
301 if (!md.isStatic()) {
302 table.put(fm.getParameter(0), lb.getGlobalThis());
304 for(int i=offset; i<fm.numParameters(); i++) {
305 TempDescriptor temp=fm.getParameter(i);
306 Integer b=lb.isGlobal(i-offset);
311 while(!tovisit.isEmpty()) {
312 FlatNode fn=tovisit.iterator().next();
314 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
316 for(int i=0; i<fn.numPrev(); i++) {
317 FlatNode prevnode=fn.getPrev(i);
318 if (atomictable.containsKey(prevnode)) {
319 atomicstate=atomictable.get(prevnode).intValue();
321 if (!temptable.containsKey(prevnode))
323 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
324 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator(); tempit.hasNext();) {
325 TempDescriptor temp=tempit.next();
326 Integer tmpint=prevtable.get(temp);
327 Integer oldint=currtable.containsKey(temp) ? currtable.get(temp) : STMEITHER;
328 Integer newint=mergestm(tmpint, oldint);
329 currtable.put(temp, newint);
332 atomictable.put(fn, atomicstate);
336 case FKind.FlatAtomicEnterNode:
337 processAtomicEnterNode((FlatAtomicEnterNode)fn, atomictable);
342 case FKind.FlatAtomicExitNode:
343 processAtomicExitNode((FlatAtomicExitNode)fn, atomictable);
347 processCallNodeSTM(lb, (FlatCall)fn, isAtomic(atomictable, fn), currtable, temptable.get(fn));
351 processNewSTM(lb, (FlatNew) fn, currtable);
354 case FKind.FlatFieldNode:
355 processFieldNodeSTM(lb, (FlatFieldNode) fn, currtable);
358 case FKind.FlatSetFieldNode:
359 processSetFieldNodeSTM(lb, (FlatSetFieldNode) fn, currtable);
362 case FKind.FlatSetElementNode:
363 processSetElementNodeSTM(lb, (FlatSetElementNode) fn, currtable);
366 case FKind.FlatElementNode:
367 processElementNodeSTM(lb, (FlatElementNode) fn, currtable);
370 case FKind.FlatOpNode:
371 processOpNodeSTM((FlatOpNode)fn, currtable);
374 case FKind.FlatCastNode:
375 processCastNodeSTM((FlatCastNode)fn, currtable);
378 case FKind.FlatReturnNode:
379 processReturnNodeSTM(lb, (FlatReturnNode)fn, currtable);
382 case FKind.FlatLiteralNode:
383 processLiteralNodeSTM((FlatLiteralNode)fn, currtable);
386 case FKind.FlatMethod:
387 case FKind.FlatOffsetNode:
388 case FKind.FlatInstanceOfNode:
389 case FKind.FlatCondBranch:
390 case FKind.FlatBackEdge:
392 case FKind.FlatPrefetchNode:
394 //No action needed for these
397 case FKind.FlatFlagActionNode:
398 case FKind.FlatCheckNode:
399 case FKind.FlatTagDeclaration:
400 throw new Error("Incompatible with tasks!");
403 throw new Error("In finding fn.kind()= " + fn.kind());
408 Hashtable<TempDescriptor,Integer> oldtable=temptable.get(fn);
409 if (oldtable==null||!oldtable.equals(currtable)) {
410 // Update table for this node
411 temptable.put(fn, currtable);
412 for(int i=0; i<fn.numNext(); i++) {
413 tovisit.add(fn.getNext(i));
419 void processNewSTM(LocalityBinding lb, FlatNew fn, Hashtable<TempDescriptor, Integer> currtable) {
421 currtable.put(fn.getDst(), SCRATCH);
423 currtable.put(fn.getDst(), NORMAL);
426 void processCallNodeSTM(LocalityBinding currlb, FlatCall fc, boolean isatomic, Hashtable<TempDescriptor, Integer> currtable, Hashtable<TempDescriptor, Integer> oldtable) {
427 MethodDescriptor nodemd=fc.getMethod();
429 Set runmethodset=null;
431 if (nodemd.isStatic()||nodemd.getReturnType()==null) {
432 methodset=new HashSet();
433 methodset.add(nodemd);
435 methodset=callgraph.getMethods(nodemd, fc.getThis().getType());
436 // Build start -> run link
437 if (nodemd.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&
438 nodemd.getSymbol().equals("start")&&!nodemd.getModifiers().isStatic()&&
439 nodemd.numParameters()==0) {
440 assert(nodemd.getModifiers().isNative());
442 MethodDescriptor runmd=null;
443 for(Iterator methodit=nodemd.getClassDesc().getMethodTable().getSet("staticStart").iterator(); methodit.hasNext();) {
444 MethodDescriptor md=(MethodDescriptor) methodit.next();
445 if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).getSymbol().equals(TypeUtil.ThreadClass))
451 runmethodset=callgraph.getMethods(runmd,fc.getThis().getType());
452 methodset.addAll(runmethodset);
453 } else throw new Error("Can't find run method");
457 Integer currreturnval=STMEITHER; //Start off with the either value
458 if (oldtable!=null&&fc.getReturnTemp()!=null&&
459 oldtable.get(fc.getReturnTemp())!=null) {
461 currreturnval=mergestm(currreturnval, oldtable.get(fc.getReturnTemp()));
464 for(Iterator methodit=methodset.iterator(); methodit.hasNext();) {
465 MethodDescriptor md=(MethodDescriptor) methodit.next();
467 boolean isnative=md.getModifiers().isNative();
468 boolean isjoin = md.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&!nodemd.getModifiers().isStatic()&&nodemd.numParameters()==0&&md.getSymbol().equals("join");
469 boolean isObjectgetType = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("getType");
470 boolean isObjecthashCode = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("nativehashCode");
472 LocalityBinding lb=new LocalityBinding(md, isatomic);
473 if (isnative&&isatomic) {
474 System.out.println("Don't call native methods in atomic blocks!"+currlb.getMethod());
477 if (runmethodset==null||!runmethodset.contains(md)) {
478 for(int i=0; i<fc.numArgs(); i++) {
479 TempDescriptor arg=fc.getArg(i);
480 lb.setGlobal(i,currtable.get(arg));
482 if (fc.getThis()!=null) {
483 Integer thistype=currtable.get(fc.getThis());
487 if(thistype.equals(STMCONFLICT))
488 throw new Error("Using type that can be either normal or scratch in context:\n"+currlb.getExplanation());
489 lb.setGlobalThis(thistype);
492 Integer thistype=currtable.get(fc.getThis());
493 if (!thistype.equals(NORMAL)) {
494 throw new Error("Called start on possible scratch object");
496 lb.setGlobal(0,currtable.get(fc.getThis()));
499 if (!discovered.containsKey(lb)) {
501 if (nodemd.getReturnType()==null||!nodemd.getReturnType().isPtr())
502 lb.setGlobalReturn(SCRATCH);
504 lb.setGlobalReturn(NORMAL);
506 lb.setGlobalReturn(STMEITHER);
508 lb.setParent(currlb);
510 discovered.put(lb, lb);
511 if (!classtolb.containsKey(lb.getMethod().getClassDesc()))
512 classtolb.put(lb.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
513 classtolb.get(lb.getMethod().getClassDesc()).add(lb);
514 if (!methodtolb.containsKey(lb.getMethod()))
515 methodtolb.put(lb.getMethod(), new HashSet<LocalityBinding>());
516 methodtolb.get(lb.getMethod()).add(lb);
518 lb=discovered.get(lb);
519 Integer returnval=lb.getGlobalReturn();
520 currreturnval=mergestm(returnval, currreturnval);
521 if (!dependence.containsKey(lb))
522 dependence.put(lb, new HashSet<LocalityBinding>());
523 dependence.get(lb).add(currlb);
525 if (!calldep.containsKey(currlb))
526 calldep.put(currlb, new HashSet<LocalityBinding>());
527 calldep.get(currlb).add(lb);
529 if (fc.getReturnTemp()!=null) {
530 currtable.put(fc.getReturnTemp(), currreturnval);
534 void processFieldNodeSTM(LocalityBinding lb, FlatFieldNode ffn, Hashtable<TempDescriptor, Integer> currtable) {
535 Integer type=currtable.get(ffn.getSrc());
536 TempDescriptor dst=ffn.getDst();
537 if (type.equals(SCRATCH)) {
538 currtable.put(dst,SCRATCH);
539 } else if (type.equals(NORMAL)) {
540 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
541 currtable.put(dst, SCRATCH); // primitives are local
543 currtable.put(dst, NORMAL);
544 } else if (type.equals(STMEITHER)) {
545 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
546 currtable.put(dst, SCRATCH); // primitives are local
548 currtable.put(dst, STMEITHER);
549 } else if (type.equals(STMCONFLICT)) {
550 throw new Error("Access to object that could be either normal or scratch in context:\n"+ffn+" "+lb.getExplanation());
554 //need to handle primitives
555 void processSetFieldNodeSTM(LocalityBinding lb, FlatSetFieldNode fsfn, Hashtable<TempDescriptor, Integer> currtable) {
556 Integer srctype=currtable.get(fsfn.getSrc());
557 Integer dsttype=currtable.get(fsfn.getDst());
559 System.out.println(fsfn);
560 if (dsttype.equals(SCRATCH)) {
561 if (srctype.equals(SCRATCH) && fsfn.getField().getType().isPrimitive() && !fsfn.getField().getType().isArray())
563 if (!(srctype.equals(SCRATCH)||srctype.equals(STMEITHER)))
564 throw new Error("Writing possible normal reference to scratch object in context: \n"+lb.getExplanation());
565 } else if (dsttype.equals(NORMAL)) {
566 //okay to store primitives in global object
567 if (srctype.equals(SCRATCH) && fsfn.getField().getType().isPrimitive() && !fsfn.getField().getType().isArray())
569 if (!(srctype.equals(NORMAL)||srctype.equals(STMEITHER)))
570 throw new Error("Writing possible scratch reference to normal object in context:\n"+lb.getExplanation()+" for FlatFieldNode "+fsfn);
571 } else if (dsttype.equals(STMEITHER)) {
572 if (srctype.equals(STMCONFLICT))
573 throw new Error("Using reference that could be scratch or normal in context:\n"+lb.getExplanation());
574 } else if (dsttype.equals(STMCONFLICT)) {
575 throw new Error("Access to object that could be either scratch or normal in context:\n"+lb.getExplanation());
579 void processSetElementNodeSTM(LocalityBinding lb, FlatSetElementNode fsen, Hashtable<TempDescriptor, Integer> currtable) {
580 Integer srctype=currtable.get(fsen.getSrc());
581 Integer dsttype=currtable.get(fsen.getDst());
583 if (dsttype.equals(SCRATCH)) {
584 if (!(srctype.equals(SCRATCH)||srctype.equals(STMEITHER)))
585 throw new Error("Writing possible normal reference to scratch object in context:\n"+lb.getExplanation()+fsen);
586 } else if (dsttype.equals(NORMAL)) {
587 if (srctype.equals(SCRATCH) && fsen.getDst().getType().dereference().isPrimitive() && !fsen.getDst().getType().dereference().isArray())
589 if (!(srctype.equals(NORMAL)||srctype.equals(STMEITHER)))
590 throw new Error("Writing possible scratch reference to normal object in context:\n"+lb.getExplanation());
591 } else if (dsttype.equals(STMEITHER)) {
592 if (srctype.equals(STMCONFLICT))
593 throw new Error("Using reference that could be scratch or normal in context:\n"+lb.getExplanation());
594 } else if (dsttype.equals(STMCONFLICT)) {
595 throw new Error("Access to object that could be either normal or scratch in context:\n"+lb.getExplanation());
599 void processOpNodeSTM(FlatOpNode fon, Hashtable<TempDescriptor, Integer> currtable) {
600 /* Just propagate value */
601 Integer srcvalue=currtable.get(fon.getLeft());
603 if (srcvalue==null) {
604 if (!fon.getLeft().getType().isPtr()) {
607 throw new Error(fon.getLeft()+" is undefined!");
609 currtable.put(fon.getDest(), srcvalue);
612 void processCastNodeSTM(FlatCastNode fcn, Hashtable<TempDescriptor, Integer> currtable) {
613 currtable.put(fcn.getDst(), currtable.get(fcn.getSrc()));
616 void processReturnNodeSTM(LocalityBinding lb, FlatReturnNode frn, Hashtable<TempDescriptor, Integer> currtable) {
617 if(frn.getReturnTemp()!=null) {
618 Integer returntype=currtable.get(frn.getReturnTemp());
619 lb.setGlobalReturn(mergestm(returntype, lb.getGlobalReturn()));
623 void processLiteralNodeSTM(FlatLiteralNode fln, Hashtable<TempDescriptor, Integer> currtable) {
625 if (fln.getType().isNull())
626 currtable.put(fln.getDst(), STMEITHER);
627 else if (fln.getType().isPtr())
628 currtable.put(fln.getDst(), NORMAL);
630 currtable.put(fln.getDst(), SCRATCH);
633 void processElementNodeSTM(LocalityBinding lb, FlatElementNode fen, Hashtable<TempDescriptor, Integer> currtable) {
634 Integer type=currtable.get(fen.getSrc());
635 TempDescriptor dst=fen.getDst();
638 System.out.println(fen +" in "+lb+" may access undefined variable");
640 } else if (type.equals(SCRATCH)) {
641 currtable.put(dst,SCRATCH);
642 } else if (type.equals(NORMAL)) {
643 if(fen.getSrc().getType().dereference().isPrimitive()&&
644 !fen.getSrc().getType().dereference().isArray())
645 currtable.put(dst, SCRATCH);
647 currtable.put(dst, NORMAL);
648 } else if (type.equals(STMEITHER)) {
649 if(fen.getSrc().getType().dereference().isPrimitive()&&
650 !fen.getSrc().getType().dereference().isArray())
651 currtable.put(dst, SCRATCH);
653 currtable.put(dst, STMEITHER);
654 } else if (type.equals(STMCONFLICT)) {
655 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
659 private void computeLocalityBindings() {
660 lbmain=new LocalityBinding(typeutil.getMain(), false);
661 lbmain.setGlobalReturn(EITHER);
662 lbmain.setGlobal(0, LOCAL);
663 lbtovisit.add(lbmain);
664 discovered.put(lbmain, lbmain);
665 if (!classtolb.containsKey(lbmain.getMethod().getClassDesc()))
666 classtolb.put(lbmain.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
667 classtolb.get(lbmain.getMethod().getClassDesc()).add(lbmain);
669 if (!methodtolb.containsKey(lbmain.getMethod()))
670 methodtolb.put(lbmain.getMethod(), new HashSet<LocalityBinding>());
671 methodtolb.get(lbmain.getMethod()).add(lbmain);
673 //Do this to force a virtual table number for the run method
674 lbrun=new LocalityBinding(typeutil.getRun(), false);
675 lbrun.setGlobalReturn(EITHER);
676 lbrun.setGlobalThis(GLOBAL);
677 lbtovisit.add(lbrun);
678 discovered.put(lbrun, lbrun);
679 if (!classtolb.containsKey(lbrun.getMethod().getClassDesc()))
680 classtolb.put(lbrun.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
681 classtolb.get(lbrun.getMethod().getClassDesc()).add(lbrun);
683 if (!methodtolb.containsKey(lbrun.getMethod()))
684 methodtolb.put(lbrun.getMethod(), new HashSet<LocalityBinding>());
685 methodtolb.get(lbrun.getMethod()).add(lbrun);
687 while(!lbtovisit.empty()) {
688 LocalityBinding lb=(LocalityBinding) lbtovisit.pop();
689 Integer returnglobal=lb.getGlobalReturn();
690 MethodDescriptor md=lb.getMethod();
691 Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>> temptable=new Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>();
692 Hashtable<FlatNode, Integer> atomictable=new Hashtable<FlatNode, Integer>();
695 computeCallsFlags(md, lb, temptable, atomictable);
697 System.out.println("Error in "+md+" context "+lb);
701 temptab.put(lb, temptable);
702 atomictab.put(lb, atomictable);
704 if (md.getReturnType()!=null&&!returnglobal.equals(lb.getGlobalReturn())) {
705 //return type is more precise now
706 //rerun everything that call us
707 lbtovisit.addAll(dependence.get(lb));
715 public void computeCallsFlags(MethodDescriptor md, LocalityBinding lb, Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable, Hashtable<FlatNode, Integer> atomictable) {
716 FlatMethod fm=state.getMethodFlat(md);
717 HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
718 tovisit.add(fm.getNext(0));
720 // Build table for initial node
721 Hashtable<TempDescriptor,Integer> table=new Hashtable<TempDescriptor,Integer>();
722 temptable.put(fm, table);
723 atomictable.put(fm, lb.isAtomic() ? 1 : 0);
724 int offset=md.isStatic() ? 0 : 1;
725 if (!md.isStatic()) {
726 table.put(fm.getParameter(0), lb.getGlobalThis());
728 for(int i=offset; i<fm.numParameters(); i++) {
729 TempDescriptor temp=fm.getParameter(i);
730 Integer b=lb.isGlobal(i-offset);
735 while(!tovisit.isEmpty()) {
736 FlatNode fn=tovisit.iterator().next();
738 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
740 for(int i=0; i<fn.numPrev(); i++) {
741 FlatNode prevnode=fn.getPrev(i);
742 if (atomictable.containsKey(prevnode)) {
743 atomicstate=atomictable.get(prevnode).intValue();
745 if (!temptable.containsKey(prevnode))
747 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
748 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator(); tempit.hasNext();) {
749 TempDescriptor temp=tempit.next();
750 Integer tmpint=prevtable.get(temp);
751 Integer oldint=currtable.containsKey(temp) ? currtable.get(temp) : EITHER;
752 Integer newint=merge(tmpint, oldint);
753 currtable.put(temp, newint);
756 atomictable.put(fn, atomicstate);
759 case FKind.FlatAtomicEnterNode:
760 processAtomicEnterNode((FlatAtomicEnterNode)fn, atomictable);
765 case FKind.FlatAtomicExitNode:
766 processAtomicExitNode((FlatAtomicExitNode)fn, atomictable);
770 processCallNode(lb, (FlatCall)fn, currtable, isAtomic(atomictable, fn));
773 case FKind.FlatFieldNode:
774 processFieldNode(lb, (FlatFieldNode)fn, isAtomic(atomictable, fn), currtable);
777 case FKind.FlatSetFieldNode:
778 processSetFieldNode(lb, (FlatSetFieldNode)fn, isAtomic(atomictable,fn), currtable);
782 processNew(lb, (FlatNew)fn, isAtomic(atomictable, fn), currtable);
785 case FKind.FlatOpNode:
786 processOpNode((FlatOpNode)fn, currtable);
789 case FKind.FlatCastNode:
790 processCastNode((FlatCastNode)fn, currtable);
793 case FKind.FlatLiteralNode:
794 processLiteralNode((FlatLiteralNode)fn, currtable);
797 case FKind.FlatReturnNode:
798 processReturnNode(lb, (FlatReturnNode)fn, currtable);
801 case FKind.FlatSetElementNode:
802 processSetElementNode(lb, (FlatSetElementNode)fn, currtable, isAtomic(atomictable, fn));
805 case FKind.FlatElementNode:
806 processElementNode(lb, (FlatElementNode)fn, currtable, isAtomic(atomictable, fn));
809 case FKind.FlatInstanceOfNode:
810 case FKind.FlatCondBranch:
811 case FKind.FlatBackEdge:
814 case FKind.FlatPrefetchNode:
815 //No action needed for these
818 case FKind.FlatFlagActionNode:
819 case FKind.FlatCheckNode:
820 case FKind.FlatTagDeclaration:
821 throw new Error("Incompatible with tasks!");
823 case FKind.FlatMethod:
826 case FKind.FlatOffsetNode:
827 processOffsetNode((FlatOffsetNode)fn, currtable);
831 throw new Error("In finding fn.kind()= " + fn.kind());
833 Hashtable<TempDescriptor,Integer> oldtable=temptable.get(fn);
834 if (oldtable==null||!oldtable.equals(currtable)) {
835 // Update table for this node
836 temptable.put(fn, currtable);
837 for(int i=0; i<fn.numNext(); i++) {
838 tovisit.add(fn.getNext(i));
844 private static boolean isAtomic(Hashtable<FlatNode, Integer> atomictable, FlatNode fn) {
845 return atomictable.get(fn).intValue()>0;
848 private static Integer merge(Integer a, Integer b) {
849 if (a==null||a.equals(EITHER))
851 if (b==null||b.equals(EITHER))
858 void processCallNode(LocalityBinding currlb, FlatCall fc, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
859 MethodDescriptor nodemd=fc.getMethod();
861 Set runmethodset=null;
863 if (nodemd.isStatic()||nodemd.getReturnType()==null) {
864 methodset=new HashSet();
865 methodset.add(nodemd);
867 methodset=callgraph.getMethods(nodemd, fc.getThis().getType());
868 // Build start -> run link
869 if (nodemd.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&
870 nodemd.getSymbol().equals("start")&&!nodemd.getModifiers().isStatic()&&
871 nodemd.numParameters()==1&&nodemd.getParamType(0).isInt()) {
872 assert(nodemd.getModifiers().isNative());
874 MethodDescriptor runmd=null;
875 for(Iterator methodit=nodemd.getClassDesc().getMethodTable().getSet("run").iterator(); methodit.hasNext();) {
876 MethodDescriptor md=(MethodDescriptor) methodit.next();
877 if (md.numParameters()!=0||md.getModifiers().isStatic())
883 runmethodset=callgraph.getMethods(runmd,fc.getThis().getType());
884 methodset.addAll(runmethodset);
885 } else throw new Error("Can't find run method");
889 Integer currreturnval=EITHER; //Start off with the either value
890 for(Iterator methodit=methodset.iterator(); methodit.hasNext();) {
891 MethodDescriptor md=(MethodDescriptor) methodit.next();
893 boolean isnative=md.getModifiers().isNative();
894 boolean isjoin = md.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&!nodemd.getModifiers().isStatic()&&nodemd.numParameters()==0&&md.getSymbol().equals("join");
895 boolean isObjectgetType = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("getType");
896 boolean isObjecthashCode = md.getClassDesc().getSymbol().equals("Object") && md.getSymbol().equals("nativehashCode");
898 LocalityBinding lb=new LocalityBinding(md, isatomic);
899 if (isnative&&isatomic) {
900 System.out.println("Don't call native methods in atomic blocks!"+currlb.getMethod());
902 if (runmethodset==null||!runmethodset.contains(md)) {
903 //Skip this part if it is a run method
904 for(int i=0; i<fc.numArgs(); i++) {
905 TempDescriptor arg=fc.getArg(i);
906 if(isnative&&(currtable.get(arg).equals(GLOBAL)||
907 currtable.get(arg).equals(CONFLICT))&& !(nodemd.getSymbol().equals("rangePrefetch"))) {
908 throw new Error("Potential call to native method "+md+" with global parameter:\n"+currlb.getExplanation());
910 lb.setGlobal(i,currtable.get(arg));
914 if (fc.getThis()!=null) {
915 Integer thistype=currtable.get(fc.getThis());
919 if(runmethodset!=null&&runmethodset.contains(md)&&thistype.equals(LOCAL))
920 throw new Error("Starting thread on local object not allowed in context:\n"+currlb.getExplanation());
921 if(isjoin&&thistype.equals(LOCAL))
922 throw new Error("Joining thread on local object not allowed in context:\n"+currlb.getExplanation());
923 if(thistype.equals(CONFLICT))
924 throw new Error("Using type that can be either local or global in context:\n"+currlb.getExplanation());
925 if(runmethodset==null&&thistype.equals(GLOBAL)&&!isatomic && !isjoin)
926 throw new Error("Using global object outside of transaction in context:\n"+currlb.getExplanation());
927 if (runmethodset==null&&isnative&&thistype.equals(GLOBAL) && !isjoin && !isObjectgetType && !isObjecthashCode)
928 throw new Error("Potential call to native method "+md+" on global objects:\n"+currlb.getExplanation());
929 lb.setGlobalThis(thistype);
932 if (!discovered.containsKey(lb)) {
934 lb.setGlobalReturn(LOCAL);
936 lb.setGlobalReturn(EITHER);
937 lb.setParent(currlb);
939 discovered.put(lb, lb);
940 if (!classtolb.containsKey(lb.getMethod().getClassDesc()))
941 classtolb.put(lb.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
942 classtolb.get(lb.getMethod().getClassDesc()).add(lb);
943 if (!methodtolb.containsKey(lb.getMethod()))
944 methodtolb.put(lb.getMethod(), new HashSet<LocalityBinding>());
945 methodtolb.get(lb.getMethod()).add(lb);
947 lb=discovered.get(lb);
948 Integer returnval=lb.getGlobalReturn();
949 currreturnval=merge(returnval, currreturnval);
950 if (!dependence.containsKey(lb))
951 dependence.put(lb, new HashSet<LocalityBinding>());
952 dependence.get(lb).add(currlb);
954 if (!calldep.containsKey(currlb))
955 calldep.put(currlb, new HashSet<LocalityBinding>());
956 calldep.get(currlb).add(lb);
958 if (fc.getReturnTemp()!=null) {
959 currtable.put(fc.getReturnTemp(), currreturnval);
963 void processFieldNode(LocalityBinding lb, FlatFieldNode ffn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
964 Integer type=currtable.get(ffn.getSrc());
965 TempDescriptor dst=ffn.getDst();
966 if (type.equals(LOCAL)) {
967 if (ffn.getField().isGlobal())
968 currtable.put(dst,GLOBAL);
970 currtable.put(dst,LOCAL);
971 } else if (type.equals(GLOBAL)) {
973 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
974 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
975 currtable.put(dst, LOCAL); // primitives are local
977 currtable.put(dst, GLOBAL);
978 } else if (type.equals(EITHER)) {
979 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
980 currtable.put(dst, LOCAL); // primitives are local
981 else if (ffn.getField().isGlobal())
982 currtable.put(dst, GLOBAL);
984 currtable.put(dst, EITHER);
985 } else if (type.equals(CONFLICT)) {
986 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
990 //need to handle primitives
991 void processSetFieldNode(LocalityBinding lb, FlatSetFieldNode fsfn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
992 Integer srctype=currtable.get(fsfn.getSrc());
993 Integer dsttype=currtable.get(fsfn.getDst());
995 if (dsttype.equals(LOCAL)) {
996 if (fsfn.getField().isGlobal()) {
997 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
998 throw new Error("Writing possible local reference to global field in context: \n"+lb.getExplanation());
1000 if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
1001 throw new Error("Writing possible global reference to local object in context: \n"+lb.getExplanation());
1003 } else if (dsttype.equals(GLOBAL)) {
1005 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
1006 //okay to store primitives in global object
1007 if (srctype.equals(LOCAL) && fsfn.getField().getType().isPrimitive() && !fsfn.getField().getType().isArray())
1009 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
1010 throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation()+" for FlatFieldNode "+fsfn);
1011 } else if (dsttype.equals(EITHER)) {
1012 if (srctype.equals(CONFLICT))
1013 throw new Error("Using reference that could be local or global in context:\n"+lb.getExplanation());
1014 } else if (dsttype.equals(CONFLICT)) {
1015 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
1019 void processNew(LocalityBinding lb, FlatNew fn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
1020 if (fn.isGlobal()&&!transaction) {
1021 throw new Error("Allocating global object outside of transaction in context:"+lb.getExplanation());
1024 currtable.put(fn.getDst(), GLOBAL);
1026 currtable.put(fn.getDst(), LOCAL);
1029 void processOpNode(FlatOpNode fon, Hashtable<TempDescriptor, Integer> currtable) {
1030 /* Just propagate value */
1031 Integer srcvalue=currtable.get(fon.getLeft());
1033 if (srcvalue==null) {
1034 if (!fon.getLeft().getType().isPtr()) {
1037 throw new Error(fon.getLeft()+" is undefined!");
1039 currtable.put(fon.getDest(), srcvalue);
1042 void processCastNode(FlatCastNode fcn, Hashtable<TempDescriptor, Integer> currtable) {
1043 currtable.put(fcn.getDst(), currtable.get(fcn.getSrc()));
1046 void processLiteralNode(FlatLiteralNode fln, Hashtable<TempDescriptor, Integer> currtable) {
1048 if (fln.getValue()==null)
1049 currtable.put(fln.getDst(), EITHER);
1051 currtable.put(fln.getDst(), LOCAL);
1054 void processOffsetNode(FlatOffsetNode fln, Hashtable<TempDescriptor, Integer> currtable) {
1055 currtable.put(fln.getDst(), LOCAL);
1058 void processReturnNode(LocalityBinding lb, FlatReturnNode frn, Hashtable<TempDescriptor, Integer> currtable) {
1059 if(frn.getReturnTemp()!=null) {
1060 Integer returntype=currtable.get(frn.getReturnTemp());
1061 lb.setGlobalReturn(merge(returntype, lb.getGlobalReturn()));
1065 void processSetElementNode(LocalityBinding lb, FlatSetElementNode fsen, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
1066 Integer srctype=currtable.get(fsen.getSrc());
1067 Integer dsttype=currtable.get(fsen.getDst());
1069 if (dsttype.equals(LOCAL)) {
1070 if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
1071 throw new Error("Writing possible global reference to local object in context:\n"+lb.getExplanation()+fsen);
1072 } else if (dsttype.equals(GLOBAL)) {
1073 if (srctype.equals(LOCAL) && fsen.getDst().getType().dereference().isPrimitive() && !fsen.getDst().getType().dereference().isArray())
1075 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
1076 throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation());
1078 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
1079 } else if (dsttype.equals(EITHER)) {
1080 if (srctype.equals(CONFLICT))
1081 throw new Error("Using reference that could be local or global in context:\n"+lb.getExplanation());
1082 } else if (dsttype.equals(CONFLICT)) {
1083 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
1087 void processElementNode(LocalityBinding lb, FlatElementNode fen, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
1088 Integer type=currtable.get(fen.getSrc());
1089 TempDescriptor dst=fen.getDst();
1090 if (type.equals(LOCAL)) {
1091 currtable.put(dst,LOCAL);
1092 } else if (type.equals(GLOBAL)) {
1094 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
1095 if(fen.getSrc().getType().dereference().isPrimitive()&&
1096 !fen.getSrc().getType().dereference().isArray())
1097 currtable.put(dst, LOCAL);
1099 currtable.put(dst, GLOBAL);
1100 } else if (type.equals(EITHER)) {
1101 if(fen.getSrc().getType().dereference().isPrimitive()&&
1102 !fen.getSrc().getType().dereference().isArray())
1103 currtable.put(dst, LOCAL);
1105 currtable.put(dst, EITHER);
1106 } else if (type.equals(CONFLICT)) {
1107 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
1111 void processAtomicEnterNode(FlatAtomicEnterNode fen, Hashtable<FlatNode, Integer> atomictable) {
1112 int atomic=atomictable.get(fen).intValue();
1113 atomictable.put(fen, new Integer(atomic+1));
1116 void processAtomicExitNode(FlatAtomicExitNode fen, Hashtable<FlatNode, Integer> atomictable) {
1117 int atomic=atomictable.get(fen).intValue();
1118 atomictable.put(fen, new Integer(atomic-1));
1121 Hashtable<FlatNode, Set<TempDescriptor>> computeLiveTemps(FlatMethod fm) {
1122 Hashtable<FlatNode, Set<TempDescriptor>> nodetotemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
1124 Set<FlatNode> toprocess=fm.getNodeSet();
1126 while(!toprocess.isEmpty()) {
1127 FlatNode fn=toprocess.iterator().next();
1128 toprocess.remove(fn);
1130 List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
1131 List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
1133 HashSet<TempDescriptor> tempset=new HashSet<TempDescriptor>();
1134 for(int i=0; i<fn.numNext(); i++) {
1135 FlatNode fnnext=fn.getNext(i);
1136 if (nodetotemps.containsKey(fnnext))
1137 tempset.addAll(nodetotemps.get(fnnext));
1139 tempset.removeAll(writes);
1140 tempset.addAll(reads);
1141 if (!nodetotemps.containsKey(fn)||
1142 !nodetotemps.get(fn).equals(tempset)) {
1143 nodetotemps.put(fn, tempset);
1144 for(int i=0; i<fn.numPrev(); i++)
1145 toprocess.add(fn.getPrev(i));
1151 private void computeTempstoSave() {
1152 for(Iterator<LocalityBinding> lbit=getLocalityBindings().iterator(); lbit.hasNext();) {
1153 LocalityBinding lb=lbit.next();
1154 computeTempstoSave(lb);
1158 /* Need to checkpoint all temps that could be read from along any
1159 * path that are either:
1160 1) Written to by any assignment inside the transaction
1161 2) Read from a global temp.
1163 Generate tempstosave map from
1164 localitybinding->flatatomicenternode->Set<TempDescriptors>
1167 private void computeTempstoSave(LocalityBinding lb) {
1170 Hashtable<FlatNode, Integer> atomictab=getAtomic(lb);
1171 Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=getNodeTempInfo(lb);
1172 MethodDescriptor md=lb.getMethod();
1173 FlatMethod fm=state.getMethodFlat(md);
1174 Hashtable<FlatNode, Set<TempDescriptor>> nodetotemps=computeLiveTemps(fm);
1175 Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> nodetosavetemps=new Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>();
1176 tempstosave.put(lb, nodetosavetemps);
1177 Hashtable<FlatNode, FlatAtomicEnterNode> nodemap=new Hashtable<FlatNode, FlatAtomicEnterNode>();
1178 HashSet<FlatNode> toprocess=new HashSet<FlatNode>();
1179 HashSet<FlatNode> discovered=new HashSet<FlatNode>();
1182 while(!toprocess.isEmpty()) {
1183 FlatNode fn=toprocess.iterator().next();
1184 toprocess.remove(fn);
1185 boolean isatomic=atomictab.get(fn).intValue()>0;
1187 atomictab.get(fn.getPrev(0)).intValue()==0) {
1188 assert(fn.getPrev(0).kind()==FKind.FlatAtomicEnterNode);
1189 nodemap.put(fn, (FlatAtomicEnterNode)fn);
1190 nodetosavetemps.put((FlatAtomicEnterNode)fn, new HashSet<TempDescriptor>());
1191 } else if (isatomic) {
1192 FlatAtomicEnterNode atomicnode=nodemap.get(fn);
1193 Set<TempDescriptor> livetemps=nodetotemps.get(fn);
1194 List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
1195 List<TempDescriptor> writes=Arrays.asList(fn.readsTemps());
1197 for(Iterator<TempDescriptor> tempit=livetemps.iterator(); tempit.hasNext();) {
1198 TempDescriptor tmp=tempit.next();
1199 if (writes.contains(tmp)) {
1200 nodetosavetemps.get(atomicnode).add(tmp);
1201 } else if (state.DSM) {
1202 if (reads.contains(tmp)&&temptab.get(fn).get(tmp)==GLOBAL) {
1203 nodetosavetemps.get(atomicnode).add(tmp);
1205 } else if (state.SINGLETM) {
1206 if (reads.contains(tmp)&&tmp.getType().isPtr()&&temptab.get(fn).get(tmp)==NORMAL) {
1207 nodetosavetemps.get(atomicnode).add(tmp);
1212 for(int i=0; i<fn.numNext(); i++) {
1213 FlatNode fnnext=fn.getNext(i);
1214 if (!discovered.contains(fnnext)) {
1215 discovered.add(fnnext);
1216 toprocess.add(fnnext);
1218 nodemap.put(fnnext, nodemap.get(fn));