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