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