changes to be tainted only if the method or its callees created new edge.
[IRC.git] / Robust / src / Analysis / OwnershipAnalysis / OwnershipGraph.java
index 41300f8df031da7220f5fd772fd94fe5a560f56c..5b7dc3cf8c1b1edf696114e9263d4c836f16ec1f 100644 (file)
@@ -212,6 +212,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);
@@ -231,8 +236,7 @@ public class OwnershipGraph {
       ReferenceEdge edge = i.next();
 
       if( removeAll                                          || 
-         (type  != null && edge.getType() .equals( type  )) ||
-         (field != null && edge.getField().equals( field ))   
+         (edge.typeEquals( type ) && edge.fieldEquals( field ))
         ){
 
        HeapRegionNode referencee = edge.getDst();
@@ -259,8 +263,7 @@ public class OwnershipGraph {
       ReferenceEdge edge = i.next();
 
       if( removeAll                                          || 
-         (type  != null && edge.getType() .equals( type  )) ||
-         (field != null && edge.getField().equals( field ))   
+         (edge.typeEquals( type ) && edge.fieldEquals( field ))
         ){
 
        OwnershipNode referencer = edge.getSrc();
@@ -343,18 +346,20 @@ public class OwnershipGraph {
 
     Iterator<ReferenceEdge> itrYhrn = lnY.iteratorToReferencees();
     while( itrYhrn.hasNext() ) {
-      ReferenceEdge edgeY = itrYhrn.next();
-      HeapRegionNode hrnY  = edgeY.getDst();
+      ReferenceEdge   edgeY = itrYhrn.next();
+      HeapRegionNode  hrnY  = edgeY.getDst();
       ReachabilitySet betaY = edgeY.getBeta();
 
       Iterator<ReferenceEdge> itrHrnFhrn = hrnY.iteratorToReferencees();
       while( itrHrnFhrn.hasNext() ) {
-       ReferenceEdge edgeHrn = itrHrnFhrn.next();
-       HeapRegionNode hrnHrn  = edgeHrn.getDst();
+       ReferenceEdge   edgeHrn = itrHrnFhrn.next();
+       HeapRegionNode  hrnHrn  = edgeHrn.getDst();
        ReachabilitySet betaHrn = edgeHrn.getBeta();
 
-       if( edgeHrn.getType() == null ||
-           edgeHrn.getType().equals( f.getType() ) ) {
+       if( edgeHrn.getType() == null ||            
+           (edgeHrn.getType() .equals( f.getType()   ) &&
+            edgeHrn.getField().equals( f.getSymbol() )    )
+         ) {
 
          ReferenceEdge edgeNew = new ReferenceEdge(lnX,
                                                    hrnHrn,
@@ -362,6 +367,9 @@ public class OwnershipGraph {
                                                    null,
                                                    false,
                                                    betaY.intersection(betaHrn) );
+         
+         int newTaintIdentifier=getTaintIdentifierFromHRN(hrnHrn);
+         edgeNew.setTaintIdentifier(newTaintIdentifier);
 
          addReferenceEdge(lnX, hrnHrn, edgeNew);
        }
@@ -379,7 +387,6 @@ public class OwnershipGraph {
     HashSet<HeapRegionNode> nodesWithNewAlpha = new HashSet<HeapRegionNode>();
     HashSet<ReferenceEdge>  edgesWithNewBeta  = new HashSet<ReferenceEdge>();
 
-
     // first look for possible strong updates and remove those edges
     boolean strongUpdate = false;
 
@@ -388,21 +395,15 @@ public class OwnershipGraph {
       ReferenceEdge edgeX = itrXhrn.next();
       HeapRegionNode hrnX = edgeX.getDst();
 
-      Iterator<ReferenceEdge> itrYhrn = lnY.iteratorToReferencees();
-      while( itrYhrn.hasNext() ) {
-       ReferenceEdge edgeY = itrYhrn.next();
-       HeapRegionNode hrnY = edgeY.getDst();
-
-       // we can do a strong update here if one of two cases holds     
-       if( f != null &&
-           hrnX.isSingleObject() &&
-           (   (hrnX.getNumReferencers() == 1) ||
-               ( lnX.getNumReferencees() == 1)
-           )
+      // we can do a strong update here if one of two cases holds      
+      if( f != null &&
+         f != OwnershipAnalysis.getArrayField( f.getType() ) &&            
+         (   (hrnX.getNumReferencers()                         == 1) || // case 1
+             (hrnX.isSingleObject() && lnX.getNumReferencees() == 1)    // case 2
+             )
          ) {
-         strongUpdate = true;
-         clearReferenceEdgesFrom( hrnX, f.getType(), f.getSymbol(), false );
-       }
+       strongUpdate = true;
+       clearReferenceEdgesFrom( hrnX, f.getType(), f.getSymbol(), false );
       }
     }
     
@@ -430,8 +431,6 @@ public class OwnershipGraph {
 
        // then propagate back just up the edges from hrn
        ChangeTupleSet Cx = R.unionUpArityToChangeSet(O);
-
-
        HashSet<ReferenceEdge> todoEdges = new HashSet<ReferenceEdge>();
 
        Hashtable<ReferenceEdge, ChangeTupleSet> edgePlannedChanges =
@@ -462,6 +461,7 @@ public class OwnershipGraph {
       edgeItr.next().applyBetaNew();
     }
 
+
     // then go back through and add the new edges
     itrXhrn = lnX.iteratorToReferencees();
     while( itrXhrn.hasNext() ) {
@@ -492,10 +492,21 @@ public class OwnershipGraph {
          edgeExisting.setBeta(
                               edgeExisting.getBeta().union( edgeNew.getBeta() )
                              );
+         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 {
+               
+               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 );
        }
       }
@@ -509,6 +520,8 @@ public class OwnershipGraph {
   }
 
 
+
+
   // the parameter model is to use a single-object heap region
   // for the primary parameter, and a multiple-object heap
   // region for the secondary objects reachable through the
@@ -540,6 +553,16 @@ public class OwnershipGraph {
          OwnershipAnalysis.getArrayField( typeDeref )
                                   );
        createSecondaryRegion = true;
+
+       // also handle a special case where an array of objects
+       // can point back to the array, which is an object!
+       if( typeParam.toPrettyString().equals( "Object[]" ) &&
+           typeDeref.toPrettyString().equals( "Object" ) ) {
+
+         primary2primaryFields.add( 
+           OwnershipAnalysis.getArrayField( typeDeref )
+                                  );
+       }
       }
     }
 
@@ -562,7 +585,7 @@ public class OwnershipGraph {
          
          if( typeUtil.isSuperorType( typeField, typeParam ) ) {
            primary2primaryFields.add( fd );
-         }     
+         }
        }
 
        cd = cd.getSuperDesc();
@@ -598,9 +621,10 @@ public class OwnershipGraph {
     idPrimary2paramIndexSet.put( newPrimaryID, s );
     paramIndex2idPrimary.put( paramIndex, newPrimaryID );
 
+    
     TokenTuple ttPrimary = new TokenTuple( newPrimaryID,
                                           false, // multi-object
-                                          TokenTuple.ARITY_ONE ).makeCanonical();
+                                          TokenTuple.ARITY_ONE ).makeCanonical();    
         
     HeapRegionNode hrnSecondary   = null;
     Integer        newSecondaryID = null;
@@ -630,9 +654,10 @@ public class OwnershipGraph {
       idSecondary2paramIndexSet.put( newSecondaryID, s2 );
       paramIndex2idSecondary.put( paramIndex, newSecondaryID );
             
+      
       ttSecondary = new TokenTuple( newSecondaryID,
                                    true, // multi-object
-                                   TokenTuple.ARITY_ONE ).makeCanonical();
+                                   TokenTuple.ARITY_ONE ).makeCanonical();      
     }
 
     // use a beta that has everything and put it all over the
@@ -642,10 +667,10 @@ public class OwnershipGraph {
     ReachabilitySet betaSoup;
     if( createSecondaryRegion ) {
       TokenTupleSet tts1 = new TokenTupleSet( ttSecondary ).makeCanonical();
-      TokenTupleSet tts2 = new TokenTupleSet( ttPrimary   ).union( ttSecondary );   
-      betaSoup = new ReachabilitySet().union( tts0 ).union( tts1 ).union( tts2 );
+      TokenTupleSet tts2 = new TokenTupleSet( ttPrimary   ).makeCanonical().union( ttSecondary );   
+      betaSoup = ReachabilitySet.factory( tts0 ).union( tts1 ).union( tts2 );
     } else {
-      betaSoup = new ReachabilitySet().union( tts0 );
+      betaSoup = ReachabilitySet.factory( tts0 );
     }
 
     ReferenceEdge edgeFromLabel =
@@ -655,6 +680,7 @@ public class OwnershipGraph {
                         null,               // field
                         false,              // special param initial (not needed on label->node)
                         betaSoup );         // reachability
+    edgeFromLabel.tainedBy(paramIndex);
     addReferenceEdge( lnParam, hrnPrimary, edgeFromLabel );
 
     ReferenceEdge edgeFromLabelQ =
@@ -664,6 +690,7 @@ public class OwnershipGraph {
                         null,               // field
                         false,              // special param initial (not needed on label->node)
                         betaSoup );         // reachability
+    edgeFromLabelQ.tainedBy(paramIndex);
     addReferenceEdge( lnParamQ, hrnPrimary, edgeFromLabelQ );
     
     ReferenceEdge edgeSecondaryReflexive;
@@ -693,6 +720,7 @@ public class OwnershipGraph {
                           null,               // field
                           false,              // special param initial (not needed on label->node)
                           betaSoup );         // reachability
+      edgeFromLabelR.tainedBy(paramIndex);
       addReferenceEdge( lnParamR, hrnSecondary, edgeFromLabelR );
     }
     
@@ -706,7 +734,7 @@ public class OwnershipGraph {
                           fd.getType(),   // type
                           fd.getSymbol(), // field
                           true,           // special param initial
-                          betaSoup );     // reachability      
+                          betaSoup );     // reachability
       addReferenceEdge( hrnPrimary, hrnPrimary, edgePrimaryReflexive );
     }
 
@@ -739,17 +767,18 @@ public class OwnershipGraph {
                                                  null,  // reachability set                 
                                                  "aliasedParams" );
 
+    
     ReachabilitySet beta = new ReachabilitySet( new TokenTuple( hrn.getID(),
                                                                true,
                                                                TokenTuple.ARITY_ONE).makeCanonical()
                                                ).makeCanonical();
-    
+        
     ReferenceEdge edgeFromLabel =
       new ReferenceEdge( lnBlob, hrn, null, null, false, beta );
 
     ReferenceEdge edgeReflexive =
       new ReferenceEdge( hrn,    hrn, null, null, true,  beta );
-
+    
     addReferenceEdge( lnBlob, hrn, edgeFromLabel );
     addReferenceEdge( hrn,    hrn, edgeReflexive );
   }
@@ -782,9 +811,11 @@ public class OwnershipGraph {
     HeapRegionNode hrnAliasBlob = lnAliased.iteratorToReferencees().next().getDst();
     Integer idAliased = hrnAliasBlob.getID();
 
+    
     TokenTuple ttAliased = new TokenTuple( idAliased,
                                           true, // multi-object
-                                          TokenTuple.ARITY_ONE ).makeCanonical();     
+                                          TokenTuple.ARITY_ONE ).makeCanonical();         
+
 
     HeapRegionNode hrnPrimary = createNewHeapRegionNode( null,      // id or null to generate a new one 
                                                         true,      // single object?                    
@@ -812,14 +843,16 @@ public class OwnershipGraph {
     paramIndex2idSecondary.put( paramIndex, idAliased );
     
 
+    
     TokenTuple ttPrimary = new TokenTuple( newPrimaryID,
                                           false, // multi-object
-                                          TokenTuple.ARITY_ONE ).makeCanonical();
+                                          TokenTuple.ARITY_ONE ).makeCanonical();   
+
     
     TokenTupleSet tts0 = new TokenTupleSet( ttPrimary ).makeCanonical();
     TokenTupleSet tts1 = new TokenTupleSet( ttAliased ).makeCanonical();
-    TokenTupleSet tts2 = new TokenTupleSet( ttPrimary ).union( ttAliased );   
-    ReachabilitySet betaSoup = new ReachabilitySet().union( tts0 ).union( tts1 ).union( tts2 );
+    TokenTupleSet tts2 = new TokenTupleSet( ttPrimary ).makeCanonical().union( ttAliased );   
+    ReachabilitySet betaSoup = ReachabilitySet.factory( tts0 ).union( tts1 ).union( tts2 );
 
 
     ReferenceEdge edgeFromLabel =
@@ -829,6 +862,7 @@ public class OwnershipGraph {
                         null,               // field
                         false,              // special param initial (not needed on label->node)
                         betaSoup );         // reachability
+    edgeFromLabel.tainedBy(paramIndex);
     addReferenceEdge( lnParam, hrnPrimary, edgeFromLabel );
 
     ReferenceEdge edgeFromLabelQ =
@@ -838,6 +872,7 @@ public class OwnershipGraph {
                         null,               // field
                         false,              // special param initial (not needed on label->node)
                         betaSoup );         // reachability
+    edgeFromLabelQ.tainedBy(paramIndex);
     addReferenceEdge( lnParamQ, hrnPrimary, edgeFromLabelQ );
     
     ReferenceEdge edgeAliased2Primary =
@@ -856,6 +891,7 @@ public class OwnershipGraph {
                         null,               // field
                         false,              // special param initial (not needed on label->node)
                         betaSoup );         // reachability
+    edgeFromLabelR.tainedBy(paramIndex);
     addReferenceEdge( lnParamR, hrnAliasBlob, edgeFromLabelR );
   }
 
@@ -870,9 +906,11 @@ public class OwnershipGraph {
     assert lnAliased.getNumReferencees() == 1;
     HeapRegionNode hrnAliasBlob = lnAliased.iteratorToReferencees().next().getDst();
     Integer idAliased = hrnAliasBlob.getID();
+
+   
     TokenTuple ttAliased = new TokenTuple( idAliased,
                                           true, // multi-object
-                                          TokenTuple.ARITY_ONE ).makeCanonical();     
+                                          TokenTuple.ARITY_ONE ).makeCanonical();
 
 
     Iterator<Integer> apItrI = aliasedParamIndices.iterator();
@@ -882,28 +920,19 @@ public class OwnershipGraph {
       TypeDescriptor typeI    = tdParamI.getType();
       LabelNode      lnParamI = getLabelNodeFromTemp( tdParamI );
 
-      Integer idPrimaryI = paramIndex2idPrimary.get( i );
-      assert idPrimaryI != null;
-      HeapRegionNode primaryI = id2hrn.get( idPrimaryI );
-
-
-      System.out.println( "  **idPrimaryI="+idPrimaryI );
-      try {
-         writeGraph( "paramProblem", true, true, true, false, false );
-      } catch( IOException e ) {}
-
-
-
-      assert primaryI != null;           
-
+      Integer        idPrimaryI =  paramIndex2idPrimary.get( i );
+      assert         idPrimaryI != null;
+      HeapRegionNode primaryI   =  id2hrn.get( idPrimaryI );
+      assert         primaryI   != null;           
+      
       TokenTuple ttPrimaryI = new TokenTuple( idPrimaryI,
                                              false, // multi-object
                                              TokenTuple.ARITY_ONE ).makeCanonical();
       
       TokenTupleSet ttsI  = new TokenTupleSet( ttPrimaryI ).makeCanonical();
       TokenTupleSet ttsA  = new TokenTupleSet( ttAliased  ).makeCanonical();
-      TokenTupleSet ttsIA = new TokenTupleSet( ttPrimaryI ).union( ttAliased );   
-      ReachabilitySet betaSoup = new ReachabilitySet().union( ttsI ).union( ttsA ).union( ttsIA );
+      TokenTupleSet ttsIA = new TokenTupleSet( ttPrimaryI ).makeCanonical().union( ttAliased );   
+      ReachabilitySet betaSoup = ReachabilitySet.factory( ttsI ).union( ttsA ).union( ttsIA );
 
 
       // calculate whether fields of this aliased parameter are able to
@@ -924,6 +953,15 @@ public class OwnershipGraph {
        primary2secondaryFields.add( 
          OwnershipAnalysis.getArrayField( typeDeref )
                                   );
+
+       // also handle a special case where an array of objects
+       // can point back to the array, which is an object!
+       if( typeI    .toPrettyString().equals( "Object[]" ) &&
+           typeDeref.toPrettyString().equals( "Object" ) ) {
+         primary2primaryFields.add( 
+           OwnershipAnalysis.getArrayField( typeDeref )
+                                  );
+       }
       }
       
       // there might be member references for class types
@@ -1003,7 +1041,7 @@ public class OwnershipGraph {
            TokenTupleSet ttsIJ  = ttsI.union( ttsJ );
            TokenTupleSet ttsAJ  = ttsA.union( ttsJ );
            TokenTupleSet ttsIAJ = ttsIA.union( ttsJ );
-           ReachabilitySet betaSoupWJ = new ReachabilitySet().union( ttsJ ).union( ttsIJ ).union( ttsAJ ).union( ttsIAJ );
+           ReachabilitySet betaSoupWJ = ReachabilitySet.factory( ttsJ ).union( ttsIJ ).union( ttsAJ ).union( ttsIAJ );
 
            ReferenceEdge edgePrimaryI2PrimaryJ =
              new ReferenceEdge( primaryI,       // src
@@ -1042,6 +1080,7 @@ public class OwnershipGraph {
          ReferenceEdge lnI2PrimaryJ = lnJ2PrimaryJ.copy();
          lnI2PrimaryJ.setSrc( lnParamI );
          lnI2PrimaryJ.setType( tdParamI.getType() );
+         lnI2PrimaryJ.tainedBy(new Integer(j));
          addReferenceEdge( lnParamI, primaryJ, lnI2PrimaryJ );
        }
       }
@@ -1133,25 +1172,31 @@ public class OwnershipGraph {
     assert x  != null;
     assert as != null;
 
-    age(as);
+    age( as );
 
     // after the age operation the newest (or zero-ith oldest)
     // node associated with the allocation site should have
     // no references to it as if it were a newly allocated
-    // heap region, so make a reference to it to complete
-    // this operation
-
-    Integer idNewest  = as.getIthOldest(0);
-    HeapRegionNode hrnNewest = id2hrn.get(idNewest);
-    assert hrnNewest != null;
-
-    LabelNode lnX = getLabelNodeFromTemp(x);
-    clearReferenceEdgesFrom(lnX, null, null, true);
-
-    ReferenceEdge edgeNew =
-      new ReferenceEdge(lnX, hrnNewest, null, null, false, hrnNewest.getAlpha() );
-
-    addReferenceEdge(lnX, hrnNewest, edgeNew);
+    // heap region
+    Integer        idNewest   = as.getIthOldest( 0 );
+    HeapRegionNode hrnNewest  = id2hrn.get( idNewest );
+    assert         hrnNewest != null;
+
+    LabelNode lnX = getLabelNodeFromTemp( x );
+    clearReferenceEdgesFrom( lnX, null, null, true );
+
+    // make a new reference to allocated node
+    TypeDescriptor type    = as.getType();
+    ReferenceEdge  edgeNew =
+      new ReferenceEdge( lnX,                  // source
+                        hrnNewest,            // dest
+                        type,                 // type
+                        null,                 // field name
+                        false,                // is initial param
+                        hrnNewest.getAlpha()  // beta
+                        );
+
+    addReferenceEdge( lnX, hrnNewest, edgeNew );
   }
 
 
@@ -1517,7 +1562,7 @@ public class OwnershipGraph {
       HeapRegionNode n  = (HeapRegionNode) me.getKey();
       ChangeTupleSet C  = (ChangeTupleSet) me.getValue();
 
-      n.setAlphaNew( n.getAlpha().applyChangeSet( C, false ) );
+      n.setAlphaNew( n.getAlpha().applyChangeSet( C, true ) );
       nodesWithNewAlpha.add( n );
     }
 
@@ -1543,7 +1588,6 @@ public class OwnershipGraph {
 
       ChangeTupleSet changesToPass = new ChangeTupleSet().makeCanonical();
 
-
       Iterator<ChangeTuple> itrC = C.iterator();
       while( itrC.hasNext() ) {
        ChangeTuple c = itrC.next();
@@ -1582,15 +1626,15 @@ public class OwnershipGraph {
       ReferenceEdge  e  = (ReferenceEdge)  me.getKey();
       ChangeTupleSet C  = (ChangeTupleSet) me.getValue();
 
-      e.setBetaNew( e.getBeta().applyChangeSet( C, true ) );
+      e.setBetaNew( e.getBetaNew().union( e.getBeta().applyChangeSet( C, true ) ) );
       edgesWithNewBeta.add( e );
     }
   }
 
 
-  public Set<Integer> calculateAliasedParamSet(FlatCall fc,
-                                              boolean isStatic,
-                                              FlatMethod fm) {
+  public Set<Integer> calculateAliasedParamSet( FlatCall fc,
+                                               boolean isStatic,
+                                               FlatMethod fm ) {
 
     Hashtable<Integer, LabelNode> paramIndex2ln =
       new Hashtable<Integer, LabelNode>();
@@ -1599,7 +1643,15 @@ public class OwnershipGraph {
       new Hashtable<Integer, HashSet<HeapRegionNode> >();
 
     for( int i = 0; i < fm.numParameters(); ++i ) {
-      Integer paramIndex = new Integer(i);
+      Integer        paramIndex = new Integer( i );
+      TempDescriptor tdParam    = fm.getParameter( i );
+      TypeDescriptor typeParam  = tdParam.getType();
+
+      if( typeParam.isImmutable() && !typeParam.isArray() ) {
+       // don't bother with this primitive parameter, it
+       // cannot affect reachability
+       continue;
+      }
 
       // now depending on whether the callee is static or not
       // we need to account for a "this" argument in order to
@@ -1630,18 +1682,17 @@ public class OwnershipGraph {
     Iterator lnArgItr = paramIndex2ln.entrySet().iterator();
     while( lnArgItr.hasNext() ) {
       Map.Entry me      = (Map.Entry)lnArgItr.next();
-      Integer index   = (Integer)   me.getKey();
+      Integer index     = (Integer)   me.getKey();
       LabelNode lnArg_i = (LabelNode) me.getValue();
 
-      // rewrite alpha for the nodes reachable from argument label i
       HashSet<HeapRegionNode> reachableNodes = new HashSet<HeapRegionNode>();
-      HashSet<HeapRegionNode> todoNodes = new HashSet<HeapRegionNode>();
+      HashSet<HeapRegionNode> todoNodes      = new HashSet<HeapRegionNode>();
 
       // 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() );
+       todoNodes.add( edge.getDst() );
       }
 
       // then follow links until all reachable nodes have been found
@@ -1672,6 +1723,11 @@ public class OwnershipGraph {
        HashSet<HeapRegionNode> s1 = paramIndex2reachableCallerNodes.get( i );
        HashSet<HeapRegionNode> s2 = paramIndex2reachableCallerNodes.get( j );
 
+       // some parameters are immutable or primitive, so skip em
+       if( s1 == null || s2 == null ) {
+         continue;
+       }
+
        Set<HeapRegionNode> intersection = new HashSet<HeapRegionNode>(s1);
        intersection.retainAll(s2);
 
@@ -1750,23 +1806,83 @@ public class OwnershipGraph {
     return rsOut;
   }
 
-  public void resolveMethodCall(FlatCall fc,
-                                boolean isStatic,
-                                FlatMethod fm,
-                                OwnershipGraph ogCallee,
-                               MethodContext mc
+  // detects strong updates to the primary parameter object and
+  // effects the removal of old edges in the calling graph
+  private void effectCalleeStrongUpdates( Integer paramIndex,
+                                         OwnershipGraph ogCallee,
+                                         HeapRegionNode hrnCaller
+                                         ) {
+    Integer idPrimary = ogCallee.paramIndex2idPrimary.get( paramIndex );
+    assert idPrimary != null;
+
+    HeapRegionNode hrnPrimary = ogCallee.id2hrn.get( idPrimary );
+    assert hrnPrimary != null;
+
+    TypeDescriptor typeParam = hrnPrimary.getType();
+    assert typeParam.isClass();
+  
+    Set<String> fieldNamesToRemove = new HashSet<String>();   
+
+    ClassDescriptor cd = typeParam.getClassDesc();
+    while( cd != null ) {
+
+      Iterator fieldItr = cd.getFields();
+      while( fieldItr.hasNext() ) {
+         
+       FieldDescriptor fd = (FieldDescriptor) fieldItr.next();
+       TypeDescriptor typeField = fd.getType();
+       assert typeField != null;       
+         
+       if( ogCallee.hasFieldBeenUpdated( hrnPrimary, fd.getSymbol() ) ) {
+         clearReferenceEdgesFrom( hrnCaller, fd.getType(), fd.getSymbol(), false );
+       }
+      }
+      
+      cd = cd.getSuperDesc();
+    }
+  }
+
+  private boolean hasFieldBeenUpdated( HeapRegionNode hrnPrimary, String field ) {
+
+    Iterator<ReferenceEdge> itr = hrnPrimary.iteratorToReferencees();
+    while( itr.hasNext() ) {
+      ReferenceEdge e = itr.next();
+      if( e.fieldEquals( field ) && e.isInitialParam() ) {
+       return false;
+      }
+    }
+
+    return true;
+  }
+
+  // resolveMethodCall() is used to incorporate a callee graph's effects into
+  // *this* graph, which is the caller.  This method can also be used, after
+  // the entire analysis is complete, to perform parameter decomposition for 
+  // a given call chain.
+  public void resolveMethodCall(FlatCall       fc,        // call site in caller method
+                                boolean        isStatic,  // whether it is a static method
+                                FlatMethod     fm,        // the callee method (when virtual, can be many)
+                                OwnershipGraph ogCallee,  // the callee's current ownership graph
+                               MethodContext  mc,        // the aliasing context for this call
+                               ParameterDecomposition pd // if this is not null, we're calling after analysis
                                ) {
 
-      System.out.println( "  In mapping proc" );
 
+    // 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 ) ) {
 
       try {
-       writeGraph( "debug1Before", true, true, true, false, false );
+       writeGraph( "debug1BeforeCall", true, true, true, false, false );
        ogCallee.writeGraph( "debug0Callee", true, true, true, false, false );
       } catch( IOException e ) {}
 
@@ -1774,6 +1890,7 @@ public class OwnershipGraph {
     }
 
 
+
     // define rewrite rules and other structures to organize data by parameter/argument index
     Hashtable<Integer, ReachabilitySet> paramIndex2rewriteH_p = new Hashtable<Integer, ReachabilitySet>();
     Hashtable<Integer, ReachabilitySet> paramIndex2rewriteH_s = new Hashtable<Integer, ReachabilitySet>();
@@ -1887,6 +2004,7 @@ public class OwnershipGraph {
        assert hrnSecondary != null;
        paramIndex2rewriteH_s.put( paramIndex, toShadowTokens( ogCallee, hrnSecondary.getAlpha() ) );
 
+
        // setup J (secondary->X)
        Iterator<ReferenceEdge> s2xItr = hrnSecondary.iteratorToReferencees();
        while( s2xItr.hasNext() ) {
@@ -1947,6 +2065,24 @@ public class OwnershipGraph {
       LabelNode argLabel_i = getLabelNodeFromTemp( argTemp_i );
       paramIndex2ln.put( paramIndex, argLabel_i );
 
+      // do a callee-effect strong update pre-pass here      
+      if( argTemp_i.getType().isClass() ) {
+
+       Iterator<ReferenceEdge> edgeItr = argLabel_i.iteratorToReferencees();
+       while( edgeItr.hasNext() ) {
+         ReferenceEdge edge = edgeItr.next();
+         HeapRegionNode hrn = edge.getDst();
+
+         if( (hrn.getNumReferencers()                                == 1) || // case 1
+             (hrn.isSingleObject() && argLabel_i.getNumReferencees() == 1)    // case 2                     
+           ) {
+           
+           effectCalleeStrongUpdates( paramIndex, ogCallee, hrn );
+         }
+       }
+      }
+
+      // then calculate the d and D rewrite rules
       ReachabilitySet d_i_p = new ReachabilitySet().makeCanonical();
       ReachabilitySet d_i_s = new ReachabilitySet().makeCanonical();
       Iterator<ReferenceEdge> edgeItr = argLabel_i.iteratorToReferencees();
@@ -2033,6 +2169,42 @@ public class OwnershipGraph {
 
     assert defParamObj.size() <= fm.numParameters();
 
+    // if we're in parameter decomposition mode, report some results here
+    if( pd != null ) {
+      Iterator mapItr;
+
+      // report primary parameter object mappings
+      mapItr = pi2dr.entrySet().iterator();
+      while( mapItr.hasNext() ) {
+       Map.Entry           me         = (Map.Entry)           mapItr.next();
+       Integer             paramIndex = (Integer)             me.getKey();
+       Set<HeapRegionNode> hrnAset    = (Set<HeapRegionNode>) me.getValue();
+
+       Iterator<HeapRegionNode> hrnItr = hrnAset.iterator();
+       while( hrnItr.hasNext() ) {
+         HeapRegionNode hrnA = hrnItr.next();
+         pd.mapRegionToParamObject( hrnA, paramIndex );
+       }
+      }
+
+      // report parameter-reachable mappings
+      mapItr = pi2r.entrySet().iterator();
+      while( mapItr.hasNext() ) {
+       Map.Entry           me         = (Map.Entry)           mapItr.next();
+       Integer             paramIndex = (Integer)             me.getKey();
+       Set<HeapRegionNode> hrnRset    = (Set<HeapRegionNode>) me.getValue();
+
+       Iterator<HeapRegionNode> hrnItr = hrnRset.iterator();
+       while( hrnItr.hasNext() ) {
+         HeapRegionNode hrnR = hrnItr.next();
+         pd.mapRegionToParamReachable( hrnR, paramIndex );
+       }
+      }
+
+      // and we're done in this method for special param decomp mode
+      return;
+    }
+
 
     // now iterate over reachable nodes to rewrite their alpha, and
     // classify edges found for beta rewrite    
@@ -2095,6 +2267,7 @@ public class OwnershipGraph {
 
          boolean edge_classified = false;
 
+
          if( on instanceof HeapRegionNode ) {
            // hrn0 may be "a_j" and/or "r_j" or even neither
            HeapRegionNode hrn0 = (HeapRegionNode) on;
@@ -2137,11 +2310,8 @@ public class OwnershipGraph {
       while( hrnItr.hasNext() ) {
        // this heap region is definitely an "r_i" or secondary by virtue of being in r
        HeapRegionNode hrn = hrnItr.next();
-
-       //assert s_i != null;
-       //assert paramIndex2rewriteH_s.get( index ) != null;
-
-       if( paramIndex2rewriteH_s.contains( index ) ) {
+      
+       if( paramIndex2rewriteH_s.containsKey( index ) ) {
 
          tokens2states.clear();
          tokens2states.put( p_i, new ReachabilitySet().makeCanonical() );
@@ -2160,7 +2330,7 @@ public class OwnershipGraph {
                                     null );
        
          nodesWithNewAlpha.add( hrn ); 
-       }
+       }       
 
        // sort edges
        Iterator<ReferenceEdge> edgeItr = hrn.iteratorToReferencers();
@@ -2222,8 +2392,8 @@ public class OwnershipGraph {
        Vector        mo     = (Vector)        edgeItr.next();
        ReferenceEdge edge   = (ReferenceEdge) mo.get( 0 );
        Integer       indexJ = (Integer)       mo.get( 1 );
-               
-       if( !paramIndex2rewriteJ_p2p.contains( makeMapKey( index, 
+
+       if( !paramIndex2rewriteJ_p2p.containsKey( makeMapKey( index, 
                                                           indexJ,
                                                           edge.getField() ) ) ) {
          continue;
@@ -2248,7 +2418,7 @@ public class OwnershipGraph {
                                   ogCallee,
                                   false,
                                   null );
-
+       
        edgesWithNewBeta.add( edge );
       }
 
@@ -2259,8 +2429,8 @@ public class OwnershipGraph {
        ReferenceEdge edge   = (ReferenceEdge) mo.get( 0 );
        Integer       indexJ = (Integer)       mo.get( 1 );
 
-       if( !paramIndex2rewriteJ_p2s.contains( makeMapKey( index, 
-                                                          edge.getField() ) ) ) {
+       if( !paramIndex2rewriteJ_p2s.containsKey( makeMapKey( index, 
+                                                             edge.getField() ) ) ) {
          continue;
        }
 
@@ -2282,8 +2452,8 @@ public class OwnershipGraph {
                                   ogCallee,
                                   false,
                                   null );
-
-       edgesWithNewBeta.add( edge );
+       
+       edgesWithNewBeta.add( edge );   
       }
 
 
@@ -2293,7 +2463,7 @@ public class OwnershipGraph {
        ReferenceEdge edge   = (ReferenceEdge) mo.get( 0 );
        Integer       indexJ = (Integer)       mo.get( 1 );
 
-       if( !paramIndex2rewriteJ_s2p.contains( index ) ) {
+       if( !paramIndex2rewriteJ_s2p.containsKey( index ) ) {
          continue;
        }
 
@@ -2325,7 +2495,7 @@ public class OwnershipGraph {
        ReferenceEdge edge   = (ReferenceEdge) mo.get( 0 );
        Integer       indexJ = (Integer)       mo.get( 1 );
 
-       if( !paramIndex2rewriteJ_s2s.contains( index ) ) {
+       if( !paramIndex2rewriteJ_s2s.containsKey( index ) ) {
          continue;
        }
 
@@ -2424,7 +2594,7 @@ public class OwnershipGraph {
        ReferenceEdge edge   = (ReferenceEdge) mo.get( 0 );
        Integer       indexJ = (Integer)       mo.get( 1 );
 
-       if( !paramIndex2rewriteK_s.contains( index ) ) {
+       if( !paramIndex2rewriteK_s.containsKey( index ) ) {
          continue;
        }
 
@@ -2579,6 +2749,7 @@ public class OwnershipGraph {
 
          // make the edge with src and dst so beta info is
          // calculated once, then copy it for each new edge in caller
+
          ReferenceEdge edgeNewInCallerTemplate = new ReferenceEdge( null,
                                                                     null,
                                                                     edgeCallee.getType(),
@@ -2590,6 +2761,7 @@ public class OwnershipGraph {
                                                                                  ogCallee,
                                                                                  mc )
                                                                     );
+
          rewriteCallerReachability( bogusIndex,
                                     null,
                                     edgeNewInCallerTemplate,
@@ -2642,7 +2814,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(),
@@ -2735,6 +2925,15 @@ public class OwnershipGraph {
     }
 
 
+    if( mc.getDescriptor().getSymbol().equals( debugCaller ) &&
+       fm.getMethod().getSymbol().equals( debugCallee ) ) {
+      try {
+       writeGraph( "debug7JustBeforeMergeToKCapacity", true, true, true, false, false );
+      } catch( IOException e ) {}
+    }
+
+
+
     // merge the shadow nodes of allocation sites back down to normal capacity
     Iterator<AllocationSite> allocItr = ogCallee.allocationSites.iterator();
     while( allocItr.hasNext() ) {
@@ -2805,7 +3004,7 @@ public class OwnershipGraph {
     if( mc.getDescriptor().getSymbol().equals( debugCaller ) &&
        fm.getMethod().getSymbol().equals( debugCallee ) ) {
       try {
-       writeGraph( "debug2JustBeforeSweep", true, true, true, false, false );
+       writeGraph( "debug8JustBeforeSweep", true, true, true, false, false );
       } catch( IOException e ) {}
     }
 
@@ -2820,12 +3019,16 @@ public class OwnershipGraph {
       try {
        writeGraph( "debug9endResolveCall", true, true, true, false, false );
       } catch( IOException e ) {}
-      System.out.println( "  "+mc+" done calling "+fm );
+      System.out.println( "  "+mc+" done calling "+fm );      
+      ++x;
+      if( x > 2 ) {
+       System.exit( -1 );   
+      }
     }
-
-    System.out.println( "  End mapping proc" );
   }
 
+  static int x = 0;
+
 
   protected boolean hasMatchingField(HeapRegionNode src, ReferenceEdge edge) {
 
@@ -2854,15 +3057,22 @@ public class OwnershipGraph {
       return false;
     }
 
-    Iterator fieldsSrcItr = tdSrc.getClassDesc().getFields();
-    while( fieldsSrcItr.hasNext() ) {
-      FieldDescriptor fd = (FieldDescriptor) fieldsSrcItr.next();
-      if( fd.getType().equals( edge.getType() ) &&
-         fd.getSymbol().equals( edge.getField() ) ) {
-       return true;
+    ClassDescriptor cd = tdSrc.getClassDesc();
+    while( cd != null ) {      
+      Iterator fieldItr = cd.getFields();
+
+      while( fieldItr.hasNext() ) {    
+       FieldDescriptor fd = (FieldDescriptor) fieldItr.next();
+
+       if( fd.getType().equals( edge.getType() ) &&
+           fd.getSymbol().equals( edge.getField() ) ) {
+         return true;
+       }
       }
+      
+      cd = cd.getSuperDesc();
     }
-
+    
     // otherwise it is a class with fields
     // but we didn't find a match
     return false;
@@ -2959,13 +3169,13 @@ public class OwnershipGraph {
 
       Iterator<TokenTuple> ruleItr = rule.iterator();
       while(ruleItr.hasNext()) {
-       TokenTuple ttCallee = ruleItr.next();
+       TokenTuple ttCallee = ruleItr.next();   
 
        // compute the possibilities for rewriting this callee token
        ReachabilitySet ttCalleeRewrites = null;
        boolean         callerSourceUsed = false;
 
-       if( tokens2states.containsKey( ttCallee ) ) {     
+       if( tokens2states.containsKey( ttCallee ) ) {
          callerSourceUsed = true;
          ttCalleeRewrites = tokens2states.get( ttCallee );
          assert ttCalleeRewrites != null;
@@ -3171,13 +3381,8 @@ public class OwnershipGraph {
   //  invoked after strong updates or method calls.
   //
   ////////////////////////////////////////////////////
-
-    static int x = 0;
-
   public void globalSweep() {
 
-            System.out.println( "    In global sweep" );
-
     // boldB is part of the phase 1 sweep
     Hashtable< Integer, Hashtable<ReferenceEdge, ReachabilitySet> > boldB =
       new Hashtable< Integer, Hashtable<ReferenceEdge, ReachabilitySet> >();    
@@ -3230,7 +3435,7 @@ public class OwnershipGraph {
            ReferenceEdge edgePrime = itrPrime.next();      
 
            ReachabilitySet prevResult   = boldB_f.get( edgePrime );
-           ReachabilitySet intersection = boldB_f.get( edge ).intersection( edgePrime.getBeta() );         
+           ReachabilitySet intersection = boldB_f.get( edge ).intersection( edgePrime.getBeta() );
                    
            if( prevResult == null || 
                prevResult.union( intersection ).size() > prevResult.size() ) {
@@ -3238,7 +3443,7 @@ public class OwnershipGraph {
              if( prevResult == null ) {
                boldB_f.put( edgePrime, edgePrime.getBeta().union( intersection ) );
              } else {
-               boldB_f.put( edgePrime, prevResult.union( intersection ) );
+               boldB_f.put( edgePrime, prevResult         .union( intersection ) );
              }
              workSetEdges.add( edgePrime );    
            }
@@ -3298,16 +3503,8 @@ public class OwnershipGraph {
            ReferenceEdge incidentEdge = incidentEdgeItr.next();
 
            // if it isn't allowed, mark for removal
-
-           
-           x++;
-           if( x % 1000 == 0 && x > 4000000 ) {
-               System.out.println( "x="+x );
-               //System.out.println( boldB.get( ttOld.getToken() ) );
-           }
-           
-
            Integer idOld = ttOld.getToken();
+           assert id2hrn.containsKey( idOld );
            Hashtable<ReferenceEdge, ReachabilitySet> B = boldB.get( idOld );       
            ReachabilitySet boldB_ttOld_incident = B.get( incidentEdge );// B is NULL!      
            if( boldB_ttOld_incident != null &&
@@ -3439,8 +3636,6 @@ public class OwnershipGraph {
     while( edgeItr.hasNext() ) {
       edgeItr.next().applyBetaNew();
     } 
-
-            System.out.println( "    End global sweep" );
   }  
 
 
@@ -3560,6 +3755,8 @@ public class OwnershipGraph {
          edgeToMerge.setBeta(
            edgeToMerge.getBeta().union(edgeA.getBeta() )
            );
+               //TODO eom
+           edgeToMerge.unionTaintIdentifier(edgeA.getTaintIdentifier());
          if( !edgeA.isInitialParam() ) {
            edgeToMerge.setIsInitialParam(false);
          }
@@ -3621,6 +3818,7 @@ public class OwnershipGraph {
          edgeToMerge.setBeta(
            edgeToMerge.getBeta().union(edgeA.getBeta() )
            );
+           edgeToMerge.unionTaintIdentifier(edgeA.getTaintIdentifier());
          if( !edgeA.isInitialParam() ) {
            edgeToMerge.setIsInitialParam(false);
          }
@@ -3958,14 +4156,14 @@ public class OwnershipGraph {
                                        TokenTuple.ARITY_ZEROORMORE).makeCanonical();
 
     // then get the merged beta of all out-going edges from these heap regions
-    ReachabilitySet beta1 = new ReachabilitySet();
+    ReachabilitySet beta1 = new ReachabilitySet().makeCanonical();
     Iterator<ReferenceEdge> itrEdge = hrn1.iteratorToReferencees();
     while( itrEdge.hasNext() ) {
       ReferenceEdge edge = itrEdge.next();
       beta1 = beta1.union( edge.getBeta() );
     }
 
-    ReachabilitySet beta2 = new ReachabilitySet();
+    ReachabilitySet beta2 = new ReachabilitySet().makeCanonical();
     itrEdge = hrn2.iteratorToReferencees();
     while( itrEdge.hasNext() ) {
       ReferenceEdge edge = itrEdge.next();
@@ -4204,7 +4402,6 @@ public class OwnershipGraph {
 
   public Set<HeapRegionNode> findCommonReachableNodes( HeapRegionNode hrn1,
                                                       HeapRegionNode hrn2 ) {
-    //assert hrn1 != hrn2;
 
     Set<HeapRegionNode> reachableNodes1 = new HashSet<HeapRegionNode>();
     Set<HeapRegionNode> reachableNodes2 = new HashSet<HeapRegionNode>();
@@ -4355,7 +4552,7 @@ public class OwnershipGraph {
     bw.write("  graphTitle[label=\""+graphName+"\",shape=box];\n");
 
     if( writeParamMappings ) {
-      /*
+      /* UNMAINTAINED
       Set df = paramIndex2id.entrySet();
       Iterator ih = df.iterator();
       while( ih.hasNext() ) {
@@ -4451,7 +4648,7 @@ public class OwnershipGraph {
                     "\\n";
 
       if( hrn.getType() != null ) {
-        attributes += hrn.getType() + "\\n";
+        attributes += hrn.getType().toPrettyString() + "\\n";
       }
        
       attributes += hrn.getDescription() +
@@ -4506,4 +4703,61 @@ public class OwnershipGraph {
                               writeReferencers);
     }
   }
+  
+  public int getTaintIdentifierFromHRN(HeapRegionNode hrn){
+         HashSet<ReferenceEdge> referenceEdges=hrn.referencers;
+         Iterator<ReferenceEdge> iter=referenceEdges.iterator();
+         
+         int taintIdentifier=0;
+         while(iter.hasNext()){
+                 ReferenceEdge edge=iter.next();
+                 taintIdentifier=taintIdentifier | edge.getTaintIdentifier();            
+         }
+         
+         return taintIdentifier;
+         
+  }
+  
+  public void propagateTaintIdentifier(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.unionTaintIdentifier(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);
+                                 propagateTaintIdentifier((HeapRegionNode)edge.getSrc(),newTaintIdentifier,visitedSet);
+                         }
+                        
+                 }
+         }       
+         
+  }
+  
+  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);
+                         }
+                        
+                 }
+         }       
+         
+  }
+  
 }