fix: handle the case that TASK doesn't have any heap conflicts
[IRC.git] / Robust / src / IR / Flat / RuntimeConflictResolver.java
1 package IR.Flat;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.util.ArrayList;
6 import java.util.HashSet;
7 import java.util.Hashtable;
8 import java.util.Iterator;
9 import java.util.Set;
10 import java.util.Vector;
11 import Util.Pair;
12 import Analysis.Disjoint.*;
13 import Analysis.Pointer.*;
14 import Analysis.Pointer.AllocFactory.AllocNode;
15 import IR.State;
16 import IR.TypeDescriptor;
17 import Analysis.OoOJava.ConflictEdge;
18 import Analysis.OoOJava.ConflictGraph;
19 import Analysis.OoOJava.ConflictNode;
20 import Analysis.OoOJava.OoOJavaAnalysis;
21 import Util.CodePrinter;
22
23 /* An instance of this class manages all OoOJava coarse-grained runtime conflicts
24  * by generating C-code to either rule out the conflict at runtime or resolve one.
25  * 
26  * How to Use:
27  * 1) Instantiate singleton object (String input is to specify output dir)
28  * 2) Call void close() 
29  */
30 public class RuntimeConflictResolver {
31   private CodePrinter headerFile, cFile;
32   private static final String hashAndQueueCFileDir = "oooJava/";
33   
34   //This keeps track of taints we've traversed to prevent printing duplicate traverse functions
35   //The Integer keeps track of the weakly connected group it's in (used in enumerateHeapRoots)
36   //private Hashtable<Taint, Integer> doneTaints;
37   private Hashtable<Pair, Integer> idMap=new Hashtable<Pair,Integer>();
38   
39   //Keeps track of stallsites that we've generated code for. 
40   protected Hashtable <FlatNode, TempDescriptor> processedStallSites = new Hashtable <FlatNode, TempDescriptor>();
41  
42   public int currentID=1;
43   private int totalWeakGroups;
44   private OoOJavaAnalysis oooa;  
45   private State globalState;
46   
47   // initializing variables can be found in printHeader()
48   private static final String allocSite = "allocsite";
49   private static final String queryAndAddToVisitedHashtable = "hashRCRInsert";
50   private static final String enqueueInC = "enqueueRCRQueue";
51   private static final String dequeueFromQueueInC = "dequeueRCRQueue()";
52   private static final String clearQueue = "resetRCRQueue()";
53   // Make hashtable; hashRCRCreate(unsigned int size, double loadfactor)
54   private static final String mallocVisitedHashtable = "hashRCRCreate(128, 0.75)";
55   private static final String deallocVisitedHashTable = "hashRCRDelete()";
56   private static final String resetVisitedHashTable = "hashRCRreset()";
57
58   public RuntimeConflictResolver( String buildir, 
59                                   OoOJavaAnalysis oooa, 
60                                   State state) 
61   throws FileNotFoundException {
62     this.oooa         = oooa;
63     this.globalState  = state;
64
65     processedStallSites = new Hashtable <FlatNode, TempDescriptor>();
66     BuildStateMachines bsm  = oooa.getBuildStateMachines();
67     totalWeakGroups         = bsm.getTotalNumOfWeakGroups();
68     
69     setupOutputFiles(buildir);
70
71     for( Pair<FlatNode, TempDescriptor> p: bsm.getAllMachineNames() ) {
72       FlatNode                taskOrStallSite      =  p.getFirst();
73       TempDescriptor          var                  =  p.getSecond();
74       StateMachineForEffects  stateMachine         = bsm.getStateMachine( taskOrStallSite, var );
75
76       //prints the traversal code
77       printCMethod( taskOrStallSite, var, stateMachine); 
78     }
79     
80     //IMPORTANT must call .close() elsewhere to finish printing the C files.  
81   }
82   
83   /*
84    * This method generates a C method for every inset variable and rblock. 
85    * 
86    * The C method works by generating a large switch statement that will run the appropriate 
87    * checking code for each object based on the current state. The switch statement is 
88    * surrounded by a while statement which dequeues objects to be checked from a queue. An
89    * object is added to a queue only if it contains a conflict (in itself or in its referencees)
90    * and we came across it while checking through it's referencer. Because of this property, 
91    * conflicts will be signaled by the referencer; the only exception is the inset variable which can 
92    * signal a conflict within itself. 
93    */
94   
95   private void printCMethod( FlatNode               taskOrStallSite,
96                              TempDescriptor         var,
97                              StateMachineForEffects smfe) {
98
99     // collect info for code gen
100     FlatSESEEnterNode task          = null;
101     String            inVar         = var.getSafeSymbol();
102     SMFEState         initialState  = smfe.getInitialState();
103     boolean           isStallSite   = !(taskOrStallSite instanceof FlatSESEEnterNode);    
104     int               weakID        = smfe.getWeaklyConnectedGroupID(taskOrStallSite);
105     
106     String blockName;    
107     //No need generate code for empty traverser
108     if (smfe.isEmpty())
109       return;
110
111     if( isStallSite ) {
112       blockName = taskOrStallSite.toString();
113       processedStallSites.put(taskOrStallSite, var);
114     } else {
115       task = (FlatSESEEnterNode) taskOrStallSite;
116       
117       //if the task is the main task, there's no traverser
118       if(task.isMainSESE)
119         return;
120       
121       blockName = task.getPrettyIdentifier();
122     }
123
124
125     
126     String methodName = "void traverse___" + inVar + removeInvalidChars(blockName) + "___(void * InVar, ";
127     int    index      = -1;
128
129     if( isStallSite ) {
130       methodName += "SESEstall *record)";
131     } else {
132       methodName += task.getSESErecordName() +" *record)";
133       //TODO check that this HACK is correct (i.e. adding and then polling immediately afterwards)
134       task.addInVarForDynamicCoarseConflictResolution(var);
135       index = task.getInVarsForDynamicCoarseConflictResolution().indexOf( var );
136     }
137     
138     cFile.println( methodName + " {");
139     headerFile.println( methodName + ";" );
140
141     cFile.println(  "  int totalcount = RUNBIAS;");      
142     if( isStallSite ) {
143       cFile.println("  record->rcrRecords[0].count = RUNBIAS;");
144     } else {
145       cFile.println("  record->rcrRecords["+index+"].count = RUNBIAS;");
146     }
147
148     //clears queue and hashtable that keeps track of where we've been. 
149     cFile.println(clearQueue + ";");
150     cFile.println(resetVisitedHashTable + ";"); 
151     cFile.println("  RCRQueueEntry * queueEntry; //needed for dequeuing");
152     
153     cFile.println("  int traverserState = "+initialState.getID()+";");
154
155     //generic cast to ___Object___ to access ptr->allocsite field. 
156     cFile.println("  struct ___Object___ * ptr = (struct ___Object___ *) InVar;");
157     cFile.println("  if (InVar != NULL) {");
158     cFile.println("    " + queryAndAddToVisitedHashtable + "(ptr, "+initialState.getID()+");");
159     cFile.println("    do {");
160
161     if( !isStallSite ) {
162       cFile.println("      if(unlikely(record->common.doneExecuting)) {");
163       cFile.println("        record->common.rcrstatus=0;");
164       cFile.println("        return;");
165       cFile.println("      }");
166     }
167
168     
169     // Traverse the StateMachineForEffects (a graph)
170     // that serves as a plan for building the heap examiner code.
171     // SWITCH on the states in the state machine, THEN
172     //   SWITCH on the concrete object's allocation site THEN
173     //     consider conflicts, enqueue more work, inline more SWITCHES, etc.
174       
175     boolean needswitch=smfe.getStates().size()>1;
176
177     if (needswitch) {
178       cFile.println("  switch( traverserState ) {");
179     }
180     for(SMFEState state: smfe.getStates()) {
181
182       if(state.getRefCount() != 1 || initialState == state) {
183         if (needswitch) {
184           cFile.println("    case "+state.getID()+":");
185         } else {
186           cFile.println("  if(traverserState=="+state.getID()+") {");
187         }
188         
189         printAllocChecksInsideState(state, taskOrStallSite, var, "ptr", 0, weakID);
190         
191         cFile.println("      break;");
192       }
193     }
194     
195     if (needswitch) {
196       cFile.println("        default: break;");
197     }
198     cFile.println("      } // end switch on traverser state");
199     cFile.println("      queueEntry = " + dequeueFromQueueInC + ";");
200     cFile.println("      if(queueEntry == NULL) {");
201     cFile.println("        break;");
202     cFile.println("      }");
203     cFile.println("      ptr = queueEntry->object;");
204     cFile.println("      traverserState = queueEntry->traverserState;");
205     cFile.println("    } while(ptr != NULL);");
206     cFile.println("  } // end if inVar not null");
207    
208
209     if( isStallSite ) {
210       cFile.println("  if(atomic_sub_and_test(totalcount,&(record->rcrRecords[0].count))) {");
211       cFile.println("    psem_give_tag(record->common.parentsStallSem, record->tag);");
212       cFile.println("    BARRIER();");
213       cFile.println("  }");
214     } else {
215       cFile.println("  if(atomic_sub_and_test(totalcount,&(record->rcrRecords["+index+"].count))) {");
216       cFile.println("    int flag=LOCKXCHG32(&(record->rcrRecords["+index+"].flag),0);");
217       cFile.println("    if(flag) {");
218       //we have resolved a heap root...see if this was the last dependence
219       cFile.println("      if(atomic_sub_and_test(1, &(record->common.unresolvedDependencies))) workScheduleSubmit((void *)record);");
220       cFile.println("    }");
221       cFile.println("  }");
222     }
223
224     cFile.println("}");
225     cFile.flush();
226   }
227   
228   public void printAllocChecksInsideState(SMFEState state, FlatNode fn, TempDescriptor tmp, String prefix, int depth, int weakID) {
229     EffectsTable et = new EffectsTable(state);
230     boolean needswitch=et.getAllAllocs().size()>1;
231     if (needswitch) {
232       cFile.println("      switch(" + prefix+"->"+allocSite + ") {");
233     }
234
235     //we assume that all allocs given in the effects are starting locs. 
236     for(Alloc a: et.getAllAllocs()) {
237       if (needswitch) {
238         cFile.println("    case "+a.getUniqueAllocSiteID()+": {");
239       } else {
240         cFile.println("     if("+prefix+"->"+allocSite+"=="+a.getUniqueAllocSiteID()+") {");
241       }
242       addChecker(a, fn, tmp, state, et, prefix, depth, weakID);
243       if (needswitch) {
244         cFile.println("       }");
245         cFile.println("       break;");
246       }
247     }
248     if (needswitch) {
249       cFile.println("      default:");
250       cFile.println("        break;");
251     }
252     cFile.println("      }");
253   }
254   
255   public void addChecker(Alloc a, FlatNode fn, TempDescriptor tmp, SMFEState state, EffectsTable et, String prefix, int depth, int weakID) {
256     if (depth>30) {
257       System.out.println(fn+"  "+state+" "+state.toStringDOT());
258     }
259
260     insertEntriesIntoHashStructureNew(fn, tmp, et, a, prefix, depth, weakID);
261     
262     int pdepth = depth+1;
263     
264     if(a.getType().isArray()) {
265       String childPtr = "((struct ___Object___ **)(((char *) &(((struct ArrayObject *)"+ prefix+")->___length___))+sizeof(int)))[i]";
266       String currPtr = "arrayElement" + pdepth;
267       
268       boolean first=true;
269       
270       for(Effect e: et.getEffects(a)) {
271         if (!state.transitionsTo(e).isEmpty()) {
272           if (first) {
273             cFile.println("  int i;");
274             cFile.println("  struct ___Object___ * "+currPtr+";");
275             cFile.println("  for(i = 0; i<((struct ArrayObject *) " + prefix + " )->___length___; i++ ) {");
276             first=false;
277           }
278           printRefSwitch(fn, tmp, pdepth, childPtr, currPtr, state.transitionsTo(e), weakID);
279         }
280       }
281       if (!first)
282         cFile.println("}");
283     }  else {
284       //All other cases
285       String currPtr = "myPtr" + pdepth;
286       cFile.println("    struct ___Object___ * "+currPtr+";");
287       
288       for(Effect e: et.getEffects(a)) {
289         if (!state.transitionsTo(e).isEmpty()) {
290           String childPtr = "((struct "+a.getType().getSafeSymbol()+" *)"+prefix +")->" + e.getField().getSafeSymbol();
291           printRefSwitch(fn, tmp, pdepth, childPtr, currPtr, state.transitionsTo(e), weakID);
292         }
293       }
294     }
295   }
296
297   private void printRefSwitch(FlatNode fn, TempDescriptor tmp, int pdepth, String childPtr, String currPtr, Set<SMFEState> transitions, int weakID) {    
298     
299     for(SMFEState tr: transitions) {
300       if(tr.getRefCount() == 1) {       //in-lineable case
301         //Don't need to update state counter since we don't care really if it's inlined...
302         cFile.println("    "+currPtr+"= (struct ___Object___ * ) " + childPtr + ";");
303         cFile.println("    if (" + currPtr + " != NULL) { ");
304         
305         printAllocChecksInsideState(tr, fn, tmp, currPtr, pdepth+1, weakID);
306         
307         cFile.println("    }"); //break for internal switch and if
308       } else {                          //non-inlineable cases
309         cFile.println("    "+currPtr+"= (struct ___Object___ * ) " + childPtr + ";");   
310         cFile.println("    if("+queryAndAddToVisitedHashtable+"("+currPtr+","+tr.getID()+"))");
311         cFile.println("    " + enqueueInC +"("+ currPtr + ", "+tr.getID()+");");
312       } 
313     }
314   }
315   
316   
317   //FlatNode and TempDescriptor are what are used to make the taint
318   private void insertEntriesIntoHashStructureNew(FlatNode fn, TempDescriptor tmp, EffectsTable et, Alloc a, String prefix, int depth, int weakID) {
319     int index = 0;
320     boolean isRblock = (fn instanceof FlatSESEEnterNode);
321     if (isRblock) {
322       FlatSESEEnterNode fsese = (FlatSESEEnterNode) fn;
323       index = fsese.getInVarsForDynamicCoarseConflictResolution().indexOf(tmp);
324     }
325     
326     String strrcr = isRblock ? "&record->rcrRecords[" + index + "], " : "NULL, ";
327     String tasksrc =isRblock ? "(SESEcommon *) record, ":"(SESEcommon *)(((INTPTR)record)|1LL), ";
328
329     if(et.hasWriteConflict(a)) {
330       cFile.append("    int tmpkey" + depth + " = rcr_generateKey(" + prefix + ");\n");
331       if (et.conflictDereference(a))
332         cFile.append("    int tmpvar" + depth + " = rcr_WTWRITEBINCASE(allHashStructures[" + weakID + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
333       else
334         cFile.append("    int tmpvar" + depth + " = rcr_WRITEBINCASE(allHashStructures["+ weakID + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
335     } else  if(et.hasReadConflict(a)) { 
336       cFile.append("    int tmpkey" + depth + " = rcr_generateKey(" + prefix + ");\n");
337       if (et.conflictDereference(a))
338         cFile.append("    int tmpvar" + depth + " = rcr_WTREADBINCASE(allHashStructures[" + weakID + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
339       else
340         cFile.append("    int tmpvar" + depth + " = rcr_READBINCASE(allHashStructures["+ weakID + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
341     }
342
343     if (et.hasReadConflict(a) || et.hasWriteConflict(a)) {
344       cFile.append("if (!(tmpvar" + depth + "&READYMASK)) totalcount--;\n");
345     }
346   }
347
348   private void setupOutputFiles(String buildir) throws FileNotFoundException {
349     cFile = new CodePrinter(new File(buildir + "RuntimeConflictResolver" + ".c"));
350     headerFile = new CodePrinter(new File(buildir + "RuntimeConflictResolver" + ".h"));
351     
352     cFile.println("#include \"" + hashAndQueueCFileDir + "hashRCR.h\"\n#include \""
353         + hashAndQueueCFileDir + "Queue_RCR.h\"\n#include <stdlib.h>");
354     cFile.println("#include \"classdefs.h\"");
355     cFile.println("#include \"structdefs.h\"");
356     cFile.println("#include \"mlp_runtime.h\"");
357     cFile.println("#include \"RuntimeConflictResolver.h\"");
358     cFile.println("#include \"hashStructure.h\"");
359     
360     headerFile.println("#ifndef __3_RCR_H_");
361     headerFile.println("#define __3_RCR_H_");
362   }
363   
364   //The official way to generate the name for a traverser call
365   public String getTraverserInvocation(TempDescriptor invar, String varString, FlatNode fn) {
366     String flatname;
367     if(fn instanceof FlatSESEEnterNode) {  //is SESE block
368       flatname = ((FlatSESEEnterNode) fn).getPrettyIdentifier();
369     } else {  //is stallsite
370       flatname = fn.toString();
371     }
372     
373     return "traverse___" + invar.getSafeSymbol() + removeInvalidChars(flatname) + "___("+varString+");";
374   }
375   
376   public String removeInvalidChars(String in) {
377     StringBuilder s = new StringBuilder(in);
378     for(int i = 0; i < s.length(); i++) {
379       if(s.charAt(i) == ' ' || 
380          s.charAt(i) == '.' || 
381          s.charAt(i) == '=' ||
382          s.charAt(i) == '[' ||
383          s.charAt(i) == ']'    ) {
384
385         s.deleteCharAt(i);
386         i--;
387       }
388     }
389     return s.toString();
390   }
391
392   public int getTraverserID(TempDescriptor invar, FlatNode fn) {
393     Pair<TempDescriptor, FlatNode> t = new Pair<TempDescriptor, FlatNode>(invar, fn);
394     if (idMap.containsKey(t)) {
395       return idMap.get(t).intValue();
396     }
397     int value=currentID++;
398     idMap.put(t, new Integer(value));
399     return value;
400   }
401   
402   public void close() {
403     //Prints out the master traverser Invocation that'll call all other traversers
404     //based on traverserID
405     printMasterTraverserInvocation();    
406     createMasterHashTableArray();
407     
408     // Adds Extra supporting methods
409     cFile.println("void initializeStructsRCR() {\n  " + mallocVisitedHashtable + ";\n  " + clearQueue + ";\n}");
410     cFile.println("void destroyRCR() {\n  " + deallocVisitedHashTable + ";\n}");
411     
412     headerFile.println("void initializeStructsRCR();\nvoid destroyRCR();");
413     headerFile.println("#endif\n");
414
415     cFile.close();
416     headerFile.close();
417   }
418
419   private void printMasterTraverserInvocation() {
420     headerFile.println("int tasktraverse(SESEcommon * record);");
421     cFile.println("int tasktraverse(SESEcommon * record) {");
422     cFile.println("  if(!CAS(&record->rcrstatus,1,2)) {");
423
424     //release traverser reference...no traversal necessary
425     cFile.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
426     cFile.println("    RELEASE_REFERENCE_TO(record);");
427     cFile.println("#endif");
428
429     cFile.println("    return;");
430     cFile.println("  }");
431     cFile.println("  switch(record->classID) {");
432     
433     for(Iterator<FlatSESEEnterNode> seseit=oooa.getAllSESEs().iterator();seseit.hasNext();) {
434       FlatSESEEnterNode fsen=seseit.next();
435       cFile.println(    "    /* "+fsen.getPrettyIdentifier()+" */");
436       cFile.println(    "    case "+fsen.getIdentifier()+": {");
437       cFile.println(    "      "+fsen.getSESErecordName()+" * rec=("+fsen.getSESErecordName()+" *) record;");
438       Vector<TempDescriptor> invars=fsen.getInVarsForDynamicCoarseConflictResolution();
439       for(int i=0;i<invars.size();i++) {
440         TempDescriptor tmp=invars.get(i);
441         
442         /* In some cases we don't want to a dynamic traversal if it is
443          * unlikely to increase parallelism...these are cases where we
444          * are just enabling a stall site to possible clear faster*/
445
446         boolean isValidToPrune=true;
447         for( FlatSESEEnterNode parentSESE: fsen.getParents() ) {
448           ConflictGraph     graph      = oooa.getConflictGraph(parentSESE);
449           if(graph!=null){
450       String            id         = tmp + "_sese" + fsen.getPrettyIdentifier();
451       ConflictNode      node       = graph.getId2cn().get(id);
452       isValidToPrune &= node.IsValidToPrune();
453           }
454         }
455         
456         if(isValidToPrune){
457           // if node is valid to prune examiner, 
458           // also needs to turn off stall site examiners connected to this node
459           for( FlatSESEEnterNode parentSESE: fsen.getParents() ) {
460             ConflictGraph     graph      = oooa.getConflictGraph(parentSESE);
461             String            id         = tmp + "_sese" + fsen.getPrettyIdentifier();
462             ConflictNode      node       = graph.getId2cn().get(id);
463             
464             for (Iterator iterator = node.getEdgeSet().iterator(); iterator.hasNext();) {
465         ConflictEdge edge = (ConflictEdge) iterator.next();
466         if (edge.getVertexU() == node) {
467           if (edge.getVertexV().isStallSiteNode()) {
468             edge.getVertexV().setToBePruned(true);
469           }
470         } else {
471           if (edge.getVertexU().isStallSiteNode()) {
472             edge.getVertexU().setToBePruned(true);
473           }
474         }        
475       }
476           }
477         }
478                 
479         if (i!=0) {
480           cFile.println("      if (record->rcrstatus!=0)");
481         }
482         
483         if(globalState.NOSTALLTR && isValidToPrune) {
484           cFile.println("    /*  " + getTraverserInvocation(tmp, "rec->"+tmp+", rec", fsen)+"*/");
485         } else {
486           cFile.println("      " + getTraverserInvocation(tmp, "rec->"+tmp+", rec", fsen));
487         }
488       }
489       //release traverser reference...traversal finished...
490       //executing thread will clean bins for us
491       cFile.println("     record->rcrstatus=0;");
492       cFile.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
493       cFile.println("    RELEASE_REFERENCE_TO(record);");
494       cFile.println("#endif");
495       cFile.println(    "    }");
496       cFile.println(    "    break;");
497     }
498     
499     for(FlatNode stallsite: processedStallSites.keySet()) {
500       
501       TempDescriptor var = processedStallSites.get(stallsite);
502       Set<FlatSESEEnterNode> seseSet=oooa.getPossibleExecutingRBlocks(stallsite);
503       boolean isValidToPrune=true;
504       for (Iterator iterator = seseSet.iterator(); iterator.hasNext();) {
505         FlatSESEEnterNode sese = (FlatSESEEnterNode) iterator.next();
506         ConflictGraph     graph      = oooa.getConflictGraph(sese);
507         if(graph!=null){
508           String id = var + "_fn" + stallsite.hashCode();
509           ConflictNode      node       = graph.getId2cn().get(id);
510           isValidToPrune &= node.isTobePruned();
511         }
512       }
513       
514       cFile.println(    "    case -" + getTraverserID(var, stallsite)+ ": {");
515       cFile.println(    "      SESEstall * rec=(SESEstall*) record;");
516       if(globalState.NOSTALLTR && isValidToPrune){
517         cFile.println(    "     /*" + getTraverserInvocation(var, "rec->___obj___, rec", stallsite)+";*/");
518       }else{
519         cFile.println(    "      " + getTraverserInvocation(var, "rec->___obj___, rec", stallsite)+";");
520       }      
521       cFile.println(    "     record->rcrstatus=0;");
522       cFile.println(    "    }");
523       cFile.println("    break;");
524     }
525
526     cFile.println("    default:");
527     cFile.println("      printf(\"Invalid SESE ID was passed in: %d.\\n\",record->classID);");
528     cFile.println("      break;");
529     cFile.println("  }");
530     cFile.println("}");
531   }
532   
533   private void createMasterHashTableArray() {
534     headerFile.println("struct Hashtable_rcr ** createAndFillMasterHashStructureArray();");
535     cFile.println("struct Hashtable_rcr ** createAndFillMasterHashStructureArray() {");
536
537     cFile.println("  struct Hashtable_rcr **table=rcr_createMasterHashTableArray("+totalWeakGroups + ");");
538     
539     for(int i = 0; i < totalWeakGroups; i++) {
540       cFile.println("  table["+i+"] = (struct Hashtable_rcr *) rcr_createHashtable();");
541     }
542     cFile.println("  return table;");
543     cFile.println("}");
544   }
545
546   public int getWeakID(TempDescriptor invar, FlatNode fn) {
547     //return weakMap.get(new Pair(invar, fn)).intValue();
548     return 0;
549   }
550
551
552   public boolean hasEmptyTraversers(FlatSESEEnterNode fsen) {
553     boolean hasEmpty = true;
554     
555     Set<FlatSESEEnterNode> children = fsen.getChildren();
556     for (Iterator<FlatSESEEnterNode> iterator = children.iterator(); iterator.hasNext();) {
557       FlatSESEEnterNode child = (FlatSESEEnterNode) iterator.next();
558       hasEmpty &= child.getInVarsForDynamicCoarseConflictResolution().size() == 0;
559     }
560     return hasEmpty;
561   }  
562
563   
564   //Simply rehashes and combines all effects for a AffectedAllocSite + Field.
565   private class EffectsTable {
566     private Hashtable<Alloc,Set<Effect>> table;
567     SMFEState state;
568
569     public EffectsTable(SMFEState state) {
570       table = new Hashtable<Alloc, Set<Effect>>();
571       this.state=state;
572       for(Effect e: state.getEffectsAllowed()) {
573         Set<Effect> eg;
574         if((eg = table.get(e.getAffectedAllocSite())) == null) {
575           eg = new HashSet<Effect>();
576           table.put(e.getAffectedAllocSite(), eg);
577         }
578         eg.add(e);
579       }
580     }
581     
582     public boolean conflictDereference(Alloc a) {
583       for(Effect e:getEffects(a)) {
584         if (!state.transitionsTo(e).isEmpty()&&state.getConflicts().contains(e))
585           return true;
586       }
587       return false;
588     }
589
590     public boolean hasWriteConflict(Alloc a) {
591       for(Effect e:getEffects(a)) {
592         if (e.isWrite() && state.getConflicts().contains(e))
593           return true;
594       }
595       return false;
596     }
597
598     public boolean hasReadConflict(Alloc a) {
599       for(Effect e:getEffects(a)) {
600         if (e.isRead() && state.getConflicts().contains(e))
601           return true;
602       }
603       return false;
604     }
605
606     public Set<Effect> getEffects(Alloc a) {
607       return table.get(a);
608     }
609
610     public Set<Alloc> getAllAllocs() {
611       return table.keySet();
612     }
613   }
614 }