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