more changes...
[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
8 public class Pointer {
9   HashMap<FlatMethod, BasicBlock> blockMap;
10   HashMap<BBlock, Graph> bbgraphMap;
11   HashMap<FlatNode, Graph> graphMap;
12   State state;
13   TypeUtil typeUtil;
14   AllocFactory allocFactory;
15   LinkedList<Delta> toprocess;
16   TempDescriptor returntmp;
17
18   public Pointer(State state, TypeUtil typeUtil) {
19     this.state=state;
20     this.blockMap=new HashMap<FlatMethod, BasicBlock>();
21     this.bbgraphMap=new HashMap<BBlock, Graph>();
22     this.graphMap=new HashMap<FlatNode, Graph>();
23     this.typeUtil=typeUtil;
24     this.allocFactory=new AllocFactory(state, typeUtil);
25     this.toprocess=new LinkedList<Delta>();
26     ClassDescriptor stringcd=typeUtil.getClass(TypeUtil.ObjectClass);
27     this.returntmp=new TempDescriptor("RETURNVAL", stringcd);
28   }
29
30   public BasicBlock getBBlock(FlatMethod fm) {
31     if (!blockMap.containsKey(fm))
32       blockMap.put(fm, BasicBlock.getBBlock(fm));
33     return blockMap.get(fm);
34   }
35   
36   Delta buildInitialContext() {
37     MethodDescriptor md=typeUtil.getMain();
38     FlatMethod fm=state.getMethodFlat(md);
39     BasicBlock bb=getBBlock(fm);
40     BBlock start=bb.getStart();
41     Delta delta=new Delta(start, true);
42     HashSet<Edge> arrayset=new HashSet<Edge>();
43     HashSet<Edge> varset=new HashSet<Edge>();
44     arrayset.add(new Edge(allocFactory.StringArray, null, allocFactory.Strings));
45     varset.add(new Edge(fm.getParameter(0), allocFactory.StringArray));
46     delta.heapedgeadd.put(allocFactory.StringArray, arrayset);
47     delta.varedgeadd.put(fm.getParameter(0), varset);
48     return delta;
49   }
50
51   public void doAnalysis() {
52     toprocess.add(buildInitialContext());
53
54     while(!toprocess.isEmpty()) {
55       Delta delta=toprocess.remove();
56       BBlock bblock=delta.getBlock();
57       Vector<FlatNode> nodes=bblock.nodes();
58
59       //Build base graph for entrance to this basic block
60       delta=applyInitDelta(delta, bblock);
61       Graph graph=bbgraphMap.get(bblock);
62
63       Graph nodeGraph=null;
64       //Compute delta at exit of each node
65       for(int i=0; i<nodes.size();i++) {
66         FlatNode currNode=nodes.get(i);
67         if (!graphMap.containsKey(currNode)) {
68           graphMap.put(currNode, new Graph(graph));
69         }
70         nodeGraph=graphMap.get(currNode);
71         delta=processNode(currNode, delta, nodeGraph);
72       }
73       generateFinalDelta(bblock, delta, nodeGraph);
74     }    
75   }
76
77   void generateFinalDelta(BBlock bblock, Delta delta, Graph graph) {
78     Delta newDelta=new Delta(null, false);
79     if (delta.getInit()) {
80       //First compute the set of temps
81       HashSet<TempDescriptor> tmpSet=new HashSet<TempDescriptor>();
82       tmpSet.addAll(graph.varMap.keySet());
83       tmpSet.addAll(graph.parent.varMap.keySet());
84
85       //Next build the temp map part of the delta
86       for(TempDescriptor tmp:tmpSet) {
87         HashSet<Edge> edgeSet=new HashSet<Edge>();
88         /* Get target set */
89         if (graph.varMap.containsKey(tmp))
90           edgeSet.addAll(graph.varMap.get(tmp));
91         else
92           edgeSet.addAll(graph.parent.varMap.get(tmp));
93         newDelta.varedgeadd.put(tmp, edgeSet);
94       }
95
96       //Next compute the set of src allocnodes
97       HashSet<AllocNode> nodeSet=new HashSet<AllocNode>();
98       nodeSet.addAll(graph.nodeMap.keySet());
99       nodeSet.addAll(graph.parent.nodeMap.keySet());
100
101       for(AllocNode node:nodeSet) {
102         HashSet<Edge> edgeSet=new HashSet<Edge>();
103         /* Get edge set */
104         if (graph.nodeMap.containsKey(node))
105           edgeSet.addAll(graph.nodeMap.get(node));
106         else
107           edgeSet.addAll(graph.parent.nodeMap.get(node));
108         newDelta.heapedgeadd.put(node, edgeSet);
109       }
110     } else {
111       /* We can break the old delta...it is done being used */
112       /* First we will build variable edges */
113       HashSet<TempDescriptor> tmpSet=new HashSet<TempDescriptor>();
114       tmpSet.addAll(delta.basevaredge.keySet());
115       tmpSet.addAll(delta.varedgeadd.keySet());
116       for(TempDescriptor tmp:tmpSet) {
117         /* Start with the new incoming edges */
118         HashSet<Edge> newbaseedge=delta.basevaredge.get(tmp);
119         /* Remove the remove set */
120         newbaseedge.removeAll(delta.varedgeremove.get(tmp));
121         /* Add in the new set*/
122         newbaseedge.addAll(delta.varedgeadd.get(tmp));
123         /* Store the results */
124         newDelta.varedgeadd.put(tmp, newbaseedge);
125       }
126
127       /* Next we build heap edges */
128       HashSet<AllocNode> nodeSet=new HashSet<AllocNode>();
129       nodeSet.addAll(delta.baseheapedge.keySet());
130       nodeSet.addAll(delta.heapedgeadd.keySet());
131       nodeSet.addAll(delta.heapedgeremove.keySet());
132       for(AllocNode node:nodeSet) {
133         /* Start with the new incoming edges */
134         HashSet<Edge> newheapedge=(HashSet<Edge>) delta.baseheapedge.get(node).clone();
135         /* Remove the remove set */
136         newheapedge.removeAll(delta.heapedgeremove.get(node));
137         /* Add in the add set */
138         newheapedge.addAll(delta.heapedgeadd.get(node));
139         newDelta.heapedgeadd.put(node, newheapedge);
140
141         /* Also need to subtract off some edges */
142         HashSet<Edge> removeset=delta.heapedgeremove.get(node);
143         /* Remove the newly created edges..no need to propagate a diff for those */
144         removeset.removeAll(delta.baseheapedge.get(node));
145         newDelta.heapedgeremove.put(node, removeset);
146       }
147     }
148     /* Now we need to propagate newdelta */
149     if (!newDelta.heapedgeadd.isEmpty()||!newDelta.heapedgeremove.isEmpty()||!newDelta.varedgeadd.isEmpty()) {
150       /* We have a delta to propagate */
151       Vector<BBlock> blockvector=bblock.next();
152       for(int i=0;i<blockvector.size();i++) {
153         if (i==0) {
154           newDelta.setBlock(blockvector.get(i));
155           toprocess.add(newDelta);
156         } else {
157           toprocess.add(newDelta.diffBlock(blockvector.get(i)));
158         }
159       }
160     }
161   }
162
163   Delta processNode(FlatNode node, Delta delta, Graph newgraph) {
164     switch(node.kind()) {
165     case FKind.FlatNew:
166       return processNewNode((FlatNew)node, delta, newgraph);
167     case FKind.FlatFieldNode:
168     case FKind.FlatElementNode:
169       return processFieldElementNode(node, delta, newgraph);
170     case FKind.FlatCastNode:
171     case FKind.FlatOpNode:
172     case FKind.FlatReturnNode:
173       return processCopyNode(node, delta, newgraph);
174     case FKind.FlatSetFieldNode:
175     case FKind.FlatSetElementNode:
176       return processSetFieldElementNode(node, delta, newgraph);
177     case FKind.FlatMethod:
178     case FKind.FlatExit:
179       return processFlatNop(node, delta, newgraph);
180     case FKind.FlatCall:
181     case FKind.FlatSESEEnterNode:
182     case FKind.FlatSESEExitNode:
183       throw new Error("Unimplemented node:"+node);
184     default:
185       throw new Error("Unrecognized node:"+node);
186     }
187   }
188
189   void applyDiffs(Graph graph, Delta delta) {
190     //Add hidden base edges
191     for(Map.Entry<AllocNode, HashSet<Edge>> e: delta.baseheapedge.entrySet()) {
192       AllocNode node=e.getKey();
193       HashSet<Edge> edges=e.getValue();
194       if (graph.nodeMap.containsKey(node)) {
195         HashSet<Edge> nodeEdges=graph.nodeMap.get(node);
196         nodeEdges.addAll(edges);
197       }
198     }
199
200     //Remove heap edges
201     for(Map.Entry<AllocNode, HashSet<Edge>> e: delta.heapedgeremove.entrySet()) {
202       AllocNode node=e.getKey();
203       HashSet<Edge> edgestoremove=e.getValue();
204       if (graph.nodeMap.containsKey(node)) {
205         //Just apply diff to current map
206         graph.nodeMap.get(node).removeAll(edgestoremove);
207       } else {
208         //Generate diff from parent graph
209         HashSet<Edge> parentedges=graph.parent.nodeMap.get(node);
210         HashSet<Edge> newedgeset=Util.setSubtract(parentedges, edgestoremove);
211         graph.nodeMap.put(node, newedgeset);
212       }
213     }
214
215     //Add heap edges
216     for(Map.Entry<AllocNode, HashSet<Edge>> e: delta.heapedgeadd.entrySet()) {
217       AllocNode node=e.getKey();
218       HashSet<Edge> edgestoadd=e.getValue();
219       //If we have not done a subtract, then 
220       if (!graph.nodeMap.containsKey(node)) {
221         //Copy the parent entry
222         graph.nodeMap.put(node, (HashSet<Edge>)graph.parent.nodeMap.get(node).clone());
223       }
224       graph.nodeMap.get(node).addAll(edgestoadd);
225     }
226
227     //Remove var edges
228     for(Map.Entry<TempDescriptor, HashSet<Edge>> e: delta.varedgeremove.entrySet()) {
229       TempDescriptor tmp=e.getKey();
230       HashSet<Edge> edgestoremove=e.getValue();
231
232       if (graph.varMap.containsKey(tmp)) {
233         //Just apply diff to current map
234         graph.varMap.get(tmp).removeAll(edgestoremove);
235       } else {
236         //Generate diff from parent graph
237         HashSet<Edge> parentedges=graph.parent.varMap.get(tmp);
238         HashSet<Edge> newedgeset=Util.setSubtract(parentedges, edgestoremove);
239         graph.varMap.put(tmp, newedgeset);
240       }
241     }
242
243     //Add var edges
244     for(Map.Entry<TempDescriptor, HashSet<Edge>> e: delta.varedgeadd.entrySet()) {
245       TempDescriptor tmp=e.getKey();
246       HashSet<Edge> edgestoadd=e.getValue();
247       graph.varMap.put(tmp, (HashSet<Edge>) edgestoadd.clone());
248     }
249   }
250
251   Delta processSetFieldElementNode(FlatNode node, Delta delta, Graph graph) {
252     TempDescriptor src;
253     FieldDescriptor fd;
254     TempDescriptor dst;
255     if (node.kind()==FKind.FlatSetElementNode) {
256       FlatSetElementNode fen=(FlatSetElementNode) node;
257       src=fen.getSrc();
258       fd=null;
259       dst=fen.getDst();
260     } else {
261       FlatSetFieldNode ffn=(FlatSetFieldNode) node;
262       src=ffn.getSrc();
263       fd=ffn.getField();
264       dst=ffn.getDst();
265     }
266     if (delta.getInit()) {
267       HashSet<AllocNode> srcNodes=GraphManip.getNodes(graph, delta, src);
268       HashSet<AllocNode> dstNodes=GraphManip.getNodes(graph, delta, dst);
269       HashSet<Edge> edgesToAdd=GraphManip.genEdges(srcNodes, fd, dstNodes);
270       HashSet<Edge> edgesToRemove=null;
271       if (dstNodes.size()==1&&!dstNodes.iterator().next().isSummary()) {
272         /* Can do a strong update */
273         edgesToRemove=GraphManip.getEdges(graph, delta, dstNodes, fd);
274       }
275       /* Update diff */
276       updateHeapDelta(graph, delta, edgesToAdd, edgesToRemove);
277       applyDiffs(graph, delta);
278     } else {
279       /* First look at new sources */
280       HashSet<Edge> edgesToAdd=new HashSet<Edge>();
281       HashSet<AllocNode> newSrcNodes=GraphManip.getDiffNodes(delta, src);
282       HashSet<AllocNode> dstNodes=GraphManip.getDiffNodes(delta, dst);
283       edgesToAdd.addAll(GraphManip.genEdges(newSrcNodes, fd, dstNodes));
284       HashSet<AllocNode> newDstNodes=GraphManip.getDiffNodes(delta, dst);
285       HashSet<Edge> edgesToRemove=null;
286       if (newDstNodes.size()!=0) {
287         if (dstNodes.size()==1&&!dstNodes.iterator().next().isSummary()) {
288           /* Need to undo strong update */
289           if (graph.strongUpdateSet!=null) {
290             edgesToAdd.addAll(graph.strongUpdateSet);
291             graph.strongUpdateSet.clear();
292           }
293         } else if (dstNodes.size()==0&&newDstNodes.size()==1&&!newDstNodes.iterator().next().isSummary()&&graph.strongUpdateSet==null) {
294           edgesToRemove=GraphManip.getEdges(graph, delta, dstNodes, fd);
295         }
296         HashSet<AllocNode> srcNodes=GraphManip.getDiffNodes(delta, src);
297         edgesToAdd.addAll(GraphManip.genEdges(srcNodes, fd, newDstNodes));
298       }
299       /* Update diff */
300       updateHeapDelta(graph, delta, edgesToAdd, edgesToRemove);
301       applyDiffs(graph, delta);
302     }
303     return delta;
304   }
305
306   Delta processCopyNode(FlatNode node, Delta delta, Graph graph) {
307     TempDescriptor src;
308     TempDescriptor dst;
309     if (node.kind()==FKind.FlatOpNode) {
310       FlatOpNode fon=(FlatOpNode) node;
311       src=fon.getLeft();
312       dst=fon.getDest();
313     } else if (node.kind()==FKind.FlatReturnNode) {
314       FlatReturnNode frn=(FlatReturnNode)node;
315       src=frn.getReturnTemp();
316       dst=returntmp;
317     } else {
318       FlatCastNode fcn=(FlatCastNode) node;
319       src=fcn.getSrc();
320       dst=fcn.getDst();
321     }
322     if (delta.getInit()) {
323       HashSet<AllocNode> srcnodes=GraphManip.getNodes(graph, delta, src);
324       HashSet<Edge> edgesToAdd=GraphManip.genEdges(src, srcnodes);
325       HashSet<Edge> edgesToRemove=GraphManip.getEdges(graph, delta, dst);
326       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
327       applyDiffs(graph, delta);
328     } else {
329       /* First compute new src nodes */
330       HashSet<AllocNode> newSrcNodes=GraphManip.getDiffNodes(delta, src);
331
332       /* Compute the union, and then the set of edges */
333       HashSet<Edge> edgesToAdd=GraphManip.genEdges(src, newSrcNodes);
334       
335       /* Compute set of edges to remove */
336       HashSet<Edge> edgesToRemove=GraphManip.getDiffEdges(delta, dst);      
337
338       /* Update diff */
339       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
340       applyDiffs(graph, delta);
341     }
342     return delta;
343   }
344
345   Delta processFieldElementNode(FlatNode node, Delta delta, Graph graph) {
346     TempDescriptor src;
347     FieldDescriptor fd;
348     TempDescriptor dst;
349     if (node.kind()==FKind.FlatElementNode) {
350       FlatElementNode fen=(FlatElementNode) node;
351       src=fen.getSrc();
352       fd=null;
353       dst=fen.getDst();
354     } else {
355       FlatFieldNode ffn=(FlatFieldNode) node;
356       src=ffn.getSrc();
357       fd=ffn.getField();
358       dst=ffn.getDst();
359     }
360     if (delta.getInit()) {
361       HashSet<AllocNode> srcnodes=GraphManip.getNodes(graph, delta, src);
362       HashSet<AllocNode> fdnodes=GraphManip.getNodes(graph, delta, srcnodes, fd);
363       HashSet<Edge> edgesToAdd=GraphManip.genEdges(src, fdnodes);
364       HashSet<Edge> edgesToRemove=GraphManip.getEdges(graph, delta, dst);
365       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
366       applyDiffs(graph, delta);
367     } else {
368       /* First compute new objects we read fields of */
369       HashSet<AllocNode> allsrcnodes=GraphManip.getNodes(graph, delta, src);
370       HashSet<AllocNode> difffdnodes=GraphManip.getDiffNodes(delta, allsrcnodes, fd);     
371       /* Next compute new targets of fields */
372       HashSet<AllocNode> newsrcnodes=GraphManip.getDiffNodes(delta, src);
373       HashSet<AllocNode> newfdnodes=GraphManip.getNodes(graph, delta, newsrcnodes, fd);
374       /* Compute the union, and then the set of edges */
375       HashSet<AllocNode> newTargets=new HashSet<AllocNode>();
376       newTargets.addAll(newfdnodes);
377       newTargets.addAll(difffdnodes);
378       HashSet<Edge> edgesToAdd=GraphManip.genEdges(src, newTargets);      
379       
380       /* Compute set of edges to remove */
381       HashSet<Edge> edgesToRemove=GraphManip.getDiffEdges(delta, dst);      
382
383       /* Update diff */
384       updateVarDelta(graph, delta, dst, edgesToAdd, edgesToRemove);
385       applyDiffs(graph, delta);
386     }
387     return delta;
388   }
389
390   static void updateVarDelta(Graph graph, Delta delta, TempDescriptor tmp, HashSet<Edge> edgestoAdd, HashSet<Edge> edgestoRemove) {
391     HashSet<Edge> edgeAdd=delta.varedgeadd.get(tmp);
392     HashSet<Edge> edgeRemove=delta.varedgeremove.get(tmp);
393     HashSet<Edge> existingEdges=graph.getEdges(tmp);
394     for(Edge e: edgestoRemove) {
395       //remove edge from delta
396       edgeAdd.remove(e);
397       //if the edge is already in the graph, add an explicit remove to the delta
398       if (existingEdges.contains(e))
399         edgeRemove.add(e);
400     }
401     for(Edge e: edgestoAdd) {
402       //Remove the edge from the remove set
403       edgeRemove.remove(e);
404       //Explicitly add it to the add set unless it is already in the graph
405       if (!existingEdges.contains(e))
406         edgeAdd.add(e);
407     }
408   }
409
410   static void updateHeapDelta(Graph graph, Delta delta, HashSet<Edge> edgestoAdd, HashSet<Edge> edgestoRemove) {
411     for(Edge e: edgestoRemove) {
412       AllocNode src=e.src;
413       HashSet<Edge> edgeAdd=delta.heapedgeadd.get(src);
414       HashSet<Edge> existingEdges=graph.getEdges(src);
415       //remove edge from delta
416       edgeAdd.remove(e);
417       //if the edge is already in the graph, add an explicit remove to the delta
418       if (existingEdges.contains(e)) {
419         HashSet<Edge> edgeRemove=delta.heapedgeremove.get(src);
420         edgeRemove.add(e);
421       }
422     }
423     for(Edge e: edgestoAdd) {
424       AllocNode src=e.src;
425       HashSet<Edge> edgeRemove=delta.heapedgeremove.get(src);
426       HashSet<Edge> existingEdges=graph.getEdges(src);
427       //Remove the edge from the remove set
428       edgeRemove.remove(e);
429       //Explicitly add it to the add set unless it is already in the graph
430       if (!existingEdges.contains(e)) {
431         HashSet<Edge> edgeAdd=delta.heapedgeadd.get(src);
432         edgeAdd.add(e);
433       }
434     }
435   }
436
437   Delta processFlatNop(FlatNode node, Delta delta, Graph graph) {
438     applyDiffs(graph, delta);
439     return delta;
440   }
441
442   Delta processNewNode(FlatNew node, Delta delta, Graph graph) {
443     AllocNode summary=allocFactory.getAllocNode(node, true);
444     AllocNode single=allocFactory.getAllocNode(node, false);
445     TempDescriptor tmp=node.getDst();
446       
447     if (delta.getInit()) {
448       //Build new Edge
449       Edge e=new Edge(tmp, single);
450       //Build new Edge set
451       HashSet<Edge> newedges=new HashSet<Edge>();
452       newedges.add(e);
453       //Add it into the diffs
454       delta.varedgeadd.put(tmp, newedges);
455       //Remove the old edges
456       delta.varedgeremove.put(tmp, graph.getEdges(tmp));
457       //Apply incoming diffs to graph
458       applyDiffs(graph, delta);
459     } else {
460       /* 1. Fix up the variable edge additions */
461
462       for(Iterator<Map.Entry<TempDescriptor, HashSet<Edge>>> entryIt=delta.varedgeadd.entrySet().iterator();entryIt.hasNext();) {
463         Map.Entry<TempDescriptor, HashSet<Edge>> entry=entryIt.next();
464
465         if (entry.getKey()==tmp) {
466           /* Check if this is the tmp we overwrite */
467           entryIt.remove();
468         } else {
469           /* Otherwise, check if the target of the edge is changed... */
470           rewriteSet(entry.getValue(), graph.varMap.get(entry.getKey()), single, summary);
471         }
472       }
473       
474       /* 2. Fix up the base variable edges */
475
476       for(Iterator<Map.Entry<TempDescriptor, HashSet<Edge>>> entryIt=delta.basevaredge.entrySet().iterator();entryIt.hasNext();) {
477         Map.Entry<TempDescriptor, HashSet<Edge>> entry=entryIt.next();
478         TempDescriptor entrytmp=entry.getKey();
479         if (entrytmp==tmp) {
480           /* Check is this is the tmp we overwrite, if so add to remove set */
481           Util.relationUpdate(delta.varedgeremove, tmp, null, entry.getValue());
482         } else {
483           /* Check if the target of the edge is changed */ 
484           HashSet<Edge> newset=(HashSet<Edge>)entry.getValue().clone();
485           HashSet<Edge> removeset=shrinkSet(newset, graph.varMap.get(entrytmp), single, summary);
486           Util.relationUpdate(delta.varedgeremove, entrytmp, newset, removeset);
487           Util.relationUpdate(delta.varedgeadd, entrytmp, null, newset);
488         }
489       }
490
491
492       /* 3. Fix up heap edge additions */
493
494       HashMap<AllocNode, HashSet<Edge>> addheapedge=new HashMap<AllocNode, HashSet<Edge>>();
495       for(Iterator<Map.Entry<AllocNode, HashSet<Edge>>> entryIt=delta.heapedgeadd.entrySet().iterator();entryIt.hasNext();) {
496         Map.Entry<AllocNode, HashSet<Edge>> entry=entryIt.next();
497         HashSet<Edge> edgeset=entry.getValue();
498         AllocNode allocnode=entry.getKey();
499         if (allocnode==single) {
500           entryIt.remove();
501           rewriteSet(edgeset, graph.nodeMap.get(summary), single, summary);
502           addheapedge.put(summary, edgeset);
503         } else {
504           rewriteSet(edgeset, graph.nodeMap.get(allocnode), single, summary);
505         }
506       }
507       
508       /* Merge in diffs */
509
510       for(Map.Entry<AllocNode, HashSet<Edge>> entry:addheapedge.entrySet()) {
511         AllocNode allocnode=entry.getKey();
512         Util.relationUpdate(delta.heapedgeadd, allocnode, null, entry.getValue());
513       }
514
515       /* 4. Fix up the base heap edges */
516
517       for(Iterator<Map.Entry<AllocNode, HashSet<Edge>>> entryIt=delta.baseheapedge.entrySet().iterator();entryIt.hasNext();) {
518         Map.Entry<AllocNode, HashSet<Edge>> entry=entryIt.next();
519         HashSet<Edge> edgeset=entry.getValue();
520         AllocNode allocnode=entry.getKey();
521         if (allocnode==single) {
522           entryIt.remove();
523         }
524         AllocNode addnode=(allocnode==single)?summary:allocnode;
525
526         HashSet<Edge> newset=(HashSet<Edge>) edgeset.clone();
527         HashSet<Edge> removeset=shrinkSet(newset, graph.nodeMap.get(addnode), single, summary);
528         Util.relationUpdate(delta.heapedgeadd, addnode, null, newset);
529         Util.relationUpdate(delta.heapedgeremove, allocnode, null, removeset);
530       }
531       
532       //Apply incoming diffs to graph
533       applyDiffs(graph, delta);      
534     }
535     return delta;
536   }
537
538   void rewriteSet(HashSet<Edge> edgeset, HashSet<Edge> oldedgeset, AllocNode oldnode, AllocNode newnode) {
539     HashSet<Edge> newSet=null;
540     for(Iterator<Edge> edgeit=edgeset.iterator();edgeit.hasNext();) {
541       Edge e=edgeit.next();
542       if (e.dst==oldnode||e.src==oldnode) {
543         if (newSet==null) {
544           newSet=new HashSet<Edge>();
545         }
546         edgeit.remove();
547         if (e.dst==oldnode)
548           e.dst=newnode;
549         if (e.src==oldnode)
550           e.src=newnode;
551         if (oldedgeset==null||!oldedgeset.contains(e))
552           newSet.add(e);
553       }
554     }
555     if (newSet!=null)
556       edgeset.addAll(newSet);
557   }
558
559   /* Shrinks the incoming set to just include rewritten values.
560    * Returns a set of the original rewritten values */
561
562   HashSet<Edge> shrinkSet(HashSet<Edge> edgeset, HashSet<Edge> oldedgeset, AllocNode oldnode, AllocNode newnode) {
563     HashSet<Edge> newSet=null;
564     HashSet<Edge> removeSet=null;
565     for(Iterator<Edge> edgeit=edgeset.iterator();edgeit.hasNext();) {
566       Edge e=edgeit.next();
567       edgeit.remove();
568       if (e.dst==oldnode||e.src==oldnode) {
569         if (newSet==null) {
570           newSet=new HashSet<Edge>();
571           removeSet=new HashSet<Edge>();
572         }
573
574         removeSet.add(e.copy());
575         if (e.dst==oldnode)
576           e.dst=newnode;
577         if (e.src==oldnode)
578           e.src=newnode;
579         if (oldedgeset==null||!oldedgeset.contains(e))
580           newSet.add(e);
581       }
582     }
583     if (newSet!=null)
584       edgeset.addAll(newSet);
585     return removeSet;
586   } 
587
588   Delta applyInitDelta(Delta delta, BBlock block) {
589     //Apply delta to graph
590     boolean newGraph=false;
591     if (!bbgraphMap.containsKey(block)) {
592       bbgraphMap.put(block, new Graph(null));
593       newGraph=true;
594     }
595     Delta newdelta;
596     Graph graph=bbgraphMap.get(block);
597
598     if (newGraph) {
599       newdelta=new Delta(null, true);
600       //Add in heap edges and throw away original diff
601       graph.nodeMap.putAll(delta.heapedgeadd);
602       //Add in var edges and throw away original diff
603       graph.varMap.putAll(delta.varedgeadd);
604       //Record that this is initial set...
605     } else {
606       newdelta=new Delta(null, false);
607       //merge in heap edges and variables
608       mergeHeapEdges(graph, delta, newdelta);
609       mergeVarEdges(graph, delta, newdelta);
610       //Record that this is a diff
611       newdelta.setInit(false);
612     }
613     return newdelta;
614   }
615
616   /* This function merges in the heap edges.  It updates delta to be
617    * the difference */
618
619   void mergeHeapEdges(Graph graph, Delta delta, Delta newdelta) {
620     //Merge in edges
621     for(Map.Entry<AllocNode, HashSet<Edge>> heapedge:delta.heapedgeadd.entrySet()) {
622       AllocNode nsrc=heapedge.getKey();
623       HashSet<Edge> edges=heapedge.getValue();
624       if (!graph.nodeMap.containsKey(nsrc)) {
625         graph.nodeMap.put(nsrc, new HashSet<Edge>());
626       }
627       HashSet<Edge> dstedges=graph.nodeMap.get(nsrc);
628       HashSet<Edge> diffedges=new HashSet<Edge>();
629       for(Edge e:edges) {
630         if (!dstedges.contains(e)) {
631           //We have a new edge
632           diffedges.add(e);
633           dstedges.add(e);
634         }
635       }
636       //Done with edge set...
637       if (diffedges.size()>0) {
638         //completely new
639         newdelta.baseheapedge.put(nsrc, diffedges);
640       }
641     }
642   }
643
644   /* This function merges in the var edges.  It updates delta to be
645    * the difference */
646
647   void mergeVarEdges(Graph graph, Delta delta, Delta newdelta) {
648     //Merge in edges
649     for(Map.Entry<TempDescriptor, HashSet<Edge>> varedge:delta.varedgeadd.entrySet()) {
650       TempDescriptor tmpsrc=varedge.getKey();
651       HashSet<Edge> edges=varedge.getValue();
652       if (!graph.varMap.containsKey(tmpsrc)) {
653         graph.varMap.put(tmpsrc, new HashSet<Edge>());
654       }
655       HashSet<Edge> dstedges=graph.varMap.get(tmpsrc);
656       HashSet<Edge> diffedges=new HashSet<Edge>();
657       for(Edge e:edges) {
658         if (!dstedges.contains(e)) {
659           //We have a new edge
660           diffedges.add(e);
661           dstedges.add(e);
662         }
663       }
664       //Done with edge set...
665       if (diffedges.size()>=0) {
666         //completely new
667         newdelta.basevaredge.put(tmpsrc,diffedges);
668       }
669     }
670   }
671 }