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, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>> temptab;
18 Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>> atomictab;
19 Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>> tempstosave;
20 Hashtable<ClassDescriptor, Set<LocalityBinding>> classtolb;
21 Hashtable<MethodDescriptor, Set<LocalityBinding>> methodtolb;
22 private LocalityBinding lbmain;
26 public static final Integer LOCAL=new Integer(0);
27 public static final Integer GLOBAL=new Integer(1);
28 public static final Integer EITHER=new Integer(2);
29 public static final Integer CONFLICT=new Integer(3);
31 public LocalityAnalysis(State state, CallGraph callgraph, TypeUtil typeutil) {
32 this.typeutil=typeutil;
34 this.discovered=new Hashtable<LocalityBinding,LocalityBinding>();
35 this.dependence=new Hashtable<LocalityBinding, Set<LocalityBinding>>();
36 this.temptab=new Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>>();
37 this.atomictab=new Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>>();
38 this.lbtovisit=new Stack();
39 this.callgraph=callgraph;
40 this.tempstosave=new Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>>();
41 this.classtolb=new Hashtable<ClassDescriptor, Set<LocalityBinding>>();
42 this.methodtolb=new Hashtable<MethodDescriptor, Set<LocalityBinding>>();
46 public LocalityBinding getMain() {
50 /** This method returns the set of LocalityBindings that a given
51 * flatcall could invoke */
53 public LocalityBinding getBinding(LocalityBinding currlb, FlatCall fc) {
54 boolean isatomic=getAtomic(currlb).get(fc).intValue()>0;
55 Hashtable<TempDescriptor, Integer> currtable=getNodePreTempInfo(currlb,fc);
56 MethodDescriptor md=fc.getMethod();
58 boolean isnative=md.getModifiers().isNative();
60 LocalityBinding lb=new LocalityBinding(md, isatomic);
62 for(int i=0;i<fc.numArgs();i++) {
63 TempDescriptor arg=fc.getArg(i);
64 lb.setGlobal(i,currtable.get(arg));
66 if (fc.getThis()!=null) {
67 Integer thistype=currtable.get(fc.getThis());
70 lb.setGlobalThis(thistype);
72 // lb.setGlobalThis(EITHER);//default value
73 if (discovered.containsKey(lb))
74 lb=discovered.get(lb);
75 else throw new Error();
80 /** This method returns a set of LocalityBindings for the parameter class. */
81 public Set<LocalityBinding> getClassBindings(ClassDescriptor cd) {
82 return classtolb.get(cd);
85 /** This method returns a set of LocalityBindings for the parameter method. */
87 public Set<LocalityBinding> getMethodBindings(MethodDescriptor md) {
88 return methodtolb.get(md);
91 /** This method returns a set of LocalityBindings. A
92 * LocalityBinding specifies a context a method can be invoked in.
93 * It specifies whether the method is in a transaction and whether
94 * its parameter objects are locals or globals. */
96 public Set<LocalityBinding> getLocalityBindings() {
97 return discovered.keySet();
100 /** This method returns a hashtable for a given LocalityBinding
101 * that tells the current local/global status of temps at the each
102 * node in the flat representation. */
104 public Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> getNodeTempInfo(LocalityBinding lb) {
105 return temptab.get(lb);
108 /** This method returns a hashtable for a given LocalityBinding
109 * that tells the current local/global status of temps at the
110 * beginning of each node in the flat representation. */
112 public Hashtable<TempDescriptor, Integer> getNodePreTempInfo(LocalityBinding lb, FlatNode fn) {
113 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
114 Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable=getNodeTempInfo(lb);
116 for(int i=0;i<fn.numPrev();i++) {
117 FlatNode prevnode=fn.getPrev(i);
118 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
119 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator();tempit.hasNext();) {
120 TempDescriptor temp=tempit.next();
121 Integer tmpint=prevtable.get(temp);
122 Integer oldint=currtable.containsKey(temp)?currtable.get(temp):EITHER;
123 Integer newint=merge(tmpint, oldint);
124 currtable.put(temp, newint);
130 /** This method returns an hashtable for a given LocalitBinding
131 * that tells whether a node in the flat represenation is in a
132 * transaction or not. Integer values greater than 0 indicate
133 * that the node is in a transaction and give the nesting depth.
134 * The outermost AtomicEnterNode will have a value of 1 and the
135 * outermost AtomicExitNode will have a value of 0. */
137 public Hashtable<FlatNode, Integer> getAtomic(LocalityBinding lb) {
138 return atomictab.get(lb);
141 /** This methods returns a hashtable for a given LocalityBinding
142 * that tells which temps needs to be saved for each
143 * AtomicEnterNode. */
145 public Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> getTemps(LocalityBinding lb) {
146 return tempstosave.get(lb);
149 public Set<TempDescriptor> getTempSet(LocalityBinding lb) {
150 HashSet<TempDescriptor> set=new HashSet<TempDescriptor>();
151 Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> table=getTemps(lb);
153 for(Iterator<FlatAtomicEnterNode> faenit=table.keySet().iterator();faenit.hasNext();) {
154 FlatAtomicEnterNode faen=faenit.next();
155 set.addAll(table.get(faen));
160 private void doAnalysis() {
161 computeLocalityBindings();
162 computeTempstoSave();
165 private void computeLocalityBindings() {
166 lbmain=new LocalityBinding(typeutil.getMain(), false);
167 lbmain.setGlobalReturn(EITHER);
168 lbmain.setGlobal(0, LOCAL);
169 lbtovisit.add(lbmain);
170 discovered.put(lbmain, lbmain);
171 if (!classtolb.containsKey(lbmain.getMethod().getClassDesc()))
172 classtolb.put(lbmain.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
173 classtolb.get(lbmain.getMethod().getClassDesc()).add(lbmain);
175 if (!methodtolb.containsKey(lbmain.getMethod()))
176 methodtolb.put(lbmain.getMethod(), new HashSet<LocalityBinding>());
177 methodtolb.get(lbmain.getMethod()).add(lbmain);
179 //Do this to force a virtual table number for the run method
180 LocalityBinding lbrun=new LocalityBinding(typeutil.getRun(), false);
181 lbrun.setGlobalReturn(EITHER);
182 lbrun.setGlobalThis(GLOBAL);
183 lbtovisit.add(lbrun);
184 discovered.put(lbrun, lbrun);
185 if (!classtolb.containsKey(lbrun.getMethod().getClassDesc()))
186 classtolb.put(lbrun.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
187 classtolb.get(lbrun.getMethod().getClassDesc()).add(lbrun);
189 if (!methodtolb.containsKey(lbrun.getMethod()))
190 methodtolb.put(lbrun.getMethod(), new HashSet<LocalityBinding>());
191 methodtolb.get(lbrun.getMethod()).add(lbrun);
193 while(!lbtovisit.empty()) {
194 LocalityBinding lb=(LocalityBinding) lbtovisit.pop();
195 Integer returnglobal=lb.getGlobalReturn();
196 MethodDescriptor md=lb.getMethod();
197 Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>> temptable=new Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>();
198 Hashtable<FlatNode, Integer> atomictable=new Hashtable<FlatNode, Integer>();
200 computeCallsFlags(md, lb, temptable, atomictable);
202 System.out.println("Error in "+md+" context "+lb);
206 atomictab.put(lb, atomictable);
207 temptab.put(lb, temptable);
209 if (md.getReturnType()!=null&&!returnglobal.equals(lb.getGlobalReturn())) {
210 //return type is more precise now
211 //rerun everything that call us
212 lbtovisit.addAll(dependence.get(lb));
217 public void computeCallsFlags(MethodDescriptor md, LocalityBinding lb, Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptable, Hashtable<FlatNode, Integer> atomictable) {
218 FlatMethod fm=state.getMethodFlat(md);
219 HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
220 tovisit.add(fm.getNext(0));
222 // Build table for initial node
223 Hashtable<TempDescriptor,Integer> table=new Hashtable<TempDescriptor,Integer>();
224 temptable.put(fm, table);
225 atomictable.put(fm, lb.isAtomic()?1:0);
226 int offset=md.isStatic()?0:1;
227 if (!md.isStatic()) {
228 table.put(fm.getParameter(0), lb.getGlobalThis());
230 for(int i=offset;i<fm.numParameters();i++) {
231 TempDescriptor temp=fm.getParameter(i);
232 Integer b=lb.isGlobal(i-offset);
237 while(!tovisit.isEmpty()) {
238 FlatNode fn=tovisit.iterator().next();
240 Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
242 for(int i=0;i<fn.numPrev();i++) {
243 FlatNode prevnode=fn.getPrev(i);
244 if (atomictable.containsKey(prevnode)) {
245 atomicstate=atomictable.get(prevnode).intValue();
247 if (!temptable.containsKey(prevnode))
249 Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
250 for(Iterator<TempDescriptor> tempit=prevtable.keySet().iterator();tempit.hasNext();) {
251 TempDescriptor temp=tempit.next();
252 Integer tmpint=prevtable.get(temp);
253 Integer oldint=currtable.containsKey(temp)?currtable.get(temp):EITHER;
254 Integer newint=merge(tmpint, oldint);
255 currtable.put(temp, newint);
258 atomictable.put(fn, atomicstate);
261 case FKind.FlatAtomicEnterNode:
262 processAtomicEnterNode((FlatAtomicEnterNode)fn, atomictable);
266 case FKind.FlatAtomicExitNode:
267 processAtomicExitNode((FlatAtomicExitNode)fn, atomictable);
270 processCallNode(lb, (FlatCall)fn, currtable, isAtomic(atomictable, fn));
272 case FKind.FlatFieldNode:
273 processFieldNode(lb, (FlatFieldNode)fn, isAtomic(atomictable, fn), currtable);
275 case FKind.FlatSetFieldNode:
276 processSetFieldNode(lb, (FlatSetFieldNode)fn, isAtomic(atomictable,fn), currtable);
279 processNew(lb, (FlatNew)fn, isAtomic(atomictable, fn), currtable);
281 case FKind.FlatOpNode:
282 processOpNode((FlatOpNode)fn, currtable);
284 case FKind.FlatCastNode:
285 processCastNode((FlatCastNode)fn, currtable);
287 case FKind.FlatLiteralNode:
288 processLiteralNode((FlatLiteralNode)fn, currtable);
290 case FKind.FlatReturnNode:
291 processReturnNode(lb, (FlatReturnNode)fn, currtable);
293 case FKind.FlatSetElementNode:
294 processSetElementNode(lb, (FlatSetElementNode)fn, currtable, isAtomic(atomictable, fn));
296 case FKind.FlatElementNode:
297 processElementNode(lb, (FlatElementNode)fn, currtable, isAtomic(atomictable, fn));
299 case FKind.FlatCondBranch:
300 case FKind.FlatBackEdge:
302 case FKind.FlatPrefetchNode:
303 //No action needed for these
305 case FKind.FlatFlagActionNode:
306 case FKind.FlatCheckNode:
307 case FKind.FlatTagDeclaration:
308 throw new Error("Incompatible with tasks!");
309 case FKind.FlatMethod:
313 Hashtable<TempDescriptor,Integer> oldtable=temptable.get(fn);
314 if (oldtable==null||!oldtable.equals(currtable)) {
315 // Update table for this node
316 temptable.put(fn, currtable);
317 for(int i=0;i<fn.numNext();i++) {
318 tovisit.add(fn.getNext(i));
324 private static boolean isAtomic(Hashtable<FlatNode, Integer> atomictable, FlatNode fn) {
325 return atomictable.get(fn).intValue()>0;
328 private static Integer merge(Integer a, Integer b) {
329 if (a==null||a.equals(EITHER))
331 if (b==null||b.equals(EITHER))
338 void processCallNode(LocalityBinding currlb, FlatCall fc, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
339 MethodDescriptor nodemd=fc.getMethod();
341 Set runmethodset=null;
343 if (nodemd.isStatic()||nodemd.getReturnType()==null) {
344 methodset=new HashSet();
345 methodset.add(nodemd);
347 methodset=callgraph.getMethods(nodemd, fc.getThis().getType());
348 // Build start -> run link
349 if (nodemd.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&
350 nodemd.getSymbol().equals("start")&&!nodemd.getModifiers().isStatic()&&
351 nodemd.numParameters()==1&&nodemd.getParamType(0).isInt()) {
352 assert(nodemd.getModifiers().isNative());
354 MethodDescriptor runmd=null;
355 for(Iterator methodit=nodemd.getClassDesc().getMethodTable().getSet("run").iterator();methodit.hasNext();) {
356 MethodDescriptor md=(MethodDescriptor) methodit.next();
357 if (md.numParameters()!=0||md.getModifiers().isStatic())
363 runmethodset=callgraph.getMethods(runmd,fc.getThis().getType());
364 methodset.addAll(runmethodset);
365 } else throw new Error("Can't find run method");
369 Integer currreturnval=EITHER; //Start off with the either value
370 for(Iterator methodit=methodset.iterator();methodit.hasNext();) {
371 MethodDescriptor md=(MethodDescriptor) methodit.next();
373 boolean isnative=md.getModifiers().isNative();
374 boolean isjoin = md.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&!nodemd.getModifiers().isStatic()&&nodemd.numParameters()==0&&md.getSymbol().equals("join");
376 LocalityBinding lb=new LocalityBinding(md, isatomic);
377 if (isnative&&isatomic) {
378 System.out.println("Don't call native methods in atomic blocks!"+currlb.getMethod());
380 if (runmethodset==null||!runmethodset.contains(md)) {
381 //Skip this part if it is a run method
382 for(int i=0;i<fc.numArgs();i++) {
383 TempDescriptor arg=fc.getArg(i);
384 if(isnative&&(currtable.get(arg).equals(GLOBAL)||
385 currtable.get(arg).equals(CONFLICT)))
386 throw new Error("Potential call to native method "+md+" with global parameter:\n"+currlb.getExplanation());
387 lb.setGlobal(i,currtable.get(arg));
391 if (fc.getThis()!=null) {
392 Integer thistype=currtable.get(fc.getThis());
396 if(runmethodset!=null&&runmethodset.contains(md)&&thistype.equals(LOCAL))
397 throw new Error("Starting thread on local object not allowed in context:\n"+currlb.getExplanation());
398 if(isjoin&&thistype.equals(LOCAL))
399 throw new Error("Joining thread on local object not allowed in context:\n"+currlb.getExplanation());
400 if(thistype.equals(CONFLICT))
401 throw new Error("Using type that can be either local or global in context:\n"+currlb.getExplanation());
402 if(runmethodset==null&&thistype.equals(GLOBAL)&&!isatomic && !isjoin)
403 throw new Error("Using global object outside of transaction in context:\n"+currlb.getExplanation());
404 if (runmethodset==null&&isnative&&thistype.equals(GLOBAL) && !isjoin)
405 throw new Error("Potential call to native method "+md+" on global objects:\n"+currlb.getExplanation());
406 lb.setGlobalThis(thistype);
409 if (!discovered.containsKey(lb)) {
411 lb.setGlobalReturn(LOCAL);
413 lb.setGlobalReturn(EITHER);
414 lb.setParent(currlb);
416 discovered.put(lb, lb);
417 if (!classtolb.containsKey(lb.getMethod().getClassDesc()))
418 classtolb.put(lb.getMethod().getClassDesc(), new HashSet<LocalityBinding>());
419 classtolb.get(lb.getMethod().getClassDesc()).add(lb);
420 if (!methodtolb.containsKey(lb.getMethod()))
421 methodtolb.put(lb.getMethod(), new HashSet<LocalityBinding>());
422 methodtolb.get(lb.getMethod()).add(lb);
424 lb=discovered.get(lb);
425 Integer returnval=lb.getGlobalReturn();
426 currreturnval=merge(returnval, currreturnval);
427 if (!dependence.containsKey(lb))
428 dependence.put(lb, new HashSet<LocalityBinding>());
429 dependence.get(lb).add(currlb);
431 if (fc.getReturnTemp()!=null) {
432 currtable.put(fc.getReturnTemp(), currreturnval);
436 void processFieldNode(LocalityBinding lb, FlatFieldNode ffn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
437 Integer type=currtable.get(ffn.getSrc());
438 TempDescriptor dst=ffn.getDst();
439 if (type.equals(LOCAL)) {
440 if (ffn.getField().isGlobal())
441 currtable.put(dst,GLOBAL);
443 currtable.put(dst,LOCAL);
444 } else if (type.equals(GLOBAL)) {
446 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
447 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
448 currtable.put(dst, LOCAL); // primitives are local
450 currtable.put(dst, GLOBAL);
451 } else if (type.equals(EITHER)) {
452 if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
453 currtable.put(dst, LOCAL); // primitives are local
454 else if (ffn.getField().isGlobal())
455 currtable.put(dst, GLOBAL);
457 currtable.put(dst, EITHER);
458 } else if (type.equals(CONFLICT)) {
459 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
463 //need to handle primitives
464 void processSetFieldNode(LocalityBinding lb, FlatSetFieldNode fsfn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
465 Integer srctype=currtable.get(fsfn.getSrc());
466 Integer dsttype=currtable.get(fsfn.getDst());
468 if (dsttype.equals(LOCAL)) {
469 if (fsfn.getField().isGlobal()) {
470 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
471 throw new Error("Writing possible local reference to global field in context: \n"+lb.getExplanation());
473 if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
474 throw new Error("Writing possible global reference to local object in context: \n"+lb.getExplanation());
476 } else if (dsttype.equals(GLOBAL)) {
478 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
479 //okay to store primitives in global object
480 if (srctype.equals(LOCAL) && fsfn.getField().getType().isPrimitive() && ! fsfn.getField().getType().isArray())
482 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
483 throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation()+" for FlatFieldNode "+fsfn);
484 } else if (dsttype.equals(EITHER)) {
485 if (srctype.equals(CONFLICT))
486 throw new Error("Using reference that could be local or global in context:\n"+lb.getExplanation());
487 } else if (dsttype.equals(CONFLICT)) {
488 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
492 void processNew(LocalityBinding lb, FlatNew fn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
493 if (fn.isGlobal()&&!transaction) {
494 throw new Error("Allocating global object outside of transaction in context:"+lb.getExplanation());
497 currtable.put(fn.getDst(), GLOBAL);
499 currtable.put(fn.getDst(), LOCAL);
502 void processOpNode(FlatOpNode fon, Hashtable<TempDescriptor, Integer> currtable) {
503 /* Just propagate value */
504 Integer srcvalue=currtable.get(fon.getLeft());
506 if (srcvalue==null) {
507 if (!fon.getLeft().getType().isPtr()) {
510 throw new Error(fon.getLeft()+" is undefined!");
512 currtable.put(fon.getDest(), srcvalue);
515 void processCastNode(FlatCastNode fcn, Hashtable<TempDescriptor, Integer> currtable) {
516 currtable.put(fcn.getDst(), currtable.get(fcn.getSrc()));
519 void processLiteralNode(FlatLiteralNode fln, Hashtable<TempDescriptor, Integer> currtable) {
521 if (fln.getValue()==null)
522 currtable.put(fln.getDst(), EITHER);
524 currtable.put(fln.getDst(), LOCAL);
527 void processReturnNode(LocalityBinding lb, FlatReturnNode frn, Hashtable<TempDescriptor, Integer> currtable) {
528 if(frn.getReturnTemp()!=null) {
529 Integer returntype=currtable.get(frn.getReturnTemp());
530 lb.setGlobalReturn(merge(returntype, lb.getGlobalReturn()));
534 void processSetElementNode(LocalityBinding lb, FlatSetElementNode fsen, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
535 Integer srctype=currtable.get(fsen.getSrc());
536 Integer dsttype=currtable.get(fsen.getDst());
538 if (dsttype.equals(LOCAL)) {
539 if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
540 throw new Error("Writing possible global reference to local object in context:\n"+lb.getExplanation()+fsen);
541 } else if (dsttype.equals(GLOBAL)) {
542 if (srctype.equals(LOCAL) && fsen.getDst().getType().dereference().isPrimitive() && ! fsen.getDst().getType().dereference().isArray())
544 if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
545 throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation());
547 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
548 } else if (dsttype.equals(EITHER)) {
549 if (srctype.equals(CONFLICT))
550 throw new Error("Using reference that could be local or global in context:\n"+lb.getExplanation());
551 } else if (dsttype.equals(CONFLICT)) {
552 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
556 void processElementNode(LocalityBinding lb, FlatElementNode fen, Hashtable<TempDescriptor, Integer> currtable, boolean isatomic) {
557 Integer type=currtable.get(fen.getSrc());
558 TempDescriptor dst=fen.getDst();
559 if (type.equals(LOCAL)) {
560 currtable.put(dst,LOCAL);
561 } else if (type.equals(GLOBAL)) {
563 throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
564 if(fen.getSrc().getType().dereference().isPrimitive()&&
565 !fen.getSrc().getType().dereference().isArray())
566 currtable.put(dst, LOCAL);
568 currtable.put(dst, GLOBAL);
569 } else if (type.equals(EITHER)) {
570 if(fen.getSrc().getType().dereference().isPrimitive()&&
571 !fen.getSrc().getType().dereference().isArray())
572 currtable.put(dst, LOCAL);
574 currtable.put(dst, EITHER);
575 } else if (type.equals(CONFLICT)) {
576 throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
580 void processAtomicEnterNode(FlatAtomicEnterNode fen, Hashtable<FlatNode, Integer> atomictable) {
581 int atomic=atomictable.get(fen).intValue();
582 atomictable.put(fen, new Integer(atomic+1));
585 void processAtomicExitNode(FlatAtomicExitNode fen, Hashtable<FlatNode, Integer> atomictable) {
586 int atomic=atomictable.get(fen).intValue();
587 atomictable.put(fen, new Integer(atomic-1));
590 private Hashtable<FlatNode, Set<TempDescriptor>> computeLiveTemps(FlatMethod fm) {
591 Hashtable<FlatNode, Set<TempDescriptor>> nodetotemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
593 Set<FlatNode> toprocess=fm.getNodeSet();
595 while(!toprocess.isEmpty()) {
596 FlatNode fn=toprocess.iterator().next();
597 toprocess.remove(fn);
599 List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
600 List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
602 HashSet<TempDescriptor> tempset=new HashSet<TempDescriptor>();
603 for(int i=0;i<fn.numNext();i++) {
604 FlatNode fnnext=fn.getNext(i);
605 if (nodetotemps.containsKey(fnnext))
606 tempset.addAll(nodetotemps.get(fnnext));
608 tempset.removeAll(writes);
609 tempset.addAll(reads);
610 if (!nodetotemps.containsKey(fn)||
611 !nodetotemps.get(fn).equals(tempset)) {
612 nodetotemps.put(fn, tempset);
613 for(int i=0;i<fn.numPrev();i++)
614 toprocess.add(fn.getPrev(i));
620 private void computeTempstoSave() {
621 for(Iterator<LocalityBinding> lbit=getLocalityBindings().iterator();lbit.hasNext();) {
622 LocalityBinding lb=lbit.next();
623 computeTempstoSave(lb);
627 /* Need to checkpoint all temps that could be read from along any
628 * path that are either:
629 1) Written to by any assignment inside the transaction
630 2) Read from a global temp.
632 Generate tempstosave map from
633 localitybinding->flatatomicenternode->Set<TempDescriptors>
636 private void computeTempstoSave(LocalityBinding lb) {
639 Hashtable<FlatNode, Integer> atomictab=getAtomic(lb);
640 Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=getNodeTempInfo(lb);
641 MethodDescriptor md=lb.getMethod();
642 FlatMethod fm=state.getMethodFlat(md);
643 Hashtable<FlatNode, Set<TempDescriptor>> nodetotemps=computeLiveTemps(fm);
644 Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> nodetosavetemps=new Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>();
645 tempstosave.put(lb, nodetosavetemps);
646 Hashtable<FlatNode, FlatAtomicEnterNode> nodemap=new Hashtable<FlatNode, FlatAtomicEnterNode>();
647 HashSet<FlatNode> toprocess=new HashSet<FlatNode>();
648 HashSet<FlatNode> discovered=new HashSet<FlatNode>();
651 while(!toprocess.isEmpty()) {
652 FlatNode fn=toprocess.iterator().next();
653 toprocess.remove(fn);
654 boolean isatomic=atomictab.get(fn).intValue()>0;
656 atomictab.get(fn.getPrev(0)).intValue()==0) {
657 assert(fn.getPrev(0).kind()==FKind.FlatAtomicEnterNode);
658 nodemap.put(fn, (FlatAtomicEnterNode)fn);
659 nodetosavetemps.put((FlatAtomicEnterNode)fn, new HashSet<TempDescriptor>());
660 } else if (isatomic) {
661 FlatAtomicEnterNode atomicnode=nodemap.get(fn);
662 Set<TempDescriptor> livetemps=nodetotemps.get(fn);
663 List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
664 List<TempDescriptor> writes=Arrays.asList(fn.readsTemps());
666 for(Iterator<TempDescriptor> tempit=livetemps.iterator();tempit.hasNext();) {
667 TempDescriptor tmp=tempit.next();
668 if (writes.contains(tmp)) {
669 nodetosavetemps.get(atomicnode).add(tmp);
670 } else if (reads.contains(tmp)&&temptab.get(fn).get(tmp)==GLOBAL) {
671 nodetosavetemps.get(atomicnode).add(tmp);
675 for(int i=0;i<fn.numNext();i++) {
676 FlatNode fnnext=fn.getNext(i);
677 if (!discovered.contains(fnnext)) {
678 discovered.add(fnnext);
679 toprocess.add(fnnext);
681 nodemap.put(fnnext, nodemap.get(fn));