get set up part of the stall site analysis
[IRC.git] / Robust / src / Analysis / Disjoint / DisjointAnalysis.java
index da618c502e1699b890628f9e25f3b2bf48f402de..3649b822c3db5269f402ed6b7a6c51352a4d95de 100644 (file)
@@ -93,227 +93,240 @@ public class DisjointAnalysis {
                return out;
        }
        
-       // use the methods given above to check every possible alias
-         // between task parameters and flagged allocation sites reachable
-         // from the task
-         public void writeAllAliases(String outputFile, 
-                                     String timeReport,
-                                     String justTime,
-                                     boolean tabularOutput,
-                                     int numLines
-)
-                       throws java.io.IOException {
-               checkAnalysisComplete();
+  // 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, 
+                              String timeReport,
+                              String justTime,
+                              boolean tabularOutput,
+                              int numLines
+                              )
+    throws java.io.IOException {
+    checkAnalysisComplete();
 
-               BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
+    BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
 
-               if (!tabularOutput) {
-                       bw.write("Conducting ownership analysis with allocation depth = "
-                                       + allocationDepth + "\n");
-                       bw.write(timeReport + "\n");
-               }
+    if (!tabularOutput) {
+      bw.write("Conducting ownership analysis with allocation depth = "
+               + allocationDepth + "\n");
+      bw.write(timeReport + "\n");
+    }
 
-               int numAlias = 0;
+    int numSharing = 0;
 
-               // look through every task for potential aliases
-               Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
-               while (taskItr.hasNext()) {
-                       TaskDescriptor td = (TaskDescriptor) taskItr.next();
+    // look through every task for potential sharing
+    Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
+    while (taskItr.hasNext()) {
+      TaskDescriptor td = (TaskDescriptor) taskItr.next();
 
-                       if (!tabularOutput) {
-                               bw.write("\n---------" + td + "--------\n");
-                       }
+      if (!tabularOutput) {
+        bw.write("\n---------" + td + "--------\n");
+      }
 
-                       HashSet<AllocSite> allocSites = getFlaggedAllocationSitesReachableFromTask(td);
+      HashSet<AllocSite> allocSites = getFlaggedAllocationSitesReachableFromTask(td);
 
-                       Set<HeapRegionNode> common;
+      Set<HeapRegionNode> common;
 
-                       // for each task parameter, check for aliases with
-                       // other task parameters and every allocation site
-                       // reachable from this task
-                       boolean foundSomeAlias = false;
+      // for each task parameter, check for sharing classes with
+      // other task parameters and every allocation site
+      // reachable from this task
+      boolean foundSomeSharing = false;
 
-                       FlatMethod fm = state.getMethodFlat(td);
-                       for (int i = 0; i < fm.numParameters(); ++i) {
+      FlatMethod fm = state.getMethodFlat(td);
+      for (int i = 0; i < fm.numParameters(); ++i) {
 
-                          // skip parameters with types that cannot reference
-                          // into the heap
-                          if( !shouldAnalysisTrack( fm.getParameter( i ).getType() ) ) {
-                            continue;
-                          }
+        // skip parameters with types that cannot reference
+        // into the heap
+        if( !shouldAnalysisTrack( fm.getParameter( i ).getType() ) ) {
+          continue;
+        }
                           
-                               // for the ith parameter check for aliases 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() ) ) {
-                                    continue;
-                                  }
-
-
-                                  common = hasPotentialSharing(td, i, j);
-                                       if (!common.isEmpty()) {
-                                               foundSomeAlias = true;
-                                               if (!tabularOutput) {
-                                                       bw.write("Potential alias between parameters " + i
-                                                                       + " and " + j + ".\n");
-                                                       bw.write(prettyPrintNodeSet(common) + "\n");
-                                               } else {
-                                                       ++numAlias;
-                                               }
-                                       }
-                               }
+        // 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() ) ) {
+            continue;
+          }
+
+
+          common = hasPotentialSharing(td, i, j);
+          if (!common.isEmpty()) {
+            foundSomeSharing = true;
+            ++numSharing;
+            if (!tabularOutput) {
+              bw.write("Potential sharing between parameters " + i
+                       + " and " + j + ".\n");
+              bw.write(prettyPrintNodeSet(common) + "\n");
+            }
+          }
+        }
 
-                               // for the ith parameter, check for aliases against
-                               // the set of allocation sites reachable from this
-                               // task context
-                               Iterator allocItr = allocSites.iterator();
-                               while (allocItr.hasNext()) {
-                                       AllocSite as = (AllocSite) allocItr.next();
-                                       common = hasPotentialSharing(td, i, as);
-                                       if (!common.isEmpty()) {
-                                               foundSomeAlias = true;
-                                               if (!tabularOutput) {
-                                                       bw.write("Potential alias between parameter " + i
-                                                                       + " and " + as.getFlatNew() + ".\n");
-                                                       bw.write(prettyPrintNodeSet(common) + "\n");
-                                               } else {
-                                                       ++numAlias;
-                                               }
-                                       }
-                               }
-                       }
+        // for the ith parameter, check for sharing classes against
+        // the set of allocation sites reachable from this
+        // task context
+        Iterator allocItr = allocSites.iterator();
+        while (allocItr.hasNext()) {
+          AllocSite as = (AllocSite) allocItr.next();
+          common = hasPotentialSharing(td, i, as);
+          if (!common.isEmpty()) {
+            foundSomeSharing = true;
+            ++numSharing;
+            if (!tabularOutput) {
+              bw.write("Potential sharing between parameter " + i
+                       + " and " + as.getFlatNew() + ".\n");
+              bw.write(prettyPrintNodeSet(common) + "\n");
+            }
+          }
+        }
+      }
 
-                       // for each allocation site check for aliases with
-                       // other allocation sites in the context of execution
-                       // of this task
-                       HashSet<AllocSite> outerChecked = new HashSet<AllocSite>();
-                       Iterator allocItr1 = allocSites.iterator();
-                       while (allocItr1.hasNext()) {
-                               AllocSite as1 = (AllocSite) allocItr1.next();
-
-                               Iterator allocItr2 = allocSites.iterator();
-                               while (allocItr2.hasNext()) {
-                                       AllocSite as2 = (AllocSite) allocItr2.next();
-
-                                       if (!outerChecked.contains(as2)) {
-                                               common = hasPotentialSharing(td, as1, as2);
-
-                                               if (!common.isEmpty()) {
-                                                       foundSomeAlias = true;
-                                                       if (!tabularOutput) {
-                                                               bw.write("Potential alias between "
-                                                                               + as1.getFlatNew() + " and "
-                                                                               + as2.getFlatNew() + ".\n");
-                                                               bw.write(prettyPrintNodeSet(common) + "\n");
-                                                       } else {
-                                                               ++numAlias;
-                                                       }
-                                               }
-                                       }
-                               }
+      // for each allocation site check for sharing classes with
+      // other allocation sites in the context of execution
+      // of this task
+      HashSet<AllocSite> outerChecked = new HashSet<AllocSite>();
+      Iterator allocItr1 = allocSites.iterator();
+      while (allocItr1.hasNext()) {
+        AllocSite as1 = (AllocSite) allocItr1.next();
+
+        Iterator allocItr2 = allocSites.iterator();
+        while (allocItr2.hasNext()) {
+          AllocSite as2 = (AllocSite) allocItr2.next();
+
+          if (!outerChecked.contains(as2)) {
+            common = hasPotentialSharing(td, as1, as2);
+
+            if (!common.isEmpty()) {
+              foundSomeSharing = true;
+              ++numSharing;
+              if (!tabularOutput) {
+                bw.write("Potential sharing between "
+                         + as1.getFlatNew() + " and "
+                         + as2.getFlatNew() + ".\n");
+                bw.write(prettyPrintNodeSet(common) + "\n");
+              }
+            }
+          }
+        }
 
-                               outerChecked.add(as1);
-                       }
+        outerChecked.add(as1);
+      }
 
-                       if (!foundSomeAlias) {
-                               if (!tabularOutput) {
-                                       bw.write("No aliases between flagged objects in Task " + td
-                                                       + ".\n");
-                               }
-                       }
-               }
+      if (!foundSomeSharing) {
+        if (!tabularOutput) {
+          bw.write("No sharing between flagged objects in Task " + td
+                   + ".\n");
+        }
+      }
+    }
 
-               /*
-               if (!tabularOutput) {
-                       bw.write("\n" + computeAliasContextHistogram());
-               } else {
-                       bw.write(" & " + numAlias + " & " + justTime + " & " + numLines
-                                       + " & " + numMethodsAnalyzed() + " \\\\\n");
-               }
-               */
+               
+    if (tabularOutput) {
+      bw.write(" & " + numSharing + " & " + justTime + " & " + numLines
+               + " & " + numMethodsAnalyzed() + " \\\\\n");
+    } else {
+      bw.write("\nNumber sharing classes: "+numSharing);
+    }
 
-               bw.close();
-       }
+    bw.close();
+  }
        
-       // this version of writeAllAliases is for Java programs that have no tasks
-         public void writeAllAliasesJava(String outputFile, 
-                                         String timeReport,
-                                         String justTime,
-                                         boolean tabularOutput,
-                                         int numLines
-)
-                       throws java.io.IOException {
-               checkAnalysisComplete();
-
-               assert !state.TASK;
-
-               BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
-
-               bw.write("Conducting disjoint reachability analysis with allocation depth = "
-                               + allocationDepth + "\n");
-               bw.write(timeReport + "\n\n");
-
-               boolean foundSomeAlias = false;
-
-               Descriptor d = typeUtil.getMain();
-               HashSet<AllocSite> allocSites = getFlaggedAllocationSites(d);
+  // this version of writeAllSharing is for Java programs that have no tasks
+  public void writeAllSharingJava(String outputFile, 
+                                  String timeReport,
+                                  String justTime,
+                                  boolean tabularOutput,
+                                  int numLines
+                                  )
+    throws java.io.IOException {
+    checkAnalysisComplete();
 
-               // for each allocation site check for aliases with
-               // other allocation sites in the context of execution
-               // of this task
-               HashSet<AllocSite> outerChecked = new HashSet<AllocSite>();
-               Iterator allocItr1 = allocSites.iterator();
-               while (allocItr1.hasNext()) {
-                       AllocSite as1 = (AllocSite) allocItr1.next();
+    assert !state.TASK;
 
-                       Iterator allocItr2 = allocSites.iterator();
-                       while (allocItr2.hasNext()) {
-                               AllocSite as2 = (AllocSite) allocItr2.next();
+    int numSharing = 0;
 
-                               if (!outerChecked.contains(as2)) {
-                                       Set<HeapRegionNode> common = hasPotentialSharing(d,
-                                                       as1, as2);
+    BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
+    
+    bw.write("Conducting disjoint reachability analysis with allocation depth = "
+             + allocationDepth + "\n");
+    bw.write(timeReport + "\n\n");
+
+    boolean foundSomeSharing = false;
+
+    Descriptor d = typeUtil.getMain();
+    HashSet<AllocSite> allocSites = getFlaggedAllocationSites(d);
+
+    // for each allocation site check for sharing classes with
+    // other allocation sites in the context of execution
+    // of this task
+    HashSet<AllocSite> outerChecked = new HashSet<AllocSite>();
+    Iterator allocItr1 = allocSites.iterator();
+    while (allocItr1.hasNext()) {
+      AllocSite as1 = (AllocSite) allocItr1.next();
+
+      Iterator allocItr2 = allocSites.iterator();
+      while (allocItr2.hasNext()) {
+        AllocSite as2 = (AllocSite) allocItr2.next();
+
+        if (!outerChecked.contains(as2)) {
+          Set<HeapRegionNode> common = hasPotentialSharing(d,
+                                                           as1, as2);
+
+          if (!common.isEmpty()) {
+            foundSomeSharing = true;
+            bw.write("Potential sharing between "
+                     + as1.getDisjointAnalysisId() + " and "
+                     + as2.getDisjointAnalysisId() + ".\n");
+            bw.write(prettyPrintNodeSet(common) + "\n");
+            ++numSharing;
+          }
+        }
+      }
 
-                                       if (!common.isEmpty()) {
-                                               foundSomeAlias = true;
-                                               bw.write("Potential alias between "
-                                                               + as1.getDisjointAnalysisId() + " and "
-                                                               + as2.getDisjointAnalysisId() + ".\n");
-                                               bw.write(prettyPrintNodeSet(common) + "\n");
-                                       }
-                               }
-                       }
+      outerChecked.add(as1);
+    }
 
-                       outerChecked.add(as1);
-               }
+    if (!foundSomeSharing) {
+      bw.write("No sharing classes between flagged objects found.\n");
+    } else {
+      bw.write("\nNumber sharing classes: "+numSharing);
+    }
 
-               if (!foundSomeAlias) {
-                       bw.write("No aliases between flagged objects found.\n");
-               }
+    bw.write("Number of methods analyzed: "+numMethodsAnalyzed()+"\n");
 
-//             bw.write("\n" + computeAliasContextHistogram());
-               bw.close();
-       }
+    bw.close();
+  }
          
-         ///////////////////////////////////////////
-         //
-         // end public interface
-         //
-         ///////////////////////////////////////////
+  ///////////////////////////////////////////
+  //
+  // end public interface
+  //
+  ///////////////////////////////////////////
 
-         protected void checkAnalysisComplete() {
-                   if( !analysisComplete ) {
-                     throw new Error("Warning: public interface method called while analysis is running.");
-                   }
-         
+  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!
   public static boolean releaseMode;
 
+  // use command line option to set this, analysis
+  // should attempt to be deterministic
+  public static boolean determinismDesired;
+
+  // 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 =
+    new DescriptorComparator();
+
+
   // data from the compiler
   public State            state;
   public CallGraph        callGraph;
@@ -323,7 +336,8 @@ public class DisjointAnalysis {
   public int              allocationDepth;
   
   // 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
@@ -362,6 +376,8 @@ public class DisjointAnalysis {
   // current descriptors to visit in fixed-point
   // interprocedural analysis, prioritized by
   // dependency in the call graph
+  protected Stack<Descriptor>
+    descriptorsToVisitStack;
   protected PriorityQueue<DescriptorQWrapper> 
     descriptorsToVisitQ;
   
@@ -376,6 +392,12 @@ public class DisjointAnalysis {
   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;
 
   // maps a descriptor to its current partial result
   // from the intraprocedural fixed-point analysis--
@@ -410,7 +432,20 @@ public class DisjointAnalysis {
   protected Hashtable< Descriptor, Hashtable< FlatCall, ReachGraph > >
     mapDescriptorToIHMcontributions;
 
-  // TODO -- CHANGE EDGE/TYPE/FIELD storage!
+  // 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;
+
+  // 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;
+
+
   public static final String arrayElementFieldName = "___element_";
   static protected Hashtable<TypeDescriptor, FieldDescriptor>
     mapTypeToArrayField;
@@ -427,15 +462,29 @@ public class DisjointAnalysis {
   
   //map task descriptor to initial task parameter 
   protected Hashtable<Descriptor, ReachGraph>
-  mapDescriptorToReachGraph;
+    mapDescriptorToReachGraph;
 
   protected PointerMethod pm;
 
+  static protected Hashtable<FlatNode, ReachGraph> fn2rg =
+    new Hashtable<FlatNode, ReachGraph>();
+
+  private Hashtable<FlatCall, Descriptor> fc2enclosing;  
+
+  //protected RBlockRelationAnalysis rra;
+
 
   // allocate various structures that are not local
   // to a single class method--should be done once
-  protected void allocateStructures() {    
-    descriptorsToAnalyze = new HashSet<Descriptor>();
+  protected void allocateStructures() {
+    
+    if( determinismDesired ) {
+      // use an ordered set
+      descriptorsToAnalyze = new TreeSet<Descriptor>( dComp );      
+    } else {
+      // otherwise use a speedy hashset
+      descriptorsToAnalyze = new HashSet<Descriptor>();
+    }
 
     mapDescriptorToCompleteReachGraph =
       new Hashtable<Descriptor, ReachGraph>();
@@ -452,14 +501,29 @@ public class DisjointAnalysis {
     mapDescriptorToIHMcontributions =
       new Hashtable< Descriptor, Hashtable< FlatCall, ReachGraph > >();
 
+    mapDescriptorToInitialContext =
+      new Hashtable<Descriptor, ReachGraph>();    
+
+    mapBackEdgeToMonotone =
+      new Hashtable<FlatNode, ReachGraph>();
+    
     mapHrnIdToAllocSite =
       new Hashtable<Integer, AllocSite>();
 
     mapTypeToArrayField = 
       new Hashtable <TypeDescriptor, FieldDescriptor>();
 
-    descriptorsToVisitQ =
-      new PriorityQueue<DescriptorQWrapper>();
+    if( state.DISJOINTDVISITSTACK ||
+        state.DISJOINTDVISITSTACKEESONTOP 
+        ) {
+      descriptorsToVisitStack =
+        new Stack<Descriptor>();
+    }
+
+    if( state.DISJOINTDVISITPQUE ) {
+      descriptorsToVisitQ =
+        new PriorityQueue<DescriptorQWrapper>();
+    }
 
     descriptorsToVisitSet =
       new HashSet<Descriptor>();
@@ -467,11 +531,18 @@ public class DisjointAnalysis {
     mapDescriptorToPriority =
       new Hashtable<Descriptor, Integer>();
     
+    calleesToEnqueue = 
+      new HashSet<Descriptor>();    
+
     mapDescriptorToAllocSiteSet =
        new Hashtable<Descriptor,    HashSet<AllocSite> >();
     
     mapDescriptorToReachGraph = 
        new Hashtable<Descriptor, ReachGraph>();
+
+    pm = new PointerMethod();
+
+    fc2enclosing = new Hashtable<FlatCall, Descriptor>();
   }
 
 
@@ -483,6 +554,7 @@ public class DisjointAnalysis {
                           CallGraph        cg,
                           Liveness         l,
                           ArrayReferencees ar
+                           //RBlockRelationAnalysis rra
                            ) throws java.io.IOException {
     init( s, tu, cg, l, ar );
   }
@@ -492,6 +564,7 @@ public class DisjointAnalysis {
                        CallGraph        callGraph,
                        Liveness         liveness,
                        ArrayReferencees arrayReferencees
+                       //RBlockRelationAnalysis rra
                        ) throws java.io.IOException {
          
     analysisComplete = false;
@@ -503,6 +576,7 @@ public class DisjointAnalysis {
     this.arrayReferencees        = arrayReferencees;
     this.allocationDepth         = state.DISJOINTALLOCDEPTH;
     this.releaseMode             = state.DISJOINTRELEASEMODE;
+    this.determinismDesired      = state.DISJOINTDETERMINISM;
 
     this.writeFinalDOTs          = state.DISJOINTWRITEDOTS && !state.DISJOINTWRITEALL;
     this.writeAllIncrementalDOTs = state.DISJOINTWRITEDOTS &&  state.DISJOINTWRITEALL;
@@ -514,14 +588,32 @@ public class DisjointAnalysis {
     this.stopAfterCapture        = state.DISJOINTSNAPSTOPAFTER;
     this.snapVisitCounter        = 1; // count visits from 1 (user will write 1, means 1st visit)
     this.snapNodeCounter         = 0; // count nodes from 0
-    this.pm=new PointerMethod();
 
+    assert
+      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.debugCallSiteVisitsUntilExit = state.DISJOINTDEBUGCALLCOUNT;
+    ReachGraph.debugCallSiteVisitStartCapture
+      = state.DISJOINTDEBUGCALLVISITTOSTART;
+
+    ReachGraph.debugCallSiteNumVisitsToCapture
+      = state.DISJOINTDEBUGCALLNUMVISITS;
+
+    ReachGraph.debugCallSiteStopAfter
+      = state.DISJOINTDEBUGCALLSTOPAFTER;
+
+    ReachGraph.debugCallSiteVisitCounter 
+      = 0; // count visits from 1, is incremented before first visit
+    
+    
 
     allocateStructures();
 
@@ -545,52 +637,70 @@ public class DisjointAnalysis {
       writeFinalIHMs();
     }
 
+    if( state.DISJOINTWRITEINITCONTEXTS ) {
+      writeInitialContexts();
+    }
+
     if( state.DISJOINTALIASFILE != null ) {
       if( state.TASK ) {
-        writeAllAliases(state.DISJOINTALIASFILE, treport, justtime, state.DISJOINTALIASTAB, state.lines);
+        writeAllSharing(state.DISJOINTALIASFILE, treport, justtime, state.DISJOINTALIASTAB, state.lines);
       } else {
-        /*
-        writeAllAliasesJava( aliasFile, 
-                             treport, 
-                             justtime, 
-                             state.DISJOINTALIASTAB, 
-                             state.lines );
-        */
+        writeAllSharingJava(state.DISJOINTALIASFILE, 
+                            treport, 
+                            justtime, 
+                            state.DISJOINTALIASTAB, 
+                            state.lines
+                            );
       }
     }
   }
 
 
+  protected boolean moreDescriptorsToVisit() {
+    if( state.DISJOINTDVISITSTACK ||
+        state.DISJOINTDVISITSTACKEESONTOP
+        ) {
+      return !descriptorsToVisitStack.isEmpty();
+
+    } else if( state.DISJOINTDVISITPQUE ) {
+      return !descriptorsToVisitQ.isEmpty();
+    }
+
+    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 {  
 
+    // 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 ) {
-      // This analysis does not support Bamboo at the moment,
-      // but if it does in the future we would initialize the
-      // set of descriptors to analyze as the program-reachable
-      // tasks and the methods callable by them.  For Java,
-      // just methods reachable from the main method.
-      System.out.println( "Bamboo..." );
-      Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();
+      System.out.println( "Bamboo mode..." );
       
-      while (taskItr.hasNext()) {
-         TaskDescriptor td = (TaskDescriptor) taskItr.next();
-         if (!descriptorsToAnalyze.contains(td)) {           
-             descriptorsToAnalyze.add(td);
-             descriptorsToAnalyze.addAll(callGraph.getAllMethods(td));
-         }       
+      Iterator taskItr = state.getTaskSymbolTable().getDescriptorsIterator();      
+      while( taskItr.hasNext() ) {
+        TaskDescriptor td = (TaskDescriptor) taskItr.next();
+        if( !descriptorsToAnalyze.contains( td ) ) {
+          // add all methods transitively reachable from the
+          // tasks as well
+          descriptorsToAnalyze.add( td );
+          descriptorsToAnalyze.addAll( callGraph.getAllMethods( td ) );
+        }        
       }
-
+      
     } else {
+      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.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
@@ -598,28 +708,69 @@ public class DisjointAnalysis {
       descriptorsToAnalyze.add( mdAnalysisEntry );
     }
 
-    // topologically sort according to the call graph so 
-    // leaf calls are ordered first, smarter analysis order
-    // CHANGED: order leaf calls last!!
-    LinkedList<Descriptor> sortedDescriptors = 
-      topologicalSort( descriptorsToAnalyze );
-
-    // add sorted descriptors to priority queue, and duplicate
-    // the queue as a set for efficiently testing whether some
-    // method is marked for analysis
-    int p = 0;
-    Iterator<Descriptor> dItr = sortedDescriptors.iterator();
-    while( dItr.hasNext() ) {
-      Descriptor d = dItr.next();
-      mapDescriptorToPriority.put( d, new Integer( p ) );
-      descriptorsToVisitQ.add( new DescriptorQWrapper( p, d ) );
-      descriptorsToVisitSet.add( d );
-      ++p;
+
+    // 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 
+      // leaf calls are last, helps build contexts up first
+      LinkedList<Descriptor> sortedDescriptors = 
+        topologicalSort( descriptorsToAnalyze );
+
+      // add sorted descriptors to priority queue, and duplicate
+      // the queue as a set for efficiently testing whether some
+      // method is marked for analysis
+      int p = 0;
+      Iterator<Descriptor> dItr;
+
+      // for the priority queue, give items at the head
+      // 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 );
+        ++p;
+      }
+
+    } else if( state.DISJOINTDVISITSTACK ||
+               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();      
+        while( taskItr.hasNext() ) {
+         TaskDescriptor td = (TaskDescriptor) taskItr.next();
+          descriptorsToVisitStack.add( td );
+          descriptorsToVisitSet.add( td );
+        }
+        
+      } else {
+        descriptorsToVisitStack.add( mdAnalysisEntry );
+        descriptorsToVisitSet.add( mdAnalysisEntry );
+      }
+
+    } else {
+      throw new Error( "Unknown method scheduling mode" );
     }
 
-    // analyze methods from the priority queue until it is empty
-    while( !descriptorsToVisitQ.isEmpty() ) {
-      Descriptor d = descriptorsToVisitQ.poll().getDescriptor();
+
+    // analyze scheduled methods until there are no more to visit
+    while( moreDescriptorsToVisit() ) {
+      Descriptor d = null;
+
+      if( state.DISJOINTDVISITSTACK ||
+          state.DISJOINTDVISITSTACKEESONTOP
+          ) {
+        d = descriptorsToVisitStack.pop();
+
+      } else if( state.DISJOINTDVISITPQUE ) {
+        d = descriptorsToVisitQ.poll().getDescriptor();
+      }
+
       assert descriptorsToVisitSet.contains( d );
       descriptorsToVisitSet.remove( d );
 
@@ -633,21 +784,48 @@ public class DisjointAnalysis {
 
       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 );
         
+        if( state.DISJOINTDEBUGSCHEDULING ) {
+          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 );
+
+          if( state.DISJOINTDEBUGSCHEDULING ) {
+            System.out.println( "    "+dNext );
+          }
        }
-      }      
-    }
+      }
+
+      // whether or not the method under analysis changed,
+      // 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
+      if( state.DISJOINTDVISITSTACKEESONTOP ) {
+        Iterator<Descriptor> depsItr = calleesToEnqueue.iterator();
+        while( depsItr.hasNext() ) {
+          Descriptor dNext = depsItr.next();
+          enqueue( dNext );
+        }
+        calleesToEnqueue.clear();
+      }     
+
+    }   
   }
 
   protected ReachGraph analyzeMethod( Descriptor d ) 
@@ -660,10 +838,19 @@ public class DisjointAnalysis {
     } else {
       fm = state.getMethodFlat( d );
     }
-    pm.analyzeMethod(fm);
+    pm.analyzeMethod( fm );
+
     // intraprocedural work set
     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
     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 );
+    }
     
     // mapping of current partial results
     Hashtable<FlatNode, ReachGraph> mapFlatNodeToReachGraph =
@@ -674,7 +861,14 @@ public class DisjointAnalysis {
     HashSet<FlatReturnNode> setReturns = new HashSet<FlatReturnNode>();
 
     while( !flatNodesToVisit.isEmpty() ) {
-      FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+
+      FlatNode fn;      
+      if( determinismDesired ) {
+        assert !flatNodesToVisitQ.isEmpty();
+        fn = flatNodesToVisitQ.remove();
+      } else {
+        fn = flatNodesToVisit.iterator().next();
+      }
       flatNodesToVisit.remove( fn );
 
       // effect transfer function defined by this node,
@@ -703,7 +897,11 @@ public class DisjointAnalysis {
          rg.merge( rgParent );
        }
       }
-
+      
+      //if(rra.isEndOfRegion(fn)){
+      //  rg.clearAccessibleVarSet();
+      //  also need to clear stall mapping
+      //}
 
       if( takeDebugSnapshots && 
          d.getSymbol().equals( descSymbolDebug ) 
@@ -731,15 +929,20 @@ public class DisjointAnalysis {
       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 );
+          if( determinismDesired ) {
+            flatNodesToVisitQ.add( nn );
+          }
        }
       }
     }
 
+
     // end by merging all return nodes into a complete
-    // ownership graph that represents all possible heap
+    // reach graph that represents all possible heap
     // states after the flat method returns
     ReachGraph completeGraph = new ReachGraph();
 
@@ -816,14 +1019,17 @@ public class DisjointAnalysis {
 
         assert fc.getMethod().equals( d );
 
-        // some call sites are in same method context though,
-        // and all of them should be merged together first,
-        // then heaps from different contexts should be merged
-        // THIS ASSUMES DIFFERENT CONTEXTS NEED SPECIAL CONSIDERATION!
-        // such as, do allocation sites need to be aged?
+        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 );
 
-        rg.merge_diffMethodContext( rgContrib );
-      }      
     } break;
       
     case FKind.FlatOpNode:
@@ -913,22 +1119,63 @@ public class DisjointAnalysis {
       }
       break;
 
+      /*
+    case FKind.FlatSESEEnterNode:
+      FlatSESEEnterNode sese = (FlatSESEEnterNode) fn;
+      rg.taintLiveTemps( sese,
+                         liveness.getLiveInTemps( fmContaining, fn ) 
+                         );
+      break;
+
+    case FKind.FlatSESEExitNode:
+      FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
+      rg.removeInContextTaints( fsexn.getFlatEnter() );
+      break;
+      */
+
     case FKind.FlatCall: {
-      //TODO: temporal fix for task descriptor case
-      //MethodDescriptor mdCaller = fmContaining.getMethod();
       Descriptor mdCaller;
-      if(fmContaining.getMethod()!=null){
-         mdCaller  = fmContaining.getMethod();
-      }else{
-         mdCaller = fmContaining.getTask();
+      if( fmContaining.getMethod() != null ){
+        mdCaller = fmContaining.getMethod();
+      } else {
+        mdCaller = fmContaining.getTask();
       }      
       FlatCall         fc       = (FlatCall) fn;
       MethodDescriptor mdCallee = fc.getMethod();
       FlatMethod       fmCallee = state.getMethodFlat( mdCallee );
 
-      boolean writeDebugDOTs = 
+
+      boolean debugCallSite =
         mdCaller.getSymbol().equals( state.DISJOINTDEBUGCALLER ) &&
-        mdCallee.getSymbol().equals( state.DISJOINTDEBUGCALLEE );      
+        mdCallee.getSymbol().equals( state.DISJOINTDEBUGCALLEE );
+
+      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)
+            ) {
+          writeDebugDOTs = true;
+          System.out.println( "      $$$ Capturing this call site visit $$$" );
+          if( ReachGraph.debugCallSiteStopAfter &&
+              (ReachGraph.debugCallSiteVisitCounter == 
+               ReachGraph.debugCallSiteVisitStartCapture + 
+               ReachGraph.debugCallSiteNumVisitsToCapture - 1)
+              ) {
+            stopAfter = true;
+          }
+        }
+      }
 
 
       // calculate the heap this call site can reach--note this is
@@ -955,18 +1202,36 @@ public class DisjointAnalysis {
         // if heap at call site changed, update the contribution,
         // and reschedule the callee for analysis
         addIHMcontribution( mdCallee, fc, heapForThisCall_cur );        
-        enqueue( mdCallee );
-      }
 
+        // map a FlatCall to its enclosing method/task descriptor 
+        // so we can write that info out later
+        fc2enclosing.put( fc, mdCaller );
+
+        if( state.DISJOINTDEBUGSCHEDULING ) {
+          System.out.println( "  context changed, scheduling callee: "+mdCallee );
+        }
 
+        if( state.DISJOINTDVISITSTACKEESONTOP ) {
+          calleesToEnqueue.add( mdCallee );
+        } else {
+          enqueue( mdCallee );
+        }
+
+      }
 
 
       // the transformation for a call site should update the
       // current heap abstraction with any effects from the callee,
       // or if the method is virtual, the effects from any possible
       // callees, so find the set of callees...
-      Set<MethodDescriptor> setPossibleCallees =
-        new HashSet<MethodDescriptor>();
+      Set<MethodDescriptor> setPossibleCallees;
+      if( determinismDesired ) {
+        // use an ordered set
+        setPossibleCallees = new TreeSet<MethodDescriptor>( dComp );        
+      } else {
+        // otherwise use a speedy hashset
+        setPossibleCallees = new HashSet<MethodDescriptor>();
+      }
 
       if( mdCallee.isStatic() ) {        
         setPossibleCallees.add( mdCallee );
@@ -998,7 +1263,17 @@ public class DisjointAnalysis {
         if( rgEffect == null ) {
           // if this method has never been analyzed just schedule it 
           // for analysis and skip over this call site for now
-          enqueue( mdPossible );
+          if( state.DISJOINTDVISITSTACKEESONTOP ) {
+            calleesToEnqueue.add( mdPossible );
+          } else {
+            enqueue( mdPossible );
+          }
+          
+          if( state.DISJOINTDEBUGSCHEDULING ) {
+            System.out.println( "  callee hasn't been analyzed, scheduling: "+mdPossible );
+          }
+
+
         } else {
           rgCopy.resolveMethodCall( fc, 
                                     fmPossible, 
@@ -1012,6 +1287,12 @@ public class DisjointAnalysis {
       }
 
 
+      if( stopAfter ) {
+        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;
@@ -1038,12 +1319,20 @@ public class DisjointAnalysis {
     //rg.globalSweep();
 
 
+    // back edges are strictly monotonic
+    if( pm.isBackEdge( fn ) ) {
+      ReachGraph rgPrevResult = mapBackEdgeToMonotone.get( fn );
+      rg.merge( rgPrevResult );
+      mapBackEdgeToMonotone.put( fn, rg );
+    }
+    
     // 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
     return rg;
   }
 
+
   
   // this method should generate integers strictly greater than zero!
   // special "shadow" regions are made from a heap region by negating
@@ -1079,11 +1368,13 @@ public class DisjointAnalysis {
       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 subset reachability states         
-                     true ); // hide edge taints                        
+                     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                        
     }
   }
 
@@ -1100,15 +1391,36 @@ public class DisjointAnalysis {
         FlatCall   fc  = (FlatCall)   me2.getKey();
         ReachGraph rg  = (ReachGraph) me2.getValue();
                 
-        rg.writeGraph( "IHMPARTFOR"+d+"FROM"+fc,
+        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
-                       false,  // hide subset reachability states
+                       true,   // hide subset reachability states
+                       false,  // hide predicates
                        true ); // hide edge taints
       }
     }
   }
+
+  private void writeInitialContexts() {
+    Set entrySet = mapDescriptorToInitialContext.entrySet();
+    Iterator itr = entrySet.iterator();
+    while( itr.hasNext() ) {
+      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                        
+    }
+  }
    
 
   protected ReachGraph getPartial( Descriptor d ) {
@@ -1133,8 +1445,10 @@ public class DisjointAnalysis {
                      true,   // write labels (variables)
                      true,   // selectively hide intermediate temp vars
                      true,   // prune unreachable heap regions
-                     false,  // hide subset reachability states
-                     true ); // hide edge taints
+                     false,  // hide all reachability
+                     true,   // hide subset reachability states
+                     false,  // hide predicates
+                     false); // hide edge taints
       
       mapDescriptorToNumUpdates.put( d, n + 1 );
     }
@@ -1146,12 +1460,11 @@ public class DisjointAnalysis {
   protected AllocSite getAllocSiteFromFlatNewPRIVATE( FlatNew fnew ) {
 
     if( !mapFlatNewToAllocSite.containsKey( fnew ) ) {
-      AllocSite as = 
-        (AllocSite) Canonical.makeCanonical( new AllocSite( allocationDepth, 
-                                                            fnew, 
-                                                            fnew.getDisjointId() 
-                                                            )
-                                             );
+      AllocSite as = AllocSite.factory( allocationDepth, 
+                                        fnew, 
+                                        fnew.getDisjointId(),
+                                        false
+                                        );
 
       // the newest nodes are single objects
       for( int i = 0; i < allocationDepth; ++i ) {
@@ -1181,185 +1494,10 @@ public class DisjointAnalysis {
     return true;
   }
 
-
-  /*
-  // return all allocation sites in the method (there is one allocation
-  // site per FlatNew node in a method)
-  protected HashSet<AllocSite> getAllocSiteSet(Descriptor d) {
-    if( !mapDescriptorToAllocSiteSet.containsKey(d) ) {
-      buildAllocSiteSet(d);
-    }
-
-    return mapDescriptorToAllocSiteSet.get(d);
-
-  }
-  */
-
-  /*
-  protected void buildAllocSiteSet(Descriptor d) {
-    HashSet<AllocSite> s = new HashSet<AllocSite>();
-
-    FlatMethod fm = state.getMethodFlat( d );
-
-    // visit every node in this FlatMethod's IR graph
-    // and make a set of the allocation sites from the
-    // FlatNew node's visited
-    HashSet<FlatNode> visited = new HashSet<FlatNode>();
-    HashSet<FlatNode> toVisit = new HashSet<FlatNode>();
-    toVisit.add( fm );
-
-    while( !toVisit.isEmpty() ) {
-      FlatNode n = toVisit.iterator().next();
-
-      if( n instanceof FlatNew ) {
-       s.add(getAllocSiteFromFlatNewPRIVATE( (FlatNew) n) );
-      }
-
-      toVisit.remove( n );
-      visited.add( n );
-
-      for( int i = 0; i < n.numNext(); ++i ) {
-       FlatNode child = n.getNext( i );
-       if( !visited.contains( child ) ) {
-         toVisit.add( child );
-       }
-      }
-    }
-
-    mapDescriptorToAllocSiteSet.put( d, s );
-  }
-  */
-  /*
-  protected HashSet<AllocSite> getFlaggedAllocSites(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 = getAllocSiteSet(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;
-  }
-  */
-
-  /*
-  protected HashSet<AllocSite>
-  getFlaggedAllocSitesReachableFromTaskPRIVATE(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 = getAllocSiteSet(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;
-  }
-  */
-
-
-  /*
-  protected String computeAliasContextHistogram() {
-    
-    Hashtable<Integer, Integer> mapNumContexts2NumDesc = 
-      new Hashtable<Integer, Integer>();
-  
-    Iterator itr = mapDescriptorToAllDescriptors.entrySet().iterator();
-    while( itr.hasNext() ) {
-      Map.Entry me = (Map.Entry) itr.next();
-      HashSet<Descriptor> s = (HashSet<Descriptor>) me.getValue();
-      
-      Integer i = mapNumContexts2NumDesc.get( s.size() );
-      if( i == null ) {
-       i = new Integer( 0 );
-      }
-      mapNumContexts2NumDesc.put( s.size(), i + 1 );
-    }   
-
-    String s = "";
-    int total = 0;
-
-    itr = mapNumContexts2NumDesc.entrySet().iterator();
-    while( itr.hasNext() ) {
-      Map.Entry me = (Map.Entry) itr.next();
-      Integer c0 = (Integer) me.getKey();
-      Integer d0 = (Integer) me.getValue();
-      total += d0;
-      s += String.format( "%4d methods had %4d unique alias contexts.\n", d0, c0 );
-    }
-
-    s += String.format( "\n%4d total methods analayzed.\n", total );
-
-    return s;
-  }
-
   protected int numMethodsAnalyzed() {    
     return descriptorsToAnalyze.size();
   }
-  */
+  
 
   
   
@@ -1423,8 +1561,17 @@ public class DisjointAnalysis {
 
   protected LinkedList<Descriptor> topologicalSort( Set<Descriptor> toSort ) {
 
-    Set       <Descriptor> discovered = new HashSet   <Descriptor>();
-    LinkedList<Descriptor> sorted     = new LinkedList<Descriptor>();
+    Set<Descriptor> discovered;
+
+    if( determinismDesired ) {
+      // use an ordered set
+      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() ) {
@@ -1493,11 +1640,21 @@ public class DisjointAnalysis {
 
 
   protected void enqueue( Descriptor d ) {
+
     if( !descriptorsToVisitSet.contains( d ) ) {
-      Integer priority = mapDescriptorToPriority.get( d );
-      descriptorsToVisitQ.add( new DescriptorQWrapper( priority, 
-                                                       d ) 
-                               );
+
+      if( state.DISJOINTDVISITSTACK ||
+          state.DISJOINTDVISITSTACKEESONTOP
+          ) {
+        descriptorsToVisitStack.add( d );
+
+      } else if( state.DISJOINTDVISITPQUE ) {
+        Integer priority = mapDescriptorToPriority.get( d );
+        descriptorsToVisitQ.add( new DescriptorQWrapper( priority, 
+                                                         d ) 
+                                 );
+      }
+
       descriptorsToVisitSet.add( d );
     }
   }
@@ -1545,12 +1702,13 @@ public class DisjointAnalysis {
       getIHMcontributions( d );
 
     if( !heapsFromCallers.containsKey( fc ) ) {
-      heapsFromCallers.put( fc, new ReachGraph() );
+      return null;
     }
 
     return heapsFromCallers.get( fc );
   }
 
+
   public void addIHMcontribution( Descriptor d,
                                   FlatCall   fc,
                                   ReachGraph rg
@@ -1561,12 +1719,33 @@ public class DisjointAnalysis {
     heapsFromCallers.put( fc, rg );
   }
 
-private AllocSite createParameterAllocSite(ReachGraph rg, TempDescriptor tempDesc) {
+
+  private AllocSite createParameterAllocSite( ReachGraph     rg, 
+                                              TempDescriptor tempDesc,
+                                              boolean        flagRegions
+                                              ) {
     
-    // create temp descriptor for each parameter variable
-    FlatNew flatNew = new FlatNew(tempDesc.getType(), tempDesc, false);
+    FlatNew flatNew;
+    if( flagRegions ) {
+      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
+                             );
+    }
+
     // create allocation site
-    AllocSite as = (AllocSite) Canonical.makeCanonical(new AllocSite( allocationDepth, flatNew, flatNew.getDisjointId()));
+    AllocSite as = AllocSite.factory( allocationDepth, 
+                                      flatNew, 
+                                      flatNew.getDisjointId(),
+                                      false
+                                      );
     for (int i = 0; i < allocationDepth; ++i) {
        Integer id = generateUniqueHeapRegionNodeID();
        as.setIthOldest(i, id);
@@ -1579,7 +1758,7 @@ private AllocSite createParameterAllocSite(ReachGraph rg, TempDescriptor tempDes
     
     return as;
     
-}
+  }
 
 private Set<FieldDescriptor> getFieldSetTobeAnalyzed(TypeDescriptor typeDesc){
        
@@ -1613,18 +1792,17 @@ private Set<FieldDescriptor> getFieldSetTobeAnalyzed(TypeDescriptor typeDesc){
                        if(i==dimCount){
                                as = alloc;
                        }else{
-                               as = createParameterAllocSite(rg, tempDesc);
+                          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, // flagged?
                                                           false, // out-of-context?
                                                           as.getType(), // type
                                                           as, // allocation site
-                                                          null, // inherent reach
+                                                          alpha, // inherent reach
                                                           alpha, // current reach
                                                           ExistPredSet.factory(rg.predTrue), // predicates
                                                           tempDesc.toString() // description
@@ -1638,12 +1816,13 @@ private Set<FieldDescriptor> getFieldSetTobeAnalyzed(TypeDescriptor typeDesc){
            
            if(prevNode==null){
                    // make a new reference between new summary node and source
-                   RefEdge edgeToSummary = new RefEdge(srcHRN, // source
+              RefEdge edgeToSummary = new RefEdge(srcHRN, // source
                                                        hrnSummary, // dest
                                                        typeDesc, // type
                                                        fd.getSymbol(), // field name
                                                        alpha, // beta
-                                                       ExistPredSet.factory(rg.predTrue) // predicates
+                                                  ExistPredSet.factory(rg.predTrue), // predicates
+                                                  null
                                                        );
                    
                    rg.addRefEdge(srcHRN, hrnSummary, edgeToSummary);
@@ -1656,7 +1835,8 @@ private Set<FieldDescriptor> getFieldSetTobeAnalyzed(TypeDescriptor typeDesc){
                                                        typeDesc, // type
                                                        arrayElementFieldName, // field name
                                                        alpha, // beta
-                                                       ExistPredSet.factory(rg.predTrue) // predicates
+                                                       ExistPredSet.factory(rg.predTrue), // predicates
+                                                        null
                                                        );
                    
                    rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
@@ -1672,17 +1852,16 @@ private Set<FieldDescriptor> getFieldSetTobeAnalyzed(TypeDescriptor typeDesc){
        typeDesc.setArrayCount(0);
        if(!mapToExistingNode.containsKey(typeDesc)){
                TempDescriptor tempDesc=new TempDescriptor(type.getSymbol(),typeDesc);
-               AllocSite as = createParameterAllocSite(rg, tempDesc);
+               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, // flagged?
                                                           false, // out-of-context?
                                                           typeDesc, // type
                                                           as, // allocation site
-                                                          null, // inherent reach
+                                                          alpha, // inherent reach
                                                           alpha, // current reach
                                                           ExistPredSet.factory(rg.predTrue), // predicates
                                                           tempDesc.toString() // description
@@ -1694,19 +1873,21 @@ private Set<FieldDescriptor> getFieldSetTobeAnalyzed(TypeDescriptor typeDesc){
                                        typeDesc, // type
                                        arrayElementFieldName, // field name
                                         alpha, // beta
-                                       ExistPredSet.factory(rg.predTrue) // predicates
+                                                        ExistPredSet.factory(rg.predTrue), // predicates
+                                                        null
                                        );
                    rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
                    prevNode=hrnSummary;
        }else{
-               HeapRegionNode hrnSummary=mapToExistingNode.get(typeDesc);
+          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
+                                                            ExistPredSet.factory(rg.predTrue), // predicates
+                                                            null
                                        );
                    rg.addRefEdge(prevNode, hrnSummary, edgeToSummary);
                }
@@ -1737,20 +1918,22 @@ private ReachGraph createInitialTaskReachGraph(FlatMethod fm) {
        
        TempDescriptor tempDesc = fm.getParameter(idx);
        
-       AllocSite as = createParameterAllocSite(rg, tempDesc);
+       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
+                                     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();) {
@@ -1787,7 +1970,7 @@ private ReachGraph createInitialTaskReachGraph(FlatMethod fm) {
                    //corresponding allocsite has already been created for a parameter variable.
                        allocSite=as;
                    }else{
-                       allocSite = createParameterAllocSite(rg, td);
+                      allocSite = createParameterAllocSite(rg, td, false);
                    }
                    String strDesc = allocSite.toStringForDOT()
                        + "\\nsummary";
@@ -1801,11 +1984,10 @@ private ReachGraph createInitialTaskReachGraph(FlatMethod fm) {
                                        rg.createNewHeapRegionNode(allocSite.getSummary(), // id or null to generate a new one
                                                                   false, // single object?
                                                                   true, // summary?
-                                                                  false, // flagged?
                                                                   false, // out-of-context?
                                                                   allocSite.getType(), // type
                                                                   allocSite, // allocation site
-                                                                  null, // inherent reach
+                                                                  hrnNewest.getAlpha(), // inherent reach
                                                                   hrnNewest.getAlpha(), // current reach
                                                                   ExistPredSet.factory(rg.predTrue), // predicates
                                                                   strDesc // description
@@ -1818,7 +2000,8 @@ private ReachGraph createInitialTaskReachGraph(FlatMethod fm) {
                                                        type, // type
                                                        fd.getSymbol(), // field name
                                                        hrnNewest.getAlpha(), // beta
-                                                       ExistPredSet.factory(rg.predTrue) // predicates
+                                                       ExistPredSet.factory(rg.predTrue), // predicates
+                                                        null
                                                        );
                    
                    rg.addRefEdge(srcHRN, hrnSummary, edgeToSummary);
@@ -1859,7 +2042,8 @@ private ReachGraph createInitialTaskReachGraph(FlatMethod fm) {
                                                        fd.getType(), // type
                                                        fd.getSymbol(), // field name
                                                        srcHRN.getAlpha(), // beta
-                                                       ExistPredSet.factory(rg.predTrue) // predicates
+                                                       ExistPredSet.factory(rg.predTrue), // predicates  
+                                                        null
                                                        );
                    rg.addRefEdge(srcHRN, hrnDst, edgeToSummary);
                    
@@ -2009,6 +2193,9 @@ getFlaggedAllocationSitesReachableFromTaskPRIVATE(TaskDescriptor td) {
   return asSetTotal;
 }
 
+  public Set<Descriptor> getDescriptorsToAnalyze() {
+    return descriptorsToAnalyze;
+  }
 
   
   
@@ -2038,11 +2225,11 @@ getFlaggedAllocationSitesReachableFromTaskPRIVATE(TaskDescriptor td) {
                           " @@@" );
       String graphName;
       if( in ) {
-        graphName = String.format( "snap%02d_%04din",
+        graphName = String.format( "snap%03d_%04din",
                                    snapVisitCounter,
                                    snapNodeCounter );
       } else {
-        graphName = String.format( "snap%02d_%04dout",
+        graphName = String.format( "snap%03d_%04dout",
                                    snapVisitCounter,
                                    snapNodeCounter );
       }
@@ -2050,11 +2237,13 @@ getFlaggedAllocationSitesReachableFromTaskPRIVATE(TaskDescriptor td) {
        graphName = graphName + fn;
       }
       rg.writeGraph( graphName,
-                     true,  // write labels (variables)
-                     true,  // selectively hide intermediate temp vars
-                     true,  // prune unreachable heap regions
-                     false, // hide subset reachability states
-                     true );// hide edge taints
+                     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
     }
   }