Create analysis model for string literals in disjointness analysis that supports...
[IRC.git] / Robust / src / Analysis / Disjoint / DisjointAnalysis.java
index 5f02861f7665e42fe96906db619930edfe21d426..c8bde2d8b2c1bc00f8ba891cadc619020779dda4 100644 (file)
@@ -3,7 +3,9 @@ package Analysis.Disjoint;
 import Analysis.CallGraph.*;
 import Analysis.Liveness;
 import Analysis.ArrayReferencees;
-import Analysis.RBlockRelationAnalysis;
+import Analysis.OoOJava.Accessible;
+import Analysis.OoOJava.RBlockRelationAnalysis;
+import Analysis.FlatIRGraph.*;
 import IR.*;
 import IR.Flat.*;
 import IR.Tree.Modifiers;
@@ -11,99 +13,137 @@ import java.util.*;
 import java.io.*;
 
 
-public class DisjointAnalysis {
-       
-         ///////////////////////////////////////////
-         //
-         //  Public interface to discover possible
-         //  aliases in the program under analysis
-         //
-         ///////////////////////////////////////////
-       
-         public HashSet<AllocSite>
-         getFlaggedAllocationSitesReachableFromTask(TaskDescriptor td) {
-           checkAnalysisComplete();
-           return getFlaggedAllocationSitesReachableFromTaskPRIVATE(td);
-         }
-         
-         public AllocSite getAllocationSiteFromFlatNew(FlatNew fn) {
-                   checkAnalysisComplete();
-                   return getAllocSiteFromFlatNewPRIVATE(fn);
-          }      
-         
-         public AllocSite getAllocationSiteFromHeapRegionNodeID(Integer id) {
-                   checkAnalysisComplete();
-                   return mapHrnIdToAllocSite.get(id);
-         }
-         
-         public Set<HeapRegionNode> hasPotentialSharing(Descriptor taskOrMethod,
-              int paramIndex1,
-              int paramIndex2) {
-                 checkAnalysisComplete();
-                 ReachGraph rg=mapDescriptorToCompleteReachGraph.get(taskOrMethod);
-                 FlatMethod fm=state.getMethodFlat(taskOrMethod);
-                 assert(rg != null);
-                 return rg.mayReachSharedObjects(fm, paramIndex1, paramIndex2);
-         }
-         
-       public Set<HeapRegionNode> hasPotentialSharing(Descriptor taskOrMethod,
-                       int paramIndex, AllocSite alloc) {
-               checkAnalysisComplete();
-               ReachGraph rg = mapDescriptorToCompleteReachGraph.get(taskOrMethod);
-           FlatMethod fm=state.getMethodFlat(taskOrMethod);
-               assert (rg != null);
-               return rg.mayReachSharedObjects(fm, paramIndex, alloc);
-       }
-
-       public Set<HeapRegionNode> hasPotentialSharing(Descriptor taskOrMethod,
-                       AllocSite alloc, int paramIndex) {
-               checkAnalysisComplete();
-               ReachGraph rg  = mapDescriptorToCompleteReachGraph.get(taskOrMethod);
-               FlatMethod fm=state.getMethodFlat(taskOrMethod);
-               assert (rg != null);
-               return rg.mayReachSharedObjects(fm, paramIndex, alloc);
-       }
-
-       public Set<HeapRegionNode> hasPotentialSharing(Descriptor taskOrMethod,
-                       AllocSite alloc1, AllocSite alloc2) {
-               checkAnalysisComplete();
-               ReachGraph rg  = mapDescriptorToCompleteReachGraph.get(taskOrMethod);
-               assert (rg != null);
-               return rg.mayReachSharedObjects(alloc1, alloc2);
-       }
-       
-       public String prettyPrintNodeSet(Set<HeapRegionNode> s) {
-               checkAnalysisComplete();
-
-               String out = "{\n";
-
-               Iterator<HeapRegionNode> i = s.iterator();
-               while (i.hasNext()) {
-                       HeapRegionNode n = i.next();
-
-                       AllocSite as = n.getAllocSite();
-                       if (as == null) {
-                               out += "  " + n.toString() + ",\n";
-                       } else {
-                               out += "  " + n.toString() + ": " + as.toStringVerbose()
-                                               + ",\n";
-                       }
-               }
-
-               out += "}\n";
-               return out;
-       }
-       
+public class DisjointAnalysis implements HeapAnalysis {
+
+  ///////////////////////////////////////////
+  //
+  //  Public interface to discover possible
+  //  sharing in the program under analysis
+  //
+  ///////////////////////////////////////////
+
+  // if an object allocated at the target site may be
+  // reachable from both an object from root1 and an
+  // object allocated at root2, return TRUE
+  public boolean mayBothReachTarget(FlatMethod fm,
+                                    FlatNew fnRoot1,
+                                    FlatNew fnRoot2,
+                                    FlatNew fnTarget) {
+
+    AllocSite asr1 = getAllocationSiteFromFlatNew(fnRoot1);
+    AllocSite asr2 = getAllocationSiteFromFlatNew(fnRoot2);
+    assert asr1.isFlagged();
+    assert asr2.isFlagged();
+
+    AllocSite ast = getAllocationSiteFromFlatNew(fnTarget);
+    ReachGraph rg = getPartial(fm.getMethod() );
+
+    return rg.mayBothReachTarget(asr1, asr2, ast);
+  }
+
+  // similar to the method above, return TRUE if ever
+  // more than one object from the root allocation site
+  // may reach an object from the target site
+  public boolean mayManyReachTarget(FlatMethod fm,
+                                    FlatNew fnRoot,
+                                    FlatNew fnTarget) {
+
+    AllocSite asr = getAllocationSiteFromFlatNew(fnRoot);
+    assert asr.isFlagged();
+
+    AllocSite ast = getAllocationSiteFromFlatNew(fnTarget);
+    ReachGraph rg = getPartial(fm.getMethod() );
+
+    return rg.mayManyReachTarget(asr, ast);
+  }
+
+
+
+
+  public HashSet<AllocSite>
+  getFlaggedAllocationSitesReachableFromTask(TaskDescriptor td) {
+    checkAnalysisComplete();
+    return getFlaggedAllocationSitesReachableFromTaskPRIVATE(td);
+  }
+
+  public AllocSite getAllocationSiteFromFlatNew(FlatNew fn) {
+    checkAnalysisComplete();
+    return getAllocSiteFromFlatNewPRIVATE(fn);
+  }
+
+  public AllocSite getAllocationSiteFromHeapRegionNodeID(Integer id) {
+    checkAnalysisComplete();
+    return mapHrnIdToAllocSite.get(id);
+  }
+
+  public Set<HeapRegionNode> hasPotentialSharing(Descriptor taskOrMethod,
+                                                 int paramIndex1,
+                                                 int paramIndex2) {
+    checkAnalysisComplete();
+    ReachGraph rg=mapDescriptorToCompleteReachGraph.get(taskOrMethod);
+    FlatMethod fm=state.getMethodFlat(taskOrMethod);
+    assert(rg != null);
+    return rg.mayReachSharedObjects(fm, paramIndex1, paramIndex2);
+  }
+
+  public Set<HeapRegionNode> hasPotentialSharing(Descriptor taskOrMethod,
+                                                 int paramIndex, AllocSite alloc) {
+    checkAnalysisComplete();
+    ReachGraph rg = mapDescriptorToCompleteReachGraph.get(taskOrMethod);
+    FlatMethod fm=state.getMethodFlat(taskOrMethod);
+    assert(rg != null);
+    return rg.mayReachSharedObjects(fm, paramIndex, alloc);
+  }
+
+  public Set<HeapRegionNode> hasPotentialSharing(Descriptor taskOrMethod,
+                                                 AllocSite alloc, int paramIndex) {
+    checkAnalysisComplete();
+    ReachGraph rg  = mapDescriptorToCompleteReachGraph.get(taskOrMethod);
+    FlatMethod fm=state.getMethodFlat(taskOrMethod);
+    assert(rg != null);
+    return rg.mayReachSharedObjects(fm, paramIndex, alloc);
+  }
+
+  public Set<HeapRegionNode> hasPotentialSharing(Descriptor taskOrMethod,
+                                                 AllocSite alloc1, AllocSite alloc2) {
+    checkAnalysisComplete();
+    ReachGraph rg  = mapDescriptorToCompleteReachGraph.get(taskOrMethod);
+    assert(rg != null);
+    return rg.mayReachSharedObjects(alloc1, alloc2);
+  }
+
+  public String prettyPrintNodeSet(Set<HeapRegionNode> s) {
+    checkAnalysisComplete();
+
+    String out = "{\n";
+
+    Iterator<HeapRegionNode> i = s.iterator();
+    while (i.hasNext()) {
+      HeapRegionNode n = i.next();
+
+      AllocSite as = n.getAllocSite();
+      if (as == null) {
+        out += "  " + n.toString() + ",\n";
+      } else {
+        out += "  " + n.toString() + ": " + as.toStringVerbose()
+               + ",\n";
+      }
+    }
+
+    out += "}\n";
+    return out;
+  }
+
   // use the methods given above to check every possible sharing class
   // between task parameters and flagged allocation sites reachable
   // from the task
-  public void writeAllSharing(String outputFile, 
+  public void writeAllSharing(String outputFile,
                               String timeReport,
                               String justTime,
                               boolean tabularOutput,
                               int numLines
                               )
-    throws java.io.IOException {
+  throws java.io.IOException {
     checkAnalysisComplete();
 
     BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
@@ -139,17 +179,17 @@ public class DisjointAnalysis {
 
         // skip parameters with types that cannot reference
         // into the heap
-        if( !shouldAnalysisTrack( fm.getParameter( i ).getType() ) ) {
+        if( !shouldAnalysisTrack(fm.getParameter(i).getType() ) ) {
           continue;
         }
-                          
+
         // for the ith parameter check for sharing classes to all
         // higher numbered parameters
         for (int j = i + 1; j < fm.numParameters(); ++j) {
 
           // skip parameters with types that cannot reference
           // into the heap
-          if( !shouldAnalysisTrack( fm.getParameter( j ).getType() ) ) {
+          if( !shouldAnalysisTrack(fm.getParameter(j).getType() ) ) {
             continue;
           }
 
@@ -224,7 +264,7 @@ public class DisjointAnalysis {
       }
     }
 
-               
+
     if (tabularOutput) {
       bw.write(" & " + numSharing + " & " + justTime + " & " + numLines
                + " & " + numMethodsAnalyzed() + " \\\\\n");
@@ -234,15 +274,22 @@ public class DisjointAnalysis {
 
     bw.close();
   }
-       
+
+
+
   // this version of writeAllSharing is for Java programs that have no tasks
-  public void writeAllSharingJava(String outputFile, 
+  // ***********************************
+  // WARNING: THIS DOES NOT DO THE RIGHT THING, REPORTS 0 ALWAYS!
+  // It should use mayBothReachTarget and mayManyReachTarget like
+  // OoOJava does to query analysis results
+  // ***********************************
+  public void writeAllSharingJava(String outputFile,
                                   String timeReport,
                                   String justTime,
                                   boolean tabularOutput,
                                   int numLines
                                   )
-    throws java.io.IOException {
+  throws java.io.IOException {
     checkAnalysisComplete();
 
     assert !state.TASK;
@@ -250,7 +297,7 @@ public class DisjointAnalysis {
     int numSharing = 0;
 
     BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
-    
+
     bw.write("Conducting disjoint reachability analysis with allocation depth = "
              + allocationDepth + "\n");
     bw.write(timeReport + "\n\n");
@@ -300,18 +347,42 @@ public class DisjointAnalysis {
 
     bw.close();
   }
-         
+
+
+
+  public Alloc getCmdLineArgsAlloc() {
+    return getAllocationSiteFromFlatNew( constructedCmdLineArgsNew );
+  }
+  public Alloc getCmdLineArgAlloc() {
+    return getAllocationSiteFromFlatNew( constructedCmdLineArgNew );
+  }
+  public Alloc getCmdLineArgBytesAlloc() {
+    return getAllocationSiteFromFlatNew( constructedCmdLineArgBytesNew );
+  }
+  public Alloc getNewStringLiteralAlloc() {
+    return newStringLiteralAlloc;
+  }
+  public Alloc getNewStringLiteralBytesAlloc() {
+    return newStringLiteralBytesAlloc;
+  }
+
   ///////////////////////////////////////////
   //
   // end public interface
   //
   ///////////////////////////////////////////
 
+
+
   protected void checkAnalysisComplete() {
     if( !analysisComplete ) {
       throw new Error("Warning: public interface method called while analysis is running.");
     }
-  } 
+  }
+
+
+
+
 
 
   // run in faster mode, only when bugs wrung out!
@@ -321,7 +392,7 @@ public class DisjointAnalysis {
   // should attempt to be deterministic
   public static boolean determinismDesired;
 
-  // when we want to enforce determinism in the 
+  // when we want to enforce determinism in the
   // analysis we need to sort descriptors rather
   // than toss them in efficient sets, use this
   public static DescriptorComparator dComp =
@@ -329,22 +400,24 @@ public class DisjointAnalysis {
 
 
   // data from the compiler
-  public State            state;
-  public CallGraph        callGraph;
-  public Liveness         liveness;
+  public State state;
+  public CallGraph callGraph;
+  public Liveness liveness;
   public ArrayReferencees arrayReferencees;
   public RBlockRelationAnalysis rblockRel;
-  public TypeUtil         typeUtil;
-  public int              allocationDepth;
+  public TypeUtil typeUtil;
+  public int allocationDepth;
 
   protected boolean doEffectsAnalysis = false;
   protected EffectsAnalysis effectsAnalysis;
-  
+  protected BuildStateMachines buildStateMachines;
+
+
   // data structure for public interface
-  private Hashtable< Descriptor, HashSet<AllocSite> > 
-    mapDescriptorToAllocSiteSet;
+  private Hashtable< Descriptor, HashSet<AllocSite> >
+  mapDescriptorToAllocSiteSet;
+
 
-  
   // for public interface methods to warn that they
   // are grabbing results during analysis
   private boolean analysisComplete;
@@ -368,66 +441,71 @@ public class DisjointAnalysis {
   // provide the analysis with an explicit
   // top-level context with no parameters
   protected MethodDescriptor mdAnalysisEntry;
-  protected FlatMethod       fmAnalysisEntry;
+  protected FlatMethod fmAnalysisEntry;
 
   // main method defined by source program
   protected MethodDescriptor mdSourceEntry;
 
   // the set of task and/or method descriptors
   // reachable in call graph
-  protected Set<Descriptor> 
-    descriptorsToAnalyze;
+  protected Set<Descriptor>
+  descriptorsToAnalyze;
 
   // current descriptors to visit in fixed-point
   // interprocedural analysis, prioritized by
   // dependency in the call graph
   protected Stack<Descriptor>
-    descriptorsToVisitStack;
-  protected PriorityQueue<DescriptorQWrapper> 
-    descriptorsToVisitQ;
-  
+  descriptorsToVisitStack;
+  protected PriorityQueue<DescriptorQWrapper>
+  descriptorsToVisitQ;
+
   // a duplication of the above structure, but
   // for efficient testing of inclusion
-  protected HashSet<Descriptor> 
-    descriptorsToVisitSet;
+  protected HashSet<Descriptor>
+  descriptorsToVisitSet;
 
   // storage for priorities (doesn't make sense)
   // to add it to the Descriptor class, just in
   // this analysis
-  protected Hashtable<Descriptor, Integer> 
-    mapDescriptorToPriority;
+  protected Hashtable<Descriptor, Integer>
+  mapDescriptorToPriority;
 
   // when analyzing a method and scheduling more:
   // remember set of callee's enqueued for analysis
   // so they can be put on top of the callers in
   // the stack-visit mode
   protected Set<Descriptor>
-    calleesToEnqueue;
+  calleesToEnqueue;
 
   // maps a descriptor to its current partial result
   // from the intraprocedural fixed-point analysis--
   // then the interprocedural analysis settles, this
   // mapping will have the final results for each
   // method descriptor
-  protected Hashtable<Descriptor, ReachGraph> 
-    mapDescriptorToCompleteReachGraph;
+  protected Hashtable<Descriptor, ReachGraph>
+  mapDescriptorToCompleteReachGraph;
 
   // maps a descriptor to its known dependents: namely
   // methods or tasks that call the descriptor's method
   // AND are part of this analysis (reachable from main)
   protected Hashtable< Descriptor, Set<Descriptor> >
-    mapDescriptorToSetDependents;
+  mapDescriptorToSetDependents;
+
+  // if the analysis client wants to flag allocation sites
+  // programmatically, it should provide a set of FlatNew
+  // statements--this may be null if unneeded
+  protected Set<FlatNew> sitesToFlag;
 
   // maps each flat new to one analysis abstraction
   // allocate site object, these exist outside reach graphs
   protected Hashtable<FlatNew, AllocSite>
-    mapFlatNewToAllocSite;
+  mapFlatNewToAllocSite;
 
   // maps intergraph heap region IDs to intergraph
   // allocation sites that created them, a redundant
   // structure for efficiency in some operations
   protected Hashtable<Integer, AllocSite>
-    mapHrnIdToAllocSite;
+  mapHrnIdToAllocSite;
 
   // maps a method to its initial heap model (IHM) that
   // is the set of reachability graphs from every caller
@@ -435,25 +513,28 @@ public class DisjointAnalysis {
   // them separate is that any one call site's contribution
   // to the IHM may changed along the path to the fixed point
   protected Hashtable< Descriptor, Hashtable< FlatCall, ReachGraph > >
-    mapDescriptorToIHMcontributions;
+  mapDescriptorToIHMcontributions;
 
   // additionally, keep a mapping from descriptors to the
   // merged in-coming initial context, because we want this
   // initial context to be STRICTLY MONOTONIC
   protected Hashtable<Descriptor, ReachGraph>
-    mapDescriptorToInitialContext;
+  mapDescriptorToInitialContext;
 
   // make the result for back edges analysis-wide STRICTLY
   // MONOTONIC as well, but notice we use FlatNode as the
   // key for this map: in case we want to consider other
   // nodes as back edge's in future implementations
   protected Hashtable<FlatNode, ReachGraph>
-    mapBackEdgeToMonotone;
+  mapBackEdgeToMonotone;
 
 
   public static final String arrayElementFieldName = "___element_";
   static protected Hashtable<TypeDescriptor, FieldDescriptor>
-    mapTypeToArrayField;
+  mapTypeToArrayField;
+
+
+  protected boolean suppressOutput;
 
   // for controlling DOT file output
   protected boolean writeFinalDOTs;
@@ -463,27 +544,112 @@ public class DisjointAnalysis {
   // partial method result, keep a tally for generating
   // unique filenames
   protected Hashtable<Descriptor, Integer>
-    mapDescriptorToNumUpdates;
-  
-  //map task descriptor to initial task parameter 
+  mapDescriptorToNumUpdates;
+
+  //map task descriptor to initial task parameter
   protected Hashtable<Descriptor, ReachGraph>
-    mapDescriptorToReachGraph;
+  mapDescriptorToReachGraph;
 
   protected PointerMethod pm;
 
-  static protected Hashtable<FlatNode, ReachGraph> fn2rg =
+  //Keeps track of all the reach graphs at every program point
+  //DO NOT USE UNLESS YOU REALLY NEED IT
+  static protected Hashtable<FlatNode, ReachGraph> fn2rgAtEnter =
     new Hashtable<FlatNode, ReachGraph>();
 
-  private Hashtable<FlatCall, Descriptor> fc2enclosing;  
+  static protected Hashtable<FlatNode, ReachGraph> fn2rgAtExit =
+    new Hashtable<FlatNode, ReachGraph>();
+
+
+  private Hashtable<FlatCall, Descriptor> fc2enclosing;
+
+  Accessible accessible;
+
+  
+  // we construct an entry method of flat nodes complete
+  // with a new allocation site to model the command line
+  // args creation just for the analysis, so remember that
+  // allocation site.  Later in code gen we might want to
+  // know if something is pointing-to to the cmd line args
+  // and we can verify by checking the allocation site field.
+  protected FlatNew constructedCmdLineArgsNew;
+  protected FlatNew constructedCmdLineArgNew;
+  protected FlatNew constructedCmdLineArgBytesNew;
+
+  // similar to above, the runtime allocates new strings
+  // for literal nodes, so make up an alloc to model that
+  protected AllocSite      newStringLiteralAlloc;
+  protected AllocSite      newStringLiteralBytesAlloc;
+
+  // both of the above need the descriptor of the field
+  // for the String's value field to reference by the
+  // byte array from the string object
+  protected TypeDescriptor  stringType;
+  protected TypeDescriptor  stringBytesType;
+  protected FieldDescriptor stringBytesField;
+
+
+  protected void initImplicitStringsModel() {
+    
+    ClassDescriptor cdString = typeUtil.getClass( typeUtil.StringClass );
+    assert cdString != null;
+
+
+    stringType = 
+      new TypeDescriptor( cdString );
+
+    stringBytesType =
+      new TypeDescriptor(TypeDescriptor.CHAR).makeArray( state );
+
+
+    stringBytesField = null;
+    Iterator sFieldsItr = cdString.getFields();
+    while( sFieldsItr.hasNext() ) {
+      FieldDescriptor fd = (FieldDescriptor) sFieldsItr.next();
+      if( fd.getSymbol().equals( typeUtil.StringClassValueField ) ) {
+        stringBytesField = fd;
+        break;
+      }
+    }
+    assert stringBytesField != null;
+
+
+    TempDescriptor throwAway1 =
+      new TempDescriptor("stringLiteralTemp_dummy1",
+                         stringType
+                         );
+    FlatNew fnStringLiteral =
+      new FlatNew(stringType,
+                  throwAway1,
+                  false  // is global
+                  );
+    newStringLiteralAlloc
+      = getAllocSiteFromFlatNewPRIVATE( fnStringLiteral );    
+
+
+    TempDescriptor throwAway2 =
+      new TempDescriptor("stringLiteralTemp_dummy2",
+                         stringBytesType
+                         );
+    FlatNew fnStringLiteralBytes =
+      new FlatNew(stringBytesType,
+                  throwAway2,
+                  false  // is global
+                  );
+    newStringLiteralBytesAlloc
+      = getAllocSiteFromFlatNewPRIVATE( fnStringLiteralBytes );    
+  }
+
+
 
 
   // allocate various structures that are not local
   // to a single class method--should be done once
   protected void allocateStructures() {
-    
+
     if( determinismDesired ) {
       // use an ordered set
-      descriptorsToAnalyze = new TreeSet<Descriptor>( dComp );      
+      descriptorsToAnalyze = new TreeSet<Descriptor>(dComp);
     } else {
       // otherwise use a speedy hashset
       descriptorsToAnalyze = new HashSet<Descriptor>();
@@ -498,26 +664,26 @@ public class DisjointAnalysis {
     mapDescriptorToSetDependents =
       new Hashtable< Descriptor, Set<Descriptor> >();
 
-    mapFlatNewToAllocSite = 
+    mapFlatNewToAllocSite =
       new Hashtable<FlatNew, AllocSite>();
 
     mapDescriptorToIHMcontributions =
       new Hashtable< Descriptor, Hashtable< FlatCall, ReachGraph > >();
 
     mapDescriptorToInitialContext =
-      new Hashtable<Descriptor, ReachGraph>();    
+      new Hashtable<Descriptor, ReachGraph>();
 
     mapBackEdgeToMonotone =
       new Hashtable<FlatNode, ReachGraph>();
-    
+
     mapHrnIdToAllocSite =
       new Hashtable<Integer, AllocSite>();
 
-    mapTypeToArrayField = 
+    mapTypeToArrayField =
       new Hashtable <TypeDescriptor, FieldDescriptor>();
 
     if( state.DISJOINTDVISITSTACK ||
-        state.DISJOINTDVISITSTACKEESONTOP 
+        state.DISJOINTDVISITSTACKEESONTOP
         ) {
       descriptorsToVisitStack =
         new Stack<Descriptor>();
@@ -533,15 +699,15 @@ public class DisjointAnalysis {
 
     mapDescriptorToPriority =
       new Hashtable<Descriptor, Integer>();
-    
-    calleesToEnqueue = 
-      new HashSet<Descriptor>();    
+
+    calleesToEnqueue =
+      new HashSet<Descriptor>();
 
     mapDescriptorToAllocSiteSet =
-       new Hashtable<Descriptor,    HashSet<AllocSite> >();
-    
-    mapDescriptorToReachGraph = 
-       new Hashtable<Descriptor, ReachGraph>();
+      new Hashtable<Descriptor,    HashSet<AllocSite> >();
+
+    mapDescriptorToReachGraph =
+      new Hashtable<Descriptor, ReachGraph>();
 
     pm = new PointerMethod();
 
@@ -552,36 +718,76 @@ public class DisjointAnalysis {
 
   // this analysis generates a disjoint reachability
   // graph for every reachable method in the program
-  public DisjointAnalysis( State            s,
-                          TypeUtil         tu,
-                          CallGraph        cg,
-                          Liveness         l,
-                          ArrayReferencees ar,
-                           RBlockRelationAnalysis rra
-                           ) {
-    init( s, tu, cg, l, ar, rra );
+  public DisjointAnalysis(State s,
+                          TypeUtil tu,
+                          CallGraph cg,
+                          Liveness l,
+                          ArrayReferencees ar,
+                          Set<FlatNew> sitesToFlag,
+                          RBlockRelationAnalysis rra
+                          ) {
+    init(s, tu, cg, l, ar, sitesToFlag, rra, null, false);
   }
-  
-  protected void init( State            state,
-                       TypeUtil         typeUtil,
-                       CallGraph        callGraph,
-                       Liveness         liveness,
-                       ArrayReferencees arrayReferencees,
-                       RBlockRelationAnalysis rra
-                       ) {
-         
+
+  public DisjointAnalysis(State s,
+                          TypeUtil tu,
+                          CallGraph cg,
+                          Liveness l,
+                          ArrayReferencees ar,
+                          Set<FlatNew> sitesToFlag,
+                          RBlockRelationAnalysis rra,
+                          boolean suppressOutput
+                          ) {
+    init(s, tu, cg, l, ar, sitesToFlag, rra, null, suppressOutput);
+  }
+
+  public DisjointAnalysis(State s,
+                          TypeUtil tu,
+                          CallGraph cg,
+                          Liveness l,
+                          ArrayReferencees ar,
+                          Set<FlatNew> sitesToFlag,
+                          RBlockRelationAnalysis rra,
+                          BuildStateMachines bsm,
+                          boolean suppressOutput
+                          ) {
+    init(s, tu, cg, l, ar, sitesToFlag, rra, bsm, suppressOutput);
+  }
+
+  protected void init(State state,
+                      TypeUtil typeUtil,
+                      CallGraph callGraph,
+                      Liveness liveness,
+                      ArrayReferencees arrayReferencees,
+                      Set<FlatNew> sitesToFlag,
+                      RBlockRelationAnalysis rra,
+                      BuildStateMachines bsm,
+                      boolean suppressOutput
+                      ) {
+
     analysisComplete = false;
-    
-    this.state                   = state;
-    this.typeUtil                = typeUtil;
-    this.callGraph               = callGraph;
-    this.liveness                = liveness;
-    this.arrayReferencees        = arrayReferencees;
-    this.rblockRel               = rra;
+
+    this.state              = state;
+    this.typeUtil           = typeUtil;
+    this.callGraph          = callGraph;
+    this.liveness           = liveness;
+    this.arrayReferencees   = arrayReferencees;
+    this.sitesToFlag        = sitesToFlag;
+    this.rblockRel          = rra;
+    this.suppressOutput     = suppressOutput;
+    this.buildStateMachines = bsm;
 
     if( rblockRel != null ) {
       doEffectsAnalysis = true;
       effectsAnalysis   = new EffectsAnalysis();
+
+      EffectsAnalysis.state              = state;
+      EffectsAnalysis.buildStateMachines = buildStateMachines;
+
+      //note: instead of reachgraph's isAccessible, using the result of accessible analysis
+      //since accessible gives us more accurate results
+      accessible=new Accessible(state, callGraph, rra, liveness);
+      accessible.doAnalysis();
     }
 
     this.allocationDepth         = state.DISJOINTALLOCDEPTH;
@@ -600,16 +806,19 @@ public class DisjointAnalysis {
     this.snapNodeCounter         = 0; // count nodes from 0
 
     assert
-      state.DISJOINTDVISITSTACK ||
-      state.DISJOINTDVISITPQUE  ||
-      state.DISJOINTDVISITSTACKEESONTOP;
+    state.DISJOINTDVISITSTACK ||
+    state.DISJOINTDVISITPQUE  ||
+    state.DISJOINTDVISITSTACKEESONTOP;
     assert !(state.DISJOINTDVISITSTACK && state.DISJOINTDVISITPQUE);
     assert !(state.DISJOINTDVISITSTACK && state.DISJOINTDVISITSTACKEESONTOP);
     assert !(state.DISJOINTDVISITPQUE  && state.DISJOINTDVISITSTACKEESONTOP);
-           
+
     // set some static configuration for ReachGraphs
     ReachGraph.allocationDepth = allocationDepth;
     ReachGraph.typeUtil        = typeUtil;
+    ReachGraph.state           = state;
+
+    ReachGraph.initOutOfScopeTemps();
 
     ReachGraph.debugCallSiteVisitStartCapture
       = state.DISJOINTDEBUGCALLVISITTOSTART;
@@ -620,61 +829,81 @@ public class DisjointAnalysis {
     ReachGraph.debugCallSiteStopAfter
       = state.DISJOINTDEBUGCALLSTOPAFTER;
 
-    ReachGraph.debugCallSiteVisitCounter 
-      = 0; // count visits from 1, is incremented before first visit
-    
-    
+    ReachGraph.debugCallSiteVisitCounter
+      = 0; // count visits from 1, is incremented before first visit    
+
+
+
+    if( suppressOutput ) {
+      System.out.println("* Running disjoint reachability analysis with output suppressed! *");
+    }
+
 
     allocateStructures();
 
+    initImplicitStringsModel();
+
+
+
     double timeStartAnalysis = (double) System.nanoTime();
 
     // start interprocedural fixed-point computation
     try {
       analyzeMethods();
     } catch( IOException e ) {
-      throw new Error( "IO Exception while writing disjointness analysis output." );
+      throw new Error("IO Exception while writing disjointness analysis output.");
     }
 
     analysisComplete=true;
 
     double timeEndAnalysis = (double) System.nanoTime();
-    double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
-    String treport = String.format( "The reachability analysis took %.3f sec.", dt );
-    String justtime = String.format( "%.2f", dt );
-    System.out.println( treport );
+    double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow(10.0, 9.0) );
+
+    String treport;
+    if( sitesToFlag != null ) {
+      treport = String.format("Disjoint reachability analysis flagged %d sites and took %.3f sec.", sitesToFlag.size(), dt);
+      if(sitesToFlag.size()>0) {
+        treport+="\nFlagged sites:"+"\n"+sitesToFlag.toString();
+      }
+    } else {
+      treport = String.format("Disjoint reachability analysis took %.3f sec.", dt);
+    }
+    String justtime = String.format("%.2f", dt);
+    System.out.println(treport);
+
 
     try {
       if( writeFinalDOTs && !writeAllIncrementalDOTs ) {
-        writeFinalGraphs();      
+        writeFinalGraphs();
       }
 
-      if( state.DISJOINTWRITEIHMS ) {
+      if( state.DISJOINTWRITEIHMS && !suppressOutput ) {
         writeFinalIHMs();
       }
 
-      if( state.DISJOINTWRITEINITCONTEXTS ) {
+      if( state.DISJOINTWRITEINITCONTEXTS && !suppressOutput ) {
         writeInitialContexts();
       }
 
-      if( state.DISJOINTALIASFILE != null ) {
+      if( state.DISJOINTALIASFILE != null && !suppressOutput ) {
         if( state.TASK ) {
           writeAllSharing(state.DISJOINTALIASFILE, treport, justtime, state.DISJOINTALIASTAB, state.lines);
         } else {
-          writeAllSharingJava(state.DISJOINTALIASFILE, 
-                              treport, 
-                              justtime, 
-                              state.DISJOINTALIASTAB, 
+          writeAllSharingJava(state.DISJOINTALIASFILE,
+                              treport,
+                              justtime,
+                              state.DISJOINTALIASTAB,
                               state.lines
                               );
         }
       }
-    } catch( IOException e ) {
-      throw new Error( "IO Exception while writing disjointness analysis output." );
-    }
 
-    if( doEffectsAnalysis ) {
-      effectsAnalysis.writeEffects( "effects.txt" );
+      if( state.RCR ) {
+        buildStateMachines.writeStateMachines();
+      }
+
+    } catch( IOException e ) {
+      throw new Error("IO Exception while writing disjointness analysis output.");
     }
   }
 
@@ -689,58 +918,63 @@ public class DisjointAnalysis {
       return !descriptorsToVisitQ.isEmpty();
     }
 
-    throw new Error( "Neither descriptor visiting mode set" );
+    throw new Error("Neither descriptor visiting mode set");
   }
 
 
   // fixed-point computation over the call graph--when a
   // method's callees are updated, it must be reanalyzed
-  protected void analyzeMethods() throws java.io.IOException {  
+  protected void analyzeMethods() throws java.io.IOException {
 
     // task or non-task (java) mode determines what the roots
     // of the call chain are, and establishes the set of methods
     // reachable from the roots that will be analyzed
-    
+
     if( state.TASK ) {
-      System.out.println( "Bamboo mode..." );
-      
-      Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();      
+      if( !suppressOutput ) {
+        System.out.println("Bamboo mode...");
+      }
+
+      Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
       while( taskItr.hasNext() ) {
         TaskDescriptor td = (TaskDescriptor) taskItr.next();
-        if( !descriptorsToAnalyze.contains( td ) ) {
+        if( !descriptorsToAnalyze.contains(td) ) {
           // add all methods transitively reachable from the
           // tasks as well
-          descriptorsToAnalyze.add( td );
-          descriptorsToAnalyze.addAll( callGraph.getAllMethods( td ) );
-        }        
+          descriptorsToAnalyze.add(td);
+          descriptorsToAnalyze.addAll(callGraph.getAllMethods(td) );
+        }
       }
-      
+
     } else {
-      System.out.println( "Java mode..." );
+      if( !suppressOutput ) {
+        System.out.println("Java mode...");
+      }
 
       // add all methods transitively reachable from the
       // source's main to set for analysis
       mdSourceEntry = typeUtil.getMain();
-      descriptorsToAnalyze.add( mdSourceEntry );
-      descriptorsToAnalyze.addAll( callGraph.getAllMethods( mdSourceEntry ) );
-      
+      descriptorsToAnalyze.add(mdSourceEntry);
+      descriptorsToAnalyze.addAll(callGraph.getAllMethods(mdSourceEntry) );
+
       // fabricate an empty calling context that will call
       // the source's main, but call graph doesn't know
       // about it, so explicitly add it
-      makeAnalysisEntryMethod( mdSourceEntry );
-      descriptorsToAnalyze.add( mdAnalysisEntry );
+      makeAnalysisEntryMethod(mdSourceEntry);
+      descriptorsToAnalyze.add(mdAnalysisEntry);
     }
 
 
-    // now, depending on the interprocedural mode for visiting 
+
+    // now, depending on the interprocedural mode for visiting
     // methods, set up the needed data structures
 
     if( state.DISJOINTDVISITPQUE ) {
-    
-      // topologically sort according to the call graph so 
+
+      // topologically sort according to the call graph so
       // leaf calls are last, helps build contexts up first
-      LinkedList<Descriptor> sortedDescriptors = 
-        topologicalSort( descriptorsToAnalyze );
+      LinkedList<Descriptor> sortedDescriptors =
+        topologicalSort(descriptorsToAnalyze);
 
       // add sorted descriptors to priority queue, and duplicate
       // the queue as a set for efficiently testing whether some
@@ -752,32 +986,32 @@ public class DisjointAnalysis {
       // of the sorted list a low number (highest priority)
       while( !sortedDescriptors.isEmpty() ) {
         Descriptor d = sortedDescriptors.removeFirst();
-        mapDescriptorToPriority.put( d, new Integer( p ) );
-        descriptorsToVisitQ.add( new DescriptorQWrapper( p, d ) );
-        descriptorsToVisitSet.add( d );
+        mapDescriptorToPriority.put(d, new Integer(p) );
+        descriptorsToVisitQ.add(new DescriptorQWrapper(p, d) );
+        descriptorsToVisitSet.add(d);
         ++p;
       }
 
     } else if( state.DISJOINTDVISITSTACK ||
-               state.DISJOINTDVISITSTACKEESONTOP 
+               state.DISJOINTDVISITSTACKEESONTOP
                ) {
       // if we're doing the stack scheme, just throw the root
       // method or tasks on the stack
       if( state.TASK ) {
-        Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();      
+        Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
         while( taskItr.hasNext() ) {
-         TaskDescriptor td = (TaskDescriptor) taskItr.next();
-          descriptorsToVisitStack.add( td );
-          descriptorsToVisitSet.add( td );
+          TaskDescriptor td = (TaskDescriptor) taskItr.next();
+          descriptorsToVisitStack.add(td);
+          descriptorsToVisitSet.add(td);
         }
-        
+
       } else {
-        descriptorsToVisitStack.add( mdAnalysisEntry );
-        descriptorsToVisitSet.add( mdAnalysisEntry );
+        descriptorsToVisitStack.add(mdAnalysisEntry);
+        descriptorsToVisitSet.add(mdAnalysisEntry);
       }
 
     } else {
-      throw new Error( "Unknown method scheduling mode" );
+      throw new Error("Unknown method scheduling mode");
     }
 
 
@@ -794,8 +1028,8 @@ public class DisjointAnalysis {
         d = descriptorsToVisitQ.poll().getDescriptor();
       }
 
-      assert descriptorsToVisitSet.contains( d );
-      descriptorsToVisitSet.remove( d );
+      assert descriptorsToVisitSet.contains(d);
+      descriptorsToVisitSet.remove(d);
 
       // because the task or method descriptor just extracted
       // was in the "to visit" set it either hasn't been analyzed
@@ -805,37 +1039,39 @@ public class DisjointAnalysis {
       // If there is a change detected, add any methods/tasks
       // that depend on this one to the "to visit" set.
 
-      System.out.println( "Analyzing " + d );
+      if( !suppressOutput ) {
+        System.out.println("Analyzing " + d);
+      }
 
       if( state.DISJOINTDVISITSTACKEESONTOP ) {
         assert calleesToEnqueue.isEmpty();
       }
 
-      ReachGraph rg     = analyzeMethod( d );
-      ReachGraph rgPrev = getPartial( d );
-      
-      if( !rg.equals( rgPrev ) ) {
-        setPartial( d, rg );
-        
+      ReachGraph rg     = analyzeMethod(d);
+      ReachGraph rgPrev = getPartial(d);
+
+      if( !rg.equals(rgPrev) ) {
+        setPartial(d, rg);
+
         if( state.DISJOINTDEBUGSCHEDULING ) {
-          System.out.println( "  complete graph changed, scheduling callers for analysis:" );
+          System.out.println("  complete graph changed, scheduling callers for analysis:");
         }
 
         // results for d changed, so enqueue dependents
         // of d for further analysis
-       Iterator<Descriptor> depsItr = getDependents( d ).iterator();
-       while( depsItr.hasNext() ) {
-         Descriptor dNext = depsItr.next();
-          enqueue( dNext );
+        Iterator<Descriptor> depsItr = getDependents(d).iterator();
+        while( depsItr.hasNext() ) {
+          Descriptor dNext = depsItr.next();
+          enqueue(dNext);
 
           if( state.DISJOINTDEBUGSCHEDULING ) {
-            System.out.println( "    "+dNext );
+            System.out.println("    "+dNext);
           }
-       }
+        }
       }
 
       // whether or not the method under analysis changed,
-      // we may have some callees that are scheduled for 
+      // we may have some callees that are scheduled for
       // more analysis, and they should go on the top of
       // the stack now (in other method-visiting modes they
       // are already enqueued at this point
@@ -843,38 +1079,38 @@ public class DisjointAnalysis {
         Iterator<Descriptor> depsItr = calleesToEnqueue.iterator();
         while( depsItr.hasNext() ) {
           Descriptor dNext = depsItr.next();
-          enqueue( dNext );
+          enqueue(dNext);
         }
         calleesToEnqueue.clear();
-      }     
+      }
 
-    }   
+    }
   }
 
-  protected ReachGraph analyzeMethod( Descriptor d ) 
-    throws java.io.IOException {
+  protected ReachGraph analyzeMethod(Descriptor d)
+  throws java.io.IOException {
 
     // get the flat code for this descriptor
     FlatMethod fm;
     if( d == mdAnalysisEntry ) {
       fm = fmAnalysisEntry;
     } else {
-      fm = state.getMethodFlat( d );
+      fm = state.getMethodFlat(d);
     }
-    pm.analyzeMethod( fm );
+    pm.analyzeMethod(fm);
 
     // intraprocedural work set
     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
-    flatNodesToVisit.add( fm );
+    flatNodesToVisit.add(fm);
 
     // if determinism is desired by client, shadow the
     // set with a queue to make visit order deterministic
     Queue<FlatNode> flatNodesToVisitQ = null;
     if( determinismDesired ) {
       flatNodesToVisitQ = new LinkedList<FlatNode>();
-      flatNodesToVisitQ.add( fm );
+      flatNodesToVisitQ.add(fm);
     }
-    
+
     // mapping of current partial results
     Hashtable<FlatNode, ReachGraph> mapFlatNodeToReachGraph =
       new Hashtable<FlatNode, ReachGraph>();
@@ -883,16 +1119,33 @@ public class DisjointAnalysis {
     // the final, conservative approximation of the entire method
     HashSet<FlatReturnNode> setReturns = new HashSet<FlatReturnNode>();
 
+
+
+    boolean snapThisMethod = false;
+    if( takeDebugSnapshots && d instanceof MethodDescriptor ) {
+      MethodDescriptor mdThisMethod = (MethodDescriptor)d;
+      ClassDescriptor  cdThisMethod = mdThisMethod.getClassDesc();
+      if( cdThisMethod != null ) {
+        snapThisMethod = 
+          descSymbolDebug.equals( cdThisMethod.getSymbol()+
+                                  "."+
+                                  mdThisMethod.getSymbol()
+                                  );
+      }
+    }
+
+
+
     while( !flatNodesToVisit.isEmpty() ) {
 
-      FlatNode fn;      
+      FlatNode fn;
       if( determinismDesired ) {
         assert !flatNodesToVisitQ.isEmpty();
         fn = flatNodesToVisitQ.remove();
       } else {
         fn = flatNodesToVisit.iterator().next();
       }
-      flatNodesToVisit.remove( fn );
+      flatNodesToVisit.remove(fn);
 
       // effect transfer function defined by this node,
       // then compare it to the old graph at this node
@@ -900,62 +1153,58 @@ public class DisjointAnalysis {
 
       ReachGraph rg = new ReachGraph();
       TaskDescriptor taskDesc;
-      if(fn instanceof FlatMethod && (taskDesc=((FlatMethod)fn).getTask())!=null){
-         if(mapDescriptorToReachGraph.containsKey(taskDesc)){
-                 // retrieve existing reach graph if it is not first time
-                 rg=mapDescriptorToReachGraph.get(taskDesc);
-         }else{
-                 // create initial reach graph for a task
-                 rg=createInitialTaskReachGraph((FlatMethod)fn);
-                 rg.globalSweep();
-                 mapDescriptorToReachGraph.put(taskDesc, rg);
-         }
+      if(fn instanceof FlatMethod && (taskDesc=((FlatMethod)fn).getTask())!=null) {
+        if(mapDescriptorToReachGraph.containsKey(taskDesc)) {
+          // retrieve existing reach graph if it is not first time
+          rg=mapDescriptorToReachGraph.get(taskDesc);
+        } else {
+          // create initial reach graph for a task
+          rg=createInitialTaskReachGraph((FlatMethod)fn);
+          rg.globalSweep();
+          mapDescriptorToReachGraph.put(taskDesc, rg);
+        }
       }
 
       // start by merging all node's parents' graphs
       for( int i = 0; i < pm.numPrev(fn); ++i ) {
-       FlatNode pn = pm.getPrev(fn,i);
-       if( mapFlatNodeToReachGraph.containsKey( pn ) ) {
-         ReachGraph rgParent = mapFlatNodeToReachGraph.get( pn );
-         rg.merge( rgParent );
-       }
+        FlatNode pn = pm.getPrev(fn,i);
+        if( mapFlatNodeToReachGraph.containsKey(pn) ) {
+          ReachGraph rgParent = mapFlatNodeToReachGraph.get(pn);
+          rg.merge(rgParent);
+        }
       }
-      
 
-      if( takeDebugSnapshots && 
-         d.getSymbol().equals( descSymbolDebug ) 
-          ) {
-       debugSnapshot( rg, fn, true );
+
+      if( snapThisMethod ) {
+        debugSnapshot(rg, fn, true);
       }
 
 
       // modify rg with appropriate transfer function
-      rg = analyzeFlatNode( d, fm, fn, setReturns, rg );
+      rg = analyzeFlatNode(d, fm, fn, setReturns, rg);
 
 
-      if( takeDebugSnapshots && 
-         d.getSymbol().equals( descSymbolDebug ) 
-          ) {
-       debugSnapshot( rg, fn, false );
+      if( snapThisMethod ) {
+        debugSnapshot(rg, fn, false);
         ++snapNodeCounter;
       }
-          
+
 
       // if the results of the new graph are different from
       // the current graph at this node, replace the graph
       // with the update and enqueue the children
-      ReachGraph rgPrev = mapFlatNodeToReachGraph.get( fn );
-      if( !rg.equals( rgPrev ) ) {
-       mapFlatNodeToReachGraph.put( fn, rg );
+      ReachGraph rgPrev = mapFlatNodeToReachGraph.get(fn);
+      if( !rg.equals(rgPrev) ) {
+        mapFlatNodeToReachGraph.put(fn, rg);
 
-       for( int i = 0; i < pm.numNext( fn ); i++ ) {
-         FlatNode nn = pm.getNext( fn, i );
+        for( int i = 0; i < pm.numNext(fn); i++ ) {
+          FlatNode nn = pm.getNext(fn, i);
 
-         flatNodesToVisit.add( nn );
+          flatNodesToVisit.add(nn);
           if( determinismDesired ) {
-            flatNodesToVisitQ.add( nn );
+            flatNodesToVisitQ.add(nn);
           }
-       }
+        }
       }
     }
 
@@ -970,27 +1219,25 @@ public class DisjointAnalysis {
     while( retItr.hasNext() ) {
       FlatReturnNode frn = (FlatReturnNode) retItr.next();
 
-      assert mapFlatNodeToReachGraph.containsKey( frn );
-      ReachGraph rgRet = mapFlatNodeToReachGraph.get( frn );
+      assert mapFlatNodeToReachGraph.containsKey(frn);
+      ReachGraph rgRet = mapFlatNodeToReachGraph.get(frn);
 
-      completeGraph.merge( rgRet );
+      completeGraph.merge(rgRet);
     }
 
 
-    if( takeDebugSnapshots && 
-        d.getSymbol().equals( descSymbolDebug ) 
-        ) {
+    if( snapThisMethod ) {
       // increment that we've visited the debug snap
       // method, and reset the node counter
-      System.out.println( "    @@@ debug snap at visit "+snapVisitCounter );
+      System.out.println("    @@@ debug snap at visit "+snapVisitCounter);
       ++snapVisitCounter;
       snapNodeCounter = 0;
 
-      if( snapVisitCounter == visitStartCapture + numVisitsToCapture && 
-          stopAfterCapture 
+      if( snapVisitCounter == visitStartCapture + numVisitsToCapture &&
+          stopAfterCapture
           ) {
-        System.out.println( "!!! Stopping analysis after debug snap captures. !!!" );
-        System.exit( 0 );
+        System.out.println("!!! Stopping analysis after debug snap captures. !!!");
+        System.exit(0);
       }
     }
 
@@ -998,72 +1245,105 @@ public class DisjointAnalysis {
     return completeGraph;
   }
 
-  
+
   protected ReachGraph
-    analyzeFlatNode( Descriptor              d,
-                     FlatMethod              fmContaining,
-                     FlatNode                fn,
-                     HashSet<FlatReturnNode> setRetNodes,
-                     ReachGraph              rg
-                     ) throws java.io.IOException {
+  analyzeFlatNode(Descriptor d,
+                  FlatMethod fmContaining,
+                  FlatNode fn,
+                  HashSet<FlatReturnNode> setRetNodes,
+                  ReachGraph rg
+                  ) throws java.io.IOException {
+
 
-    
     // any variables that are no longer live should be
     // nullified in the graph to reduce edges
     //rg.nullifyDeadVars( liveness.getLiveInTemps( fmContaining, fn ) );
 
-    /*
-      if( doEffectsAnalysis &&  && fmContaining != fmAnalysisEntry
-        rra.isEndOfRegion(fn)){
-      rg.clearAccessibleVarSet();
-      also need to clear stall mapping
-    }
-    */
-         
-    TempDescriptor  lhs;
-    TempDescriptor  rhs;
+    TempDescriptor lhs;
+    TempDescriptor rhs;
     FieldDescriptor fld;
+    TypeDescriptor tdElement;
+    FieldDescriptor fdElement;
+    FlatSESEEnterNode sese;
+    FlatSESEExitNode fsexn;
+
+    //Stores the flatnode's reach graph at enter
+    ReachGraph rgOnEnter = new ReachGraph();
+    rgOnEnter.merge(rg);
+    fn2rgAtEnter.put(fn, rgOnEnter);
+
+
 
     // use node type to decide what transfer function
     // to apply to the reachability graph
     switch( fn.kind() ) {
 
+    case FKind.FlatGenReachNode: {
+      FlatGenReachNode fgrn = (FlatGenReachNode) fn;
+
+      System.out.println("  Generating reach graph for program point: "+fgrn.getGraphName() );
+
+
+      rg.writeGraph("genReach"+fgrn.getGraphName(),
+                    true,     // write labels (variables)
+                    false, //true,    // selectively hide intermediate temp vars
+                    false, //true,     // prune unreachable heap regions
+                    true,    // hide reachability altogether
+                    true,    // hide subset reachability states
+                    true,     // hide predicates
+                    true); //false);    // hide edge taints
+    } break;
+
+
     case FKind.FlatMethod: {
       // construct this method's initial heap model (IHM)
       // since we're working on the FlatMethod, we know
       // the incoming ReachGraph 'rg' is empty
 
-      Hashtable<FlatCall, ReachGraph> heapsFromCallers = 
-        getIHMcontributions( d );
+      Hashtable<FlatCall, ReachGraph> heapsFromCallers =
+        getIHMcontributions(d);
 
       Set entrySet = heapsFromCallers.entrySet();
       Iterator itr = entrySet.iterator();
       while( itr.hasNext() ) {
-        Map.Entry  me        = (Map.Entry)  itr.next();
-        FlatCall   fc        = (FlatCall)   me.getKey();
+        Map.Entry me        = (Map.Entry)itr.next();
+        FlatCall fc        = (FlatCall)   me.getKey();
         ReachGraph rgContrib = (ReachGraph) me.getValue();
 
-        assert fc.getMethod().equals( d );
+        assert fc.getMethod().equals(d);
 
-        rg.merge( rgContrib );
+        rg.merge(rgContrib);
       }
 
       // additionally, we are enforcing STRICT MONOTONICITY for the
       // method's initial context, so grow the context by whatever
       // the previously computed context was, and put the most
       // up-to-date context back in the map
-      ReachGraph rgPrevContext = mapDescriptorToInitialContext.get( d );
-      rg.merge( rgPrevContext );      
-      mapDescriptorToInitialContext.put( d, rg );
+      ReachGraph rgPrevContext = mapDescriptorToInitialContext.get(d);
+      rg.merge(rgPrevContext);
+      mapDescriptorToInitialContext.put(d, rg);
 
     } break;
-      
+
     case FKind.FlatOpNode:
       FlatOpNode fon = (FlatOpNode) fn;
       if( fon.getOp().getOp() == Operation.ASSIGN ) {
-       lhs = fon.getDest();
-       rhs = fon.getLeft();
-       rg.assignTempXEqualToTempY( lhs, rhs );
+        lhs = fon.getDest();
+        rhs = fon.getLeft();
+
+        // before transfer, do effects analysis support
+        if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+          if(rblockRel.isPotentialStallSite(fn)) {
+            // x gets status of y
+//            if(!rg.isAccessible(rhs)){
+            if(!accessible.isAccessible(fn, rhs)) {
+              rg.makeInaccessible(lhs);
+            }
+          }
+        }
+
+        // transfer func
+        rg.assignTempXEqualToTempY(lhs, rhs);
       }
       break;
 
@@ -1074,147 +1354,336 @@ public class DisjointAnalysis {
 
       TypeDescriptor td = fcn.getType();
       assert td != null;
-      
-      rg.assignTempXEqualToCastedTempY( lhs, rhs, td );
+
+      // before transfer, do effects analysis support
+      if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+        if(rblockRel.isPotentialStallSite(fn)) {
+          // x gets status of y
+//          if(!rg.isAccessible(rhs)){
+          if(!accessible.isAccessible(fn,rhs)) {
+            rg.makeInaccessible(lhs);
+          }
+        }
+      }
+
+      // transfer func
+      rg.assignTempXEqualToCastedTempY(lhs, rhs, td);
       break;
 
     case FKind.FlatFieldNode:
       FlatFieldNode ffn = (FlatFieldNode) fn;
+
       lhs = ffn.getDst();
       rhs = ffn.getSrc();
       fld = ffn.getField();
-      if( shouldAnalysisTrack( fld.getType() ) ) {
-       rg.assignTempXEqualToTempYFieldF( lhs, rhs, fld );
 
-        if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
-          effectsAnalysis.analyzeFlatFieldNode( rg, rhs, fld );          
+      // before graph transform, possible inject
+      // a stall-site taint
+      if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+
+        if(rblockRel.isPotentialStallSite(fn)) {
+          // x=y.f, stall y if not accessible
+          // contributes read effects on stall site of y
+//          if(!rg.isAccessible(rhs)) {
+          if(!accessible.isAccessible(fn,rhs)) {
+            rg.taintStallSite(fn, rhs);
+          }
+
+          // after this, x and y are accessbile.
+          rg.makeAccessible(lhs);
+          rg.makeAccessible(rhs);
         }
-      }          
+      }
+
+      if( shouldAnalysisTrack(fld.getType() ) ) {
+        // transfer func
+        rg.assignTempXEqualToTempYFieldF(lhs, rhs, fld, fn);
+      }
+
+      // after transfer, use updated graph to
+      // do effects analysis
+      if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+        effectsAnalysis.analyzeFlatFieldNode(rg, rhs, fld, fn);
+      }
       break;
 
     case FKind.FlatSetFieldNode:
       FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
+
       lhs = fsfn.getDst();
       fld = fsfn.getField();
       rhs = fsfn.getSrc();
 
-      if( shouldAnalysisTrack( fld.getType() ) ) {
-        boolean strongUpdate = rg.assignTempXFieldFEqualToTempY( lhs, fld, rhs );
+      boolean strongUpdate = false;
 
-        if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
-          effectsAnalysis.analyzeFlatSetFieldNode( rg, lhs, fld, strongUpdate );
+      // before transfer func, possibly inject
+      // stall-site taints
+      if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+
+        if(rblockRel.isPotentialStallSite(fn)) {
+          // x.y=f , stall x and y if they are not accessible
+          // also contribute write effects on stall site of x
+//          if(!rg.isAccessible(lhs)) {
+          if(!accessible.isAccessible(fn,lhs)) {
+            rg.taintStallSite(fn, lhs);
+          }
+
+//          if(!rg.isAccessible(rhs)) {
+          if(!accessible.isAccessible(fn,rhs)) {
+            rg.taintStallSite(fn, rhs);
+          }
+
+          // accessible status update
+          rg.makeAccessible(lhs);
+          rg.makeAccessible(rhs);
         }
-      }           
+      }
+
+      if( shouldAnalysisTrack(fld.getType() ) ) {
+        // transfer func
+        strongUpdate = rg.assignTempXFieldFEqualToTempY(lhs, fld, rhs, fn);
+      }
+
+      // use transformed graph to do effects analysis
+      if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+        effectsAnalysis.analyzeFlatSetFieldNode(rg, lhs, fld, fn, strongUpdate);
+      }
       break;
 
     case FKind.FlatElementNode:
       FlatElementNode fen = (FlatElementNode) fn;
+
       lhs = fen.getDst();
       rhs = fen.getSrc();
-      if( shouldAnalysisTrack( lhs.getType() ) ) {
 
-       assert rhs.getType() != null;
-       assert rhs.getType().isArray();
-       
-       TypeDescriptor  tdElement = rhs.getType().dereference();
-       FieldDescriptor fdElement = getArrayField( tdElement );
-  
-       rg.assignTempXEqualToTempYFieldF( lhs, rhs, fdElement );
-        
-        if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
-          effectsAnalysis.analyzeFlatFieldNode( rg, rhs, fdElement );          
+      assert rhs.getType() != null;
+      assert rhs.getType().isArray();
+
+      tdElement = rhs.getType().dereference();
+      fdElement = getArrayField(tdElement);
+
+      // before transfer func, possibly inject
+      // stall-site taint
+      if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+        if(rblockRel.isPotentialStallSite(fn)) {
+          // x=y.f, stall y if not accessible
+          // contributes read effects on stall site of y
+          // after this, x and y are accessbile.
+//          if(!rg.isAccessible(rhs)) {
+          if(!accessible.isAccessible(fn,rhs)) {
+            rg.taintStallSite(fn, rhs);
+          }
+
+          rg.makeAccessible(lhs);
+          rg.makeAccessible(rhs);
         }
       }
+
+      if( shouldAnalysisTrack(lhs.getType() ) ) {
+        // transfer func
+        rg.assignTempXEqualToTempYFieldF(lhs, rhs, fdElement, fn);
+      }
+
+      // use transformed graph to do effects analysis
+      if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+        effectsAnalysis.analyzeFlatFieldNode(rg, rhs, fdElement, fn);
+      }
       break;
 
     case FKind.FlatSetElementNode:
       FlatSetElementNode fsen = (FlatSetElementNode) fn;
 
-      if( arrayReferencees.doesNotCreateNewReaching( fsen ) ) {
-       // skip this node if it cannot create new reachability paths
-        break;
-      }
-
       lhs = fsen.getDst();
       rhs = fsen.getSrc();
-      if( shouldAnalysisTrack( rhs.getType() ) ) {
 
-       assert lhs.getType() != null;
-       assert lhs.getType().isArray();
-       
-       TypeDescriptor  tdElement = lhs.getType().dereference();
-       FieldDescriptor fdElement = getArrayField( tdElement );
+      assert lhs.getType() != null;
+      assert lhs.getType().isArray();
 
-       rg.assignTempXFieldFEqualToTempY( lhs, fdElement, rhs );
+      tdElement = lhs.getType().dereference();
+      fdElement = getArrayField(tdElement);
 
-        if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
-          effectsAnalysis.analyzeFlatSetFieldNode( rg, lhs, fdElement,
-                                                   false );
+      // before transfer func, possibly inject
+      // stall-site taints
+      if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+
+        if(rblockRel.isPotentialStallSite(fn)) {
+          // x.y=f , stall x and y if they are not accessible
+          // also contribute write effects on stall site of x
+//          if(!rg.isAccessible(lhs)) {
+          if(!accessible.isAccessible(fn,lhs)) {
+            rg.taintStallSite(fn, lhs);
+          }
+
+//          if(!rg.isAccessible(rhs)) {
+          if(!accessible.isAccessible(fn,rhs)) {
+            rg.taintStallSite(fn, rhs);
+          }
+
+          // accessible status update
+          rg.makeAccessible(lhs);
+          rg.makeAccessible(rhs);
         }
       }
+
+      if( shouldAnalysisTrack(rhs.getType() ) ) {
+        // transfer func, BUT
+        // skip this node if it cannot create new reachability paths
+        if( !arrayReferencees.doesNotCreateNewReaching(fsen) ) {
+          rg.assignTempXFieldFEqualToTempY(lhs, fdElement, rhs, fn);
+        }
+      }
+
+      // use transformed graph to do effects analysis
+      if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+        effectsAnalysis.analyzeFlatSetFieldNode(rg, lhs, fdElement, fn,
+                                                false);
+      }
       break;
-      
+
     case FKind.FlatNew:
       FlatNew fnn = (FlatNew) fn;
       lhs = fnn.getDst();
-      if( shouldAnalysisTrack( lhs.getType() ) ) {
-       AllocSite as = getAllocSiteFromFlatNewPRIVATE( fnn );   
-       rg.assignTempEqualToNewAlloc( lhs, as );
+      if( shouldAnalysisTrack(lhs.getType() ) ) {
+        AllocSite as = getAllocSiteFromFlatNewPRIVATE(fnn);
+
+        // before transform, support effects analysis
+        if (doEffectsAnalysis && fmContaining != fmAnalysisEntry) {
+          if (rblockRel.isPotentialStallSite(fn)) {
+            // after creating new object, lhs is accessible
+            rg.makeAccessible(lhs);
+          }
+        }
+
+        // transfer func
+        rg.assignTempEqualToNewAlloc(lhs, as);
       }
       break;
 
+      
+    case FKind.FlatLiteralNode:
+      // BIG NOTE: this transfer function is only here for
+      // points-to information for String literals.  That's it.
+      // Effects and disjoint reachability and all of that don't
+      // care about references to literals.
+      FlatLiteralNode fln = (FlatLiteralNode) fn;
+
+      if( fln.getType().equals( stringType ) ) {
+        rg.assignTempEqualToStringLiteral( fln.getDst(),
+                                           newStringLiteralAlloc,
+                                           newStringLiteralBytesAlloc,
+                                           stringBytesField );
+      }      
+      break;
+
+
     case FKind.FlatSESEEnterNode:
+      sese = (FlatSESEEnterNode) fn;
+
       if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
-        FlatSESEEnterNode sese = (FlatSESEEnterNode) fn;
-        rg.taintInSetVars( sese );                         
+
+        // always remove ALL stall site taints at enter
+        rg.removeAllStallSiteTaints();
+
+        // inject taints for in-set vars
+        rg.taintInSetVars(sese);
+
       }
       break;
 
     case FKind.FlatSESEExitNode:
+      fsexn = (FlatSESEExitNode) fn;
+      sese  = fsexn.getFlatEnter();
+
       if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
-        FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
-        rg.removeInContextTaints( fsexn.getFlatEnter() );
+
+        // @ sese exit make all live variables
+        // inaccessible to later parent statements
+        rg.makeInaccessible(liveness.getLiveInTemps(fmContaining, fn) );
+
+        // always remove ALL stall site taints at exit
+        rg.removeAllStallSiteTaints();
+
+        // remove in-set var taints for the exiting rblock
+        rg.removeInContextTaints(sese);
       }
       break;
 
 
     case FKind.FlatCall: {
       Descriptor mdCaller;
-      if( fmContaining.getMethod() != null ){
+      if( fmContaining.getMethod() != null ) {
         mdCaller = fmContaining.getMethod();
       } else {
         mdCaller = fmContaining.getTask();
-      }      
-      FlatCall         fc       = (FlatCall) fn;
+      }
+      FlatCall fc       = (FlatCall) fn;
       MethodDescriptor mdCallee = fc.getMethod();
-      FlatMethod       fmCallee = state.getMethodFlat( mdCallee );
+      FlatMethod fmCallee = state.getMethodFlat(mdCallee);
+
 
 
-      boolean debugCallSite =
-        mdCaller.getSymbol().equals( state.DISJOINTDEBUGCALLER ) &&
-        mdCallee.getSymbol().equals( state.DISJOINTDEBUGCALLEE );
+      // all this jimma jamma to debug call sites is WELL WORTH the
+      // effort, so so so many bugs or buggy info appears through call
+      // sites
+      boolean debugCallSite = false;
+      if( state.DISJOINTDEBUGCALLEE != null &&
+          state.DISJOINTDEBUGCALLER != null ) {
+
+        boolean debugCalleeMatches = false;
+        boolean debugCallerMatches = false;
+        
+        ClassDescriptor cdCallee = mdCallee.getClassDesc();
+        if( cdCallee != null ) {
+          debugCalleeMatches = 
+            state.DISJOINTDEBUGCALLEE.equals( cdCallee.getSymbol()+
+                                              "."+
+                                              mdCallee.getSymbol()
+                                              );
+        }
+
+
+        if( mdCaller instanceof MethodDescriptor ) {
+          ClassDescriptor cdCaller = ((MethodDescriptor)mdCaller).getClassDesc();
+          if( cdCaller != null ) {
+            debugCallerMatches = 
+              state.DISJOINTDEBUGCALLER.equals( cdCaller.getSymbol()+
+                                                "."+
+                                                mdCaller.getSymbol()
+                                                );
+          }        
+        } else {
+          // for bristlecone style tasks
+          debugCallerMatches =
+            state.DISJOINTDEBUGCALLER.equals( mdCaller.getSymbol() );
+        }
+
+        debugCallSite = debugCalleeMatches && debugCallerMatches;
+      }
+
+      
+
 
       boolean writeDebugDOTs = false;
       boolean stopAfter      = false;
       if( debugCallSite ) {
         ++ReachGraph.debugCallSiteVisitCounter;
-        System.out.println( "    $$$ Debug call site visit "+
-                            ReachGraph.debugCallSiteVisitCounter+
-                            " $$$"
-                            );
-        if( 
-           (ReachGraph.debugCallSiteVisitCounter >= 
-            ReachGraph.debugCallSiteVisitStartCapture)  &&
-           
-           (ReachGraph.debugCallSiteVisitCounter < 
-            ReachGraph.debugCallSiteVisitStartCapture + 
-            ReachGraph.debugCallSiteNumVisitsToCapture)
-            ) {
+        System.out.println("    $$$ Debug call site visit "+
+                           ReachGraph.debugCallSiteVisitCounter+
+                           " $$$"
+                           );
+        if(
+          (ReachGraph.debugCallSiteVisitCounter >=
+           ReachGraph.debugCallSiteVisitStartCapture)  &&
+
+          (ReachGraph.debugCallSiteVisitCounter <
+           ReachGraph.debugCallSiteVisitStartCapture +
+           ReachGraph.debugCallSiteNumVisitsToCapture)
+          ) {
           writeDebugDOTs = true;
-          System.out.println( "      $$$ Capturing this call site visit $$$" );
+          System.out.println("      $$$ Capturing this call site visit $$$");
           if( ReachGraph.debugCallSiteStopAfter &&
-              (ReachGraph.debugCallSiteVisitCounter == 
-               ReachGraph.debugCallSiteVisitStartCapture + 
+              (ReachGraph.debugCallSiteVisitCounter ==
+               ReachGraph.debugCallSiteVisitStartCapture +
                ReachGraph.debugCallSiteNumVisitsToCapture - 1)
               ) {
             stopAfter = true;
@@ -1227,39 +1696,43 @@ public class DisjointAnalysis {
       // not used for the current call site transform, we are
       // grabbing this heap model for future analysis of the callees,
       // so if different results emerge we will return to this site
-      ReachGraph heapForThisCall_old = 
-        getIHMcontribution( mdCallee, fc );
+      ReachGraph heapForThisCall_old =
+        getIHMcontribution(mdCallee, fc);
 
       // the computation of the callee-reachable heap
       // is useful for making the callee starting point
       // and for applying the call site transfer function
-      Set<Integer> callerNodeIDsCopiedToCallee = 
+      Set<Integer> callerNodeIDsCopiedToCallee =
         new HashSet<Integer>();
 
-      ReachGraph heapForThisCall_cur = 
-        rg.makeCalleeView( fc, 
-                           fmCallee,
-                           callerNodeIDsCopiedToCallee,
-                           writeDebugDOTs
-                           );
+      ReachGraph heapForThisCall_cur =
+        rg.makeCalleeView(fc,
+                          fmCallee,
+                          callerNodeIDsCopiedToCallee,
+                          writeDebugDOTs
+                          );
 
-      if( !heapForThisCall_cur.equals( heapForThisCall_old ) ) {        
+      // enforce that a call site contribution can only
+      // monotonically increase
+      heapForThisCall_cur.merge(heapForThisCall_old);
+
+      if( !heapForThisCall_cur.equals(heapForThisCall_old) ) {
         // if heap at call site changed, update the contribution,
         // and reschedule the callee for analysis
-        addIHMcontribution( mdCallee, fc, heapForThisCall_cur );        
+        addIHMcontribution(mdCallee, fc, heapForThisCall_cur);
 
-        // map a FlatCall to its enclosing method/task descriptor 
+        // map a FlatCall to its enclosing method/task descriptor
         // so we can write that info out later
-        fc2enclosing.put( fc, mdCaller );
+        fc2enclosing.put(fc, mdCaller);
 
         if( state.DISJOINTDEBUGSCHEDULING ) {
-          System.out.println( "  context changed, scheduling callee: "+mdCallee );
+          System.out.println("  context changed, scheduling callee: "+mdCallee);
         }
 
         if( state.DISJOINTDVISITSTACKEESONTOP ) {
-          calleesToEnqueue.add( mdCallee );
+          calleesToEnqueue.add(mdCallee);
         } else {
-          enqueue( mdCallee );
+          enqueue(mdCallee);
         }
 
       }
@@ -1271,91 +1744,126 @@ public class DisjointAnalysis {
       Set<MethodDescriptor> setPossibleCallees;
       if( determinismDesired ) {
         // use an ordered set
-        setPossibleCallees = new TreeSet<MethodDescriptor>( dComp );        
+        setPossibleCallees = new TreeSet<MethodDescriptor>(dComp);
       } else {
         // otherwise use a speedy hashset
         setPossibleCallees = new HashSet<MethodDescriptor>();
       }
 
-      if( mdCallee.isStatic() ) {        
-        setPossibleCallees.add( mdCallee );
+      if( mdCallee.isStatic() ) {
+        setPossibleCallees.add(mdCallee);
       } else {
-       TypeDescriptor typeDesc = fc.getThis().getType();
-       setPossibleCallees.addAll( callGraph.getMethods( mdCallee, 
-                                                         typeDesc )
-                                   );
+        TypeDescriptor typeDesc = fc.getThis().getType();
+        setPossibleCallees.addAll(callGraph.getMethods(mdCallee,
+                                                       typeDesc)
+                                  );
       }
 
-      ReachGraph rgMergeOfEffects = new ReachGraph();
+
+
+      ReachGraph rgMergeOfPossibleCallers = new ReachGraph();
 
       Iterator<MethodDescriptor> mdItr = setPossibleCallees.iterator();
       while( mdItr.hasNext() ) {
         MethodDescriptor mdPossible = mdItr.next();
-        FlatMethod       fmPossible = state.getMethodFlat( mdPossible );
+        FlatMethod fmPossible = state.getMethodFlat(mdPossible);
 
-        addDependent( mdPossible, // callee
-                      d );        // caller
+        addDependent(mdPossible,  // callee
+                     d);          // caller
 
-        // don't alter the working graph (rg) until we compute a 
+        // don't alter the working graph (rg) until we compute a
         // result for every possible callee, merge them all together,
         // then set rg to that
-        ReachGraph rgCopy = new ReachGraph();
-        rgCopy.merge( rg );            
-                
-        ReachGraph rgEffect = getPartial( mdPossible );
+        ReachGraph rgPossibleCaller = new ReachGraph();
+        rgPossibleCaller.merge(rg);
 
-        if( rgEffect == null ) {
-          // if this method has never been analyzed just schedule it 
+        ReachGraph rgPossibleCallee = getPartial(mdPossible);
+
+        if( rgPossibleCallee == null ) {
+          // if this method has never been analyzed just schedule it
           // for analysis and skip over this call site for now
           if( state.DISJOINTDVISITSTACKEESONTOP ) {
-            calleesToEnqueue.add( mdPossible );
+            calleesToEnqueue.add(mdPossible);
           } else {
-            enqueue( mdPossible );
+            enqueue(mdPossible);
           }
-          
+
           if( state.DISJOINTDEBUGSCHEDULING ) {
-            System.out.println( "  callee hasn't been analyzed, scheduling: "+mdPossible );
+            System.out.println("  callee hasn't been analyzed, scheduling: "+mdPossible);
           }
 
-
         } else {
-          // calculate the method call transform         
-          rgCopy.resolveMethodCall( fc, 
-                                    fmPossible, 
-                                    rgEffect,
-                                    callerNodeIDsCopiedToCallee,
-                                    writeDebugDOTs
-                                    );
+          // calculate the method call transform
+          rgPossibleCaller.resolveMethodCall(fc,
+                                             fmPossible,
+                                             rgPossibleCallee,
+                                             callerNodeIDsCopiedToCallee,
+                                             writeDebugDOTs
+                                             );
+
+          if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+//            if( !rgPossibleCallee.isAccessible( ReachGraph.tdReturn ) ) {
+            if( !accessible.isAccessible(fn, ReachGraph.tdReturn) ) {
+              rgPossibleCaller.makeInaccessible(fc.getReturnTemp() );
+            }
+          }
+
         }
-        
-        rgMergeOfEffects.merge( rgCopy );        
+
+        rgMergeOfPossibleCallers.merge(rgPossibleCaller);
       }
 
 
       if( stopAfter ) {
-        System.out.println( "$$$ Exiting after requested captures of call site. $$$" );
-        System.exit( 0 );
+        System.out.println("$$$ Exiting after requested captures of call site. $$$");
+        System.exit(0);
       }
 
 
       // now that we've taken care of building heap models for
       // callee analysis, finish this transformation
-      rg = rgMergeOfEffects;
+      rg = rgMergeOfPossibleCallers;
+
+
+      // jjenista: what is this?  It breaks compilation
+      // of programs with no tasks/SESEs/rblocks...
+      //XXXXXXXXXXXXXXXXXXXXXXXXX
+      //need to consider more
+      if( state.OOOJAVA ) {
+        FlatNode nextFN=fmCallee.getNext(0);
+        if( nextFN instanceof FlatSESEEnterNode ) {
+          FlatSESEEnterNode calleeSESE=(FlatSESEEnterNode)nextFN;
+          if(!calleeSESE.getIsLeafSESE()) {
+            rg.makeInaccessible(liveness.getLiveInTemps(fmContaining, fn) );
+          }
+        }
+      }
+
     } break;
-      
+
 
     case FKind.FlatReturnNode:
       FlatReturnNode frn = (FlatReturnNode) fn;
       rhs = frn.getReturnTemp();
-      if( rhs != null && shouldAnalysisTrack( rhs.getType() ) ) {
-       rg.assignReturnEqualToTemp( rhs );
+
+      // before transfer, do effects analysis support
+      if( doEffectsAnalysis && fmContaining != fmAnalysisEntry ) {
+//        if(!rg.isAccessible(rhs)){
+        if(!accessible.isAccessible(fn,rhs)) {
+          rg.makeInaccessible(ReachGraph.tdReturn);
+        }
       }
-      setRetNodes.add( frn );
+
+      if( rhs != null && shouldAnalysisTrack(rhs.getType() ) ) {
+        rg.assignReturnEqualToTemp(rhs);
+      }
+
+      setRetNodes.add(frn);
       break;
 
     } // end switch
 
-    
+
     // dead variables were removed before the above transfer function
     // was applied, so eliminate heap regions and edges that are no
     // longer part of the abstractly-live heap graph, and sweep up
@@ -1365,12 +1873,18 @@ public class DisjointAnalysis {
 
 
     // back edges are strictly monotonic
-    if( pm.isBackEdge( fn ) ) {
-      ReachGraph rgPrevResult = mapBackEdgeToMonotone.get( fn );
-      rg.merge( rgPrevResult );
-      mapBackEdgeToMonotone.put( fn, rg );
+    if( pm.isBackEdge(fn) ) {
+      ReachGraph rgPrevResult = mapBackEdgeToMonotone.get(fn);
+      rg.merge(rgPrevResult);
+      mapBackEdgeToMonotone.put(fn, rg);
     }
-    
+
+
+    ReachGraph rgOnExit = new ReachGraph();
+    rgOnExit.merge(rg);
+    fn2rgAtExit.put(fn, rgOnExit);
+
+
     // at this point rg should be the correct update
     // by an above transfer function, or untouched if
     // the flat node type doesn't affect the heap
@@ -1378,72 +1892,79 @@ public class DisjointAnalysis {
   }
 
 
-  
+
   // this method should generate integers strictly greater than zero!
   // special "shadow" regions are made from a heap region by negating
   // the ID
   static public Integer generateUniqueHeapRegionNodeID() {
     ++uniqueIDcount;
-    return new Integer( uniqueIDcount );
+    return new Integer(uniqueIDcount);
   }
 
 
-  
-  static public FieldDescriptor getArrayField( TypeDescriptor tdElement ) {
-    FieldDescriptor fdElement = mapTypeToArrayField.get( tdElement );
+
+  static public FieldDescriptor getArrayField(TypeDescriptor tdElement) {
+    FieldDescriptor fdElement = mapTypeToArrayField.get(tdElement);
     if( fdElement == null ) {
-      fdElement = new FieldDescriptor( new Modifiers( Modifiers.PUBLIC ),
-                                       tdElement,
-                                       arrayElementFieldName,
-                                       null,
-                                       false );
-      mapTypeToArrayField.put( tdElement, fdElement );
+      fdElement = new FieldDescriptor(new Modifiers(Modifiers.PUBLIC),
+                                      tdElement,
+                                      arrayElementFieldName,
+                                      null,
+                                      false);
+      mapTypeToArrayField.put(tdElement, fdElement);
     }
     return fdElement;
   }
 
-  
-  
+
+
   private void writeFinalGraphs() {
     Set entrySet = mapDescriptorToCompleteReachGraph.entrySet();
     Iterator itr = entrySet.iterator();
     while( itr.hasNext() ) {
-      Map.Entry  me = (Map.Entry)  itr.next();
-      Descriptor  d = (Descriptor) me.getKey();
+      Map.Entry me = (Map.Entry)itr.next();
+      Descriptor d = (Descriptor) me.getKey();
       ReachGraph rg = (ReachGraph) me.getValue();
 
-      rg.writeGraph( "COMPLETE"+d,
-                     true,    // write labels (variables)                
-                     true,    // selectively hide intermediate temp vars 
-                     true,    // prune unreachable heap regions          
-                     false,   // hide reachability altogether
-                     true,    // hide subset reachability states         
-                     true,    // hide predicates
-                     false ); // hide edge taints                        
+      String graphName;
+      if( d instanceof TaskDescriptor ) {
+        graphName = "COMPLETEtask"+d;
+      } else {
+        graphName = "COMPLETE"+d;
+      }
+
+      rg.writeGraph(graphName,
+                    true,     // write labels (variables)
+                    true,     // selectively hide intermediate temp vars
+                    true,     // prune unreachable heap regions
+                    true,     // hide reachability altogether
+                    true,     // hide subset reachability states
+                    true,     // hide predicates
+                    false);   // hide edge taints
     }
   }
 
   private void writeFinalIHMs() {
     Iterator d2IHMsItr = mapDescriptorToIHMcontributions.entrySet().iterator();
     while( d2IHMsItr.hasNext() ) {
-      Map.Entry                        me1 = (Map.Entry)                       d2IHMsItr.next();
-      Descriptor                         d = (Descriptor)                      me1.getKey();
-      Hashtable<FlatCall, ReachGraph> IHMs = (Hashtable<FlatCall, ReachGraph>) me1.getValue();
+      Map.Entry me1 = (Map.Entry)d2IHMsItr.next();
+      Descriptor d = (Descriptor)                      me1.getKey();
+      Hashtable<FlatCall, ReachGraph> IHMs = (Hashtable<FlatCall, ReachGraph>)me1.getValue();
 
       Iterator fc2rgItr = IHMs.entrySet().iterator();
       while( fc2rgItr.hasNext() ) {
-        Map.Entry  me2 = (Map.Entry)  fc2rgItr.next();
-        FlatCall   fc  = (FlatCall)   me2.getKey();
+        Map.Entry me2 = (Map.Entry)fc2rgItr.next();
+        FlatCall fc  = (FlatCall)   me2.getKey();
         ReachGraph rg  = (ReachGraph) me2.getValue();
-                
-        rg.writeGraph( "IHMPARTFOR"+d+"FROM"+fc2enclosing.get( fc )+fc,
-                       true,   // write labels (variables)
-                       true,   // selectively hide intermediate temp vars
-                       true,   // hide reachability altogether
-                       true,   // prune unreachable heap regions
-                       true,   // hide subset reachability states
-                       false,  // hide predicates
-                       true ); // hide edge taints
+
+        rg.writeGraph("IHMPARTFOR"+d+"FROM"+fc2enclosing.get(fc)+fc,
+                      true,    // write labels (variables)
+                      true,    // selectively hide intermediate temp vars
+                      true,    // hide reachability altogether
+                      true,    // prune unreachable heap regions
+                      true,    // hide subset reachability states
+                      false,   // hide predicates
+                      true);   // hide edge taints
       }
     }
   }
@@ -1452,28 +1973,28 @@ public class DisjointAnalysis {
     Set entrySet = mapDescriptorToInitialContext.entrySet();
     Iterator itr = entrySet.iterator();
     while( itr.hasNext() ) {
-      Map.Entry  me = (Map.Entry)  itr.next();
-      Descriptor  d = (Descriptor) me.getKey();
+      Map.Entry me = (Map.Entry)itr.next();
+      Descriptor d = (Descriptor) me.getKey();
       ReachGraph rg = (ReachGraph) me.getValue();
 
-      rg.writeGraph( "INITIAL"+d,
-                     true,   // write labels (variables)                
-                     true,   // selectively hide intermediate temp vars 
-                     true,   // prune unreachable heap regions          
-                     false,  // hide all reachability
-                     true,   // hide subset reachability states         
-                     true,   // hide predicates
-                     false );// hide edge taints                        
+      rg.writeGraph("INITIAL"+d,
+                    true,    // write labels (variables)
+                    true,    // selectively hide intermediate temp vars
+                    true,    // prune unreachable heap regions
+                    false,   // hide all reachability
+                    true,    // hide subset reachability states
+                    true,    // hide predicates
+                    false);  // hide edge taints
     }
   }
-   
 
-  protected ReachGraph getPartial( Descriptor d ) {
-    return mapDescriptorToCompleteReachGraph.get( d );
+
+  protected ReachGraph getPartial(Descriptor d) {
+    return mapDescriptorToCompleteReachGraph.get(d);
   }
 
-  protected void setPartial( Descriptor d, ReachGraph rg ) {
-    mapDescriptorToCompleteReachGraph.put( d, rg );
+  protected void setPartial(Descriptor d, ReachGraph rg) {
+    mapDescriptorToCompleteReachGraph.put(d, rg);
 
     // when the flag for writing out every partial
     // result is set, we should spit out the graph,
@@ -1481,54 +2002,66 @@ public class DisjointAnalysis {
     // to track how many partial results for this
     // descriptor we've already written out
     if( writeAllIncrementalDOTs ) {
-      if( !mapDescriptorToNumUpdates.containsKey( d ) ) {
-       mapDescriptorToNumUpdates.put( d, new Integer( 0 ) );
+      if( !mapDescriptorToNumUpdates.containsKey(d) ) {
+        mapDescriptorToNumUpdates.put(d, new Integer(0) );
       }
-      Integer n = mapDescriptorToNumUpdates.get( d );
-      
-      rg.writeGraph( d+"COMPLETE"+String.format( "%05d", n ),
-                     true,   // write labels (variables)
-                     true,   // selectively hide intermediate temp vars
-                     true,   // prune unreachable heap regions
-                     false,  // hide all reachability
-                     true,   // hide subset reachability states
-                     false,  // hide predicates
-                     false); // hide edge taints
-      
-      mapDescriptorToNumUpdates.put( d, n + 1 );
+      Integer n = mapDescriptorToNumUpdates.get(d);
+
+      String graphName;
+      if( d instanceof TaskDescriptor ) {
+        graphName = d+"COMPLETEtask"+String.format("%05d", n);
+      } else {
+        graphName = d+"COMPLETE"+String.format("%05d", n);
+      }
+
+      rg.writeGraph(graphName,
+                    true,    // write labels (variables)
+                    true,    // selectively hide intermediate temp vars
+                    true,    // prune unreachable heap regions
+                    false,   // hide all reachability
+                    true,    // hide subset reachability states
+                    false,   // hide predicates
+                    false);  // hide edge taints
+
+      mapDescriptorToNumUpdates.put(d, n + 1);
     }
   }
 
 
 
   // return just the allocation site associated with one FlatNew node
-  protected AllocSite getAllocSiteFromFlatNewPRIVATE( FlatNew fnew ) {
+  protected AllocSite getAllocSiteFromFlatNewPRIVATE(FlatNew fnew) {
+
+    boolean flagProgrammatically = false;
+    if( sitesToFlag != null && sitesToFlag.contains(fnew) ) {
+      flagProgrammatically = true;
+    }
 
-    if( !mapFlatNewToAllocSite.containsKey( fnew ) ) {
-      AllocSite as = AllocSite.factory( allocationDepth, 
-                                        fnew, 
-                                        fnew.getDisjointId(),
-                                        false
-                                        );
+    if( !mapFlatNewToAllocSite.containsKey(fnew) ) {
+      AllocSite as = AllocSite.factory(allocationDepth,
+                                       fnew,
+                                       fnew.getDisjointId(),
+                                       flagProgrammatically
+                                       );
 
       // the newest nodes are single objects
       for( int i = 0; i < allocationDepth; ++i ) {
-       Integer id = generateUniqueHeapRegionNodeID();
-       as.setIthOldest( i, id );
-       mapHrnIdToAllocSite.put( id, as );
+        Integer id = generateUniqueHeapRegionNodeID();
+        as.setIthOldest(i, id);
+        mapHrnIdToAllocSite.put(id, as);
       }
 
       // the oldest node is a summary node
-      as.setSummary( generateUniqueHeapRegionNodeID() );
+      as.setSummary(generateUniqueHeapRegionNodeID() );
 
-      mapFlatNewToAllocSite.put( fnew, as );
+      mapFlatNewToAllocSite.put(fnew, as);
     }
 
-    return mapFlatNewToAllocSite.get( fnew );
+    return mapFlatNewToAllocSite.get(fnew);
   }
 
 
-  public static boolean shouldAnalysisTrack( TypeDescriptor type ) {
+  public static boolean shouldAnalysisTrack(TypeDescriptor type) {
     // don't track primitive types, but an array
     // of primitives is heap memory
     if( type.isImmutable() ) {
@@ -1539,97 +2072,182 @@ public class DisjointAnalysis {
     return true;
   }
 
-  protected int numMethodsAnalyzed() {    
+  protected int numMethodsAnalyzed() {
     return descriptorsToAnalyze.size();
   }
-  
 
-  
-  
-  
+
+
+
   // Take in source entry which is the program's compiled entry and
   // create a new analysis entry, a method that takes no parameters
   // and appears to allocate the command line arguments and call the
   // source entry with them.  The purpose of this analysis entry is
   // to provide a top-level method context with no parameters left.
-  protected void makeAnalysisEntryMethod( MethodDescriptor mdSourceEntry ) {
+  protected void makeAnalysisEntryMethod(MethodDescriptor mdSourceEntry) {
 
     Modifiers mods = new Modifiers();
-    mods.addModifier( Modifiers.PUBLIC );
-    mods.addModifier( Modifiers.STATIC );
+    mods.addModifier(Modifiers.PUBLIC);
+    mods.addModifier(Modifiers.STATIC);
 
-    TypeDescriptor returnType = 
-      new TypeDescriptor( TypeDescriptor.VOID );
+    TypeDescriptor returnType = new TypeDescriptor(TypeDescriptor.VOID);
+    
+    this.mdAnalysisEntry =
+      new MethodDescriptor(mods,
+                           returnType,
+                           "analysisEntryMethod"
+                           );
 
-    this.mdAnalysisEntry = 
-      new MethodDescriptor( mods,
-                            returnType,
-                            "analysisEntryMethod"
-                            );
+    TypeDescriptor argsType = mdSourceEntry.getParamType(0);
+    TempDescriptor cmdLineArgs =
+      new TempDescriptor("analysisEntryTemp_args",
+                         argsType
+                         );
+    FlatNew fnArgs =
+      new FlatNew(argsType,
+                  cmdLineArgs,
+                  false  // is global
+                  );
+    this.constructedCmdLineArgsNew = fnArgs;
+
+    TypeDescriptor argType = argsType.dereference();
+    TempDescriptor anArg =
+      new TempDescriptor("analysisEntryTemp_arg",
+                         argType
+                         );
+    FlatNew fnArg =
+      new FlatNew(argType,
+                  anArg,
+                  false  // is global
+                  );
+    this.constructedCmdLineArgNew = fnArg;
+
+    TypeDescriptor typeIndex = new TypeDescriptor(TypeDescriptor.INT);
+    TempDescriptor index =
+      new TempDescriptor("analysisEntryTemp_index",
+                         typeIndex
+                         );
+    FlatLiteralNode fli =
+      new FlatLiteralNode(typeIndex,
+                          new Integer( 0 ),
+                          index
+                          );
+    
+    FlatSetElementNode fse =
+      new FlatSetElementNode(cmdLineArgs,
+                             index,
+                             anArg
+                             );
 
-    TempDescriptor cmdLineArgs = 
-      new TempDescriptor( "args",
-                          mdSourceEntry.getParamType( 0 )
+    TypeDescriptor typeSize = new TypeDescriptor(TypeDescriptor.INT);
+    TempDescriptor sizeBytes =
+      new TempDescriptor("analysisEntryTemp_size",
+                         typeSize
+                         );
+    FlatLiteralNode fls =
+      new FlatLiteralNode(typeSize,
+                          new Integer( 1 ),
+                          sizeBytes
                           );
 
-    FlatNew fn = 
-      new FlatNew( mdSourceEntry.getParamType( 0 ),
-                   cmdLineArgs,
-                   false // is global 
-                   );
-    
+    TempDescriptor strBytes =
+      new TempDescriptor("analysisEntryTemp_strBytes",
+                         stringBytesType
+                         );
+    FlatNew fnBytes =
+      new FlatNew(stringBytesType,
+                  strBytes,
+                  //sizeBytes,
+                  false  // is global
+                  );
+    this.constructedCmdLineArgBytesNew = fnBytes;
+
+    FlatSetFieldNode fsf =
+      new FlatSetFieldNode(anArg,
+                           stringBytesField,
+                           strBytes
+                           );
+
+    // throw this in so you can always see what the initial heap context
+    // looks like if you want to, its cheap
+    FlatGenReachNode fgen = new FlatGenReachNode( "argContext" );
+
     TempDescriptor[] sourceEntryArgs = new TempDescriptor[1];
     sourceEntryArgs[0] = cmdLineArgs;
-    
-    FlatCall fc = 
-      new FlatCall( mdSourceEntry,
-                    null, // dst temp
-                    null, // this temp
-                    sourceEntryArgs
-                    );
+    FlatCall fc =
+      new FlatCall(mdSourceEntry,
+                   null,  // dst temp
+                   null,  // this temp
+                   sourceEntryArgs
+                   );
 
-    FlatReturnNode frn = new FlatReturnNode( null );
+    FlatReturnNode frn = new FlatReturnNode(null);
 
     FlatExit fe = new FlatExit();
 
-    this.fmAnalysisEntry = 
-      new FlatMethod( mdAnalysisEntry, 
-                      fe
-                      );
+    this.fmAnalysisEntry =
+      new FlatMethod(mdAnalysisEntry,
+                     fe
+                     );
+
+    List<FlatNode> nodes = new LinkedList<FlatNode>();
+    nodes.add( fnArgs );
+    nodes.add( fnArg );
+    nodes.add( fli );
+    nodes.add( fse );
+    nodes.add( fls );
+    nodes.add( fnBytes );
+    nodes.add( fsf );
+    nodes.add( fgen );
+    nodes.add( fc );
+    nodes.add( frn );
+    nodes.add( fe );
+
+    FlatNode current = this.fmAnalysisEntry;
+    for( FlatNode next: nodes ) {
+      current.addNext( next );
+      current = next;
+    }
 
-    this.fmAnalysisEntry.addNext( fn );
-    fn.addNext( fc );
-    fc.addNext( frn );
-    frn.addNext( fe );
+    
+    // jjenista - this is useful for looking at the FlatIRGraph of the
+    // analysis entry method constructed above if you have to modify it.
+    // The usual method of writing FlatIRGraphs out doesn't work because
+    // this flat method is private to the model of this analysis only.
+    //try {
+    //  FlatIRGraph flatMethodWriter = 
+    //    new FlatIRGraph( state, false, false, false );
+    //  flatMethodWriter.writeFlatIRGraph( fmAnalysisEntry, "analysisEntry" );
+    //} catch( IOException e ) {}
   }
 
 
-  protected LinkedList<Descriptor> topologicalSort( Set<Descriptor> toSort ) {
+  protected LinkedList<Descriptor> topologicalSort(Set<Descriptor> toSort) {
 
     Set<Descriptor> discovered;
 
     if( determinismDesired ) {
       // use an ordered set
-      discovered = new TreeSet<Descriptor>( dComp );      
+      discovered = new TreeSet<Descriptor>(dComp);
     } else {
       // otherwise use a speedy hashset
       discovered = new HashSet<Descriptor>();
     }
 
     LinkedList<Descriptor> sorted = new LinkedList<Descriptor>();
-  
+
     Iterator<Descriptor> itr = toSort.iterator();
     while( itr.hasNext() ) {
       Descriptor d = itr.next();
-          
-      if( !discovered.contains( d ) ) {
-       dfsVisit( d, toSort, sorted, discovered );
+
+      if( !discovered.contains(d) ) {
+        dfsVisit(d, toSort, sorted, discovered);
       }
     }
-    
+
     return sorted;
   }
-  
+
   // While we're doing DFS on call graph, remember
   // dependencies for efficient queuing of methods
   // during interprocedural analysis:
@@ -1637,12 +2255,12 @@ public class DisjointAnalysis {
   // a dependent of a method decriptor d for this analysis is:
   //  1) a method or task that invokes d
   //  2) in the descriptorsToAnalyze set
-  protected void dfsVisit( Descriptor             d,
-                           Set       <Descriptor> toSort,                       
-                           LinkedList<Descriptor> sorted,
-                           Set       <Descriptor> discovered ) {
-    discovered.add( d );
-    
+  protected void dfsVisit(Descriptor d,
+                          Set       <Descriptor> toSort,
+                          LinkedList<Descriptor> sorted,
+                          Set       <Descriptor> discovered) {
+    discovered.add(d);
+
     // only methods have callers, tasks never do
     if( d instanceof MethodDescriptor ) {
 
@@ -1651,56 +2269,56 @@ public class DisjointAnalysis {
       // the call graph is not aware that we have a fabricated
       // analysis entry that calls the program source's entry
       if( md == mdSourceEntry ) {
-        if( !discovered.contains( mdAnalysisEntry ) ) {
-          addDependent( mdSourceEntry,  // callee
-                        mdAnalysisEntry // caller
-                        );
-          dfsVisit( mdAnalysisEntry, toSort, sorted, discovered );
+        if( !discovered.contains(mdAnalysisEntry) ) {
+          addDependent(mdSourceEntry,   // callee
+                       mdAnalysisEntry  // caller
+                       );
+          dfsVisit(mdAnalysisEntry, toSort, sorted, discovered);
         }
       }
 
       // otherwise call graph guides DFS
-      Iterator itr = callGraph.getCallerSet( md ).iterator();
+      Iterator itr = callGraph.getCallerSet(md).iterator();
       while( itr.hasNext() ) {
-       Descriptor dCaller = (Descriptor) itr.next();
-       
-       // only consider callers in the original set to analyze
-        if( !toSort.contains( dCaller ) ) {
-         continue;
+        Descriptor dCaller = (Descriptor) itr.next();
+
+        // only consider callers in the original set to analyze
+        if( !toSort.contains(dCaller) ) {
+          continue;
         }
-          
-       if( !discovered.contains( dCaller ) ) {
-          addDependent( md,     // callee
-                        dCaller // caller
-                        );
 
-         dfsVisit( dCaller, toSort, sorted, discovered );
-       }
+        if( !discovered.contains(dCaller) ) {
+          addDependent(md,      // callee
+                       dCaller  // caller
+                       );
+
+          dfsVisit(dCaller, toSort, sorted, discovered);
+        }
       }
     }
-    
+
     // for leaf-nodes last now!
-    sorted.addLast( d );
+    sorted.addLast(d);
   }
 
 
-  protected void enqueue( Descriptor d ) {
+  protected void enqueue(Descriptor d) {
 
-    if( !descriptorsToVisitSet.contains( d ) ) {
+    if( !descriptorsToVisitSet.contains(d) ) {
 
       if( state.DISJOINTDVISITSTACK ||
           state.DISJOINTDVISITSTACKEESONTOP
           ) {
-        descriptorsToVisitStack.add( d );
+        descriptorsToVisitStack.add(d);
 
       } else if( state.DISJOINTDVISITPQUE ) {
-        Integer priority = mapDescriptorToPriority.get( d );
-        descriptorsToVisitQ.add( new DescriptorQWrapper( priority, 
-                                                         d ) 
-                                 );
+        Integer priority = mapDescriptorToPriority.get(d);
+        descriptorsToVisitQ.add(new DescriptorQWrapper(priority,
+                                                       d)
+                                );
       }
 
-      descriptorsToVisitSet.add( d );
+      descriptorsToVisitSet.add(d);
     }
   }
 
@@ -1708,410 +2326,410 @@ public class DisjointAnalysis {
   // a dependent of a method decriptor d for this analysis is:
   //  1) a method or task that invokes d
   //  2) in the descriptorsToAnalyze set
-  protected void addDependent( Descriptor callee, Descriptor caller ) {
-    Set<Descriptor> deps = mapDescriptorToSetDependents.get( callee );
+  protected void addDependent(Descriptor callee, Descriptor caller) {
+    Set<Descriptor> deps = mapDescriptorToSetDependents.get(callee);
     if( deps == null ) {
       deps = new HashSet<Descriptor>();
     }
-    deps.add( caller );
-    mapDescriptorToSetDependents.put( callee, deps );
+    deps.add(caller);
+    mapDescriptorToSetDependents.put(callee, deps);
   }
-  
-  protected Set<Descriptor> getDependents( Descriptor callee ) {
-    Set<Descriptor> deps = mapDescriptorToSetDependents.get( callee );
+
+  protected Set<Descriptor> getDependents(Descriptor callee) {
+    Set<Descriptor> deps = mapDescriptorToSetDependents.get(callee);
     if( deps == null ) {
       deps = new HashSet<Descriptor>();
-      mapDescriptorToSetDependents.put( callee, deps );
+      mapDescriptorToSetDependents.put(callee, deps);
     }
     return deps;
   }
 
-  
-  public Hashtable<FlatCall, ReachGraph> getIHMcontributions( Descriptor d ) {
 
-    Hashtable<FlatCall, ReachGraph> heapsFromCallers = 
-      mapDescriptorToIHMcontributions.get( d );
-    
+  public Hashtable<FlatCall, ReachGraph> getIHMcontributions(Descriptor d) {
+
+    Hashtable<FlatCall, ReachGraph> heapsFromCallers =
+      mapDescriptorToIHMcontributions.get(d);
+
     if( heapsFromCallers == null ) {
       heapsFromCallers = new Hashtable<FlatCall, ReachGraph>();
-      mapDescriptorToIHMcontributions.put( d, heapsFromCallers );
+      mapDescriptorToIHMcontributions.put(d, heapsFromCallers);
     }
-    
+
     return heapsFromCallers;
   }
 
-  public ReachGraph getIHMcontribution( Descriptor d, 
-                                        FlatCall   fc
-                                        ) {
-    Hashtable<FlatCall, ReachGraph> heapsFromCallers = 
-      getIHMcontributions( d );
+  public ReachGraph getIHMcontribution(Descriptor d,
+                                       FlatCall fc
+                                       ) {
+    Hashtable<FlatCall, ReachGraph> heapsFromCallers =
+      getIHMcontributions(d);
 
-    if( !heapsFromCallers.containsKey( fc ) ) {
+    if( !heapsFromCallers.containsKey(fc) ) {
       return null;
     }
 
-    return heapsFromCallers.get( fc );
+    return heapsFromCallers.get(fc);
   }
 
 
-  public void addIHMcontribution( Descriptor d,
-                                  FlatCall   fc,
-                                  ReachGraph rg
-                                  ) {
-    Hashtable<FlatCall, ReachGraph> heapsFromCallers = 
-      getIHMcontributions( d );
+  public void addIHMcontribution(Descriptor d,
+                                 FlatCall fc,
+                                 ReachGraph rg
+                                 ) {
+    Hashtable<FlatCall, ReachGraph> heapsFromCallers =
+      getIHMcontributions(d);
 
-    heapsFromCallers.put( fc, rg );
+    heapsFromCallers.put(fc, rg);
   }
 
 
-  private AllocSite createParameterAllocSite( ReachGraph     rg, 
-                                              TempDescriptor tempDesc,
-                                              boolean        flagRegions
-                                              ) {
-    
+  private AllocSite createParameterAllocSite(ReachGraph rg,
+                                             TempDescriptor tempDesc,
+                                             boolean flagRegions
+                                             ) {
+
     FlatNew flatNew;
     if( flagRegions ) {
-      flatNew = new FlatNew( tempDesc.getType(), // type
-                             tempDesc,           // param temp
-                             false,              // global alloc?
-                             "param"+tempDesc    // disjoint site ID string
-                             );
+      flatNew = new FlatNew(tempDesc.getType(),  // type
+                            tempDesc,            // param temp
+                            false,               // global alloc?
+                            "param"+tempDesc     // disjoint site ID string
+                            );
     } else {
-      flatNew = new FlatNew( tempDesc.getType(), // type
-                             tempDesc,           // param temp
-                             false,              // global alloc?
-                             null                // disjoint site ID string
-                             );
+      flatNew = new FlatNew(tempDesc.getType(),  // type
+                            tempDesc,            // param temp
+                            false,               // global alloc?
+                            null                 // disjoint site ID string
+                            );
     }
 
     // create allocation site
-    AllocSite as = AllocSite.factory( allocationDepth, 
-                                      flatNew, 
-                                      flatNew.getDisjointId(),
-                                      false
-                                      );
+    AllocSite as = AllocSite.factory(allocationDepth,
+                                     flatNew,
+                                     flatNew.getDisjointId(),
+                                     false
+                                     );
     for (int i = 0; i < allocationDepth; ++i) {
-       Integer id = generateUniqueHeapRegionNodeID();
-       as.setIthOldest(i, id);
-       mapHrnIdToAllocSite.put(id, as);
+      Integer id = generateUniqueHeapRegionNodeID();
+      as.setIthOldest(i, id);
+      mapHrnIdToAllocSite.put(id, as);
     }
     // the oldest node is a summary node
-    as.setSummary( generateUniqueHeapRegionNodeID() );
-    
+    as.setSummary(generateUniqueHeapRegionNodeID() );
+
     rg.age(as);
-    
+
     return as;
-    
+
   }
 
-private Set<FieldDescriptor> getFieldSetTobeAnalyzed(TypeDescriptor typeDesc){
-       
-       Set<FieldDescriptor> fieldSet=new HashSet<FieldDescriptor>();
-    if(!typeDesc.isImmutable()){
-           ClassDescriptor classDesc = typeDesc.getClassDesc();                    
-           for (Iterator it = classDesc.getFields(); it.hasNext();) {
-                   FieldDescriptor field = (FieldDescriptor) it.next();
-                   TypeDescriptor fieldType = field.getType();
-                   if (shouldAnalysisTrack( fieldType )) {
-                       fieldSet.add(field);                    
-                   }
-           }
+  private Set<FieldDescriptor> getFieldSetTobeAnalyzed(TypeDescriptor typeDesc) {
+
+    Set<FieldDescriptor> fieldSet=new HashSet<FieldDescriptor>();
+    if(!typeDesc.isImmutable()) {
+      ClassDescriptor classDesc = typeDesc.getClassDesc();
+      for (Iterator it = classDesc.getFields(); it.hasNext(); ) {
+        FieldDescriptor field = (FieldDescriptor) it.next();
+        TypeDescriptor fieldType = field.getType();
+        if (shouldAnalysisTrack(fieldType)) {
+          fieldSet.add(field);
+        }
+      }
     }
     return fieldSet;
-       
-}
 
-  private HeapRegionNode createMultiDeimensionalArrayHRN(ReachGraph rg, AllocSite alloc, HeapRegionNode srcHRN, FieldDescriptor fd, Hashtable<HeapRegionNode, HeapRegionNode> map, Hashtable<TypeDescriptor, HeapRegionNode> mapToExistingNode, ReachSet alpha ){
-
-       int dimCount=fd.getType().getArrayCount();
-       HeapRegionNode prevNode=null;
-       HeapRegionNode arrayEntryNode=null;
-       for(int i=dimCount;i>0;i--){
-               TypeDescriptor typeDesc=fd.getType().dereference();//hack to get instance of type desc
-               typeDesc.setArrayCount(i);
-               TempDescriptor tempDesc=new TempDescriptor(typeDesc.getSymbol(),typeDesc);
-               HeapRegionNode hrnSummary ;
-               if(!mapToExistingNode.containsKey(typeDesc)){
-                       AllocSite as;
-                       if(i==dimCount){
-                               as = alloc;
-                       }else{
-                          as = createParameterAllocSite(rg, tempDesc, false);
-                       }
-                       // make a new reference to allocated node
-                   hrnSummary = 
-                               rg.createNewHeapRegionNode(as.getSummary(), // id or null to generate a new one
-                                                          false, // single object?
-                                                          true, // summary?
-                                                          false, // out-of-context?
-                                                          as.getType(), // type
-                                                          as, // allocation site
-                                                          alpha, // inherent reach
-                                                          alpha, // current reach
-                                                          ExistPredSet.factory(rg.predTrue), // predicates
-                                                          tempDesc.toString() // description
-                                                          );
-                   rg.id2hrn.put(as.getSummary(),hrnSummary);
-                   
-                   mapToExistingNode.put(typeDesc, hrnSummary);
-               }else{
-                       hrnSummary=mapToExistingNode.get(typeDesc);
-               }
-           
-           if(prevNode==null){
-                   // make a new reference between new summary node and source
-              RefEdge edgeToSummary = new RefEdge(srcHRN, // source
-                                                       hrnSummary, // dest
-                                                       typeDesc, // type
-                                                       fd.getSymbol(), // field name
-                                                       alpha, // beta
-                                                  ExistPredSet.factory(rg.predTrue), // predicates
-                                                  null
-                                                       );
-                   
-                   rg.addRefEdge(srcHRN, hrnSummary, edgeToSummary);
-                   prevNode=hrnSummary;
-                   arrayEntryNode=hrnSummary;
-           }else{
-                   // make a new reference between summary nodes of array
-                   RefEdge edgeToSummary = new RefEdge(prevNode, // source
-                                                       hrnSummary, // dest
-                                                       typeDesc, // type
-                                                       arrayElementFieldName, // field name
-                                                       alpha, // beta
-                                                       ExistPredSet.factory(rg.predTrue), // predicates
-                                                        null
-                                                       );
-                   
-                   rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
-                   prevNode=hrnSummary;
-           }
-           
-       }
-       
-       // create a new obj node if obj has at least one non-primitive field
-       TypeDescriptor type=fd.getType();
-    if(getFieldSetTobeAnalyzed(type).size()>0){
-       TypeDescriptor typeDesc=type.dereference();
-       typeDesc.setArrayCount(0);
-       if(!mapToExistingNode.containsKey(typeDesc)){
-               TempDescriptor tempDesc=new TempDescriptor(type.getSymbol(),typeDesc);
-               AllocSite as = createParameterAllocSite(rg, tempDesc, false);
-               // make a new reference to allocated node
-                   HeapRegionNode hrnSummary = 
-                               rg.createNewHeapRegionNode(as.getSummary(), // id or null to generate a new one
-                                                          false, // single object?
-                                                          true, // summary?
-                                                          false, // out-of-context?
-                                                          typeDesc, // type
-                                                          as, // allocation site
-                                                          alpha, // inherent reach
-                                                          alpha, // current reach
-                                                          ExistPredSet.factory(rg.predTrue), // predicates
-                                                          tempDesc.toString() // description
-                                                          );
-                   rg.id2hrn.put(as.getSummary(),hrnSummary);
-                   mapToExistingNode.put(typeDesc, hrnSummary);
-                   RefEdge edgeToSummary = new RefEdge(prevNode, // source
-                                       hrnSummary, // dest
-                                       typeDesc, // type
-                                       arrayElementFieldName, // field name
-                                        alpha, // beta
-                                                        ExistPredSet.factory(rg.predTrue), // predicates
-                                                        null
-                                       );
-                   rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
-                   prevNode=hrnSummary;
-       }else{
-          HeapRegionNode hrnSummary=mapToExistingNode.get(typeDesc);
-               if(prevNode.getReferenceTo(hrnSummary, typeDesc, arrayElementFieldName)==null){
-                       RefEdge edgeToSummary = new RefEdge(prevNode, // source
-                                       hrnSummary, // dest
-                                       typeDesc, // type
-                                       arrayElementFieldName, // field name
-                                       alpha, // beta
-                                                            ExistPredSet.factory(rg.predTrue), // predicates
-                                                            null
-                                       );
-                   rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
-               }
-                prevNode=hrnSummary;
-       }
+  }
+
+  private HeapRegionNode createMultiDeimensionalArrayHRN(ReachGraph rg, AllocSite alloc, HeapRegionNode srcHRN, FieldDescriptor fd, Hashtable<HeapRegionNode, HeapRegionNode> map, Hashtable<TypeDescriptor, HeapRegionNode> mapToExistingNode, ReachSet alpha) {
+
+    int dimCount=fd.getType().getArrayCount();
+    HeapRegionNode prevNode=null;
+    HeapRegionNode arrayEntryNode=null;
+    for(int i=dimCount; i>0; i--) {
+      TypeDescriptor typeDesc=fd.getType().dereference();          //hack to get instance of type desc
+      typeDesc.setArrayCount(i);
+      TempDescriptor tempDesc=new TempDescriptor(typeDesc.getSymbol(),typeDesc);
+      HeapRegionNode hrnSummary;
+      if(!mapToExistingNode.containsKey(typeDesc)) {
+        AllocSite as;
+        if(i==dimCount) {
+          as = alloc;
+        } else {
+          as = createParameterAllocSite(rg, tempDesc, false);
+        }
+        // make a new reference to allocated node
+        hrnSummary =
+          rg.createNewHeapRegionNode(as.getSummary(),                       // id or null to generate a new one
+                                     false,                       // single object?
+                                     true,                       // summary?
+                                     false,                       // out-of-context?
+                                     as.getType(),                       // type
+                                     as,                       // allocation site
+                                     alpha,                       // inherent reach
+                                     alpha,                       // current reach
+                                     ExistPredSet.factory(rg.predTrue),                       // predicates
+                                     tempDesc.toString()                       // description
+                                     );
+        rg.id2hrn.put(as.getSummary(),hrnSummary);
+
+        mapToExistingNode.put(typeDesc, hrnSummary);
+      } else {
+        hrnSummary=mapToExistingNode.get(typeDesc);
+      }
+
+      if(prevNode==null) {
+        // make a new reference between new summary node and source
+        RefEdge edgeToSummary = new RefEdge(srcHRN,       // source
+                                            hrnSummary,             // dest
+                                            typeDesc,             // type
+                                            fd.getSymbol(),             // field name
+                                            alpha,             // beta
+                                            ExistPredSet.factory(rg.predTrue),       // predicates
+                                            null
+                                            );
+
+        rg.addRefEdge(srcHRN, hrnSummary, edgeToSummary);
+        prevNode=hrnSummary;
+        arrayEntryNode=hrnSummary;
+      } else {
+        // make a new reference between summary nodes of array
+        RefEdge edgeToSummary = new RefEdge(prevNode,             // source
+                                            hrnSummary,             // dest
+                                            typeDesc,             // type
+                                            arrayElementFieldName,             // field name
+                                            alpha,             // beta
+                                            ExistPredSet.factory(rg.predTrue),             // predicates
+                                            null
+                                            );
+
+        rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
+        prevNode=hrnSummary;
+      }
+
     }
-       
-       map.put(arrayEntryNode, prevNode);
-       return arrayEntryNode;
-}
 
-private ReachGraph createInitialTaskReachGraph(FlatMethod fm) {
+    // create a new obj node if obj has at least one non-primitive field
+    TypeDescriptor type=fd.getType();
+    if(getFieldSetTobeAnalyzed(type).size()>0) {
+      TypeDescriptor typeDesc=type.dereference();
+      typeDesc.setArrayCount(0);
+      if(!mapToExistingNode.containsKey(typeDesc)) {
+        TempDescriptor tempDesc=new TempDescriptor(type.getSymbol(),typeDesc);
+        AllocSite as = createParameterAllocSite(rg, tempDesc, false);
+        // make a new reference to allocated node
+        HeapRegionNode hrnSummary =
+          rg.createNewHeapRegionNode(as.getSummary(),                       // id or null to generate a new one
+                                     false,                       // single object?
+                                     true,                       // summary?
+                                     false,                       // out-of-context?
+                                     typeDesc,                       // type
+                                     as,                       // allocation site
+                                     alpha,                       // inherent reach
+                                     alpha,                       // current reach
+                                     ExistPredSet.factory(rg.predTrue),                       // predicates
+                                     tempDesc.toString()                       // description
+                                     );
+        rg.id2hrn.put(as.getSummary(),hrnSummary);
+        mapToExistingNode.put(typeDesc, hrnSummary);
+        RefEdge edgeToSummary = new RefEdge(prevNode,             // source
+                                            hrnSummary, // dest
+                                            typeDesc, // type
+                                            arrayElementFieldName, // field name
+                                            alpha, // beta
+                                            ExistPredSet.factory(rg.predTrue),             // predicates
+                                            null
+                                            );
+        rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
+        prevNode=hrnSummary;
+      } else {
+        HeapRegionNode hrnSummary=mapToExistingNode.get(typeDesc);
+        if(prevNode.getReferenceTo(hrnSummary, typeDesc, arrayElementFieldName)==null) {
+          RefEdge edgeToSummary = new RefEdge(prevNode,               // source
+                                              hrnSummary, // dest
+                                              typeDesc, // type
+                                              arrayElementFieldName, // field name
+                                              alpha, // beta
+                                              ExistPredSet.factory(rg.predTrue),               // predicates
+                                              null
+                                              );
+          rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
+        }
+        prevNode=hrnSummary;
+      }
+    }
+
+    map.put(arrayEntryNode, prevNode);
+    return arrayEntryNode;
+  }
+
+  private ReachGraph createInitialTaskReachGraph(FlatMethod fm) {
     ReachGraph rg = new ReachGraph();
     TaskDescriptor taskDesc = fm.getTask();
-    
+
     for (int idx = 0; idx < taskDesc.numParameters(); idx++) {
-       Descriptor paramDesc = taskDesc.getParameter(idx);
-       TypeDescriptor paramTypeDesc = taskDesc.getParamType(idx);
-       
-       // setup data structure
-       Set<HashMap<HeapRegionNode, FieldDescriptor>> workSet = 
-           new HashSet<HashMap<HeapRegionNode, FieldDescriptor>>();
-       Hashtable<TypeDescriptor, HeapRegionNode> mapTypeToExistingSummaryNode = 
-           new Hashtable<TypeDescriptor, HeapRegionNode>();
-       Hashtable<HeapRegionNode, HeapRegionNode> mapToFirstDimensionArrayNode = 
-           new Hashtable<HeapRegionNode, HeapRegionNode>();
-       Set<String> doneSet = new HashSet<String>();
-       
-       TempDescriptor tempDesc = fm.getParameter(idx);
-       
-       AllocSite as = createParameterAllocSite(rg, tempDesc, true);
-       VariableNode lnX = rg.getVariableNodeFromTemp(tempDesc);
-       Integer idNewest = as.getIthOldest(0);
-       HeapRegionNode hrnNewest = rg.id2hrn.get(idNewest);
-
-       // make a new reference to allocated node
-       RefEdge edgeNew = new RefEdge(lnX, // source
-                                     hrnNewest, // dest
-                                     taskDesc.getParamType(idx), // type
-                                     null, // field name
-                                     hrnNewest.getAlpha(), // beta
-                                     ExistPredSet.factory(rg.predTrue), // predicates
-                                      null
-                                     );
-       rg.addRefEdge(lnX, hrnNewest, edgeNew);
-
-       // set-up a work set for class field
-       ClassDescriptor classDesc = paramTypeDesc.getClassDesc();
-       for (Iterator it = classDesc.getFields(); it.hasNext();) {
-           FieldDescriptor fd = (FieldDescriptor) it.next();
-           TypeDescriptor fieldType = fd.getType();
-           if (shouldAnalysisTrack( fieldType )) {
-               HashMap<HeapRegionNode, FieldDescriptor> newMap = new HashMap<HeapRegionNode, FieldDescriptor>();
-               newMap.put(hrnNewest, fd);
-               workSet.add(newMap);
-           }
-       }
-       
-       int uniqueIdentifier = 0;
-       while (!workSet.isEmpty()) {
-           HashMap<HeapRegionNode, FieldDescriptor> map = workSet
-               .iterator().next();
-           workSet.remove(map);
-           
-           Set<HeapRegionNode> key = map.keySet();
-           HeapRegionNode srcHRN = key.iterator().next();
-           FieldDescriptor fd = map.get(srcHRN);
-           TypeDescriptor type = fd.getType();
-           String doneSetIdentifier = srcHRN.getIDString() + "_" + fd;
-           
-           if (!doneSet.contains(doneSetIdentifier)) {
-               doneSet.add(doneSetIdentifier);
-               if (!mapTypeToExistingSummaryNode.containsKey(type)) {
-                   // create new summary Node
-                   TempDescriptor td = new TempDescriptor("temp"
-                                                          + uniqueIdentifier, type);
-                   
-                   AllocSite allocSite;
-                   if(type.equals(paramTypeDesc)){
-                   //corresponding allocsite has already been created for a parameter variable.
-                       allocSite=as;
-                   }else{
-                      allocSite = createParameterAllocSite(rg, td, false);
-                   }
-                   String strDesc = allocSite.toStringForDOT()
-                       + "\\nsummary";
-                   TypeDescriptor allocType=allocSite.getType();
-                   
-                   HeapRegionNode      hrnSummary;
-                   if(allocType.isArray() && allocType.getArrayCount()>0){
-                      hrnSummary=createMultiDeimensionalArrayHRN(rg,allocSite,srcHRN,fd,mapToFirstDimensionArrayNode,mapTypeToExistingSummaryNode,hrnNewest.getAlpha());
-                   }else{                  
-                       hrnSummary = 
-                                       rg.createNewHeapRegionNode(allocSite.getSummary(), // id or null to generate a new one
-                                                                  false, // single object?
-                                                                  true, // summary?
-                                                                  false, // out-of-context?
-                                                                  allocSite.getType(), // type
-                                                                  allocSite, // allocation site
-                                                                  hrnNewest.getAlpha(), // inherent reach
-                                                                  hrnNewest.getAlpha(), // current reach
-                                                                  ExistPredSet.factory(rg.predTrue), // predicates
-                                                                  strDesc // description
-                                                                  );
-                                   rg.id2hrn.put(allocSite.getSummary(),hrnSummary);
-                   
-                   // make a new reference to summary node
-                   RefEdge edgeToSummary = new RefEdge(srcHRN, // source
-                                                       hrnSummary, // dest
-                                                       type, // type
-                                                       fd.getSymbol(), // field name
-                                                       hrnNewest.getAlpha(), // beta
-                                                       ExistPredSet.factory(rg.predTrue), // predicates
-                                                        null
-                                                       );
-                   
-                   rg.addRefEdge(srcHRN, hrnSummary, edgeToSummary);
-                   }               
-                   uniqueIdentifier++;
-                   
-                   mapTypeToExistingSummaryNode.put(type, hrnSummary);
-                   
-                   // set-up a work set for  fields of the class
-                   Set<FieldDescriptor> fieldTobeAnalyzed=getFieldSetTobeAnalyzed(type);
-                   for (Iterator iterator = fieldTobeAnalyzed.iterator(); iterator
-                                       .hasNext();) {
-                               FieldDescriptor fieldDescriptor = (FieldDescriptor) iterator
-                                               .next();
-                               HeapRegionNode newDstHRN;
-                               if(mapToFirstDimensionArrayNode.containsKey(hrnSummary)){
-                                       //related heap region node is already exsited.
-                                       newDstHRN=mapToFirstDimensionArrayNode.get(hrnSummary);
-                               }else{
-                                       newDstHRN=hrnSummary;
-                               }
-                                doneSetIdentifier = newDstHRN.getIDString() + "_" + fieldDescriptor;                                                            
-                                if(!doneSet.contains(doneSetIdentifier)){
-                                // add new work item
-                                        HashMap<HeapRegionNode, FieldDescriptor> newMap = 
-                                           new HashMap<HeapRegionNode, FieldDescriptor>();
-                                        newMap.put(newDstHRN, fieldDescriptor);
-                                        workSet.add(newMap);
-                                 }                             
-                       }
-                   
-               }else{
-                   // if there exists corresponding summary node
-                   HeapRegionNode hrnDst=mapTypeToExistingSummaryNode.get(type);
-                   
-                   RefEdge edgeToSummary = new RefEdge(srcHRN, // source
-                                                       hrnDst, // dest
-                                                       fd.getType(), // type
-                                                       fd.getSymbol(), // field name
-                                                       srcHRN.getAlpha(), // beta
-                                                       ExistPredSet.factory(rg.predTrue), // predicates  
-                                                        null
-                                                       );
-                   rg.addRefEdge(srcHRN, hrnDst, edgeToSummary);
-                   
-               }               
-           }       
-       }           
-    }  
-//    debugSnapshot(rg, fm, true);
+      Descriptor paramDesc = taskDesc.getParameter(idx);
+      TypeDescriptor paramTypeDesc = taskDesc.getParamType(idx);
+
+      // setup data structure
+      Set<HashMap<HeapRegionNode, FieldDescriptor>> workSet =
+        new HashSet<HashMap<HeapRegionNode, FieldDescriptor>>();
+      Hashtable<TypeDescriptor, HeapRegionNode> mapTypeToExistingSummaryNode =
+        new Hashtable<TypeDescriptor, HeapRegionNode>();
+      Hashtable<HeapRegionNode, HeapRegionNode> mapToFirstDimensionArrayNode =
+        new Hashtable<HeapRegionNode, HeapRegionNode>();
+      Set<String> doneSet = new HashSet<String>();
+
+      TempDescriptor tempDesc = fm.getParameter(idx);
+
+      AllocSite as = createParameterAllocSite(rg, tempDesc, true);
+      VariableNode lnX = rg.getVariableNodeFromTemp(tempDesc);
+      Integer idNewest = as.getIthOldest(0);
+      HeapRegionNode hrnNewest = rg.id2hrn.get(idNewest);
+
+      // make a new reference to allocated node
+      RefEdge edgeNew = new RefEdge(lnX,   // source
+                                    hrnNewest,   // dest
+                                    taskDesc.getParamType(idx),   // type
+                                    null,   // field name
+                                    hrnNewest.getAlpha(),   // beta
+                                    ExistPredSet.factory(rg.predTrue),   // predicates
+                                    null
+                                    );
+      rg.addRefEdge(lnX, hrnNewest, edgeNew);
+
+      // set-up a work set for class field
+      ClassDescriptor classDesc = paramTypeDesc.getClassDesc();
+      for (Iterator it = classDesc.getFields(); it.hasNext(); ) {
+        FieldDescriptor fd = (FieldDescriptor) it.next();
+        TypeDescriptor fieldType = fd.getType();
+        if (shouldAnalysisTrack(fieldType)) {
+          HashMap<HeapRegionNode, FieldDescriptor> newMap = new HashMap<HeapRegionNode, FieldDescriptor>();
+          newMap.put(hrnNewest, fd);
+          workSet.add(newMap);
+        }
+      }
+
+      int uniqueIdentifier = 0;
+      while (!workSet.isEmpty()) {
+        HashMap<HeapRegionNode, FieldDescriptor> map = workSet
+                                                       .iterator().next();
+        workSet.remove(map);
+
+        Set<HeapRegionNode> key = map.keySet();
+        HeapRegionNode srcHRN = key.iterator().next();
+        FieldDescriptor fd = map.get(srcHRN);
+        TypeDescriptor type = fd.getType();
+        String doneSetIdentifier = srcHRN.getIDString() + "_" + fd;
+
+        if (!doneSet.contains(doneSetIdentifier)) {
+          doneSet.add(doneSetIdentifier);
+          if (!mapTypeToExistingSummaryNode.containsKey(type)) {
+            // create new summary Node
+            TempDescriptor td = new TempDescriptor("temp"
+                                                   + uniqueIdentifier, type);
+
+            AllocSite allocSite;
+            if(type.equals(paramTypeDesc)) {
+              //corresponding allocsite has already been created for a parameter variable.
+              allocSite=as;
+            } else {
+              allocSite = createParameterAllocSite(rg, td, false);
+            }
+            String strDesc = allocSite.toStringForDOT()
+                             + "\\nsummary";
+            TypeDescriptor allocType=allocSite.getType();
+
+            HeapRegionNode hrnSummary;
+            if(allocType.isArray() && allocType.getArrayCount()>0) {
+              hrnSummary=createMultiDeimensionalArrayHRN(rg,allocSite,srcHRN,fd,mapToFirstDimensionArrayNode,mapTypeToExistingSummaryNode,hrnNewest.getAlpha());
+            } else {
+              hrnSummary =
+                rg.createNewHeapRegionNode(allocSite.getSummary(),                         // id or null to generate a new one
+                                           false,                         // single object?
+                                           true,                         // summary?
+                                           false,                         // out-of-context?
+                                           allocSite.getType(),                         // type
+                                           allocSite,                         // allocation site
+                                           hrnNewest.getAlpha(),                         // inherent reach
+                                           hrnNewest.getAlpha(),                         // current reach
+                                           ExistPredSet.factory(rg.predTrue),                         // predicates
+                                           strDesc                         // description
+                                           );
+              rg.id2hrn.put(allocSite.getSummary(),hrnSummary);
+
+              // make a new reference to summary node
+              RefEdge edgeToSummary = new RefEdge(srcHRN,       // source
+                                                  hrnSummary,       // dest
+                                                  type,       // type
+                                                  fd.getSymbol(),       // field name
+                                                  hrnNewest.getAlpha(),       // beta
+                                                  ExistPredSet.factory(rg.predTrue),       // predicates
+                                                  null
+                                                  );
+
+              rg.addRefEdge(srcHRN, hrnSummary, edgeToSummary);
+            }
+            uniqueIdentifier++;
+
+            mapTypeToExistingSummaryNode.put(type, hrnSummary);
+
+            // set-up a work set for  fields of the class
+            Set<FieldDescriptor> fieldTobeAnalyzed=getFieldSetTobeAnalyzed(type);
+            for (Iterator iterator = fieldTobeAnalyzed.iterator(); iterator
+                 .hasNext(); ) {
+              FieldDescriptor fieldDescriptor = (FieldDescriptor) iterator
+                                                .next();
+              HeapRegionNode newDstHRN;
+              if(mapToFirstDimensionArrayNode.containsKey(hrnSummary)) {
+                //related heap region node is already exsited.
+                newDstHRN=mapToFirstDimensionArrayNode.get(hrnSummary);
+              } else {
+                newDstHRN=hrnSummary;
+              }
+              doneSetIdentifier = newDstHRN.getIDString() + "_" + fieldDescriptor;
+              if(!doneSet.contains(doneSetIdentifier)) {
+                // add new work item
+                HashMap<HeapRegionNode, FieldDescriptor> newMap =
+                  new HashMap<HeapRegionNode, FieldDescriptor>();
+                newMap.put(newDstHRN, fieldDescriptor);
+                workSet.add(newMap);
+              }
+            }
+
+          } else {
+            // if there exists corresponding summary node
+            HeapRegionNode hrnDst=mapTypeToExistingSummaryNode.get(type);
+
+            RefEdge edgeToSummary = new RefEdge(srcHRN,         // source
+                                                hrnDst,         // dest
+                                                fd.getType(),         // type
+                                                fd.getSymbol(),         // field name
+                                                srcHRN.getAlpha(),         // beta
+                                                ExistPredSet.factory(rg.predTrue),         // predicates
+                                                null
+                                                );
+            rg.addRefEdge(srcHRN, hrnDst, edgeToSummary);
+
+          }
+        }
+      }
+    }
+
     return rg;
-}
+  }
 
 // return all allocation sites in the method (there is one allocation
 // site per FlatNew node in a method)
-private HashSet<AllocSite> getAllocationSiteSet(Descriptor d) {
-  if( !mapDescriptorToAllocSiteSet.containsKey(d) ) {
-    buildAllocationSiteSet(d);
-  }
+  private HashSet<AllocSite> getAllocationSiteSet(Descriptor d) {
+    if( !mapDescriptorToAllocSiteSet.containsKey(d) ) {
+      buildAllocationSiteSet(d);
+    }
 
-  return mapDescriptorToAllocSiteSet.get(d);
+    return mapDescriptorToAllocSiteSet.get(d);
 
-}
+  }
 
-private void buildAllocationSiteSet(Descriptor d) {
+  private void buildAllocationSiteSet(Descriptor d) {
     HashSet<AllocSite> s = new HashSet<AllocSite>();
 
     FlatMethod fm;
@@ -2134,128 +2752,138 @@ private void buildAllocationSiteSet(Descriptor d) {
       FlatNode n = toVisit.iterator().next();
 
       if( n instanceof FlatNew ) {
-       s.add(getAllocSiteFromFlatNewPRIVATE( (FlatNew) n) );
+        s.add(getAllocSiteFromFlatNewPRIVATE( (FlatNew) n) );
       }
 
       toVisit.remove(n);
       visited.add(n);
 
       for( int i = 0; i < pm.numNext(n); ++i ) {
-       FlatNode child = pm.getNext(n, i);
-       if( !visited.contains(child) ) {
-         toVisit.add(child);
-       }
+        FlatNode child = pm.getNext(n, i);
+        if( !visited.contains(child) ) {
+          toVisit.add(child);
+        }
       }
     }
 
     mapDescriptorToAllocSiteSet.put(d, s);
   }
 
-       private HashSet<AllocSite> getFlaggedAllocationSites(Descriptor dIn) {
-
-               HashSet<AllocSite> out = new HashSet<AllocSite>();
-               HashSet<Descriptor> toVisit = new HashSet<Descriptor>();
-               HashSet<Descriptor> visited = new HashSet<Descriptor>();
-
-               toVisit.add(dIn);
-
-               while (!toVisit.isEmpty()) {
-                       Descriptor d = toVisit.iterator().next();
-                       toVisit.remove(d);
-                       visited.add(d);
-
-                       HashSet<AllocSite> asSet = getAllocationSiteSet(d);
-                       Iterator asItr = asSet.iterator();
-                       while (asItr.hasNext()) {
-                               AllocSite as = (AllocSite) asItr.next();
-                               if (as.getDisjointAnalysisId() != null) {
-                                       out.add(as);
-                               }
-                       }
-
-                       // enqueue callees of this method to be searched for
-                       // allocation sites also
-                       Set callees = callGraph.getCalleeSet(d);
-                       if (callees != null) {
-                               Iterator methItr = callees.iterator();
-                               while (methItr.hasNext()) {
-                                       MethodDescriptor md = (MethodDescriptor) methItr.next();
-
-                                       if (!visited.contains(md)) {
-                                               toVisit.add(md);
-                                       }
-                               }
-                       }
-               }
-
-               return out;
-       }
-    
-private HashSet<AllocSite>
-getFlaggedAllocationSitesReachableFromTaskPRIVATE(TaskDescriptor td) {
-
-  HashSet<AllocSite> asSetTotal = new HashSet<AllocSite>();
-  HashSet<Descriptor>     toVisit    = new HashSet<Descriptor>();
-  HashSet<Descriptor>     visited    = new HashSet<Descriptor>();
-
-  toVisit.add(td);
-
-  // traverse this task and all methods reachable from this task
-  while( !toVisit.isEmpty() ) {
-    Descriptor d = toVisit.iterator().next();
-    toVisit.remove(d);
-    visited.add(d);
-
-    HashSet<AllocSite> asSet = getAllocationSiteSet(d);
-    Iterator asItr = asSet.iterator();
-    while( asItr.hasNext() ) {
-       AllocSite as = (AllocSite) asItr.next();
-       TypeDescriptor typed = as.getType();
-       if( typed != null ) {
-         ClassDescriptor cd = typed.getClassDesc();
-         if( cd != null && cd.hasFlags() ) {
-           asSetTotal.add(as);
-         }
-       }
-    }
+  private HashSet<AllocSite> getFlaggedAllocationSites(Descriptor dIn) {
 
-    // enqueue callees of this method to be searched for
-    // allocation sites also
-    Set callees = callGraph.getCalleeSet(d);
-    if( callees != null ) {
-       Iterator methItr = callees.iterator();
-       while( methItr.hasNext() ) {
-         MethodDescriptor md = (MethodDescriptor) methItr.next();
-
-         if( !visited.contains(md) ) {
-           toVisit.add(md);
-         }
-       }
+    HashSet<AllocSite> out = new HashSet<AllocSite>();
+    HashSet<Descriptor> toVisit = new HashSet<Descriptor>();
+    HashSet<Descriptor> visited = new HashSet<Descriptor>();
+
+    toVisit.add(dIn);
+
+    while (!toVisit.isEmpty()) {
+      Descriptor d = toVisit.iterator().next();
+      toVisit.remove(d);
+      visited.add(d);
+
+      HashSet<AllocSite> asSet = getAllocationSiteSet(d);
+      Iterator asItr = asSet.iterator();
+      while (asItr.hasNext()) {
+        AllocSite as = (AllocSite) asItr.next();
+        if (as.getDisjointAnalysisId() != null) {
+          out.add(as);
+        }
+      }
+
+      // enqueue callees of this method to be searched for
+      // allocation sites also
+      Set callees = callGraph.getCalleeSet(d);
+      if (callees != null) {
+        Iterator methItr = callees.iterator();
+        while (methItr.hasNext()) {
+          MethodDescriptor md = (MethodDescriptor) methItr.next();
+
+          if (!visited.contains(md)) {
+            toVisit.add(md);
+          }
+        }
+      }
     }
+
+    return out;
   }
 
-  return asSetTotal;
-}
+
+  private HashSet<AllocSite>
+  getFlaggedAllocationSitesReachableFromTaskPRIVATE(TaskDescriptor td) {
+
+    HashSet<AllocSite> asSetTotal = new HashSet<AllocSite>();
+    HashSet<Descriptor>     toVisit    = new HashSet<Descriptor>();
+    HashSet<Descriptor>     visited    = new HashSet<Descriptor>();
+
+    toVisit.add(td);
+
+    // traverse this task and all methods reachable from this task
+    while( !toVisit.isEmpty() ) {
+      Descriptor d = toVisit.iterator().next();
+      toVisit.remove(d);
+      visited.add(d);
+
+      HashSet<AllocSite> asSet = getAllocationSiteSet(d);
+      Iterator asItr = asSet.iterator();
+      while( asItr.hasNext() ) {
+        AllocSite as = (AllocSite) asItr.next();
+        TypeDescriptor typed = as.getType();
+        if( typed != null ) {
+          ClassDescriptor cd = typed.getClassDesc();
+          if( cd != null && cd.hasFlags() ) {
+            asSetTotal.add(as);
+          }
+        }
+      }
+
+      // enqueue callees of this method to be searched for
+      // allocation sites also
+      Set callees = callGraph.getCalleeSet(d);
+      if( callees != null ) {
+        Iterator methItr = callees.iterator();
+        while( methItr.hasNext() ) {
+          MethodDescriptor md = (MethodDescriptor) methItr.next();
+
+          if( !visited.contains(md) ) {
+            toVisit.add(md);
+          }
+        }
+      }
+    }
+
+    return asSetTotal;
+  }
 
   public Set<Descriptor> getDescriptorsToAnalyze() {
     return descriptorsToAnalyze;
   }
 
-  
-  
+  public EffectsAnalysis getEffectsAnalysis() {
+    return effectsAnalysis;
+  }
+
+  public ReachGraph getReachGraph(Descriptor d) {
+    return mapDescriptorToCompleteReachGraph.get(d);
+  }
+
+  public ReachGraph getEnterReachGraph(FlatNode fn) {
+    return fn2rgAtEnter.get(fn);
+  }
+
   // get successive captures of the analysis state, use compiler
   // flags to control
   boolean takeDebugSnapshots = false;
-  String  descSymbolDebug    = null;
+  String descSymbolDebug    = null;
   boolean stopAfterCapture   = false;
-  int     snapVisitCounter   = 0;
-  int     snapNodeCounter    = 0;
-  int     visitStartCapture  = 0;
-  int     numVisitsToCapture = 0;
+  int snapVisitCounter   = 0;
+  int snapNodeCounter    = 0;
+  int visitStartCapture  = 0;
+  int numVisitsToCapture = 0;
 
 
-  void debugSnapshot( ReachGraph rg, FlatNode fn, boolean in ) {
+  void debugSnapshot(ReachGraph rg, FlatNode fn, boolean in) {
     if( snapVisitCounter > visitStartCapture + numVisitsToCapture ) {
       return;
     }
@@ -2265,31 +2893,84 @@ getFlaggedAllocationSitesReachableFromTaskPRIVATE(TaskDescriptor td) {
     }
 
     if( snapVisitCounter >= visitStartCapture ) {
-      System.out.println( "    @@@ snapping visit="+snapVisitCounter+
-                          ", node="+snapNodeCounter+
-                          " @@@" );
+      System.out.println("    @@@ snapping visit="+snapVisitCounter+
+                         ", node="+snapNodeCounter+
+                         " @@@");
       String graphName;
       if( in ) {
-        graphName = String.format( "snap%03d_%04din",
-                                   snapVisitCounter,
-                                   snapNodeCounter );
+        graphName = String.format("snap%03d_%04din",
+                                  snapVisitCounter,
+                                  snapNodeCounter);
       } else {
-        graphName = String.format( "snap%03d_%04dout",
-                                   snapVisitCounter,
-                                   snapNodeCounter );
+        graphName = String.format("snap%03d_%04dout",
+                                  snapVisitCounter,
+                                  snapNodeCounter);
       }
       if( fn != null ) {
-       graphName = graphName + fn;
-      }
-      rg.writeGraph( graphName,
-                     true,   // write labels (variables)
-                     true,   // selectively hide intermediate temp vars
-                     true,   // prune unreachable heap regions
-                     false,  // hide reachability
-                     true,   // hide subset reachability states
-                     true,   // hide predicates
-                     false );// hide edge taints
+        graphName = graphName + fn;
+      }
+      rg.writeGraph(graphName,
+                    true,    // write labels (variables)
+                    true,    // selectively hide intermediate temp vars
+                    true,    // prune unreachable heap regions
+                    false,   // hide reachability
+                    false,   // hide subset reachability states
+                    true,    // hide predicates
+                    true);   // hide edge taints
+    }
+  }
+
+
+
+
+  public Set<Alloc> canPointToAt( TempDescriptor x,
+                                  FlatNode programPoint ) {
+
+    ReachGraph rgAtEnter = fn2rgAtEnter.get( programPoint );
+    if( rgAtEnter == null ) {
+      return null; 
+    }
+
+    return rgAtEnter.canPointTo( x );
+  }
+
+
+  public Set<Alloc> canPointToAfter( TempDescriptor x,
+                                     FlatNode programPoint ) {
+
+    ReachGraph rgAtExit = fn2rgAtExit.get( programPoint );
+    if( rgAtExit == null ) {
+      return null; 
+    }
+
+    return rgAtExit.canPointTo( x );
+  }
+  
+
+  public Hashtable< Alloc, Set<Alloc> > canPointToAt( TempDescriptor x,
+                                                      FieldDescriptor f,
+                                                      FlatNode programPoint ) {
+
+    ReachGraph rgAtEnter = fn2rgAtEnter.get( programPoint );
+    if( rgAtEnter == null ) {
+      return null; 
     }
+    
+    return rgAtEnter.canPointTo( x, f.getSymbol(), f.getType() );
   }
 
+
+  public Hashtable< Alloc, Set<Alloc> > canPointToAtElement( TempDescriptor x,
+                                                             FlatNode programPoint ) {
+
+    ReachGraph rgAtEnter = fn2rgAtEnter.get( programPoint );
+    if( rgAtEnter == null ) {
+      return null; 
+    }
+
+    assert x.getType() != null;
+    assert x.getType().isArray();
+
+    return rgAtEnter.canPointTo( x, arrayElementFieldName, x.getType().dereference() );
+  }
 }