more changes...RCR wasn't usable until it was too late...
[IRC.git] / Robust / src / Analysis / OoOJava / OoOJavaAnalysis.java
index 0c7707d362a72e5330bbd4c8b23a08247c22b7e6..9ec6c2d608fb1cadcd428cb1928302a84ab1230e 100644 (file)
@@ -1,10 +1,13 @@
 package Analysis.OoOJava;
 
+import java.io.BufferedWriter;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 import java.util.Stack;
 import java.util.Map.Entry;
@@ -16,20 +19,28 @@ import Analysis.Disjoint.DisjointAnalysis;
 import Analysis.Disjoint.Effect;
 import Analysis.Disjoint.EffectsAnalysis;
 import Analysis.Disjoint.Taint;
+import Analysis.MLP.CodePlan;
+import Analysis.MLP.SESEandAgePair;
+import Analysis.MLP.VSTWrapper;
+import Analysis.MLP.VarSrcTokTable;
+import Analysis.MLP.VariableSourceToken;
 import IR.Descriptor;
 import IR.MethodDescriptor;
 import IR.Operation;
 import IR.State;
 import IR.TypeUtil;
 import IR.Flat.FKind;
+import IR.Flat.FlatCall;
 import IR.Flat.FlatEdge;
+import IR.Flat.FlatElementNode;
 import IR.Flat.FlatFieldNode;
 import IR.Flat.FlatMethod;
+import IR.Flat.FlatNew;
 import IR.Flat.FlatNode;
 import IR.Flat.FlatOpNode;
-import IR.Flat.FlatNew;
 import IR.Flat.FlatSESEEnterNode;
 import IR.Flat.FlatSESEExitNode;
+import IR.Flat.FlatSetElementNode;
 import IR.Flat.FlatSetFieldNode;
 import IR.Flat.FlatWriteDynamicVarNode;
 import IR.Flat.TempDescriptor;
@@ -55,22 +66,13 @@ public class OoOJavaAnalysis {
 
   private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
 
-  // temporal data structures to track analysis progress. 
-  static private int uniqueLockSetId = 0;  
+  // temporal data structures to track analysis progress.
+  static private int uniqueLockSetId = 0;
   // mapping of a conflict graph to its compiled lock
   private Hashtable<ConflictGraph, HashSet<SESELock>> conflictGraph2SESELock;
   // mapping of a sese block to its conflict graph
   private Hashtable<FlatNode, ConflictGraph> sese2conflictGraph;
 
-
-  
-
-  // private Hashtable<FlatNode, ParentChildConflictsMap> conflictsResults;
-  // private Hashtable<FlatMethod, MethodSummary> methodSummaryResults;
-  // private OwnershipAnalysis ownAnalysisForSESEConflicts;
-
-  // static private int uniqueLockSetId = 0;
-
   public static int maxSESEage = -1;
 
   public int getMaxSESEage() {
@@ -83,6 +85,10 @@ public class OoOJavaAnalysis {
     return cp;
   }
 
+  public Set<FlatNode> getNodesWithPlans() {
+    return codePlans.keySet();
+  }
+
   public OoOJavaAnalysis(State state, TypeUtil typeUtil, CallGraph callGraph, Liveness liveness,
       ArrayReferencees arrayReferencees) {
 
@@ -114,20 +120,10 @@ public class OoOJavaAnalysis {
 
     descriptorsToAnalyze.add(mdSourceEntry);
 
-    // conflictsResults = new Hashtable<FlatNode, ParentChildConflictsMap>();
-    // methodSummaryResults = new Hashtable<FlatMethod, MethodSummary>();
-    // conflictGraphResults = new Hashtable<FlatNode, ConflictGraph>();
-
-    // seseSummaryMap = new Hashtable<FlatNode, SESESummary>();
-    // isAfterChildSESEIndicatorMap = new Hashtable<FlatNode, Boolean>();
-    // conflictGraphLockMap = new Hashtable<ConflictGraph, HashSet<SESELock>>();
-
-    // 1st pass, find basic rblock relations
+    // 1st pass, find basic rblock relations & status
     rblockRel = new RBlockRelationAnalysis(state, typeUtil, callGraph);
-    
     rblockStatus = new RBlockStatusAnalysis(state, typeUtil, callGraph, rblockRel);
 
-
     // 2nd pass, liveness, in-set out-set (no virtual reads yet!)
     Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
     while (rootItr.hasNext()) {
@@ -156,16 +152,10 @@ public class OoOJavaAnalysis {
 
     // 5th pass, use disjointness with NO FLAGGED REGIONS
     // to compute taints and effects
-    disjointAnalysisTaints = 
-      new DisjointAnalysis(state, 
-                           typeUtil, 
-                           callGraph, 
-                           liveness,
-                           arrayReferencees, 
-                           null, // no FlatNew set to flag
-                           rblockRel, 
-                           rblockStatus
-                           );
+    disjointAnalysisTaints =
+        new DisjointAnalysis(state, typeUtil, callGraph, liveness, arrayReferencees, null, 
+                             rblockRel, rblockStatus,
+                             true ); // suppress output--this is an intermediate pass
 
     // 6th pass, not available analysis FOR VARIABLES!
     methItr = descriptorsToAnalyze.iterator();
@@ -178,60 +168,98 @@ public class OoOJavaAnalysis {
       notAvailableForward(fm);
     }
 
-    // 7th pass,  make conflict graph
+    // 7th pass, make conflict graph
     // conflict graph is maintained by each parent sese,
-    // and while making the graph identify set of FlatNew
-    // that next disjoint reach. analysis should flag
+    Iterator descItr = disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
+    while (descItr.hasNext()) {
+      Descriptor d = (Descriptor) descItr.next();
+      FlatMethod fm = state.getMethodFlat(d);
+      if (fm != null)
+        makeConflictGraph(fm);
+    }
+
+    // debug routine
+    /*
+     * Iterator iter = sese2conflictGraph.entrySet().iterator(); while
+     * (iter.hasNext()) { Entry e = (Entry) iter.next(); FlatNode fn =
+     * (FlatNode) e.getKey(); ConflictGraph conflictGraph = (ConflictGraph)
+     * e.getValue();
+     * System.out.println("---------------------------------------");
+     * System.out.println("CONFLICT GRAPH for " + fn); Set<String> keySet =
+     * conflictGraph.id2cn.keySet(); for (Iterator iterator = keySet.iterator();
+     * iterator.hasNext();) { String key = (String) iterator.next();
+     * ConflictNode node = conflictGraph.id2cn.get(key);
+     * System.out.println("key=" + key + " \n" + node.toStringAllEffects()); } }
+     */
+
+    // 8th pass, calculate all possible conflicts without using reachability
+    // info
+    // and identify set of FlatNew that next disjoint reach. analysis should
+    // flag
     Set<FlatNew> sitesToFlag = new HashSet<FlatNew>();
-    
+    calculateConflicts(sitesToFlag, false);
+
+
+    if (!state.RCR) {
+      // 9th pass, ask disjoint analysis to compute reachability
+      // for objects that may cause heap conflicts so the most
+      // efficient method to deal with conflict can be computed
+      // later
+      
+      disjointAnalysisReach =
+        new DisjointAnalysis(state, typeUtil, callGraph, liveness, arrayReferencees, sitesToFlag,
+                            null, // don't do effects analysis again!
+                            null // don't do effects analysis again!
+                            );
+      // 10th pass, calculate conflicts with reachability info
+      calculateConflicts(null, true);
+    }
+    // 11th pass, compiling locks
+    synthesizeLocks();
+
+    // 12th pass, compute a plan for code injections
     methItr = descriptorsToAnalyze.iterator();
     while (methItr.hasNext()) {
       Descriptor d = methItr.next();
       FlatMethod fm = state.getMethodFlat(d);
-      makeConflictGraph(fm, sitesToFlag);
+      codePlansForward(fm);
     }
 
-    // debug routine 
-    Iterator iter = sese2conflictGraph.entrySet().iterator();
-    while (iter.hasNext()) {
-      Entry e = (Entry) iter.next();
-      FlatNode fn = (FlatNode) e.getKey();
-      ConflictGraph conflictGraph = (ConflictGraph) e.getValue();
-      System.out.println("CONFLICT GRAPH for " + fn);
-      Set<String> keySet = conflictGraph.id2cn.keySet();
-      for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
-        String key = (String) iterator.next();
-        ConflictNode node = conflictGraph.id2cn.get(key);
-        System.out.println("key=" + key + " --\n" + node.toString());
+    // 13th pass,
+    // splice new IR nodes into graph after all
+    // analysis passes are complete
+    Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
+    while (spliceItr.hasNext()) {
+      Map.Entry me = (Map.Entry) spliceItr.next();
+      FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
+      fwdvn.spliceIntoIR();
+    }
+
+    if (state.OOODEBUG) {
+      try {
+        writeReports("");
+        disjointAnalysisTaints.getEffectsAnalysis().writeEffects("effects.txt");
+        writeConflictGraph();
+      } catch (IOException e) {
       }
     }
-    
-    // 8th pass, ask disjoint analysis to compute reachability
-    // for objects that may cause heap conflicts so the most
-    // efficient method to deal with conflict can be computed
-    // later
-    disjointAnalysisReach = 
-      new DisjointAnalysis(state, 
-                           typeUtil, 
-                           callGraph, 
-                           liveness,
-                           arrayReferencees, 
-                           sitesToFlag,
-                           null, // don't do effects analysis again!
-                           null  // don't do effects analysis again!
-                           );
-
-    // 9th pass, calculate conflicts
-    //calculateConflicts();
-    
-    /*
-    // #th pass, compiling locks
-    synthesizeLocks();
 
-    // #th pass, writing conflict graph
-    writeConflictGraph();
-    */
-    
+  }
+
+  private void writeFile(Set<FlatNew> sitesToFlag) {
+
+    try {
+      BufferedWriter bw = new BufferedWriter(new FileWriter("sitesToFlag.txt"));
+
+      for (Iterator iterator = sitesToFlag.iterator(); iterator.hasNext();) {
+        FlatNew fn = (FlatNew) iterator.next();
+        bw.write(fn + "\n");
+      }
+      bw.close();
+    } catch (IOException e) {
+
+    }
+
   }
 
   private void livenessAnalysisBackward(FlatSESEEnterNode fsen, boolean toplevel,
@@ -249,7 +277,8 @@ public class OoOJavaAnalysis {
       flatNodesToVisit.add(fsen.getFlatExit());
     }
 
-    Hashtable<FlatNode, Set<TempDescriptor>> livenessResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
+    Hashtable<FlatNode, Set<TempDescriptor>> livenessResults =
+        new Hashtable<FlatNode, Set<TempDescriptor>>();
 
     if (toplevel) {
       liveout = new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
@@ -421,8 +450,8 @@ public class OoOJavaAnalysis {
       // anything virtually read by this SESE should be pruned
       // of parent or sibling sources
       Set<TempDescriptor> liveVars = livenessRootView.get(fn);
-      Set<TempDescriptor> fsenVirtReads = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(
-          fsen, liveVars);
+      Set<TempDescriptor> fsenVirtReads =
+          vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(fsen, liveVars);
       Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
       if (fsenVirtReadsOld != null) {
         fsenVirtReads.addAll(fsenVirtReadsOld);
@@ -640,8 +669,8 @@ public class OoOJavaAnalysis {
 
           VariableSourceToken vst = vstIfStatic.vst;
 
-          Iterator<VariableSourceToken> availItr = vstTable.get(vst.getSESE(), vst.getAge())
-              .iterator();
+          Iterator<VariableSourceToken> availItr =
+              vstTable.get(vst.getSESE(), vst.getAge()).iterator();
 
           // look through things that are also available from same source
           while (availItr.hasNext()) {
@@ -654,8 +683,8 @@ public class OoOJavaAnalysis {
               // if a variable is available from the same source, AND it ALSO
               // only comes from one statically known source, mark it available
               VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
-              Integer srcTypeAlso = vstTable.getRefVarSrcType(refVarAlso, currentSESE,
-                  vstIfStaticNotUsed);
+              Integer srcTypeAlso =
+                  vstTable.getRefVarSrcType(refVarAlso, currentSESE, vstIfStaticNotUsed);
               if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
                 notAvailSet.remove(refVarAlso);
               }
@@ -669,7 +698,282 @@ public class OoOJavaAnalysis {
     } // end switch
   }
 
-  private void makeConflictGraph(FlatMethod fm, Set<FlatNew> sitesToFlag) {
+  private void codePlansForward(FlatMethod fm) {
+
+    // start from flat method top, visit every node in
+    // method exactly once
+    Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+    flatNodesToVisit.add(fm);
+
+    Set<FlatNode> visited = new HashSet<FlatNode>();
+
+    while (!flatNodesToVisit.isEmpty()) {
+      Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
+      FlatNode fn = fnItr.next();
+
+      flatNodesToVisit.remove(fn);
+      visited.add(fn);
+
+      Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
+      assert seseStack != null;
+
+      // use incoming results as "dot statement" or just
+      // before the current statement
+      VarSrcTokTable dotSTtable = new VarSrcTokTable();
+      for (int i = 0; i < fn.numPrev(); i++) {
+        FlatNode nn = fn.getPrev(i);
+        dotSTtable.merge(variableResults.get(nn));
+      }
+
+      // find dt-st notAvailableSet also
+      Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
+      for (int i = 0; i < fn.numPrev(); i++) {
+        FlatNode nn = fn.getPrev(i);
+        Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
+        if (notAvailIn != null) {
+          dotSTnotAvailSet.addAll(notAvailIn);
+        }
+      }
+
+      Set<TempDescriptor> dotSTlive = livenessRootView.get(fn);
+
+      if (!seseStack.empty()) {
+        codePlans_nodeActions(fn, dotSTlive, dotSTtable, dotSTnotAvailSet, seseStack.peek());
+      }
+
+      for (int i = 0; i < fn.numNext(); i++) {
+        FlatNode nn = fn.getNext(i);
+
+        if (!visited.contains(nn)) {
+          flatNodesToVisit.add(nn);
+        }
+      }
+    }
+  }
+
+  private void codePlans_nodeActions(FlatNode fn, Set<TempDescriptor> liveSetIn,
+      VarSrcTokTable vstTableIn, Set<TempDescriptor> notAvailSetIn, FlatSESEEnterNode currentSESE) {
+
+    CodePlan plan = new CodePlan(currentSESE);
+
+    switch (fn.kind()) {
+
+    case FKind.FlatSESEEnterNode: {
+      FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
+      assert fsen.equals(currentSESE);
+
+      // track the source types of the in-var set so generated
+      // code at this SESE issue can compute the number of
+      // dependencies properly
+      Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
+      while (inVarItr.hasNext()) {
+        TempDescriptor inVar = inVarItr.next();
+
+        // when we get to an SESE enter node we change the
+        // currentSESE variable of this analysis to the
+        // child that is declared by the enter node, so
+        // in order to classify in-vars correctly, pass
+        // the parent SESE in--at other FlatNode types just
+        // use the currentSESE
+        VSTWrapper vstIfStatic = new VSTWrapper();
+        Integer srcType = vstTableIn.getRefVarSrcType(inVar, fsen.getParent(), vstIfStatic);
+
+        // the current SESE needs a local space to track the dynamic
+        // variable and the child needs space in its SESE record
+        if (srcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
+          fsen.addDynamicInVar(inVar);
+          fsen.getParent().addDynamicVar(inVar);
+
+        } else if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
+          fsen.addStaticInVar(inVar);
+          VariableSourceToken vst = vstIfStatic.vst;
+          fsen.putStaticInVar2src(inVar, vst);
+          fsen.addStaticInVarSrc(new SESEandAgePair(vst.getSESE(), vst.getAge()));
+        } else {
+          assert srcType.equals(VarSrcTokTable.SrcType_READY);
+          fsen.addReadyInVar(inVar);
+        }
+      }
+
+    }
+      break;
+
+    case FKind.FlatSESEExitNode: {
+      FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
+    }
+      break;
+
+    case FKind.FlatOpNode: {
+      FlatOpNode fon = (FlatOpNode) fn;
+
+      if (fon.getOp().getOp() == Operation.ASSIGN) {
+        TempDescriptor lhs = fon.getDest();
+        TempDescriptor rhs = fon.getLeft();
+
+        // if this is an op node, don't stall, copy
+        // source and delay until we need to use value
+
+        // ask whether lhs and rhs sources are dynamic, static, etc.
+        VSTWrapper vstIfStatic = new VSTWrapper();
+        Integer lhsSrcType = vstTableIn.getRefVarSrcType(lhs, currentSESE, vstIfStatic);
+        Integer rhsSrcType = vstTableIn.getRefVarSrcType(rhs, currentSESE, vstIfStatic);
+
+        if (rhsSrcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
+          // if rhs is dynamic going in, lhs will definitely be dynamic
+          // going out of this node, so track that here
+          plan.addDynAssign(lhs, rhs);
+          currentSESE.addDynamicVar(lhs);
+          currentSESE.addDynamicVar(rhs);
+
+        } else if (lhsSrcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
+          // otherwise, if the lhs is dynamic, but the rhs is not, we
+          // need to update the variable's dynamic source as "current SESE"
+          plan.addDynAssign(lhs);
+        }
+
+        // only break if this is an ASSIGN op node,
+        // otherwise fall through to default case
+        break;
+      }
+    }
+
+      // note that FlatOpNode's that aren't ASSIGN
+      // fall through to this default case
+    default: {
+
+      // a node with no live set has nothing to stall for
+      if (liveSetIn == null) {
+        break;
+      }
+
+      TempDescriptor[] readarray = fn.readsTemps();
+      for (int i = 0; i < readarray.length; i++) {
+        TempDescriptor readtmp = readarray[i];
+
+        // ignore temps that are definitely available
+        // when considering to stall on it
+        if (!notAvailSetIn.contains(readtmp)) {
+          continue;
+        }
+
+        // check the source type of this variable
+        VSTWrapper vstIfStatic = new VSTWrapper();
+        Integer srcType = vstTableIn.getRefVarSrcType(readtmp, currentSESE, vstIfStatic);
+
+        if (srcType.equals(VarSrcTokTable.SrcType_DYNAMIC)) {
+          // 1) It is not clear statically where this variable will
+          // come from, so dynamically we must keep track
+          // along various control paths, and therefore when we stall,
+          // just stall for the exact thing we need and move on
+          plan.addDynamicStall(readtmp);
+          currentSESE.addDynamicVar(readtmp);
+
+        } else if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
+          // 2) Single token/age pair: Stall for token/age pair, and copy
+          // all live variables with same token/age pair at the same
+          // time. This is the same stuff that the notavaialable analysis
+          // marks as now available.
+          VariableSourceToken vst = vstIfStatic.vst;
+
+          Iterator<VariableSourceToken> availItr =
+              vstTableIn.get(vst.getSESE(), vst.getAge()).iterator();
+
+          while (availItr.hasNext()) {
+            VariableSourceToken vstAlsoAvail = availItr.next();
+
+            // only grab additional stuff that is live
+            Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
+
+            Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
+            while (refVarItr.hasNext()) {
+              TempDescriptor refVar = refVarItr.next();
+              if (liveSetIn.contains(refVar)) {
+                copySet.add(refVar);
+              }
+            }
+
+            if (!copySet.isEmpty()) {
+              plan.addStall2CopySet(vstAlsoAvail, copySet);
+            }
+          }
+
+        } else {
+          // the other case for srcs is READY, so do nothing
+        }
+
+        // assert that everything being stalled for is in the
+        // "not available" set coming into this flat node and
+        // that every VST identified is in the possible "stall set"
+        // that represents VST's from children SESE's
+
+      }
+    }
+      break;
+
+    } // end switch
+
+    // identify sese-age pairs that are statically useful
+    // and should have an associated SESE variable in code
+    // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
+    // AND ALWAYS GIVE NAMES TO PARENTS
+    Set<VariableSourceToken> staticSet = vstTableIn.get();
+    Iterator<VariableSourceToken> vstItr = staticSet.iterator();
+    while (vstItr.hasNext()) {
+      VariableSourceToken vst = vstItr.next();
+
+      // placeholder source tokens are useful results, but
+      // the placeholder static name is never needed
+      if (vst.getSESE().getIsCallerSESEplaceholder()) {
+        continue;
+      }
+
+      FlatSESEEnterNode sese = currentSESE;
+      while (sese != null) {
+        sese.addNeededStaticName(new SESEandAgePair(vst.getSESE(), vst.getAge()));
+        sese.mustTrackAtLeastAge(vst.getAge());
+
+        sese = sese.getParent();
+      }
+    }
+
+    codePlans.put(fn, plan);
+
+    // if any variables at this-node-*dot* have a static source (exactly one
+    // vst)
+    // but go to a dynamic source at next-node-*dot*, create a new IR graph
+    // node on that edge to track the sources dynamically
+    VarSrcTokTable thisVstTable = variableResults.get(fn);
+    for (int i = 0; i < fn.numNext(); i++) {
+      FlatNode nn = fn.getNext(i);
+      VarSrcTokTable nextVstTable = variableResults.get(nn);
+      Set<TempDescriptor> nextLiveIn = livenessRootView.get(nn);
+
+      // the table can be null if it is one of the few IR nodes
+      // completely outside of the root SESE scope
+      if (nextVstTable != null && nextLiveIn != null) {
+
+        Hashtable<TempDescriptor, VSTWrapper> readyOrStatic2dynamicSet =
+            thisVstTable.getReadyOrStatic2DynamicSet(nextVstTable, nextLiveIn, currentSESE);
+
+        if (!readyOrStatic2dynamicSet.isEmpty()) {
+
+          // either add these results to partial fixed-point result
+          // or make a new one if we haven't made any here yet
+          FlatEdge fe = new FlatEdge(fn, nn);
+          FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get(fe);
+
+          if (fwdvn == null) {
+            fwdvn = new FlatWriteDynamicVarNode(fn, nn, readyOrStatic2dynamicSet, currentSESE);
+            wdvNodesToSpliceIn.put(fe, fwdvn);
+          } else {
+            fwdvn.addMoreVar2Src(readyOrStatic2dynamicSet);
+          }
+        }
+      }
+    }
+  }
+
+  private void makeConflictGraph(FlatMethod fm) {
 
     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
     flatNodesToVisit.add(fm);
@@ -688,10 +992,10 @@ public class OoOJavaAnalysis {
 
         ConflictGraph conflictGraph = sese2conflictGraph.get(seseStack.peek());
         if (conflictGraph == null) {
-          conflictGraph = new ConflictGraph();
+          conflictGraph = new ConflictGraph(state);
         }
 
-        conflictGraph_nodeAction(fn, seseStack.peek(), sitesToFlag);
+        conflictGraph_nodeAction(fn, seseStack.peek());
       }
 
       // schedule forward nodes for analysis
@@ -705,80 +1009,138 @@ public class OoOJavaAnalysis {
     }
 
   }
 
-  private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE, Set<FlatNew> sitesToFlag) {
+  private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE) {
+
+    ConflictGraph conflictGraph;
+    TempDescriptor lhs;
+    TempDescriptor rhs;
 
     EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
-    ConflictGraph conflictGraph = sese2conflictGraph.get(currentSESE.getParent());
-    if (conflictGraph == null) {
-      conflictGraph = new ConflictGraph();
-    }
-    
+
     switch (fn.kind()) {
 
     case FKind.FlatSESEEnterNode: {
 
+      if (currentSESE.getParent() == null) {
+        return;
+      }
+      conflictGraph = sese2conflictGraph.get(currentSESE.getParent());
+      if (conflictGraph == null) {
+        conflictGraph = new ConflictGraph(state);
+      }
+
       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
 
       if (!fsen.getIsCallerSESEplaceholder() && currentSESE.getParent() != null) {
         // collects effects set of invar set and generates invar node
-        Hashtable<Taint, Set<Effect>> taint2Effects=effectsAnalysis.get(currentSESE);
+        Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(currentSESE);
         conflictGraph.addLiveIn(taint2Effects);
       }
+
+      if (conflictGraph.id2cn.size() > 0) {
+        sese2conflictGraph.put(currentSESE.getParent(), conflictGraph);
+      }
+
     }
       break;
-      
-    case FKind.FlatFieldNode:  
+
+    case FKind.FlatFieldNode:
     case FKind.FlatElementNode: {
-      
-      FlatFieldNode ffn = (FlatFieldNode) fn;
-      TempDescriptor rhs = ffn.getSrc();
-      
-      // add stall site      
-      //Hashtable<Taint, Set<Effect>> taint2Effects=effectsAnalysis.get(fn, rhs);
-      //conflictGraph.addStallSite(taint2Effects);
-      
-    }    
+
+      conflictGraph = sese2conflictGraph.get(currentSESE);
+      if (conflictGraph == null) {
+        conflictGraph = new ConflictGraph(state);
+      }
+
+      if (fn instanceof FlatFieldNode) {
+        FlatFieldNode ffn = (FlatFieldNode) fn;
+        rhs = ffn.getSrc();
+      } else {
+        FlatElementNode fen = (FlatElementNode) fn;
+        rhs = fen.getSrc();
+      } 
+
+      // add stall site
+      Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
+      conflictGraph.addStallSite(taint2Effects, rhs);
+
+      if (conflictGraph.id2cn.size() > 0) {
+        sese2conflictGraph.put(currentSESE, conflictGraph);
+      }
+    }
       break;
-      
-    case FKind.FlatSetFieldNode: 
+
+    case FKind.FlatSetFieldNode:
     case FKind.FlatSetElementNode: {
-      
-      FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
-      TempDescriptor lhs = fsfn.getDst();
-      TempDescriptor rhs = fsfn.getSrc();
-      
+
+      conflictGraph = sese2conflictGraph.get(currentSESE);
+      if (conflictGraph == null) {
+        conflictGraph = new ConflictGraph(state);
+      }
+
+      if (fn instanceof FlatSetFieldNode) {
+        FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
+        lhs = fsfn.getDst();
+        rhs = fsfn.getSrc();
+      } else {
+        FlatSetElementNode fsen = (FlatSetElementNode) fn;
+        lhs = fsen.getDst();
+        rhs = fsen.getSrc();
+      }
+
       // collects effects of stall site and generates stall site node
-      //Hashtable<Taint, Set<Effect>> taint2Effects=effectsAnalysis.get(fn, rhs);
-      //conflictGraph.addStallSite(taint2Effects);
-      
-      //taint2Effects=effectsAnalysis.get(fn, lhs);
-      //conflictGraph.addStallSite(taint2Effects);
-      
-    }    
+      Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
+      conflictGraph.addStallSite(taint2Effects, rhs);
+      conflictGraph.addStallSite(taint2Effects, lhs);
+
+      if (conflictGraph.id2cn.size() > 0) {
+        sese2conflictGraph.put(currentSESE, conflictGraph);
+      }
+    }
       break;
+
+    case FKind.FlatCall: {
+      conflictGraph = sese2conflictGraph.get(currentSESE);
+      if (conflictGraph == null) {
+        conflictGraph = new ConflictGraph(state);
+      }
+
+      FlatCall fc = (FlatCall) fn;
+      lhs = fc.getThis();
+
+      // collects effects of stall site and generates stall site node
+      Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
+      conflictGraph.addStallSite(taint2Effects, lhs);
+      if (conflictGraph.id2cn.size() > 0) {
+        sese2conflictGraph.put(currentSESE, conflictGraph);
+      }
     }
 
-    if (conflictGraph.id2cn.size() > 0) {
-      sese2conflictGraph.put(currentSESE.getParent(), conflictGraph);
+      break;
+
     }
-    
+
   }
-  
-  private void calculateConflicts() {
+
+  private void calculateConflicts(Set<FlatNew> sitesToFlag, boolean useReachInfo) {
     // decide fine-grain edge or coarse-grain edge among all vertexes by
     // pair-wise comparison
-
     Iterator<FlatNode> seseIter = sese2conflictGraph.keySet().iterator();
     while (seseIter.hasNext()) {
-      FlatNode sese = seseIter.next();
+      FlatSESEEnterNode sese = (FlatSESEEnterNode) seseIter.next();
       ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
-      conflictGraph.analyzeConflicts();
+      if (useReachInfo) {
+        // clear current conflict before recalculating with reachability info
+        conflictGraph.clearAllConflictEdge();
+        conflictGraph.setDisJointAnalysis(disjointAnalysisReach);
+        conflictGraph.setFMEnclosing(sese.getfmEnclosing());
+      }
+      conflictGraph.analyzeConflicts(sitesToFlag, useReachInfo);
       sese2conflictGraph.put(sese, conflictGraph);
     }
   }
-  
+
   private void writeConflictGraph() {
     Enumeration<FlatNode> keyEnum = sese2conflictGraph.keys();
     while (keyEnum.hasMoreElements()) {
@@ -794,7 +1156,7 @@ public class OoOJavaAnalysis {
       }
     }
   }
-  
+
   private void synthesizeLocks() {
     Set<Entry<FlatNode, ConflictGraph>> graphEntrySet = sese2conflictGraph.entrySet();
     for (Iterator iterator = graphEntrySet.iterator(); iterator.hasNext();) {
@@ -804,7 +1166,7 @@ public class OoOJavaAnalysis {
       calculateCovering(conflictGraph);
     }
   }
-  
+
   private void calculateCovering(ConflictGraph conflictGraph) {
     uniqueLockSetId = 0; // reset lock counter for every new conflict graph
     HashSet<ConflictEdge> fineToCover = new HashSet<ConflictEdge>();
@@ -893,6 +1255,12 @@ public class OoOJavaAnalysis {
 
             changed = true;
 
+            if (seseLock.containsConflictNode(newNode)) {
+              seseLock.addEdge(edge);
+              fineToCover.remove(edge);
+              break;
+            }
+
             if (seseLock.isWriteNode(newNode)) {
               if (newNode.isStallSiteNode()) {
                 type = ConflictNode.PARENT_WRITE;
@@ -937,13 +1305,13 @@ public class OoOJavaAnalysis {
         }
 
       } while (changed);
+      HashSet<ConflictEdge> notCovered=new HashSet<ConflictEdge>();
       do { // coarse
         changed = false;
         int type;
         for (Iterator iterator = coarseToCover.iterator(); iterator.hasNext();) {
 
           ConflictEdge edge = (ConflictEdge) iterator.next();
-
           if (seseLock.getConflictNodeSet().size() == 0) {
             // initial setup
             if (seseLock.hasSelfCoarseEdge(edge.getVertexU())) {
@@ -952,12 +1320,16 @@ public class OoOJavaAnalysis {
                 // and it is not parent
                 type = ConflictNode.SCC;
               } else {
-                type = ConflictNode.PARENT_COARSE;
+                type = ConflictNode.PARENT_WRITE;
               }
               seseLock.addConflictNode(edge.getVertexU(), type);
             } else {
               if (edge.getVertexU().isStallSiteNode()) {
-                type = ConflictNode.PARENT_COARSE;
+                if (edge.getVertexU().getWriteEffectSet().isEmpty()) {
+                  type = ConflictNode.PARENT_READ;
+                } else {
+                  type = ConflictNode.PARENT_WRITE;
+                }
               } else {
                 type = ConflictNode.COARSE;
               }
@@ -969,12 +1341,16 @@ public class OoOJavaAnalysis {
                 // and it is not parent
                 type = ConflictNode.SCC;
               } else {
-                type = ConflictNode.PARENT_COARSE;
+                type = ConflictNode.PARENT_WRITE;
               }
               seseLock.addConflictNode(edge.getVertexV(), type);
             } else {
               if (edge.getVertexV().isStallSiteNode()) {
-                type = ConflictNode.PARENT_COARSE;
+                if (edge.getVertexV().getWriteEffectSet().isEmpty()) {
+                  type = ConflictNode.PARENT_READ;
+                } else {
+                  type = ConflictNode.PARENT_WRITE;
+                }
               } else {
                 type = ConflictNode.COARSE;
               }
@@ -991,7 +1367,21 @@ public class OoOJavaAnalysis {
             // new node has a coarse-grained edge to all fine-read, fine-write,
             // parent
             changed = true;
+            
+            if (newNode.isInVarNode() && (!seseLock.hasSelfCoarseEdge(newNode))
+                && seseLock.hasCoarseEdgeWithParentCoarse(newNode)) {
+              // this case can't be covered by this queue
+              coarseToCover.remove(edge);
+              notCovered.add(edge);
+              break;
+            }
 
+            if (seseLock.containsConflictNode(newNode)) {
+              seseLock.addEdge(edge);
+              coarseToCover.remove(edge);
+              break;
+            }
+            
             if (seseLock.hasSelfCoarseEdge(newNode)) {
               // SCC
               if (newNode.isStallSiteNode()) {
@@ -1039,6 +1429,7 @@ public class OoOJavaAnalysis {
       lockSet.add(seseLock);
 
       toCover.clear();
+      coarseToCover.addAll(notCovered);
       toCover.addAll(fineToCover);
       toCover.addAll(coarseToCover);
 
@@ -1047,4 +1438,143 @@ public class OoOJavaAnalysis {
     conflictGraph2SESELock.put(conflictGraph, lockSet);
   }
 
+  public ConflictGraph getConflictGraph(FlatNode sese) {
+    return sese2conflictGraph.get(sese);
+  }
+
+  public Set<SESELock> getLockMappings(ConflictGraph graph) {
+    return conflictGraph2SESELock.get(graph);
+  }
+
+  public Set<FlatSESEEnterNode> getAllSESEs() {
+    return rblockRel.getAllSESEs();
+  }
+
+  public FlatSESEEnterNode getMainSESE() {
+    return rblockRel.getMainSESE();
+  }
+
+  public void writeReports(String timeReport) throws java.io.IOException {
+
+    BufferedWriter bw = new BufferedWriter(new FileWriter("mlpReport_summary.txt"));
+    bw.write("MLP Analysis Results\n\n");
+    bw.write(timeReport + "\n\n");
+    printSESEHierarchy(bw);
+    bw.write("\n");
+    printSESEInfo(bw);
+    bw.close();
+
+    Iterator<Descriptor> methItr = disjointAnalysisTaints.getDescriptorsToAnalyze().iterator();
+    while (methItr.hasNext()) {
+      MethodDescriptor md = (MethodDescriptor) methItr.next();
+      FlatMethod fm = state.getMethodFlat(md);
+      if (fm != null) {
+        bw =
+            new BufferedWriter(new FileWriter("mlpReport_" + md.getClassMethodName()
+                + md.getSafeMethodDescriptor() + ".txt"));
+        bw.write("MLP Results for " + md + "\n-------------------\n");
+
+        FlatSESEEnterNode implicitSESE = (FlatSESEEnterNode) fm.getNext(0);
+        if (!implicitSESE.getIsCallerSESEplaceholder() && implicitSESE != rblockRel.getMainSESE()) {
+          System.out.println(implicitSESE + " is not implicit?!");
+          System.exit(-1);
+        }
+        bw.write("Dynamic vars to manage:\n  " + implicitSESE.getDynamicVarSet());
+
+        bw.write("\n\nLive-In, Root View\n------------------\n" + fm.printMethod(livenessRootView));
+        bw.write("\n\nVariable Results-Out\n----------------\n" + fm.printMethod(variableResults));
+        bw.write("\n\nNot Available Results-Out\n---------------------\n"
+            + fm.printMethod(notAvailableResults));
+        bw.write("\n\nCode Plans\n----------\n" + fm.printMethod(codePlans));
+        bw.close();
+      }
+    }
+  }
+
+  private void printSESEHierarchy(BufferedWriter bw) throws java.io.IOException {
+    bw.write("SESE Hierarchy\n--------------\n");
+    Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
+    while (rootItr.hasNext()) {
+      FlatSESEEnterNode root = rootItr.next();
+      if (root.getIsCallerSESEplaceholder()) {
+        if (!root.getChildren().isEmpty()) {
+          printSESEHierarchyTree(bw, root, 0);
+        }
+      } else {
+        printSESEHierarchyTree(bw, root, 0);
+      }
+    }
+  }
+
+  private void printSESEHierarchyTree(BufferedWriter bw, FlatSESEEnterNode fsen, int depth)
+      throws java.io.IOException {
+    for (int i = 0; i < depth; ++i) {
+      bw.write("  ");
+    }
+    bw.write("- " + fsen.getPrettyIdentifier() + "\n");
+
+    Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
+    while (childItr.hasNext()) {
+      FlatSESEEnterNode fsenChild = childItr.next();
+      printSESEHierarchyTree(bw, fsenChild, depth + 1);
+    }
+  }
+
+  private void printSESEInfo(BufferedWriter bw) throws java.io.IOException {
+    bw.write("\nSESE info\n-------------\n");
+    Iterator<FlatSESEEnterNode> rootItr = rblockRel.getRootSESEs().iterator();
+    while (rootItr.hasNext()) {
+      FlatSESEEnterNode root = rootItr.next();
+      if (root.getIsCallerSESEplaceholder()) {
+        if (!root.getChildren().isEmpty()) {
+          printSESEInfoTree(bw, root);
+        }
+      } else {
+        printSESEInfoTree(bw, root);
+      }
+    }
+  }
+
+  public DisjointAnalysis getDisjointAnalysis() {
+    return disjointAnalysisTaints;
+  }
+
+  private void printSESEInfoTree(BufferedWriter bw, FlatSESEEnterNode fsen)
+      throws java.io.IOException {
+
+    if (!fsen.getIsCallerSESEplaceholder()) {
+      bw.write("SESE " + fsen.getPrettyIdentifier());
+      if( fsen.getIsLeafSESE() ) {
+        bw.write(" (leaf)");
+      }
+      bw.write(" {\n");
+
+      bw.write("  in-set: " + fsen.getInVarSet() + "\n");
+      Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
+      while (tItr.hasNext()) {
+        TempDescriptor inVar = tItr.next();
+        if (fsen.getReadyInVarSet().contains(inVar)) {
+          bw.write("    (ready)  " + inVar + "\n");
+        }
+        if (fsen.getStaticInVarSet().contains(inVar)) {
+          bw.write("    (static) " + inVar + " from " + fsen.getStaticInVarSrc(inVar) + "\n");
+        }
+        if (fsen.getDynamicInVarSet().contains(inVar)) {
+          bw.write("    (dynamic)" + inVar + "\n");
+        }
+      }
+
+      bw.write("   Dynamic vars to manage: " + fsen.getDynamicVarSet() + "\n");
+
+      bw.write("  out-set: " + fsen.getOutVarSet() + "\n");
+      bw.write("}\n");
+    }
+
+    Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
+    while (childItr.hasNext()) {
+      FlatSESEEnterNode fsenChild = childItr.next();
+      printSESEInfoTree(bw, fsenChild);
+    }
+  }
+
 }