1 package Analysis.Locality;
2 import Analysis.Liveness;
3 import Analysis.ReachingDefs;
4 import Analysis.Loops.DomTree;
6 import IR.MethodDescriptor;
7 import IR.TypeDescriptor;
8 import IR.FieldDescriptor;
10 import Analysis.Loops.GlobalFieldType;
11 import java.util.HashSet;
12 import java.util.Hashtable;
14 import java.util.List;
15 import java.util.Arrays;
16 import java.util.Stack;
17 import java.util.Iterator;
19 public class DelayComputation {
21 LocalityAnalysis locality;
22 TypeAnalysis typeanalysis;
24 DiscoverConflicts dcopts;
25 Hashtable<LocalityBinding, HashSet<FlatNode>> notreadymap;
26 Hashtable<LocalityBinding, HashSet<FlatNode>> cannotdelaymap;
27 Hashtable<LocalityBinding, HashSet<FlatNode>> derefmap;
28 Hashtable<LocalityBinding, HashSet<FlatNode>> othermap;
30 public DelayComputation(LocalityAnalysis locality, State state, TypeAnalysis typeanalysis, GlobalFieldType gft) {
31 this.locality=locality;
33 this.typeanalysis=typeanalysis;
35 this.notreadymap=new Hashtable<LocalityBinding, HashSet<FlatNode>>();
36 this.cannotdelaymap=new Hashtable<LocalityBinding, HashSet<FlatNode>>();
37 if (state.STMARRAY&&!state.DUALVIEW)
38 this.derefmap=new Hashtable<LocalityBinding, HashSet<FlatNode>>();
39 this.othermap=new Hashtable<LocalityBinding, HashSet<FlatNode>>();
42 public DiscoverConflicts getConflicts() {
46 public Hashtable<LocalityBinding, HashSet<FlatNode>> getCannotDelayMap() {
47 return cannotdelaymap;
51 public HashSet<FlatNode> getDeref(LocalityBinding lb) {
52 return derefmap.get(lb);
55 public void doAnalysis() {
56 //first dcopts...use to figure out what we need to lock
57 dcopts=new DiscoverConflicts(locality, state, typeanalysis, null);
60 //compute cannotdelaymap
61 Set<LocalityBinding> localityset=locality.getLocalityBindings();
62 for(Iterator<LocalityBinding> lbit=localityset.iterator();lbit.hasNext();) {
63 analyzeMethod(lbit.next());
66 //ignore things that aren't in the map
67 dcopts=new DiscoverConflicts(locality, state, typeanalysis, cannotdelaymap, false, false, state.READSET?gft:null);
71 for(Iterator<LocalityBinding> lbit=localityset.iterator();lbit.hasNext();) {
72 LocalityBinding lb=lbit.next();
74 MethodDescriptor md=lb.getMethod();
75 FlatMethod fm=state.getMethodFlat(md);
79 if (lb.getHasAtomic()) {
80 HashSet<FlatNode> cannotdelay=cannotdelaymap.get(lb);
81 HashSet<FlatNode> notreadyset=computeNotReadySet(lb, cannotdelay);
82 HashSet<FlatNode> otherset=new HashSet<FlatNode>();
83 otherset.addAll(fm.getNodeSet());
84 otherset.removeAll(notreadyset);
85 otherset.removeAll(cannotdelay);
87 Hashtable<FlatNode, Integer> atomicmap=locality.getAtomic(lb);
88 for(Iterator<FlatNode> fnit=otherset.iterator();fnit.hasNext();) {
89 FlatNode fn=fnit.next();
90 if (atomicmap.get(fn).intValue()>0&&
91 fn.kind()!=FKind.FlatAtomicEnterNode&&
92 fn.kind()!=FKind.FlatGlobalConvNode) {
93 //remove non-atomic flatnodes
100 notreadymap.put(lb, notreadyset);
101 othermap.put(lb, otherset);
105 //(1) Cannot delay set -- stuff that must be done before commit
106 //(2) Not ready set -- stuff that must wait until commit
107 //(3) everything else -- stuff that should be done before commit
111 public HashSet<FlatNode> computeWriteSet(LocalityBinding lb) {
112 HashSet<FlatNode> writeset=new HashSet<FlatNode>();
113 Set<FlatNode> storeset=livecode(lb);
114 HashSet<FlatNode> delayedset=getNotReady(lb);
115 Hashtable<FlatNode, Hashtable<TempDescriptor, Set<TempFlatPair>>> fnmap=dcopts.getMap(lb);
116 for(Iterator<FlatNode> fnit=delayedset.iterator();fnit.hasNext();) {
117 FlatNode fn=fnit.next();
118 Hashtable<TempDescriptor, Set<TempFlatPair>> tempmap=fnmap.get(fn);
119 if (fn.kind()==FKind.FlatSetElementNode) {
120 FlatSetElementNode fsen=(FlatSetElementNode) fn;
121 Set<TempFlatPair> tfpset=tempmap.get(fsen.getDst());
123 for(Iterator<TempFlatPair> tfpit=tfpset.iterator();tfpit.hasNext();) {
124 TempFlatPair tfp=tfpit.next();
125 if (storeset.contains(tfp.f))
129 } else if (fn.kind()==FKind.FlatSetFieldNode) {
130 FlatSetFieldNode fsfn=(FlatSetFieldNode) fn;
131 Set<TempFlatPair> tfpset=tempmap.get(fsfn.getDst());
133 for(Iterator<TempFlatPair> tfpit=tfpset.iterator();tfpit.hasNext();) {
134 TempFlatPair tfp=tfpit.next();
135 if (storeset.contains(tfp.f))
145 public HashSet<FlatNode> getNotReady(LocalityBinding lb) {
146 return notreadymap.get(lb);
149 public HashSet<FlatNode> getCannotDelay(LocalityBinding lb) {
150 return cannotdelaymap.get(lb);
153 public HashSet<FlatNode> getOther(LocalityBinding lb) {
154 return othermap.get(lb);
157 //This method computes which temps are live into the second part
158 public Set<TempDescriptor> alltemps(LocalityBinding lb, FlatAtomicEnterNode faen, Set<FlatNode> recordset) {
159 MethodDescriptor md=lb.getMethod();
160 FlatMethod fm=state.getMethodFlat(md);
161 Set<FlatNode> atomicnodes=faen.getReachableSet(faen.getExits());
163 //Compute second part set of nodes
164 Set<FlatNode> secondpart=new HashSet<FlatNode>();
165 secondpart.addAll(getNotReady(lb));
166 secondpart.addAll(recordset);
168 //make it just this transaction
169 secondpart.retainAll(atomicnodes);
171 HashSet<TempDescriptor> tempset=new HashSet<TempDescriptor>();
173 for(Iterator<FlatNode> fnit=secondpart.iterator();fnit.hasNext();) {
174 FlatNode fn=fnit.next();
175 List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
176 tempset.addAll(writes);
177 if (!recordset.contains(fn)) {
178 List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
179 tempset.addAll(reads);
186 //This method computes which temps are live into the second part
187 public Set<TempDescriptor> liveinto(LocalityBinding lb, FlatAtomicEnterNode faen, Set<FlatNode> recordset) {
188 MethodDescriptor md=lb.getMethod();
189 FlatMethod fm=state.getMethodFlat(md);
190 Set<FlatNode> atomicnodes=faen.getReachableSet(faen.getExits());
192 //Compute second part set of nodes
193 Set<FlatNode> secondpart=new HashSet<FlatNode>();
194 secondpart.addAll(getNotReady(lb));
195 secondpart.addAll(recordset);
197 //make it just this transaction
198 secondpart.retainAll(atomicnodes);
200 Set<TempDescriptor> liveinto=new HashSet<TempDescriptor>();
202 Hashtable<FlatNode, Hashtable<TempDescriptor, Set<FlatNode>>> reachingdefs=ReachingDefs.computeReachingDefs(fm, Liveness.computeLiveTemps(fm), true);
204 for(Iterator<FlatNode> fnit=secondpart.iterator();fnit.hasNext();) {
205 FlatNode fn=fnit.next();
206 if (recordset.contains(fn))
208 TempDescriptor readset[]=fn.readsTemps();
209 for(int i=0;i<readset.length;i++) {
210 TempDescriptor rtmp=readset[i];
211 Set<FlatNode> fnset=reachingdefs.get(fn).get(rtmp);
212 for(Iterator<FlatNode> fnit2=fnset.iterator();fnit2.hasNext();) {
213 FlatNode fn2=fnit2.next();
214 if (secondpart.contains(fn2))
216 //otherwise we mark this as live in
225 //This method computes which temps are live out of the second part
226 public Set<TempDescriptor> liveoutvirtualread(LocalityBinding lb, FlatAtomicEnterNode faen) {
227 MethodDescriptor md=lb.getMethod();
228 FlatMethod fm=state.getMethodFlat(md);
229 Set<FlatNode> exits=faen.getExits();
230 Hashtable<FlatNode, Set<TempDescriptor>> livemap=Liveness.computeLiveTemps(fm);
231 Hashtable<FlatNode, Hashtable<TempDescriptor, Set<FlatNode>>> reachingdefs=ReachingDefs.computeReachingDefs(fm, Liveness.computeLiveTemps(fm), true);
233 Set<FlatNode> atomicnodes=faen.getReachableSet(faen.getExits());
235 Set<FlatNode> secondpart=new HashSet<FlatNode>(getNotReady(lb));
236 secondpart.retainAll(atomicnodes);
238 Set<TempDescriptor> liveset=new HashSet<TempDescriptor>();
239 //Have list of all live temps
241 for(Iterator<FlatNode> fnit=exits.iterator();fnit.hasNext();) {
242 FlatNode fn=fnit.next();
243 Set<TempDescriptor> tempset=livemap.get(fn);
244 Hashtable<TempDescriptor, Set<FlatNode>> reachmap=reachingdefs.get(fn);
245 //Look for reaching defs for all live variables that are in the secondpart
247 for(Iterator<TempDescriptor> tmpit=tempset.iterator();tmpit.hasNext();) {
248 TempDescriptor tmp=tmpit.next();
249 Set<FlatNode> fnset=reachmap.get(tmp);
250 boolean outsidenode=false;
251 boolean insidenode=false;
253 for(Iterator<FlatNode> fnit2=fnset.iterator();fnit2.hasNext();) {
254 FlatNode fn2=fnit2.next();
255 if (secondpart.contains(fn2)) {
257 } else if (!atomicnodes.contains(fn2)) {
260 if (outsidenode&&insidenode) {
270 //This method computes which temps are live out of the second part
271 public Set<TempDescriptor> liveout(LocalityBinding lb, FlatAtomicEnterNode faen) {
272 MethodDescriptor md=lb.getMethod();
273 FlatMethod fm=state.getMethodFlat(md);
274 Set<FlatNode> exits=faen.getExits();
275 Hashtable<FlatNode, Set<TempDescriptor>> livemap=Liveness.computeLiveTemps(fm);
276 Hashtable<FlatNode, Hashtable<TempDescriptor, Set<FlatNode>>> reachingdefs=ReachingDefs.computeReachingDefs(fm, livemap, true);
278 Set<FlatNode> atomicnodes=faen.getReachableSet(faen.getExits());
280 Set<FlatNode> secondpart=new HashSet<FlatNode>(getNotReady(lb));
281 secondpart.retainAll(atomicnodes);
283 Set<TempDescriptor> liveset=new HashSet<TempDescriptor>();
284 //Have list of all live temps
286 for(Iterator<FlatNode> fnit=exits.iterator();fnit.hasNext();) {
287 FlatNode fn=fnit.next();
288 Set<TempDescriptor> tempset=livemap.get(fn);
289 Hashtable<TempDescriptor, Set<FlatNode>> reachmap=reachingdefs.get(fn);
290 //Look for reaching defs for all live variables that are in the secondpart
292 for(Iterator<TempDescriptor> tmpit=tempset.iterator();tmpit.hasNext();) {
293 TempDescriptor tmp=tmpit.next();
294 Set<FlatNode> fnset=reachmap.get(tmp);
296 System.out.println("null temp set for"+fn+" tmp="+tmp);
297 System.out.println(fm.printMethod());
299 for(Iterator<FlatNode> fnit2=fnset.iterator();fnit2.hasNext();) {
300 FlatNode fn2=fnit2.next();
301 if (secondpart.contains(fn2)) {
311 //This method computes which nodes from the first part of the
312 //transaction must store their output for the second part
313 //Note that many nodes don't need to...
315 public Set<FlatNode> livecode(LocalityBinding lb) {
316 if (!othermap.containsKey(lb))
318 MethodDescriptor md=lb.getMethod();
319 FlatMethod fm=state.getMethodFlat(md);
321 HashSet<FlatNode> delayedset=notreadymap.get(lb);
322 HashSet<FlatNode> derefset=null;
323 if (state.STMARRAY&&!state.DUALVIEW)
324 derefset=derefmap.get(lb);
325 HashSet<FlatNode> otherset=othermap.get(lb);
326 HashSet<FlatNode> cannotdelayset=cannotdelaymap.get(lb);
327 Hashtable<FlatNode,Set<TempDescriptor>> livemap=Liveness.computeLiveTemps(fm);
328 Hashtable<FlatNode, Hashtable<TempDescriptor, Set<FlatNode>>> reachingdefsmap=ReachingDefs.computeReachingDefs(fm, livemap, true);
329 HashSet<FlatNode> unionset=new HashSet<FlatNode>(delayedset);
330 Hashtable<FlatNode, Hashtable<TempDescriptor, HashSet<FlatNode>>> map=new Hashtable<FlatNode, Hashtable<TempDescriptor, HashSet<FlatNode>>>();
331 HashSet<FlatNode> livenodes=new HashSet<FlatNode>();
332 Hashtable<FlatCondBranch, Set<FlatNode>> branchmap=revGetBranchSet(lb);
334 //Here we check for temps that are live out on the transaction...
335 //If both parts can contribute to the temp, then we need to do
336 //reads to make sure that liveout set has the right values
338 for(Iterator<FlatNode> fnit=fm.getNodeSet().iterator();fnit.hasNext();) {
339 FlatNode fn=fnit.next();
340 if (fn.kind()==FKind.FlatAtomicExitNode) {
341 Set<TempDescriptor> livetemps=livemap.get(fn);
342 Hashtable<TempDescriptor, Set<FlatNode>> tempmap=reachingdefsmap.get(fn);
344 //Iterate over the temps that are live into this node
345 for(Iterator<TempDescriptor> tmpit=livetemps.iterator();tmpit.hasNext();) {
346 TempDescriptor tmp=tmpit.next();
347 Set<FlatNode> fnset=tempmap.get(tmp);
348 boolean inpart1=false;
349 boolean inpart2=false;
351 //iterate over the reaching definitions for the temp
352 for(Iterator<FlatNode> fnit2=fnset.iterator();fnit2.hasNext();) {
353 FlatNode fn2=fnit2.next();
354 if (delayedset.contains(fn2)) {
358 } else if (otherset.contains(fn2)||cannotdelayset.contains(fn2)) {
364 if (inpart1&&inpart2) {
365 for(Iterator<FlatNode> fnit2=fnset.iterator();fnit2.hasNext();) {
366 FlatNode fn2=fnit2.next();
367 if ((otherset.contains(fn2)||cannotdelayset.contains(fn2))&&
368 locality.getAtomic(lb).get(fn2).intValue()>0) {
378 HashSet<FlatNode> toanalyze=new HashSet<FlatNode>();
381 while(!toanalyze.isEmpty()) {
382 FlatNode fn=toanalyze.iterator().next();
383 toanalyze.remove(fn);
384 Hashtable<TempDescriptor, HashSet<FlatNode>> tmptofn=new Hashtable<TempDescriptor, HashSet<FlatNode>>();
386 //Don't process non-atomic nodes
387 if (locality.getAtomic(lb).get(fn).intValue()==0) {
388 if (!map.containsKey(fn)) {
389 map.put(fn, new Hashtable<TempDescriptor, HashSet<FlatNode>>());
391 for(int i=0;i<fn.numNext();i++)
392 toanalyze.add(fn.getNext(i));
397 //Do merge on incoming edges
398 for(int i=0;i<fn.numPrev();i++) {
399 FlatNode fnprev=fn.getPrev(i);
400 Hashtable<TempDescriptor, HashSet<FlatNode>> prevmap=map.get(fnprev);
402 for(Iterator<TempDescriptor> tmpit=prevmap.keySet().iterator();tmpit.hasNext();) {
403 TempDescriptor tmp=tmpit.next();
404 if (!tmptofn.containsKey(tmp))
405 tmptofn.put(tmp, new HashSet<FlatNode>());
406 tmptofn.get(tmp).addAll(prevmap.get(tmp));
410 if (delayedset.contains(fn)) {
411 if(state.STMARRAY&&!state.DUALVIEW&&derefset.contains(fn)) {
412 //FlatElementNodes don't read anything...
413 if (fn.kind()==FKind.FlatSetElementNode) {
414 //check only the source read tmp
415 TempDescriptor tmp=((FlatSetElementNode)fn).getSrc();
416 if (tmptofn.containsKey(tmp)) {
417 livenodes.addAll(tmptofn.get(tmp)); //Add live nodes
418 unionset.addAll(tmptofn.get(tmp));
422 //If the node is in the second set, check our readset
423 TempDescriptor readset[]=fn.readsTemps();
424 for(int i=0;i<readset.length;i++) {
425 TempDescriptor tmp=readset[i];
426 if (tmptofn.containsKey(tmp)) {
427 livenodes.addAll(tmptofn.get(tmp)); //Add live nodes
428 unionset.addAll(tmptofn.get(tmp));
433 TempDescriptor writeset[]=fn.writesTemps();
434 for(int i=0;i<writeset.length;i++) {
435 TempDescriptor tmp=writeset[i];
439 //If the node is in the first set, search over what we write
440 //We write -- our reads are done
441 TempDescriptor writeset[]=fn.writesTemps();
442 for(int i=0;i<writeset.length;i++) {
443 TempDescriptor tmp=writeset[i];
444 HashSet<FlatNode> set=new HashSet<FlatNode>();
445 tmptofn.put(tmp,set);
448 if (fn.numNext()>1) {
449 Set<FlatNode> branchset=branchmap.get((FlatCondBranch)fn);
450 for(Iterator<FlatNode> brit=branchset.iterator();brit.hasNext();) {
451 FlatNode brfn=brit.next();
452 if (unionset.contains(brfn)) {
453 //This branch is important--need to remember how it goes
460 if (!map.containsKey(fn)||!map.get(fn).equals(tmptofn)) {
461 map.put(fn, tmptofn);
463 for(int i=0;i<fn.numNext();i++)
464 toanalyze.add(fn.getNext(i));
470 public static Set<FlatNode> getNext(FlatNode fn, int i, Set<FlatNode> delayset, LocalityBinding lb, LocalityAnalysis locality, boolean contpastnode) {
471 Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
472 FlatNode fnnext=fn.getNext(i);
473 HashSet<FlatNode> reachable=new HashSet<FlatNode>();
475 if (delayset.contains(fnnext)||atomictable.get(fnnext).intValue()==0) {
476 reachable.add(fnnext);
479 Stack<FlatNode> nodes=new Stack<FlatNode>();
480 HashSet<FlatNode> visited=new HashSet<FlatNode>();
485 while(!nodes.isEmpty()) {
486 FlatNode fn2=nodes.pop();
487 if (visited.contains(fn2))
490 for (int j=0;j<fn2.numNext();j++) {
491 FlatNode fn2next=fn2.getNext(j);
492 if (delayset.contains(fn2next)||atomictable.get(fn2next).intValue()==0) {
493 reachable.add(fn2next);
501 //Computes cannotdelayset---flatnodes that must be evaluated in the
502 //speculative component.
504 public void analyzeMethod(LocalityBinding lb) {
505 MethodDescriptor md=lb.getMethod();
506 FlatMethod fm=state.getMethodFlat(md);
507 HashSet<FlatNode> cannotdelay=new HashSet<FlatNode>();
508 HashSet<FlatNode> derefset=new HashSet<FlatNode>();
509 Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
511 //We are in a transaction already...
512 //skip past this method or something
516 Hashtable<FlatNode, Set<TempDescriptor>> oldtempmap=dcopts.computeOldTemps(lb);
518 HashSet<FlatNode> toanalyze=new HashSet<FlatNode>();
519 toanalyze.addAll(fm.getNodeSet());
521 //Build the hashtables
522 Hashtable<FlatNode, HashSet<TempDescriptor>> nodelaytemps=new Hashtable<FlatNode, HashSet<TempDescriptor>>();
523 Hashtable<FlatNode, HashSet<FieldDescriptor>> nodelayfieldswr=new Hashtable<FlatNode, HashSet<FieldDescriptor>>();
524 Hashtable<FlatNode, HashSet<TypeDescriptor>> nodelayarrayswr=new Hashtable<FlatNode, HashSet<TypeDescriptor>>();
525 Hashtable<FlatNode, HashSet<FieldDescriptor>> nodelayfieldsrd=new Hashtable<FlatNode, HashSet<FieldDescriptor>>();
526 Hashtable<FlatNode, HashSet<TypeDescriptor>> nodelayarraysrd=new Hashtable<FlatNode, HashSet<TypeDescriptor>>();
528 Hashtable<FlatCondBranch, Set<FlatNode>> revbranchmap=revGetBranchSet(lb);
529 Hashtable<FlatNode, Set<FlatCondBranch>> branchmap=getBranchSet(lb);
530 //Effect of adding something to nodelay set is to move it up past everything in delay set
531 //Have to make sure we can do this commute
533 while(!toanalyze.isEmpty()) {
534 FlatNode fn=toanalyze.iterator().next();
535 toanalyze.remove(fn);
537 boolean isatomic=atomictable.get(fn).intValue()>0;
541 boolean isnodelay=false;
543 /* Compute incoming nodelay sets */
544 HashSet<TempDescriptor> nodelaytempset=new HashSet<TempDescriptor>();
545 HashSet<FieldDescriptor> nodelayfieldwrset=new HashSet<FieldDescriptor>();
546 HashSet<TypeDescriptor> nodelayarraywrset=new HashSet<TypeDescriptor>();
547 HashSet<FieldDescriptor> nodelayfieldrdset=new HashSet<FieldDescriptor>();
548 HashSet<TypeDescriptor> nodelayarrayrdset=new HashSet<TypeDescriptor>();
549 for(int i=0;i<fn.numNext();i++) {
550 if (nodelaytemps.containsKey(fn.getNext(i)))
551 nodelaytempset.addAll(nodelaytemps.get(fn.getNext(i)));
552 //do field/array write sets
553 if (nodelayfieldswr.containsKey(fn.getNext(i)))
554 nodelayfieldwrset.addAll(nodelayfieldswr.get(fn.getNext(i)));
555 if (nodelayarrayswr.containsKey(fn.getNext(i)))
556 nodelayarraywrset.addAll(nodelayarrayswr.get(fn.getNext(i)));
558 if (nodelayfieldsrd.containsKey(fn.getNext(i)))
559 nodelayfieldrdset.addAll(nodelayfieldsrd.get(fn.getNext(i)));
560 if (nodelayarraysrd.containsKey(fn.getNext(i)))
561 nodelayarrayrdset.addAll(nodelayarraysrd.get(fn.getNext(i)));
564 /* Check our temp write set */
566 TempDescriptor writeset[]=fn.writesTemps();
567 for(int i=0;i<writeset.length;i++) {
568 TempDescriptor tmp=writeset[i];
569 if (nodelaytempset.contains(tmp)) {
570 //We are writing to a nodelay temp
571 //Therefore we are nodelay
573 //Kill temp we wrote to
574 nodelaytempset.remove(tmp);
578 //See if flatnode is definitely no delay
579 if (fn.kind()==FKind.FlatCall) {
580 FlatCall fcall=(FlatCall)fn;
581 MethodDescriptor mdcall=fcall.getMethod();
582 if (!mdcall.getClassDesc().getSymbol().equals("System")||
583 (!mdcall.getSymbol().equals("println")&&!mdcall.getSymbol().equals("printString")))
587 //Delay branches if possible
588 if (fn.kind()==FKind.FlatCondBranch) {
589 Set<FlatNode> branchset=revbranchmap.get((FlatCondBranch)fn);
590 for(Iterator<FlatNode> brit=branchset.iterator();brit.hasNext();) {
591 FlatNode branchnode=brit.next();
592 if (cannotdelay.contains(branchnode)||(state.STMARRAY&&!state.DUALVIEW&&derefset.contains(branchnode))) {
599 //Check for field conflicts
600 if (fn.kind()==FKind.FlatSetFieldNode) {
601 FieldDescriptor fd=((FlatSetFieldNode)fn).getField();
603 if (nodelayfieldwrset.contains(fd))
606 if (nodelayfieldrdset.contains(fd))
610 if (fn.kind()==FKind.FlatFieldNode) {
611 FieldDescriptor fd=((FlatFieldNode)fn).getField();
613 if (nodelayfieldwrset.contains(fd))
616 //Check for array conflicts
617 if (fn.kind()==FKind.FlatSetElementNode) {
618 TypeDescriptor td=((FlatSetElementNode)fn).getDst().getType();
619 //check for write conflicts
620 if (nodelayarraywrset.contains(td))
622 //check for read conflicts
623 if (nodelayarrayrdset.contains(td))
626 if (fn.kind()==FKind.FlatElementNode) {
627 TypeDescriptor td=((FlatElementNode)fn).getSrc().getType();
628 //check for write conflicts
629 if (nodelayarraywrset.contains(td))
633 //If we are no delay, then the temps we read are no delay
635 /* Add our read set */
636 TempDescriptor readset[]=fn.readsTemps();
637 for(int i=0;i<readset.length;i++) {
638 TempDescriptor tmp=readset[i];
639 nodelaytempset.add(tmp);
643 if (branchmap.containsKey(fn)) {
644 Set<FlatCondBranch> fcbset=branchmap.get(fn);
645 for(Iterator<FlatCondBranch> fcbit=fcbset.iterator();fcbit.hasNext();) {
646 FlatCondBranch fcb=fcbit.next();
647 //enqueue flatcondbranch node for reanalysis
648 if (!cannotdelay.contains(fcb)) {
649 cannotdelay.add(fcb);
654 /* Do we write to fields */
655 if (fn.kind()==FKind.FlatSetFieldNode) {
656 nodelayfieldwrset.add(((FlatSetFieldNode)fn).getField());
658 /* Do we read from fields */
659 if (fn.kind()==FKind.FlatFieldNode) {
660 nodelayfieldrdset.add(((FlatFieldNode)fn).getField());
662 /* Do we write to arrays */
663 if (fn.kind()==FKind.FlatSetElementNode) {
664 //have to do expansion
665 nodelayarraywrset.addAll(typeanalysis.expand(((FlatSetElementNode)fn).getDst().getType()));
667 /* Do we read from arrays */
668 if (fn.kind()==FKind.FlatElementNode) {
669 //have to do expansion
670 nodelayarrayrdset.addAll(typeanalysis.expand(((FlatElementNode)fn).getSrc().getType()));
673 //See if flatnode is definitely no delay
674 if (fn.kind()==FKind.FlatCall) {
675 //Have to deal with fields/arrays
676 FlatCall fcall=(FlatCall)fn;
677 MethodDescriptor mdcall=fcall.getMethod();
678 nodelayfieldwrset.addAll(gft.getFieldsAll(mdcall));
679 nodelayarraywrset.addAll(typeanalysis.expandSet(gft.getArraysAll(mdcall)));
680 //Have to deal with field/array reads
681 nodelayfieldrdset.addAll(gft.getFieldsRdAll(mdcall));
682 nodelayarrayrdset.addAll(typeanalysis.expandSet(gft.getArraysRdAll(mdcall)));
685 //Need to know which objects to lock on
686 Set<TempDescriptor> oldtemps=oldtempmap.get(fn);
688 case FKind.FlatSetFieldNode: {
689 FlatSetFieldNode fsfn=(FlatSetFieldNode)fn;
690 if (oldtemps.contains(fsfn.getDst())) {
691 nodelaytempset.add(fsfn.getDst());
695 case FKind.FlatSetElementNode: {
696 FlatSetElementNode fsen=(FlatSetElementNode)fn;
697 if (oldtemps.contains(fsen.getDst())) {
698 nodelaytempset.add(fsen.getDst());
699 //Word Array support requires index
700 if (state.STMARRAY&&!state.DUALVIEW) {
701 nodelaytempset.add(fsen.getIndex());
707 case FKind.FlatFieldNode: {
708 FlatFieldNode ffn=(FlatFieldNode)fn;
709 if (oldtemps.contains(ffn.getSrc())&&
710 dcopts.getFields().contains(ffn.getField())) {
711 nodelaytempset.add(ffn.getSrc());
715 case FKind.FlatElementNode: {
716 FlatElementNode fen=(FlatElementNode)fn;
717 if (oldtemps.contains(fen.getSrc())&&
718 dcopts.getArrays().contains(fen.getSrc().getType())) {
719 nodelaytempset.add(fen.getSrc());
720 //Word Array support requires index
721 if (state.STMARRAY&&!state.DUALVIEW) {
722 nodelaytempset.add(fen.getIndex());
731 boolean changed=false;
732 //See if we need to propagate changes
733 if (!nodelaytemps.containsKey(fn)||
734 !nodelaytemps.get(fn).equals(nodelaytempset)) {
735 nodelaytemps.put(fn, nodelaytempset);
739 //See if we need to propagate changes
740 if (!nodelayfieldswr.containsKey(fn)||
741 !nodelayfieldswr.get(fn).equals(nodelayfieldwrset)) {
742 nodelayfieldswr.put(fn, nodelayfieldwrset);
746 //See if we need to propagate changes
747 if (!nodelayfieldsrd.containsKey(fn)||
748 !nodelayfieldsrd.get(fn).equals(nodelayfieldrdset)) {
749 nodelayfieldsrd.put(fn, nodelayfieldrdset);
753 //See if we need to propagate changes
754 if (!nodelayarrayswr.containsKey(fn)||
755 !nodelayarrayswr.get(fn).equals(nodelayarraywrset)) {
756 nodelayarrayswr.put(fn, nodelayarraywrset);
760 //See if we need to propagate changes
761 if (!nodelayarraysrd.containsKey(fn)||
762 !nodelayarraysrd.get(fn).equals(nodelayarrayrdset)) {
763 nodelayarraysrd.put(fn, nodelayarrayrdset);
768 for(int i=0;i<fn.numPrev();i++)
769 toanalyze.add(fn.getPrev(i));
772 if (lb.getHasAtomic()) {
773 if (state.STMARRAY&&!state.DUALVIEW)
774 derefmap.put(lb, derefset);
775 cannotdelaymap.put(lb, cannotdelay);
780 //1) we acquire locks too early to object we don't need to yet
781 //2) we don't realize that certain operations have side effects
783 public HashSet<FlatNode> computeNotReadySet(LocalityBinding lb, HashSet<FlatNode> cannotdelay) {
784 //You are in not ready set if:
785 //I. You read a not ready temp
786 //II. You access a field or element and
787 //(A). You are not in the cannot delay set
788 //(B). You read a field/element in the transactional set
789 //(C). The source didn't have a transactional read on it
791 MethodDescriptor md=lb.getMethod();
792 FlatMethod fm=state.getMethodFlat(md);
793 Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
794 HashSet<FlatNode> notreadynodes=new HashSet<FlatNode>();
795 HashSet<FlatNode> toanalyze=new HashSet<FlatNode>();
796 toanalyze.addAll(fm.getNodeSet());
797 Hashtable<FlatNode, HashSet<TempDescriptor>> notreadymap=new Hashtable<FlatNode, HashSet<TempDescriptor>>();
799 Hashtable<FlatCondBranch, Set<FlatNode>> revbranchmap=revGetBranchSet(lb);
800 Hashtable<FlatNode, Set<FlatCondBranch>> branchmap=getBranchSet(lb);
802 while(!toanalyze.isEmpty()) {
803 FlatNode fn=toanalyze.iterator().next();
804 toanalyze.remove(fn);
805 boolean isatomic=atomictable.get(fn).intValue()>0;
810 //Compute initial notready set
811 HashSet<TempDescriptor> notreadyset=new HashSet<TempDescriptor>();
812 for(int i=0;i<fn.numPrev();i++) {
813 if (notreadymap.containsKey(fn.getPrev(i)))
814 notreadyset.addAll(notreadymap.get(fn.getPrev(i)));
818 boolean notready=false;
820 //Test our read set first
821 TempDescriptor readset[]=fn.readsTemps();
822 for(int i=0;i<readset.length;i++) {
823 TempDescriptor tmp=readset[i];
824 if (notreadyset.contains(tmp)) {
830 if (!notready&&!cannotdelay.contains(fn)) {
832 case FKind.FlatFieldNode: {
833 FlatFieldNode ffn=(FlatFieldNode)fn;
834 if (!dcopts.getFields().contains(ffn.getField())) {
837 TempDescriptor tmp=ffn.getSrc();
838 Set<TempFlatPair> tfpset=dcopts.getMap(lb).get(fn).get(tmp);
840 for(Iterator<TempFlatPair> tfpit=tfpset.iterator();tfpit.hasNext();) {
841 TempFlatPair tfp=tfpit.next();
842 if (!dcopts.getNeedSrcTrans(lb, tfp.f)) {
843 //if a source didn't need a translation and we are
844 //accessing it, it did...so therefore we are note
853 case FKind.FlatSetFieldNode: {
854 FlatSetFieldNode fsfn=(FlatSetFieldNode)fn;
855 TempDescriptor tmp=fsfn.getDst();
856 Hashtable<TempDescriptor, Set<TempFlatPair>> tmpmap=dcopts.getMap(lb).get(fn);
857 Set<TempFlatPair> tfpset=tmpmap!=null?tmpmap.get(tmp):null;
860 for(Iterator<TempFlatPair> tfpit=tfpset.iterator();tfpit.hasNext();) {
861 TempFlatPair tfp=tfpit.next();
862 if (!dcopts.getNeedSrcTrans(lb, tfp.f)) {
863 //if a source didn't need a translation and we are
864 //accessing it, it did...so therefore we are note
873 case FKind.FlatElementNode: {
874 FlatElementNode fen=(FlatElementNode)fn;
875 if (!dcopts.getArrays().contains(fen.getSrc().getType())) {
878 TempDescriptor tmp=fen.getSrc();
879 Set<TempFlatPair> tfpset=dcopts.getMap(lb).get(fn).get(tmp);
881 for(Iterator<TempFlatPair> tfpit=tfpset.iterator();tfpit.hasNext();) {
882 TempFlatPair tfp=tfpit.next();
883 if (!dcopts.getNeedSrcTrans(lb, tfp.f)) {
884 //if a source didn't need a translation and we are
885 //accessing it, it did...so therefore we are note
894 case FKind.FlatSetElementNode: {
895 FlatSetElementNode fsen=(FlatSetElementNode)fn;
896 TempDescriptor tmp=fsen.getDst();
897 Set<TempFlatPair> tfpset=dcopts.getMap(lb).get(fn).get(tmp);
899 for(Iterator<TempFlatPair> tfpit=tfpset.iterator();tfpit.hasNext();) {
900 TempFlatPair tfp=tfpit.next();
901 if (!dcopts.getNeedSrcTrans(lb, tfp.f)) {
902 //if a source didn't need a translation and we are
903 //accessing it, it did...so therefore we are note
916 //See if we depend on a conditional branch that is not ready
917 Set<FlatCondBranch> branchset=branchmap.get(fn);
919 for(Iterator<FlatCondBranch> branchit=branchset.iterator();branchit.hasNext();) {
920 FlatCondBranch fcb=branchit.next();
921 if (notreadynodes.contains(fcb)) {
922 //if we depend on a branch that isn't ready, we aren't ready
930 //Fix up things based on our status
932 if (fn.kind()==FKind.FlatCondBranch&&!notreadynodes.contains(fn)) {
933 //enqueue everything in our dependence set
934 Set<FlatNode> branchdepset=revbranchmap.get((FlatCondBranch)fn);
935 toanalyze.addAll(branchdepset);
939 notreadynodes.add(fn);
942 TempDescriptor writeset[]=fn.writesTemps();
943 for(int i=0;i<writeset.length;i++) {
944 TempDescriptor tmp=writeset[i];
945 notreadyset.add(tmp);
949 TempDescriptor writeset[]=fn.writesTemps();
950 for(int i=0;i<writeset.length;i++) {
951 TempDescriptor tmp=writeset[i];
952 notreadyset.remove(tmp);
956 //See if we need to propagate changes
957 if (!notreadymap.containsKey(fn)||
958 !notreadymap.get(fn).equals(notreadyset)) {
959 notreadymap.put(fn, notreadyset);
960 for(int i=0;i<fn.numNext();i++)
961 toanalyze.add(fn.getNext(i));
964 return notreadynodes;
965 } //end of computeNotReadySet
967 public Hashtable<FlatCondBranch, Set<FlatNode>> revGetBranchSet(LocalityBinding lb) {
968 MethodDescriptor md=lb.getMethod();
969 FlatMethod fm=state.getMethodFlat(md);
970 Hashtable<FlatCondBranch, Set<FlatNode>> condmap=new Hashtable<FlatCondBranch, Set<FlatNode>>();
971 DomTree postdt=new DomTree(fm, true);
972 for(Iterator<FlatNode> fnit=fm.getNodeSet().iterator();fnit.hasNext();) {
973 FlatNode fn=fnit.next();
974 if (fn.kind()!=FKind.FlatCondBranch)
976 FlatCondBranch fcb=(FlatCondBranch)fn;
977 //only worry about fcb inside of transactions
978 if (locality.getAtomic(lb).get(fcb).intValue()==0)
980 FlatNode postdom=postdt.idom(fcb);
982 //Reverse the mapping
983 Set<FlatNode> fnset=computeBranchSet(lb, fcb, postdom);
984 condmap.put(fcb, fnset);
989 public Hashtable<FlatNode, Set<FlatCondBranch>> getBranchSet(LocalityBinding lb) {
990 MethodDescriptor md=lb.getMethod();
991 FlatMethod fm=state.getMethodFlat(md);
992 Hashtable<FlatNode, Set<FlatCondBranch>> condmap=new Hashtable<FlatNode, Set<FlatCondBranch>>();
993 DomTree postdt=new DomTree(fm, true);
994 for(Iterator<FlatNode> fnit=fm.getNodeSet().iterator();fnit.hasNext();) {
995 FlatNode fn=fnit.next();
996 if (fn.kind()!=FKind.FlatCondBranch)
998 FlatCondBranch fcb=(FlatCondBranch)fn;
999 //only worry about fcb inside of transactions
1000 if (locality.getAtomic(lb).get(fcb).intValue()==0)
1002 FlatNode postdom=postdt.idom(fcb);
1004 //Reverse the mapping
1005 Set<FlatNode> fnset=computeBranchSet(lb, fcb, postdom);
1006 for(Iterator<FlatNode>fnit2=fnset.iterator();fnit2.hasNext();) {
1007 FlatNode fn2=fnit2.next();
1008 if (!condmap.containsKey(fn2))
1009 condmap.put(fn2,new HashSet<FlatCondBranch>());
1010 condmap.get(fn2).add(fcb);
1016 public Set<FlatNode> computeBranchSet(LocalityBinding lb, FlatNode first, FlatNode last) {
1017 HashSet<FlatNode> toanalyze=new HashSet<FlatNode>();
1018 HashSet<FlatNode> visited=new HashSet<FlatNode>();
1019 toanalyze.add(first);
1021 while(!toanalyze.isEmpty()) {
1022 FlatNode fn=toanalyze.iterator().next();
1023 toanalyze.remove(fn);
1025 //already examined or exit node
1026 if (visited.contains(fn)||fn==last)
1029 //out of transaction
1030 if (locality.getAtomic(lb).get(fn).intValue()==0)
1034 for(int i=0;i<fn.numNext();i++) {
1035 FlatNode fnext=fn.getNext(i);
1036 toanalyze.add(fnext);
1040 } //end of computeBranchSet