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