even more bug fixes...3 test cases work
[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.Pointer.BasicBlock.BBlock;
6 import Analysis.Pointer.AllocFactory.AllocNode;
7 import java.io.*;
8
9 public class Pointer {
10   HashMap<FlatMethod, BasicBlock> blockMap;
11   HashMap<BBlock, Graph> bbgraphMap;
12   HashMap<FlatNode, Graph> graphMap;
13   HashMap<FlatCall, Set<BBlock>> callMap;
14   HashMap<BBlock, Set<PPoint>> returnMap;
15
16   State state;
17   TypeUtil typeUtil;
18   AllocFactory allocFactory;
19   LinkedList<Delta> toprocess;
20   TempDescriptor returntmp;
21
22   public Pointer(State state, TypeUtil typeUtil) {
23     this.state=state;
24     this.blockMap=new HashMap<FlatMethod, BasicBlock>();
25     this.bbgraphMap=new HashMap<BBlock, Graph>();
26     this.graphMap=new HashMap<FlatNode, Graph>();
27     this.callMap=new HashMap<FlatCall, Set<BBlock>>();
28     this.returnMap=new HashMap<BBlock, Set<PPoint>>();
29     this.typeUtil=typeUtil;
30     this.allocFactory=new AllocFactory(state, typeUtil);
31     this.toprocess=new LinkedList<Delta>();
32     ClassDescriptor stringcd=typeUtil.getClass(TypeUtil.ObjectClass);
33     this.returntmp=new TempDescriptor("RETURNVAL", stringcd);
34   }
35
36   public BasicBlock getBBlock(FlatMethod fm) {
37     if (!blockMap.containsKey(fm))
38       blockMap.put(fm, BasicBlock.getBBlock(fm));
39     return blockMap.get(fm);
40   }
41   
42   Delta buildInitialContext() {
43     MethodDescriptor md=typeUtil.getMain();
44     FlatMethod fm=state.getMethodFlat(md);
45     BasicBlock bb=getBBlock(fm);
46     BBlock start=bb.getStart();
47     Delta delta=new Delta(new PPoint(start), true);
48     MySet<Edge> arrayset=new MySet<Edge>();
49     MySet<Edge> varset=new MySet<Edge>();
50     Edge arrayedge=new Edge(allocFactory.StringArray, null, allocFactory.Strings);
51     Edge stringedge=new Edge(fm.getParameter(0), allocFactory.StringArray);
52     delta.addHeapEdge(arrayedge);
53     delta.addVarEdge(stringedge);
54
55     return delta;
56   }
57
58   public void doAnalysis() {
59     toprocess.add(buildInitialContext());
60
61     while(!toprocess.isEmpty()) {
62       Delta delta=toprocess.remove();
63       PPoint ppoint=delta.getBlock();
64       BBlock bblock=ppoint.getBBlock();
65       Vector<FlatNode> nodes=bblock.nodes();
66       int startindex=0;
67       if (ppoint.getIndex()==-1) {
68         //Build base graph for entrance to this basic block
69         delta=applyInitDelta(delta, bblock);
70       } else {
71         startindex=ppoint.getIndex()+1;
72         delta=applyCallDelta(delta, bblock);
73       }
74       Graph graph=bbgraphMap.get(bblock);
75       Graph nodeGraph=null;
76       //Compute delta at exit of each node
77       for(int i=startindex; i<nodes.size();i++) {
78         FlatNode currNode=nodes.get(i);
79         if (!graphMap.containsKey(currNode)) {
80           graphMap.put(currNode, new Graph(graph));
81         }
82         nodeGraph=graphMap.get(currNode);
83         delta=processNode(bblock, i, currNode, delta, nodeGraph);
84       }
85       generateFinalDelta(bblock, delta, nodeGraph);
86     }
87
88     //DEBUG
89     int debugindex=0;
90     for(Map.Entry<BBlock, Graph> e:bbgraphMap.entrySet()) {
91       Graph g=e.getValue();
92       try {
93         PrintWriter pw=new PrintWriter(new FileWriter("BB"+debugindex+".dot"));
94         g.printGraph(pw, "BB");
95         pw.close();
96       } catch (Exception ex) {
97         ex.printStackTrace();
98       }
99       debugindex++;
100     }
101
102     for(Map.Entry<FlatNode, Graph> e:graphMap.entrySet()) {
103       FlatNode fn=e.getKey();
104       Graph g=e.getValue();
105       try {
106         PrintWriter pw=new PrintWriter(new FileWriter("FN"+fn.toString().replace(' ','_')+".dot"));
107         g.printGraph(pw, fn.toString());
108         pw.close();
109       } catch (Exception ex) {
110         ex.printStackTrace();
111       }
112       debugindex++;
113     }
114     for(FlatMethod fm:blockMap.keySet()) {
115       fm.printMethod();
116     }
117   }
118
119   /* This function builds the last delta for a basic block.  It
120    * handles the case for the first time the basic block is
121    * evaluated.*/
122
123   void buildInitDelta(Graph graph, Delta newDelta) {
124     //First compute the set of temps
125     HashSet<TempDescriptor> tmpSet=new HashSet<TempDescriptor>();
126     tmpSet.addAll(graph.varMap.keySet());
127     tmpSet.addAll(graph.parent.varMap.keySet());
128     
129     //Next build the temp map part of the delta
130     for(TempDescriptor tmp:tmpSet) {
131       MySet<Edge> edgeSet=new MySet<Edge>();
132       /* Get target set */
133       if (graph.varMap.containsKey(tmp))
134         edgeSet.addAll(graph.varMap.get(tmp));
135       else
136         edgeSet.addAll(graph.parent.varMap.get(tmp));
137       newDelta.varedgeadd.put(tmp, edgeSet);
138     }
139     
140     //Next compute the set of src allocnodes
141     HashSet<AllocNode> nodeSet=new HashSet<AllocNode>();
142     nodeSet.addAll(graph.nodeMap.keySet());
143     nodeSet.addAll(graph.parent.nodeMap.keySet());
144     
145     for(AllocNode node:nodeSet) {
146       MySet<Edge> edgeSet=new MySet<Edge>();
147       /* Get edge set */
148       if (graph.nodeMap.containsKey(node))
149         edgeSet.addAll(graph.nodeMap.get(node));
150       else
151         edgeSet.addAll(graph.parent.nodeMap.get(node));
152       newDelta.heapedgeadd.put(node, edgeSet);
153       
154       /* Compute ages */
155       if (graph.nodeAges.contains(node))
156         newDelta.addNodeAges.add(node);
157       else if (graph.parent.nodeAges.contains(node))
158         newDelta.addNodeAges.add(node);
159
160       /* Compute ages */
161       if (graph.oldNodes.containsKey(node)) {
162         if (graph.oldNodes.get(node).booleanValue())
163           newDelta.addOldNodes.put(node, Boolean.TRUE);
164       } else if (graph.parent.oldNodes.containsKey(node)) {
165         //parent graphs only contain true...no need to check
166         newDelta.addOldNodes.put(node, Boolean.TRUE);
167       }
168     }
169   }
170
171   /* This function build the delta for the exit of a basic block. */
172
173   void generateFinalDelta(BBlock bblock, Delta delta, Graph graph) {
174     Delta newDelta=new Delta(null, false);
175     if (delta.getInit()) {
176       buildInitDelta(graph, newDelta);
177     } else {
178       /* We can break the old delta...it is done being used */
179       /* First we will build variable edges */
180       HashSet<TempDescriptor> tmpSet=new HashSet<TempDescriptor>();
181       tmpSet.addAll(delta.basevaredge.keySet());
182       tmpSet.addAll(delta.varedgeadd.keySet());
183       for(TempDescriptor tmp:tmpSet) {
184         /* Start with the new incoming edges */
185         MySet<Edge> newbaseedge=delta.basevaredge.get(tmp);
186         /* Remove the remove set */
187         if (newbaseedge==null)
188           newbaseedge=new MySet<Edge>();
189         newbaseedge.removeAll(delta.varedgeremove.get(tmp));
190         /* Add in the new set*/
191         newbaseedge.addAll(delta.varedgeadd.get(tmp));
192         /* Store the results */
193         newDelta.varedgeadd.put(tmp, newbaseedge);
194       }
195       delta.basevaredge.clear();
196
197       /* Next we build heap edges */
198       HashSet<AllocNode> nodeSet=new HashSet<AllocNode>();
199       nodeSet.addAll(delta.baseheapedge.keySet());
200       nodeSet.addAll(delta.heapedgeadd.keySet());
201       nodeSet.addAll(delta.heapedgeremove.keySet());
202       for(AllocNode node:nodeSet) {
203         /* Start with the new incoming edges */
204         MySet<Edge> newheapedge=new MySet<Edge>(delta.baseheapedge.get(node));
205         /* Remove the remove set */
206         MySet<Edge> removeset=delta.heapedgeremove.get(node);
207
208         if (removeset!=null)
209           newheapedge.removeAll(removeset);
210
211         /* Add in the add set */
212         MySet<Edge> settoadd=delta.heapedgeadd.get(node);
213         if (settoadd!=null)
214           newheapedge.addAll(settoadd);
215         newDelta.heapedgeadd.put(node, newheapedge);
216
217         /* Remove the newly created edges..no need to propagate a diff for those */
218         if (removeset!=null) {
219           removeset.removeAll(delta.baseheapedge.get(node));
220           newDelta.heapedgeremove.put(node, removeset);
221         }
222       }
223
224       /* Compute new ages */
225       newDelta.addNodeAges.addAll(delta.baseNodeAges);
226       newDelta.addNodeAges.addAll(delta.addNodeAges);
227       HashSet<AllocNode> oldNodes=new HashSet<AllocNode>();
228
229       /* Compute whether old nodes survive */
230       oldNodes.addAll(delta.baseOldNodes.keySet());
231       oldNodes.addAll(delta.addOldNodes.keySet());
232       for(AllocNode node:oldNodes) {
233         if (delta.addOldNodes.containsKey(node)) {
234           if (delta.addOldNodes.get(node).booleanValue()) {
235             newDelta.addOldNodes.put(node, Boolean.TRUE);
236           }
237         } else {
238           if (delta.baseOldNodes.get(node).booleanValue()) {
239             newDelta.addOldNodes.put(node, Boolean.TRUE);
240           }
241         }
242       }
243     }
244
245     /* Now we need to propagate newdelta */
246     if (!newDelta.heapedgeadd.isEmpty()||!newDelta.heapedgeremove.isEmpty()||!newDelta.varedgeadd.isEmpty()||!newDelta.addNodeAges.isEmpty()||!newDelta.addOldNodes.isEmpty()) {
247       /* We have a delta to propagate */
248
249       if (returnMap.containsKey(bblock)) {
250         //exit of call block
251         boolean first=true;
252
253         for(PPoint caller:returnMap.get(bblock)) {
254           if (first) {
255             newDelta.setBlock(caller);
256             toprocess.add(newDelta);
257             first=false;
258           } else {
259             Delta d=newDelta.diffBlock(caller);
260             toprocess.add(d);
261           }
262         }
263       } else {
264         //normal block
265         Vector<BBlock> blockvector=bblock.next();
266         for(int i=0;i<blockvector.size();i++) {
267           if (i==0) {
268             newDelta.setBlock(new PPoint(blockvector.get(i)));
269             toprocess.add(newDelta);
270           } else {
271             Delta d=newDelta.diffBlock(new PPoint(blockvector.get(i)));
272             toprocess.add(d);
273           }
274         }
275       }
276     }
277   }
278
279   Delta processNode(BBlock bblock, int index, FlatNode node, Delta delta, Graph newgraph) {
280     switch(node.kind()) {
281     case FKind.FlatNew:
282       return processNewNode((FlatNew)node, delta, newgraph);
283     case FKind.FlatFieldNode:
284     case FKind.FlatElementNode:
285       return processFieldElementNode(node, delta, newgraph);
286     case FKind.FlatCastNode:
287     case FKind.FlatOpNode:
288     case FKind.FlatReturnNode:
289       return processCopyNode(node, delta, newgraph);
290     case FKind.FlatSetFieldNode:
291     case FKind.FlatSetElementNode:
292       return processSetFieldElementNode(node, delta, newgraph);
293     case FKind.FlatMethod:
294     case FKind.FlatExit:
295     case FKind.FlatGenReachNode:
296       return processFlatNop(node, delta, newgraph);
297     case FKind.FlatCall:
298       return processFlatCall(bblock, index, (FlatCall) node, delta, newgraph);
299     case FKind.FlatSESEEnterNode:
300     case FKind.FlatSESEExitNode:
301       throw new Error("Unimplemented node:"+node);
302     default:
303       throw new Error("Unrecognized node:"+node);
304     }
305   }
306
307   /* This function compute the edges for the this variable for a
308    * callee if it exists. */
309
310   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) {
311     //Handle the this temp
312     if (tmpthis!=null) {
313       MySet<Edge> edges=(oldnodeset!=null)?GraphManip.getDiffEdges(delta, tmpthis):GraphManip.getEdges(graph, delta, tmpthis);
314       newDelta.varedgeadd.put(tmpthis, (MySet<Edge>) edges.clone());
315       edgeset.addAll(edges);
316       for(Edge e:edges) {
317         AllocNode dstnode=e.dst;
318         if (!nodeset.contains(dstnode)&&(oldnodeset==null||!oldnodeset.contains(dstnode))) {
319           TypeDescriptor type=dstnode.getType();
320           if (!type.isArray()) {
321             targetSet.add(type.getClassDesc());
322           } else {
323             //arrays don't have code
324             targetSet.add(typeUtil.getClass(TypeUtil.ObjectClass));
325           }
326           nodeset.add(dstnode);
327           tovisit.add(dstnode);
328         }
329       }
330     }
331   }
332
333   /* This function compute the edges for a call's parameters. */
334
335   void processParams(Graph graph, Delta delta, Delta newDelta, HashSet<AllocNode> nodeset, Stack<AllocNode> tovisit, MySet<Edge> edgeset, FlatCall fcall, boolean diff) {
336     //Go through each temp
337     for(int i=0;i<fcall.numArgs();i++) {
338       TempDescriptor tmp=fcall.getArg(i);
339       MySet<Edge> edges=diff?GraphManip.getDiffEdges(delta, tmp):GraphManip.getEdges(graph, delta, tmp);
340       newDelta.varedgeadd.put(tmp, (MySet<Edge>) edges.clone());
341       edgeset.addAll(edges);
342       for(Edge e:edges) {
343         if (!nodeset.contains(e.dst)) {
344           nodeset.add(e.dst);
345           tovisit.add(e.dst);
346         }
347       }
348     }
349   }
350
351   /* This function computes the reachable nodes for a callee. */
352
353   void computeReachableNodes(Graph graph, Delta delta, Delta newDelta, HashSet<AllocNode> nodeset, Stack<AllocNode> tovisit, MySet<Edge> edgeset, HashSet<AllocNode> oldnodeset) {
354       while(!tovisit.isEmpty()) {
355         AllocNode node=tovisit.pop();
356         MySet<Edge> edges=GraphManip.getEdges(graph, delta, node);
357         newDelta.heapedgeadd.put(node, edges);
358         edgeset.addAll(edges);
359         for(Edge e:edges) {
360           if (!nodeset.contains(e.dst)&&(oldnodeset==null||!oldnodeset.contains(e.dst))) {
361             nodeset.add(e.dst);
362             tovisit.add(e.dst);
363           }
364         }
365       }
366   }
367
368   HashSet<MethodDescriptor> computeTargets(FlatCall fcall, Delta newDelta) {
369     TempDescriptor tmpthis=fcall.getThis();
370     MethodDescriptor md=fcall.getMethod();
371     HashSet<MethodDescriptor> targets=new HashSet<MethodDescriptor>();
372     if (md.isStatic()) {
373       targets.add(md);
374     } else {
375       //Compute Edges
376       for(Edge e:newDelta.varedgeadd.get(tmpthis)) {
377         AllocNode node=e.dst;
378         ClassDescriptor cd=node.getType().getClassDesc();
379         //Figure out exact method called and add to set
380         targets.add(cd.getCalledMethod(md));
381       }
382     }
383     return targets;
384   }
385
386   void fixMapping(FlatCall fcall, HashSet<MethodDescriptor> targets, MySet<Edge> oldedgeset, Delta newDelta, BBlock callblock, int callindex) {
387     Delta basedelta=null;
388     TempDescriptor tmpthis=fcall.getThis();
389
390     for(MethodDescriptor calledmd:targets) {
391       FlatMethod fm=state.getMethodFlat(calledmd);
392       boolean newmethod=false;
393       
394       //Build tmpMap
395       HashMap<TempDescriptor, TempDescriptor> tmpMap=new HashMap<TempDescriptor, TempDescriptor>();
396       int offset=0;
397       if(tmpthis!=null) {
398         tmpMap.put(tmpthis, fm.getParameter(offset++));
399       }
400       for(int i=0;i<fcall.numArgs();i++) {
401         TempDescriptor tmp=fcall.getArg(i);
402         tmpMap.put(tmp,fm.getParameter(i+offset));
403       }
404
405       //Get basicblock for the method
406       BasicBlock block=getBBlock(fm);
407       
408       //Hook up exits
409       if (!callMap.containsKey(fcall)) {
410         callMap.put(fcall, new HashSet<BBlock>());
411       }
412       
413       Delta returnDelta=null;
414       if (!callMap.get(fcall).contains(block.getStart())) {
415         callMap.get(fcall).add(block.getStart());
416         newmethod=true;
417         
418         //Hook up return
419         if (!returnMap.containsKey(block.getExit())) {
420           returnMap.put(block.getExit(), new HashSet<PPoint>());
421         }
422         returnMap.get(block.getExit()).add(new PPoint(callblock, callindex));
423         
424         if (bbgraphMap.containsKey(block.getExit())) {
425           //Need to push existing results to current node
426           if (returnDelta==null) {
427             returnDelta=new Delta(null, false);
428             Vector<FlatNode> exitblocknodes=block.getExit().nodes();
429             FlatExit fexit=(FlatExit)exitblocknodes.get(exitblocknodes.size()-1);
430             buildInitDelta(graphMap.get(fexit), returnDelta);
431             if (!returnDelta.heapedgeadd.isEmpty()||!returnDelta.heapedgeremove.isEmpty()||!returnDelta.varedgeadd.isEmpty()) {
432               returnDelta.setBlock(new PPoint(callblock, callindex));
433               toprocess.add(returnDelta);
434             }
435           } else {
436             if (!returnDelta.heapedgeadd.isEmpty()||!returnDelta.heapedgeremove.isEmpty()||!returnDelta.varedgeadd.isEmpty()) {
437               toprocess.add(returnDelta.diffBlock(new PPoint(callblock, callindex)));
438             }
439           }
440         }
441       }
442       
443       if (oldedgeset==null) {
444         //First build of this graph
445         //Build and enqueue delta...safe to just use existing delta
446         Delta d=newDelta.changeParams(tmpMap, new PPoint(block.getStart()));
447         toprocess.add(d);
448       } else if (newmethod) {
449         if (basedelta==null) {
450           basedelta=newDelta.buildBase(oldedgeset);
451         }
452         //Build and enqueue delta
453         Delta d=basedelta.changeParams(tmpMap, new PPoint(block.getStart()));
454         toprocess.add(d);
455       } else  {
456         //Build and enqueue delta
457         Delta d=newDelta.changeParams(tmpMap, new PPoint(block.getStart()));
458         toprocess.add(d);
459       }
460     }
461   }
462
463
464   /* This function computes all edges that start outside of the callee context and go into the callee context */
465
466   void computeExternalEdges(Graph graph, Delta delta, HashSet<AllocNode> nodeset, HashSet<AllocNode> deltaset, MySet<Edge> externaledgeset) {
467     //Do heap edges first
468     HashSet<AllocNode> externalnodes=new HashSet<AllocNode>();
469     externalnodes.addAll(delta.baseheapedge.keySet());
470     externalnodes.addAll(delta.heapedgeadd.keySet());
471     externalnodes.addAll(delta.heapedgeremove.keySet());
472     //remove allinternal nodes
473     externalnodes.removeAll(nodeset);
474     for(AllocNode extNode:externalnodes) {
475       //Compute set of edges from given node
476       MySet<Edge> edges=new MySet<Edge>(delta.baseheapedge.get(extNode));
477       edges.removeAll(delta.heapedgeremove.get(extNode));
478       edges.addAll(delta.heapedgeadd.get(extNode));
479       
480       for(Edge e:edges) {
481         if (nodeset.contains(e.dst))
482           externaledgeset.add(e);
483       }
484     }
485
486     //Do heap edges first
487     HashSet<TempDescriptor> temps=new HashSet<TempDescriptor>();
488     temps.addAll(delta.basevaredge.keySet());
489     temps.addAll(delta.varedgeadd.keySet());
490     temps.addAll(delta.varedgeremove.keySet());
491     //remove allinternal nodes
492     temps.removeAll(nodeset);
493     
494     for(TempDescriptor tmp:temps) {
495       //Compute set of edges from given node
496       MySet<Edge> edges=new MySet<Edge>(delta.basevaredge.get(tmp));
497       
498       edges.removeAll(delta.varedgeremove.get(tmp));
499       edges.addAll(delta.varedgeadd.get(tmp));
500       
501       for(Edge e:edges) {
502         if (nodeset.contains(e.dst))
503           externaledgeset.add(e);
504       }
505     }
506   }
507
508   /* This function removes the caller reachable edges from the
509    * callee's heap. */
510   
511   void removeEdges(Delta delta, HashSet<AllocNode> nodeset, MySet<Edge> edgeset, MySet<Edge> externaledgeset) {
512     //Want to remove the set of internal edges
513     for(Edge e:edgeset) {
514       if (e.src!=null) {
515         delta.removeHeapEdge(e);
516       }
517     }
518
519     //Want to remove the set of external edges
520     for(Edge e:externaledgeset) {
521       //want to remove the set of internal edges
522       delta.removeEdge(e);
523     }
524   }
525
526   Delta processFlatCall(BBlock callblock, int callindex, FlatCall fcall, Delta delta, Graph graph) {
527     Delta newDelta=new Delta(null, false);
528
529     if (delta.getInit()) {
530       MySet<Edge> edgeset=new MySet<Edge>();
531       MySet<Edge> externaledgeset=new MySet<Edge>();
532       HashSet<AllocNode> nodeset=new HashSet<AllocNode>();
533       HashSet<ClassDescriptor> targetSet=new HashSet<ClassDescriptor>();
534       Stack<AllocNode> tovisit=new Stack<AllocNode>();
535       TempDescriptor tmpthis=fcall.getThis();
536
537       //Handle the this temp
538       processThisTargets(targetSet, graph, delta, newDelta, nodeset, tovisit, edgeset, tmpthis, null);
539
540       //Go through each temp
541       processParams(graph, delta, newDelta, nodeset, tovisit, edgeset, fcall, false);
542       
543       //Traverse all reachable nodes
544       computeReachableNodes(graph, delta, newDelta, nodeset, tovisit, edgeset, null);
545
546       //Compute call targets
547       HashSet<MethodDescriptor> targets=computeTargets(fcall, newDelta);
548
549       //Fix mapping
550       fixMapping(fcall, targets, null, newDelta, callblock, callindex);
551
552       //Compute edges into region to splice out
553       computeExternalEdges(graph, delta, nodeset, null, externaledgeset);
554
555       //Splice out internal edges
556       removeEdges(delta, nodeset, edgeset, externaledgeset);
557
558       //store data structures
559       graph.externalEdgeSet=externaledgeset;
560       graph.reachNode=nodeset;
561       graph.reachEdge=edgeset;
562       
563       graph.callNodeAges=new HashSet<AllocNode>();
564       graph.callOldNodes=new HashSet<AllocNode>();
565
566       //Apply diffs to graph
567       applyDiffs(graph, delta, true);
568     } else {
569       MySet<Edge> edgeset=new MySet<Edge>();
570       MySet<Edge> externaledgeset=new MySet<Edge>();
571       HashSet<AllocNode> nodeset=new HashSet<AllocNode>();
572       MySet<Edge> oldedgeset=graph.reachEdge;
573       HashSet<AllocNode> oldnodeset=graph.reachNode;
574
575       HashSet<ClassDescriptor> targetSet=new HashSet<ClassDescriptor>();
576       Stack<AllocNode> tovisit=new Stack<AllocNode>();
577       TempDescriptor tmpthis=fcall.getThis();
578
579       //Handle the this temp
580       processThisTargets(targetSet, graph, delta, newDelta, nodeset, tovisit, edgeset, tmpthis, oldnodeset);
581
582       //Go through each temp
583       processParams(graph, delta, newDelta, nodeset, tovisit, edgeset, fcall, true);
584
585       //Go through each new heap edge that starts from old node
586       MySet<Edge> newedges=GraphManip.getDiffEdges(delta, oldnodeset);
587       edgeset.addAll(newedges);
588       for(Edge e:newedges) {
589         if (!nodeset.contains(e.dst)&&!oldnodeset.contains(e.dst)) {
590           nodeset.add(e.dst);
591           tovisit.add(e.dst);
592         }
593       }
594       
595       //Traverse all reachable nodes
596       computeReachableNodes(graph, delta, newDelta, nodeset, tovisit, edgeset, oldnodeset);
597
598       //Compute call targets
599       HashSet<MethodDescriptor> targets=computeTargets(fcall, newDelta);
600
601       //add in new nodeset and edgeset
602       oldnodeset.addAll(nodeset);
603       oldedgeset.addAll(edgeset);
604
605       //Fix mapping
606       fixMapping(fcall, targets, oldedgeset, newDelta, callblock, callindex);
607
608       //Compute edges into region to splice out
609       computeExternalEdges(graph, delta, oldnodeset, nodeset, externaledgeset);
610
611       //Splice out internal edges
612       removeEdges(delta, nodeset, edgeset, externaledgeset);
613
614       //Add in new external edges
615       graph.externalEdgeSet.addAll(externaledgeset);
616
617       //Apply diffs to graph
618       applyDiffs(graph, delta);
619     }
620     return delta;
621   }
622
623   /* This function applies callee deltas to the caller heap. */
624
625   Delta applyCallDelta(Delta delta, BBlock bblock) {
626     Delta newDelta=new Delta(null, false);
627     Vector<FlatNode> nodes=bblock.nodes();
628     PPoint ppoint=delta.getBlock();
629     FlatCall fcall=(FlatCall)nodes.get(ppoint.getIndex());
630     Graph graph=graphMap.get(fcall);
631     Graph oldgraph=(ppoint.getIndex()==0)?
632       bbgraphMap.get(bblock):
633       graphMap.get(nodes.get(ppoint.getIndex()-1));
634
635     //Age outside nodes if necessary
636     for(Iterator<AllocNode> nodeit=delta.addNodeAges.iterator();nodeit.hasNext();) {
637       AllocNode node=nodeit.next();
638       if (!graph.callNodeAges.contains(node)) {
639         graph.callNodeAges.add(node);
640       } else {
641         nodeit.remove();
642       }
643       if (!graph.reachNode.contains(node)&&!node.isSummary()) {
644         /* Need to age node in existing graph*/
645         summarizeInGraph(graph, newDelta, node);
646       }
647     }
648     //Add heap edges in
649     for(Map.Entry<AllocNode, MySet<Edge>> entry:delta.heapedgeadd.entrySet()) {
650       for(Edge e:entry.getValue()) {
651         boolean addedge=false;
652         Edge edgetoadd=null;
653         if (e.statuspredicate==Edge.NEW) {
654           edgetoadd=e;
655         } else {
656           Edge origEdgeKey=e.makeStatus(allocFactory);
657           if (oldgraph.nodeMap.containsKey(origEdgeKey.src)&&
658               oldgraph.nodeMap.get(origEdgeKey.src).contains(origEdgeKey)) {
659             Edge origEdge=oldgraph.nodeMap.get(origEdgeKey.src).get(origEdgeKey);
660             //copy the predicate
661             origEdgeKey.statuspredicate=origEdge.statuspredicate;
662             edgetoadd=origEdgeKey;
663           }
664         }
665         mergeEdge(graph, newDelta, edgetoadd);
666       }
667     }
668     //Add external edges in
669     for(Edge e:graph.externalEdgeSet) {
670       //First did we age the source
671       Edge newedge=e.copy();
672       if (newedge.src!=null&&!e.src.isSummary()&&graph.callNodeAges.contains(e.src)) {
673         AllocNode summaryNode=allocFactory.getAllocNode(newedge.src, true);
674         newedge.src=summaryNode;
675       }
676       //Compute target
677       if (graph.callNodeAges.contains(e.dst)&&!e.dst.isSummary()) {
678         if (graph.callOldNodes.contains(e.dst)) {
679           //Need two edges
680           Edge copy=newedge.copy();
681           mergeEdge(graph, newDelta, copy);
682         }
683         //Now add summarized node
684         newedge.dst=allocFactory.getAllocNode(newedge.dst, true);
685         mergeEdge(graph, newDelta, newedge);
686       } else {
687         //Add edge to single node
688         mergeEdge(graph, newDelta, newedge);
689       }
690     }
691     //Add edge for return value
692     if (fcall.getReturnTemp()!=null) {
693       MySet<Edge> returnedge=delta.varedgeadd.get(returntmp);
694       if (returnedge!=null)
695         for(Edge e:returnedge) {
696           Edge newedge=e.copy();
697           newedge.srcvar=fcall.getReturnTemp();
698           if (graph.getEdges(fcall.getReturnTemp())==null||!graph.getEdges(fcall.getReturnTemp()).contains(newedge))
699             newDelta.addEdge(newedge);
700         }
701     }
702     applyDiffs(graph, newDelta);
703     return newDelta;
704   }
705   
706   public void mergeEdge(Graph graph, Delta newDelta, Edge edgetoadd) {
707     if (edgetoadd!=null) {
708       Edge match=graph.getMatch(edgetoadd);
709
710       if (match==null||!match.subsumes(edgetoadd)) {
711         Edge mergededge=edgetoadd.merge(match);
712         newDelta.addEdge(mergededge);
713       }
714     }
715   }
716
717
718   /* Summarizes out of context nodes in graph */
719   void summarizeInGraph(Graph graph, Delta newDelta, AllocNode singleNode) {
720     AllocNode summaryNode=allocFactory.getAllocNode(singleNode, true);
721
722     //Handle outgoing heap edges
723     MySet<Edge> edgeset=graph.getEdges(singleNode);
724
725     for(Edge e:edgeset) {
726       Edge rewrite=e.rewrite(singleNode, summaryNode);
727       //Remove old edge
728       newDelta.removeHeapEdge(e);
729       mergeEdge(graph, newDelta, rewrite);
730     }
731     
732     //Handle incoming edges
733     MySet<Edge> backedges=graph.getBackEdges(singleNode);
734     for(Edge e:backedges) {
735       if (e.dst==singleNode) {
736         //Need to get original edge so that predicate will be correct
737         Edge match=graph.getMatch(e);
738         Edge rewrite=match.rewrite(singleNode, summaryNode);
739         newDelta.removeEdge(match);
740         mergeEdge(graph, newDelta, rewrite);
741       }
742     }
743   }
744
745   void applyDiffs(Graph graph, Delta delta) {
746     applyDiffs(graph, delta, false);
747   }
748
749   void applyDiffs(Graph graph, Delta delta, boolean genbackwards) {
750     //build backwards map if requested
751     if (genbackwards&&graph.backMap==null) {
752       graph.backMap=new HashMap<AllocNode, MySet<Edge>>();
753       if (graph.parent.backMap==null) {
754         graph.parent.backMap=new HashMap<AllocNode, MySet<Edge>>();
755         for(Map.Entry<AllocNode, MySet<Edge>> entry:graph.nodeMap.entrySet()) {
756           for(Edge e:entry.getValue()) {
757             if (!graph.parent.backMap.containsKey(e.dst))
758               graph.parent.backMap.put(e.dst, new MySet<Edge>());
759             graph.parent.backMap.get(e.dst).add(e);
760           }
761         }
762         for(Map.Entry<TempDescriptor, MySet<Edge>> entry:graph.varMap.entrySet()) {
763           for(Edge e:entry.getValue()) {
764             if (!graph.parent.backMap.containsKey(e.dst))
765               graph.parent.backMap.put(e.dst, new MySet<Edge>());
766             graph.parent.backMap.get(e.dst).add(e);
767           }
768         }
769       }
770     }
771
772     //Add hidden base edges
773     for(Map.Entry<AllocNode, MySet<Edge>> e: delta.baseheapedge.entrySet()) {
774       AllocNode node=e.getKey();
775       MySet<Edge> edges=e.getValue();
776       if (graph.nodeMap.containsKey(node)) {
777         MySet<Edge> nodeEdges=graph.nodeMap.get(node);
778         nodeEdges.addAll(edges);
779       }
780     }
781
782     //Remove heap edges
783     for(Map.Entry<AllocNode, MySet<Edge>> e: delta.heapedgeremove.entrySet()) {
784       AllocNode node=e.getKey();
785       MySet<Edge> edgestoremove=e.getValue();
786       if (graph.nodeMap.containsKey(node)) {
787         //Just apply diff to current map
788         graph.nodeMap.get(node).removeAll(edgestoremove);
789       } else {
790         //Generate diff from parent graph
791         MySet<Edge> parentedges=graph.parent.nodeMap.get(node);
792         MySet<Edge> newedgeset=Util.setSubtract(parentedges, edgestoremove);
793         graph.nodeMap.put(node, newedgeset);
794       }
795     }
796
797     //Add heap edges
798     for(Map.Entry<AllocNode, MySet<Edge>> e: delta.heapedgeadd.entrySet()) {
799       AllocNode node=e.getKey();
800       MySet<Edge> edgestoadd=e.getValue();
801       //If we have not done a subtract, then 
802       if (!graph.nodeMap.containsKey(node)) {
803         //Copy the parent entry
804         if (graph.parent.nodeMap.containsKey(node))
805           graph.nodeMap.put(node, (MySet<Edge>)graph.parent.nodeMap.get(node).clone());
806         else
807           graph.nodeMap.put(node, new MySet<Edge>());
808       }
809       graph.nodeMap.get(node).addAll(edgestoadd);
810       if (genbackwards) {
811         for(Edge eadd:edgestoadd) {
812           if (!graph.backMap.containsKey(eadd.dst))
813             graph.backMap.put(eadd.dst, new MySet<Edge>());
814           graph.backMap.get(eadd.dst).add(eadd);
815         }
816       }
817     }
818
819     //Remove var edges
820     for(Map.Entry<TempDescriptor, MySet<Edge>> e: delta.varedgeremove.entrySet()) {
821       TempDescriptor tmp=e.getKey();
822       MySet<Edge> edgestoremove=e.getValue();
823
824       if (graph.varMap.containsKey(tmp)) {
825         //Just apply diff to current map
826         graph.varMap.get(tmp).removeAll(edgestoremove);
827       } else if (graph.parent.varMap.containsKey(tmp)) {
828         //Generate diff from parent graph
829         MySet<Edge> parentedges=graph.parent.varMap.get(tmp);
830         MySet<Edge> newedgeset=Util.setSubtract(parentedges, edgestoremove);
831         graph.varMap.put(tmp, newedgeset);
832       }
833     }
834
835     //Add var edges
836     for(Map.Entry<TempDescriptor, MySet<Edge>> e: delta.varedgeadd.entrySet()) {
837       TempDescriptor tmp=e.getKey();
838       MySet<Edge> edgestoadd=e.getValue();
839       graph.varMap.put(tmp, (MySet<Edge>) edgestoadd.clone());
840       if (genbackwards) {
841         for(Edge eadd:edgestoadd) {
842           if (!graph.backMap.containsKey(eadd.dst))
843             graph.backMap.put(eadd.dst, new MySet<Edge>());
844           graph.backMap.get(eadd.dst).add(eadd);
845         }
846       }
847     }
848
849     //Add node additions
850     for(AllocNode node:delta.addNodeAges) {
851       graph.nodeAges.add(node);
852     }
853     
854     for(Map.Entry<AllocNode, Boolean> nodeentry:delta.addOldNodes.entrySet()) {
855       AllocNode node=nodeentry.getKey();
856       Boolean ispresent=nodeentry.getValue();
857       graph.oldNodes.put(node, ispresent);
858     }
859   }
860
861   Delta processSetFieldElementNode(FlatNode node, Delta delta, Graph graph) {
862     TempDescriptor src;
863     FieldDescriptor fd;
864     TempDescriptor dst;
865     if (node.kind()==FKind.FlatSetElementNode) {
866       FlatSetElementNode fen=(FlatSetElementNode) node;
867       src=fen.getSrc();
868       fd=null;
869       dst=fen.getDst();
870     } else {
871       FlatSetFieldNode ffn=(FlatSetFieldNode) node;
872       src=ffn.getSrc();
873       fd=ffn.getField();
874       dst=ffn.getDst();
875     }
876     if (delta.getInit()) {
877       HashSet<AllocNode> srcNodes=GraphManip.getNodes(graph, delta, src);
878       HashSet<AllocNode> dstNodes=GraphManip.getNodes(graph, delta, dst);
879       MySet<Edge> edgesToAdd=GraphManip.genEdges(dstNodes, fd, srcNodes);
880       MySet<Edge> edgesToRemove=null;
881       if (dstNodes.size()==1&&!dstNodes.iterator().next().isSummary()) {
882         /* Can do a strong update */
883         edgesToRemove=GraphManip.getEdges(graph, delta, dstNodes, fd);
884         graph.strongUpdateSet=edgesToRemove;
885       } else
886         graph.strongUpdateSet=new MySet<Edge>();
887       /* Update diff */
888       updateHeapDelta(graph, delta, edgesToAdd, edgesToRemove);
889       applyDiffs(graph, delta);
890     } else {
891       /* First look at new sources */
892       MySet<Edge> edgesToAdd=new MySet<Edge>();
893       HashSet<AllocNode> newSrcNodes=GraphManip.getDiffNodes(delta, src);
894       HashSet<AllocNode> srcNodes=GraphManip.getNodes(graph, delta, src);
895       HashSet<AllocNode> dstNodes=GraphManip.getNodes(graph, delta, dst);
896       HashSet<AllocNode> newDstNodes=GraphManip.getDiffNodes(delta, dst);
897
898
899       MySet<Edge> edgesToRemove=null;
900       if (newDstNodes.size()!=0) {
901         if (dstNodes.size()>1&&!dstNodes.iterator().next().isSummary()) {
902           /* Need to undo strong update */
903           if (graph.strongUpdateSet!=null) {
904             edgesToAdd.addAll(graph.strongUpdateSet);
905             graph.strongUpdateSet=null; //Prevent future strong updates
906           }
907         } else if (dstNodes.size()==1&&newDstNodes.size()==1&&!newDstNodes.iterator().next().isSummary()&&graph.strongUpdateSet!=null) {
908           edgesToRemove=GraphManip.getEdges(graph, delta, dstNodes, fd);
909           graph.strongUpdateSet.addAll(edgesToRemove);
910         }
911         edgesToAdd.addAll(GraphManip.genEdges(newDstNodes, fd, srcNodes));
912       }
913
914       //Kill new edges
915       if (graph.strongUpdateSet!=null) {
916         MySet<Edge> otherEdgesToRemove=GraphManip.getDiffEdges(delta, dstNodes);
917         if (edgesToRemove!=null)
918           edgesToRemove.addAll(otherEdgesToRemove);
919         else
920           edgesToRemove=otherEdgesToRemove;
921         graph.strongUpdateSet.addAll(otherEdgesToRemove);
922       }
923
924       //Next look at new destinations
925       edgesToAdd.addAll(GraphManip.genEdges(dstNodes, fd, newSrcNodes));
926
927       /* Update diff */
928       updateHeapDelta(graph, delta, edgesToAdd, edgesToRemove);
929       applyDiffs(graph, delta);
930     }
931     return delta;
932   }
933
934   Delta processCopyNode(FlatNode node, Delta delta, Graph graph) {
935     TempDescriptor src;
936     TempDescriptor dst;
937     if (node.kind()==FKind.FlatOpNode) {
938       FlatOpNode fon=(FlatOpNode) node;
939       src=fon.getLeft();
940       dst=fon.getDest();
941     } else if (node.kind()==FKind.FlatReturnNode) {
942       FlatReturnNode frn=(FlatReturnNode)node;
943       src=frn.getReturnTemp();
944       dst=returntmp;
945       if (src==null||!src.getType().isPtr()) {
946         //This is a NOP
947         applyDiffs(graph, delta);
948         return delta;
949       }
950     } else {
951       FlatCastNode fcn=(FlatCastNode) node;
952       src=fcn.getSrc();
953       dst=fcn.getDst();
954     }
955     if (delta.getInit()) {
956       HashSet<AllocNode> srcnodes=GraphManip.getNodes(graph, delta, src);
957       MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, srcnodes);
958       MySet<Edge> edgesToRemove=GraphManip.getEdges(graph, delta, dst);
959       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
960       applyDiffs(graph, delta);
961     } else {
962       /* First compute new src nodes */
963       HashSet<AllocNode> newSrcNodes=GraphManip.getDiffNodes(delta, src);
964
965       /* Compute the union, and then the set of edges */
966       MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, newSrcNodes);
967       
968       /* Compute set of edges to remove */
969       MySet<Edge> edgesToRemove=GraphManip.getDiffEdges(delta, dst);      
970
971       /* Update diff */
972       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
973       applyDiffs(graph, delta);
974     }
975     return delta;
976   }
977
978   Delta processFieldElementNode(FlatNode node, Delta delta, Graph graph) {
979     TempDescriptor src;
980     FieldDescriptor fd;
981     TempDescriptor dst;
982     if (node.kind()==FKind.FlatElementNode) {
983       FlatElementNode fen=(FlatElementNode) node;
984       src=fen.getSrc();
985       fd=null;
986       dst=fen.getDst();
987     } else {
988       FlatFieldNode ffn=(FlatFieldNode) node;
989       src=ffn.getSrc();
990       fd=ffn.getField();
991       dst=ffn.getDst();
992     }
993     if (delta.getInit()) {
994       HashSet<AllocNode> srcnodes=GraphManip.getNodes(graph, delta, src);
995       HashSet<AllocNode> fdnodes=GraphManip.getNodes(graph, delta, srcnodes, fd);
996       MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, fdnodes);
997       MySet<Edge> edgesToRemove=GraphManip.getEdges(graph, delta, dst);
998       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
999       applyDiffs(graph, delta);
1000     } else {
1001       /* First compute new objects we read fields of */
1002       HashSet<AllocNode> allsrcnodes=GraphManip.getNodes(graph, delta, src);
1003       HashSet<AllocNode> difffdnodes=GraphManip.getDiffNodes(delta, allsrcnodes, fd);     
1004       /* Next compute new targets of fields */
1005       HashSet<AllocNode> newsrcnodes=GraphManip.getDiffNodes(delta, src);
1006       HashSet<AllocNode> newfdnodes=GraphManip.getNodes(graph, delta, newsrcnodes, fd);
1007       /* Compute the union, and then the set of edges */
1008       HashSet<AllocNode> newTargets=new HashSet<AllocNode>();
1009       newTargets.addAll(newfdnodes);
1010       newTargets.addAll(difffdnodes);
1011       MySet<Edge> edgesToAdd=GraphManip.genEdges(dst, newTargets);      
1012       
1013       /* Compute set of edges to remove */
1014       MySet<Edge> edgesToRemove=GraphManip.getDiffEdges(delta, dst);      
1015
1016       /* Update diff */
1017       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
1018       applyDiffs(graph, delta);
1019     }
1020     return delta;
1021   }
1022
1023   static void updateVarDelta(Graph graph, Delta delta, TempDescriptor tmp, MySet<Edge> edgestoAdd, MySet<Edge> edgestoRemove) {
1024     MySet<Edge> edgeAdd=delta.varedgeadd.get(tmp);
1025     MySet<Edge> edgeRemove=delta.varedgeremove.get(tmp);
1026     MySet<Edge> existingEdges=graph.getEdges(tmp);
1027     for(Edge e: edgestoRemove) {
1028       //remove edge from delta
1029       if (edgeAdd!=null)
1030         edgeAdd.remove(e);
1031       //if the edge is already in the graph, add an explicit remove to the delta
1032       if (existingEdges.contains(e))
1033         delta.removeVarEdge(e);
1034     }
1035     for(Edge e: edgestoAdd) {
1036       //Remove the edge from the remove set
1037       if (edgeRemove!=null)
1038         edgeRemove.remove(e);
1039       //Explicitly add it to the add set unless it is already in the graph
1040       if (!existingEdges.contains(e))
1041         delta.addVarEdge(e);
1042     }
1043   }
1044
1045   static void updateHeapDelta(Graph graph, Delta delta, MySet<Edge> edgestoAdd, MySet<Edge> edgestoRemove) {
1046     if (edgestoRemove!=null)
1047       for(Edge e: edgestoRemove) {
1048         AllocNode src=e.src;
1049         MySet<Edge> edgeAdd=delta.heapedgeadd.get(src);
1050         MySet<Edge> existingEdges=graph.getEdges(src);
1051         //remove edge from delta
1052         edgeAdd.remove(e);
1053         //if the edge is already in the graph, add an explicit remove to the delta
1054         if (existingEdges.contains(e)) {
1055           delta.removeHeapEdge(e);
1056         }
1057       }
1058     if (edgestoAdd!=null)
1059       for(Edge e: edgestoAdd) {
1060         AllocNode src=e.src;
1061         MySet<Edge> edgeRemove=delta.heapedgeremove.get(src);
1062         MySet<Edge> existingEdges=graph.getEdges(src);
1063         //Remove the edge from the remove set
1064         if (edgeRemove!=null)
1065           edgeRemove.remove(e);
1066         //Explicitly add it to the add set unless it is already in the graph
1067         if (!existingEdges.contains(e)||!existingEdges.get(e).isNew()) {
1068           delta.addHeapEdge(e);
1069         }
1070       }
1071   }
1072
1073   Delta processFlatNop(FlatNode node, Delta delta, Graph graph) {
1074     applyDiffs(graph, delta);
1075     return delta;
1076   }
1077   
1078   Delta processNewNode(FlatNew node, Delta delta, Graph graph) {
1079     AllocNode summary=allocFactory.getAllocNode(node, true);
1080     AllocNode single=allocFactory.getAllocNode(node, false);
1081     TempDescriptor tmp=node.getDst();
1082
1083     if (delta.getInit()) {
1084       /* We don't have to deal with summarization here...  The
1085        * intuition is that this is the only place where we generate
1086        * nodes for this allocation site and this is the first time
1087        * we've analyzed this site */
1088
1089       //Build new Edge
1090       Edge e=new Edge(tmp, single);
1091       //Build new Edge set
1092       MySet<Edge> newedges=new MySet<Edge>();
1093       newedges.add(e);
1094       //Add it into the diffs
1095       delta.varedgeadd.put(tmp, newedges);
1096       //Remove the old edges
1097       delta.varedgeremove.put(tmp, (MySet<Edge>) graph.getEdges(tmp).clone());
1098       //Apply incoming diffs to graph
1099       applyDiffs(graph, delta);
1100       //Note that we create a single node
1101       delta.addNodeAges.add(single);
1102       //Kill the old node
1103       if (delta.addOldNodes.containsKey(single)||delta.baseOldNodes.containsKey(single)) {
1104         delta.addOldNodes.put(single, Boolean.FALSE);
1105       }
1106     } else {
1107       /* 1. Fix up the variable edge additions */
1108
1109       for(Iterator<Map.Entry<TempDescriptor, MySet<Edge>>> entryIt=delta.varedgeadd.entrySet().iterator();entryIt.hasNext();) {
1110         Map.Entry<TempDescriptor, MySet<Edge>> entry=entryIt.next();
1111
1112         if (entry.getKey()==tmp) {
1113           /* Check if this is the tmp we overwrite */
1114           entryIt.remove();
1115         } else {
1116           /* Otherwise, check if the target of the edge is changed... */
1117           summarizeSet(entry.getValue(), graph.varMap.get(entry.getKey()), single, summary);
1118         }
1119       }
1120       
1121       /* 2. Fix up the base variable edges */
1122
1123       for(Iterator<Map.Entry<TempDescriptor, MySet<Edge>>> entryIt=delta.basevaredge.entrySet().iterator();entryIt.hasNext();) {
1124         Map.Entry<TempDescriptor, MySet<Edge>> entry=entryIt.next();
1125         TempDescriptor entrytmp=entry.getKey();
1126         if (entrytmp==tmp) {
1127           /* Check is this is the tmp we overwrite, if so add to remove set */
1128           Util.relationUpdate(delta.varedgeremove, tmp, null, entry.getValue());
1129         } else {
1130           /* Check if the target of the edge is changed */ 
1131           MySet<Edge> newset=(MySet<Edge>)entry.getValue().clone();
1132           MySet<Edge> removeset=shrinkSet(newset, graph.varMap.get(entrytmp), single, summary);
1133           Util.relationUpdate(delta.varedgeremove, entrytmp, newset, removeset);
1134           Util.relationUpdate(delta.varedgeadd, entrytmp, null, newset);
1135         }
1136       }
1137
1138
1139       /* 3. Fix up heap edge additions */
1140
1141       HashMap<AllocNode, MySet<Edge>> addheapedge=new HashMap<AllocNode, MySet<Edge>>();
1142       for(Iterator<Map.Entry<AllocNode, MySet<Edge>>> entryIt=delta.heapedgeadd.entrySet().iterator();entryIt.hasNext();) {
1143         Map.Entry<AllocNode, MySet<Edge>> entry=entryIt.next();
1144         MySet<Edge> edgeset=entry.getValue();
1145         AllocNode allocnode=entry.getKey();
1146         if (allocnode==single) {
1147           entryIt.remove();
1148           summarizeSet(edgeset, graph.nodeMap.get(summary), single, summary);
1149           addheapedge.put(summary, edgeset);
1150         } else {
1151           summarizeSet(edgeset, graph.nodeMap.get(allocnode), single, summary);
1152         }
1153       }
1154       
1155       /* Merge in diffs */
1156
1157       for(Map.Entry<AllocNode, MySet<Edge>> entry:addheapedge.entrySet()) {
1158         AllocNode allocnode=entry.getKey();
1159         Util.relationUpdate(delta.heapedgeadd, allocnode, null, entry.getValue());
1160       }
1161
1162       /* 4. Fix up the base heap edges */
1163
1164       for(Iterator<Map.Entry<AllocNode, MySet<Edge>>> entryIt=delta.baseheapedge.entrySet().iterator();entryIt.hasNext();) {
1165         Map.Entry<AllocNode, MySet<Edge>> entry=entryIt.next();
1166         MySet<Edge> edgeset=entry.getValue();
1167         AllocNode allocnode=entry.getKey();
1168         if (allocnode==single) {
1169           entryIt.remove();
1170         }
1171         AllocNode addnode=(allocnode==single)?summary:allocnode;
1172
1173         MySet<Edge> newset=(MySet<Edge>) edgeset.clone();
1174         MySet<Edge> removeset=shrinkSet(newset, graph.nodeMap.get(addnode), single, summary);
1175         Util.relationUpdate(delta.heapedgeadd, addnode, null, newset);
1176         Util.relationUpdate(delta.heapedgeremove, allocnode, null, removeset);
1177       }
1178
1179       /* Update Node Ages...If the base or addNodeAges set contains a
1180        * single node, it now should also contain a summary node...  No
1181        * need to generate a single node as that has already been
1182        * done. */
1183       if (delta.baseNodeAges.contains(single)||delta.addNodeAges.contains(single)) {
1184         delta.addNodeAges.add(summary);
1185       }
1186
1187       //Kill the old node if someone tries to add it
1188       if (delta.addOldNodes.containsKey(single)||delta.baseOldNodes.containsKey(single)) {
1189         delta.addOldNodes.put(single, Boolean.FALSE);
1190       }
1191       
1192       //Apply incoming diffs to graph
1193       applyDiffs(graph, delta);      
1194     }
1195     return delta;
1196   }
1197
1198   /* This function builds a new edge set where oldnode is summarized into new node */
1199
1200   void summarizeSet(MySet<Edge> edgeset, MySet<Edge> oldedgeset, AllocNode oldnode, AllocNode sumnode) {
1201     MySet<Edge> newSet=null;
1202     for(Iterator<Edge> edgeit=edgeset.iterator();edgeit.hasNext();) {
1203       Edge e=edgeit.next();
1204       if (e.dst==oldnode||e.src==oldnode) {
1205         if (newSet==null) {
1206           newSet=new MySet<Edge>();
1207         }
1208         edgeit.remove();
1209         e=e.copy();
1210
1211         if (e.dst==oldnode) {
1212           e.dst=sumnode;
1213         }
1214         if (e.src==oldnode) {
1215           e.src=sumnode;
1216         }
1217         if (oldedgeset==null||!oldedgeset.contains(e))
1218           newSet.add(e);
1219       }
1220     }
1221     if (newSet!=null)
1222       edgeset.addAll(newSet);
1223   }
1224
1225   /* Shrinks the incoming set to just include rewritten values.
1226    * Returns a set of the original rewritten values */
1227
1228   MySet<Edge> shrinkSet(MySet<Edge> edgeset, MySet<Edge> oldedgeset, AllocNode oldnode, AllocNode newnode) {
1229     MySet<Edge> newSet=null;
1230     MySet<Edge> removeSet=null;
1231     for(Iterator<Edge> edgeit=edgeset.iterator();edgeit.hasNext();) {
1232       Edge e=edgeit.next();
1233       edgeit.remove();
1234       if (e.dst==oldnode||e.src==oldnode) {
1235         if (newSet==null) {
1236           newSet=new MySet<Edge>();
1237           removeSet=new MySet<Edge>();
1238         }
1239
1240         removeSet.add(e.copy());
1241         if (e.dst==oldnode)
1242           e.dst=newnode;
1243         if (e.src==oldnode)
1244           e.src=newnode;
1245         if (oldedgeset==null||!oldedgeset.contains(e))
1246           newSet.add(e);
1247       }
1248     }
1249     if (newSet!=null)
1250       edgeset.addAll(newSet);
1251     return removeSet;
1252   } 
1253
1254   /* This function returns a completely new Delta...  It is safe to
1255    * modify this */
1256
1257   Delta applyInitDelta(Delta delta, BBlock block) {
1258     //Apply delta to graph
1259     boolean newGraph=false;
1260     if (!bbgraphMap.containsKey(block)) {
1261       bbgraphMap.put(block, new Graph(null));
1262       newGraph=true;
1263     }
1264     Delta newdelta;
1265     Graph graph=bbgraphMap.get(block);
1266
1267     if (newGraph) {
1268       newdelta=new Delta(null, true);
1269       //Add in heap edges and throw away original diff
1270       graph.nodeMap.putAll(delta.heapedgeadd);
1271       //Add in var edges and throw away original diff
1272       graph.varMap.putAll(delta.varedgeadd);
1273       //Record that this is initial set...
1274       graph.nodeAges.addAll(delta.addNodeAges);
1275       //Add old nodes
1276       for(Map.Entry<AllocNode, Boolean> oldentry:delta.addOldNodes.entrySet()) {
1277         if (oldentry.getValue().booleanValue()) {
1278           graph.oldNodes.put(oldentry.getKey(), Boolean.TRUE);
1279         }
1280       }
1281     } else {
1282       newdelta=new Delta(null, false);
1283       //merge in heap edges and variables
1284       mergeHeapEdges(graph, delta, newdelta);
1285       mergeVarEdges(graph, delta, newdelta);
1286       mergeAges(graph, delta, newdelta);
1287     }
1288
1289     return newdelta;
1290   }
1291
1292   /* This function merges in the heap edges.  It updates delta to be
1293    * the difference */
1294
1295   void mergeHeapEdges(Graph graph, Delta delta, Delta newdelta) {
1296     //Merge in edges
1297     for(Map.Entry<AllocNode, MySet<Edge>> heapedge:delta.heapedgeadd.entrySet()) {
1298       AllocNode nsrc=heapedge.getKey();
1299       MySet<Edge> edges=heapedge.getValue();
1300
1301       if (graph.backMap!=null) {
1302         for(Edge e:edges) {
1303           if (!graph.backMap.containsKey(e.dst))
1304             graph.backMap.put(e.dst, new MySet<Edge>());
1305           graph.backMap.get(e.dst).add(e);
1306         }
1307       }
1308
1309       if (!graph.nodeMap.containsKey(nsrc)) {
1310         graph.nodeMap.put(nsrc, new MySet<Edge>());
1311       }
1312       MySet<Edge> dstedges=graph.nodeMap.get(nsrc);
1313       MySet<Edge> diffedges=new MySet<Edge>();
1314       for(Edge e:edges) {
1315         if (!dstedges.contains(e)) {
1316           //We have a new edge
1317           diffedges.add(e);
1318           dstedges.add(e);
1319         } else {
1320           Edge origedge=dstedges.get(e);
1321           if (!origedge.subsumes(e)) {
1322             Edge mergededge=origedge.merge(e);
1323             diffedges.add(mergededge);
1324             dstedges.add(mergededge);
1325           }
1326         }
1327       }
1328       //Done with edge set...
1329       if (diffedges.size()>0) {
1330         //completely new
1331         newdelta.baseheapedge.put(nsrc, diffedges);
1332       }
1333     }
1334   }
1335
1336   /* This function merges in the var edges.  It updates delta to be
1337    * the difference */
1338
1339   void mergeVarEdges(Graph graph, Delta delta, Delta newdelta) {
1340     //Merge in edges
1341     for(Map.Entry<TempDescriptor, MySet<Edge>> varedge:delta.varedgeadd.entrySet()) {
1342       TempDescriptor tmpsrc=varedge.getKey();
1343       MySet<Edge> edges=varedge.getValue();
1344       if (graph.backMap!=null) {
1345         for(Edge e:edges) {
1346           if (!graph.backMap.containsKey(e.dst))
1347             graph.backMap.put(e.dst, new MySet<Edge>());
1348           graph.backMap.get(e.dst).add(e);
1349         }
1350       }
1351
1352       if (!graph.varMap.containsKey(tmpsrc)) {
1353         graph.varMap.put(tmpsrc, new MySet<Edge>());
1354       }
1355       MySet<Edge> dstedges=graph.varMap.get(tmpsrc);
1356       MySet<Edge> diffedges=new MySet<Edge>();
1357       for(Edge e:edges) {
1358         if (!dstedges.contains(e)) {
1359           //We have a new edge
1360           diffedges.add(e);
1361           dstedges.add(e);
1362         }
1363       }
1364       //Done with edge set...
1365       if (diffedges.size()>=0) {
1366         //completely new
1367         newdelta.basevaredge.put(tmpsrc,diffedges);
1368       }
1369     }
1370   }
1371
1372   void mergeAges(Graph graph, Delta delta, Delta newDelta) {
1373     //Merge in edges
1374     for(AllocNode node:delta.addNodeAges) {
1375       if (!graph.nodeAges.contains(node)) {
1376         graph.nodeAges.add(node);
1377         newDelta.baseNodeAges.add(node);
1378       }
1379     }
1380     for(Map.Entry<AllocNode, Boolean> oldentry:delta.addOldNodes.entrySet()) {
1381       AllocNode node=oldentry.getKey();
1382       boolean ispresent=oldentry.getValue().booleanValue();
1383       if (ispresent&&!graph.oldNodes.containsKey(node)) {
1384         graph.oldNodes.put(node, Boolean.TRUE);
1385         newDelta.baseOldNodes.put(node, Boolean.TRUE);
1386       }
1387     }
1388   }
1389 }