omputation to determine set of aliased parameter indices was very conservative,
[IRC.git] / Robust / src / Analysis / OwnershipAnalysis / OwnershipGraph.java
index 6a7032418eb066c1f7f3c0515a33bbac960b0648..c61a9ea4c9797cf88de9c43952bd0aed757e8679 100644 (file)
@@ -7,8 +7,16 @@ import java.io.*;
 
 public class OwnershipGraph {
 
-  private int allocationDepth;
-  private TypeUtil typeUtil;
+  // use to disable improvements for comparison
+  protected static final boolean DISABLE_STRONG_UPDATES = false;
+  protected static final boolean DISABLE_GLOBAL_SWEEP   = false;
+
+  protected static int      allocationDepth   = -1;
+  protected static TypeUtil typeUtil          = null;
+  protected static boolean  debugCallMap      = false;
+  protected static int      debugCallMapCount = 0;
+  protected static String   debugCallee       = null;
+  protected static String   debugCaller       = null;
 
   // there was already one other very similar reason
   // for traversing heap nodes that is no longer needed
@@ -67,9 +75,7 @@ public class OwnershipGraph {
   public Hashtable<Integer, TokenTuple> paramIndex2paramTokenSecondaryStar;
 
 
-  public OwnershipGraph(int allocationDepth, TypeUtil typeUtil) {
-    this.allocationDepth = allocationDepth;
-    this.typeUtil        = typeUtil;
+  public OwnershipGraph() {
 
     id2hrn                    = new Hashtable<Integer,        HeapRegionNode>();
     td2ln                     = new Hashtable<TempDescriptor, LabelNode     >();
@@ -212,6 +218,11 @@ public class OwnershipGraph {
     assert edge == referencee.getReferenceFrom(referencer,
                                                type,
                                               field);
+       
+//    int oldTaint=edge.getTaintIdentifier();
+//    if(referencer instanceof HeapRegionNode){
+//     depropagateTaintIdentifier((HeapRegionNode)referencer,oldTaint,new HashSet<HeapRegionNode>());
+//    }
 
     referencer.removeReferencee(edge);
     referencee.removeReferencer(edge);
@@ -362,6 +373,9 @@ public class OwnershipGraph {
                                                    null,
                                                    false,
                                                    betaY.intersection(betaHrn) );
+         
+         int newTaintIdentifier=getTaintIdentifierFromHRN(hrnHrn);
+         edgeNew.setTaintIdentifier(newTaintIdentifier);
 
          addReferenceEdge(lnX, hrnHrn, edgeNew);
        }
@@ -394,8 +408,10 @@ public class OwnershipGraph {
              (hrnX.isSingleObject() && lnX.getNumReferencees() == 1)    // case 2
              )
          ) {
-       strongUpdate = true;
-       clearReferenceEdgesFrom( hrnX, f.getType(), f.getSymbol(), false );
+        if( !DISABLE_STRONG_UPDATES ) {
+          strongUpdate = true;
+          clearReferenceEdgesFrom( hrnX, f.getType(), f.getSymbol(), false );
+        }
       }
     }
     
@@ -484,15 +500,21 @@ public class OwnershipGraph {
          edgeExisting.setBeta(
                               edgeExisting.getBeta().union( edgeNew.getBeta() )
                              );
-         int newTaintIdentifier=getTaintIdentifierFromHRN(hrnY);
-         edgeExisting.tainedBy(newTaintIdentifier);
+         if((!hrnX.isParameter() && hrnY.isParameter()) || ( hrnX.isParameter() && hrnY.isParameter())){
+                 int newTaintIdentifier=getTaintIdentifierFromHRN(hrnY);
+                 edgeExisting.unionTaintIdentifier(newTaintIdentifier);
+         }
          // a new edge here cannot be reflexive, so existing will
          // always be also not reflexive anymore
          edgeExisting.setIsInitialParam( false );
        } else {
-               int newTaintIdentifier=getTaintIdentifierFromHRN(hrnY);
-               edgeNew.setTaintIdentifier(newTaintIdentifier);
-               propagateTaintIdentifier(hrnX,newTaintIdentifier,new HashSet<HeapRegionNode>());
+               
+               if((!hrnX.isParameter() && hrnY.isParameter()) || ( hrnX.isParameter() && hrnY.isParameter())){
+                       int newTaintIdentifier=getTaintIdentifierFromHRN(hrnY);
+                       edgeNew.setTaintIdentifier(newTaintIdentifier);
+               }
+               //currently, taint isn't propagated through the chain of refrences
+        //propagateTaintIdentifier(hrnX,newTaintIdentifier,new HashSet<HeapRegionNode>());
          addReferenceEdge( hrnX, hrnY, edgeNew );
        }
       }
@@ -500,8 +522,10 @@ public class OwnershipGraph {
 
     // if there was a strong update, make sure to improve
     // reachability with a global sweep
-    if( strongUpdate ) {      
-      globalSweep();
+    if( strongUpdate ) {    
+      if( !DISABLE_GLOBAL_SWEEP ) {
+        globalSweep();
+      }
     }
   }
 
@@ -688,7 +712,6 @@ public class OwnershipGraph {
                           null,            // match all fields
                           true,            // special param initial
                           betaSoup );      // reachability
-      edgeSecondaryReflexive.tainedBy(paramIndex);
       addReferenceEdge( hrnSecondary, hrnSecondary, edgeSecondaryReflexive );
 
       ReferenceEdge edgeSecondary2Primary =
@@ -698,7 +721,6 @@ public class OwnershipGraph {
                           null,            // match all fields
                           true,            // special param initial
                           betaSoup );      // reachability
-      edgeSecondary2Primary.tainedBy(paramIndex);
       addReferenceEdge( hrnSecondary, hrnPrimary, edgeSecondary2Primary );
 
       ReferenceEdge edgeFromLabelR =
@@ -723,7 +745,6 @@ public class OwnershipGraph {
                           fd.getSymbol(), // field
                           true,           // special param initial
                           betaSoup );     // reachability
-      edgePrimaryReflexive.tainedBy(paramIndex);
       addReferenceEdge( hrnPrimary, hrnPrimary, edgePrimaryReflexive );
     }
 
@@ -738,7 +759,6 @@ public class OwnershipGraph {
                           fd.getSymbol(), // field
                           true,           // special param initial
                           betaSoup );     // reachability      
-      edgePrimary2Secondary.tainedBy(paramIndex);
       addReferenceEdge( hrnPrimary, hrnSecondary, edgePrimary2Secondary );
     }
   }
@@ -872,7 +892,6 @@ public class OwnershipGraph {
                         null,            // match all fields
                         true,            // special param initial
                         betaSoup );      // reachability
-    edgeAliased2Primary.tainedBy(paramIndex);
     addReferenceEdge( hrnAliasBlob, hrnPrimary, edgeAliased2Primary );    
 
     ReferenceEdge edgeFromLabelR =
@@ -912,6 +931,24 @@ public class OwnershipGraph {
       LabelNode      lnParamI = getLabelNodeFromTemp( tdParamI );
 
       Integer        idPrimaryI =  paramIndex2idPrimary.get( i );
+
+      /*
+      if( idPrimaryI == null ) {
+       try { 
+         writeGraph( "debugalias", 
+                     true,  // write labels (variables)
+                     true,  // selectively hide intermediate temp vars
+                     true,  // prune unreachable heap regions
+                     false, // show back edges to confirm graph validity
+                     false, // show parameter indices (unmaintained!)
+                     true,  // hide subset reachability states
+                     true); // hide edge taints
+       } catch( Exception e ) {}
+       System.out.println( "FlatMethod="+fm+"\nalias set="+aliasedParamIndices+
+                           "\nindex bad="+i);
+      }
+      */
+
       assert         idPrimaryI != null;
       HeapRegionNode primaryI   =  id2hrn.get( idPrimaryI );
       assert         primaryI   != null;           
@@ -938,9 +975,20 @@ public class OwnershipGraph {
        // affect reachability
        TypeDescriptor typeDeref = typeI.dereference();
        
+
+
+       /////////////////////////////////////////////////////////////
+       // NOTE! For the KMeans benchmark a parameter of type float
+       // array, which has an immutable dereferenced type, is causing
+       // this assertion to fail.  I'm commenting it out for now which
+       // is safe, because it allows aliasing where no aliasing can occur,
+       // so it can only get a worse-but-not-wrong answer.  FIX!
+       /////////////////////////////////////////////////////////////
        // for this parameter to be aliased the following must be true
-       assert !typeDeref.isImmutable() || typeDeref.isArray();
+       //assert !typeDeref.isImmutable() || typeDeref.isArray();
+       
        
+
        primary2secondaryFields.add( 
          OwnershipAnalysis.getArrayField( typeDeref )
                                   );
@@ -991,7 +1039,6 @@ public class OwnershipGraph {
                             fd.getSymbol(), // field
                             true,           // special param initial
                             betaSoup );     // reachability      
-       edgePrimaryReflexive.tainedBy(new Integer(i));
        addReferenceEdge( primaryI, primaryI, edgePrimaryReflexive );
       }
 
@@ -1008,7 +1055,6 @@ public class OwnershipGraph {
                             fd.getSymbol(), // field
                             true,           // special param initial
                             betaSoup );     // reachability
-       edgePrimary2Secondary.tainedBy(new Integer(i));
        addReferenceEdge( primaryI, hrnAliasBlob, edgePrimary2Secondary );
 
        // ask whether these fields might match any of the other aliased
@@ -1043,7 +1089,6 @@ public class OwnershipGraph {
                                 fd.getSymbol(), // field
                                 true,           // special param initial
                                 betaSoupWJ );   // reachability
-           edgePrimaryI2PrimaryJ.tainedBy(new Integer(i));
            addReferenceEdge( primaryI, primaryJ, edgePrimaryI2PrimaryJ );
          }
        }       
@@ -1313,6 +1358,10 @@ public class OwnershipGraph {
       if( as.getType().isClass() ) {
        hasFlags = as.getType().getClassDesc().hasFlags();
       }
+      
+      if(as.getFlag()){
+         hasFlags=as.getFlag();
+      }
 
       hrnSummary = createNewHeapRegionNode(idSummary,    // id or null to generate a new one 
                                            false,       // single object?                       
@@ -1627,111 +1676,117 @@ public class OwnershipGraph {
 
 
   public Set<Integer> calculateAliasedParamSet( FlatCall fc,
-                                               boolean isStatic,
                                                FlatMethod fm ) {
+    // to decide if two parameters are aliased, look
+    // at the caller graph (this graph) and if these
+    // two conditions are met, they may be aliased:
+    // 1. The argument labels reference a shared node
+    // 2. The edges to that shared node have a common
+    //    reachability state.
+
+    Set<Integer> aliasedIndices = new HashSet<Integer>();
 
-    Hashtable<Integer, LabelNode> paramIndex2ln =
-      new Hashtable<Integer, LabelNode>();
 
-    Hashtable<Integer, HashSet<HeapRegionNode> > paramIndex2reachableCallerNodes =
-      new Hashtable<Integer, HashSet<HeapRegionNode> >();
+    //System.out.println("Aliases for "+fm+" at "+fc);
+
 
     for( int i = 0; i < fm.numParameters(); ++i ) {
-      Integer        paramIndex = new Integer( i );
-      TempDescriptor tdParam    = fm.getParameter( i );
-      TypeDescriptor typeParam  = tdParam.getType();
+      for( int j = 0; j < i; ++j ) {   
 
-      if( typeParam.isImmutable() && !typeParam.isArray() ) {
-       // don't bother with this primitive parameter, it
-       // cannot affect reachability
-       continue;
-      }
+       TempDescriptor argTemp_i  = fc.getArgMatchingParamIndex( fm, i );
+       LabelNode      argLabel_i = getLabelNodeFromTemp( argTemp_i );
 
-      // now depending on whether the callee is static or not
-      // we need to account for a "this" argument in order to
-      // find the matching argument in the caller context
-      TempDescriptor argTemp_i;
-      if( isStatic ) {
-       argTemp_i = fc.getArg(paramIndex);
-      } else {
-       if( paramIndex.equals(0) ) {
-         argTemp_i = fc.getThis();
-       } else {
-         argTemp_i = fc.getArg(paramIndex - 1);
-       }
-      }
+       TempDescriptor argTemp_j  = fc.getArgMatchingParamIndex( fm, j );
+       LabelNode      argLabel_j = getLabelNodeFromTemp( argTemp_j );
 
-      // in non-static methods there is a "this" pointer
-      // that should be taken into account
-      if( isStatic ) {
-       assert fc.numArgs()     == fm.numParameters();
-      } else {
-       assert fc.numArgs() + 1 == fm.numParameters();
-      }
+       /*
+       System.out.println("  "+argTemp_i.getType()+" "+argTemp_i+" and "+
+                          argTemp_j.getType()+" "+argTemp_j+" aliased?");
+       */
 
-      LabelNode argLabel_i = getLabelNodeFromTemp(argTemp_i);
-      paramIndex2ln.put(paramIndex, argLabel_i);
-    }
+       // first condition--do these arguments 
+       // reference any common nodes?
+       Iterator<ReferenceEdge> edgeItr;
 
-    Iterator lnArgItr = paramIndex2ln.entrySet().iterator();
-    while( lnArgItr.hasNext() ) {
-      Map.Entry me      = (Map.Entry)lnArgItr.next();
-      Integer index     = (Integer)   me.getKey();
-      LabelNode lnArg_i = (LabelNode) me.getValue();
+       Set<HeapRegionNode> hrnSetI = new HashSet<HeapRegionNode>();
+       edgeItr = argLabel_i.iteratorToReferencees();
+       while( edgeItr.hasNext() ) {
+         hrnSetI.add( edgeItr.next().getDst() );
+       }
 
-      HashSet<HeapRegionNode> reachableNodes = new HashSet<HeapRegionNode>();
-      HashSet<HeapRegionNode> todoNodes      = new HashSet<HeapRegionNode>();
+       Set<HeapRegionNode> hrnSetJ = new HashSet<HeapRegionNode>();
+       edgeItr = argLabel_j.iteratorToReferencees();
+       while( edgeItr.hasNext() ) {
+         hrnSetJ.add( edgeItr.next().getDst() );
+       }
 
-      // to find all reachable nodes, start with label referencees
-      Iterator<ReferenceEdge> edgeArgItr = lnArg_i.iteratorToReferencees();
-      while( edgeArgItr.hasNext() ) {
-       ReferenceEdge edge = edgeArgItr.next();
-       todoNodes.add( edge.getDst() );
-      }
+       Set<HeapRegionNode> intersection = 
+         new HashSet<HeapRegionNode>( hrnSetI );
+       intersection.retainAll( hrnSetJ );
 
-      // then follow links until all reachable nodes have been found
-      while( !todoNodes.isEmpty() ) {
-       HeapRegionNode hrn = todoNodes.iterator().next();
-       todoNodes.remove(hrn);
-       reachableNodes.add(hrn);
+       // condition two--for each shared node, do the reference
+       // edges to it from arguments have a common reachability
+       // state that is *ALSO* on the shared node?
+       boolean foundAlias = false;
 
-       Iterator<ReferenceEdge> edgeItr = hrn.iteratorToReferencees();
-       while( edgeItr.hasNext() ) {
-         ReferenceEdge edge = edgeItr.next();
+       Iterator<HeapRegionNode> hrnItr = intersection.iterator();
+       while( hrnItr.hasNext() ) {
+         HeapRegionNode hrn = hrnItr.next();
 
-         if( !reachableNodes.contains(edge.getDst() ) ) {
-           todoNodes.add(edge.getDst() );
-         }
-       }
-      }
+         ReferenceEdge ei = argLabel_i.getReferenceTo( hrn, 
+                                                       argTemp_i.getType(),
+                                                       null );
 
-      // save for later
-      paramIndex2reachableCallerNodes.put(index, reachableNodes);
-    }
+         ReferenceEdge ej = argLabel_j.getReferenceTo( hrn, 
+                                                       argTemp_j.getType(),
+                                                       null );
+         assert ei != null; 
+         assert ej != null;
 
-    Set<Integer> aliasedIndices = new HashSet<Integer>();
+         ReachabilitySet allStatesForParamI = 
+           ei.getBeta().intersection( hrn.getAlpha() );
 
-    // check for arguments that are aliased
-    for( int i = 0; i < fm.numParameters(); ++i ) {
-      for( int j = 0; j < i; ++j ) {   
-       HashSet<HeapRegionNode> s1 = paramIndex2reachableCallerNodes.get( i );
-       HashSet<HeapRegionNode> s2 = paramIndex2reachableCallerNodes.get( j );
+         ReachabilitySet allStatesForParamJ = 
+           ej.getBeta().intersection( hrn.getAlpha() );
 
-       // some parameters are immutable or primitive, so skip em
-       if( s1 == null || s2 == null ) {
-         continue;
-       }
+         ReachabilitySet commonStates = 
+           allStatesForParamI.intersection( allStatesForParamJ );
+
+         if( !commonStates.isEmpty() ) {
+           foundAlias = true;
+           aliasedIndices.add( new Integer( i ) );
+           aliasedIndices.add( new Integer( j ) );
 
-       Set<HeapRegionNode> intersection = new HashSet<HeapRegionNode>(s1);
-       intersection.retainAll(s2);
+           //System.out.println( "    yes!" );
+         }
+       }
 
-       if( !intersection.isEmpty() ) {
-         aliasedIndices.add( new Integer( i ) );
-         aliasedIndices.add( new Integer( j ) );
+       // as soon as we detect one possible way to alias
+       // these parameters, skip on to another pair
+       if( foundAlias ) {
+         continue;
        }
       }
     }
 
+    if( !aliasedIndices.isEmpty() ) {
+      try { 
+       writeGraph( "foundaliases", 
+                   true,  // write labels (variables)
+                   true,  // selectively hide intermediate temp vars
+                   true,  // prune unreachable heap regions
+                   false, // show back edges to confirm graph validity
+                   false, // show parameter indices (unmaintained!)
+                   true,  // hide subset reachability states
+                   true); // hide edge taints
+      } catch( Exception e ) {}
+      /*
+      System.out.println("FlatCall="+fc+
+                        "\nflat method="+fm+
+                        "\nAliases="+aliasedIndices );
+      */
+    }
+    
     return aliasedIndices;
   }
 
@@ -1861,23 +1916,29 @@ public class OwnershipGraph {
                                ParameterDecomposition pd // if this is not null, we're calling after analysis
                                ) {
 
-
-    // this debug snippet is harmless for regular use and INVALUABLE at debug time
-    // to see what potentially goes wrong when a specific method calls another
-    String debugCaller = "foo";
-    String debugCallee = "bar";
-    //String debugCaller = "StandardEngine";
-    //String debugCaller = "register_by_type";
-    //String debugCaller = "register_by_type_front";
-    //String debugCaller = "addFirst";
-    //String debugCallee = "LinkedListElement";
-
-    if( mc.getDescriptor().getSymbol().equals( debugCaller ) &&
-       fm.getMethod().getSymbol().equals( debugCallee ) ) {
+    if( debugCallMap &&
+       mc.getDescriptor().getSymbol().equals( debugCaller ) &&
+       fm.getMethod().getSymbol().equals( debugCallee ) 
+       ) {
 
       try {
-       writeGraph( "debug1BeforeCall", true, true, true, false, false );
-       ogCallee.writeGraph( "debug0Callee", true, true, true, false, false );
+       writeGraph("debug1BeforeCall",
+                     true,  // write labels (variables)
+                     true,  // selectively hide intermediate temp vars
+                     true,  // prune unreachable heap regions
+                     false, // show back edges to confirm graph validity
+                     false, // show parameter indices (unmaintained!)
+                     true,  // hide subset reachability states
+                     true); // hide edge taints
+
+       ogCallee.writeGraph("debug0Callee",
+                     true,  // write labels (variables)
+                     true,  // selectively hide intermediate temp vars
+                     true,  // prune unreachable heap regions
+                     false, // show back edges to confirm graph validity
+                     false, // show parameter indices (unmaintained!)
+                     true,  // hide subset reachability states
+                     true); // hide edge taints
       } catch( IOException e ) {}
 
       System.out.println( "  "+mc+" is calling "+fm );
@@ -2036,24 +2097,7 @@ public class OwnershipGraph {
       // now depending on whether the callee is static or not
       // we need to account for a "this" argument in order to
       // find the matching argument in the caller context
-      TempDescriptor argTemp_i;
-      if( isStatic ) {
-       argTemp_i = fc.getArg( paramIndex );
-      } else {
-       if( paramIndex.equals( 0 ) ) {
-         argTemp_i = fc.getThis();
-       } else {
-         argTemp_i = fc.getArg( paramIndex - 1 );
-       }
-      }
-
-      // in non-static methods there is a "this" pointer
-      // that should be taken into account
-      if( isStatic ) {
-       assert fc.numArgs()     == fm.numParameters();
-      } else {
-       assert fc.numArgs() + 1 == fm.numParameters();
-      }
+      TempDescriptor argTemp_i = fc.getArgMatchingParamIndex( fm, paramIndex );
 
       // remember which caller arg label maps to param index
       LabelNode argLabel_i = getLabelNodeFromTemp( argTemp_i );
@@ -2070,8 +2114,9 @@ public class OwnershipGraph {
          if( (hrn.getNumReferencers()                                == 1) || // case 1
              (hrn.isSingleObject() && argLabel_i.getNumReferencees() == 1)    // case 2                     
            ) {
-           
-           effectCalleeStrongUpdates( paramIndex, ogCallee, hrn );
+           if( !DISABLE_STRONG_UPDATES ) {
+              effectCalleeStrongUpdates( paramIndex, ogCallee, hrn );
+            }
          }
        }
       }
@@ -2211,7 +2256,6 @@ public class OwnershipGraph {
     Hashtable< Integer, Set<Vector> > edges_up_dr = new Hashtable< Integer, Set<Vector> >();
     Hashtable< Integer, Set<Vector> > edges_up_r  = new Hashtable< Integer, Set<Vector> >();
 
-
     // so again, with respect to some arg i...
     lnArgItr = paramIndex2ln.entrySet().iterator();
     while( lnArgItr.hasNext() ) {
@@ -2719,6 +2763,7 @@ public class OwnershipGraph {
     // in the caller graph
     Set      sCallee = ogCallee.id2hrn.entrySet();
     Iterator iCallee = sCallee.iterator();
+
     while( iCallee.hasNext() ) {
       Map.Entry      meCallee  = (Map.Entry)      iCallee.next();
       Integer        idCallee  = (Integer)        meCallee.getKey();
@@ -2808,7 +2853,25 @@ public class OwnershipGraph {
              // otherwise the caller src and dst pair can match the edge, so make it
              ReferenceEdge edgeNewInCaller = edgeNewInCallerTemplate.copy();
              edgeNewInCaller.setSrc( src );
-             edgeNewInCaller.setDst( dst );          
+             edgeNewInCaller.setDst( dst );         
+             
+             // handle taint info if callee created this edge
+             // added by eom
+             Set<Integer> pParamSet=idPrimary2paramIndexSet.get(dst.getID());
+             Set<Integer> sParamSet=idSecondary2paramIndexSet.get(dst.getID());
+             HashSet<Integer> paramSet=new  HashSet<Integer>();
+             if(pParamSet!=null){
+                 paramSet.addAll(pParamSet);  
+             }
+             if(sParamSet!=null){
+                 paramSet.addAll(sParamSet);  
+             }
+             Iterator<Integer> paramIter=paramSet.iterator();
+             int newTaintIdentifier=0;
+             while(paramIter.hasNext()){
+                 Integer paramIdx=paramIter.next();
+                 edgeNewInCaller.tainedBy(paramIdx);
+             }
 
              ReferenceEdge edgeExisting = src.getReferenceTo( dst, 
                                                               edgeNewInCaller.getType(),
@@ -2828,6 +2891,7 @@ public class OwnershipGraph {
     }
 
 
+
     // return value may need to be assigned in caller
     TempDescriptor returnTemp = fc.getReturnTemp();
     if( returnTemp != null && !returnTemp.getType().isImmutable() ) {
@@ -2901,13 +2965,24 @@ public class OwnershipGraph {
     }
 
 
-    if( mc.getDescriptor().getSymbol().equals( debugCaller ) &&
-       fm.getMethod().getSymbol().equals( debugCallee ) ) {
+    /*
+    if( debugCallMap &&
+       mc.getDescriptor().getSymbol().equals( debugCaller ) &&
+       fm.getMethod().getSymbol().equals( debugCallee ) 
+       ) {
+
       try {
-       writeGraph( "debug7JustBeforeMergeToKCapacity", true, true, true, false, false );
+       writeGraph("debug7JustBeforeMergeToKCapacity",
+                  true,  // write labels (variables)
+                  true,  // selectively hide intermediate temp vars
+                  true,  // prune unreachable heap regions
+                  false, // show back edges to confirm graph validity
+                  false, // show parameter indices (unmaintained!)
+                  true,  // hide subset reachability states
+                  true); // hide edge taints
       } catch( IOException e ) {}
     }
-
+    */
 
 
     // merge the shadow nodes of allocation sites back down to normal capacity
@@ -2977,28 +3052,51 @@ public class OwnershipGraph {
     }
 
 
-    if( mc.getDescriptor().getSymbol().equals( debugCaller ) &&
-       fm.getMethod().getSymbol().equals( debugCallee ) ) {
+    /*
+    if( debugCallMap &&
+       mc.getDescriptor().getSymbol().equals( debugCaller ) &&
+       fm.getMethod().getSymbol().equals( debugCallee ) 
+       ) {
+
       try {
-       writeGraph( "debug8JustBeforeSweep", true, true, true, false, false );
+       writeGraph( "debug8JustBeforeSweep",
+                   true,  // write labels (variables)
+                   true,  // selectively hide intermediate temp vars
+                   true,  // prune unreachable heap regions
+                   false, // show back edges to confirm graph validity
+                   false, // show parameter indices (unmaintained!)
+                   true,  // hide subset reachability states
+                   true); // hide edge taints
       } catch( IOException e ) {}
     }
+    */
 
 
     // improve reachability as much as possible
-    globalSweep();
-
+    if( !DISABLE_GLOBAL_SWEEP ) {
+      globalSweep();
+    }
 
 
-    if( mc.getDescriptor().getSymbol().equals( debugCaller ) &&
-       fm.getMethod().getSymbol().equals( debugCallee ) ) {
+    if( debugCallMap &&
+       mc.getDescriptor().getSymbol().equals( debugCaller ) &&
+       fm.getMethod().getSymbol().equals( debugCallee ) 
+       ) {
+      
       try {
-       writeGraph( "debug9endResolveCall", true, true, true, false, false );
+       writeGraph( "debug9endResolveCall",
+                   true,  // write labels (variables)
+                   true,  // selectively hide intermediate temp vars
+                   true,  // prune unreachable heap regions
+                   false, // show back edges to confirm graph validity
+                   false, // show parameter indices (unmaintained!)
+                   true,  // hide subset reachability states
+                   true); // hide edge taints
       } catch( IOException e ) {}
       System.out.println( "  "+mc+" done calling "+fm );      
       ++x;
-      if( x > 2 ) {
-       System.exit( -1 );   
+      if( x == debugCallMapCount ) {
+       System.exit( 0 );   
       }
     }
   }
@@ -3794,7 +3892,6 @@ public class OwnershipGraph {
          edgeToMerge.setBeta(
            edgeToMerge.getBeta().union(edgeA.getBeta() )
            );
-               //TODO eom
            edgeToMerge.unionTaintIdentifier(edgeA.getTaintIdentifier());
          if( !edgeA.isInitialParam() ) {
            edgeToMerge.setIsInitialParam(false);
@@ -4211,7 +4308,9 @@ public class OwnershipGraph {
     Set<HeapRegionNode> common = new HashSet<HeapRegionNode>();
     if( aliasDetected ) {
       common = findCommonReachableNodes( hrn1, hrn2 );
-      assert !common.isEmpty();
+      if( !(DISABLE_STRONG_UPDATES || DISABLE_GLOBAL_SWEEP) ) {
+        assert !common.isEmpty();
+      }
     }
 
     return common;    
@@ -4429,6 +4528,7 @@ public class OwnershipGraph {
   }
 
 
+  /*
   // for writing ownership graphs to dot files
   public void writeGraph(MethodContext mc,
                          FlatNode fn,
@@ -4466,6 +4566,25 @@ public class OwnershipGraph {
                );
   }
 
+  public void writeGraph(MethodContext mc,
+                         boolean writeLabels,
+                         boolean labelSelect,
+                         boolean pruneGarbage,
+                         boolean writeReferencers,
+                         boolean writeParamMappings,
+                         boolean hideSubsetReachability
+                         ) throws java.io.IOException {
+
+    writeGraph(mc+"COMPLETE",
+               writeLabels,
+               labelSelect,
+               pruneGarbage,
+               writeReferencers,
+               writeParamMappings,
+               hideSubsetReachability
+               );
+  }
+
   public void writeGraph(MethodContext mc,
                          Integer numUpdate,
                          boolean writeLabels,
@@ -4475,14 +4594,32 @@ public class OwnershipGraph {
                          boolean writeParamMappings
                          ) throws java.io.IOException {
 
+    writeGraph(mc+"COMPLETE"+String.format("%05d", numUpdate),
+               writeLabels,
+               labelSelect,
+               pruneGarbage,
+               writeReferencers,
+               writeParamMappings
+               );
+  }
 
+  public void writeGraph(MethodContext mc,
+                         Integer numUpdate,
+                         boolean writeLabels,
+                         boolean labelSelect,
+                         boolean pruneGarbage,
+                         boolean writeReferencers,
+                         boolean writeParamMappings,
+                         boolean hideSubsetReachability
+                         ) throws java.io.IOException {
 
     writeGraph(mc+"COMPLETE"+String.format("%05d", numUpdate),
                writeLabels,
                labelSelect,
                pruneGarbage,
                writeReferencers,
-               writeParamMappings
+               writeParamMappings,
+               hideSubsetReachability
                );
   }
 
@@ -4493,6 +4630,26 @@ public class OwnershipGraph {
                          boolean writeReferencers,
                          boolean writeParamMappings
                          ) throws java.io.IOException {
+    writeGraph(graphName,
+               writeLabels,
+               labelSelect,
+               pruneGarbage,
+               writeReferencers,
+               writeParamMappings,
+               false
+               );
+  }
+  */
+
+  public void writeGraph(String graphName,
+                         boolean writeLabels,
+                         boolean labelSelect,
+                         boolean pruneGarbage,
+                         boolean writeReferencers,
+                         boolean writeParamMappings,
+                         boolean hideSubsetReachability,
+                        boolean hideEdgeTaints
+                         ) throws java.io.IOException {
 
     // remove all non-word characters from the graph name so
     // the filename and identifier in dot don't cause errors
@@ -4521,7 +4678,9 @@ public class OwnershipGraph {
                                  bw,
                                  null,
                                  visited,
-                                 writeReferencers);
+                                 writeReferencers,
+                                  hideSubsetReachability,
+                                 hideEdgeTaints);
        }
       }
     }
@@ -4576,12 +4735,15 @@ public class OwnershipGraph {
                                    bw,
                                    null,
                                    visited,
-                                   writeReferencers);
+                                   writeReferencers,
+                                    hideSubsetReachability,
+                                   hideEdgeTaints);
          }
 
          bw.write("  "        + ln.toString() +
                   " -> "      + hrn.toString() +
-                  "[label=\"" + edge.toGraphEdgeString() +
+                  "[label=\"" + edge.toGraphEdgeString(hideSubsetReachability,
+                                                       hideEdgeTaints) +
                   "\",decorate];\n");
        }
       }
@@ -4597,7 +4759,9 @@ public class OwnershipGraph {
                                          BufferedWriter bw,
                                          TempDescriptor td,
                                          HashSet<HeapRegionNode> visited,
-                                         boolean writeReferencers
+                                         boolean writeReferencers,
+                                         boolean hideSubsetReachability,
+                                        boolean hideEdgeTaints
                                          ) throws java.io.IOException {
 
     if( visited.contains(hrn) ) {
@@ -4630,7 +4794,7 @@ public class OwnershipGraph {
        
       attributes += hrn.getDescription() +
                    "\\n"                +
-                    hrn.getAlphaString() +
+                    hrn.getAlphaString(hideSubsetReachability) +
                     "\"]";
 
       bw.write("  " + hrn.toString() + attributes + ";\n");
@@ -4667,7 +4831,8 @@ public class OwnershipGraph {
       case VISIT_HRN_WRITE_FULL:
        bw.write("  "        + hrn.toString() +
                 " -> "      + hrnChild.toString() +
-                "[label=\"" + edge.toGraphEdgeString() +
+                "[label=\"" + edge.toGraphEdgeString(hideSubsetReachability,
+                                                     hideEdgeTaints) +
                 "\",decorate];\n");
        break;
       }
@@ -4677,7 +4842,9 @@ public class OwnershipGraph {
                               bw,
                               td,
                               visited,
-                              writeReferencers);
+                              writeReferencers,
+                              hideSubsetReachability,
+                             hideEdgeTaints);
     }
   }
   
@@ -4716,4 +4883,25 @@ public class OwnershipGraph {
          
   }
   
+  public void depropagateTaintIdentifier(HeapRegionNode hrn, int newTaintIdentifier, HashSet<HeapRegionNode> visitedSet){
+         
+         HashSet<ReferenceEdge> setEdge=hrn.referencers;
+         Iterator<ReferenceEdge> iter=setEdge.iterator();
+         while(iter.hasNext()){
+                 ReferenceEdge edge= iter.next();
+                 edge.minusTaintIdentifier(newTaintIdentifier);                  
+                 if(edge.getSrc() instanceof HeapRegionNode){
+                         
+                         HeapRegionNode refHRN=(HeapRegionNode)edge.getSrc();
+                         //check whether it is reflexive edge
+                         if(!refHRN.equals(hrn) && !visitedSet.contains(refHRN)){
+                                 visitedSet.add(refHRN);
+                                 depropagateTaintIdentifier((HeapRegionNode)edge.getSrc(),newTaintIdentifier,visitedSet);
+                         }
+                        
+                 }
+         }       
+         
+  }
+  
 }