Minor changes: Removing vestigial code
[IRC.git] / Robust / src / IR / Flat / RuntimeConflictResolver.java
index 343bbfaab00a1f516569192c75249cabce82e74e..e71407d57a6aaa5a629f7d37a717d8f0b084126b 100644 (file)
 package IR.Flat;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.Vector;
+import Util.Tuple;
 import Analysis.Disjoint.*;
+import Analysis.MLP.CodePlan;
 import IR.TypeDescriptor;
-
-//TODO Make more efficient by only using ONE hashtable. 
-
-//TODO make threads be aware of each other and add another check for other rblocks or something
-//to fix issue of sometimes one thread marking conflict and not the other.
-//TODO it appears that using the optimize flags screws with the invar naming. 
+import Analysis.OoOJava.OoOJavaAnalysis;
 
 /* An instance of this class manages all OoOJava coarse-grained runtime conflicts
  * by generating C-code to either rule out the conflict at runtime or resolve one.
  * 
  * How to Use:
- * 1) Instantiate singleton object
- * 2a) Call void traverse(FlatSESEEnterNode rblock, Hashtable<Taint, Set<Effect>> effects, Hashtable<Taint, Set<Effect>> conflicts, ReachGraph rg)
- *    as many times as needed
- * 2b) call String getTraverserInvocation(TempDescriptor invar, String varString, FlatSESEEnterNode sese) to get the name of the traverse method in C
- * 3) Call void close()
+ * 1) Instantiate singleton object (String input is to specify output dir)
+ * 2) Call setGlobalEffects setGlobalEffects(Hashtable<Taint, Set<Effect>> ) ONCE
+ * 3) Input SESE blocks, for each block:
+ *    3a) call addToTraverseToDoList(FlatSESEEnterNode , ReachGraph , Hashtable<Taint, Set<Effect>>) for the seseBlock
+ *    3b) call String getTraverserInvocation(TempDescriptor, String, FlatSESEEnterNode) to get the name of the traverse method in C
+ * 4) Call void close() 
+ * Note: All computation is done upon closing the object. Steps 1-3 only input data
  */
 public class RuntimeConflictResolver {
-  private static boolean debug = false;
+  public static final boolean javaDebug = true;
+  public static final boolean cSideDebug = false;
   
-  public static String outputFile;
   private PrintWriter cFile;
   private PrintWriter headerFile;
   private static final String hashAndQueueCFileDir = "oooJava/";
+  //This keeps track of taints we've traversed to prevent printing duplicate traverse functions
+  //The Integer keeps track of the weakly connected group it's in (used in enumerateHeapRoots)
+  private Hashtable<Taint, Integer> doneTaints;
+  private Hashtable<Tuple, Integer> idMap=new Hashtable<Tuple,Integer>();
+  private Hashtable<Taint, Set<Effect>> globalEffects;
+  private Hashtable<Taint, Set<Effect>> globalConflicts;
+  private ArrayList<TraversalInfo> toTraverse;
+
+  public int currentID=1;
 
   // initializing variables can be found in printHeader()
   private static final String getAllocSiteInC = "->allocsite";
-  private static final String queryAndAddHashTableInC = "hashRCRInsert(";
+  private static final String queryVistedHashtable = "hashRCRInsert";
   private static final String addToQueueInC = "enqueueRCRQueue(";
   private static final String dequeueFromQueueInC = "dequeueRCRQueue()";
-
   private static final String clearQueue = "resetRCRQueue()";
   // Make hashtable; hashRCRCreate(unsigned int size, double loadfactor)
-  private static final String mallocHashTable = "hashRCRCreate(1024, 0.25)";
-  private static final String deallocHashTable = "hashRCRDelete()";
-  private static final String resetHashTable = "hashRCRreset()";
+  private static final String mallocVisitedHashtable = "hashRCRCreate(128, 0.75)";
+  private static final String deallocVisitedHashTable = "hashRCRDelete()";
+  private static final String resetVisitedHashTable = "hashRCRreset()";
+  
+  // Hashtable provides fast access to heaproot # lookups
+  private Hashtable<Taint, WeaklyConectedHRGroup> connectedHRHash;
+  private ArrayList<WeaklyConectedHRGroup> num2WeaklyConnectedHRGroup;
+  private int traverserIDCounter;
+  private int weaklyConnectedHRCounter;
+  private ArrayList<TaintAndInternalHeapStructure> pendingPrintout;
+  private EffectsTable effectsLookupTable;
+  private OoOJavaAnalysis oooa;
+
+  public RuntimeConflictResolver(String buildir, OoOJavaAnalysis oooa) throws FileNotFoundException {
+    String outputFile = buildir + "RuntimeConflictResolver";
+    this.oooa=oooa;
 
-  public RuntimeConflictResolver(String buildir) throws FileNotFoundException {
-    outputFile = buildir + "RuntimeConflictResolver";
-    
     cFile = new PrintWriter(new File(outputFile + ".c"));
     headerFile = new PrintWriter(new File(outputFile + ".h"));
     
-    cFile.append("#include \"" + hashAndQueueCFileDir + "hashRCR.h\"\n#include \""
-        + hashAndQueueCFileDir + "Queue_RCR.h\"\n#include <stdlib.h>\n");
-    cFile.append("#include \"classdefs.h\"\n");
-    cFile.append("#include \"RuntimeConflictResolver.h\"\n");
+    cFile.println("#include \"" + hashAndQueueCFileDir + "hashRCR.h\"\n#include \""
+        + hashAndQueueCFileDir + "Queue_RCR.h\"\n#include <stdlib.h>");
+    cFile.println("#include \"classdefs.h\"");
+    cFile.println("#include \"structdefs.h\"");
+    cFile.println("#include \"mlp_runtime.h\"");
+    cFile.println("#include \"RuntimeConflictResolver.h\"");
+    cFile.println("#include \"hashStructure.h\"");
+    
+    headerFile.println("#ifndef __3_RCR_H_");
+    headerFile.println("#define __3_RCR_H_");
+    
+    doneTaints = new Hashtable<Taint, Integer>();
+    connectedHRHash = new Hashtable<Taint, WeaklyConectedHRGroup>();
+    
+    traverserIDCounter = 1;
+    weaklyConnectedHRCounter = 0;
+    pendingPrintout = new ArrayList<TaintAndInternalHeapStructure>();
+    toTraverse = new ArrayList<TraversalInfo>();
+    globalConflicts = new Hashtable<Taint, Set<Effect>>(); 
+    //Note: globalEffects is not instantiated since it'll be passed in whole while conflicts comes in chunks
+  }
+
+  public void setGlobalEffects(Hashtable<Taint, Set<Effect>> effects) {
+    globalEffects = effects;
     
-    headerFile.append("#ifndef __3_RCR_H_\n");
-    headerFile.append("#define __3_RCR_H_\n");
-    //TODO more closely integrate this by asking generic type from other components? 
-    //generic cast struct
-    cFile.append("struct genericObjectStruct {int type; int oid; int allocsite; int ___cachedCode___; int ___cachedHash___;};\n");
+    if(javaDebug) {
+      System.out.println("============EFFECTS LIST AS PASSED IN============");
+      for(Taint t: globalEffects.keySet()) {
+        System.out.println("For Taint " + t);
+        for(Effect e: globalEffects.get(t)) {
+          System.out.println("\t" + e);
+        }
+      }
+      System.out.println("====================END  LIST====================");
+    }
   }
 
+  public void init() {
+    // Go through the SESE's
+    for (Iterator<FlatSESEEnterNode> seseit = oooa.getAllSESEs().iterator(); seseit.hasNext();) {
+      FlatSESEEnterNode fsen = seseit.next();
+      Analysis.OoOJava.ConflictGraph conflictGraph;
+      Hashtable<Taint, Set<Effect>> conflicts;
+      System.out.println("-------");
+      System.out.println(fsen);
+      System.out.println(fsen.getIsCallerSESEplaceholder());
+      System.out.println(fsen.getParent());
+
+      if (fsen.getParent() != null) {
+        conflictGraph = oooa.getConflictGraph(fsen.getParent());
+        System.out.println("CG=" + conflictGraph);
+        if (conflictGraph != null)
+          System.out.println("Conflicts=" + conflictGraph.getConflictEffectSet(fsen));
+      }
+
+      if (!fsen.getIsCallerSESEplaceholder() && fsen.getParent() != null
+          && (conflictGraph = oooa.getConflictGraph(fsen.getParent())) != null
+          && (conflicts = conflictGraph.getConflictEffectSet(fsen)) != null) {
+        FlatMethod fm = fsen.getfmEnclosing();
+        ReachGraph rg = oooa.getDisjointAnalysis().getReachGraph(fm.getMethod());
+        if (cSideDebug)
+          rg.writeGraph("RCR_RG_SESE_DEBUG");
+
+        addToTraverseToDoList(fsen, rg, conflicts);
+      }
+    }
+    // Go through the stall sites
+    for (Iterator<FlatNode> codeit = oooa.getNodesWithPlans().iterator(); codeit.hasNext();) {
+      FlatNode fn = codeit.next();
+      CodePlan cp = oooa.getCodePlan(fn);
+      FlatSESEEnterNode currentSESE = cp.getCurrentSESE();
+      Analysis.OoOJava.ConflictGraph graph = oooa.getConflictGraph(currentSESE);
+
+      if (graph != null) {
+        Set<Analysis.OoOJava.SESELock> seseLockSet = oooa.getLockMappings(graph);
+        Set<Analysis.OoOJava.WaitingElement> waitingElementSet =
+            graph.getStallSiteWaitingElementSet(fn, seseLockSet);
+
+        if (waitingElementSet.size() > 0) {
+          for (Iterator<Analysis.OoOJava.WaitingElement> iterator = waitingElementSet.iterator(); iterator.hasNext();) {
+            Analysis.OoOJava.WaitingElement waitingElement =
+                (Analysis.OoOJava.WaitingElement) iterator.next();
+
+            Analysis.OoOJava.ConflictGraph conflictGraph = graph;
+            Hashtable<Taint, Set<Effect>> conflicts;
+            ReachGraph rg = oooa.getDisjointAnalysis().getReachGraph(currentSESE.getmdEnclosing());
+            if (cSideDebug) {
+              rg.writeGraph("RCR_RG_STALLSITE_DEBUG");
+            }
+            if ((conflictGraph != null) && (conflicts = graph.getConflictEffectSet(fn)) != null
+                && (rg != null)) {
+              addToTraverseToDoList(fn, waitingElement.getTempDesc(), rg, conflicts);
+            }
+          }
+        }
+      }
+    }
+
+    buildEffectsLookupStructure();
+    runAllTraversals();
+  }
+  
   /*
-   * Basic steps: 
-   * 1) Create pruned data structures from givens 
-   *     1a) Use effects sets to verify if we can access something (reads) 
-   *     1b) Mark conflicts with 2 flags (one for self, one for references down the line) 
-   * 2) build code output structure 
-   * 3) printout
+   * Basic Strategy:
+   * 1) Get global effects and conflicts 
+   * 2) Create a hash structure (EffectsTable) to manage effects (hashed by affected Allocsite, then taint, then field)
+   *     2a) Use Effects to verify we can access something (reads)
+   *     2b) Use conflicts to mark conflicts (read/write/strongupdate)
+   *     2c) At second level of hash, store Heaproots that can cause conflicts at the field
+   * 3) Walk hash structure to identify and enumerate weakly connected groups and generate waiting queue slots. 
+   * 4) Build internal representation of the rgs (pruned)
+   * 5) Print c methods by walking internal representation
    */
-  public void traverse(FlatSESEEnterNode rblock, 
-      Hashtable<Taint, Set<Effect>> effects,
-      Hashtable<Taint, Set<Effect>> conflicts, 
-      ReachGraph rg) {
+  
+  public void addToTraverseToDoList(FlatSESEEnterNode rblock, ReachGraph rg, 
+      Hashtable<Taint, Set<Effect>> conflicts) {
+    //Add to todo list
+    toTraverse.add(new TraversalInfo(rblock, rg));
+
+    //Add to Global conflicts
+    for(Taint t: conflicts.keySet()) {
+      if(globalConflicts.containsKey(t)) {
+        globalConflicts.get(t).addAll(conflicts.get(t));
+      } else {
+        globalConflicts.put(t, conflicts.get(t));
+      }
+    }
+  }
+  
+
+  public void addToTraverseToDoList(FlatNode fn, TempDescriptor tempDesc, 
+      ReachGraph rg, Hashtable<Taint, Set<Effect>> conflicts) {
+    toTraverse.add(new TraversalInfo(fn, rg, tempDesc));
     
-    Set<TempDescriptor> inVars = rblock.getInVarSet();
+    for(Taint t: conflicts.keySet()) {
+      if(globalConflicts.containsKey(t)) {
+        globalConflicts.get(t).addAll(conflicts.get(t));
+      } else {
+        globalConflicts.put(t, conflicts.get(t));
+      }
+    }
+  }
+
+  private void traverseSESEBlock(FlatSESEEnterNode rblock, ReachGraph rg) {
+    Collection<TempDescriptor> inVars = rblock.getInVarSet();
     
     if (inVars.size() == 0)
       return;
+    System.out.println("RBLOCK:"+rblock);
+    System.out.println("["+inVars+"]");
     
     // For every non-primitive variable, generate unique method
-    // Special Note: The Criteria for executing printCMethod in this loop should match
-    // exactly the criteria in buildcode.java to invoke the generated C method(s). 
     for (TempDescriptor invar : inVars) {
       TypeDescriptor type = invar.getType();
-      if(type == null || type.isPrimitive()) {
+      if(isReallyAPrimitive(type)) {
         continue;
       }
-
-      Hashtable<AllocSite, ConcreteRuntimeObjNode> created = new Hashtable<AllocSite, ConcreteRuntimeObjNode>();
-
-      createTree(rblock, invar, effects, conflicts, rg, created);
-      if (!created.isEmpty()) {
-        rblock.addInVarForDynamicCoarseConflictResolution(invar);
-        printCMethod(created, invar.getSafeSymbol(), rblock.getPrettyIdentifier());
+      System.out.println(invar);
+      //"created" stores nodes with specific alloc sites that have been traversed while building
+      //internal data structure. Created is later traversed sequentially to find inset variables and
+      //build output code.
+      //NOTE: Integer stores Allocation Site ID in hashtable
+      Hashtable<Integer, ConcreteRuntimeObjNode> created = new Hashtable<Integer, ConcreteRuntimeObjNode>();
+      VariableNode varNode = rg.getVariableNodeNoMutation(invar);
+      Taint taint = getProperTaintForFlatSESEEnterNode(rblock, varNode, globalEffects);
+      if (taint == null) {
+        printDebug(javaDebug, "Null FOR " +varNode.getTempDescriptor().getSafeSymbol() + rblock.toPrettyString());
+        continue;
+      }
+      
+      //This is to prevent duplicate traversals from being generated 
+      if(doneTaints.containsKey(taint))
+        return;
+      
+      doneTaints.put(taint, traverserIDCounter++);
+      createConcreteGraph(effectsLookupTable, created, varNode, taint);
+      
+      
+      //This will add the taint to the printout, there will be NO duplicates (checked above)
+      if(!created.isEmpty()) {
+        for(Iterator<ConcreteRuntimeObjNode> it=created.values().iterator();it.hasNext();) {
+          ConcreteRuntimeObjNode obj=it.next();
+          if (obj.hasPrimitiveConflicts()||obj.decendantsConflict()) {
+            rblock.addInVarForDynamicCoarseConflictResolution(invar);
+            break;
+          }
+        }
+        
+        pendingPrintout.add(new TaintAndInternalHeapStructure(taint, created));
       }
     }
   }
 
-  public String getTraverserInvocation(TempDescriptor invar, String varString, FlatSESEEnterNode sese) {
-    return "traverse___" + invar.getSafeSymbol().replaceAll(" ", "") + 
-    sese.getPrettyIdentifier().replaceAll(" ", "") + "___("+varString+");";
+  //This extends a tempDescriptor's isPrimitive test by also excluding primitive arrays. 
+  private boolean isReallyAPrimitive(TypeDescriptor type) {
+    return (type.isPrimitive() && !type.isArray());
+  }
+  
+  private void traverseStallSite(FlatNode enterNode, TempDescriptor invar, ReachGraph rg) {
+    TypeDescriptor type = invar.getType();
+    if(type == null || isReallyAPrimitive(type)) {
+      return;
+    }
+    
+    Hashtable<Integer, ConcreteRuntimeObjNode> created = new Hashtable<Integer, ConcreteRuntimeObjNode>();
+    VariableNode varNode = rg.getVariableNodeNoMutation(invar);
+    Taint taint = getProperTaintForEnterNode(enterNode, varNode, globalEffects);
+    
+    if (taint == null) {
+      printDebug(javaDebug, "Null FOR " +varNode.getTempDescriptor().getSafeSymbol() + enterNode.toString());
+      return;
+    }        
+    
+    if(doneTaints.containsKey(taint))
+      return;
+    
+    doneTaints.put(taint, traverserIDCounter++);
+    createConcreteGraph(effectsLookupTable, created, varNode, taint);
+    
+    if (!created.isEmpty()) {
+      pendingPrintout.add(new TaintAndInternalHeapStructure(taint, created));
+    }
+  }
+  
+  public String getTraverserInvocation(TempDescriptor invar, String varString, FlatNode fn) {
+    String flatname;
+    if(fn instanceof FlatSESEEnterNode) {
+      flatname = ((FlatSESEEnterNode) fn).getPrettyIdentifier();
+    } else {
+      flatname = fn.toString();
+    }
+    
+    return "traverse___" + invar.getSafeSymbol() + 
+    removeInvalidChars(flatname) + "___("+varString+");";
+  }
+
+  public int getTraverserID(TempDescriptor invar, FlatNode fn) {
+    Tuple t=new Tuple(invar, fn);
+    if (idMap.containsKey(t))
+      return idMap.get(t).intValue();
+    int value=currentID++;
+    idMap.put(t, new Integer(value));
+    return value;
+  }
+  
+  public String removeInvalidChars(String in) {
+    StringBuilder s = new StringBuilder(in);
+    for(int i = 0; i < s.length(); i++) {
+      if(s.charAt(i) == ' ' || s.charAt(i) == '.' || s.charAt(i) == '='||s.charAt(i)=='['||s.charAt(i)==']') {
+        s.deleteCharAt(i);
+        i--;
+      }
+    }
+    return s.toString();
   }
 
   public void close() {
+    //prints out all generated code
+    for(TaintAndInternalHeapStructure ths: pendingPrintout) {
+      printCMethod(ths.nodesInHeap, ths.t);
+    }
+    
+    //Prints out the master traverser Invocation that'll call all other traversers
+    //based on traverserID
+    printMasterTraverserInvocation();
+    printResumeTraverserInvocation();
+    
+    //TODO this is only temporary, remove when thread local vars implemented. 
+    createMasterHashTableArray();
+    
     // Adds Extra supporting methods
-    cFile.append("void initializeStructsRCR() { " + mallocHashTable + "; " + clearQueue + "; }");
-    cFile.append("void destroyRCR() { " + deallocHashTable + "; }\n");
+    cFile.println("void initializeStructsRCR() {\n  " + mallocVisitedHashtable + ";\n  " + clearQueue + ";\n}");
+    cFile.println("void destroyRCR() {\n  " + deallocVisitedHashTable + ";\n}");
     
-    headerFile.append("void initializeStructsRCR(); \nvoid destroyRCR(); \n");
-    headerFile.append("#endif\n");
+    headerFile.println("void initializeStructsRCR();\nvoid destroyRCR();");
+    headerFile.println("#endif\n");
 
     cFile.close();
     headerFile.close();
   }
 
-  //TODO it appears that using the optimize flags screws with the invar naming. 
-  private void createTree(FlatSESEEnterNode rblock, 
-      TempDescriptor invar,
-      Hashtable<Taint, Set<Effect>> effects,
-      Hashtable<Taint, Set<Effect>> conflicts, 
-      ReachGraph rg, 
-      Hashtable<AllocSite, ConcreteRuntimeObjNode> created) {
+  //Builds Effects Table and runs the analysis on them to get weakly connected HRs
+  //SPECIAL NOTE: Only runs after we've taken all the conflicts and effects
+  private void buildEffectsLookupStructure(){
+    effectsLookupTable = new EffectsTable(globalEffects, globalConflicts);
+    effectsLookupTable.runAnalysis();
+    enumerateHeaproots();
+  }
 
-    VariableNode varNode = rg.getVariableNodeNoMutation(invar);
-   
-    //TODO Fix bug where it recognizes multiple effects for the same string ><
-    Hashtable<AllocSite, EffectsGroup> table =
-        generateEffectsLookupTable(rblock, varNode, effects, conflicts);
+  private void runAllTraversals() {
+    for(TraversalInfo t: toTraverse) {
+      printDebug(javaDebug, "Running Traversal a traversal on " + t.f);
+      
+      if(t.f instanceof FlatSESEEnterNode) {
+        traverseSESEBlock((FlatSESEEnterNode)t.f, t.rg);
+      } else {
+        if(t.invar == null) {
+          System.out.println("RCR ERROR: Attempted to run a stall site traversal with NO INVAR");
+        } else {
+          traverseStallSite(t.f, t.invar, t.rg);
+        }
+      }
+        
+    }
+  }
+
+  //TODO: This is only temporary, remove when thread local variables are functional. 
+  private void createMasterHashTableArray() {
+    headerFile.println("void createAndFillMasterHashStructureArray();");
+    cFile.println("void createAndFillMasterHashStructureArray() {\n" +
+               "  rcr_createMasterHashTableArray("+weaklyConnectedHRCounter + ");");
+    
+    for(int i = 0; i < weaklyConnectedHRCounter; i++) {
+      cFile.println("  allHashStructures["+i+"] = (HashStructure *) rcr_createHashtable("+num2WeaklyConnectedHRGroup.get(i).connectedHRs.size()+");");
+    }
+    cFile.println("}");
+  }
+
+  private void printMasterTraverserInvocation() {
+    headerFile.println("\nint tasktraverse(SESEcommon * record);");
+    cFile.println("\nint tasktraverse(SESEcommon * record) {");
+    cFile.println("  if(!CAS(&record->rcrstatus,1,2)) return;");
+    cFile.println("  switch(record->classID) {");
+    
+    for(Iterator<FlatSESEEnterNode> seseit=oooa.getAllSESEs().iterator();seseit.hasNext();) {
+      FlatSESEEnterNode fsen=seseit.next();
+      cFile.println(    "    /* "+fsen.getPrettyIdentifier()+" */");
+      cFile.println(    "    case "+fsen.getIdentifier()+": {");
+      cFile.println(    "      "+fsen.getSESErecordName()+" * rec=("+fsen.getSESErecordName()+" *) record;");
+      Vector<TempDescriptor> invars=fsen.getInVarsForDynamicCoarseConflictResolution();
+      for(int i=0;i<invars.size();i++) {
+        TempDescriptor tmp=invars.get(i);
+        cFile.println("      " + this.getTraverserInvocation(tmp, "rec->"+tmp+", rec", fsen));
+      }
+      cFile.println(    "    }");
+      cFile.println(    "    break;");
+    }
+    
+    for(Taint t: doneTaints.keySet()) {
+      if (t.isStallSiteTaint()){
+        cFile.println(    "    case -" + getTraverserID(t.getVar(), t.getStallSite())+ ": {");
+        cFile.println(    "      SESEstall * rec=(SESEstall*) record;");
+        cFile.println(    "      " + this.getTraverserInvocation(t.getVar(), "rec->___obj___, rec", t.getStallSite())+";");
+        cFile.println(    "    }");
+        cFile.println("    break;");
+      }
+    }
+
+    cFile.println("    default:\n    printf(\"Invalid SESE ID was passed in: %d.\\n\",record->classID);\n    break;");
+    
+    cFile.println("  }");
+    cFile.println("}");
+  }
+
+
+  //This will print the traverser invocation that takes in a traverserID and starting ptr
+  private void printResumeTraverserInvocation() {
+    headerFile.println("\nint traverse(void * startingPtr, SESEcommon * record, int traverserID);");
+    cFile.println("\nint traverse(void * startingPtr, SESEcommon *record, int traverserID) {");
+    cFile.println("  switch(traverserID) {");
+    
+    for(Taint t: doneTaints.keySet()) {
+      cFile.println("  case " + doneTaints.get(t)+ ":");
+      if(t.isRBlockTaint()) {
+        cFile.println("    " + this.getTraverserInvocation(t.getVar(), "startingPtr, ("+t.getSESE().getSESErecordName()+" *)record", t.getSESE()));
+      } else if (t.isStallSiteTaint()){
+        cFile.println("/*    " + this.getTraverserInvocation(t.getVar(), "startingPtr, record", t.getStallSite())+"*/");
+      } else {
+        System.out.println("RuntimeConflictResolver encountered a taint that is neither SESE nor stallsite: " + t);
+      }
+      cFile.println("    break;");
+    }
+    
+    if(RuntimeConflictResolver.cSideDebug) {
+      cFile.println("  default:\n    printf(\"Invalid traverser ID %u was passed in.\\n\", traverserID);\n    break;");
+    } else {
+      cFile.println("  default:\n    break;");
+    }
+    
+    cFile.println(" }");
+    cFile.println("}");
+  }
+
+  private void createConcreteGraph(
+      EffectsTable table,
+      Hashtable<Integer, ConcreteRuntimeObjNode> created, 
+      VariableNode varNode, 
+      Taint t) {
     
     // if table is null that means there's no conflicts, therefore we need not
     // create a traversal
     if (table == null)
       return;
-   
-    if(debug) {
-      System.out.println("==========Table print out============");
-      for(AllocSite key: table.keySet()) {
-        EffectsGroup eg= table.get(key);
-        for(String innerKey: eg.myEffects.keySet()) {
-          EffectPair ef = eg.myEffects.get(innerKey);
-          System.out.println(key.hashCode() + "." + innerKey + "    conflict="+ ef.conflict );
-        }
-      }
-    }
 
-    Iterator<RefEdge> possibleEdges = varNode.iteratorToReferencees();    
-    
+    Iterator<RefEdge> possibleEdges = varNode.iteratorToReferencees();
     while (possibleEdges.hasNext()) {
       RefEdge edge = possibleEdges.next();
       assert edge != null;
 
       ConcreteRuntimeObjNode singleRoot = new ConcreteRuntimeObjNode(edge.getDst(), true);
-      AllocSite rootKey = singleRoot.allocSite;
+      int rootKey = singleRoot.allocSite.getUniqueAllocSiteID();
 
       if (!created.containsKey(rootKey)) {
         created.put(rootKey, singleRoot);
-        createHelper(singleRoot, edge.getDst().iteratorToReferencees(), created, table);
+        createHelper(singleRoot, edge.getDst().iteratorToReferencees(), created, table, t);
       }
     }
   }
 
-  private Hashtable<AllocSite, EffectsGroup> generateEffectsLookupTable(FlatSESEEnterNode rblock,
-        VariableNode var, Hashtable<Taint, Set<Effect>> effects,
-        Hashtable<Taint, Set<Effect>> conflicts) {
-      // we search effects since conflicts is only a subset of effects
-      Taint taint = getProperTaint(rblock, var, effects);
-      if (taint == null) {
-        if(debug) {
-          System.out.println("Null FOR " +var.getTempDescriptor().getSafeSymbol() + rblock.toPrettyString());
-        }
-        return null;
-      }
-    
-      Set<Effect> localEffects = effects.get(taint);
-      Set<Effect> localConflicts = conflicts.get(taint);
-      
-      if (localEffects == null || localEffects.isEmpty() || localConflicts == null || localConflicts.isEmpty())
-        return null;
-      
-  //    Debug Code for manually checking effects
-      if(debug) {
-        System.out.println("#### List of Effects/Conflicts ####");
-        System.out.println("For Taint " + taint);
-        System.out.println("Effects");
-        for(Effect e: localEffects)
-        {
-         System.out.println(e); 
-        }
-        
-        System.out.println("Conflicts");
-        for(Effect e: localConflicts)
-        {
-          System.out.println(e); 
-        }
-      }
-      
-      Hashtable<AllocSite, EffectsGroup> lookupTable = new Hashtable<AllocSite, EffectsGroup>();
-      
-      for (Effect e : localEffects) {
-        boolean conflict = localConflicts.contains(e);
-        AllocSite key = e.getAffectedAllocSite();
-        EffectsGroup myEffects = lookupTable.get(key);
-        
-        if(myEffects == null) {
-          myEffects = new EffectsGroup();
-          lookupTable.put(key, myEffects);
-        }
-        
-        if(e.getField().getType().isPrimitive()) {
-          if(conflict) {
-            myEffects.addPrimative(e);
-          }
-        }
-        else {
-          myEffects.addObj(e, conflict);
-        }      
-      }
-      
-      return lookupTable;
-    }
-
   // Plan is to add stuff to the tree depth-first sort of way. That way, we can
   // propagate up conflicts
   private void createHelper(ConcreteRuntimeObjNode curr, 
                             Iterator<RefEdge> edges, 
-                            Hashtable<AllocSite, ConcreteRuntimeObjNode> created,
-                            Hashtable<AllocSite, EffectsGroup> table) {
+                            Hashtable<Integer, ConcreteRuntimeObjNode> created,
+                            EffectsTable table, 
+                            Taint taint) {
     assert table != null;
-    
     AllocSite parentKey = curr.allocSite;
-    EffectsGroup currEffects = table.get(parentKey);
+    EffectsGroup currEffects = table.getEffects(parentKey, taint); 
     
     if (currEffects == null || currEffects.isEmpty()) 
       return;
     
-    //Handle Objects
-    if(currEffects.hasObjectConflicts()) {
+    //Handle Objects (and primitives if child is new)
+    if(currEffects.hasObjectEffects()) {
       while(edges.hasNext()) {
         RefEdge edge = edges.next();
         String field = edge.getField();
-        EffectPair effect = currEffects.getObjEffect(field); // TODO are you certain there is only one effect to get here?
-        //If there is no effect, then there's not point in traversing this edge
-        if(effect != null)
-        {
+        CombinedObjEffects effectsForGivenField = currEffects.getObjEffect(field);
+        //If there are no effects, then there's no point in traversing this edge
+        if(effectsForGivenField != null) {
           HeapRegionNode childHRN = edge.getDst();
-          AllocSite childKey = childHRN.getAllocSite();
+          int childKey = childHRN.getAllocSite().getUniqueAllocSiteID();
           boolean isNewChild = !created.containsKey(childKey);
           ConcreteRuntimeObjNode child; 
-    
+          
           if(isNewChild) {
             child = new ConcreteRuntimeObjNode(childHRN, false);
             created.put(childKey, child);
-          }
-          else {
+          } else {
             child = created.get(childKey);
           }
     
-          curr.addObjChild(field, child, effect.conflict);
+          curr.addObjChild(field, child, effectsForGivenField);
           
-          if (effect.conflict) {
-            propogateObjConflictFlag(child);
+          if (effectsForGivenField.hasConflict()) {
+            child.hasPotentialToBeIncorrectDueToConflict |= effectsForGivenField.hasReadConflict;
+            propagateObjConflict(curr, child);
           }
           
-          if (effect.type == Effect.read && isNewChild) {
-            createHelper(child, childHRN.iteratorToReferencees(), created, table);
+          if(effectsForGivenField.hasReadEffect) {
+            child.addReachableParent(curr);
+            
+            //If isNewChild, flag propagation will be handled at recursive call
+            if(isNewChild) {
+              createHelper(child, childHRN.iteratorToReferencees(), created, table, taint);
+            } else {
+            //This makes sure that all conflicts below the child is propagated up the referencers.
+              if(child.decendantsPrimConflict || child.hasPrimitiveConflicts()) {
+                propagatePrimConflict(child, child.enqueueToWaitingQueueUponConflict);
+              }
+              
+              if(child.decendantsObjConflict) {
+                propagateObjConflict(child, child.enqueueToWaitingQueueUponConflict);
+              }
+            }
           }
         }
       }
     }
     
-    //Handle primitives
-    if(currEffects.hasPrimativeConflicts()) {
-      curr.primativeFields = currEffects.primativeConflictingFields; 
-      propogatePrimConflictFlag(curr);
-    } 
+    //Handles primitives
+    curr.primitiveConflictingFields = currEffects.primitiveConflictingFields; 
+    if(currEffects.hasPrimitiveConflicts()) {
+      //Reminder: primitive conflicts are abstracted to object. 
+      propagatePrimConflict(curr, curr);
+    }
   }
 
   // This will propagate the conflict up the data structure.
-  private void propogateObjConflictFlag(ConcreteRuntimeObjNode in) {
-    ConcreteRuntimeObjNode node = in;
-    
-    while(node.lastReferencer != null) {
-      node.lastReferencer.decendantsObjConflict = true;
-      if(!node.conflictingParents.add(node.lastReferencer))
-        break;
-      node = node.lastReferencer;
+  private void propagateObjConflict(ConcreteRuntimeObjNode curr, HashSet<ConcreteRuntimeObjNode> pointsOfAccess) {
+    for(ConcreteRuntimeObjNode referencer: curr.parentsWithReadToNode) {
+      if(curr.parentsThatWillLeadToConflicts.add(referencer) || //case where referencee has never seen referncer
+          (pointsOfAccess != null && referencer.addPossibleWaitingQueueEnqueue(pointsOfAccess))) // case where referencer has never seen possible unresolved referencee below 
+      {
+        referencer.decendantsObjConflict = true;
+        propagateObjConflict(referencer, pointsOfAccess);
+      }
     }
   }
   
-  private void propogatePrimConflictFlag(ConcreteRuntimeObjNode in) {
-    ConcreteRuntimeObjNode node = in;
-    
-    while(node.lastReferencer != null) {
-      node.lastReferencer.decendantsPrimConflict = true;
-      if(!node.conflictingParents.add(node.lastReferencer))
-        break;
-      node = node.lastReferencer;
+  private void propagateObjConflict(ConcreteRuntimeObjNode curr, ConcreteRuntimeObjNode pointOfAccess) {
+    for(ConcreteRuntimeObjNode referencer: curr.parentsWithReadToNode) {
+      if(curr.parentsThatWillLeadToConflicts.add(referencer) || //case where referencee has never seen referncer
+          (pointOfAccess != null && referencer.addPossibleWaitingQueueEnqueue(pointOfAccess))) // case where referencer has never seen possible unresolved referencee below 
+      {
+        referencer.decendantsObjConflict = true;
+        propagateObjConflict(referencer, pointOfAccess);
+      }
     }
   }
-
+  
+  private void propagatePrimConflict(ConcreteRuntimeObjNode curr, HashSet<ConcreteRuntimeObjNode> pointsOfAccess) {
+    for(ConcreteRuntimeObjNode referencer: curr.parentsWithReadToNode) {
+      if(curr.parentsThatWillLeadToConflicts.add(referencer) || //same cases as above
+          (pointsOfAccess != null && referencer.addPossibleWaitingQueueEnqueue(pointsOfAccess))) 
+      {
+        referencer.decendantsPrimConflict = true;
+        propagatePrimConflict(referencer, pointsOfAccess);
+      }
+    }
+  }
+  
+  private void propagatePrimConflict(ConcreteRuntimeObjNode curr, ConcreteRuntimeObjNode pointOfAccess) {
+    for(ConcreteRuntimeObjNode referencer: curr.parentsWithReadToNode) {
+      if(curr.parentsThatWillLeadToConflicts.add(referencer) || //same cases as above
+          (pointOfAccess != null && referencer.addPossibleWaitingQueueEnqueue(pointOfAccess))) 
+      {
+        referencer.decendantsPrimConflict = true;
+        propagatePrimConflict(referencer, pointOfAccess);
+      }
+    }
+  }
+  
   /*
    * This method generates a C method for every inset variable and rblock. 
    * 
@@ -315,323 +606,855 @@ public class RuntimeConflictResolver {
    *  conflicts will be signaled by the referencer; the only exception is the inset variable which can 
    *  signal a conflict within itself. 
    */
-  private void printCMethod(Hashtable<AllocSite, ConcreteRuntimeObjNode> created, String inVar, String rBlock) {
-    //This hash table keeps track of all the case statements generated. Although it may seem a bit much
-    //for its purpose, I think it may come in handy later down the road to do it this way. 
-    //(i.e. what if we want to eliminate some cases? Or build filter for 1 case)
+  
+  private void printCMethod(Hashtable<Integer, ConcreteRuntimeObjNode> created, Taint taint) {
+    String inVar = taint.getVar().getSafeSymbol();
+    String rBlock;
+    
+    if(taint.isStallSiteTaint()) {
+      rBlock = taint.getStallSite().toString();
+    } else if(taint.isRBlockTaint()) {
+      rBlock = taint.getSESE().getPrettyIdentifier();
+    } else {
+      System.out.println("RCR CRITICAL ERROR: TAINT IS NEITHER A STALLSITE NOR SESE! " + taint.toString());
+      return;
+    }
+    
+    //This hash table keeps track of all the case statements generated.
     Hashtable<AllocSite, StringBuilder> cases = new Hashtable<AllocSite, StringBuilder>();
     
     //Generate C cases 
     for (ConcreteRuntimeObjNode node : created.values()) {
-      // If we haven't seen it and it's a node with more than 1 parent
-      // Note: a node with 0 parents is a root node (i.e. inset variable)
-      if (!cases.containsKey(node.allocSite) && (node.getNumOfReachableParents() != 1 || node.isInsetVar)
-          && node.decendantsConflict()) {
-        //resets the lastReferncer if we're dealing with an insetVar
-        node.lastReferencer = null;
-        addChecker(node, cases, null, "ptr", 0);
+      printDebug(javaDebug, "Considering " + node.allocSite + " for traversal");
+      if (!cases.containsKey(node.allocSite) && qualifiesForCaseStatement(node)) {
+        printDebug(javaDebug, "+\t" + node.allocSite + " qualified for case statement");
+        addChecker(taint, node, cases, null, "ptr", 0);
       }
     }
     
-    //IMPORTANT: remember to change getTraverserInvocation if you change the line below
-    String methodName = "void traverse___" + inVar.replaceAll(" ", "") + rBlock.replaceAll(" ", "") + 
-    "___(void * InVar)";
-    
-    cFile.append(methodName + " {\n");
-    headerFile.append(methodName + ";\n");
+    String methodName;
+    int index=-1;
+
+    if (taint.isStallSiteTaint()) {
+      methodName= "void traverse___" + inVar + removeInvalidChars(rBlock) + "___(void * InVar, SESEstall *record)";
+    } else {
+      methodName= "void traverse___" + inVar + removeInvalidChars(rBlock) + "___(void * InVar, "+taint.getSESE().getSESErecordName() +" *record)";
+      FlatSESEEnterNode fsese=taint.getSESE();
+      TempDescriptor tmp=taint.getVar();
+      index=fsese.getInVarsForDynamicCoarseConflictResolution().indexOf(tmp);
+    }
+
+    cFile.println(methodName + " {");
+    headerFile.println(methodName + ";");
     
-    cFile.append("printf(\"The traverser ran for " + methodName + "\\n\");\n");
+    if(cSideDebug) {
+      cFile.println("printf(\"The traverser ran for " + methodName + "\\n\");");
+      }
+
     
     if(cases.size() == 0) {
-      cFile.append(" return; }");
-    } 
-    else {
-      //Casts the ptr to a genericObjectStruct so we can get to the ptr->allocsite field. 
-      cFile.append("struct genericObjectStruct * ptr = (struct genericObjectStruct *) InVar;  if(InVar != NULL) { " + queryAndAddHashTableInC
-          + "ptr); do { ");
+      cFile.println(" return;");
+    } else {
+      cFile.println("    int totalcount=RUNBIAS;\n");
+      
+      if (taint.isStallSiteTaint()) {
+        cFile.println("    record->rcrRecords[0].count=RUNBIAS;\n");
+      } else {
+        cFile.println("    record->rcrRecords["+index+"].count=RUNBIAS;\n");
+        cFile.println("    record->rcrRecords["+index+"].index=0;\n");
+      }
       
-      cFile.append("switch(ptr->allocsite) { ");
+      //clears queue and hashtable that keeps track of where we've been. 
+      cFile.println(clearQueue + ";\n" + resetVisitedHashTable + ";"); 
+      //generic cast to ___Object___ to access ptr->allocsite field. 
+      cFile.println("struct ___Object___ * ptr = (struct ___Object___ *) InVar;\nif (InVar != NULL) {\n " + queryVistedHashtable + "(ptr);\n do {");
+      if (taint.isRBlockTaint()) {
+       cFile.println("  if(unlikely(record->common.doneExecuting)) {");
+       cFile.println("    record->common.rcrstatus=0;");
+       cFile.println("    return;");
+       cFile.println("  }");
+      }
+      cFile.println("  switch(ptr->allocsite) {");
       
-      for(AllocSite singleCase: cases.keySet())
+      for(AllocSite singleCase: cases.keySet()) {
         cFile.append(cases.get(singleCase));
+      }
       
-      cFile.append(" default : break; ");
-      cFile.append("}} while( (ptr = " + dequeueFromQueueInC + ") != NULL); ");
+      cFile.println("  default:\n    break; ");
+      cFile.println("  }\n } while((ptr = " + dequeueFromQueueInC + ") != NULL);\n}");
       
-      //Closes the method by clearing the Queue and reseting the hashTable to prevent
-      //overhead from freeing and mallocing the structures. 
-      cFile.append(clearQueue + "; " + resetHashTable + "; }}\n"); 
+      if (taint.isStallSiteTaint()) {
+        //need to add this
+        cFile.println("     if(atomic_sub_and_test(RUNBIAS-totalcount,&(record->rcrRecords[0].count))) {");
+        cFile.println("         psem_give_tag(record->common.parentsStallSem, record->tag);");
+        cFile.println("         BARRIER();");
+        cFile.println("         record->common.rcrstatus=0;");
+        cFile.println("}");
+      } else {
+        cFile.println("     if(atomic_sub_and_test(RUNBIAS-totalcount,&(record->rcrRecords["+index+"].count))) {");
+        cFile.println("        int flag=LOCKXCHG32(&(record->rcrRecords["+index+"].flag),0);");
+        cFile.println("        if(flag) {");
+        //we have resolved a heap root...see if this was the last dependence
+        cFile.println("            if(atomic_sub_and_test(1, &(record->common.unresolvedDependencies))) workScheduleSubmit((void *)record);");
+        cFile.println("        }");
+        cFile.println("     }");
+        cFile.println("     record->common.rcrstatus=0;");
+      }
     }
+    cFile.println("}");
     cFile.flush();
   }
   
   /*
-   * addChecker creates a case statement for every object that is either an inset variable
-   * or has multiple referencers (incoming edges). Else it just prints the checker for that object
-   * so that its processing can be pushed up to the referencer node. 
+   * addChecker creates a case statement for every object that is an inset variable, has more
+   * than 1 parent && has conflicts, or where resumes are possible (from waiting queue). 
+   * See .qualifiesForCaseStatement
    */
-  private void addChecker(ConcreteRuntimeObjNode node, 
+  private void addChecker(Taint taint, 
+                          ConcreteRuntimeObjNode node, 
                           Hashtable<AllocSite,StringBuilder> cases, 
                           StringBuilder possibleContinuingCase, 
                           String prefix, 
                           int depth) {
     StringBuilder currCase = possibleContinuingCase;
-    // We don't need a case statement for things with either 1 incoming or 0 out
-    // going edges, because they can be processed when checking the parent. 
-    if ((node.getNumOfReachableParents() != 1 || node.isInsetVar)  && node.decendantsConflict()) {
+    if(qualifiesForCaseStatement(node)) {
       assert prefix.equals("ptr") && !cases.containsKey(node.allocSite);
       currCase = new StringBuilder();
       cases.put(node.allocSite, currCase);
-      currCase.append("case " + node.getAllocationSite() + ":\n { ");
+      currCase.append("  case " + node.getAllocationSite() + ": {\n");
     }
     //either currCase is continuing off a parent case or is its own. 
     assert currCase !=null;
     
-    //Specific Primitives test for invars
-    if(node.isInsetVar && node.hasPrimativeConflicts()) {
-      handlePrimitiveConflict(currCase, prefix, node.primativeFields, node.allocSite);
+    boolean primConfRead=false;
+    boolean primConfWrite=false;
+    boolean objConfRead=false;
+    boolean objConfWrite=false;
+
+    //Direct Primitives Test
+    for(String field: node.primitiveConflictingFields.keySet()) {
+      CombinedObjEffects effect=node.primitiveConflictingFields.get(field);
+      primConfRead|=effect.hasReadConflict;
+      primConfWrite|=effect.hasWriteConflict;
+    }
+
+    //Direct Object Reference Test
+    for(String field: node.objectRefs.keySet()) {
+      for(ObjRef ref: node.objectRefs.get(field)) {
+        CombinedObjEffects effect=ref.myEffects;
+        objConfRead|=effect.hasReadConflict;
+        objConfWrite|=effect.hasWriteConflict;
+      }
     }
+
+    int index=-1;
+    if (taint.isRBlockTaint()) {
+      FlatSESEEnterNode fsese=taint.getSESE();
+      TempDescriptor tmp=taint.getVar();
+      index=fsese.getInVarsForDynamicCoarseConflictResolution().indexOf(tmp);
+    }
+
+    String strrcr=taint.isRBlockTaint()?"&record->rcrRecords["+index+"], ":"NULL, ";
     
-    //Casts C pointer; depth is used to create unique "myPtr" name for when things are inlined
-    String currPtr = "myPtr" + depth;
-    String structType = node.original.getType().getSafeSymbol();
-    currCase.append("struct " + structType + " * "+currPtr+"= (struct "+ structType + " * ) " + prefix + "; ");
-  
-    //Handles Objects
-    for (ObjRef ref : node.objectRefs) {
-      // Will only process edge if there is some sort of conflict with the Child
-      if (ref.hasConflictsDownThisPath(node)) {
-        String childPtr = currPtr +"->___" + ref.field + "___";
+    //Do call if we need it.
+    if(primConfWrite||objConfWrite) {
+      int heaprootNum = connectedHRHash.get(taint).id;
+      assert heaprootNum != -1;
+      int allocSiteID = connectedHRHash.get(taint).getWaitingQueueBucketNum(node);
+      int traverserID = doneTaints.get(taint);
+        currCase.append("    int tmpkey"+depth+"=rcr_generateKey("+prefix+");\n");
+      if (objConfRead)
+        currCase.append("    int tmpvar"+depth+"=rcr_WTWRITEBINCASE(allHashStructures["+heaprootNum+"], tmpkey"+depth+", (SESEcommon *) record, "+strrcr+index+");\n");
+      else
+        currCase.append("    int tmpvar"+depth+"=rcr_WRITEBINCASE(allHashStructures["+heaprootNum+"], tmpkey"+depth+", (SESEcommon *) record, "+strrcr+index+");\n");
+    } else if (primConfRead||objConfRead) {
+      int heaprootNum = connectedHRHash.get(taint).id;
+      assert heaprootNum != -1;
+      int allocSiteID = connectedHRHash.get(taint).getWaitingQueueBucketNum(node);
+      int traverserID = doneTaints.get(taint);
+      currCase.append("    int tmpkey"+depth+"=rcr_generateKey("+prefix+");\n");
+      if (objConfRead) 
+        currCase.append("    int tmpvar"+depth+"=rcr_WTREADBINCASE(allHashStructures["+heaprootNum+"], tmpkey"+depth+", (SESEcommon *) record, "+strrcr+index+");\n");
+      else
+        currCase.append("    int tmpvar"+depth+"=rcr_READBINCASE(allHashStructures["+heaprootNum+"], tmpkey"+depth+", (SESEcommon *) record, "+strrcr+index+");\n");
+    }
+
+    if(primConfWrite||objConfWrite||primConfRead||objConfRead) {
+      currCase.append("if (!(tmpvar"+depth+"&READYMASK)) totalcount--;\n");
+    }
+    
+    //Handle conflicts further down. 
+    if(node.decendantsConflict()) {
+      int pdepth=depth+1;
+      currCase.append("{\n");
+      
+      //Array Case
+      if(node.isArray() && node.decendantsConflict()) {
+        String childPtr = "((struct ___Object___ **)(((char *) &(((struct ArrayObject *)"+ prefix+")->___length___))+sizeof(int)))[i]";
+        String currPtr = "arrayElement" + pdepth;
         
-        // Checks if the child exists and has allocsite matching the conflict
-        currCase.append("if(" + childPtr + " != NULL && " + childPtr + getAllocSiteInC + "=="
-            + ref.allocSite + ") { ");
-
-        // Prints out conflicts of child
-        if (ref.child.hasConflicts())
-          handleObjConflict(currCase, childPtr, node.allocSite);
-       
-        if(ref.child.hasPrimativeConflicts())
-          handlePrimitiveConflict(currCase, childPtr, ref.child.primativeFields, ref.child.allocSite);
-
-        if (ref.child.decendantsConflict()) {
-          // Checks if we have visited the child before
-          currCase.append("if(!" + queryAndAddHashTableInC + childPtr + ")) { ");
-          if (ref.child.getNumOfReachableParents() == 1 && !ref.child.isInsetVar) {
-            addChecker(ref.child, cases, currCase, childPtr, depth + 1);
-          }
-          else {
-            currCase.append(addToQueueInC + childPtr + ");");
-          }
+        currCase.append("{\n  int i;\n");
+        currCase.append("    struct ___Object___ * "+currPtr+";\n");
+        currCase.append("  for(i = 0; i<((struct ArrayObject *) " + prefix + " )->___length___; i++ ) {\n");
+        
+        //There should be only one field, hence we only take the first field in the keyset.
+        assert node.objectRefs.keySet().size() <= 1;
+        ObjRefList refsAtParticularField = node.objectRefs.get(node.objectRefs.keySet().iterator().next());
+        printObjRefSwitchStatement(taint,cases,pdepth,currCase,refsAtParticularField,childPtr,currPtr);
+        currCase.append("      }}\n");
+      } else {
+      //All other cases
+        String currPtr = "myPtr" + pdepth;
+        currCase.append("    struct ___Object___ * "+currPtr+";\n");
+        for(String field: node.objectRefs.keySet()) {
+          ObjRefList refsAtParticularField = node.objectRefs.get(field);
           
-          currCase.append(" } ");
-        }
-        currCase.append(" } ");
+          if(refsAtParticularField.hasConflicts()) {
+            String childPtr = "((struct "+node.original.getType().getSafeSymbol()+" *)"+prefix +")->___" + field + "___";
+            printObjRefSwitchStatement(taint, cases, depth, currCase, refsAtParticularField, childPtr, currPtr);
+          }
+        }      
       }
+      
+      currCase.append("}\n"); //For particular top level case statement. 
+    }
+    if(qualifiesForCaseStatement(node)) {
+      currCase.append("  }\n  break;\n");
     }
-
-    if ((node.getNumOfReachableParents() != 1 || node.isInsetVar) && node.decendantsConflict())
-      currCase.append(" } break; \n");
   }
 
-  private void handleObjConflict(StringBuilder currCase, String childPtr, AllocSite allocSite) {
-    currCase.append("printf(\"Conflict detected with %p from parent with allocation site %u\\n\"," + childPtr + "," + allocSite.hashCodeSpecific() + ");");
+  private void printObjRefSwitchStatement(Taint taint, Hashtable<AllocSite, StringBuilder> cases,
+      int pDepth, StringBuilder currCase, ObjRefList refsAtParticularField, String childPtr,
+      String currPtr) {
+    
+    currCase.append("    "+currPtr+"= (struct ___Object___ * ) " + childPtr + ";\n");
+    currCase.append("    if (" + currPtr + " != NULL) { \n");
+    currCase.append("    switch(" + currPtr + getAllocSiteInC + ") {\n");
+    
+    for(ObjRef ref: refsAtParticularField) {
+      if(ref.child.decendantsConflict() || ref.child.hasPrimitiveConflicts()) {
+        currCase.append("      case "+ref.allocSite+":\n      {\n");
+        //The hash insert is here because we don't want to enqueue things unless we know it conflicts. 
+        currCase.append("        if (" + queryVistedHashtable +"("+ currPtr + ")) {\n");
+        
+        //Either it's an in-lineable case or we're just handling primitive conflicts
+        if ((ref.child.getNumOfReachableParents() == 1 && !ref.child.isInsetVar) ||
+            (ref.child.hasPrimitiveConflicts() && !qualifiesForCaseStatement(ref.child)))
+        {
+          addChecker(taint, ref.child, cases, currCase, currPtr, pDepth + 1);
+        }
+        else {
+          //if we are going to insert something into the queue, 
+          //we should be able to resume traverser from it. 
+          assert qualifiesForCaseStatement(ref.child);
+          currCase.append("        " + addToQueueInC + childPtr + ");\n ");
+        }
+        currCase.append("    }\n");  //close for queryVistedHashtable
+        
+        currCase.append("}\n"); //close for internal case statement
+      }
+    }
+    
+    currCase.append("    default:\n" +
+                           "       break;\n"+
+                           "    }}\n"); //internal switch. 
   }
   
-  private void handlePrimitiveConflict(StringBuilder currCase, String ptr, ArrayList<String> conflicts, AllocSite allocSite) {
-    currCase.append("printf(\"Primitive Conflict detected with %p with alloc site %u\\n\", "+ptr+", "+allocSite.hashCodeSpecific()+"); ");
+  private boolean qualifiesForCaseStatement(ConcreteRuntimeObjNode node) {
+    return (          
+        //insetVariable case
+        (node.isInsetVar && (node.decendantsConflict() || node.hasPrimitiveConflicts())) ||
+        //non-inline-able code cases
+        (node.getNumOfReachableParents() != 1 && node.decendantsConflict()) ||
+        //Cases where resumes are possible
+        (node.hasPotentialToBeIncorrectDueToConflict) && node.decendantsObjConflict);
   }
-
-  private Taint getProperTaint(FlatSESEEnterNode rblock, VariableNode var,
+  
+  private Taint getProperTaintForFlatSESEEnterNode(FlatSESEEnterNode rblock, VariableNode var,
       Hashtable<Taint, Set<Effect>> effects) {
     Set<Taint> taints = effects.keySet();
-    
     for (Taint t : taints) {
       FlatSESEEnterNode sese = t.getSESE();
-      //Jim says that this case should never happen, but it may
-      if( sese == null ) {
-          System.out.println( "What should I do with a stall site taint? --Jim");
-      }
       if(sese != null && sese.equals(rblock) && t.getVar().equals(var.getTempDescriptor())) {
         return t;
       }
     }
     return null;
   }
+  
+  
+  private Taint getProperTaintForEnterNode(FlatNode stallSite, VariableNode var,
+      Hashtable<Taint, Set<Effect>> effects) {
+    Set<Taint> taints = effects.keySet();
+    for (Taint t : taints) {
+      FlatNode flatnode = t.getStallSite();
+      if(flatnode != null && flatnode.equals(stallSite) && t.getVar().equals(var.getTempDescriptor())) {
+        return t;
+      }
+    }
+    return null;
+  }
 
-  private class EffectsGroup
-  {
-    Hashtable<String, EffectPair> myEffects;
-    ArrayList<String> primativeConflictingFields;
+  private void printDebug(boolean guard, String debugStatements) {
+    if(guard)
+      System.out.println(debugStatements);
+  }
+  
+  private void enumerateHeaproots() {
+    weaklyConnectedHRCounter = 0;
+    num2WeaklyConnectedHRGroup = new ArrayList<WeaklyConectedHRGroup>();
+    
+    for(Taint t: connectedHRHash.keySet()) {
+      if(connectedHRHash.get(t).id == -1) {
+        WeaklyConectedHRGroup hg = connectedHRHash.get(t);
+        hg.id = weaklyConnectedHRCounter;
+        num2WeaklyConnectedHRGroup.add(weaklyConnectedHRCounter, hg);
+        weaklyConnectedHRCounter++;
+      }
+    }
+  }
+  
+  private void printoutTable(EffectsTable table) {
+    
+    System.out.println("==============EFFECTS TABLE PRINTOUT==============");
+    for(AllocSite as: table.table.keySet()) {
+      System.out.println("\tFor AllocSite " + as.getUniqueAllocSiteID());
+      
+      BucketOfEffects boe = table.table.get(as);
+      
+      if(boe.potentiallyConflictingRoots != null && !boe.potentiallyConflictingRoots.isEmpty()) {
+        System.out.println("\t\tPotentially conflicting roots: ");
+        for(String key: boe.potentiallyConflictingRoots.keySet()) {
+          System.out.println("\t\t-Field: " + key);
+          System.out.println("\t\t\t" + boe.potentiallyConflictingRoots.get(key));
+        }
+      }
+      for(Taint t: boe.taint2EffectsGroup.keySet()) {
+        System.out.println("\t\t For Taint " + t);
+        EffectsGroup eg = boe.taint2EffectsGroup.get(t);
+          
+        if(eg.hasPrimitiveConflicts()) {
+          System.out.print("\t\t\tPrimitive Conflicts at alloc " + as.getUniqueAllocSiteID() +" : ");
+          for(String field: eg.primitiveConflictingFields.keySet()) {
+            System.out.print(field + " ");
+          }
+          System.out.println();
+        }
+        for(String fieldKey: eg.myEffects.keySet()) {
+          CombinedObjEffects ce = eg.myEffects.get(fieldKey);
+          System.out.println("\n\t\t\tFor allocSite " + as.getUniqueAllocSiteID() + " && field " + fieldKey);
+          System.out.println("\t\t\t\tread " + ce.hasReadEffect + "/"+ce.hasReadConflict + 
+              " write " + ce.hasWriteEffect + "/" + ce.hasWriteConflict + 
+              " SU " + ce.hasStrongUpdateEffect + "/" + ce.hasStrongUpdateConflict);
+          for(Effect ef: ce.originalEffects) {
+            System.out.println("\t" + ef);
+          }
+        }
+      }
+        
+    }
+    
+  }
+  
+  private class EffectsGroup {
+    Hashtable<String, CombinedObjEffects> myEffects;
+    Hashtable<String, CombinedObjEffects> primitiveConflictingFields;
     
     public EffectsGroup() {
-      myEffects = new Hashtable<String, EffectPair>();
-      primativeConflictingFields = new ArrayList<String>();
+      myEffects = new Hashtable<String, CombinedObjEffects>();
+      primitiveConflictingFields = new Hashtable<String, CombinedObjEffects>();
     }
 
-    public void addPrimative(Effect e) {
-      primativeConflictingFields.add(e.getField().toPrettyStringBrief());
+    public void addPrimitive(Effect e, boolean conflict) {
+      CombinedObjEffects effects;
+      if((effects = primitiveConflictingFields.get(e.getField().getSymbol())) == null) {
+        effects = new CombinedObjEffects();
+        primitiveConflictingFields.put(e.getField().getSymbol(), effects);
+      }
+      effects.add(e, conflict);
     }
     
-    public void addObj(Effect e, boolean conflict) {
-      EffectPair effect = new EffectPair(e, conflict);
-      myEffects.put(e.getField().getSymbol(), effect);
+    public void addObjEffect(Effect e, boolean conflict) {
+      CombinedObjEffects effects;
+      if((effects = myEffects.get(e.getField().getSymbol())) == null) {
+        effects = new CombinedObjEffects();
+        myEffects.put(e.getField().getSymbol(), effects);
+      }
+      effects.add(e, conflict);
     }
     
     public boolean isEmpty() {
-      return myEffects.isEmpty() && primativeConflictingFields.isEmpty();
+      return myEffects.isEmpty() && primitiveConflictingFields.isEmpty();
     }
     
-    public boolean hasPrimativeConflicts(){
-      return !primativeConflictingFields.isEmpty();
+    public boolean hasPrimitiveConflicts(){
+      return !primitiveConflictingFields.isEmpty();
     }
     
-    public boolean hasObjectConflicts() {
+    public CombinedObjEffects getPrimEffect(String field) {
+      return primitiveConflictingFields.get(field);
+    }
+
+    public boolean hasObjectEffects() {
       return !myEffects.isEmpty();
     }
     
-    public EffectPair getObjEffect(String field) {
+    public CombinedObjEffects getObjEffect(String field) {
       return myEffects.get(field);
     }
   }
   
-  private class EffectPair {
-    Effect originalEffect;
-    int type;
-    boolean conflict;
-
-    public EffectPair(Effect e, boolean conflict) {
-      originalEffect = e;
-      type = e.getType();
-      this.conflict = conflict;
-    }
-
-    public int hashCode() {
-      return originalEffect.hashCode();
+  //Is the combined effects for all effects with the same affectedAllocSite and field
+  private class CombinedObjEffects {
+    ArrayList<Effect> originalEffects;
+    
+    public boolean hasReadEffect;
+    public boolean hasWriteEffect;
+    public boolean hasStrongUpdateEffect;
+    
+    public boolean hasReadConflict;
+    public boolean hasWriteConflict;
+    public boolean hasStrongUpdateConflict;
+    
+    
+    public CombinedObjEffects() {
+      originalEffects = new ArrayList<Effect>();
+      
+      hasReadEffect = false;
+      hasWriteEffect = false;
+      hasStrongUpdateEffect = false;
+      
+      hasReadConflict = false;
+      hasWriteConflict = false;
+      hasStrongUpdateConflict = false;
     }
-
-    public boolean equals(Object o) {
-      if (o == null)
-        return false;
-
-      if (!(o instanceof EffectPair))
+    
+    public boolean add(Effect e, boolean conflict) {
+      if(!originalEffects.add(e))
         return false;
-
-      EffectPair other = (EffectPair) o;
-
-      return (other.originalEffect.getAffectedAllocSite().equals(
-          originalEffect.getAffectedAllocSite()) && other.originalEffect.getField().equals(
-          originalEffect.getField()));
+      
+      switch(e.getType()) {
+      case Effect.read:
+        hasReadEffect = true;
+        hasReadConflict = conflict;
+        break;
+      case Effect.write:
+        hasWriteEffect = true;
+        hasWriteConflict = conflict;
+        break;
+      case Effect.strongupdate:
+        hasStrongUpdateEffect = true;
+        hasStrongUpdateConflict = conflict;
+        break;
+      default:
+        System.out.println("RCR ERROR: An Effect Type never seen before has been encountered");
+        assert false;
+        break;
+      }
+      return true;
     }
     
-    public String toString()
-    {
-      return originalEffect.toString();
+    public boolean hasConflict() {
+      return hasReadConflict || hasWriteConflict || hasStrongUpdateConflict;
+    }
+
+    public void mergeWith(CombinedObjEffects other) {
+      for(Effect e: other.originalEffects) {
+        if(!originalEffects.contains(e)){
+          originalEffects.add(e);
+        }
+      }
+      
+      hasReadEffect |= other.hasReadEffect;
+      hasWriteEffect |= other.hasWriteEffect;
+      hasStrongUpdateEffect |= other.hasStrongUpdateEffect;
+      
+      hasReadConflict |= other.hasReadConflict;
+      hasWriteConflict |= other.hasWriteConflict;
+      hasStrongUpdateConflict |= other.hasStrongUpdateConflict;
     }
   }
 
+  //This will keep track of a reference
   private class ObjRef {
     String field;
     int allocSite;
+    CombinedObjEffects myEffects;
+    
     //This keeps track of the parent that we need to pass by inorder to get
     //to the conflicting child (if there is one). 
-    ConcreteRuntimeObjNode parentPathToMe;
     ConcreteRuntimeObjNode child;
 
     public ObjRef(String fieldname, 
                   ConcreteRuntimeObjNode ref, 
-                  boolean con, 
-                  ConcreteRuntimeObjNode grandParent) {
+                  CombinedObjEffects myEffects) {
       field = fieldname;
       allocSite = ref.getAllocationSite();
       child = ref;
-      parentPathToMe = con ? grandParent : null;
+      
+      this.myEffects = myEffects;
+    }
+    
+    public boolean hasConflictsDownThisPath() {
+      return child.decendantsObjConflict || child.decendantsPrimConflict || child.hasPrimitiveConflicts() || myEffects.hasConflict(); 
+    }
+    
+    public boolean hasDirectObjConflict() {
+      return myEffects.hasConflict();
     }
     
-    public boolean hasConflictsDownThisPath(ConcreteRuntimeObjNode curr) {
-      if(!child.hasConflicts())
+    public boolean equals(Object other) {
+      if(other == null || !(other instanceof ObjRef)) 
         return false;
       
-      if(curr.conflictingParents.isEmpty() && curr.isInsetVar)
-        return true;
+      ObjRef o = (ObjRef) other;
       
-      for(ConcreteRuntimeObjNode parent: curr.conflictingParents)
-        // we can do a == since it will LITTERALLY be the same object. 
-        if(parent == parentPathToMe)
-          return true;
+      if(o.field == this.field && o.allocSite == this.allocSite && this.child.equals(o.child))
+        return true;
       
       return false;
     }
+    
+    public int hashCode() {
+      return child.allocSite.hashCode() ^ field.hashCode();
+    }
+
+    public void mergeWith(ObjRef ref) {
+      myEffects.mergeWith(ref.myEffects);
+    }
   }
 
   private class ConcreteRuntimeObjNode {
-    ArrayList<ObjRef> objectRefs;
-    ArrayList<String> primativeFields;
-    ArrayList<ConcreteRuntimeObjNode> parents;
-    HashSet<ConcreteRuntimeObjNode> conflictingParents;
-    ConcreteRuntimeObjNode lastReferencer;
+    Hashtable<String, ObjRefList> objectRefs;
+    Hashtable<String, CombinedObjEffects> primitiveConflictingFields;
+    HashSet<ConcreteRuntimeObjNode> parentsWithReadToNode;
+    HashSet<ConcreteRuntimeObjNode> parentsThatWillLeadToConflicts;
+    //this set keeps track of references down the line that need to be enqueued if traverser is "paused"
+    HashSet<ConcreteRuntimeObjNode> enqueueToWaitingQueueUponConflict;
     boolean decendantsPrimConflict;
     boolean decendantsObjConflict;
+    boolean hasPotentialToBeIncorrectDueToConflict;
     boolean isInsetVar;
     AllocSite allocSite;
     HeapRegionNode original;
 
     public ConcreteRuntimeObjNode(HeapRegionNode me, boolean isInVar) {
-      objectRefs = new ArrayList<ObjRef>();
-      parents = new ArrayList<ConcreteRuntimeObjNode>();
-      conflictingParents = new HashSet<ConcreteRuntimeObjNode>();
-      lastReferencer = null;
+      objectRefs = new Hashtable<String, ObjRefList>(5);
+      primitiveConflictingFields = null;
+      parentsThatWillLeadToConflicts = new HashSet<ConcreteRuntimeObjNode>();
+      parentsWithReadToNode = new HashSet<ConcreteRuntimeObjNode>();
+      enqueueToWaitingQueueUponConflict = new HashSet<ConcreteRuntimeObjNode>();
       allocSite = me.getAllocSite();
       original = me;
       isInsetVar = isInVar;
       decendantsPrimConflict = false;
       decendantsObjConflict = false;
-      primativeFields = null;
+      hasPotentialToBeIncorrectDueToConflict = false;
     }
 
-    @Override
-    public int hashCode() {
-      // This gets allocsite number
-      return allocSite.hashCodeSpecific();
+    public void addReachableParent(ConcreteRuntimeObjNode curr) {
+      parentsWithReadToNode.add(curr);
     }
 
     @Override
-    public boolean equals(Object obj) {
-      return original.equals(obj);
+    public boolean equals(Object other) {
+      if(other == null || !(other instanceof ConcreteRuntimeObjNode)) 
+        return false;
+      
+      return original.equals(((ConcreteRuntimeObjNode)other).original);
     }
 
     public int getAllocationSite() {
-      return allocSite.hashCodeSpecific();
+      return allocSite.getUniqueAllocSiteID();
     }
 
     public int getNumOfReachableParents() {
-      return conflictingParents.size();
+      return parentsThatWillLeadToConflicts.size();
     }
     
-    public boolean hasPrimativeConflicts() {
-      return primativeFields != null;
-    }
-    
-    public boolean hasConflicts() {
-      return (primativeFields != null) || !conflictingParents.isEmpty();
+    public boolean hasPrimitiveConflicts() {
+      return primitiveConflictingFields != null && !primitiveConflictingFields.isEmpty();
     }
     
     public boolean decendantsConflict() {
       return decendantsPrimConflict || decendantsObjConflict;
     }
+    
+    
+    //returns true if at least one of the objects in points of access has been added
+    public boolean addPossibleWaitingQueueEnqueue(HashSet<ConcreteRuntimeObjNode> pointsOfAccess) {
+      boolean addedNew = false;
+      for(ConcreteRuntimeObjNode dec: pointsOfAccess) {
+        if(dec != null && dec != this){
+          addedNew = addedNew || enqueueToWaitingQueueUponConflict.add(dec);
+        }
+      }
+      
+      return addedNew;
+    }
+    
+    public boolean addPossibleWaitingQueueEnqueue(ConcreteRuntimeObjNode pointOfAccess) {
+      if(pointOfAccess != null && pointOfAccess != this){
+        return enqueueToWaitingQueueUponConflict.add(pointOfAccess);
+      }
+      
+      return false;
+    }
 
-    public void addObjChild(String field, ConcreteRuntimeObjNode child, boolean conflict) {
-      child.lastReferencer = this;
-      ObjRef ref = new ObjRef(field, child, conflict, this.lastReferencer);
-      objectRefs.add(ref);
-      child.parents.add(this);
+    public void addObjChild(String field, ConcreteRuntimeObjNode child, CombinedObjEffects ce) {
+      printDebug(javaDebug,this.allocSite.getUniqueAllocSiteID() + " added child at " + child.getAllocationSite());
+      ObjRef ref = new ObjRef(field, child, ce);
+      
+      if(objectRefs.containsKey(field)){
+        ObjRefList array = objectRefs.get(field);
+        
+        if(array.contains(ref)) {
+          ObjRef other = array.get(array.indexOf(ref));
+          other.mergeWith(ref);
+          printDebug(javaDebug,"    Merged with old");
+          printDebug(javaDebug,"    Old="+ other.child.original + "\n    new="+ref.child.original);
+        }
+        else {
+          array.add(ref);
+          printDebug(javaDebug,"    Just added new;\n      Field: " + field);
+          printDebug(javaDebug,"      AllocSite: " + child.getAllocationSite());
+          printDebug(javaDebug,"      Child: "+child.original);
+        }
+      }
+      else {
+        ObjRefList array = new ObjRefList(3);
+        
+        array.add(ref);
+        objectRefs.put(field, array);
+      }
+    }
+    
+    public boolean isArray() {
+      return original.getType().isArray();
     }
     
-    public String toString()
-    {
-      return "AllocSite=" + getAllocationSite() + " myConflict=" + !conflictingParents.isEmpty() + 
-              " decCon="+decendantsObjConflict+ " NumOfParents=" + parents.size()+ 
+    public ArrayList<Integer> getReferencedAllocSites() {
+      ArrayList<Integer> list = new ArrayList<Integer>();
+      
+      for(String key: objectRefs.keySet()) {
+        for(ObjRef r: objectRefs.get(key)) {
+          if(r.hasDirectObjConflict() || (r.child.parentsWithReadToNode.contains(this) && r.hasConflictsDownThisPath())) {
+            list.add(r.allocSite);
+          }
+        }
+      }
+      
+      return list;
+    }
+    
+    public String toString() {
+      return "AllocSite=" + getAllocationSite() + " myConflict=" + !parentsThatWillLeadToConflicts.isEmpty() + 
+              " decCon="+decendantsObjConflict+ 
               " NumOfConParents=" + getNumOfReachableParents() + " ObjectChildren=" + objectRefs.size();
     }
   }
+  
+  //Simple extension of the ArrayList to allow it to find if any ObjRefs conflict.
+  private class ObjRefList extends ArrayList<ObjRef> {
+    private static final long serialVersionUID = 326523675530835596L;
+    
+    public ObjRefList(int size) {
+      super(size);
+    }
+    
+    public boolean add(ObjRef o){
+      return super.add(o);
+    }
+    
+    public boolean hasConflicts() {
+      for(ObjRef r: this) {
+        if(r.hasConflictsDownThisPath() || r.child.hasPrimitiveConflicts())
+          return true;
+      }
+      
+      return false;
+    }
+  }
+  
+  private class EffectsTable {
+    private Hashtable<AllocSite, BucketOfEffects> table;
+
+    public EffectsTable(Hashtable<Taint, Set<Effect>> effects,
+        Hashtable<Taint, Set<Effect>> conflicts) {
+      table = new Hashtable<AllocSite, BucketOfEffects>();
+
+      // rehash all effects (as a 5-tuple) by their affected allocation site
+      for (Taint t : effects.keySet()) {
+        Set<Effect> localConflicts = conflicts.get(t);
+        for (Effect e : effects.get(t)) {
+          BucketOfEffects bucket;
+          if ((bucket = table.get(e.getAffectedAllocSite())) == null) {
+            bucket = new BucketOfEffects();
+            table.put(e.getAffectedAllocSite(), bucket);
+          }
+          printDebug(javaDebug, "Added Taint" + t + " Effect " + e + "Conflict Status = " + (localConflicts!=null?localConflicts.contains(e):false)+" localConflicts = "+localConflicts);
+          bucket.add(t, e, localConflicts!=null?localConflicts.contains(e):false);
+        }
+      }
+    }
+
+    public EffectsGroup getEffects(AllocSite parentKey, Taint taint) {
+      //This would get the proper bucket of effects and then get all the effects
+      //for a parent for a specific taint
+      try {
+        return table.get(parentKey).taint2EffectsGroup.get(taint);
+      }
+      catch (NullPointerException e) {
+        return null;
+      }
+    }
+
+    // Run Analysis will walk the data structure and figure out the weakly
+    // connected heap roots. 
+    public void runAnalysis() {
+      if(javaDebug) {
+        printoutTable(this); 
+      }
+      
+      for(AllocSite key: table.keySet()) {
+        BucketOfEffects effects = table.get(key);
+        //make sure there are actually conflicts in the bucket
+        if(effects.potentiallyConflictingRoots != null && !effects.potentiallyConflictingRoots.isEmpty()){
+          for(String field: effects.potentiallyConflictingRoots.keySet()){
+            ArrayList<Taint> taints = effects.potentiallyConflictingRoots.get(field);
+            //For simplicity, we just create a new group and add everything to it instead of
+            //searching through all of them for the largest group and adding everyone in. 
+            WeaklyConectedHRGroup group = new WeaklyConectedHRGroup();
+            group.add(taints); //This will automatically add the taint to the connectedHRhash
+          }
+        }
+      }
+    }
+  }
+  
+  private class WeaklyConectedHRGroup {
+    HashSet<Taint> connectedHRs;
+    //This is to keep track of unique waitingQueue positions for each allocsite. 
+    Hashtable<AllocSite, Integer> allocSiteToWaitingQueueMap;
+    int waitingQueueCounter;
+    int id;
+    
+    public WeaklyConectedHRGroup() {
+      connectedHRs = new HashSet<Taint>();
+      id = -1; //this will be later modified
+      waitingQueueCounter = 0;
+      allocSiteToWaitingQueueMap = new Hashtable<AllocSite, Integer>();
+    }
+    
+    public void add(ArrayList<Taint> list) {
+      for(Taint t: list) {
+        this.add(t);
+      }
+    }
+    
+    public int getWaitingQueueBucketNum(ConcreteRuntimeObjNode node) {
+      if(allocSiteToWaitingQueueMap.containsKey(node.allocSite)) {
+        return allocSiteToWaitingQueueMap.get(node.allocSite);
+      } else {
+        allocSiteToWaitingQueueMap.put(node.allocSite, waitingQueueCounter);
+        return waitingQueueCounter++;
+      }
+    }
+    
+    public void add(Taint t) {
+      connectedHRs.add(t);
+      WeaklyConectedHRGroup oldGroup = connectedHRHash.get(t);
+      connectedHRHash.put(t, this); //put new group into hash
+      //If the taint was already in another group, move all its buddies over. 
+      if(oldGroup != this && oldGroup != null) {
+        Iterator<Taint> it = oldGroup.connectedHRs.iterator();
+        Taint relatedTaint;
+        
+        while((relatedTaint = it.next()) != null && !connectedHRs.contains(relatedTaint)) {
+          this.add(relatedTaint);
+        }
+      }
+    }
+  }
+  
+  //This is a class that stores all the effects for an affected allocation site
+  //across ALL taints. The structure is a hashtable of EffectGroups (see above) hashed
+  //by a Taint. This way, I can keep EffectsGroups so I can reuse most to all of my old code
+  //and allows for easier tracking of effects. In addition, a hashtable (keyed by the string
+  //of the field access) keeps track of an ArrayList of taints of SESEblocks that conflict on that
+  //field.
+  private class BucketOfEffects {
+    // This table is used for lookup while creating the traversal.
+    Hashtable<Taint, EffectsGroup> taint2EffectsGroup;
+    
+    //This table is used to help identify weakly connected groups: Contains ONLY 
+    //conflicting effects AND is only initialized when needed
+    //String stores the field
+    Hashtable<String, ArrayList<Taint>> potentiallyConflictingRoots;
+
+    public BucketOfEffects() {
+      taint2EffectsGroup = new Hashtable<Taint, EffectsGroup>();
+    }
+
+    public void add(Taint t, Effect e, boolean conflict) {
+      EffectsGroup effectsForGivenTaint;
+
+      if ((effectsForGivenTaint = taint2EffectsGroup.get(t)) == null) {
+        effectsForGivenTaint = new EffectsGroup();
+        taint2EffectsGroup.put(t, effectsForGivenTaint);
+      }
+
+      if (isReallyAPrimitive(e.getField().getType())) {
+        if (conflict) {
+          effectsForGivenTaint.addPrimitive(e, true);
+        }
+      } else {
+        effectsForGivenTaint.addObjEffect(e, conflict);
+      }
+      
+      if(conflict) {
+        if(potentiallyConflictingRoots == null) {
+          potentiallyConflictingRoots = new Hashtable<String, ArrayList<Taint>>();
+        }
+        
+        ArrayList<Taint> taintsForField = potentiallyConflictingRoots.get(e.getField().getSafeSymbol());
+        if(taintsForField == null) {
+          taintsForField = new ArrayList<Taint>();
+          potentiallyConflictingRoots.put(e.getField().getSafeSymbol(), taintsForField);
+        }
+        
+        if(!taintsForField.contains(t)) {
+          taintsForField.add(t);
+        }
+      }
+    }
+  }
+  
+  private class TaintAndInternalHeapStructure {
+    public Taint t;
+    public Hashtable<Integer, ConcreteRuntimeObjNode> nodesInHeap;
+    
+    public TaintAndInternalHeapStructure(Taint taint, Hashtable<Integer, ConcreteRuntimeObjNode> nodesInHeap) {
+      t = taint;
+      this.nodesInHeap = nodesInHeap;
+    }
+  }
+  
+  private class TraversalInfo {
+    public FlatNode f;
+    public ReachGraph rg;
+    public TempDescriptor invar;
+    
+    public TraversalInfo(FlatNode fn, ReachGraph g) {
+      f = fn;
+      rg =g;
+      invar = null;
+    }
+
+    public TraversalInfo(FlatNode fn, ReachGraph rg2, TempDescriptor tempDesc) {
+      f = fn;
+      rg =rg2;
+      invar = tempDesc;
+    }
+  }
 }