bug fix...things are slower to compile...:(
[IRC.git] / Robust / src / Analysis / Pointer / Pointer.java
index a801f12d97afad93f26ebbf0444efdb1c765774a..f1fddad9884416a17c175dbae0befdf46445e5e3 100644 (file)
@@ -5,21 +5,53 @@ import IR.*;
 import Analysis.Liveness;
 import Analysis.Pointer.BasicBlock.BBlock;
 import Analysis.Pointer.AllocFactory.AllocNode;
+import Analysis.Disjoint.Alloc;
+import Analysis.Disjoint.Taint;
+import Analysis.Disjoint.TaintSet;
+import Analysis.Disjoint.Canonical;
+import Analysis.Disjoint.HeapAnalysis;
+import Analysis.CallGraph.CallGraph;
+import Analysis.OoOJava.RBlockRelationAnalysis;
+import Analysis.OoOJava.Accessible;
+import Analysis.Disjoint.ExistPred;
+import Analysis.Disjoint.ReachGraph;
+import Analysis.Disjoint.EffectsAnalysis;
+import Analysis.Disjoint.BuildStateMachines;
 import java.io.*;
 
-public class Pointer {
+
+public class Pointer implements HeapAnalysis{
   HashMap<FlatMethod, BasicBlock> blockMap;
   HashMap<BBlock, Graph> bbgraphMap;
   HashMap<FlatNode, Graph> graphMap;
   HashMap<FlatCall, Set<BBlock>> callMap;
   HashMap<BBlock, Set<PPoint>> returnMap;
   HashMap<BBlock, Set<TempDescriptor>> bblivetemps;
+  HashSet<FlatNode> mustProcess;
 
+  private boolean OoOJava=false;
+  CallGraph callGraph;
   State state;
   TypeUtil typeUtil;
   AllocFactory allocFactory;
   LinkedList<Delta> toprocess;
   TempDescriptor returntmp;
+  RBlockRelationAnalysis taskAnalysis;
+  EffectsAnalysis effectsAnalysis;
+  Accessible accessible;
+
+  public Pointer(State state, TypeUtil typeUtil, CallGraph callGraph, RBlockRelationAnalysis taskAnalysis, Liveness liveness, BuildStateMachines bsm) {
+    this(state, typeUtil);
+    this.callGraph=callGraph;
+    this.OoOJava=true;
+    this.taskAnalysis=taskAnalysis;
+    this.effectsAnalysis=new EffectsAnalysis();
+    effectsAnalysis.state=state;
+    effectsAnalysis.buildStateMachines=bsm;
+    accessible=new Accessible(state, callGraph, taskAnalysis, liveness);
+    accessible.doAnalysis();
+    State.logEvent("Done Writing Accessible Analysis");
+  }
 
   public Pointer(State state, TypeUtil typeUtil) {
     this.state=state;
@@ -34,6 +66,11 @@ public class Pointer {
     this.toprocess=new LinkedList<Delta>();
     ClassDescriptor stringcd=typeUtil.getClass(TypeUtil.ObjectClass);
     this.returntmp=new TempDescriptor("RETURNVAL", stringcd);
+    this.mustProcess=new HashSet<FlatNode>();
+  }
+
+  public EffectsAnalysis getEffectsAnalysis() {
+    return effectsAnalysis;
   }
 
   public BasicBlock getBBlock(FlatMethod fm) {
@@ -72,7 +109,13 @@ public class Pointer {
     return delta;
   }
 
+
+  public Graph getGraph(FlatNode fn) {
+    return graphMap.get(fn);
+  }
+
   public void doAnalysis() {
+
     toprocess.add(buildInitialContext());
     nextdelta:
     while(!toprocess.isEmpty()) {
@@ -104,13 +147,44 @@ public class Pointer {
       if (!init&&delta.isEmpty())
        continue nextdelta;
       
+      int lasti=-1;
       //Compute delta at exit of each node
       for(int i=startindex; i<nodes.size();i++) {
        FlatNode currNode=nodes.get(i);
        //System.out.println("Start Processing "+currNode);
+
        if (!graphMap.containsKey(currNode)) {
-         graphMap.put(currNode, new Graph(graph));
+         if (isNEEDED(currNode)) {
+           graphMap.put(currNode, new Graph(graph));
+         } else {
+           boolean fallthru=true;
+           if (isINACC(currNode)&&((lasti==-1)||(lasti==i))) {
+             if (lasti==-1) {
+               for(lasti=nodes.size()-1;lasti>=i;lasti--) {
+                 FlatNode scurrNode=nodes.get(lasti);
+                 if (isNEEDED(scurrNode)||isINACC(scurrNode)) {
+                   break;
+                 }
+               }
+             }
+             if (i==lasti) {
+               mustProcess.add(currNode);
+               graphMap.put(currNode, new Graph(graph));
+               fallthru=false;
+             }
+           }
+           if (fallthru) {
+             if (i==0) {
+               //base graph works for us
+               graphMap.put(currNode, new Graph(graph));
+             } else {
+               //just use previous graph
+               graphMap.put(currNode, graphMap.get(nodes.get(i-1)));
+             }
+           }
+         }
        }
+
        nodeGraph=graphMap.get(currNode);
        delta=processNode(bblock, i, currNode, delta, nodeGraph);
        //System.out.println("Processing "+currNode+" and generating delta:");
@@ -120,13 +194,14 @@ public class Pointer {
     }
 
     //DEBUG
-    if (true) {
+    if (false) {
       int debugindex=0;
       for(Map.Entry<BBlock, Graph> e:bbgraphMap.entrySet()) {
        Graph g=e.getValue();
        plotGraph(g,"BB"+e.getKey().nodes.get(0).toString().replace(' ','_'));
        debugindex++;
       }
+      
       for(FlatMethod fm:blockMap.keySet()) {
        System.out.println(fm.printMethod());
       }
@@ -137,6 +212,14 @@ public class Pointer {
        debugindex++;
       } 
     }
+
+    State.logEvent("Done With Pointer Analysis");
+
+
+    if (OoOJava) {
+      effectsAnalysis.buildStateMachines.writeStateMachines();
+      State.logEvent("Done Writing State Machines");
+    }
   }
 
   void plotGraph(Graph g, String name) {
@@ -185,12 +268,6 @@ public class Pointer {
        edgeSet.addAll(graph.parent.nodeMap.get(node));
       newDelta.heapedgeadd.put(node, edgeSet);
       
-      /* Compute ages */
-      if (graph.nodeAges.contains(node))
-       newDelta.addNodeAges.add(node);
-      else if (graph.parent.nodeAges.contains(node))
-       newDelta.addNodeAges.add(node);
-
       /* Compute ages */
       if (graph.oldNodes.containsKey(node)) {
        if (graph.oldNodes.get(node).booleanValue())
@@ -200,6 +277,9 @@ public class Pointer {
        newDelta.addOldNodes.put(node, Boolean.TRUE);
       }
     }
+    
+    newDelta.addNodeAges.addAll(graph.nodeAges);
+    newDelta.addNodeAges.addAll(graph.parent.nodeAges);
   }
 
   /* This function build the delta for the exit of a basic block. */
@@ -319,6 +399,28 @@ public class Pointer {
     }
   }
 
+  boolean isNEEDED(FlatNode node) {
+    switch(node.kind()) {
+    case FKind.FlatSetFieldNode: {
+      FlatSetFieldNode n=(FlatSetFieldNode)node;
+      return n.getSrc().getType().isPtr();
+    }
+    case FKind.FlatSetElementNode: {
+      FlatSetElementNode n=(FlatSetElementNode)node;
+      return n.getSrc().getType().isPtr();
+    }
+    case FKind.FlatFieldNode: {
+      FlatFieldNode n=(FlatFieldNode)node;
+      return n.getDst().getType().isPtr();
+    }
+    case FKind.FlatElementNode: {
+      FlatElementNode n=(FlatElementNode)node;
+      return n.getDst().getType().isPtr();
+    }
+    }
+    return true;
+  }
+
   Delta processNode(BBlock bblock, int index, FlatNode node, Delta delta, Graph newgraph) {
     switch(node.kind()) {
     case FKind.FlatNew:
@@ -333,12 +435,14 @@ public class Pointer {
     case FKind.FlatSetFieldNode:
     case FKind.FlatSetElementNode:
       return processSetFieldElementNode(node, delta, newgraph);
+    case FKind.FlatSESEEnterNode:
+      return processSESEEnterNode((FlatSESEEnterNode) node, delta, newgraph);
+    case FKind.FlatSESEExitNode:
+      return processSESEExitNode((FlatSESEExitNode) node, delta, newgraph);
     case FKind.FlatMethod:
     case FKind.FlatExit:
     case FKind.FlatBackEdge:
     case FKind.FlatGenReachNode:
-    case FKind.FlatSESEEnterNode:
-    case FKind.FlatSESEExitNode:
       return processFlatNop(node, delta, newgraph);
     case FKind.FlatCall:
       return processFlatCall(bblock, index, (FlatCall) node, delta, newgraph);
@@ -347,6 +451,156 @@ public class Pointer {
     }
   }
 
+  Delta processSESEEnterNode(FlatSESEEnterNode sese, Delta delta, Graph graph) {
+    if (!OoOJava)
+      return processFlatNop(sese, delta, graph);
+    if (delta.getInit()) {
+      removeInitTaints(null, delta, graph);
+      for (TempDescriptor tmp:sese.getInVarSet()) {
+       Taint taint=Taint.factory(sese,  null, tmp, AllocFactory.dummySite, null, ReachGraph.predsEmpty);
+       MySet<Edge> edges=GraphManip.getEdges(graph, delta, tmp);
+       for(Edge e:edges) {
+         Edge newe=e.addTaint(taint);
+         delta.addVarEdge(newe);
+       }
+      }
+    } else {
+      removeDiffTaints(null, delta);
+      for (TempDescriptor tmp:sese.getInVarSet()) {
+       Taint taint=Taint.factory(sese,  null, tmp, AllocFactory.dummySite, null, ReachGraph.predsEmpty);
+       MySet<Edge> edges=GraphManip.getDiffEdges(delta, tmp);
+       for(Edge e:edges) {
+         Edge newe=e.addTaint(taint);
+         delta.addVarEdge(newe);
+       }
+      }
+    }
+
+
+    applyDiffs(graph, delta);
+    return delta;
+  }
+  
+  private boolean isRecursive(FlatSESEEnterNode sese) {
+    MethodDescriptor md=sese.getmdEnclosing();
+    boolean isrecursive=callGraph.getCalleeSet(md).contains(md);
+    return isrecursive;
+  }
+
+  Delta processSESEExitNode(FlatSESEExitNode seseexit, Delta delta, Graph graph) {
+    if (!OoOJava)
+      return processFlatNop(seseexit, delta, graph);
+    FlatSESEEnterNode sese=seseexit.getFlatEnter();
+    //Strip Taints from this SESE
+    if (delta.getInit()) {
+      removeInitTaints(isRecursive(sese)?null:sese, delta, graph);
+    } else {
+      removeDiffTaints(isRecursive(sese)?null:sese, delta);
+    }
+    applyDiffs(graph, delta);
+    return delta;
+  }
+  
+  void removeDiffTaints(FlatSESEEnterNode sese, Delta delta) {
+    //Start with variable edges
+    {
+      MySet<Edge> edgestoadd=new MySet<Edge>();
+      MySet<Edge> edgestoremove=new MySet<Edge>();
+      
+      //Process base diff edges
+      processEdgeMap(sese, delta.basevaredge, null, delta.varedgeremove, edgestoremove, edgestoadd); 
+      //Process delta edges
+      processEdgeMap(sese, delta.varedgeadd, null, null, edgestoremove, edgestoadd); 
+      for(Edge e:edgestoremove) {
+       delta.removeVarEdge(e);
+      }
+      for(Edge e:edgestoadd) {
+       delta.addVarEdge(e);
+      }
+    }
+
+    //Now do heap edges
+    {
+      MySet<Edge> edgestoadd=new MySet<Edge>();
+      MySet<Edge> edgestoremove=new MySet<Edge>();
+
+      //Process base diff edges
+      processEdgeMap(sese, delta.baseheapedge, null, delta.heapedgeremove, edgestoremove, edgestoadd); 
+      //Process delta edges
+      processEdgeMap(sese, delta.heapedgeadd, null, null, edgestoremove, edgestoadd); 
+      for(Edge e:edgestoremove) {
+       delta.removeHeapEdge(e);
+      }
+      for(Edge e:edgestoadd) {
+       delta.addHeapEdge(e);
+      }
+    }
+  }
+
+  void removeInitTaints(FlatSESEEnterNode sese, Delta delta, Graph graph) {
+    //Start with variable edges
+    {
+      MySet<Edge> edgestoadd=new MySet<Edge>();
+      MySet<Edge> edgestoremove=new MySet<Edge>();
+      
+      //Process parent edges
+      processEdgeMap(sese, graph.parent.varMap, graph.varMap, delta.varedgeremove, edgestoremove, edgestoadd);
+      //Process graph edges
+      processEdgeMap(sese, graph.varMap, null, delta.varedgeremove, edgestoremove, edgestoadd); 
+      //Process delta edges
+      processEdgeMap(sese, delta.varedgeadd, null, null, edgestoremove, edgestoadd); 
+      for(Edge e:edgestoremove) {
+       delta.removeVarEdge(e);
+      }
+      for(Edge e:edgestoadd) {
+       delta.addVarEdge(e);
+      }
+    }
+
+    //Now do heap edges
+    {
+      MySet<Edge> edgestoadd=new MySet<Edge>();
+      MySet<Edge> edgestoremove=new MySet<Edge>();
+
+      //Process parent edges
+      processEdgeMap(sese, graph.parent.nodeMap, graph.nodeMap, delta.heapedgeremove, edgestoremove, edgestoadd);
+      //Process graph edges
+      processEdgeMap(sese, graph.nodeMap, null, delta.heapedgeremove, edgestoremove, edgestoadd); 
+      //Process delta edges
+      processEdgeMap(sese, delta.heapedgeadd, null, null, edgestoremove, edgestoadd); 
+      for(Edge e:edgestoremove) {
+       delta.removeHeapEdge(e);
+      }
+      for(Edge e:edgestoadd) {
+       delta.addHeapEdge(e);
+      }
+    }
+  }
+
+  void processEdgeMap(FlatSESEEnterNode sese, HashMap<?, MySet<Edge>> edgemap, HashMap<?, MySet<Edge>> childmap, HashMap<?, MySet<Edge>> removemap, MySet<Edge> edgestoremove, MySet<Edge> edgestoadd) {
+    for(Map.Entry<?, MySet<Edge>> entry:edgemap.entrySet()) {
+      //If the parent map exists and overrides this entry, skip it
+      if (childmap!=null&&childmap.containsKey(entry.getKey()))
+       continue;
+      for(Edge e:entry.getValue()) {
+       //check whether this edge has been removed
+       if (removemap!=null&&removemap.containsKey(entry.getKey())&&
+           removemap.get(entry.getKey()).contains(e))
+         continue;
+       //have real edge
+       TaintSet ts=e.getTaints();
+       TaintSet newts=null;
+       //update non-null taint set
+       if (ts!=null)
+         newts=Canonical.removeInContextTaintsNP(ts, sese);
+       if (newts!=null) {
+         edgestoremove.add(e);
+         edgestoadd.add(e.changeTaintSet(newts));
+       }
+      }
+    }
+  }
+
   /* This function compute the edges for the this variable for a
    * callee if it exists. */
 
@@ -398,7 +652,7 @@ public class Pointer {
        AllocNode node=tovisit.pop();
        MySet<Edge> edges=GraphManip.getEdges(graph, delta, node);
        if (!edges.isEmpty()) {
-         newDelta.heapedgeadd.put(node, edges);
+         newDelta.heapedgeadd.put(node, Edge.makeOld(edges));
          edgeset.addAll(edges);
          for(Edge e:edges) {
            if (!nodeset.contains(e.dst)&&(oldnodeset==null||!oldnodeset.contains(e.dst))) {
@@ -414,7 +668,7 @@ public class Pointer {
     TempDescriptor tmpthis=fcall.getThis();
     MethodDescriptor md=fcall.getMethod();
     HashSet<MethodDescriptor> targets=new HashSet<MethodDescriptor>();
-    if (md.isStatic()) {
+    if (md.isStatic()||fcall.getSuper()) {
       targets.add(md);
     } else {
       //Compute Edges
@@ -513,7 +767,8 @@ public class Pointer {
   }
 
 
-  /* This function computes all edges that start outside of the callee context and go into the callee context */
+  /* This function computes all edges that start outside of the callee
+   * context and go into the callee context */
 
   void computeExternalEdges(Graph graph, Delta delta, HashSet<AllocNode> nodeset, HashSet<AllocNode> deltaset, MySet<Edge> externaledgeset) {
     //Do heap edges first
@@ -535,7 +790,7 @@ public class Pointer {
       }
     }
 
-    //Do heap edges first
+    //Do var edges now
     HashSet<TempDescriptor> temps=new HashSet<TempDescriptor>();
     temps.addAll(delta.basevaredge.keySet());
     temps.addAll(delta.varedgeadd.keySet());
@@ -560,10 +815,10 @@ public class Pointer {
   /* This function removes the caller reachable edges from the
    * callee's heap. */
   
-  void removeEdges(Delta delta, HashSet<AllocNode> nodeset, MySet<Edge> edgeset, MySet<Edge> externaledgeset) {
+  void removeEdges(Graph graph, Delta delta, HashSet<AllocNode> nodeset, MySet<Edge> edgeset, MySet<Edge> externaledgeset) {
     //Want to remove the set of internal edges
     for(Edge e:edgeset) {
-      if (e.src!=null) {
+      if (e.src!=null&&!graph.callerEdges.contains(e)) {
        delta.removeHeapEdge(e);
       }
     }
@@ -571,7 +826,8 @@ public class Pointer {
     //Want to remove the set of external edges
     for(Edge e:externaledgeset) {
       //want to remove the set of internal edges
-      delta.removeEdge(e);
+      if (!graph.callerEdges.contains(e))
+       delta.removeEdge(e);
     }
   }
 
@@ -585,6 +841,7 @@ public class Pointer {
       HashSet<ClassDescriptor> targetSet=new HashSet<ClassDescriptor>();
       Stack<AllocNode> tovisit=new Stack<AllocNode>();
       TempDescriptor tmpthis=fcall.getThis();
+      graph.callerEdges=new MySet<Edge>();
 
       //Handle the this temp
       processThisTargets(targetSet, graph, delta, newDelta, nodeset, tovisit, edgeset, tmpthis, null);
@@ -605,7 +862,7 @@ public class Pointer {
       computeExternalEdges(graph, delta, nodeset, null, externaledgeset);
 
       //Splice out internal edges
-      removeEdges(delta, nodeset, edgeset, externaledgeset);
+      removeEdges(graph, delta, nodeset, edgeset, externaledgeset);
 
       //store data structures
       graph.externalEdgeSet=externaledgeset;
@@ -615,6 +872,8 @@ public class Pointer {
       graph.callTargets=newtargets;
       graph.callNodeAges=new HashSet<AllocNode>();
       graph.callOldNodes=new HashSet<AllocNode>();
+      graph.callNewEdges=new HashMap<AllocNode, MySet<Edge>>();
+      graph.callOldEdges=new HashMap<Edge,MySet<Edge>>();
 
       //Apply diffs to graph
       applyDiffs(graph, delta, true);
@@ -628,7 +887,24 @@ public class Pointer {
       HashSet<ClassDescriptor> targetSet=new HashSet<ClassDescriptor>();
       Stack<AllocNode> tovisit=new Stack<AllocNode>();
       TempDescriptor tmpthis=fcall.getThis();
+      //Fix up delta to get rid of unnecessary heap edge removals
+      for(Map.Entry<AllocNode, MySet<Edge>> entry:delta.heapedgeremove.entrySet()) {
+       for(Iterator<Edge> eit=entry.getValue().iterator();eit.hasNext();) {
+         Edge e=eit.next();
+         if (graph.callerEdges.contains(e))
+           eit.remove();
+       }
+      }
 
+      //Fix up delta to get rid of unnecessary var edge removals
+      for(Map.Entry<TempDescriptor, MySet<Edge>> entry:delta.varedgeremove.entrySet()) {
+       for(Iterator<Edge> eit=entry.getValue().iterator();eit.hasNext();) {
+         Edge e=eit.next();
+         if (graph.callerEdges.contains(e))
+           eit.remove();
+       }
+      }
+      
       //Handle the this temp
       processThisTargets(targetSet, graph, delta, newDelta, nodeset, tovisit, edgeset, tmpthis, oldnodeset);
 
@@ -643,7 +919,7 @@ public class Pointer {
        if (!newDelta.heapedgeadd.containsKey(src)) {
          newDelta.heapedgeadd.put(src, new MySet<Edge>());
        }
-       newDelta.heapedgeadd.get(src).add(e);
+       newDelta.heapedgeadd.get(src).add(e.makeOld());
        if (!nodeset.contains(e.dst)&&!oldnodeset.contains(e.dst)) {
          nodeset.add(e.dst);
          tovisit.add(e.dst);
@@ -655,6 +931,7 @@ public class Pointer {
       //Compute call targets
       HashSet<MethodDescriptor> newtargets=computeTargets(fcall, newDelta);
       graph.callTargets.addAll(newtargets);
+
       //add in new nodeset and edgeset
       oldnodeset.addAll(nodeset);
       oldedgeset.addAll(edgeset);
@@ -662,8 +939,45 @@ public class Pointer {
       fixMapping(fcall, graph.callTargets, oldedgeset, newDelta, callblock, callindex);
       //Compute edges into region to splice out
       computeExternalEdges(graph, delta, oldnodeset, nodeset, externaledgeset);
+
       //Splice out internal edges
-      removeEdges(delta, nodeset, edgeset, externaledgeset);
+      removeEdges(graph, delta, nodeset, edgeset, externaledgeset);
+
+      //Add external edges back in
+      processCallExternal(graph, delta, externaledgeset);
+
+      //Move new edges that should be summarized
+      processSummarization(graph, delta);
+
+      Set<FlatSESEEnterNode> seseCallers=OoOJava?taskAnalysis.getTransitiveExecutingRBlocks(fcall):null;
+      //Check if the new nodes allow us to insert a new edge
+      for(AllocNode node:nodeset) {
+       if (graph.callNewEdges.containsKey(node)) {
+         for(Iterator<Edge> eit=graph.callNewEdges.get(node).iterator();eit.hasNext();) {
+           Edge e=eit.next();
+           if ((graph.callNodeAges.contains(e.src)||graph.reachNode.contains(e.src))&&
+               (graph.callNodeAges.contains(e.dst)||graph.reachNode.contains(e.dst))) {
+             Edge edgetoadd=e.copy();//we need our own copy to modify below
+             eit.remove();
+             if (seseCallers!=null)
+               edgetoadd.taintModify(seseCallers);
+             mergeCallEdge(graph, delta, edgetoadd);
+           }
+         }
+       }
+      }
+
+      for(Edge e:edgeset) {
+       //See if these edges would allow an old edge to be added
+       if (graph.callOldEdges.containsKey(e)) {
+         for(Edge adde:graph.callOldEdges.get(e)) {
+           Edge ecopy=adde.copy();
+           ecopy.statuspredicate=e.statuspredicate;
+           mergeCallEdge(graph, delta, ecopy);
+         }
+       }
+      }
+
       //Add in new external edges
       graph.externalEdgeSet.addAll(externaledgeset);
       //Apply diffs to graph
@@ -672,6 +986,107 @@ public class Pointer {
     return delta;
   }
 
+  void processSummarization(Graph graph, Delta delta) {
+    processSumHeapEdgeSet(delta.heapedgeadd, delta, graph);
+    processSumHeapEdgeSet(delta.baseheapedge, delta, graph);
+    processSumVarEdgeSet(delta.varedgeadd, delta, graph);
+    processSumVarEdgeSet(delta.basevaredge, delta, graph);
+  }
+
+  void processSumVarEdgeSet(HashMap<TempDescriptor, MySet<Edge>> map, Delta delta, Graph graph) {
+    MySet<Edge> edgestoadd=new MySet<Edge>();
+    MySet<Edge> edgestoremove=new MySet<Edge>();
+    for(Iterator<Map.Entry<TempDescriptor, MySet<Edge>>> eit=map.entrySet().iterator();eit.hasNext();) {
+      Map.Entry<TempDescriptor, MySet<Edge>> entry=eit.next();
+      MySet<Edge> edgeset=entry.getValue();
+
+      for(Edge e:edgeset) {
+       Edge copy=e.copy();
+       boolean rewrite=false;
+       if (copy.dst!=null&&graph.callNodeAges.contains(copy.dst)) {
+         copy.dst=allocFactory.getAllocNode(copy.dst, true);
+         rewrite=true;
+       }
+       if (rewrite) {
+         edgestoremove.add(e);
+         edgestoadd.add(copy);
+       }
+      }
+    }
+    for(Edge e:edgestoremove) {
+      if (!graph.callerEdges.contains(e))
+       delta.removeVarEdge(e);
+    }
+    for(Edge e:edgestoadd) {
+      delta.addVarEdge(e);
+    }
+  }
+  
+  public Alloc getAllocationSiteFromFlatNew(FlatNew node) {
+    return allocFactory.getAllocNode(node, false).getAllocSite();
+  }
+  void processSumHeapEdgeSet(HashMap<AllocNode, MySet<Edge>> map, Delta delta, Graph graph) {
+    MySet<Edge> edgestoadd=new MySet<Edge>();
+    MySet<Edge> edgestoremove=new MySet<Edge>();
+    for(Iterator<Map.Entry<AllocNode, MySet<Edge>>> eit=map.entrySet().iterator();eit.hasNext();) {
+      Map.Entry<AllocNode, MySet<Edge>> entry=eit.next();
+      AllocNode node=entry.getKey();
+      MySet<Edge> edgeset=entry.getValue();
+
+      for(Edge e:edgeset) {
+       Edge copy=e.copy();
+       boolean rewrite=false;
+       if (copy.src!=null&&graph.callNodeAges.contains(copy.src)) {
+         copy.src=allocFactory.getAllocNode(copy.src, true);
+         rewrite=true;
+       }
+       if (copy.dst!=null&&graph.callNodeAges.contains(copy.dst)) {
+         copy.dst=allocFactory.getAllocNode(copy.dst, true);
+         rewrite=true;
+       }
+       if (rewrite) {
+         edgestoremove.add(e);
+         edgestoadd.add(copy);
+       }
+      }
+    }
+    for(Edge e:edgestoremove) {
+      if (!graph.callerEdges.contains(e))
+       delta.removeHeapEdge(e);
+    }
+    for(Edge e:edgestoadd) {
+      delta.addHeapEdge(e);
+    }
+  }
+
+  //Handle external edges
+  void processCallExternal(Graph graph, Delta newDelta, MySet<Edge> externalEdgeSet) {
+    //Add external edges in
+    for(Edge e:externalEdgeSet) {
+      //First did we age the source
+      Edge newedge=e.copy();
+      if (newedge.src!=null&&!e.src.isSummary()&&graph.callNodeAges.contains(e.src)) {
+       AllocNode summaryNode=allocFactory.getAllocNode(newedge.src, true);
+       newedge.src=summaryNode;
+      }
+      //Compute target
+      if (graph.callNodeAges.contains(e.dst)&&!e.dst.isSummary()) {
+       if (graph.callOldNodes.contains(e.dst)) {
+         //Need two edges
+         Edge copy=newedge.copy();
+         mergeEdge(graph, newDelta, copy);
+       }
+       //Now add summarized node
+       newedge.dst=allocFactory.getAllocNode(newedge.dst, true);
+       mergeCallEdge(graph, newDelta, newedge);
+      } else {
+       //Add edge to single node
+       mergeEdge(graph, newDelta, newedge);
+      }
+    }
+  }
+
   /* This function applies callee deltas to the caller heap. */
 
   Delta applyCallDelta(Delta delta, BBlock bblock) {
@@ -683,72 +1098,94 @@ public class Pointer {
     Graph oldgraph=(ppoint.getIndex()==0)?
       bbgraphMap.get(bblock):
       graphMap.get(nodes.get(ppoint.getIndex()-1));
+    Set<FlatSESEEnterNode> seseCallers=OoOJava?taskAnalysis.getTransitiveExecutingRBlocks(fcall):null;
 
     //Age outside nodes if necessary
     for(Iterator<AllocNode> nodeit=delta.addNodeAges.iterator();nodeit.hasNext();) {
       AllocNode node=nodeit.next();
       if (!graph.callNodeAges.contains(node)) {
        graph.callNodeAges.add(node);
-      } else {
-       nodeit.remove();
+       newDelta.addNodeAges.add(node);
       }
       if (!graph.reachNode.contains(node)&&!node.isSummary()) {
        /* Need to age node in existing graph*/
        summarizeInGraph(graph, newDelta, node);
       }
+      if (graph.callNewEdges.containsKey(node)) {
+       for(Iterator<Edge> eit=graph.callNewEdges.get(node).iterator();eit.hasNext();) {
+         Edge e=eit.next();
+         if ((graph.callNodeAges.contains(e.src)||graph.reachNode.contains(e.src))&&
+             (graph.callNodeAges.contains(e.dst)||graph.reachNode.contains(e.dst))) {
+           Edge edgetoadd=e.copy();//we need our own copy to modify below
+           eit.remove();
+           if (seseCallers!=null)
+             edgetoadd.taintModify(seseCallers);
+           mergeCallEdge(graph, newDelta, edgetoadd);
+         }
+       }
+      }
     }
+
     //Add heap edges in
     for(Map.Entry<AllocNode, MySet<Edge>> entry:delta.heapedgeadd.entrySet()) {
       for(Edge e:entry.getValue()) {
        boolean addedge=false;
        Edge edgetoadd=null;
        if (e.statuspredicate==Edge.NEW) {
-         edgetoadd=e;
+         if ((graph.callNodeAges.contains(e.src)||graph.reachNode.contains(e.src))&&
+             (graph.callNodeAges.contains(e.dst)||graph.reachNode.contains(e.dst))) {
+           edgetoadd=e.copy();//we need our own copy to modify below
+         } else {
+           graph.addCallEdge(e);
+         }
        } else {
-         Edge origEdgeKey=e.makeStatus(allocFactory);
-         if (oldgraph.nodeMap.containsKey(origEdgeKey.src)&&
-             oldgraph.nodeMap.get(origEdgeKey.src).contains(origEdgeKey)) {
-           Edge origEdge=oldgraph.nodeMap.get(origEdgeKey.src).get(origEdgeKey);
-           //copy the predicate
-           origEdgeKey.statuspredicate=origEdge.statuspredicate;
-           edgetoadd=origEdgeKey;
+         Edge[] edgeArray=e.makeStatus(allocFactory);
+
+         int statuspredicate=0;
+         for(int i=0;i<edgeArray.length;i++) {
+           Edge origEdgeKey=edgeArray[i];
+           if (graph.reachEdge.contains(origEdgeKey)) {
+             Edge origEdge=graph.reachEdge.get(origEdgeKey);
+             //copy the predicate
+             statuspredicate=statuspredicate|origEdge.statuspredicate;
+           }
+           if (!graph.callOldEdges.containsKey(origEdgeKey)) {
+             graph.callOldEdges.put(origEdgeKey, new MySet<Edge>());
+           }
+           if (graph.callOldEdges.get(origEdgeKey).contains(e)) {
+             Edge olde=graph.callOldEdges.get(origEdgeKey).get(e);
+             graph.callOldEdges.get(origEdgeKey).add(olde.merge(e));
+           } else {
+             graph.callOldEdges.get(origEdgeKey).add(e);
+           }
+         }
+         if (statuspredicate!=0) {
+           Edge newe=e.copy();
+           newe.statuspredicate=statuspredicate;
+           edgetoadd=newe;
          }
        }
-       mergeEdge(graph, newDelta, edgetoadd);
-      }
-    }
-    //Add external edges in
-    for(Edge e:graph.externalEdgeSet) {
-      //First did we age the source
-      Edge newedge=e.copy();
-      if (newedge.src!=null&&!e.src.isSummary()&&graph.callNodeAges.contains(e.src)) {
-       AllocNode summaryNode=allocFactory.getAllocNode(newedge.src, true);
-       newedge.src=summaryNode;
-      }
-      //Compute target
-      if (graph.callNodeAges.contains(e.dst)&&!e.dst.isSummary()) {
-       if (graph.callOldNodes.contains(e.dst)) {
-         //Need two edges
-         Edge copy=newedge.copy();
-         mergeEdge(graph, newDelta, copy);
-       }
-       //Now add summarized node
-       newedge.dst=allocFactory.getAllocNode(newedge.dst, true);
-       mergeEdge(graph, newDelta, newedge);
-      } else {
-       //Add edge to single node
-       mergeEdge(graph, newDelta, newedge);
+       if (seseCallers!=null&&edgetoadd!=null)
+         edgetoadd.taintModify(seseCallers);
+       mergeCallEdge(graph, newDelta, edgetoadd);
       }
     }
+    
+    processCallExternal(graph, newDelta, graph.externalEdgeSet);
+
     //Add edge for return value
     if (fcall.getReturnTemp()!=null) {
       MySet<Edge> returnedge=delta.varedgeadd.get(returntmp);
       if (returnedge!=null)
        for(Edge e:returnedge) {
+         //skip the edge if types don't allow it...
+         if (!typeUtil.isSuperorType(fcall.getReturnTemp().getType(), e.dst.getType()))
+           continue;
          Edge newedge=e.copy();
          newedge.srcvar=fcall.getReturnTemp();
-         if (graph.getEdges(fcall.getReturnTemp())==null||!graph.getEdges(fcall.getReturnTemp()).contains(newedge))
-           newDelta.addEdge(newedge);
+         if (seseCallers!=null)
+           newedge.taintModify(seseCallers);
+         mergeEdge(graph, newDelta, newedge);
        }
     }
     applyDiffs(graph, newDelta);
@@ -766,6 +1203,22 @@ public class Pointer {
     }
   }
 
+  /* This is a call produced edge...need to remember this */
+
+  public void mergeCallEdge(Graph graph, Delta newDelta, Edge edgetoadd) {
+    if (edgetoadd!=null) {
+      newDelta.addEdgeClear(edgetoadd);
+
+      Edge match=graph.getMatch(edgetoadd);
+      
+      if (match==null||!match.subsumes(edgetoadd)) {
+       Edge mergededge=edgetoadd.merge(match);
+       newDelta.addEdge(mergededge);
+       graph.callerEdges.add(mergededge);
+      }
+    }
+  }
+
 
   /* Summarizes out of context nodes in graph */
   void summarizeInGraph(Graph graph, Delta newDelta, AllocNode singleNode) {
@@ -778,7 +1231,7 @@ public class Pointer {
       Edge rewrite=e.rewrite(singleNode, summaryNode);
       //Remove old edge
       newDelta.removeHeapEdge(e);
-      mergeEdge(graph, newDelta, rewrite);
+      mergeCallEdge(graph, newDelta, rewrite);
     }
     
     //Handle incoming edges
@@ -787,9 +1240,11 @@ public class Pointer {
       if (e.dst==singleNode) {
        //Need to get original edge so that predicate will be correct
        Edge match=graph.getMatch(e);
-       Edge rewrite=match.rewrite(singleNode, summaryNode);
-       newDelta.removeEdge(match);
-       mergeEdge(graph, newDelta, rewrite);
+       if (match!=null) {
+         Edge rewrite=match.rewrite(singleNode, summaryNode);
+         newDelta.removeEdge(match);
+         mergeCallEdge(graph, newDelta, rewrite);
+       }
       }
     }
   }
@@ -860,7 +1315,7 @@ public class Pointer {
        else
          graph.nodeMap.put(node, new MySet<Edge>());
       }
-      graph.nodeMap.get(node).addAll(edgestoadd);
+      Edge.mergeEdgesInto(graph.nodeMap.get(node),edgestoadd);
       if (genbackwards) {
        for(Edge eadd:edgestoadd) {
          if (!graph.backMap.containsKey(eadd.dst))
@@ -891,8 +1346,11 @@ public class Pointer {
       TempDescriptor tmp=e.getKey();
       MySet<Edge> edgestoadd=e.getValue();
       if (graph.varMap.containsKey(tmp)) {
-       graph.varMap.get(tmp).addAll(edgestoadd);
-      } else 
+       Edge.mergeEdgesInto(graph.varMap.get(tmp), edgestoadd);
+      } else if (graph.parent.varMap.containsKey(tmp)) {
+       graph.varMap.put(tmp, new MySet<Edge>(graph.parent.varMap.get(tmp)));
+       Edge.mergeEdgesInto(graph.varMap.get(tmp), edgestoadd);
+      } else
        graph.varMap.put(tmp, (MySet<Edge>) edgestoadd.clone());
       if (genbackwards) {
        for(Edge eadd:edgestoadd) {
@@ -915,6 +1373,30 @@ public class Pointer {
     }
   }
 
+  boolean isINACC(FlatNode node) {
+    if (!OoOJava)
+      return false;
+    switch(node.kind()) {
+    case FKind.FlatSetFieldNode: {
+      FlatSetFieldNode n=(FlatSetFieldNode)node;
+      return !accessible.isAccessible(n, n.getDst());
+    }
+    case FKind.FlatSetElementNode: {
+      FlatSetElementNode n=(FlatSetElementNode)node;
+      return !accessible.isAccessible(n, n.getDst());
+    }
+    case FKind.FlatFieldNode: {
+      FlatFieldNode n=(FlatFieldNode)node;
+      return !accessible.isAccessible(n, n.getSrc());
+    }
+    case FKind.FlatElementNode: {
+      FlatElementNode n=(FlatElementNode)node;
+      return !accessible.isAccessible(n, n.getSrc());
+    }
+    }
+    return false;
+  }
+
   Delta processSetFieldElementNode(FlatNode node, Delta delta, Graph graph) {
     TempDescriptor src;
     FieldDescriptor fd;
@@ -930,42 +1412,92 @@ public class Pointer {
       fd=ffn.getField();
       dst=ffn.getDst();
     }
+
     if (delta.getInit()) {
-      HashSet<AllocNode> srcNodes=GraphManip.getNodes(graph, delta, src);
-      HashSet<AllocNode> dstNodes=GraphManip.getNodes(graph, delta, dst);
-      MySet<Edge> edgesToAdd=GraphManip.genEdges(dstNodes, fd, srcNodes);
+      MySet<Edge> dstEdges=GraphManip.getEdges(graph, delta, dst);
+
+      if (OoOJava&&!accessible.isAccessible(node, dst)) {
+       Taint dstStallTaint=Taint.factory(node,  dst, AllocFactory.dummySite, null, ReachGraph.predsEmpty);
+       dstEdges=Edge.taintAll(dstEdges, dstStallTaint);
+       updateVarDelta(graph, delta, dst, dstEdges, null);
+      }
+      if (OoOJava) {
+       effectsAnalysis.analyzeFlatSetFieldNode(dstEdges, fd, node);
+      }
+
+      //Do nothing for non pointers
+      if (!src.getType().isPtr()) {
+       if (mustProcess.contains(node)) {
+         applyDiffs(graph, delta);
+       }
+       return delta;
+      }
+
+      MySet<Edge> srcEdges=GraphManip.getEdges(graph, delta, src);
+      if (OoOJava&&!accessible.isAccessible(node, src)) {
+       Taint srcStallTaint=Taint.factory(node,  src, AllocFactory.dummySite, null, ReachGraph.predsEmpty);
+       srcEdges=Edge.taintAll(srcEdges, srcStallTaint);
+       updateVarDelta(graph, delta, src, srcEdges, null);
+      }
+
+      MySet<Edge> edgesToAdd=GraphManip.genEdges(dstEdges, fd, srcEdges);
       MySet<Edge> edgesToRemove=null;
-      if (dstNodes.size()==1&&!dstNodes.iterator().next().isSummary()&&fd!=null) {
+      if (dstEdges.size()==1&&!dstEdges.iterator().next().dst.isSummary()&&fd!=null) {
        /* Can do a strong update */
-       edgesToRemove=GraphManip.getEdges(graph, delta, dstNodes, fd);
+       edgesToRemove=GraphManip.getEdges(graph, delta, dstEdges, fd);
        graph.strongUpdateSet=edgesToRemove;
       } else
        graph.strongUpdateSet=new MySet<Edge>();
+
       /* Update diff */
       updateHeapDelta(graph, delta, edgesToAdd, edgesToRemove);
       applyDiffs(graph, delta);
     } else {
-      /* First look at new sources */
+      MySet<Edge> newDstEdges=GraphManip.getDiffEdges(delta, dst);
+
+      if (OoOJava&&!accessible.isAccessible(node, dst)) {
+       Taint dstStallTaint=Taint.factory(node,  dst, AllocFactory.dummySite, null, ReachGraph.predsEmpty);
+       newDstEdges=Edge.taintAll(newDstEdges, dstStallTaint);
+       updateVarDelta(graph, delta, dst, newDstEdges, null);
+      }
+
+      if (OoOJava) {
+       effectsAnalysis.analyzeFlatSetFieldNode(newDstEdges, fd, node);
+      }
+
+      if (!src.getType().isPtr()) {
+       if (mustProcess.contains(node)) {
+         applyDiffs(graph, delta);
+       }
+       return delta;
+      }
+
+      /* Next look at new sources */
+
       MySet<Edge> edgesToAdd=new MySet<Edge>();
-      HashSet<AllocNode> newSrcNodes=GraphManip.getDiffNodes(delta, src);
-      HashSet<AllocNode> srcNodes=GraphManip.getNodes(graph, delta, src);
+      MySet<Edge> newSrcEdges=GraphManip.getDiffEdges(delta, src);
+      MySet<Edge> srcEdges=GraphManip.getEdges(graph, delta, src);
       HashSet<AllocNode> dstNodes=GraphManip.getNodes(graph, delta, dst);
-      HashSet<AllocNode> newDstNodes=GraphManip.getDiffNodes(delta, dst);
 
+      if (OoOJava&&!accessible.isAccessible(node, src)) {
+       Taint srcStallTaint=Taint.factory(node,  src, AllocFactory.dummySite, null, ReachGraph.predsEmpty);
+       newSrcEdges=Edge.taintAll(newSrcEdges, srcStallTaint);
+       updateVarDelta(graph, delta, src, newSrcEdges, null);
+      }
 
       MySet<Edge> edgesToRemove=null;
-      if (newDstNodes.size()!=0) {
+      if (newDstEdges.size()!=0) {
        if (dstNodes.size()>1&&!dstNodes.iterator().next().isSummary()&&fd!=null) {
          /* Need to undo strong update */
          if (graph.strongUpdateSet!=null) {
            edgesToAdd.addAll(graph.strongUpdateSet);
            graph.strongUpdateSet=null; //Prevent future strong updates
          }
-       } else if (dstNodes.size()==1&&newDstNodes.size()==1&&!newDstNodes.iterator().next().isSummary()&&graph.strongUpdateSet!=null&&fd!=null) {
+       } else if (dstNodes.size()==1&&newDstEdges.size()==1&&!newDstEdges.iterator().next().dst.isSummary()&&graph.strongUpdateSet!=null&&fd!=null) {
          edgesToRemove=GraphManip.getEdges(graph, delta, dstNodes, fd);
          graph.strongUpdateSet.addAll(edgesToRemove);
        }
-       edgesToAdd.addAll(GraphManip.genEdges(newDstNodes, fd, srcNodes));
+       Edge.mergeEdgesInto(edgesToAdd, GraphManip.genEdges(newDstEdges, fd, srcEdges));
       }
 
       //Kill new edges
@@ -979,7 +1511,7 @@ public class Pointer {
       }
 
       //Next look at new destinations
-      edgesToAdd.addAll(GraphManip.genEdges(dstNodes, fd, newSrcNodes));
+      Edge.mergeEdgesInto(edgesToAdd, GraphManip.genEdges(dstNodes, fd, newSrcEdges));
 
       /* Update diff */
       updateHeapDelta(graph, delta, edgesToAdd, edgesToRemove);
@@ -1010,17 +1542,17 @@ public class Pointer {
       dst=fcn.getDst();
     }
     if (delta.getInit()) {
-      HashSet<AllocNode> srcnodes=GraphManip.getNodes(graph, delta, src);
-      MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, srcnodes);
+      MySet<Edge> srcedges=GraphManip.getEdges(graph, delta, src);
+      MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, srcedges);
       MySet<Edge> edgesToRemove=GraphManip.getEdges(graph, delta, dst);
       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
       applyDiffs(graph, delta);
     } else {
       /* First compute new src nodes */
-      HashSet<AllocNode> newSrcNodes=GraphManip.getDiffNodes(delta, src);
+      MySet<Edge> newSrcEdges=GraphManip.getDiffEdges(delta, src);
 
       /* Compute the union, and then the set of edges */
-      MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, newSrcNodes);
+      MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, newSrcEdges);
       
       /* Compute set of edges to remove */
       MySet<Edge> edgesToRemove=GraphManip.getDiffEdges(delta, dst);      
@@ -1036,6 +1568,8 @@ public class Pointer {
     TempDescriptor src;
     FieldDescriptor fd;
     TempDescriptor dst;
+    TaintSet taint=null;
+
     if (node.kind()==FKind.FlatElementNode) {
       FlatElementNode fen=(FlatElementNode) node;
       src=fen.getSrc();
@@ -1047,33 +1581,65 @@ public class Pointer {
       fd=ffn.getField();
       dst=ffn.getDst();
     }
+    if (OoOJava&&!accessible.isAccessible(node, src)) {
+      taint=TaintSet.factory(Taint.factory(node,  src, AllocFactory.dummySite, null, ReachGraph.predsEmpty));
+    }
+
+    //Do nothing for non pointers
     if (delta.getInit()) {
-      HashSet<AllocNode> srcnodes=GraphManip.getNodes(graph, delta, src);
-      HashSet<AllocNode> fdnodes=GraphManip.getNodes(graph, delta, srcnodes, fd);
-      MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, fdnodes);
+      MySet<Edge> srcedges=GraphManip.getEdges(graph, delta, src);
+      if (OoOJava) {
+       if (taint!=null) {
+         srcedges=Edge.taintAll(srcedges, taint);
+         updateVarDelta(graph, delta, src, srcedges, null);
+       }
+       effectsAnalysis.analyzeFlatFieldNode(srcedges, fd, node);
+      }
+      if (!dst.getType().isPtr()) {
+       if (mustProcess.contains(node)) {
+         applyDiffs(graph, delta);
+       }
+       return delta;
+      }
+
+      MySet<Edge> edgesToAdd=GraphManip.dereference(graph, delta, dst, srcedges, fd, node);
       MySet<Edge> edgesToRemove=GraphManip.getEdges(graph, delta, dst);
+
       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
       applyDiffs(graph, delta);
     } else {
+      MySet<Edge> newsrcedges=GraphManip.getDiffEdges(delta, src);
+      if (OoOJava) {
+       if (taint!=null) {
+         newsrcedges=Edge.taintAll(newsrcedges, taint);
+         updateVarDelta(graph, delta, src, newsrcedges, null);
+       }
+       effectsAnalysis.analyzeFlatFieldNode(newsrcedges, fd, node);
+      }
+      if (!dst.getType().isPtr()) {
+       if (mustProcess.contains(node)) {
+         applyDiffs(graph, delta);
+       }
+       return delta;
+      }
       /* First compute new objects we read fields of */
-      HashSet<AllocNode> allsrcnodes=GraphManip.getNodes(graph, delta, src);
-      HashSet<AllocNode> difffdnodes=GraphManip.getDiffNodes(delta, allsrcnodes, fd);     
+      MySet<Edge> allsrcedges=GraphManip.getEdges(graph, delta, src);
+      MySet<Edge> edgesToAdd=GraphManip.diffDereference(delta, dst, allsrcedges, fd, node);
       /* Next compute new targets of fields */
-      HashSet<AllocNode> newsrcnodes=GraphManip.getDiffNodes(delta, src);
-      HashSet<AllocNode> newfdnodes=GraphManip.getNodes(graph, delta, newsrcnodes, fd);
+      MySet<Edge> newfdedges=GraphManip.dereference(graph, delta, dst, newsrcedges, fd, node);
+
       /* Compute the union, and then the set of edges */
-      HashSet<AllocNode> newTargets=new HashSet<AllocNode>();
-      newTargets.addAll(newfdnodes);
-      newTargets.addAll(difffdnodes);
-      MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, newTargets);      
+      Edge.mergeEdgesInto(edgesToAdd, newfdedges);
       
       /* Compute set of edges to remove */
       MySet<Edge> edgesToRemove=GraphManip.getDiffEdges(delta, dst);      
 
+      
       /* Update diff */
       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
       applyDiffs(graph, delta);
     }
+
     return delta;
   }
 
@@ -1081,21 +1647,31 @@ public class Pointer {
     MySet<Edge> edgeAdd=delta.varedgeadd.get(tmp);
     MySet<Edge> edgeRemove=delta.varedgeremove.get(tmp);
     MySet<Edge> existingEdges=graph.getEdges(tmp);
-    for(Edge e: edgestoRemove) {
-      //remove edge from delta
-      if (edgeAdd!=null)
-       edgeAdd.remove(e);
-      //if the edge is already in the graph, add an explicit remove to the delta
-      if (existingEdges.contains(e))
-       delta.removeVarEdge(e);
-    }
+    if (edgestoRemove!=null)
+      for(Edge e: edgestoRemove) {
+       //remove edge from delta
+       if (edgeAdd!=null)
+         edgeAdd.remove(e);
+       //if the edge is already in the graph, add an explicit remove to the delta
+       if (existingEdges.contains(e))
+         delta.removeVarEdge(e);
+      }
     for(Edge e: edgestoAdd) {
       //Remove the edge from the remove set
       if (edgeRemove!=null)
        edgeRemove.remove(e);
       //Explicitly add it to the add set unless it is already in the graph
-      if (!existingEdges.contains(e)&&typeUtil.isSuperorType(tmp.getType(),e.dst.getType()))
-       delta.addVarEdge(e);
+      if (typeUtil.isSuperorType(tmp.getType(), e.dst.getType())) {
+       if (!existingEdges.contains(e)) {
+         delta.addVarEdge(e);
+       } else {
+         //See if the old edge subsumes the new one
+         Edge olde=existingEdges.get(e);
+         if (!olde.subsumes(e)) {
+           delta.addVarEdge(olde.merge(e));
+         }
+       }
+      }
     }
   }
 
@@ -1122,8 +1698,14 @@ public class Pointer {
        if (edgeRemove!=null)
          edgeRemove.remove(e);
        //Explicitly add it to the add set unless it is already in the graph
-       if ((!existingEdges.contains(e)||!existingEdges.get(e).isNew())&&(e.fd==null||typeUtil.isSuperorType(e.fd.getType(), e.dst.getType()))) {
+       if (!existingEdges.contains(e)) {
          delta.addHeapEdge(e);
+       } else {
+         //See if the old edge subsumes the new one
+         Edge olde=existingEdges.get(e);
+         if (!olde.subsumes(e)) {
+           delta.addHeapEdge(olde.merge(e));
+         }
        }
       }
   }
@@ -1155,8 +1737,6 @@ public class Pointer {
       MySet<Edge> oldedges=graph.getEdges(tmp);
       if (!oldedges.isEmpty())
        delta.varedgeremove.put(tmp, (MySet<Edge>) oldedges);
-      //Apply incoming diffs to graph
-      applyDiffs(graph, delta);
       //Note that we create a single node
       delta.addNodeAges.add(single);
       //Kill the old node
@@ -1186,12 +1766,18 @@ public class Pointer {
        if (entrytmp==tmp) {
          /* Check is this is the tmp we overwrite, if so add to remove set */
          Util.relationUpdate(delta.varedgeremove, tmp, null, entry.getValue());
-       } else {
+       } else if (graph.varMap.containsKey(entrytmp)) {
          /* Check if the target of the edge is changed */ 
          MySet<Edge> newset=(MySet<Edge>)entry.getValue().clone();
          MySet<Edge> removeset=shrinkSet(newset, graph.varMap.get(entrytmp), single, summary);
          Util.relationUpdate(delta.varedgeremove, entrytmp, newset, removeset);
          Util.relationUpdate(delta.varedgeadd, entrytmp, null, newset);
+       } else {
+         /* Check if the target of the edge is changed */ 
+         MySet<Edge> newset=(MySet<Edge>)entry.getValue().clone();
+         MySet<Edge> removeset=shrinkSet(newset, graph.parent.varMap.get(entrytmp), single, summary);
+         Util.relationUpdate(delta.varedgeremove, entrytmp, newset, removeset);
+         Util.relationUpdate(delta.varedgeadd, entrytmp, null, newset);
        }
       }
 
@@ -1249,9 +1835,10 @@ public class Pointer {
        delta.addOldNodes.put(single, Boolean.FALSE);
       }
       
-      //Apply incoming diffs to graph
-      applyDiffs(graph, delta);      
     }
+    //Apply incoming diffs to graph
+    applyDiffs(graph, delta);      
+
     return delta;
   }
 
@@ -1380,7 +1967,6 @@ public class Pointer {
       MySet<Edge> dstedges=graph.nodeMap.get(nsrc);
       MySet<Edge> diffedges=new MySet<Edge>();
       for(Edge e:edges) {
-
        if (!dstedges.contains(e)) {
          //We have a new edge
          diffedges.add(e);
@@ -1431,6 +2017,13 @@ public class Pointer {
            //We have a new edge
            diffedges.add(e);
            dstedges.add(e);
+         } else {
+           Edge origedge=dstedges.get(e);
+           if (!origedge.subsumes(e)) {
+             Edge mergededge=origedge.merge(e);
+             diffedges.add(mergededge);
+             dstedges.add(mergededge);
+           }
          }
        }
        //Done with edge set...