50b4974cd9dc52de594b1641e7cd07b27211729e
[IRC.git] / Robust / src / Analysis / Pointer / Pointer.java
1 package Analysis.Pointer;
2 import java.util.*;
3 import IR.Flat.*;
4 import IR.*;
5 import Analysis.Liveness;
6 import Analysis.Pointer.BasicBlock.BBlock;
7 import Analysis.Pointer.AllocFactory.AllocNode;
8 import Analysis.Disjoint.Taint;
9 import Analysis.Disjoint.TaintSet;
10 import Analysis.Disjoint.Canonical;
11 import Analysis.CallGraph.CallGraph;
12 import java.io.*;
13
14 public class Pointer {
15   HashMap<FlatMethod, BasicBlock> blockMap;
16   HashMap<BBlock, Graph> bbgraphMap;
17   HashMap<FlatNode, Graph> graphMap;
18   HashMap<FlatCall, Set<BBlock>> callMap;
19   HashMap<BBlock, Set<PPoint>> returnMap;
20   HashMap<BBlock, Set<TempDescriptor>> bblivetemps;
21
22   boolean OoOJava=false;
23   CallGraph callGraph;
24   State state;
25   TypeUtil typeUtil;
26   AllocFactory allocFactory;
27   LinkedList<Delta> toprocess;
28   TempDescriptor returntmp;
29
30   public Pointer(State state, TypeUtil typeUtil, CallGraph callGraph) {
31     this(state, typeUtil);
32     this.callGraph=callGraph;
33   }
34
35   public Pointer(State state, TypeUtil typeUtil) {
36     this.state=state;
37     this.blockMap=new HashMap<FlatMethod, BasicBlock>();
38     this.bbgraphMap=new HashMap<BBlock, Graph>();
39     this.bblivetemps=new HashMap<BBlock, Set<TempDescriptor>>();
40     this.graphMap=new HashMap<FlatNode, Graph>();
41     this.callMap=new HashMap<FlatCall, Set<BBlock>>();
42     this.returnMap=new HashMap<BBlock, Set<PPoint>>();
43     this.typeUtil=typeUtil;
44     this.allocFactory=new AllocFactory(state, typeUtil);
45     this.toprocess=new LinkedList<Delta>();
46     ClassDescriptor stringcd=typeUtil.getClass(TypeUtil.ObjectClass);
47     this.returntmp=new TempDescriptor("RETURNVAL", stringcd);
48   }
49
50   public BasicBlock getBBlock(FlatMethod fm) {
51     if (!blockMap.containsKey(fm)) {
52       blockMap.put(fm, BasicBlock.getBBlock(fm));
53       Hashtable<FlatNode, Set<TempDescriptor>> livemap=Liveness.computeLiveTemps(fm);
54       for(BBlock bblock:blockMap.get(fm).getBlocks()) {
55         FlatNode fn=bblock.nodes.get(0);
56         if (fn==fm) {
57           HashSet<TempDescriptor> fmset=new HashSet<TempDescriptor>();
58           fmset.addAll((List<TempDescriptor>)Arrays.asList(fm.writesTemps()));
59           bblivetemps.put(bblock, fmset);
60         } else {
61           Set<TempDescriptor> livetemps=livemap.get(fn);
62           bblivetemps.put(bblock, livetemps);
63           livetemps.add(returntmp);
64         }
65       }
66     }
67     return blockMap.get(fm);
68   }
69   
70   Delta buildInitialContext() {
71     MethodDescriptor md=typeUtil.getMain();
72     FlatMethod fm=state.getMethodFlat(md);
73     BasicBlock bb=getBBlock(fm);
74     BBlock start=bb.getStart();
75     Delta delta=new Delta(new PPoint(start), true);
76     MySet<Edge> arrayset=new MySet<Edge>();
77     MySet<Edge> varset=new MySet<Edge>();
78     Edge arrayedge=new Edge(allocFactory.StringArray, null, allocFactory.Strings);
79     Edge stringedge=new Edge(fm.getParameter(0), allocFactory.StringArray);
80     delta.addHeapEdge(arrayedge);
81     delta.addVarEdge(stringedge);
82
83     return delta;
84   }
85
86   public void doAnalysis() {
87     toprocess.add(buildInitialContext());
88     nextdelta:
89     while(!toprocess.isEmpty()) {
90       Delta delta=toprocess.remove();
91       PPoint ppoint=delta.getBlock();
92       BBlock bblock=ppoint.getBBlock();
93       Vector<FlatNode> nodes=bblock.nodes();
94       int startindex=0;
95
96       if (ppoint.getIndex()==-1) {
97         //Build base graph for entrance to this basic block
98         //System.out.println("Processing "+bblock.nodes.get(0).toString().replace(' ','_'));
99         //delta.print();
100         delta=applyInitDelta(delta, bblock);
101         //System.out.println("Generating:");
102         //delta.print();
103       } else {
104         //System.out.println("Processing Call "+bblock.nodes.get(ppoint.getIndex()).toString().replace(' ','_'));
105         //delta.print();
106
107         startindex=ppoint.getIndex()+1;
108         delta=applyCallDelta(delta, bblock);
109         //System.out.println("Generating:");
110         //delta.print();
111       }
112       Graph graph=bbgraphMap.get(bblock);
113       Graph nodeGraph=null;
114       boolean init=delta.getInit();
115       if (!init&&delta.isEmpty())
116         continue nextdelta;
117       
118       //Compute delta at exit of each node
119       for(int i=startindex; i<nodes.size();i++) {
120         FlatNode currNode=nodes.get(i);
121         //System.out.println("Start Processing "+currNode);
122         if (!graphMap.containsKey(currNode)) {
123           if (isNEEDED(currNode))
124             graphMap.put(currNode, new Graph(graph));
125           else {
126             if (i==0) {
127               //base graph works for us
128               graphMap.put(currNode, new Graph(graph));
129             } else {
130               //just use previous graph
131               graphMap.put(currNode, graphMap.get(nodes.get(i-1)));
132             }
133           }
134         }
135         nodeGraph=graphMap.get(currNode);
136         delta=processNode(bblock, i, currNode, delta, nodeGraph);
137         //System.out.println("Processing "+currNode+" and generating delta:");
138         //delta.print();
139       }
140       generateFinalDelta(bblock, delta, nodeGraph);
141     }
142
143     //DEBUG
144     if (true) {
145       int debugindex=0;
146       for(Map.Entry<BBlock, Graph> e:bbgraphMap.entrySet()) {
147         Graph g=e.getValue();
148         plotGraph(g,"BB"+e.getKey().nodes.get(0).toString().replace(' ','_'));
149         debugindex++;
150       }
151       
152       for(FlatMethod fm:blockMap.keySet()) {
153         System.out.println(fm.printMethod());
154       }
155       for(Map.Entry<FlatNode, Graph> e:graphMap.entrySet()) {
156         FlatNode fn=e.getKey();
157         Graph g=e.getValue();
158         plotGraph(g,"FN"+fn.toString()+debugindex);
159         debugindex++;
160       } 
161     }
162   }
163
164   void plotGraph(Graph g, String name) {
165     try {
166       PrintWriter pw=new PrintWriter(new FileWriter(name.toString().replace(' ','_')+".dot"));
167       g.printGraph(pw, name);
168       pw.close();
169     } catch (Exception ex) {
170       ex.printStackTrace();
171     }
172   }
173   
174
175   /* This function builds the last delta for a basic block.  It
176    * handles the case for the first time the basic block is
177    * evaluated.*/
178
179   void buildInitDelta(Graph graph, Delta newDelta) {
180     //First compute the set of temps
181     HashSet<TempDescriptor> tmpSet=new HashSet<TempDescriptor>();
182     tmpSet.addAll(graph.varMap.keySet());
183     tmpSet.addAll(graph.parent.varMap.keySet());
184     
185     //Next build the temp map part of the delta
186     for(TempDescriptor tmp:tmpSet) {
187       MySet<Edge> edgeSet=new MySet<Edge>();
188       /* Get target set */
189       if (graph.varMap.containsKey(tmp))
190         edgeSet.addAll(graph.varMap.get(tmp));
191       else
192         edgeSet.addAll(graph.parent.varMap.get(tmp));
193       newDelta.varedgeadd.put(tmp, edgeSet);
194     }
195     
196     //Next compute the set of src allocnodes
197     HashSet<AllocNode> nodeSet=new HashSet<AllocNode>();
198     nodeSet.addAll(graph.nodeMap.keySet());
199     nodeSet.addAll(graph.parent.nodeMap.keySet());
200     
201     for(AllocNode node:nodeSet) {
202       MySet<Edge> edgeSet=new MySet<Edge>();
203       /* Get edge set */
204       if (graph.nodeMap.containsKey(node))
205         edgeSet.addAll(graph.nodeMap.get(node));
206       else
207         edgeSet.addAll(graph.parent.nodeMap.get(node));
208       newDelta.heapedgeadd.put(node, edgeSet);
209       
210       /* Compute ages */
211       if (graph.oldNodes.containsKey(node)) {
212
213       } else if (graph.parent.oldNodes.containsKey(node)) {
214         //parent graphs only contain true...no need to check
215         newDelta.addOldNodes.put(node, Boolean.TRUE);
216       }
217     }
218     
219     for(AllocNode node:graph.oldNodes.keySet()) {
220       if (graph.oldNodes.get(node).booleanValue())
221         newDelta.addOldNodes.put(node, Boolean.TRUE);
222     }
223
224     for(AllocNode node:graph.parent.oldNodes.keySet()) {
225       //make sure child doesn't override
226       if (!graph.oldNodes.containsKey(node))
227         newDelta.addOldNodes.put(node, Boolean.TRUE);
228     }
229
230     newDelta.addNodeAges.addAll(graph.nodeAges);
231     newDelta.addNodeAges.addAll(graph.parent.nodeAges);
232   }
233
234   /* This function build the delta for the exit of a basic block. */
235
236   void generateFinalDelta(BBlock bblock, Delta delta, Graph graph) {
237     Delta newDelta=new Delta(null, false);
238     if (delta.getInit()) {
239       buildInitDelta(graph, newDelta);
240     } else {
241       /* We can break the old delta...it is done being used */
242       /* First we will build variable edges */
243       HashSet<TempDescriptor> tmpSet=new HashSet<TempDescriptor>();
244       tmpSet.addAll(delta.basevaredge.keySet());
245       tmpSet.addAll(delta.varedgeadd.keySet());
246       for(TempDescriptor tmp:tmpSet) {
247         /* Start with the new incoming edges */
248         MySet<Edge> newbaseedge=delta.basevaredge.get(tmp);
249         /* Remove the remove set */
250         if (newbaseedge==null)
251           newbaseedge=new MySet<Edge>();
252         newbaseedge.removeAll(delta.varedgeremove.get(tmp));
253         /* Add in the new set*/
254         newbaseedge.addAll(delta.varedgeadd.get(tmp));
255         /* Store the results */
256         newDelta.varedgeadd.put(tmp, newbaseedge);
257       }
258       delta.basevaredge.clear();
259
260       /* Next we build heap edges */
261       HashSet<AllocNode> nodeSet=new HashSet<AllocNode>();
262       nodeSet.addAll(delta.baseheapedge.keySet());
263       nodeSet.addAll(delta.heapedgeadd.keySet());
264       nodeSet.addAll(delta.heapedgeremove.keySet());
265       for(AllocNode node:nodeSet) {
266         /* Start with the new incoming edges */
267         MySet<Edge> newheapedge=new MySet<Edge>(delta.baseheapedge.get(node));
268         /* Remove the remove set */
269         MySet<Edge> removeset=delta.heapedgeremove.get(node);
270
271         if (removeset!=null)
272           newheapedge.removeAll(removeset);
273
274         /* Add in the add set */
275         MySet<Edge> settoadd=delta.heapedgeadd.get(node);
276         if (settoadd!=null)
277           newheapedge.addAll(settoadd);
278         newDelta.heapedgeadd.put(node, newheapedge);
279
280         /* Remove the newly created edges..no need to propagate a diff for those */
281         if (removeset!=null) {
282           removeset.removeAll(delta.baseheapedge.get(node));
283           newDelta.heapedgeremove.put(node, removeset);
284         }
285       }
286
287       /* Compute new ages */
288       newDelta.addNodeAges.addAll(delta.baseNodeAges);
289       newDelta.addNodeAges.addAll(delta.addNodeAges);
290       HashSet<AllocNode> oldNodes=new HashSet<AllocNode>();
291
292       /* Compute whether old nodes survive */
293       oldNodes.addAll(delta.baseOldNodes.keySet());
294       oldNodes.addAll(delta.addOldNodes.keySet());
295       for(AllocNode node:oldNodes) {
296         if (delta.addOldNodes.containsKey(node)) {
297           if (delta.addOldNodes.get(node).booleanValue()) {
298             newDelta.addOldNodes.put(node, Boolean.TRUE);
299           }
300         } else {
301           if (delta.baseOldNodes.get(node).booleanValue()) {
302             newDelta.addOldNodes.put(node, Boolean.TRUE);
303           }
304         }
305       }
306     }
307
308     /* Now we need to propagate newdelta */
309     if (!newDelta.heapedgeadd.isEmpty()||!newDelta.heapedgeremove.isEmpty()||!newDelta.varedgeadd.isEmpty()||!newDelta.addNodeAges.isEmpty()||!newDelta.addOldNodes.isEmpty()) {
310       /* We have a delta to propagate */
311       if (returnMap.containsKey(bblock)) {
312         //exit of call block
313         boolean first=true;
314
315         for(PPoint caller:returnMap.get(bblock)) {
316           //System.out.println("Sending Return BBlock to "+caller.getBBlock().nodes.get(caller.getIndex()).toString().replace(' ','_'));
317           //newDelta.print();
318           if (first) {
319             newDelta.setBlock(caller);
320             toprocess.add(newDelta);
321             first=false;
322           } else {
323             Delta d=newDelta.diffBlock(caller);
324             toprocess.add(d);
325           }
326         }
327       } else {
328         //normal block
329         Vector<BBlock> blockvector=bblock.next();
330         for(int i=0;i<blockvector.size();i++) {
331           //System.out.println("Sending BBlock to "+blockvector.get(i).nodes.get(0).toString().replace(' ','_'));
332           //newDelta.print();
333           if (i==0) {
334             newDelta.setBlock(new PPoint(blockvector.get(i)));
335             toprocess.add(newDelta);
336           } else {
337             Delta d=newDelta.diffBlock(new PPoint(blockvector.get(i)));
338             toprocess.add(d);
339           }
340         }
341       }
342     } else {
343       //System.out.println("EMPTY DELTA");
344       //System.out.println("delta");
345       //delta.print();
346       //System.out.println("newDelta");
347       //newDelta.print();
348     }
349   }
350
351   boolean isNEEDED(FlatNode node) {
352     switch(node.kind()) {
353     case FKind.FlatSetFieldNode: {
354       FlatSetFieldNode n=(FlatSetFieldNode)node;
355       return n.getSrc().getType().isPtr();
356     }
357     case FKind.FlatSetElementNode: {
358       FlatSetElementNode n=(FlatSetElementNode)node;
359       return n.getSrc().getType().isPtr();
360     }
361     case FKind.FlatFieldNode: {
362       FlatFieldNode n=(FlatFieldNode)node;
363       return n.getDst().getType().isPtr();
364     }
365     case FKind.FlatElementNode: {
366       FlatElementNode n=(FlatElementNode)node;
367       return n.getDst().getType().isPtr();
368     }
369     }
370     return true;
371   }
372
373   Delta processNode(BBlock bblock, int index, FlatNode node, Delta delta, Graph newgraph) {
374     switch(node.kind()) {
375     case FKind.FlatNew:
376       return processNewNode((FlatNew)node, delta, newgraph);
377     case FKind.FlatFieldNode:
378     case FKind.FlatElementNode:
379       return processFieldElementNode(node, delta, newgraph);
380     case FKind.FlatCastNode:
381     case FKind.FlatOpNode:
382     case FKind.FlatReturnNode:
383       return processCopyNode(node, delta, newgraph);
384     case FKind.FlatSetFieldNode:
385     case FKind.FlatSetElementNode:
386       return processSetFieldElementNode(node, delta, newgraph);
387     case FKind.FlatSESEEnterNode:
388       return processSESEEnterNode((FlatSESEEnterNode) node, delta, newgraph);
389     case FKind.FlatSESEExitNode:
390       return processSESEExitNode((FlatSESEExitNode) node, delta, newgraph);
391     case FKind.FlatMethod:
392     case FKind.FlatExit:
393     case FKind.FlatBackEdge:
394     case FKind.FlatGenReachNode:
395       return processFlatNop(node, delta, newgraph);
396     case FKind.FlatCall:
397       return processFlatCall(bblock, index, (FlatCall) node, delta, newgraph);
398     default:
399       throw new Error("Unrecognized node:"+node);
400     }
401   }
402
403   Delta processSESEEnterNode(FlatSESEEnterNode sese, Delta delta, Graph graph) {
404     if (!OoOJava)
405       return processFlatNop(sese, delta, graph);
406     if (delta.getInit()) {
407       removeInitTaints(null, delta, graph);
408       for (TempDescriptor tmp:sese.getInVarSet()) {
409         Taint taint=Taint.factory(sese,  null, tmp, null, sese, null);
410         MySet<Edge> edges=GraphManip.getEdges(graph, delta, tmp);
411         for(Edge e:edges) {
412           Edge newe=e.addTaint(taint);
413           delta.addVarEdge(newe);
414         }
415       }
416     } else {
417       removeDiffTaints(null, delta, graph);
418       for (TempDescriptor tmp:sese.getInVarSet()) {
419         Taint taint=Taint.factory(sese,  null, tmp, null, sese, null);
420         MySet<Edge> edges=GraphManip.getDiffEdges(delta, tmp);
421         for(Edge e:edges) {
422           Edge newe=e.addTaint(taint);
423           delta.addVarEdge(newe);
424         }
425       }
426     }
427
428
429     applyDiffs(graph, delta);
430     return delta;
431   }
432   
433   private boolean isRecursive(FlatSESEEnterNode sese) {
434     MethodDescriptor md=sese.getmdEnclosing();
435     return callGraph.getCalleeSet(md).contains(md);
436   }
437
438   Delta processSESEExitNode(FlatSESEExitNode seseexit, Delta delta, Graph graph) {
439     if (!OoOJava)
440       return processFlatNop(seseexit, delta, graph);
441     FlatSESEEnterNode sese=seseexit.getFlatEnter();
442     //Strip Taints from this SESE
443     if (delta.getInit()) {
444       removeInitTaints(isRecursive(sese)?sese:null, delta, graph);
445     } else {
446       removeDiffTaints(isRecursive(sese)?sese:null, delta);
447     }
448     applyDiffs(graph, delta);
449     return delta;
450   }
451   
452   void removeDiffTaints(FlatSESEEnterNode sese, Delta delta) {
453     //Start with variable edges
454     {
455       MySet<Edge> edgestoadd=new MySet<Edge>();
456       MySet<Edge> edgestoremove=new MySet<Edge>();
457       
458       //Process base diff edges
459       processEdgeMap(sese, delta.basevaredge, null, delta.varedgeremove, edgestoremove, edgestoadd); 
460       //Process delta edges
461       processEdgeMap(sese, delta.varedgeadd, null, null, edgestoremove, edgestoadd); 
462       for(Edge e:edgestoremove) {
463         delta.removeVarEdge(e);
464       }
465       for(Edge e:edgestoadd) {
466         delta.addVarEdge(e);
467       }
468     }
469
470     //Now do heap edges
471     {
472       MySet<Edge> edgestoadd=new MySet<Edge>();
473       MySet<Edge> edgestoremove=new MySet<Edge>();
474
475       //Process base diff edges
476       processEdgeMap(sese, delta.baseheapedge, null, delta.heapedgeremove, edgestoremove, edgestoadd); 
477       //Process delta edges
478       processEdgeMap(sese, delta.heapedgeadd, null, null, edgestoremove, edgestoadd); 
479       for(Edge e:edgestoremove) {
480         delta.removeHeapEdge(e);
481       }
482       for(Edge e:edgestoadd) {
483         delta.addHeapEdge(e);
484       }
485     }
486   }
487
488   void removeInitTaints(FlatSESEEnterNode sese, Delta delta, Graph graph) {
489     //Start with variable edges
490     {
491       MySet<Edge> edgestoadd=new MySet<Edge>();
492       MySet<Edge> edgestoremove=new MySet<Edge>();
493       
494       //Process parent edges
495       processEdgeMap(sese, graph.parent.varMap, graph.varMap, delta.varedgeremove, edgestoremove, edgestoadd);
496       //Process graph edges
497       processEdgeMap(sese, graph.varMap, null, delta.varedgeremove, edgestoremove, edgestoadd); 
498       //Process delta edges
499       processEdgeMap(sese, delta.varedgeadd, null, null, edgestoremove, edgestoadd); 
500       for(Edge e:edgestoremove) {
501         delta.removeVarEdge(e);
502       }
503       for(Edge e:edgestoadd) {
504         delta.addVarEdge(e);
505       }
506     }
507
508     //Now do heap edges
509     {
510       MySet<Edge> edgestoadd=new MySet<Edge>();
511       MySet<Edge> edgestoremove=new MySet<Edge>();
512
513       //Process parent edges
514       processEdgeMap(sese, graph.parent.nodeMap, graph.nodeMap, delta.heapedgeremove, edgestoremove, edgestoadd);
515       //Process graph edges
516       processEdgeMap(sese, graph.nodeMap, null, delta.heapedgeremove, edgestoremove, edgestoadd); 
517       //Process delta edges
518       processEdgeMap(sese, delta.heapedgeadd, null, null, edgestoremove, edgestoadd); 
519       for(Edge e:edgestoremove) {
520         delta.removeHeapEdge(e);
521       }
522       for(Edge e:edgestoadd) {
523         delta.addHeapEdge(e);
524       }
525     }
526   }
527
528   void processEdgeMap(FlatSESEEnterNode sese, HashMap<?, MySet<Edge>> edgemap, HashMap<?, MySet<Edge>> childmap, HashMap<?, MySet<Edge>> removemap, MySet<Edge> edgestoremove, MySet<Edge> edgestoadd) {
529     for(Map.Entry<?, MySet<Edge>> entry:edgemap.entrySet()) {
530       //If the parent map exists and overrides this entry, skip it
531       if (childmap!=null&&childmap.containsKey(entry.getKey()))
532         continue;
533       for(Edge e:entry.getValue()) {
534         //check whether this edge has been removed
535         if (removemap==null&&removemap.containsKey(entry.getKey())&&
536             removemap.get(entry.getKey()).contains(e))
537           continue;
538         //have real edge
539         TaintSet ts=e.getTaints();
540         TaintSet newts=null;
541         //update non-null taint set
542         if (ts!=null)
543           newts=Canonical.removeInContextTaintsNP(ts, sese);
544         if (newts!=null) {
545           edgestoremove.add(e);
546           edgestoadd.add(e.changeTaintSet(newts));
547         }
548       }
549     }
550   }
551
552   void removeDiffTaints(FlatSESEEnterNode sese, Delta delta, Graph graph) {
553     
554   }
555
556   /* This function compute the edges for the this variable for a
557    * callee if it exists. */
558
559   void processThisTargets(HashSet<ClassDescriptor> targetSet, Graph graph, Delta delta, Delta newDelta, HashSet<AllocNode> nodeset, Stack<AllocNode> tovisit, MySet<Edge> edgeset, TempDescriptor tmpthis, HashSet<AllocNode> oldnodeset) {
560     //Handle the this temp
561     if (tmpthis!=null) {
562       MySet<Edge> edges=(oldnodeset!=null)?GraphManip.getDiffEdges(delta, tmpthis):GraphManip.getEdges(graph, delta, tmpthis);
563       newDelta.varedgeadd.put(tmpthis, (MySet<Edge>) edges.clone());
564       edgeset.addAll(edges);
565       for(Edge e:edges) {
566         AllocNode dstnode=e.dst;
567         if (!nodeset.contains(dstnode)&&(oldnodeset==null||!oldnodeset.contains(dstnode))) {
568           TypeDescriptor type=dstnode.getType();
569           if (!type.isArray()) {
570             targetSet.add(type.getClassDesc());
571           } else {
572             //arrays don't have code
573             targetSet.add(typeUtil.getClass(TypeUtil.ObjectClass));
574           }
575           nodeset.add(dstnode);
576           tovisit.add(dstnode);
577         }
578       }
579     }
580   }
581
582   /* This function compute the edges for a call's parameters. */
583
584   void processParams(Graph graph, Delta delta, Delta newDelta, HashSet<AllocNode> nodeset, Stack<AllocNode> tovisit, MySet<Edge> edgeset, FlatCall fcall, boolean diff) {
585     //Go through each temp
586     for(int i=0;i<fcall.numArgs();i++) {
587       TempDescriptor tmp=fcall.getArg(i);
588       MySet<Edge> edges=diff?GraphManip.getDiffEdges(delta, tmp):GraphManip.getEdges(graph, delta, tmp);
589       newDelta.varedgeadd.put(tmp, (MySet<Edge>) edges.clone());
590       edgeset.addAll(edges);
591       for(Edge e:edges) {
592         if (!nodeset.contains(e.dst)) {
593           nodeset.add(e.dst);
594           tovisit.add(e.dst);
595         }
596       }
597     }
598   }
599
600   /* This function computes the reachable nodes for a callee. */
601
602   void computeReachableNodes(Graph graph, Delta delta, Delta newDelta, HashSet<AllocNode> nodeset, Stack<AllocNode> tovisit, MySet<Edge> edgeset, HashSet<AllocNode> oldnodeset) {
603       while(!tovisit.isEmpty()) {
604         AllocNode node=tovisit.pop();
605         MySet<Edge> edges=GraphManip.getEdges(graph, delta, node);
606         if (!edges.isEmpty()) {
607           newDelta.heapedgeadd.put(node, edges);
608           edgeset.addAll(edges);
609           for(Edge e:edges) {
610             if (!nodeset.contains(e.dst)&&(oldnodeset==null||!oldnodeset.contains(e.dst))) {
611               nodeset.add(e.dst);
612               tovisit.add(e.dst);
613             }
614           }
615         }
616       }
617   }
618
619   HashSet<MethodDescriptor> computeTargets(FlatCall fcall, Delta newDelta) {
620     TempDescriptor tmpthis=fcall.getThis();
621     MethodDescriptor md=fcall.getMethod();
622     HashSet<MethodDescriptor> targets=new HashSet<MethodDescriptor>();
623     if (md.isStatic()) {
624       targets.add(md);
625     } else {
626       //Compute Edges
627       for(Edge e:newDelta.varedgeadd.get(tmpthis)) {
628         AllocNode node=e.dst;
629         ClassDescriptor cd=node.getType().getClassDesc();
630         //Figure out exact method called and add to set
631         MethodDescriptor calledmd=cd.getCalledMethod(md);
632         targets.add(calledmd);
633       }
634     }
635     return targets;
636   }
637
638   void fixMapping(FlatCall fcall, HashSet<MethodDescriptor> targets, MySet<Edge> oldedgeset, Delta newDelta, BBlock callblock, int callindex) {
639     Delta basedelta=null;
640     TempDescriptor tmpthis=fcall.getThis();
641
642     for(MethodDescriptor calledmd:targets) {
643       FlatMethod fm=state.getMethodFlat(calledmd);
644       boolean newmethod=false;
645       
646       //Build tmpMap
647       HashMap<TempDescriptor, TempDescriptor> tmpMap=new HashMap<TempDescriptor, TempDescriptor>();
648       int offset=0;
649       if(tmpthis!=null) {
650         tmpMap.put(tmpthis, fm.getParameter(offset++));
651       }
652       for(int i=0;i<fcall.numArgs();i++) {
653         TempDescriptor tmp=fcall.getArg(i);
654         tmpMap.put(tmp,fm.getParameter(i+offset));
655       }
656
657       //Get basicblock for the method
658       BasicBlock block=getBBlock(fm);
659       
660       //Hook up exits
661       if (!callMap.containsKey(fcall)) {
662         callMap.put(fcall, new HashSet<BBlock>());
663       }
664       
665       Delta returnDelta=null;
666       if (!callMap.get(fcall).contains(block.getStart())) {
667         callMap.get(fcall).add(block.getStart());
668         newmethod=true;
669         
670         //Hook up return
671         if (!returnMap.containsKey(block.getExit())) {
672           returnMap.put(block.getExit(), new HashSet<PPoint>());
673         }
674         returnMap.get(block.getExit()).add(new PPoint(callblock, callindex));
675         
676         if (bbgraphMap.containsKey(block.getExit())) {
677           //Need to push existing results to current node
678           if (returnDelta==null) {
679             returnDelta=new Delta(null, false);
680             Vector<FlatNode> exitblocknodes=block.getExit().nodes();
681             FlatExit fexit=(FlatExit)exitblocknodes.get(exitblocknodes.size()-1);
682             buildInitDelta(graphMap.get(fexit), returnDelta);
683             if (!returnDelta.heapedgeadd.isEmpty()||!returnDelta.heapedgeremove.isEmpty()||!returnDelta.varedgeadd.isEmpty()) {
684               returnDelta.setBlock(new PPoint(callblock, callindex));
685               toprocess.add(returnDelta);
686             }
687           } else {
688             if (!returnDelta.heapedgeadd.isEmpty()||!returnDelta.heapedgeremove.isEmpty()||!returnDelta.varedgeadd.isEmpty()) {
689               toprocess.add(returnDelta.diffBlock(new PPoint(callblock, callindex)));
690             }
691           }
692         }
693       }
694       
695       if (oldedgeset==null) {
696         //First build of this graph
697         //Build and enqueue delta...safe to just use existing delta
698         Delta d=newDelta.changeParams(tmpMap, new PPoint(block.getStart()));
699         //System.out.println("AProcessing "+block.getStart().nodes.get(0).toString().replace(' ','_'));
700         //d.print();
701         toprocess.add(d);
702       } else if (newmethod) {
703         if (basedelta==null) {
704           basedelta=newDelta.buildBase(oldedgeset);
705         }
706         //Build and enqueue delta
707         Delta d=basedelta.changeParams(tmpMap, new PPoint(block.getStart()));
708         //System.out.println("BProcessing "+block.getStart().nodes.get(0).toString().replace(' ','_'));
709         //d.print();
710         toprocess.add(d);
711       } else  {
712         //Build and enqueue delta
713         Delta d=newDelta.changeParams(tmpMap, new PPoint(block.getStart()));
714         //System.out.println("CProcessing "+block.getStart().nodes.get(0).toString().replace(' ','_'));
715         //d.print();
716         toprocess.add(d);
717       }
718     }
719   }
720
721
722   /* This function computes all edges that start outside of the callee
723    * context and go into the callee context */
724
725   void computeExternalEdges(Graph graph, Delta delta, HashSet<AllocNode> nodeset, HashSet<AllocNode> deltaset, MySet<Edge> externaledgeset) {
726     //Do heap edges first
727     HashSet<AllocNode> externalnodes=new HashSet<AllocNode>();
728     externalnodes.addAll(delta.baseheapedge.keySet());
729     externalnodes.addAll(delta.heapedgeadd.keySet());
730     externalnodes.addAll(delta.heapedgeremove.keySet());
731     //remove allinternal nodes
732     externalnodes.removeAll(nodeset);
733     for(AllocNode extNode:externalnodes) {
734       //Compute set of edges from given node
735       MySet<Edge> edges=new MySet<Edge>(delta.baseheapedge.get(extNode));
736       edges.removeAll(delta.heapedgeremove.get(extNode));
737       edges.addAll(delta.heapedgeadd.get(extNode));
738       
739       for(Edge e:edges) {
740         if (nodeset.contains(e.dst))
741           externaledgeset.add(e);
742       }
743     }
744
745     //Do var edges now
746     HashSet<TempDescriptor> temps=new HashSet<TempDescriptor>();
747     temps.addAll(delta.basevaredge.keySet());
748     temps.addAll(delta.varedgeadd.keySet());
749     temps.addAll(delta.varedgeremove.keySet());
750     //remove allinternal nodes
751     temps.removeAll(nodeset);
752     
753     for(TempDescriptor tmp:temps) {
754       //Compute set of edges from given node
755       MySet<Edge> edges=new MySet<Edge>(delta.basevaredge.get(tmp));
756       
757       edges.removeAll(delta.varedgeremove.get(tmp));
758       edges.addAll(delta.varedgeadd.get(tmp));
759       
760       for(Edge e:edges) {
761         if (nodeset.contains(e.dst))
762           externaledgeset.add(e);
763       }
764     }
765   }
766
767   /* This function removes the caller reachable edges from the
768    * callee's heap. */
769   
770   void removeEdges(Graph graph, Delta delta, HashSet<AllocNode> nodeset, MySet<Edge> edgeset, MySet<Edge> externaledgeset) {
771     //Want to remove the set of internal edges
772     for(Edge e:edgeset) {
773       if (e.src!=null&&!graph.callerEdges.contains(e)) {
774         delta.removeHeapEdge(e);
775       }
776     }
777
778     //Want to remove the set of external edges
779     for(Edge e:externaledgeset) {
780       //want to remove the set of internal edges
781       if (!graph.callerEdges.contains(e))
782         delta.removeEdge(e);
783     }
784   }
785
786   Delta processFlatCall(BBlock callblock, int callindex, FlatCall fcall, Delta delta, Graph graph) {
787     Delta newDelta=new Delta(null, false);
788
789     if (delta.getInit()) {
790       MySet<Edge> edgeset=new MySet<Edge>();
791       MySet<Edge> externaledgeset=new MySet<Edge>();
792       HashSet<AllocNode> nodeset=new HashSet<AllocNode>();
793       HashSet<ClassDescriptor> targetSet=new HashSet<ClassDescriptor>();
794       Stack<AllocNode> tovisit=new Stack<AllocNode>();
795       TempDescriptor tmpthis=fcall.getThis();
796       graph.callerEdges=new MySet<Edge>();
797
798       //Handle the this temp
799       processThisTargets(targetSet, graph, delta, newDelta, nodeset, tovisit, edgeset, tmpthis, null);
800
801       //Go through each temp
802       processParams(graph, delta, newDelta, nodeset, tovisit, edgeset, fcall, false);
803       
804       //Traverse all reachable nodes
805       computeReachableNodes(graph, delta, newDelta, nodeset, tovisit, edgeset, null);
806
807       //Compute call targets
808       HashSet<MethodDescriptor> newtargets=computeTargets(fcall, newDelta);
809
810       //Fix mapping
811       fixMapping(fcall, newtargets, null, newDelta, callblock, callindex);
812
813       //Compute edges into region to splice out
814       computeExternalEdges(graph, delta, nodeset, null, externaledgeset);
815
816       //Splice out internal edges
817       removeEdges(graph, delta, nodeset, edgeset, externaledgeset);
818
819       //store data structures
820       graph.externalEdgeSet=externaledgeset;
821       graph.reachNode=nodeset;
822       graph.reachEdge=edgeset;
823       
824       graph.callTargets=newtargets;
825       graph.callNodeAges=new HashSet<AllocNode>();
826       graph.callOldNodes=new HashSet<AllocNode>();
827
828       //Apply diffs to graph
829       applyDiffs(graph, delta, true);
830     } else {
831       MySet<Edge> edgeset=new MySet<Edge>();
832       MySet<Edge> externaledgeset=new MySet<Edge>();
833       HashSet<AllocNode> nodeset=new HashSet<AllocNode>();
834       MySet<Edge> oldedgeset=graph.reachEdge;
835       HashSet<AllocNode> oldnodeset=graph.reachNode;
836
837       HashSet<ClassDescriptor> targetSet=new HashSet<ClassDescriptor>();
838       Stack<AllocNode> tovisit=new Stack<AllocNode>();
839       TempDescriptor tmpthis=fcall.getThis();
840       //Fix up delta to get rid of unnecessary heap edge removals
841       for(Map.Entry<AllocNode, MySet<Edge>> entry:delta.heapedgeremove.entrySet()) {
842         for(Iterator<Edge> eit=entry.getValue().iterator();eit.hasNext();) {
843           Edge e=eit.next();
844           if (graph.callerEdges.contains(e))
845             eit.remove();
846         }
847       }
848
849       //Fix up delta to get rid of unnecessary var edge removals
850       for(Map.Entry<TempDescriptor, MySet<Edge>> entry:delta.varedgeremove.entrySet()) {
851         for(Iterator<Edge> eit=entry.getValue().iterator();eit.hasNext();) {
852           Edge e=eit.next();
853           if (graph.callerEdges.contains(e))
854             eit.remove();
855         }
856       }
857       
858       //Handle the this temp
859       processThisTargets(targetSet, graph, delta, newDelta, nodeset, tovisit, edgeset, tmpthis, oldnodeset);
860
861       //Go through each temp
862       processParams(graph, delta, newDelta, nodeset, tovisit, edgeset, fcall, true);
863       //Go through each new heap edge that starts from old node
864       MySet<Edge> newedges=GraphManip.getDiffEdges(delta, oldnodeset);
865       edgeset.addAll(newedges);
866       for(Edge e:newedges) {
867         //Add new edges that start from old node to newDelta
868         AllocNode src=e.src;
869         if (!newDelta.heapedgeadd.containsKey(src)) {
870           newDelta.heapedgeadd.put(src, new MySet<Edge>());
871         }
872         newDelta.heapedgeadd.get(src).add(e);
873         if (!nodeset.contains(e.dst)&&!oldnodeset.contains(e.dst)) {
874           nodeset.add(e.dst);
875           tovisit.add(e.dst);
876         }
877       }
878
879       //Traverse all reachable nodes
880       computeReachableNodes(graph, delta, newDelta, nodeset, tovisit, edgeset, oldnodeset);
881       //Compute call targets
882       HashSet<MethodDescriptor> newtargets=computeTargets(fcall, newDelta);
883       graph.callTargets.addAll(newtargets);
884       //add in new nodeset and edgeset
885       oldnodeset.addAll(nodeset);
886       oldedgeset.addAll(edgeset);
887       //Fix mapping
888       fixMapping(fcall, graph.callTargets, oldedgeset, newDelta, callblock, callindex);
889       //Compute edges into region to splice out
890       computeExternalEdges(graph, delta, oldnodeset, nodeset, externaledgeset);
891
892       //Splice out internal edges
893       removeEdges(graph, delta, nodeset, edgeset, externaledgeset);
894
895       //Add external edges back in
896       processCallExternal(graph, delta, externaledgeset);
897
898       //Move new edges that should be summarized
899       processSummarization(graph, delta);
900       
901       //Add in new external edges
902       graph.externalEdgeSet.addAll(externaledgeset);
903       //Apply diffs to graph
904       applyDiffs(graph, delta);
905     }
906     return delta;
907   }
908
909   void processSummarization(Graph graph, Delta delta) {
910     processSumHeapEdgeSet(delta.heapedgeadd, delta, graph);
911     processSumHeapEdgeSet(delta.baseheapedge, delta, graph);
912     processSumVarEdgeSet(delta.varedgeadd, delta, graph);
913     processSumVarEdgeSet(delta.basevaredge, delta, graph);
914   }
915
916   void processSumVarEdgeSet(HashMap<TempDescriptor, MySet<Edge>> map, Delta delta, Graph graph) {
917     MySet<Edge> edgestoadd=new MySet<Edge>();
918     MySet<Edge> edgestoremove=new MySet<Edge>();
919     for(Iterator<Map.Entry<TempDescriptor, MySet<Edge>>> eit=map.entrySet().iterator();eit.hasNext();) {
920       Map.Entry<TempDescriptor, MySet<Edge>> entry=eit.next();
921       MySet<Edge> edgeset=entry.getValue();
922
923       for(Edge e:edgeset) {
924         Edge copy=e.copy();
925         boolean rewrite=false;
926         if (copy.dst!=null&&graph.callNodeAges.contains(copy.dst)) {
927           copy.dst=allocFactory.getAllocNode(copy.dst, true);
928           rewrite=true;
929         }
930         if (rewrite) {
931           edgestoremove.add(e);
932           edgestoadd.add(copy);
933         }
934       }
935     }
936     for(Edge e:edgestoremove) {
937       delta.removeVarEdge(e);
938     }
939     for(Edge e:edgestoadd) {
940       delta.addVarEdge(e);
941     }
942   }
943   
944   void processSumHeapEdgeSet(HashMap<AllocNode, MySet<Edge>> map, Delta delta, Graph graph) {
945     MySet<Edge> edgestoadd=new MySet<Edge>();
946     MySet<Edge> edgestoremove=new MySet<Edge>();
947     for(Iterator<Map.Entry<AllocNode, MySet<Edge>>> eit=map.entrySet().iterator();eit.hasNext();) {
948       Map.Entry<AllocNode, MySet<Edge>> entry=eit.next();
949       AllocNode node=entry.getKey();
950       MySet<Edge> edgeset=entry.getValue();
951
952       for(Edge e:edgeset) {
953         Edge copy=e.copy();
954         boolean rewrite=false;
955         if (copy.src!=null&&graph.callNodeAges.contains(copy.src)) {
956           copy.src=allocFactory.getAllocNode(copy.src, true);
957           rewrite=true;
958         }
959         if (copy.dst!=null&&graph.callNodeAges.contains(copy.dst)) {
960           copy.dst=allocFactory.getAllocNode(copy.dst, true);
961           rewrite=true;
962         }
963         if (rewrite) {
964           edgestoremove.add(e);
965           edgestoadd.add(copy);
966         }
967       }
968     }
969     for(Edge e:edgestoremove) {
970       delta.removeHeapEdge(e);
971     }
972     for(Edge e:edgestoadd) {
973       delta.addHeapEdge(e);
974     }
975   }
976
977   //Handle external edges
978   void processCallExternal(Graph graph, Delta newDelta, MySet<Edge> externalEdgeSet) {
979     //Add external edges in
980     for(Edge e:externalEdgeSet) {
981       //First did we age the source
982       Edge newedge=e.copy();
983       if (newedge.src!=null&&!e.src.isSummary()&&graph.callNodeAges.contains(e.src)) {
984         AllocNode summaryNode=allocFactory.getAllocNode(newedge.src, true);
985         newedge.src=summaryNode;
986       }
987       //Compute target
988       if (graph.callNodeAges.contains(e.dst)&&!e.dst.isSummary()) {
989         if (graph.callOldNodes.contains(e.dst)) {
990           //Need two edges
991           Edge copy=newedge.copy();
992           mergeEdge(graph, newDelta, copy);
993         }
994         //Now add summarized node
995         newedge.dst=allocFactory.getAllocNode(newedge.dst, true);
996         mergeCallEdge(graph, newDelta, newedge);
997       } else {
998         //Add edge to single node
999         mergeEdge(graph, newDelta, newedge);
1000       }
1001     }
1002   }
1003
1004   /* This function applies callee deltas to the caller heap. */
1005
1006   Delta applyCallDelta(Delta delta, BBlock bblock) {
1007     Delta newDelta=new Delta(null, false);
1008     Vector<FlatNode> nodes=bblock.nodes();
1009     PPoint ppoint=delta.getBlock();
1010     FlatCall fcall=(FlatCall)nodes.get(ppoint.getIndex());
1011     Graph graph=graphMap.get(fcall);
1012     Graph oldgraph=(ppoint.getIndex()==0)?
1013       bbgraphMap.get(bblock):
1014       graphMap.get(nodes.get(ppoint.getIndex()-1));
1015
1016     //Age outside nodes if necessary
1017     for(Iterator<AllocNode> nodeit=delta.addNodeAges.iterator();nodeit.hasNext();) {
1018       AllocNode node=nodeit.next();
1019       if (!graph.callNodeAges.contains(node)) {
1020         graph.callNodeAges.add(node);
1021         newDelta.addNodeAges.add(node);
1022       }
1023       if (!graph.reachNode.contains(node)&&!node.isSummary()) {
1024         /* Need to age node in existing graph*/
1025         summarizeInGraph(graph, newDelta, node);
1026       }
1027     }
1028     //Add heap edges in
1029     for(Map.Entry<AllocNode, MySet<Edge>> entry:delta.heapedgeadd.entrySet()) {
1030       for(Edge e:entry.getValue()) {
1031         boolean addedge=false;
1032         Edge edgetoadd=null;
1033         if (e.statuspredicate==Edge.NEW) {
1034           edgetoadd=e;
1035         } else {
1036           Edge origEdgeKey=e.makeStatus(allocFactory);
1037           if (oldgraph.nodeMap.containsKey(origEdgeKey.src)&&
1038               oldgraph.nodeMap.get(origEdgeKey.src).contains(origEdgeKey)) {
1039             Edge origEdge=oldgraph.nodeMap.get(origEdgeKey.src).get(origEdgeKey);
1040             //copy the predicate
1041             origEdgeKey.statuspredicate=origEdge.statuspredicate;
1042             edgetoadd=origEdgeKey;
1043           }
1044         }
1045         mergeCallEdge(graph, newDelta, edgetoadd);
1046       }
1047     }
1048     
1049     processCallExternal(graph, newDelta, graph.externalEdgeSet);
1050
1051     //Add edge for return value
1052     if (fcall.getReturnTemp()!=null) {
1053       MySet<Edge> returnedge=delta.varedgeadd.get(returntmp);
1054       if (returnedge!=null)
1055         for(Edge e:returnedge) {
1056           Edge newedge=e.copy();
1057           newedge.srcvar=fcall.getReturnTemp();
1058           if (graph.getEdges(fcall.getReturnTemp())==null||!graph.getEdges(fcall.getReturnTemp()).contains(newedge))
1059             newDelta.addEdge(newedge);
1060         }
1061     }
1062     applyDiffs(graph, newDelta);
1063     return newDelta;
1064   }
1065   
1066   public void mergeEdge(Graph graph, Delta newDelta, Edge edgetoadd) {
1067     if (edgetoadd!=null) {
1068       Edge match=graph.getMatch(edgetoadd);
1069
1070       if (match==null||!match.subsumes(edgetoadd)) {
1071         Edge mergededge=edgetoadd.merge(match);
1072         newDelta.addEdge(mergededge);
1073       }
1074     }
1075   }
1076
1077   /* This is a call produced edge...need to remember this */
1078
1079   public void mergeCallEdge(Graph graph, Delta newDelta, Edge edgetoadd) {
1080     if (edgetoadd!=null) {
1081       Edge match=graph.getMatch(edgetoadd);
1082
1083       if (match==null||!match.subsumes(edgetoadd)) {
1084         Edge mergededge=edgetoadd.merge(match);
1085         newDelta.addEdge(mergededge);
1086         graph.callerEdges.add(mergededge);
1087         //System.out.println("ADDING: "+ mergededge);
1088       }
1089     }
1090   }
1091
1092
1093   /* Summarizes out of context nodes in graph */
1094   void summarizeInGraph(Graph graph, Delta newDelta, AllocNode singleNode) {
1095     AllocNode summaryNode=allocFactory.getAllocNode(singleNode, true);
1096
1097     //Handle outgoing heap edges
1098     MySet<Edge> edgeset=graph.getEdges(singleNode);
1099
1100     for(Edge e:edgeset) {
1101       Edge rewrite=e.rewrite(singleNode, summaryNode);
1102       //Remove old edge
1103       newDelta.removeHeapEdge(e);
1104       mergeCallEdge(graph, newDelta, rewrite);
1105     }
1106     
1107     //Handle incoming edges
1108     MySet<Edge> backedges=graph.getBackEdges(singleNode);
1109     for(Edge e:backedges) {
1110       if (e.dst==singleNode) {
1111         //Need to get original edge so that predicate will be correct
1112         Edge match=graph.getMatch(e);
1113         if (match!=null) {
1114           Edge rewrite=match.rewrite(singleNode, summaryNode);
1115           newDelta.removeEdge(match);
1116           mergeCallEdge(graph, newDelta, rewrite);
1117         }
1118       }
1119     }
1120   }
1121
1122   void applyDiffs(Graph graph, Delta delta) {
1123     applyDiffs(graph, delta, false);
1124   }
1125
1126   void applyDiffs(Graph graph, Delta delta, boolean genbackwards) {
1127     //build backwards map if requested
1128     if (genbackwards&&graph.backMap==null) {
1129       graph.backMap=new HashMap<AllocNode, MySet<Edge>>();
1130       if (graph.parent.backMap==null) {
1131         graph.parent.backMap=new HashMap<AllocNode, MySet<Edge>>();
1132         for(Map.Entry<AllocNode, MySet<Edge>> entry:graph.nodeMap.entrySet()) {
1133           for(Edge e:entry.getValue()) {
1134             if (!graph.parent.backMap.containsKey(e.dst))
1135               graph.parent.backMap.put(e.dst, new MySet<Edge>());
1136             graph.parent.backMap.get(e.dst).add(e);
1137           }
1138         }
1139         for(Map.Entry<TempDescriptor, MySet<Edge>> entry:graph.varMap.entrySet()) {
1140           for(Edge e:entry.getValue()) {
1141             if (!graph.parent.backMap.containsKey(e.dst))
1142               graph.parent.backMap.put(e.dst, new MySet<Edge>());
1143             graph.parent.backMap.get(e.dst).add(e);
1144           }
1145         }
1146       }
1147     }
1148
1149     //Add hidden base edges
1150     for(Map.Entry<AllocNode, MySet<Edge>> e: delta.baseheapedge.entrySet()) {
1151       AllocNode node=e.getKey();
1152       MySet<Edge> edges=e.getValue();
1153       if (graph.nodeMap.containsKey(node)) {
1154         MySet<Edge> nodeEdges=graph.nodeMap.get(node);
1155         nodeEdges.addAll(edges);
1156       }
1157     }
1158
1159     //Remove heap edges
1160     for(Map.Entry<AllocNode, MySet<Edge>> e: delta.heapedgeremove.entrySet()) {
1161       AllocNode node=e.getKey();
1162       MySet<Edge> edgestoremove=e.getValue();
1163       if (graph.nodeMap.containsKey(node)) {
1164         //Just apply diff to current map
1165         graph.nodeMap.get(node).removeAll(edgestoremove);
1166       } else {
1167         //Generate diff from parent graph
1168         MySet<Edge> parentedges=graph.parent.nodeMap.get(node);
1169         if (parentedges!=null) {
1170           MySet<Edge> newedgeset=Util.setSubtract(parentedges, edgestoremove);
1171           graph.nodeMap.put(node, newedgeset);
1172         }
1173       }
1174     }
1175
1176     //Add heap edges
1177     for(Map.Entry<AllocNode, MySet<Edge>> e: delta.heapedgeadd.entrySet()) {
1178       AllocNode node=e.getKey();
1179       MySet<Edge> edgestoadd=e.getValue();
1180       //If we have not done a subtract, then 
1181       if (!graph.nodeMap.containsKey(node)) {
1182         //Copy the parent entry
1183         if (graph.parent.nodeMap.containsKey(node))
1184           graph.nodeMap.put(node, (MySet<Edge>)graph.parent.nodeMap.get(node).clone());
1185         else
1186           graph.nodeMap.put(node, new MySet<Edge>());
1187       }
1188       graph.nodeMap.get(node).addAll(edgestoadd);
1189       if (genbackwards) {
1190         for(Edge eadd:edgestoadd) {
1191           if (!graph.backMap.containsKey(eadd.dst))
1192             graph.backMap.put(eadd.dst, new MySet<Edge>());
1193           graph.backMap.get(eadd.dst).add(eadd);
1194         }
1195       }
1196     }
1197
1198     //Remove var edges
1199     for(Map.Entry<TempDescriptor, MySet<Edge>> e: delta.varedgeremove.entrySet()) {
1200       TempDescriptor tmp=e.getKey();
1201       MySet<Edge> edgestoremove=e.getValue();
1202
1203       if (graph.varMap.containsKey(tmp)) {
1204         //Just apply diff to current map
1205         graph.varMap.get(tmp).removeAll(edgestoremove);
1206       } else if (graph.parent.varMap.containsKey(tmp)) {
1207         //Generate diff from parent graph
1208         MySet<Edge> parentedges=graph.parent.varMap.get(tmp);
1209         MySet<Edge> newedgeset=Util.setSubtract(parentedges, edgestoremove);
1210         graph.varMap.put(tmp, newedgeset);
1211       }
1212     }
1213
1214     //Add var edges
1215     for(Map.Entry<TempDescriptor, MySet<Edge>> e: delta.varedgeadd.entrySet()) {
1216       TempDescriptor tmp=e.getKey();
1217       MySet<Edge> edgestoadd=e.getValue();
1218       if (graph.varMap.containsKey(tmp)) {
1219         graph.varMap.get(tmp).addAll(edgestoadd);
1220       } else 
1221         graph.varMap.put(tmp, (MySet<Edge>) edgestoadd.clone());
1222       if (genbackwards) {
1223         for(Edge eadd:edgestoadd) {
1224           if (!graph.backMap.containsKey(eadd.dst))
1225             graph.backMap.put(eadd.dst, new MySet<Edge>());
1226           graph.backMap.get(eadd.dst).add(eadd);
1227         }
1228       }
1229     }
1230
1231     //Add node additions
1232     for(AllocNode node:delta.addNodeAges) {
1233       graph.nodeAges.add(node);
1234     }
1235     
1236     for(Map.Entry<AllocNode, Boolean> nodeentry:delta.addOldNodes.entrySet()) {
1237       AllocNode node=nodeentry.getKey();
1238       Boolean ispresent=nodeentry.getValue();
1239       graph.oldNodes.put(node, ispresent);
1240     }
1241   }
1242
1243   Delta processSetFieldElementNode(FlatNode node, Delta delta, Graph graph) {
1244     TempDescriptor src;
1245     FieldDescriptor fd;
1246     TempDescriptor dst;
1247     if (node.kind()==FKind.FlatSetElementNode) {
1248       FlatSetElementNode fen=(FlatSetElementNode) node;
1249       src=fen.getSrc();
1250       fd=null;
1251       dst=fen.getDst();
1252     } else {
1253       FlatSetFieldNode ffn=(FlatSetFieldNode) node;
1254       src=ffn.getSrc();
1255       fd=ffn.getField();
1256       dst=ffn.getDst();
1257     }
1258     //Do nothing for non pointers
1259     if (!src.getType().isPtr())
1260       return delta;
1261
1262     if (delta.getInit()) {
1263       HashSet<AllocNode> srcNodes=GraphManip.getNodes(graph, delta, src);
1264       HashSet<AllocNode> dstNodes=GraphManip.getNodes(graph, delta, dst);
1265       MySet<Edge> edgesToAdd=GraphManip.genEdges(dstNodes, fd, srcNodes);
1266       MySet<Edge> edgesToRemove=null;
1267       if (dstNodes.size()==1&&!dstNodes.iterator().next().isSummary()&&fd!=null) {
1268         /* Can do a strong update */
1269         edgesToRemove=GraphManip.getEdges(graph, delta, dstNodes, fd);
1270         graph.strongUpdateSet=edgesToRemove;
1271       } else
1272         graph.strongUpdateSet=new MySet<Edge>();
1273       /* Update diff */
1274       updateHeapDelta(graph, delta, edgesToAdd, edgesToRemove);
1275       applyDiffs(graph, delta);
1276     } else {
1277       /* First look at new sources */
1278       MySet<Edge> edgesToAdd=new MySet<Edge>();
1279       HashSet<AllocNode> newSrcNodes=GraphManip.getDiffNodes(delta, src);
1280       HashSet<AllocNode> srcNodes=GraphManip.getNodes(graph, delta, src);
1281       HashSet<AllocNode> dstNodes=GraphManip.getNodes(graph, delta, dst);
1282       HashSet<AllocNode> newDstNodes=GraphManip.getDiffNodes(delta, dst);
1283
1284
1285       MySet<Edge> edgesToRemove=null;
1286       if (newDstNodes.size()!=0) {
1287         if (dstNodes.size()>1&&!dstNodes.iterator().next().isSummary()&&fd!=null) {
1288           /* Need to undo strong update */
1289           if (graph.strongUpdateSet!=null) {
1290             edgesToAdd.addAll(graph.strongUpdateSet);
1291             graph.strongUpdateSet=null; //Prevent future strong updates
1292           }
1293         } else if (dstNodes.size()==1&&newDstNodes.size()==1&&!newDstNodes.iterator().next().isSummary()&&graph.strongUpdateSet!=null&&fd!=null) {
1294           edgesToRemove=GraphManip.getEdges(graph, delta, dstNodes, fd);
1295           graph.strongUpdateSet.addAll(edgesToRemove);
1296         }
1297         edgesToAdd.addAll(GraphManip.genEdges(newDstNodes, fd, srcNodes));
1298       }
1299
1300       //Kill new edges
1301       if (graph.strongUpdateSet!=null&&fd!=null) {
1302         MySet<Edge> otherEdgesToRemove=GraphManip.getDiffEdges(delta, dstNodes, fd);
1303         if (edgesToRemove!=null)
1304           edgesToRemove.addAll(otherEdgesToRemove);
1305         else
1306           edgesToRemove=otherEdgesToRemove;
1307         graph.strongUpdateSet.addAll(otherEdgesToRemove);
1308       }
1309
1310       //Next look at new destinations
1311       edgesToAdd.addAll(GraphManip.genEdges(dstNodes, fd, newSrcNodes));
1312
1313       /* Update diff */
1314       updateHeapDelta(graph, delta, edgesToAdd, edgesToRemove);
1315       applyDiffs(graph, delta);
1316     }
1317     return delta;
1318   }
1319
1320   Delta processCopyNode(FlatNode node, Delta delta, Graph graph) {
1321     TempDescriptor src;
1322     TempDescriptor dst;
1323     if (node.kind()==FKind.FlatOpNode) {
1324       FlatOpNode fon=(FlatOpNode) node;
1325       src=fon.getLeft();
1326       dst=fon.getDest();
1327     } else if (node.kind()==FKind.FlatReturnNode) {
1328       FlatReturnNode frn=(FlatReturnNode)node;
1329       src=frn.getReturnTemp();
1330       dst=returntmp;
1331       if (src==null||!src.getType().isPtr()) {
1332         //This is a NOP
1333         applyDiffs(graph, delta);
1334         return delta;
1335       }
1336     } else {
1337       FlatCastNode fcn=(FlatCastNode) node;
1338       src=fcn.getSrc();
1339       dst=fcn.getDst();
1340     }
1341     if (delta.getInit()) {
1342       HashSet<AllocNode> srcnodes=GraphManip.getNodes(graph, delta, src);
1343       MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, srcnodes);
1344       MySet<Edge> edgesToRemove=GraphManip.getEdges(graph, delta, dst);
1345       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
1346       applyDiffs(graph, delta);
1347     } else {
1348       /* First compute new src nodes */
1349       HashSet<AllocNode> newSrcNodes=GraphManip.getDiffNodes(delta, src);
1350
1351       /* Compute the union, and then the set of edges */
1352       MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, newSrcNodes);
1353       
1354       /* Compute set of edges to remove */
1355       MySet<Edge> edgesToRemove=GraphManip.getDiffEdges(delta, dst);      
1356
1357       /* Update diff */
1358       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
1359       applyDiffs(graph, delta);
1360     }
1361     return delta;
1362   }
1363
1364   Delta processFieldElementNode(FlatNode node, Delta delta, Graph graph) {
1365     TempDescriptor src;
1366     FieldDescriptor fd;
1367     TempDescriptor dst;
1368     if (node.kind()==FKind.FlatElementNode) {
1369       FlatElementNode fen=(FlatElementNode) node;
1370       src=fen.getSrc();
1371       fd=null;
1372       dst=fen.getDst();
1373     } else {
1374       FlatFieldNode ffn=(FlatFieldNode) node;
1375       src=ffn.getSrc();
1376       fd=ffn.getField();
1377       dst=ffn.getDst();
1378     }
1379     //Do nothing for non pointers
1380     if (!dst.getType().isPtr())
1381       return delta;
1382     if (delta.getInit()) {
1383       HashSet<AllocNode> srcnodes=GraphManip.getNodes(graph, delta, src);
1384       HashSet<AllocNode> fdnodes=GraphManip.getNodes(graph, delta, srcnodes, fd);
1385       MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, fdnodes);
1386       MySet<Edge> edgesToRemove=GraphManip.getEdges(graph, delta, dst);
1387       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
1388       applyDiffs(graph, delta);
1389     } else {
1390       /* First compute new objects we read fields of */
1391       HashSet<AllocNode> allsrcnodes=GraphManip.getNodes(graph, delta, src);
1392       HashSet<AllocNode> difffdnodes=GraphManip.getDiffNodes(delta, allsrcnodes, fd);     
1393       /* Next compute new targets of fields */
1394       HashSet<AllocNode> newsrcnodes=GraphManip.getDiffNodes(delta, src);
1395       HashSet<AllocNode> newfdnodes=GraphManip.getNodes(graph, delta, newsrcnodes, fd);
1396       /* Compute the union, and then the set of edges */
1397       HashSet<AllocNode> newTargets=new HashSet<AllocNode>();
1398       newTargets.addAll(newfdnodes);
1399       newTargets.addAll(difffdnodes);
1400       MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, newTargets);      
1401       
1402       /* Compute set of edges to remove */
1403       MySet<Edge> edgesToRemove=GraphManip.getDiffEdges(delta, dst);      
1404
1405       /* Update diff */
1406       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
1407       applyDiffs(graph, delta);
1408     }
1409     return delta;
1410   }
1411
1412   void updateVarDelta(Graph graph, Delta delta, TempDescriptor tmp, MySet<Edge> edgestoAdd, MySet<Edge> edgestoRemove) {
1413     MySet<Edge> edgeAdd=delta.varedgeadd.get(tmp);
1414     MySet<Edge> edgeRemove=delta.varedgeremove.get(tmp);
1415     MySet<Edge> existingEdges=graph.getEdges(tmp);
1416     for(Edge e: edgestoRemove) {
1417       //remove edge from delta
1418       if (edgeAdd!=null)
1419         edgeAdd.remove(e);
1420       //if the edge is already in the graph, add an explicit remove to the delta
1421       if (existingEdges.contains(e))
1422         delta.removeVarEdge(e);
1423     }
1424     for(Edge e: edgestoAdd) {
1425       //Remove the edge from the remove set
1426       if (edgeRemove!=null)
1427         edgeRemove.remove(e);
1428       //Explicitly add it to the add set unless it is already in the graph
1429       if (!existingEdges.contains(e)&&typeUtil.isSuperorType(tmp.getType(),e.dst.getType()))
1430         delta.addVarEdge(e);
1431     }
1432   }
1433
1434   void updateHeapDelta(Graph graph, Delta delta, MySet<Edge> edgestoAdd, MySet<Edge> edgestoRemove) {
1435     if (edgestoRemove!=null)
1436       for(Edge e: edgestoRemove) {
1437         AllocNode src=e.src;
1438         MySet<Edge> edgeAdd=delta.heapedgeadd.get(src);
1439         MySet<Edge> existingEdges=graph.getEdges(src);
1440         //remove edge from delta
1441         if (edgeAdd!=null)
1442           edgeAdd.remove(e);
1443         //if the edge is already in the graph, add an explicit remove to the delta
1444         if (existingEdges.contains(e)) {
1445           delta.removeHeapEdge(e);
1446         }
1447       }
1448     if (edgestoAdd!=null)
1449       for(Edge e: edgestoAdd) {
1450         AllocNode src=e.src;
1451         MySet<Edge> edgeRemove=delta.heapedgeremove.get(src);
1452         MySet<Edge> existingEdges=graph.getEdges(src);
1453         //Remove the edge from the remove set
1454         if (edgeRemove!=null)
1455           edgeRemove.remove(e);
1456         //Explicitly add it to the add set unless it is already in the graph
1457         if (!existingEdges.contains(e)||!existingEdges.get(e).isNew()) {
1458           delta.addHeapEdge(e);
1459         }
1460       }
1461   }
1462
1463   Delta processFlatNop(FlatNode node, Delta delta, Graph graph) {
1464     applyDiffs(graph, delta);
1465     return delta;
1466   }
1467   
1468   Delta processNewNode(FlatNew node, Delta delta, Graph graph) {
1469     AllocNode summary=allocFactory.getAllocNode(node, true);
1470     AllocNode single=allocFactory.getAllocNode(node, false);
1471     TempDescriptor tmp=node.getDst();
1472
1473     if (delta.getInit()) {
1474       /* We don't have to deal with summarization here...  The
1475        * intuition is that this is the only place where we generate
1476        * nodes for this allocation site and this is the first time
1477        * we've analyzed this site */
1478
1479       //Build new Edge
1480       Edge e=new Edge(tmp, single);
1481       //Build new Edge set
1482       MySet<Edge> newedges=new MySet<Edge>();
1483       newedges.add(e);
1484       //Add it into the diffs
1485       delta.varedgeadd.put(tmp, newedges);
1486       //Remove the old edges
1487       MySet<Edge> oldedges=graph.getEdges(tmp);
1488       if (!oldedges.isEmpty())
1489         delta.varedgeremove.put(tmp, (MySet<Edge>) oldedges);
1490       //Apply incoming diffs to graph
1491       applyDiffs(graph, delta);
1492       //Note that we create a single node
1493       delta.addNodeAges.add(single);
1494       //Kill the old node
1495       if (delta.addOldNodes.containsKey(single)||delta.baseOldNodes.containsKey(single)) {
1496         delta.addOldNodes.put(single, Boolean.FALSE);
1497       }
1498     } else {
1499       /* 1. Fix up the variable edge additions */
1500
1501       for(Iterator<Map.Entry<TempDescriptor, MySet<Edge>>> entryIt=delta.varedgeadd.entrySet().iterator();entryIt.hasNext();) {
1502         Map.Entry<TempDescriptor, MySet<Edge>> entry=entryIt.next();
1503
1504         if (entry.getKey()==tmp) {
1505           /* Check if this is the tmp we overwrite */
1506           entryIt.remove();
1507         } else {
1508           /* Otherwise, check if the target of the edge is changed... */
1509           summarizeSet(entry.getValue(), graph.varMap.get(entry.getKey()), single, summary);
1510         }
1511       }
1512       
1513       /* 2. Fix up the base variable edges */
1514
1515       for(Iterator<Map.Entry<TempDescriptor, MySet<Edge>>> entryIt=delta.basevaredge.entrySet().iterator();entryIt.hasNext();) {
1516         Map.Entry<TempDescriptor, MySet<Edge>> entry=entryIt.next();
1517         TempDescriptor entrytmp=entry.getKey();
1518         if (entrytmp==tmp) {
1519           /* Check is this is the tmp we overwrite, if so add to remove set */
1520           Util.relationUpdate(delta.varedgeremove, tmp, null, entry.getValue());
1521         } else {
1522           /* Check if the target of the edge is changed */ 
1523           MySet<Edge> newset=(MySet<Edge>)entry.getValue().clone();
1524           MySet<Edge> removeset=shrinkSet(newset, graph.varMap.get(entrytmp), single, summary);
1525           Util.relationUpdate(delta.varedgeremove, entrytmp, newset, removeset);
1526           Util.relationUpdate(delta.varedgeadd, entrytmp, null, newset);
1527         }
1528       }
1529
1530
1531       /* 3. Fix up heap edge additions */
1532
1533       HashMap<AllocNode, MySet<Edge>> addheapedge=new HashMap<AllocNode, MySet<Edge>>();
1534       for(Iterator<Map.Entry<AllocNode, MySet<Edge>>> entryIt=delta.heapedgeadd.entrySet().iterator();entryIt.hasNext();) {
1535         Map.Entry<AllocNode, MySet<Edge>> entry=entryIt.next();
1536         MySet<Edge> edgeset=entry.getValue();
1537         AllocNode allocnode=entry.getKey();
1538         if (allocnode==single) {
1539           entryIt.remove();
1540           summarizeSet(edgeset, graph.nodeMap.get(summary), single, summary);
1541           addheapedge.put(summary, edgeset);
1542         } else {
1543           summarizeSet(edgeset, graph.nodeMap.get(allocnode), single, summary);
1544         }
1545       }
1546       
1547       /* Merge in diffs */
1548
1549       for(Map.Entry<AllocNode, MySet<Edge>> entry:addheapedge.entrySet()) {
1550         AllocNode allocnode=entry.getKey();
1551         Util.relationUpdate(delta.heapedgeadd, allocnode, null, entry.getValue());
1552       }
1553
1554       /* 4. Fix up the base heap edges */
1555
1556       for(Iterator<Map.Entry<AllocNode, MySet<Edge>>> entryIt=delta.baseheapedge.entrySet().iterator();entryIt.hasNext();) {
1557         Map.Entry<AllocNode, MySet<Edge>> entry=entryIt.next();
1558         MySet<Edge> edgeset=entry.getValue();
1559         AllocNode allocnode=entry.getKey();
1560         if (allocnode==single) {
1561           entryIt.remove();
1562         }
1563         AllocNode addnode=(allocnode==single)?summary:allocnode;
1564
1565         MySet<Edge> newset=(MySet<Edge>) edgeset.clone();
1566         MySet<Edge> removeset=shrinkSet(newset, graph.nodeMap.get(addnode), single, summary);
1567         Util.relationUpdate(delta.heapedgeadd, addnode, null, newset);
1568         Util.relationUpdate(delta.heapedgeremove, allocnode, null, removeset);
1569       }
1570
1571       /* Update Node Ages...If the base or addNodeAges set contains a
1572        * single node, it now should also contain a summary node...  No
1573        * need to generate a single node as that has already been
1574        * done. */
1575       if (delta.baseNodeAges.contains(single)||delta.addNodeAges.contains(single)) {
1576         delta.addNodeAges.add(summary);
1577       }
1578
1579       //Kill the old node if someone tries to add it
1580       if (delta.addOldNodes.containsKey(single)||delta.baseOldNodes.containsKey(single)) {
1581         delta.addOldNodes.put(single, Boolean.FALSE);
1582       }
1583       
1584       //Apply incoming diffs to graph
1585       applyDiffs(graph, delta);      
1586     }
1587     return delta;
1588   }
1589
1590   /* This function builds a new edge set where oldnode is summarized into new node */
1591
1592   void summarizeSet(MySet<Edge> edgeset, MySet<Edge> oldedgeset, AllocNode oldnode, AllocNode sumnode) {
1593     MySet<Edge> newSet=null;
1594     for(Iterator<Edge> edgeit=edgeset.iterator();edgeit.hasNext();) {
1595       Edge e=edgeit.next();
1596       if (e.dst==oldnode||e.src==oldnode) {
1597         if (newSet==null) {
1598           newSet=new MySet<Edge>();
1599         }
1600         edgeit.remove();
1601         e=e.copy();
1602
1603         if (e.dst==oldnode) {
1604           e.dst=sumnode;
1605         }
1606         if (e.src==oldnode) {
1607           e.src=sumnode;
1608         }
1609         if (oldedgeset==null||!oldedgeset.contains(e))
1610           newSet.add(e);
1611       }
1612     }
1613     if (newSet!=null)
1614       edgeset.addAll(newSet);
1615   }
1616
1617   /* Shrinks the incoming set to just include rewritten values.
1618    * Returns a set of the original rewritten values */
1619
1620   MySet<Edge> shrinkSet(MySet<Edge> edgeset, MySet<Edge> oldedgeset, AllocNode oldnode, AllocNode newnode) {
1621     MySet<Edge> newSet=null;
1622     MySet<Edge> removeSet=null;
1623     for(Iterator<Edge> edgeit=edgeset.iterator();edgeit.hasNext();) {
1624       Edge e=edgeit.next();
1625       edgeit.remove();
1626       if (e.dst==oldnode||e.src==oldnode) {
1627         if (newSet==null) {
1628           newSet=new MySet<Edge>();
1629           removeSet=new MySet<Edge>();
1630         }
1631
1632         removeSet.add(e);
1633         e=e.copy();
1634         if (e.dst==oldnode)
1635           e.dst=newnode;
1636         if (e.src==oldnode)
1637           e.src=newnode;
1638         if (oldedgeset==null||!oldedgeset.contains(e))
1639           newSet.add(e);
1640       }
1641     }
1642     if (newSet!=null)
1643       edgeset.addAll(newSet);
1644     return removeSet;
1645   } 
1646
1647   /* This function returns a completely new Delta...  It is safe to
1648    * modify this */
1649
1650   Delta applyInitDelta(Delta delta, BBlock block) {
1651     //Apply delta to graph
1652     boolean newGraph=false;
1653     if (!bbgraphMap.containsKey(block)) {
1654       bbgraphMap.put(block, new Graph(null));
1655       newGraph=true;
1656     }
1657     Graph graph=bbgraphMap.get(block);
1658
1659     if (newGraph) {
1660       Delta newdelta=new Delta(null, true);
1661       //Add in heap edges and throw away original diff
1662
1663       for(Map.Entry<AllocNode, MySet<Edge>> entry:delta.heapedgeadd.entrySet()) {
1664         graph.nodeMap.put(entry.getKey(), new MySet<Edge>(entry.getValue()));
1665       }
1666       //Add in var edges and throw away original diff
1667       Set<TempDescriptor> livetemps=bblivetemps.get(block);
1668
1669       for(Map.Entry<TempDescriptor, MySet<Edge>> entry:delta.varedgeadd.entrySet()) {
1670         if (livetemps.contains(entry.getKey()))
1671           graph.varMap.put(entry.getKey(), new MySet<Edge>(entry.getValue()));
1672       }
1673       //Record that this is initial set...
1674       graph.nodeAges.addAll(delta.addNodeAges);
1675       //Add old nodes
1676       for(Map.Entry<AllocNode, Boolean> oldentry:delta.addOldNodes.entrySet()) {
1677         if (oldentry.getValue().booleanValue()) {
1678           graph.oldNodes.put(oldentry.getKey(), Boolean.TRUE);
1679         }
1680       }
1681       return newdelta;
1682     } else {
1683       Delta newdelta=new Delta(null, false);
1684       //merge in heap edges and variables
1685       mergeHeapEdges(graph, delta, newdelta);
1686       mergeVarEdges(graph, delta, newdelta, block);
1687       mergeAges(graph, delta, newdelta);
1688       return newdelta;
1689     }
1690   }
1691
1692   /* This function merges in the heap edges.  It updates delta to be
1693    * the difference */
1694
1695   void mergeHeapEdges(Graph graph, Delta delta, Delta newdelta) {
1696     //Merge in edges
1697     for(Map.Entry<AllocNode, MySet<Edge>> heapedge:delta.heapedgeadd.entrySet()) {
1698       AllocNode nsrc=heapedge.getKey();
1699       MySet<Edge> edges=heapedge.getValue();
1700
1701       if (graph.backMap!=null) {
1702         for(Edge e:edges) {
1703           if (!graph.backMap.containsKey(e.dst))
1704             graph.backMap.put(e.dst, new MySet<Edge>());
1705           graph.backMap.get(e.dst).add(e);
1706         }
1707       }
1708
1709       if (!graph.nodeMap.containsKey(nsrc)) {
1710         graph.nodeMap.put(nsrc, new MySet<Edge>());
1711       }
1712       MySet<Edge> dstedges=graph.nodeMap.get(nsrc);
1713       MySet<Edge> diffedges=new MySet<Edge>();
1714       for(Edge e:edges) {
1715         if (!dstedges.contains(e)) {
1716           //We have a new edge
1717           diffedges.add(e);
1718           dstedges.add(e);
1719         } else {
1720           Edge origedge=dstedges.get(e);
1721           if (!origedge.subsumes(e)) {
1722             Edge mergededge=origedge.merge(e);
1723             diffedges.add(mergededge);
1724             dstedges.add(mergededge);
1725           }
1726         }
1727       }
1728       //Done with edge set...
1729       if (diffedges.size()>0) {
1730         //completely new
1731         newdelta.baseheapedge.put(nsrc, diffedges);
1732       }
1733     }
1734   }
1735
1736   /* This function merges in the var edges.  It updates delta to be
1737    * the difference */
1738
1739   void mergeVarEdges(Graph graph, Delta delta, Delta newdelta, BBlock block) {
1740     //Merge in edges
1741     Set<TempDescriptor> livetemps=bblivetemps.get(block);
1742     
1743     for(Map.Entry<TempDescriptor, MySet<Edge>> varedge:delta.varedgeadd.entrySet()) {
1744       TempDescriptor tmpsrc=varedge.getKey();
1745       if (livetemps.contains(tmpsrc)) {
1746         MySet<Edge> edges=varedge.getValue();
1747         if (graph.backMap!=null) {
1748           for(Edge e:edges) {
1749             if (!graph.backMap.containsKey(e.dst))
1750               graph.backMap.put(e.dst, new MySet<Edge>());
1751             graph.backMap.get(e.dst).add(e);
1752           }
1753         }
1754         
1755         if (!graph.varMap.containsKey(tmpsrc)) {
1756           graph.varMap.put(tmpsrc, new MySet<Edge>());
1757         }
1758         MySet<Edge> dstedges=graph.varMap.get(tmpsrc);
1759         MySet<Edge> diffedges=new MySet<Edge>();
1760         for(Edge e:edges) {
1761           if (!dstedges.contains(e)) {
1762             //We have a new edge
1763             diffedges.add(e);
1764             dstedges.add(e);
1765           }
1766         }
1767         //Done with edge set...
1768         if (diffedges.size()>0) {
1769           //completely new
1770           newdelta.basevaredge.put(tmpsrc,diffedges);
1771         }
1772       }
1773     }
1774   }
1775
1776   void mergeAges(Graph graph, Delta delta, Delta newDelta) {
1777     //Merge in edges
1778     for(AllocNode node:delta.addNodeAges) {
1779       if (!graph.nodeAges.contains(node)) {
1780         graph.nodeAges.add(node);
1781         newDelta.baseNodeAges.add(node);
1782       }
1783     }
1784     for(Map.Entry<AllocNode, Boolean> oldentry:delta.addOldNodes.entrySet()) {
1785       AllocNode node=oldentry.getKey();
1786       boolean ispresent=oldentry.getValue().booleanValue();
1787       if (ispresent&&!graph.oldNodes.containsKey(node)) {
1788         graph.oldNodes.put(node, Boolean.TRUE);
1789         newDelta.baseOldNodes.put(node, Boolean.TRUE);
1790       }
1791     }
1792   }
1793 }