fix: keeps SESEstatus for either case(TRUE/FALSE)
[IRC.git] / Robust / src / Analysis / OoOJava / OoOJavaAnalysis.java
index 95941e6e9bc161d9dc418dbb1027af1f81263e3a..2b79fa6b876a9e248a397046e872135677f9f65c 100644 (file)
@@ -3,29 +3,34 @@ package Analysis.OoOJava;
 import java.io.BufferedWriter;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.io.StringWriter;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.Map;
 import java.util.Set;
 import java.util.Stack;
 import java.util.Map.Entry;
-import Analysis.Liveness;
+
 import Analysis.ArrayReferencees;
+import Analysis.Liveness;
 import Analysis.CallGraph.CallGraph;
+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.FieldDescriptor;
 import IR.MethodDescriptor;
 import IR.Operation;
 import IR.State;
-import IR.TypeDescriptor;
 import IR.TypeUtil;
 import IR.Flat.FKind;
 import IR.Flat.FlatCall;
-import IR.Flat.FlatCondBranch;
 import IR.Flat.FlatEdge;
 import IR.Flat.FlatElementNode;
 import IR.Flat.FlatFieldNode;
@@ -33,7 +38,6 @@ import IR.Flat.FlatMethod;
 import IR.Flat.FlatNew;
 import IR.Flat.FlatNode;
 import IR.Flat.FlatOpNode;
-import IR.Flat.FlatReturnNode;
 import IR.Flat.FlatSESEEnterNode;
 import IR.Flat.FlatSESEExitNode;
 import IR.Flat.FlatSetElementNode;
@@ -41,21 +45,1577 @@ import IR.Flat.FlatSetFieldNode;
 import IR.Flat.FlatWriteDynamicVarNode;
 import IR.Flat.TempDescriptor;
 
-
 public class OoOJavaAnalysis {
 
   // data from the compiler
-  private State             state;
-  private TypeUtil          typeUtil;
-  private CallGraph         callGraph;
+  private State state;
+  private TypeUtil typeUtil;
+  private CallGraph callGraph;
+  private RBlockRelationAnalysis rblockRel;
+  private RBlockStatusAnalysis rblockStatus;
+  private DisjointAnalysis disjointAnalysisTaints;
+  private DisjointAnalysis disjointAnalysisReach;
+
+  private Hashtable<FlatNode, Set<TempDescriptor>> livenessRootView;
+  private Hashtable<FlatNode, Set<TempDescriptor>> livenessVirtualReads;
+  private Hashtable<FlatNode, VarSrcTokTable> variableResults;
+  private Hashtable<FlatNode, Set<TempDescriptor>> notAvailableResults;
+  private Hashtable<FlatNode, CodePlan> codePlans;
+
+  private Hashtable<FlatSESEEnterNode, Set<TempDescriptor>> notAvailableIntoSESE;
+
+  private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
+
+  // 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;
+
+  public static int maxSESEage = -1;
+
+  public int getMaxSESEage() {
+    return maxSESEage;
+  }
+
+  // may be null
+  public CodePlan getCodePlan(FlatNode fn) {
+    CodePlan cp = codePlans.get(fn);
+    return cp;
+  }
+
+  public Set<FlatNode> getNodesWithPlans() {
+    return codePlans.keySet();
+  }
+
+  public OoOJavaAnalysis(State state, TypeUtil typeUtil, CallGraph callGraph, Liveness liveness,
+      ArrayReferencees arrayReferencees) {
+
+    double timeStartAnalysis = (double) System.nanoTime();
+
+    this.state = state;
+    this.typeUtil = typeUtil;
+    this.callGraph = callGraph;
+    this.maxSESEage = state.MLP_MAXSESEAGE;
+
+    livenessRootView = new Hashtable<FlatNode, Set<TempDescriptor>>();
+    livenessVirtualReads = new Hashtable<FlatNode, Set<TempDescriptor>>();
+    variableResults = new Hashtable<FlatNode, VarSrcTokTable>();
+    notAvailableResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
+    codePlans = new Hashtable<FlatNode, CodePlan>();
+    wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
+
+    notAvailableIntoSESE = new Hashtable<FlatSESEEnterNode, Set<TempDescriptor>>();
+
+    sese2conflictGraph = new Hashtable<FlatNode, ConflictGraph>();
+    conflictGraph2SESELock = new Hashtable<ConflictGraph, HashSet<SESELock>>();
+
+    // add all methods transitively reachable from the
+    // source's main to set for analysis
+    MethodDescriptor mdSourceEntry = typeUtil.getMain();
+    FlatMethod fmMain = state.getMethodFlat(mdSourceEntry);
+
+    Set<MethodDescriptor> descriptorsToAnalyze = callGraph.getAllMethods(mdSourceEntry);
+
+    descriptorsToAnalyze.add(mdSourceEntry);
+
+    // 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()) {
+      FlatSESEEnterNode root = rootItr.next();
+      livenessAnalysisBackward(root, true, null);
+    }
+
+    // 3rd pass, variable analysis
+    Iterator<MethodDescriptor> methItr = descriptorsToAnalyze.iterator();
+    while (methItr.hasNext()) {
+      Descriptor d = methItr.next();
+      FlatMethod fm = state.getMethodFlat(d);
+
+      // starting from roots do a forward, fixed-point
+      // variable analysis for refinement and stalls
+      variableAnalysisForward(fm);
+    }
+
+    // 4th pass, compute liveness contribution from
+    // virtual reads discovered in variable pass
+    rootItr = rblockRel.getRootSESEs().iterator();
+    while (rootItr.hasNext()) {
+      FlatSESEEnterNode root = rootItr.next();
+      livenessAnalysisBackward(root, true, null);
+    }
+
+    // 5th pass, use disjointness with NO FLAGGED REGIONS
+    // to compute taints and effects
+    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();
+    while (methItr.hasNext()) {
+      Descriptor d = methItr.next();
+      FlatMethod fm = state.getMethodFlat(d);
+
+      // compute what is not available at every program
+      // point, in a forward fixed-point pass
+      notAvailableForward(fm);
+    }
+
+    // 7th pass, make conflict graph
+    // conflict graph is maintained by each parent sese,
+    
+    Set<FlatSESEEnterNode> allSESEs=rblockRel.getAllSESEs();
+    for (Iterator iterator = allSESEs.iterator(); iterator.hasNext();) {
+
+      FlatSESEEnterNode parent = (FlatSESEEnterNode) iterator.next();
+      if (!parent.getIsLeafSESE()) {
+        
+        EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
+        ConflictGraph conflictGraph = sese2conflictGraph.get(parent);     
+        if (conflictGraph == null) {
+          conflictGraph = new ConflictGraph(state);
+        }
+
+        Set<FlatSESEEnterNode> children = parent.getSESEChildren();
+        for (Iterator iterator2 = children.iterator(); iterator2.hasNext();) {
+          FlatSESEEnterNode child = (FlatSESEEnterNode) iterator2.next();
+          Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(child);
+          conflictGraph.addLiveIn(taint2Effects);
+          if(taint2Effects!=null)
+            System.out.println("#add ="+taint2Effects+"currentSESE="+child+" into conflictGraph="+conflictGraph);
+          
+          sese2conflictGraph.put(parent, conflictGraph);
+        }
+      }
+    }
+    
+    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);
+      codePlansForward(fm);
+    }
+
+    // 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) {
+      }
+    }
+
+  }
+  
+
+  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,
+      Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
+
+    // start from an SESE exit, visit nodes in reverse up to
+    // SESE enter in a fixed-point scheme, where children SESEs
+    // should already be analyzed and therefore can be skipped
+    // because child SESE enter node has all necessary info
+    Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+
+    if (toplevel) {
+      flatNodesToVisit.add(fsen.getfmEnclosing().getFlatExit());
+    } else {
+      flatNodesToVisit.add(fsen.getFlatExit());
+    }
+
+    Hashtable<FlatNode, Set<TempDescriptor>> livenessResults =
+        new Hashtable<FlatNode, Set<TempDescriptor>>();
+
+    if (toplevel) {
+      liveout = new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
+    }
+
+    while (!flatNodesToVisit.isEmpty()) {
+      FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+      flatNodesToVisit.remove(fn);
+
+      Set<TempDescriptor> prev = livenessResults.get(fn);
+
+      // merge sets from control flow joins
+      Set<TempDescriptor> u = new HashSet<TempDescriptor>();
+      for (int i = 0; i < fn.numNext(); i++) {
+        FlatNode nn = fn.getNext(i);
+        Set<TempDescriptor> s = livenessResults.get(nn);
+        if (s != null) {
+          u.addAll(s);
+        }
+      }
+
+      Set<TempDescriptor> curr = liveness_nodeActions(fn, u, fsen, toplevel, liveout);
+
+      // if a new result, schedule backward nodes for analysis
+      if (!curr.equals(prev)) {
+        livenessResults.put(fn, curr);
+
+        // don't flow backwards past current SESE enter
+        if (!fn.equals(fsen)) {
+          for (int i = 0; i < fn.numPrev(); i++) {
+            FlatNode nn = fn.getPrev(i);
+            flatNodesToVisit.add(nn);
+          }
+        }
+      }
+    }
+
+    Set<TempDescriptor> s = livenessResults.get(fsen);
+    if (s != null) {
+      fsen.addInVarSet(s);
+    }
+
+    // remember liveness per node from the root view as the
+    // global liveness of variables for later passes to use
+    if (toplevel) {
+      livenessRootView.putAll(livenessResults);
+    }
+
+    // post-order traversal, so do children first
+    Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
+    while (childItr.hasNext()) {
+      FlatSESEEnterNode fsenChild = childItr.next();
+      livenessAnalysisBackward(fsenChild, false, liveout);
+    }
+  }
+
+  private Set<TempDescriptor> liveness_nodeActions(FlatNode fn, Set<TempDescriptor> liveIn,
+      FlatSESEEnterNode currentSESE, boolean toplevel,
+      Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
+    switch (fn.kind()) {
+
+    case FKind.FlatSESEExitNode:
+      if (toplevel) {
+        FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
+        if (!liveout.containsKey(fsexn)) {
+          liveout.put(fsexn, new HashSet<TempDescriptor>());
+        }
+        liveout.get(fsexn).addAll(liveIn);
+      }
+      // no break, sese exits should also execute default actions
+
+    default: {
+      // handle effects of statement in reverse, writes then reads
+      TempDescriptor[] writeTemps = fn.writesTemps();
+      for (int i = 0; i < writeTemps.length; ++i) {
+        liveIn.remove(writeTemps[i]);
+
+        if (!toplevel) {
+          FlatSESEExitNode fsexn = currentSESE.getFlatExit();
+          Set<TempDescriptor> livetemps = liveout.get(fsexn);
+          if (livetemps != null && livetemps.contains(writeTemps[i])) {
+            // write to a live out temp...
+            // need to put in SESE liveout set
+            currentSESE.addOutVar(writeTemps[i]);
+          }
+        }
+      }
+
+      TempDescriptor[] readTemps = fn.readsTemps();
+      for (int i = 0; i < readTemps.length; ++i) {
+        liveIn.add(readTemps[i]);
+      }
+
+      Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get(fn);
+      if (virtualReadTemps != null) {
+        liveIn.addAll(virtualReadTemps);
+      }
+
+    }
+      break;
+
+    } // end switch
+
+    return liveIn;
+  }
+
+  private void variableAnalysisForward(FlatMethod fm) {
 
+    Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+    flatNodesToVisit.add(fm);
 
+    while (!flatNodesToVisit.isEmpty()) {
+      FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+      flatNodesToVisit.remove(fn);
 
-  public OoOJavaAnalysis( State            state,
-                          TypeUtil         tu,
-                          CallGraph        callGraph,
-                          Liveness         liveness,
-                          ArrayReferencees arrayReferencees
-                          ) {
+      Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
+      assert seseStack != null;
+
+      VarSrcTokTable prev = variableResults.get(fn);
+
+      // merge sets from control flow joins
+      VarSrcTokTable curr = new VarSrcTokTable();
+      for (int i = 0; i < fn.numPrev(); i++) {
+        FlatNode nn = fn.getPrev(i);
+        VarSrcTokTable incoming = variableResults.get(nn);
+        curr.merge(incoming);
+      }
+
+      if (!seseStack.empty()) {
+        variable_nodeActions(fn, curr, seseStack.peek());
+      }
+
+      // if a new result, schedule forward nodes for analysis
+      if (!curr.equals(prev)) {
+        variableResults.put(fn, curr);
+
+        for (int i = 0; i < fn.numNext(); i++) {
+          FlatNode nn = fn.getNext(i);
+          flatNodesToVisit.add(nn);
+        }
+      }
+    }
+  }
+
+  private void variable_nodeActions(FlatNode fn, VarSrcTokTable vstTable,
+      FlatSESEEnterNode currentSESE) {
+    switch (fn.kind()) {
+
+    case FKind.FlatSESEEnterNode: {
+      FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
+      assert fsen.equals(currentSESE);
+
+      vstTable.age(currentSESE);
+      vstTable.assertConsistency();
+    }
+      break;
+
+    case FKind.FlatSESEExitNode: {
+      FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
+      FlatSESEEnterNode fsen = fsexn.getFlatEnter();
+      assert currentSESE.getChildren().contains(fsen);
+
+      // remap all of this child's children tokens to be
+      // from this child as the child exits
+      vstTable.remapChildTokens(fsen);
+
+      // liveness virtual reads are things that might be
+      // written by an SESE and should be added to the in-set
+      // 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> fsenVirtReadsOld = livenessVirtualReads.get(fn);
+      if (fsenVirtReadsOld != null) {
+        fsenVirtReads.addAll(fsenVirtReadsOld);
+      }
+      livenessVirtualReads.put(fn, fsenVirtReads);
+
+      // then all child out-set tokens are guaranteed
+      // to be filled in, so clobber those entries with
+      // the latest, clean sources
+      Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
+      while (outVarItr.hasNext()) {
+        TempDescriptor outVar = outVarItr.next();
+        HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
+        ts.add(outVar);
+        VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
+        vstTable.remove(outVar);
+        vstTable.add(vst);
+      }
+      vstTable.assertConsistency();
+
+    }
+      break;
+
+    case FKind.FlatOpNode: {
+      FlatOpNode fon = (FlatOpNode) fn;
+
+      if (fon.getOp().getOp() == Operation.ASSIGN) {
+        TempDescriptor lhs = fon.getDest();
+        TempDescriptor rhs = fon.getLeft();
+
+        vstTable.remove(lhs);
+
+        Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
+
+        Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
+        while (itr.hasNext()) {
+          VariableSourceToken vst = itr.next();
+
+          HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
+          ts.add(lhs);
+
+          if (currentSESE.getChildren().contains(vst.getSESE())) {
+            // if the source comes from a child, copy it over
+            forAddition.add(new VariableSourceToken(ts, vst.getSESE(), vst.getAge(), vst
+                .getAddrVar()));
+          } else {
+            // otherwise, stamp it as us as the source
+            forAddition.add(new VariableSourceToken(ts, currentSESE, new Integer(0), lhs));
+          }
+        }
+
+        vstTable.addAll(forAddition);
+
+        // only break if this is an ASSIGN op node,
+        // otherwise fall through to default case
+        vstTable.assertConsistency();
+        break;
+      }
+    }
+
+      // note that FlatOpNode's that aren't ASSIGN
+      // fall through to this default case
+    default: {
+      TempDescriptor[] writeTemps = fn.writesTemps();
+      if (writeTemps.length > 0) {
+
+        // for now, when writeTemps > 1, make sure
+        // its a call node, programmer enforce only
+        // doing stuff like calling a print routine
+        // assert writeTemps.length == 1;
+        if (writeTemps.length > 1) {
+          assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
+          break;
+        }
+
+        vstTable.remove(writeTemps[0]);
+
+        HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
+        ts.add(writeTemps[0]);
+
+        vstTable.add(new VariableSourceToken(ts, currentSESE, new Integer(0), writeTemps[0]));
+      }
+
+      vstTable.assertConsistency();
+    }
+      break;
+
+    } // end switch
+  }
+
+  private void notAvailableForward(FlatMethod fm) {
+
+    Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+    flatNodesToVisit.add(fm);
+
+    while (!flatNodesToVisit.isEmpty()) {
+      FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+      flatNodesToVisit.remove(fn);
+
+      Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
+      assert seseStack != null;
+
+      Set<TempDescriptor> prev = notAvailableResults.get(fn);
+
+      Set<TempDescriptor> curr = 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) {
+          curr.addAll(notAvailIn);
+        }
+      }
+
+      if (!seseStack.empty()) {
+        notAvailable_nodeActions(fn, curr, seseStack.peek());
+      }
+
+      // if a new result, schedule forward nodes for analysis
+      if (!curr.equals(prev)) {
+        notAvailableResults.put(fn, curr);
+
+        for (int i = 0; i < fn.numNext(); i++) {
+          FlatNode nn = fn.getNext(i);
+          flatNodesToVisit.add(nn);
+        }
+      }
+    }
+  }
+
+  private void notAvailable_nodeActions(FlatNode fn, Set<TempDescriptor> notAvailSet,
+      FlatSESEEnterNode currentSESE) {
+
+    // any temps that are removed from the not available set
+    // at this node should be marked in this node's code plan
+    // as temps to be grabbed at runtime!
+
+    switch (fn.kind()) {
+
+    case FKind.FlatSESEEnterNode: {
+      FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
+      assert fsen.equals(currentSESE);
+
+      // keep a copy of what's not available into the SESE
+      // and restore it at the matching exit node
+      Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
+      Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
+      while (tdItr.hasNext()) {
+        notAvailCopy.add(tdItr.next());
+      }
+      notAvailableIntoSESE.put(fsen, notAvailCopy);
+
+      notAvailSet.clear();
+    }
+      break;
+
+    case FKind.FlatSESEExitNode: {
+      FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
+      FlatSESEEnterNode fsen = fsexn.getFlatEnter();
+      assert currentSESE.getChildren().contains(fsen);
+
+      notAvailSet.addAll(fsen.getOutVarSet());
+
+      Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
+      assert notAvailIn != null;
+      notAvailSet.addAll(notAvailIn);
+
+    }
+      break;
+
+    case FKind.FlatMethod: {
+      notAvailSet.clear();
+    }
+
+    case FKind.FlatOpNode: {
+      FlatOpNode fon = (FlatOpNode) fn;
+
+      if (fon.getOp().getOp() == Operation.ASSIGN) {
+        TempDescriptor lhs = fon.getDest();
+        TempDescriptor rhs = fon.getLeft();
+
+        // copy makes lhs same availability as rhs
+        if (notAvailSet.contains(rhs)) {
+          notAvailSet.add(lhs);
+        } else {
+          notAvailSet.remove(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: {
+      TempDescriptor[] writeTemps = fn.writesTemps();
+      for (int i = 0; i < writeTemps.length; i++) {
+        TempDescriptor wTemp = writeTemps[i];
+        notAvailSet.remove(wTemp);
+      }
+      TempDescriptor[] readTemps = fn.readsTemps();
+      for (int i = 0; i < readTemps.length; i++) {
+        TempDescriptor rTemp = readTemps[i];
+        notAvailSet.remove(rTemp);
+
+        // if this variable has exactly one source, potentially
+        // get other things from this source as well
+        VarSrcTokTable vstTable = variableResults.get(fn);
+
+        VSTWrapper vstIfStatic = new VSTWrapper();
+        Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
+
+        if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
+
+          VariableSourceToken vst = vstIfStatic.vst;
+
+          Iterator<VariableSourceToken> availItr =
+              vstTable.get(vst.getSESE(), vst.getAge()).iterator();
+
+          // look through things that are also available from same source
+          while (availItr.hasNext()) {
+            VariableSourceToken vstAlsoAvail = availItr.next();
+
+            Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
+            while (refVarItr.hasNext()) {
+              TempDescriptor refVarAlso = refVarItr.next();
+
+              // 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);
+              if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
+                notAvailSet.remove(refVarAlso);
+              }
+            }
+          }
+        }
+      }
+    }
+      break;
+
+    } // end switch
   }
+
+  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);
+
+    Set<FlatNode> visited = new HashSet<FlatNode>();
+
+    while (!flatNodesToVisit.isEmpty()) {
+      FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+      flatNodesToVisit.remove(fn);
+      visited.add(fn);
+
+      Stack<FlatSESEEnterNode> seseStack = rblockRel.getRBlockStacks(fm, fn);
+      assert seseStack != null;
+
+      if (!seseStack.isEmpty()) {
+        conflictGraph_nodeAction(fn, seseStack.peek());
+      }
+
+      // schedule forward nodes for analysis
+      for (int i = 0; i < fn.numNext(); i++) {
+        FlatNode nn = fn.getNext(i);
+        if (!visited.contains(nn)) {
+          flatNodesToVisit.add(nn);
+        }
+      }
+
+    }
+
+  }
+
+  private void conflictGraph_nodeAction(FlatNode fn, FlatSESEEnterNode currentSESE) {
+
+    ConflictGraph conflictGraph;
+    TempDescriptor lhs;
+    TempDescriptor rhs;
+    
+    EffectsAnalysis effectsAnalysis = disjointAnalysisTaints.getEffectsAnalysis();
+
+    switch (fn.kind()) {
+
+    case FKind.FlatFieldNode:
+    case FKind.FlatElementNode: {
+
+      if (fn instanceof FlatFieldNode) {
+        FlatFieldNode ffn = (FlatFieldNode) fn;
+        rhs = ffn.getSrc();
+      } else {
+        FlatElementNode fen = (FlatElementNode) fn;
+        rhs = fen.getSrc();
+      }
+
+      Set<FlatSESEEnterNode> parentSet = currentSESE.getSESEParent();
+      for (Iterator iterator = parentSet.iterator(); iterator.hasNext();) {
+        FlatSESEEnterNode parent = (FlatSESEEnterNode) iterator.next();
+//        System.out.println("##current="+currentSESE.getmdEnclosing()+" PARENT=" + parent);
+        conflictGraph = sese2conflictGraph.get(parent);
+        if (conflictGraph == null) {
+          conflictGraph = new ConflictGraph(state);
+        }
+
+        // add stall site
+        Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
+        conflictGraph.addStallSite(taint2Effects, rhs);
+        if (taint2Effects != null)
+//          System.out.println("add =" + taint2Effects + "currentSESE=" + parent
+//              + " into conflictGraph=" + conflictGraph);
+
+        if (conflictGraph.id2cn.size() > 0) {
+          sese2conflictGraph.put(parent, conflictGraph);
+        }
+      }
+
+    }
+      break;
+
+    case FKind.FlatSetFieldNode:
+    case FKind.FlatSetElementNode: {
+
+      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
+      Set<FlatSESEEnterNode> parentSet = currentSESE.getSESEParent();
+      for (Iterator iterator = parentSet.iterator(); iterator.hasNext();) {
+        FlatSESEEnterNode parent = (FlatSESEEnterNode) iterator.next();
+        conflictGraph = sese2conflictGraph.get(parent);
+        if (conflictGraph == null) {
+          conflictGraph = new ConflictGraph(state);
+        }
+
+        Hashtable<Taint, Set<Effect>> taint2Effects = effectsAnalysis.get(fn);
+        conflictGraph.addStallSite(taint2Effects, rhs);
+        conflictGraph.addStallSite(taint2Effects, lhs);
+
+        if (conflictGraph.id2cn.size() > 0) {
+          sese2conflictGraph.put(parent, 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);
+
+      Set<FlatSESEEnterNode> parentSet = currentSESE.getSESEParent();
+      for (Iterator iterator = parentSet.iterator(); iterator.hasNext();) {
+        FlatSESEEnterNode parent = (FlatSESEEnterNode) iterator.next();
+        conflictGraph = sese2conflictGraph.get(parent);
+        if (conflictGraph == null) {
+          conflictGraph = new ConflictGraph(state);
+        }
+
+        conflictGraph.addStallSite(taint2Effects, lhs);
+        if (conflictGraph.id2cn.size() > 0) {
+          sese2conflictGraph.put(parent, conflictGraph);
+        }
+
+      }
+
+    }
+
+      break;
+
+    }
+
+  }
+
+  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()) {
+      FlatSESEEnterNode sese = (FlatSESEEnterNode) seseIter.next();
+      ConflictGraph conflictGraph = sese2conflictGraph.get(sese);
+//      System.out.println("# CALCULATING SESE CONFLICT="+sese);
+      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()) {
+      FlatNode key = (FlatNode) keyEnum.nextElement();
+      ConflictGraph cg = sese2conflictGraph.get(key);
+      try {
+        if (cg.hasConflictEdge()) {
+          cg.writeGraph("ConflictGraphFor" + key, false);
+        }
+      } catch (IOException e) {
+        System.out.println("Error writing");
+        System.exit(0);
+      }
+    }
+  }
+
+  private void synthesizeLocks() {
+    Set<Entry<FlatNode, ConflictGraph>> graphEntrySet = sese2conflictGraph.entrySet();
+    for (Iterator iterator = graphEntrySet.iterator(); iterator.hasNext();) {
+      Entry<FlatNode, ConflictGraph> graphEntry = (Entry<FlatNode, ConflictGraph>) iterator.next();
+      FlatNode sese = graphEntry.getKey();
+      ConflictGraph conflictGraph = graphEntry.getValue();
+      calculateCovering(conflictGraph);
+    }
+  }
+
+  private void calculateCovering(ConflictGraph conflictGraph) {
+    uniqueLockSetId = 0; // reset lock counter for every new conflict graph
+    HashSet<ConflictEdge> fineToCover = new HashSet<ConflictEdge>();
+    HashSet<ConflictEdge> coarseToCover = new HashSet<ConflictEdge>();
+    HashSet<SESELock> lockSet = new HashSet<SESELock>();
+
+    Set<ConflictEdge> tempCover = conflictGraph.getEdgeSet();
+    for (Iterator iterator = tempCover.iterator(); iterator.hasNext();) {
+      ConflictEdge conflictEdge = (ConflictEdge) iterator.next();
+      if (conflictEdge.isCoarseEdge()) {
+        coarseToCover.add(conflictEdge);
+      } else {
+        fineToCover.add(conflictEdge);
+      }
+    }
+
+    HashSet<ConflictEdge> toCover = new HashSet<ConflictEdge>();
+    toCover.addAll(fineToCover);
+    toCover.addAll(coarseToCover);
+
+    while (!toCover.isEmpty()) {
+
+      SESELock seseLock = new SESELock();
+      seseLock.setID(uniqueLockSetId++);
+
+      boolean changed;
+
+      do { // fine-grained edge
+
+        changed = false;
+
+        for (Iterator iterator = fineToCover.iterator(); iterator.hasNext();) {
+
+          int type;
+          ConflictEdge edge = (ConflictEdge) iterator.next();
+          if (seseLock.getConflictNodeSet().size() == 0) {
+            // initial setup
+            if (seseLock.isWriteNode(edge.getVertexU())) {
+              // mark as fine_write
+              if (edge.getVertexU().isStallSiteNode()) {
+                type = ConflictNode.PARENT_WRITE;
+              } else {
+                type = ConflictNode.FINE_WRITE;
+              }
+              seseLock.addConflictNode(edge.getVertexU(), type);
+            } else {
+              // mark as fine_read
+              if (edge.getVertexU().isStallSiteNode()) {
+                type = ConflictNode.PARENT_READ;
+              } else {
+                type = ConflictNode.FINE_READ;
+              }
+              seseLock.addConflictNode(edge.getVertexU(), type);
+            }
+            if (edge.getVertexV() != edge.getVertexU()) {
+              if (seseLock.isWriteNode(edge.getVertexV())) {
+                // mark as fine_write
+                if (edge.getVertexV().isStallSiteNode()) {
+                  type = ConflictNode.PARENT_WRITE;
+                } else {
+                  type = ConflictNode.FINE_WRITE;
+                }
+                seseLock.addConflictNode(edge.getVertexV(), type);
+              } else {
+                // mark as fine_read
+                if (edge.getVertexV().isStallSiteNode()) {
+                  type = ConflictNode.PARENT_READ;
+                } else {
+                  type = ConflictNode.FINE_READ;
+                }
+                seseLock.addConflictNode(edge.getVertexV(), type);
+              }
+            }
+            changed = true;
+            seseLock.addConflictEdge(edge);
+            fineToCover.remove(edge);
+            break;// exit iterator loop
+          }// end of initial setup
+
+          ConflictNode newNode;
+          if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
+            // new node has a fine-grained edge to all current node
+            // If there is a coarse grained edge where need a fine edge, it's
+            // okay to add the node
+            // but the edge must remain uncovered.
+
+            changed = true;
+
+            if (seseLock.containsConflictNode(newNode)) {
+              seseLock.addEdge(edge);
+              fineToCover.remove(edge);
+              break;
+            }
+
+            if (seseLock.isWriteNode(newNode)) {
+              if (newNode.isStallSiteNode()) {
+                type = ConflictNode.PARENT_WRITE;
+              } else {
+                type = ConflictNode.FINE_WRITE;
+              }
+              seseLock.setNodeType(newNode, type);
+            } else {
+              if (newNode.isStallSiteNode()) {
+                type = ConflictNode.PARENT_READ;
+              } else {
+                type = ConflictNode.FINE_READ;
+              }
+              seseLock.setNodeType(newNode, type);
+            }
+
+            seseLock.addEdge(edge);
+            Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
+            for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
+              ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
+
+              // mark all fine edges between new node and nodes in the group as
+              // covered
+              if (!conflictEdge.getVertexU().equals(newNode)) {
+                if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
+                  changed = true;
+                  seseLock.addConflictEdge(conflictEdge);
+                  fineToCover.remove(conflictEdge);
+                }
+              } else if (!conflictEdge.getVertexV().equals(newNode)) {
+                if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
+                  changed = true;
+                  seseLock.addConflictEdge(conflictEdge);
+                  fineToCover.remove(conflictEdge);
+                }
+              }
+
+            }
+
+            break;// exit iterator loop
+          }
+        }
+
+      } 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())) {
+              // node has a coarse-grained edge with itself
+              if (!(edge.getVertexU().isStallSiteNode())) {
+                // and it is not parent
+                type = ConflictNode.SCC;
+              } else {
+                if(state.RCR){
+                  type = ConflictNode.PARENT_COARSE;
+                }else{
+                  type = ConflictNode.PARENT_WRITE;
+                }
+              }
+              seseLock.addConflictNode(edge.getVertexU(), type);
+            } else {
+              if (edge.getVertexU().isStallSiteNode()) {
+                if(state.RCR){
+                  type = ConflictNode.PARENT_COARSE;
+                }else{
+                  if (edge.getVertexU().getWriteEffectSet().isEmpty()) {
+                    type = ConflictNode.PARENT_READ;
+                  } else {
+                    type = ConflictNode.PARENT_WRITE;
+                  }
+                }
+              } else {
+                type = ConflictNode.COARSE;
+              }
+              seseLock.addConflictNode(edge.getVertexU(), type);
+            }
+            if (seseLock.hasSelfCoarseEdge(edge.getVertexV())) {
+              // node has a coarse-grained edge with itself
+              if (!(edge.getVertexV().isStallSiteNode())) {
+                // and it is not parent
+                type = ConflictNode.SCC;
+              } else {
+                if(state.RCR){
+                  type = ConflictNode.PARENT_COARSE;
+                }else{
+                  type = ConflictNode.PARENT_WRITE;
+                }
+              }
+              seseLock.addConflictNode(edge.getVertexV(), type);
+            } else {
+              if (edge.getVertexV().isStallSiteNode()) {
+                if(state.RCR){
+                  type = ConflictNode.PARENT_COARSE;
+                }else{
+                  if (edge.getVertexV().getWriteEffectSet().isEmpty()) {
+                    type = ConflictNode.PARENT_READ;
+                  } else {
+                    type = ConflictNode.PARENT_WRITE;
+                  }
+                }
+              } else {
+                type = ConflictNode.COARSE;
+              }
+              seseLock.addConflictNode(edge.getVertexV(), type);
+            }
+            changed = true;
+            coarseToCover.remove(edge);
+            seseLock.addConflictEdge(edge);
+            break;// exit iterator loop
+          }// end of initial setup
+
+          ConflictNode newNode;
+          if ((newNode = seseLock.getNewNodeConnectedWithGroup(edge)) != null) {
+            // 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()) {
+                type = ConflictNode.PARENT_COARSE;
+              } else {
+                type = ConflictNode.SCC;
+              }
+              seseLock.setNodeType(newNode, type);
+            } else {
+              if (newNode.isStallSiteNode()) {
+                type = ConflictNode.PARENT_COARSE;
+              } else {
+                type = ConflictNode.COARSE;
+              }
+              seseLock.setNodeType(newNode, type);
+            }
+
+            seseLock.addEdge(edge);
+            Set<ConflictEdge> edgeSet = newNode.getEdgeSet();
+            for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
+              ConflictEdge conflictEdge = (ConflictEdge) iterator2.next();
+              // mark all coarse edges between new node and nodes in the group
+              // as covered
+              if (!conflictEdge.getVertexU().equals(newNode)) {
+                if (seseLock.containsConflictNode(conflictEdge.getVertexU())) {
+                  changed = true;
+                  seseLock.addConflictEdge(conflictEdge);
+                  coarseToCover.remove(conflictEdge);
+                }
+              } else if (!conflictEdge.getVertexV().equals(newNode)) {
+                if (seseLock.containsConflictNode(conflictEdge.getVertexV())) {
+                  changed = true;
+                  seseLock.addConflictEdge(conflictEdge);
+                  coarseToCover.remove(conflictEdge);
+                }
+              }
+
+            }
+            break;// exit iterator loop
+          }
+
+        }
+
+      } while (changed);
+      lockSet.add(seseLock);
+
+      toCover.clear();
+      coarseToCover.addAll(notCovered);
+      toCover.addAll(fineToCover);
+      toCover.addAll(coarseToCover);
+
+    }
+
+    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);
+    }
+  }
+
 }