couple fixes to make sure out-of-context nodes get all the states they need, and...
[IRC.git] / Robust / src / Analysis / Disjoint / ReachGraph.java
index 72f42dbd05171587451425d88117d51c49ffce4c..3f13f4901b268c0adab3040bdd5c70062f6b4f8e 100644 (file)
@@ -139,10 +139,7 @@ public class ReachGraph {
       alpha = inherent;
     }
 
-    if( preds == null ) {
-      // TODO: do this right?  For out-of-context nodes?
-      preds = ExistPredSet.factory();
-    }
+    assert preds != null;
     
     HeapRegionNode hrn = new HeapRegionNode( id,
                                             isSingleObject,
@@ -575,7 +572,7 @@ public class ReachGraph {
        
        if( edgeExisting != null ) {
          edgeExisting.setBeta(
-                               Canonical.union( edgeExisting.getBeta(),
+                               Canonical.unionORpreds( edgeExisting.getBeta(),
                                                 edgeNew.getBeta()
                                                 )
                                );
@@ -881,7 +878,7 @@ public class ReachGraph {
        // otherwise an edge from the referencer to hrnSummary exists already
        // and the edge referencer->hrn should be merged with it
        edgeSummary.setBeta( 
-                            Canonical.union( edgeMerged.getBeta(),
+                            Canonical.unionORpreds( edgeMerged.getBeta(),
                                              edgeSummary.getBeta() 
                                              ) 
                              );
@@ -915,7 +912,7 @@ public class ReachGraph {
        // otherwise an edge from the referencer to alpha_S exists already
        // and the edge referencer->alpha_K should be merged with it
        edgeSummary.setBeta( 
-                            Canonical.union( edgeMerged.getBeta(),
+                            Canonical.unionORpreds( edgeMerged.getBeta(),
                                              edgeSummary.getBeta() 
                                              ) 
                              );
@@ -929,7 +926,7 @@ public class ReachGraph {
 
     // then merge hrn reachability into hrnSummary
     hrnSummary.setAlpha( 
-                        Canonical.union( hrnSummary.getAlpha(),
+                        Canonical.unionORpreds( hrnSummary.getAlpha(),
                                          hrn.getAlpha() 
                                          )
                          );
@@ -1080,8 +1077,10 @@ public class ReachGraph {
        Iterator<ChangeTuple> itrCprime = C.iterator();
        while( itrCprime.hasNext() ) {
          ChangeTuple c = itrCprime.next();
-         if( edgeF.getBeta().contains( c.getSetToMatch() ) ) {
-           changesToPass = Canonical.union( changesToPass, c );
+         if( edgeF.getBeta().containsIgnorePreds( c.getStateToMatch() ) 
+              != null
+              ) {
+           changesToPass = Canonical.add( changesToPass, c );
          }
        }
 
@@ -1123,7 +1122,7 @@ public class ReachGraph {
       // but this propagation may be only one of many concurrent
       // possible changes, so keep a running union with the node's
       // partially updated new alpha set
-      n.setAlphaNew( Canonical.union( n.getAlphaNew(),
+      n.setAlphaNew( Canonical.unionORpreds( n.getAlphaNew(),
                                       localDelta 
                                       )
                      );
@@ -1160,8 +1159,10 @@ public class ReachGraph {
       Iterator<ChangeTuple> itrC = C.iterator();
       while( itrC.hasNext() ) {
        ChangeTuple c = itrC.next();
-       if( edgeE.getBeta().contains( c.getSetToMatch() ) ) {
-         changesToPass = Canonical.union( changesToPass, c );
+       if( edgeE.getBeta().containsIgnorePreds( c.getStateToMatch() ) 
+            != null
+            ) {
+         changesToPass = Canonical.add( changesToPass, c );
        }
       }
 
@@ -1212,7 +1213,7 @@ public class ReachGraph {
       // but this propagation may be only one of many concurrent
       // possible changes, so keep a running union with the edge's
       // partially updated new beta set
-      e.setBetaNew( Canonical.union( e.getBetaNew(),
+      e.setBetaNew( Canonical.unionORpreds( e.getBetaNew(),
                                      localDelta  
                                      )
                     );
@@ -1280,15 +1281,9 @@ public class ReachGraph {
 
   // used below to convert a ReachSet to its callee-context
   // equivalent with respect to allocation sites in this graph
-  protected ReachSet toCalleeContext( Set<ReachTuple> oocTuples,
-                                      ReachSet        rs,
-                                      Integer         hrnID,
-                                      TempDescriptor  tdSrc,
-                                      Integer         hrnSrcID,
-                                      Integer         hrnDstID,
-                                      TypeDescriptor  type,
-                                      String          field,
-                                      boolean         outOfContext
+  protected ReachSet toCalleeContext( ReachSet        rs,
+                                      ExistPredSet    preds,
+                                      Set<ReachTuple> oocTuples
                                       ) {
     ReachSet out = ReachSet.factory();
    
@@ -1307,9 +1302,10 @@ public class ReachGraph {
         while( rtItr.hasNext() ) {
           ReachTuple rt = rtItr.next();
 
-          // only translate this tuple if it is in the out-context bag
+          // only translate this tuple if it is
+          // in the out-callee-context bag
           if( !oocTuples.contains( rt ) ) {
-            stateNew = Canonical.union( stateNew, rt );
+            stateNew = Canonical.add( stateNew, rt );
             continue;
           }
 
@@ -1331,20 +1327,20 @@ public class ReachGraph {
       
           if( age == AllocSite.AGE_notInThisSite ) {
             // things not from the site just go back in
-            stateNew = Canonical.union( stateNew, rt );
+            stateNew = Canonical.add( stateNew, rt );
 
           } else if( age == AllocSite.AGE_summary ||
                      rt.isOutOfContext()
                      ) {
             // the in-context summary and all existing out-of-context
             // stuff all become
-            stateNew = Canonical.union( stateNew,
-                                        ReachTuple.factory( as.getSummary(),
-                                                            true, // multi
-                                                            rt.getArity(),
-                                                            true  // out-of-context
-                                                            )
-                                        );
+            stateNew = Canonical.add( stateNew,
+                                      ReachTuple.factory( as.getSummary(),
+                                                          true, // multi
+                                                          rt.getArity(),
+                                                          true  // out-of-context
+                                                          )
+                                      );
           } else {
             // otherwise everything else just goes to an out-of-context
             // version, everything else the same
@@ -1353,46 +1349,20 @@ public class ReachGraph {
 
             assert !rt.isMultiObject();
 
-            stateNew = Canonical.union( stateNew,
-                                        ReachTuple.factory( rt.getHrnID(),
-                                                            rt.isMultiObject(),
-                                                            rt.getArity(),
-                                                            true  // out-of-context
-                                                            )
-                                        );        
+            stateNew = Canonical.add( stateNew,
+                                      ReachTuple.factory( rt.getHrnID(),
+                                                          rt.isMultiObject(),
+                                                          rt.getArity(),
+                                                          true  // out-of-context
+                                                          )
+                                      );        
           }
         }
         
         stateCallee = stateNew;
       }
-
-
-      ExistPredSet preds;
-
-      if( outOfContext ) {
-        preds = predsEmpty;
-      } else {
-        ExistPred pred;
-        if( hrnID != null ) {
-          assert tdSrc    == null;
-          assert hrnSrcID == null;
-          assert hrnDstID == null;
-          pred = ExistPred.factory( hrnID, 
-                                    stateCaller );
-        } else {
-          assert tdSrc != null || hrnSrcID != null;
-          assert hrnDstID != null;
-          pred = ExistPred.factory( tdSrc,
-                                    hrnSrcID,
-                                    hrnDstID,
-                                    type,
-                                    field,
-                                    stateCaller,
-                                    false );
-        }
-        preds = ExistPredSet.factory( pred );
-      }
       
+      // attach the passed in preds
       stateCallee = Canonical.attach( stateCallee,
                                       preds );
 
@@ -1439,11 +1409,11 @@ public class ReachGraph {
           stateCaller = Canonical.attach( stateCaller,
                                           calleeStatesSatisfied.get( stateCallee )
                                           );        
-          out = Canonical.union( out,
-                                 stateCaller
-                                 );
+          out = Canonical.add( out,
+                               stateCaller
+                               );
         }
-      }
+      } 
     }    
 
     assert out.isCanonical();
@@ -1615,16 +1585,14 @@ public class ReachGraph {
                                   false, // out-of-context?
                                   hrnCaller.getType(),
                                   hrnCaller.getAllocSite(),
-                                  toCalleeContext( oocTuples,
-                                                   hrnCaller.getInherent(),      // in state
-                                                   hrnCaller.getID(),            // node pred
-                                                   null, null, null, null, null, // edge pred
-                                                   false ),                      // ooc pred
-                                  toCalleeContext( oocTuples,
-                                                   hrnCaller.getAlpha(),         // in state
-                                                   hrnCaller.getID(),            // node pred
-                                                   null, null, null, null, null, // edge pred
-                                                   false ),                      // ooc pred
+                                  toCalleeContext( hrnCaller.getInherent(),
+                                                   preds,
+                                                   oocTuples 
+                                                   ),
+                                  toCalleeContext( hrnCaller.getAlpha(),
+                                                   preds,
+                                                   oocTuples 
+                                                   ),
                                   preds,
                                   hrnCaller.getDescription()
                                   );
@@ -1654,7 +1622,9 @@ public class ReachGraph {
                            reArg.getType(),
                            reArg.getField(),
                            null,
-                           false ); // out-of-context
+                           true,  // out-of-callee-context
+                           false  // out-of-caller-context
+                           );
       
       ExistPredSet preds = 
         ExistPredSet.factory( pred );
@@ -1664,15 +1634,10 @@ public class ReachGraph {
                      hrnDstCallee,
                      reArg.getType(),
                      reArg.getField(),
-                     toCalleeContext( oocTuples,
-                                      reArg.getBeta(),      // in state
-                                      null,                 // node pred
-                                      arg,                  // edge pred
-                                      null,                 // edge pred
-                                      hrnDstCallee.getID(), // edge pred
-                                      reArg.getType(),      // edge pred
-                                      reArg.getField(),     // edge pred
-                                      false ),              // ooc pred
+                     toCalleeContext( reArg.getBeta(),
+                                      preds,
+                                      oocTuples
+                                      ),
                      preds
                      );
       
@@ -1703,7 +1668,9 @@ public class ReachGraph {
                            reCaller.getType(),
                            reCaller.getField(),
                            null,
-                           false ); // out-of-context
+                           false, // out-of-callee-context
+                           false  // out-of-caller-context
+                           );
       
       ExistPredSet preds = 
         ExistPredSet.factory( pred );
@@ -1713,15 +1680,10 @@ public class ReachGraph {
                      hrnDstCallee,
                      reCaller.getType(),
                      reCaller.getField(),
-                     toCalleeContext( oocTuples,
-                                      reCaller.getBeta(),   // in state
-                                      null,                 // node pred
-                                      null,                 // edge pred
-                                      hrnSrcCallee.getID(), // edge pred
-                                      hrnDstCallee.getID(), // edge pred
-                                      reCaller.getType(),   // edge pred
-                                      reCaller.getField(),  // edge pred
-                                      false ),              // ooc pred
+                     toCalleeContext( reCaller.getBeta(),
+                                      preds,
+                                      oocTuples 
+                                      ),
                      preds
                      );
       
@@ -1744,19 +1706,30 @@ public class ReachGraph {
       ReachSet       oocReach;
       TempDescriptor oocPredSrcTemp = null;
       Integer        oocPredSrcID   = null;
+      boolean        outOfCalleeContext;
+      boolean        outOfCallerContext;
 
       if( rsnCaller instanceof VariableNode ) {
         VariableNode vnCaller = (VariableNode) rsnCaller;
         oocNodeType    = null;
         oocReach       = rsetEmpty;
         oocPredSrcTemp = vnCaller.getTempDescriptor();
+        outOfCalleeContext = true;
+        outOfCallerContext = false;
 
       } else {
         HeapRegionNode hrnSrcCaller = (HeapRegionNode) rsnCaller;
         assert !callerNodeIDsCopiedToCallee.contains( hrnSrcCaller.getID() );
         oocNodeType  = hrnSrcCaller.getType();
         oocReach     = hrnSrcCaller.getAlpha(); 
-        oocPredSrcID = hrnSrcCaller.getID();        
+        oocPredSrcID = hrnSrcCaller.getID();
+        if( hrnSrcCaller.isOutOfContext() ) {
+          outOfCalleeContext = false;
+          outOfCallerContext = true;
+        } else {
+          outOfCalleeContext = true;
+          outOfCallerContext = false;
+        }
       }
 
       ExistPred pred =
@@ -1766,7 +1739,9 @@ public class ReachGraph {
                            reCaller.getType(),
                            reCaller.getField(),
                            null,
-                           true ); // out-of-context
+                           outOfCalleeContext,
+                           outOfCallerContext
+                           );
 
       ExistPredSet preds = 
         ExistPredSet.factory( pred );
@@ -1802,18 +1777,14 @@ public class ReachGraph {
                                         true,  // out-of-context?
                                         oocNodeType,
                                         null,  // alloc site, shouldn't be used
-                                        toCalleeContext( oocTuples, 
-                                                         oocReach,                     // in state
-                                                         null,                         // node pred
-                                                         null, null, null, null, null, // edge pred
-                                                         true                          // ooc pred
-                                                         ), // inherent
-                                        toCalleeContext( oocTuples,
-                                                         oocReach,                     // in state
-                                                         null,                         // node pred
-                                                         null, null, null, null, null, // edge pred
-                                                         true                          // ooc pred
-                                                         ), // alpha
+                                        toCalleeContext( oocReach,               
+                                                         preds,
+                                                         oocTuples
+                                                         ),
+                                        toCalleeContext( oocReach,
+                                                         preds,
+                                                         oocTuples
+                                                         ),
                                         preds,
                                         "out-of-context"
                                         );       
@@ -1835,21 +1806,26 @@ public class ReachGraph {
                                           true,  // out-of-context?
                                           oocNodeType,
                                           null,  // alloc site, shouldn't be used
-                                          toCalleeContext( oocTuples,
-                                                           oocReach,                     // in state
-                                                           null,                         // node pred
-                                                           null, null, null, null, null, // edge pred
-                                                           true                          // ooc pred
-                                                           ), // inherent
-                                          toCalleeContext( oocTuples,
-                                                           oocReach,                     // in state
-                                                           null,                         // node pred
-                                                           null, null, null, null, null, // edge pred
-                                                           true                          // ooc pred
-                                                           ), // alpha
+                                          toCalleeContext( oocReach,
+                                                           preds,
+                                                           oocTuples
+                                                           ),
+                                          toCalleeContext( oocReach,
+                                                           preds,
+                                                           oocTuples
+                                                           ),
                                           preds,
                                           "out-of-context"
                                           );       
+          } else {
+            // otherwise it is there, so merge reachability
+            hrnCalleeAndOutContext.setAlpha( Canonical.unionORpreds( hrnCalleeAndOutContext.getAlpha(),
+                                                                     toCalleeContext( oocReach,
+                                                                                      preds,
+                                                                                      oocTuples
+                                                                                      )
+                                                                     )
+                                             );
           }
         }
 
@@ -1859,15 +1835,9 @@ public class ReachGraph {
                                     hrnDstCallee,
                                     reCaller.getType(),
                                     reCaller.getField(),
-                                    toCalleeContext( oocTuples,
-                                                     reCaller.getBeta(),   // in state
-                                                     null,                 // node pred
-                                                     oocPredSrcTemp,       // edge pred
-                                                     oocPredSrcID,         // edge pred
-                                                     hrnDstCaller.getID(), // edge pred
-                                                     reCaller.getType(),   // edge pred
-                                                     reCaller.getField(),  // edge pred
-                                                     false                 // ooc pred
+                                    toCalleeContext( reCaller.getBeta(),
+                                                     preds,
+                                                     oocTuples
                                                      ),
                                     preds
                                     )
@@ -1875,17 +1845,11 @@ public class ReachGraph {
         
         } else {
         // the out-of-context edge already exists
-        oocEdgeExisting.setBeta( Canonical.union( oocEdgeExisting.getBeta(),
-                                                  toCalleeContext( oocTuples,
-                                                                   reCaller.getBeta(),   // in state
-                                                                   null,                 // node pred
-                                                                   oocPredSrcTemp,       // edge pred
-                                                                   oocPredSrcID,         // edge pred
-                                                                   hrnDstCaller.getID(), // edge pred
-                                                                   reCaller.getType(),   // edge pred
-                                                                   reCaller.getField(),  // edge pred
-                                                                   false                 // ooc pred
-                                                                   )
+        oocEdgeExisting.setBeta( Canonical.unionORpreds( oocEdgeExisting.getBeta(),
+                                                         toCalleeContext( reCaller.getBeta(),
+                                                                          preds,
+                                                                          oocTuples
+                                                                          )
                                                   )
                                  );         
           
@@ -1893,6 +1857,17 @@ public class ReachGraph {
                                                   reCaller.getPreds()
                                                   )
                                   );          
+
+        HeapRegionNode hrnCalleeAndOutContext =
+          (HeapRegionNode) oocEdgeExisting.getSrc();
+        hrnCalleeAndOutContext.setAlpha( Canonical.unionORpreds( hrnCalleeAndOutContext.getAlpha(),
+                                                                 toCalleeContext( oocReach,
+                                                                                  preds,
+                                                                                  oocTuples
+                                                                                  )
+                                                                 )
+                                         );
+        
         
       }                
     }
@@ -1901,11 +1876,11 @@ public class ReachGraph {
     if( writeDebugDOTs ) {    
       try {
         rg.writeGraph( "calleeview", 
-                       true,   // write labels (variables)                
-                       true,   // selectively hide intermediate temp vars 
-                       true,   // prune unreachable heap regions          
-                       true,   // hide subset reachability states         
-                       true ); // hide edge taints                        
+                       resolveMethodDebugDOTwriteLabels,    
+                       resolveMethodDebugDOTselectTemps,    
+                       resolveMethodDebugDOTpruneGarbage,   
+                       resolveMethodDebugDOThideSubsetReach,
+                       resolveMethodDebugDOThideEdgeTaints );
       } catch( IOException e ) {}
     }
 
@@ -1916,6 +1891,14 @@ public class ReachGraph {
     new Hashtable<String, Integer>();
 
 
+  // useful since many graphs writes in the method call debug code
+  private static boolean resolveMethodDebugDOTwriteLabels     = true;
+  private static boolean resolveMethodDebugDOTselectTemps     = true;
+  private static boolean resolveMethodDebugDOTpruneGarbage    = true;
+  private static boolean resolveMethodDebugDOThideSubsetReach = false;
+  private static boolean resolveMethodDebugDOThideEdgeTaints  = true;
+
+
 
   public void 
     resolveMethodCall( FlatCall     fc,        
@@ -1929,17 +1912,18 @@ public class ReachGraph {
     if( writeDebugDOTs ) {
       try {
         rgCallee.writeGraph( "callee", 
-                             true,   // write labels (variables)                  
-                             true,   // selectively hide intermediate temp vars   
-                             true,   // prune unreachable heap regions            
-                             true,   // hide subset reachability states           
-                             true ); // hide edge taints                        
-        writeGraph( "caller00In", 
-                    true,  // write labels (variables)                
-                    true,  // selectively hide intermediate temp vars 
-                    true,  // prune unreachable heap regions          
-                    true,  // hide subset reachability states         
-                    true,  // hide edge taints                        
+                       resolveMethodDebugDOTwriteLabels,    
+                       resolveMethodDebugDOTselectTemps,    
+                       resolveMethodDebugDOTpruneGarbage,   
+                       resolveMethodDebugDOThideSubsetReach,
+                       resolveMethodDebugDOThideEdgeTaints );
+
+        writeGraph( "caller00In",  
+                    resolveMethodDebugDOTwriteLabels,    
+                    resolveMethodDebugDOTselectTemps,    
+                    resolveMethodDebugDOTpruneGarbage,   
+                    resolveMethodDebugDOThideSubsetReach,
+                    resolveMethodDebugDOThideEdgeTaints,
                     callerNodeIDsCopiedToCallee );
       } catch( IOException e ) {}
     }
@@ -2104,9 +2088,7 @@ public class ReachGraph {
               calleeStatesSatisfied.put( stateCallee, predsIfSatis );
             } 
           }
-
         }        
-
       }
     }
 
@@ -2161,11 +2143,11 @@ public class ReachGraph {
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller20BeforeWipe", 
-                    true,   // write labels (variables)                
-                    true,   // selectively hide intermediate temp vars 
-                    true,   // prune unreachable heap regions          
-                    true,   // hide subset reachability states         
-                    true ); // hide edge taints                        
+                    resolveMethodDebugDOTwriteLabels,    
+                    resolveMethodDebugDOTselectTemps,    
+                    resolveMethodDebugDOTpruneGarbage,   
+                    resolveMethodDebugDOThideSubsetReach,
+                    resolveMethodDebugDOThideEdgeTaints );
       } catch( IOException e ) {}
     }
 
@@ -2187,11 +2169,11 @@ public class ReachGraph {
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller30BeforeAddingNodes", 
-                    true,   // write labels (variables)                
-                    true,   // selectively hide intermediate temp vars 
-                    true,   // prune unreachable heap regions          
-                    true,   // hide subset reachability states         
-                    true ); // hide edge taints                        
+                    resolveMethodDebugDOTwriteLabels,    
+                    resolveMethodDebugDOTselectTemps,    
+                    resolveMethodDebugDOTpruneGarbage,   
+                    resolveMethodDebugDOThideSubsetReach,
+                    resolveMethodDebugDOThideEdgeTaints );
       } catch( IOException e ) {}
     }
 
@@ -2256,11 +2238,11 @@ public class ReachGraph {
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller31BeforeAddingEdges", 
-                    true,   // write labels (variables)                
-                    true,   // selectively hide intermediate temp vars 
-                    true,   // prune unreachable heap regions          
-                    true,   // hide subset reachability states         
-                    true ); // hide edge taints                        
+                    resolveMethodDebugDOTwriteLabels,    
+                    resolveMethodDebugDOTselectTemps,    
+                    resolveMethodDebugDOTpruneGarbage,   
+                    resolveMethodDebugDOThideSubsetReach,
+                    resolveMethodDebugDOThideEdgeTaints );
       } catch( IOException e ) {}
     }
 
@@ -2384,30 +2366,31 @@ public class ReachGraph {
         ChangeSet cs = ChangeSet.factory();
         Iterator<ReachState> rsItr = reCaller.getBeta().iterator();
         while( rsItr.hasNext() ) {
-          ReachState   state = rsItr.next();
-          ExistPredSet preds2 = state.getPreds();
-          assert preds2.preds.size() == 1;
+          ReachState   state          = rsItr.next();
+          ExistPredSet predsPreCallee = state.getPreds();
 
           if( state.isEmpty() ) {
             continue;
           }
 
-          ExistPred pred = preds2.preds.iterator().next();
-          ReachState old = pred.ne_state;
+          Iterator<ExistPred> predItr = predsPreCallee.iterator();
+          while( predItr.hasNext() ) {            
+            ExistPred pred = predItr.next();
+            ReachState old = pred.ne_state;
 
-          if( old == null ) {
-            old = rstateEmpty;
-          }
-
-          assert old != null;
+            if( old == null ) {
+              old = rstateEmpty;
+            }
 
-          cs = Canonical.union( cs,
+            cs = Canonical.add( cs,
                                 ChangeTuple.factory( old,
                                                      state
                                                      )
                                 );
+          }
         }
         
+
         // look to see if an edge with same field exists
         // and merge with it, otherwise just add the edge
         RefEdge edgeExisting = rsnCaller.getReferenceTo( hrnDstCaller,
@@ -2416,7 +2399,7 @@ public class ReachGraph {
                                                          );    
         if( edgeExisting != null ) {
           edgeExisting.setBeta(
-                               Canonical.union( edgeExisting.getBeta(),
+                               Canonical.unionORpreds( edgeExisting.getBeta(),
                                                 reCaller.getBeta()
                                                 )
                                );
@@ -2456,11 +2439,11 @@ public class ReachGraph {
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller35BeforeAssignReturnValue", 
-                    true,   // write labels (variables)                
-                    true,   // selectively hide intermediate temp vars 
-                    true,   // prune unreachable heap regions          
-                    true,   // hide subset reachability states         
-                    true ); // hide edge taints                        
+                    resolveMethodDebugDOTwriteLabels,    
+                    resolveMethodDebugDOTselectTemps,    
+                    resolveMethodDebugDOTpruneGarbage,   
+                    resolveMethodDebugDOThideSubsetReach,
+                    resolveMethodDebugDOThideEdgeTaints );
       } catch( IOException e ) {}
     }
 
@@ -2542,11 +2525,11 @@ public class ReachGraph {
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller38propagateReach", 
-                    true,   // write labels (variables)                
-                    true,   // selectively hide intermediate temp vars 
-                    true,   // prune unreachable heap regions          
-                    true,   // hide subset reachability states         
-                    true ); // hide edge taints                        
+                    resolveMethodDebugDOTwriteLabels,    
+                    resolveMethodDebugDOTselectTemps,    
+                    resolveMethodDebugDOTpruneGarbage,   
+                    resolveMethodDebugDOThideSubsetReach,
+                    resolveMethodDebugDOThideEdgeTaints );
       } catch( IOException e ) {}
     }
 
@@ -2572,11 +2555,11 @@ public class ReachGraph {
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller40BeforeShadowMerge", 
-                    true,   // write labels (variables)                
-                    true,   // selectively hide intermediate temp vars 
-                    true,   // prune unreachable heap regions          
-                    true,   // hide subset reachability states         
-                    true ); // hide edge taints                        
+                    resolveMethodDebugDOTwriteLabels,    
+                    resolveMethodDebugDOTselectTemps,    
+                    resolveMethodDebugDOTpruneGarbage,   
+                    resolveMethodDebugDOThideSubsetReach,
+                    resolveMethodDebugDOThideEdgeTaints );
       } catch( IOException e ) {}
     }
     
@@ -2673,11 +2656,11 @@ public class ReachGraph {
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller45BeforeUnshadow", 
-                    true,   // write labels (variables)                
-                    true,   // selectively hide intermediate temp vars 
-                    true,   // prune unreachable heap regions          
-                    true,   // hide subset reachability states         
-                    true ); // hide edge taints                        
+                    resolveMethodDebugDOTwriteLabels,    
+                    resolveMethodDebugDOTselectTemps,    
+                    resolveMethodDebugDOTpruneGarbage,   
+                    resolveMethodDebugDOThideSubsetReach,
+                    resolveMethodDebugDOThideEdgeTaints );
       } catch( IOException e ) {}
     }
     
@@ -2701,11 +2684,11 @@ public class ReachGraph {
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller50BeforeGlobalSweep", 
-                    true,   // write labels (variables)                
-                    true,   // selectively hide intermediate temp vars 
-                    true,   // prune unreachable heap regions          
-                    true,   // hide subset reachability states         
-                    true ); // hide edge taints                        
+                    resolveMethodDebugDOTwriteLabels,    
+                    resolveMethodDebugDOTselectTemps,    
+                    resolveMethodDebugDOTpruneGarbage,   
+                    resolveMethodDebugDOThideSubsetReach,
+                    resolveMethodDebugDOThideEdgeTaints );
       } catch( IOException e ) {}
     }
 
@@ -2720,11 +2703,11 @@ public class ReachGraph {
     if( writeDebugDOTs ) {
       try {
         writeGraph( "caller90AfterTransfer", 
-                    true,   // write labels (variables)                
-                    true,   // selectively hide intermediate temp vars 
-                    true,   // prune unreachable heap regions          
-                    true,   // hide subset reachability states         
-                    true ); // hide edge taints                        
+                    resolveMethodDebugDOTwriteLabels,    
+                    resolveMethodDebugDOTselectTemps,    
+                    resolveMethodDebugDOTpruneGarbage,   
+                    resolveMethodDebugDOThideSubsetReach,
+                    resolveMethodDebugDOThideEdgeTaints );
       } catch( IOException e ) {}
     }
   } 
@@ -2984,20 +2967,22 @@ public class ReachGraph {
                                                             );
           
             if( prevResult == null || 
-                Canonical.union( prevResult,
-                                 intersection ).size() > prevResult.size() ) {
+                Canonical.unionORpreds( prevResult,
+                                        intersection ).size() 
+                > prevResult.size() 
+                ) {
             
               if( prevResult == null ) {
                 boldB_f.put( edgePrime, 
-                             Canonical.union( edgePrime.getBeta(),
-                                              intersection 
-                                              )
+                             Canonical.unionORpreds( edgePrime.getBeta(),
+                                                     intersection 
+                                                     )
                              );
               } else {
                 boldB_f.put( edgePrime, 
-                             Canonical.union( prevResult,
-                                              intersection 
-                                              )
+                             Canonical.unionORpreds( prevResult,
+                                                     intersection 
+                                                     )
                              );
               }
               workSetEdges.add( edgePrime );   
@@ -3081,7 +3066,8 @@ public class ReachGraph {
             if( B != null ) {            
               ReachSet boldB_rtOld_incident = B.get( incidentEdge );
               if( boldB_rtOld_incident != null &&
-                  boldB_rtOld_incident.contains( stateOld ) ) {
+                  boldB_rtOld_incident.containsIgnorePreds( stateOld ) != null
+                  ) {
                 foundState = true;
               }
             }
@@ -3094,9 +3080,9 @@ public class ReachGraph {
 
        // if there is nothing marked, just move on
        if( markedHrnIDs.isEmpty() ) {
-         hrn.setAlphaNew( Canonical.union( hrn.getAlphaNew(),
-                                            stateOld
-                                            )
+         hrn.setAlphaNew( Canonical.add( hrn.getAlphaNew(),
+                                          stateOld
+                                          )
                            );
          continue;
        }
@@ -3109,19 +3095,19 @@ public class ReachGraph {
          ReachTuple rtOld = rtItr.next();
 
          if( !markedHrnIDs.containsTuple( rtOld ) ) {
-           statePruned = Canonical.union( statePruned, rtOld );
+           statePruned = Canonical.add( statePruned, rtOld );
          }
        }
        assert !stateOld.equals( statePruned );
 
-       hrn.setAlphaNew( Canonical.union( hrn.getAlphaNew(),
-                                          statePruned
-                                          )
+       hrn.setAlphaNew( Canonical.add( hrn.getAlphaNew(),
+                                        statePruned
+                                        )
                          );
        ChangeTuple ct = ChangeTuple.factory( stateOld,
                                               statePruned
                                               );
-       cts = Canonical.union( cts, ct );
+       cts = Canonical.add( cts, ct );
       }
 
       // throw change tuple set on all incident edges
@@ -3164,7 +3150,16 @@ public class ReachGraph {
     Iterator<HeapRegionNode> nodeItr = id2hrn.values().iterator();
     while( nodeItr.hasNext() ) {
       HeapRegionNode hrn = nodeItr.next();
-      hrn.applyAlphaNew();
+
+      // as mentioned above, out-of-context nodes only serve
+      // as sources of reach states for the sweep, not part
+      // of the changes
+      if( hrn.isOutOfContext() ) {
+        assert hrn.getAlphaNew().equals( rsetEmpty );
+      } else {
+        hrn.applyAlphaNew();
+      }
+
       Iterator<RefEdge> itrRes = hrn.iteratorToReferencers();
       while( itrRes.hasNext() ) {
        res.add( itrRes.next() );
@@ -3214,13 +3209,16 @@ public class ReachGraph {
                                   edgePrime.getBetaNew() 
                                   );
                    
-       if( Canonical.union( prevResult,
-                             intersection
-                             ).size() > prevResult.size() ) {
+       if( Canonical.unionORpreds( prevResult,
+                                    intersection
+                                    ).size() 
+            > prevResult.size() 
+            ) {
+          
          edge.setBetaNew( 
-                          Canonical.union( prevResult,
-                                           intersection 
-                                           )
+                          Canonical.unionORpreds( prevResult,
+                                                  intersection 
+                                                  )
                            );
          edgeWorkSet.add( edge );
        }       
@@ -3293,7 +3291,7 @@ public class ReachGraph {
        // so make the new reachability set a union of the
        // nodes' reachability sets
        HeapRegionNode hrnB = id2hrn.get( idA );
-       hrnB.setAlpha( Canonical.union( hrnB.getAlpha(),
+       hrnB.setAlpha( Canonical.unionORpreds( hrnB.getAlpha(),
                                         hrnA.getAlpha() 
                                         )
                        );
@@ -3375,7 +3373,7 @@ public class ReachGraph {
          // just replace this beta set with the union
          assert edgeToMerge != null;
          edgeToMerge.setBeta(
-                              Canonical.union( edgeToMerge.getBeta(),
+                              Canonical.unionORpreds( edgeToMerge.getBeta(),
                                                edgeA.getBeta() 
                                                )
                               );
@@ -3439,7 +3437,7 @@ public class ReachGraph {
        // so merge their reachability sets
        else {
          // just replace this beta set with the union
-         edgeToMerge.setBeta( Canonical.union( edgeToMerge.getBeta(),
+         edgeToMerge.setBeta( Canonical.unionORpreds( edgeToMerge.getBeta(),
                                                 edgeA.getBeta()
                                                 )
                                );
@@ -4000,5 +3998,293 @@ public class ReachGraph {
                                callerNodeIDsCopiedToCallee );
     }
   }  
+  
+       public Set<HeapRegionNode> findCommonReachableNodes(HeapRegionNode hrn1,
+                       HeapRegionNode hrn2) {
+
+               Set<HeapRegionNode> reachableNodes1 = new HashSet<HeapRegionNode>();
+               Set<HeapRegionNode> reachableNodes2 = new HashSet<HeapRegionNode>();
+
+               Set<HeapRegionNode> todoNodes1 = new HashSet<HeapRegionNode>();
+               todoNodes1.add(hrn1);
+
+               Set<HeapRegionNode> todoNodes2 = new HashSet<HeapRegionNode>();
+               todoNodes2.add(hrn2);
+
+               // follow links until all reachable nodes have been found
+               while (!todoNodes1.isEmpty()) {
+                       HeapRegionNode hrn = todoNodes1.iterator().next();
+                       todoNodes1.remove(hrn);
+                       reachableNodes1.add(hrn);
+
+                       Iterator<RefEdge> edgeItr = hrn.iteratorToReferencees();
+                       while (edgeItr.hasNext()) {
+                               RefEdge edge = edgeItr.next();
+
+                               if (!reachableNodes1.contains(edge.getDst())) {
+                                       todoNodes1.add(edge.getDst());
+                               }
+                       }
+               }
+
+               while (!todoNodes2.isEmpty()) {
+                       HeapRegionNode hrn = todoNodes2.iterator().next();
+                       todoNodes2.remove(hrn);
+                       reachableNodes2.add(hrn);
+
+                       Iterator<RefEdge> edgeItr = hrn.iteratorToReferencees();
+                       while (edgeItr.hasNext()) {
+                               RefEdge edge = edgeItr.next();
+
+                               if (!reachableNodes2.contains(edge.getDst())) {
+                                       todoNodes2.add(edge.getDst());
+                               }
+                       }
+               }
+
+               Set<HeapRegionNode> intersection =
+                  new HashSet<HeapRegionNode>( reachableNodes1 );
+
+               intersection.retainAll( reachableNodes2 );
+
+               return intersection;
+       }
+        
+       public Set<HeapRegionNode> mayReachSharedObjects(HeapRegionNode hrn1,
+                       HeapRegionNode hrn2) {
+               assert hrn1 != null;
+               assert hrn2 != null;
+
+               // then get the various tokens for these heap regions
+               ReachTuple h1 = ReachTuple.factory(hrn1.getID(),
+                               !hrn1.isSingleObject(), ReachTuple.ARITY_ONE, false);
+
+               int arity;
+               if(hrn1.isSingleObject){
+                       arity=ReachTuple.ARITY_ONE;
+               }else{
+                       arity=ReachTuple.ARITY_ZEROORMORE;
+               }
+               ReachTuple h1star = ReachTuple.factory(hrn1.getID(), !hrn1
+                               .isSingleObject(), arity, false);
+
+               ReachTuple h2 = ReachTuple.factory(hrn2.getID(),
+                               !hrn2.isSingleObject(), ReachTuple.ARITY_ONE, false);
+
+               if(hrn2.isSingleObject){
+                       arity=ReachTuple.ARITY_ONE;
+               }else{
+                       arity=ReachTuple.ARITY_ZEROORMORE;
+               }
+               
+               ReachTuple h2star = ReachTuple.factory(hrn2.getID(), !hrn2
+                               .isSingleObject(), arity, false);
+
+               // then get the merged beta of all out-going edges from these heap
+               // regions
+
+               ReachSet beta1 = ReachSet.factory();
+               Iterator<RefEdge> itrEdge = hrn1.iteratorToReferencees();
+               while (itrEdge.hasNext()) {
+                       RefEdge edge = itrEdge.next();
+                       beta1 = Canonical.unionORpreds(beta1, edge.getBeta());
+               }
+
+               ReachSet beta2 = ReachSet.factory();
+               itrEdge = hrn2.iteratorToReferencees();
+               while (itrEdge.hasNext()) {
+                       RefEdge edge = itrEdge.next();
+                       beta2 = Canonical.unionORpreds(beta2, edge.getBeta());
+               }
+
+               boolean aliasDetected = false;
+
+               // only do this one if they are different tokens
+               if (h1 != h2 && beta1.containsStateWithBoth(h1, h2)) {
+                       aliasDetected = true;
+               }
+//             if (beta1.containsStateWithBoth(h1plus, h2)) {
+//                     aliasDetected = true;
+//             }
+               if (beta1.containsStateWithBoth(h1star, h2)) {
+                       aliasDetected = true;
+               }
+//             if (beta1.containsStateWithBoth(h1, h2plus)) {
+//                     aliasDetected = true;
+//             }
+//             if (beta1.containsStateWithBoth(h1plus, h2plus)) {
+//                     aliasDetected = true;
+//             }
+//             if (beta1.containsStateWithBoth(h1star, h2plus)) {
+//                     aliasDetected = true;
+//             }
+               if (beta1.containsStateWithBoth(h1, h2star)) {
+                       aliasDetected = true;
+               }
+//             if (beta1.containsStateWithBoth(h1plus, h2star)) {
+//                     aliasDetected = true;
+//             }
+               if (beta1.containsStateWithBoth(h1star, h2star)) {
+                       aliasDetected = true;
+               }
+
+               if (h1 != h2 && beta2.containsStateWithBoth(h1, h2)) {
+                       aliasDetected = true;
+               }
+//             if (beta2.containsStateWithBoth(h1plus, h2)) {
+//                     aliasDetected = true;
+//             }
+               if (beta2.containsStateWithBoth(h1star, h2)) {
+                       aliasDetected = true;
+               }
+//             if (beta2.containsStateWithBoth(h1, h2plus)) {
+//                     aliasDetected = true;
+//             }
+//             if (beta2.containsStateWithBoth(h1plus, h2plus)) {
+//                     aliasDetected = true;
+//             }
+//             if (beta2.containsStateWithBoth(h1star, h2plus)) {
+//                     aliasDetected = true;
+//             }
+               if (beta2.containsStateWithBoth(h1, h2star)) {
+                       aliasDetected = true;
+               }
+//             if (beta2.containsStateWithBoth(h1plus, h2star)) {
+//                     aliasDetected = true;
+//             }
+               if (beta2.containsStateWithBoth(h1star, h2star)) {
+                       aliasDetected = true;
+               }
+
+               Set<HeapRegionNode> common = new HashSet<HeapRegionNode>();
+               if (aliasDetected) {
+                       common = findCommonReachableNodes(hrn1, hrn2);
+                       if (!(DISABLE_STRONG_UPDATES || DISABLE_GLOBAL_SWEEP)) {
+                               assert !common.isEmpty();
+                       }
+               }
+
+               return common;
+       }
+
+       public Set<HeapRegionNode> mayReachSharedObjects(FlatMethod fm,
+                       Integer paramIndex1, Integer paramIndex2) {
+
+               // get parameter's heap regions
+               TempDescriptor paramTemp1 = fm.getParameter(paramIndex1.intValue());
+               VariableNode argVar1 = getVariableNodeFromTemp(paramTemp1);
+               RefEdge argEdge1 = argVar1.iteratorToReferencees().next();
+               HeapRegionNode hrnParam1 = argEdge1.getDst();
+
+               TempDescriptor paramTemp2 = fm.getParameter(paramIndex2.intValue());
+               VariableNode argVar2 = getVariableNodeFromTemp(paramTemp2);
+               RefEdge argEdge2 = argVar2.iteratorToReferencees().next();
+               HeapRegionNode hrnParam2 = argEdge2.getDst();
+
+               Set<HeapRegionNode> common = new HashSet<HeapRegionNode>();
+               common.addAll(mayReachSharedObjects(hrnParam1, hrnParam2));
+
+               return common;
+       }
+
+       public Set<HeapRegionNode> mayReachSharedObjects(FlatMethod fm,
+                       Integer paramIndex, AllocSite as) {
+
+               // get parameter's heap regions
+               TempDescriptor paramTemp = fm.getParameter(paramIndex.intValue());
+               VariableNode argVar = getVariableNodeFromTemp(paramTemp);
+               RefEdge argEdge = argVar.iteratorToReferencees().next();
+               HeapRegionNode hrnParam = argEdge.getDst();
 
+               // get summary node
+               HeapRegionNode hrnSummary=null;
+               if(id2hrn.containsKey(as.getSummary())){
+                       // if summary node doesn't exist, ignore this case
+                       hrnSummary = id2hrn.get(as.getSummary());
+                       assert hrnSummary != null;
+               }
+
+               Set<HeapRegionNode> common  = new HashSet<HeapRegionNode>();
+               if(hrnSummary!=null){
+                       common.addAll( mayReachSharedObjects(hrnParam, hrnSummary) );
+               }
+
+               // check for other nodes
+               for (int i = 0; i < as.getAllocationDepth(); ++i) {
+
+                       assert id2hrn.containsKey(as.getIthOldest(i));
+                       HeapRegionNode hrnIthOldest = id2hrn.get(as.getIthOldest(i));
+                       assert hrnIthOldest != null;
+
+                       common.addAll(mayReachSharedObjects(hrnParam, hrnIthOldest));
+
+               }
+
+               return common;
+       }
+
+       public Set<HeapRegionNode> mayReachSharedObjects(AllocSite as1,
+                       AllocSite as2) {
+
+               // get summary node 1's alpha
+               Integer idSum1 = as1.getSummary();
+               HeapRegionNode hrnSum1=null;
+               if(id2hrn.containsKey(idSum1)){
+                       hrnSum1 = id2hrn.get(idSum1);
+               }
+
+               // get summary node 2's alpha
+               Integer idSum2 = as2.getSummary();
+               HeapRegionNode hrnSum2=null;
+               if(id2hrn.containsKey(idSum2)){
+                       hrnSum2 = id2hrn.get(idSum2);
+               }
+               
+               Set<HeapRegionNode> common = new HashSet<HeapRegionNode>();
+               if(hrnSum1!=null && hrnSum2!=null){
+                       common.addAll(mayReachSharedObjects(hrnSum1, hrnSum2));
+               }
+
+               // check sum2 against alloc1 nodes
+               if(hrnSum2!=null){
+               for (int i = 0; i < as1.getAllocationDepth(); ++i) {
+                       Integer idI1 = as1.getIthOldest(i);
+                       assert id2hrn.containsKey(idI1);
+                       HeapRegionNode hrnI1 = id2hrn.get(idI1);
+                       assert hrnI1 != null;
+                       common.addAll(mayReachSharedObjects(hrnI1, hrnSum2));
+               }
+               }
+
+               // check sum1 against alloc2 nodes
+               for (int i = 0; i < as2.getAllocationDepth(); ++i) {
+                       Integer idI2 = as2.getIthOldest(i);
+                       assert id2hrn.containsKey(idI2);
+                       HeapRegionNode hrnI2 = id2hrn.get(idI2);
+                       assert hrnI2 != null;
+
+                       if(hrnSum1!=null){
+                               common.addAll(mayReachSharedObjects(hrnSum1, hrnI2));
+                       }
+
+                       // while we're at it, do an inner loop for alloc2 vs alloc1 nodes
+                       for (int j = 0; j < as1.getAllocationDepth(); ++j) {
+                               Integer idI1 = as1.getIthOldest(j);
+
+                               // if these are the same site, don't look for the same token, no
+                               // alias.
+                               // different tokens of the same site could alias together though
+                               if (idI1.equals(idI2)) {
+                                       continue;
+                               }
+
+                               HeapRegionNode hrnI1 = id2hrn.get(idI1);
+
+                               common.addAll(mayReachSharedObjects(hrnI1, hrnI2));
+                       }
+               }
+
+               return common;
+       }
+  
 }