2ab6dad9ce625cac5d96cda64b5d4f1f989c8b6a
[IRC.git] / Robust / src / Analysis / SSJava / FlowGraph.java
1 package Analysis.SSJava;
2
3 import java.io.BufferedWriter;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Iterator;
9 import java.util.Map;
10 import java.util.Set;
11
12 import IR.ClassDescriptor;
13 import IR.Descriptor;
14 import IR.FieldDescriptor;
15 import IR.MethodDescriptor;
16 import IR.VarDescriptor;
17
18 public class FlowGraph {
19
20   MethodDescriptor md;
21
22   Set<FlowNode> returnNodeSet;
23   FlowNode thisVarNode;
24
25   Map<FlowNode, Set<FlowEdge>> mapFlowNodeToInEdgeSet;
26   Map<FlowNode, Set<FlowEdge>> mapFlowNodeToOutEdgeSet;
27
28   Map<NTuple<Location>, FlowNode> mapLocTupleToFlowNode;
29   Map<FlowNode, NTuple<Location>> mapFlowNodeToLocTuple;
30
31   // maps the composite representation of field/var descriptors to infer nodes
32   Map<NTuple<Descriptor>, FlowNode> mapDescTupleToInferNode;
33
34   // maps a paramter descriptor to its index
35   Map<Descriptor, Integer> mapParamDescToIdx;
36
37   // DS for the lattice generation
38   Map<Integer, FlowNode> mapIdxToFlowNode;
39
40   public static int interseed = 0;
41
42   boolean debug = true;
43
44   public FlowGraph(MethodDescriptor md, Map<Descriptor, Integer> mapParamDescToIdx) {
45     this.md = md;
46     this.mapFlowNodeToLocTuple = new HashMap<FlowNode, NTuple<Location>>();
47     this.mapLocTupleToFlowNode = new HashMap<NTuple<Location>, FlowNode>();
48     this.mapDescTupleToInferNode = new HashMap<NTuple<Descriptor>, FlowNode>();
49     this.mapParamDescToIdx = new HashMap<Descriptor, Integer>();
50     this.mapParamDescToIdx.putAll(mapParamDescToIdx);
51     this.returnNodeSet = new HashSet<FlowNode>();
52     this.mapIdxToFlowNode = new HashMap<Integer, FlowNode>();
53     this.mapFlowNodeToOutEdgeSet = new HashMap<FlowNode, Set<FlowEdge>>();
54     this.mapFlowNodeToInEdgeSet = new HashMap<FlowNode, Set<FlowEdge>>();
55
56     if (!md.isStatic()) {
57       // create a node for 'this' varialbe
58       // NTuple<Descriptor> thisDescTuple = new NTuple<Descriptor>();
59       // thisDescTuple.add(md.getThis());
60
61       NTuple<Descriptor> thisVarTuple = new NTuple<Descriptor>();
62       thisVarTuple.add(md.getThis());
63       FlowNode thisNode = createNewFlowNode(thisVarTuple);
64       thisNode.setSkeleton(true);
65       thisVarNode = thisNode;
66     }
67
68     setupMapIdxToDesc();
69
70   }
71
72   public Map<NTuple<Descriptor>, FlowNode> getMapDescTupleToInferNode() {
73     return mapDescTupleToInferNode;
74   }
75
76   public void setMapDescTupleToInferNode(Map<NTuple<Descriptor>, FlowNode> in) {
77     this.mapDescTupleToInferNode.putAll(in);
78   }
79
80   public Map<NTuple<Location>, FlowNode> getMapLocTupleToFlowNode() {
81     return mapLocTupleToFlowNode;
82   }
83
84   public void setMapLocTupleToFlowNode(Map<NTuple<Location>, FlowNode> in) {
85     this.mapLocTupleToFlowNode.putAll(in);
86   }
87
88   public void setReturnNodeSet(Set<FlowNode> in) {
89     this.returnNodeSet.addAll(in);
90   }
91
92   public void setThisVarNode(FlowNode thisVarNode) {
93     this.thisVarNode = thisVarNode;
94   }
95
96   public Map<Descriptor, Integer> getMapParamDescToIdx() {
97     return mapParamDescToIdx;
98   }
99
100   public FlowNode createIntermediateNode() {
101     NTuple<Descriptor> tuple = new NTuple<Descriptor>();
102     Descriptor interDesc = new InterDescriptor(LocationInference.INTERLOC + interseed);
103     tuple.add(interDesc);
104     interseed++;
105
106     FlowNode newNode = new FlowNode(tuple);
107     newNode.setIntermediate(true);
108
109     mapDescTupleToInferNode.put(tuple, newNode);
110     // nodeSet.add(newNode);
111
112      System.out.println("create new intermediate node= " + newNode);
113
114     return newNode;
115   }
116
117   private void setupMapIdxToDesc() {
118
119     Set<Descriptor> descSet = mapParamDescToIdx.keySet();
120     for (Iterator iterator = descSet.iterator(); iterator.hasNext();) {
121       Descriptor paramDesc = (Descriptor) iterator.next();
122       int idx = mapParamDescToIdx.get(paramDesc);
123       NTuple<Descriptor> descTuple = new NTuple<Descriptor>();
124       descTuple.add(paramDesc);
125       FlowNode paramNode = getFlowNode(descTuple);
126       mapIdxToFlowNode.put(idx, paramNode);
127       paramNode.setSkeleton(true);
128     }
129
130   }
131
132   public int getNumParameters() {
133     return mapIdxToFlowNode.keySet().size();
134   }
135
136   public FlowNode getParamFlowNode(int idx) {
137     return mapIdxToFlowNode.get(idx);
138   }
139
140   public Set<FlowEdge> getEdgeSet() {
141     Set<FlowEdge> edgeSet = new HashSet<FlowEdge>();
142
143     Set<FlowNode> nodeSet = getNodeSet();
144     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
145       FlowNode flowNode = (FlowNode) iterator.next();
146       edgeSet.addAll(getOutEdgeSet(flowNode));
147     }
148
149     return edgeSet;
150   }
151
152   public Set<FlowNode> getNodeSet() {
153     Set<FlowNode> set = new HashSet<FlowNode>();
154     set.addAll(mapDescTupleToInferNode.values());
155     return set;
156   }
157
158   public MethodDescriptor getMethodDescriptor() {
159     return md;
160   }
161
162   public boolean isParamDesc(Descriptor desc) {
163
164     if (mapParamDescToIdx.containsKey(desc)) {
165       int idx = mapParamDescToIdx.get(desc);
166       if (!md.isStatic() && idx == 0) {
167         return false;
168       }
169       return true;
170     }
171
172     return false;
173   }
174
175   public boolean hasEdge(NTuple<Descriptor> fromDescTuple, NTuple<Descriptor> toDescTuple) {
176
177     FlowNode fromNode = mapDescTupleToInferNode.get(fromDescTuple);
178     FlowNode toNode = mapDescTupleToInferNode.get(toDescTuple);
179
180     Set<FlowEdge> fromNodeOutEdgeSet = getOutEdgeSet(fromNode);
181     for (Iterator iterator = fromNodeOutEdgeSet.iterator(); iterator.hasNext();) {
182       FlowEdge flowEdge = (FlowEdge) iterator.next();
183       if (flowEdge.getDst().equals(toNode)) {
184         return true;
185       } else {
186         if (hasEdge(flowEdge.getDst().getDescTuple(), toDescTuple)) {
187           return true;
188         }
189       }
190     }
191
192     return false;
193   }
194
195   public Set<FlowEdge> getOutEdgeSetStartingFrom(FlowNode startNode) {
196
197     Descriptor prefixDesc = startNode.getCurrentDescTuple().get(0);
198
199     // returns the set of edges that share the same prefix of startNode
200     Set<FlowEdge> edgeSet = new HashSet<FlowEdge>();
201
202     for (Iterator<Set<FlowEdge>> iter = mapFlowNodeToOutEdgeSet.values().iterator(); iter.hasNext();) {
203       Set<FlowEdge> nodeEdgeSet = iter.next();
204       for (Iterator<FlowEdge> iter2 = nodeEdgeSet.iterator(); iter2.hasNext();) {
205         FlowEdge edge = iter2.next();
206         if (edge.getInitTuple().get(0).equals(prefixDesc)) {
207           edgeSet.add(edge);
208         }
209       }
210     }
211
212     return edgeSet;
213   }
214
215   public Set<FlowEdge> getOutEdgeSet(FlowNode node) {
216     if (!mapFlowNodeToOutEdgeSet.containsKey(node)) {
217       mapFlowNodeToOutEdgeSet.put(node, new HashSet<FlowEdge>());
218     }
219     return mapFlowNodeToOutEdgeSet.get(node);
220   }
221
222   public Set<FlowEdge> getInEdgeSet(FlowNode node) {
223     if (!mapFlowNodeToInEdgeSet.containsKey(node)) {
224       mapFlowNodeToInEdgeSet.put(node, new HashSet<FlowEdge>());
225     }
226     return mapFlowNodeToInEdgeSet.get(node);
227   }
228
229   public void addValueFlowEdge(NTuple<Descriptor> fromDescTuple, NTuple<Descriptor> toDescTuple) {
230
231     FlowNode fromNode = getFlowNode(fromDescTuple);
232     FlowNode toNode = getFlowNode(toDescTuple);
233
234     if (toNode.getDescTuple().get(0).equals(LocationInference.LITERALDESC)) {
235       return;
236     }
237
238     System.out.println("create an edge from " + fromNode + " to " + toNode);
239
240     int fromTupleSize = fromDescTuple.size();
241     NTuple<Descriptor> curFromTuple = new NTuple<Descriptor>();
242     for (int i = 0; i < fromTupleSize; i++) {
243       Descriptor desc = fromDescTuple.get(i);
244       curFromTuple.add(desc);
245       int toTupleSize = toDescTuple.size();
246       NTuple<Descriptor> curToTuple = new NTuple<Descriptor>();
247       for (int k = 0; k < toTupleSize; k++) {
248         Descriptor toDesc = toDescTuple.get(k);
249         curToTuple.add(toDesc);
250         addFlowEdge(getFlowNode(curFromTuple), getFlowNode(curToTuple), fromDescTuple, toDescTuple);
251       }
252     }
253
254     // int fromTupleSize = fromDescTuple.size();
255     // NTuple<Descriptor> curTuple = new NTuple<Descriptor>();
256     // for (int i = 0; i < fromTupleSize; i++) {
257     // Descriptor desc = fromDescTuple.get(i);
258     // curTuple.add(desc);
259     // addFlowEdge(getFlowNode(curTuple), toNode, fromDescTuple, toDescTuple);
260     // }
261     //
262     // int toTupleSize = toDescTuple.size();
263     // curTuple = new NTuple<Descriptor>();
264     // for (int i = 0; i < toTupleSize; i++) {
265     // Descriptor desc = toDescTuple.get(i);
266     // curTuple.add(desc);
267     // addFlowEdge(fromNode, getFlowNode(curTuple), fromDescTuple, toDescTuple);
268     // }
269
270   }
271
272   private void addFlowEdge(FlowNode fromNode, FlowNode toNode, NTuple<Descriptor> initTuple,
273       NTuple<Descriptor> endTuple) {
274
275     FlowEdge edge = new FlowEdge(fromNode, toNode, initTuple, endTuple);
276     addOutEdge(fromNode, edge);
277     addInEdge(toNode, edge);
278
279     // System.out.println("add a new edge=" + edge);
280   }
281
282   private void addInEdge(FlowNode toNode, FlowEdge edge) {
283     getInEdgeSet(toNode).add(edge);
284   }
285
286   private void addOutEdge(FlowNode fromNode, FlowEdge edge) {
287     if (!mapFlowNodeToOutEdgeSet.containsKey(fromNode)) {
288       mapFlowNodeToOutEdgeSet.put(fromNode, new HashSet<FlowEdge>());
289     }
290     mapFlowNodeToOutEdgeSet.get(fromNode).add(edge);
291   }
292
293   public boolean contains(NTuple<Descriptor> descTuple) {
294     return mapDescTupleToInferNode.containsKey(descTuple);
295   }
296
297   public FlowNode getFlowNode(NTuple<Descriptor> descTuple) {
298     if (!mapDescTupleToInferNode.containsKey(descTuple)) {
299       FlowNode node = createNewFlowNode(descTuple);
300       mapDescTupleToInferNode.put(descTuple, node);
301     }
302     return mapDescTupleToInferNode.get(descTuple);
303   }
304
305   public FlowNode getThisVarNode() {
306     return thisVarNode;
307   }
308
309   public FlowNode createNewFlowNode(NTuple<Descriptor> tuple) {
310
311     if (!mapDescTupleToInferNode.containsKey(tuple)) {
312       FlowNode node = new FlowNode(tuple);
313       mapDescTupleToInferNode.put(tuple, node);
314       // nodeSet.add(node);
315
316       mapLocTupleToFlowNode.put(getLocationTuple(node), node);
317
318       if (tuple.size() > 1) {
319         NTuple<Descriptor> baseTuple = tuple.subList(0, tuple.size() - 1);
320         getFlowNode(baseTuple).addFieldNode(node);
321       }
322
323       // System.out.println("Creating new node=" + node);
324       return node;
325     } else {
326       return mapDescTupleToInferNode.get(tuple);
327     }
328
329   }
330
331   public void addReturnFlowNode(NTuple<Descriptor> tuple) {
332
333     if (!mapDescTupleToInferNode.containsKey(tuple)) {
334       createNewFlowNode(tuple);
335     }
336
337     FlowNode node = mapDescTupleToInferNode.get(tuple);
338     returnNodeSet.add(node);
339   }
340
341   public Set<FlowNode> getReturnNodeSet() {
342     return returnNodeSet;
343   }
344
345   public Set<FlowNode> getLocalReachFlowNodeSetFrom(FlowNode fn) {
346     Set<FlowNode> set = new HashSet<FlowNode>();
347     recurLocalReachFlowNodeSet(fn, set);
348     return set;
349   }
350
351   private void recurLocalReachFlowNodeSet(FlowNode fn, Set<FlowNode> visited) {
352
353     Set<FlowEdge> outEdgeSet = getOutEdgeSet(fn);
354     for (Iterator iterator = outEdgeSet.iterator(); iterator.hasNext();) {
355       FlowEdge edge = (FlowEdge) iterator.next();
356       FlowNode dstNode = edge.getDst();
357
358       if (!visited.contains(dstNode)) {
359         visited.add(dstNode);
360         recurLocalReachFlowNodeSet(dstNode, visited);
361       }
362     }
363
364   }
365
366   private void getReachFlowNodeSetFrom(FlowNode fn, Set<FlowNode> visited) {
367
368     Set<FlowEdge> outEdgeSet = getOutEdgeSet(fn);
369     for (Iterator iterator = outEdgeSet.iterator(); iterator.hasNext();) {
370       FlowEdge edge = (FlowEdge) iterator.next();
371
372       if (fn.equals(getFlowNode(edge.getInitTuple()))) {
373         FlowNode dstNode = getFlowNode(edge.getEndTuple());
374         if (!visited.contains(dstNode)) {
375           visited.add(dstNode);
376           getReachFlowNodeSetFrom(dstNode, visited);
377         }
378       }
379     }
380
381   }
382
383   public Set<FlowNode> getReachFlowNodeSetFrom(FlowNode fn) {
384     Set<FlowNode> set = new HashSet<FlowNode>();
385     getReachFlowNodeSetFrom(fn, set);
386     return set;
387   }
388
389   public Set<FlowNode> getReachableSetFrom(NTuple<Descriptor> prefix) {
390     Set<FlowNode> reachableSet = new HashSet<FlowNode>();
391
392     Set<FlowNode> nodeSet = getNodeSet();
393     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
394       FlowNode flowNode = (FlowNode) iterator.next();
395       if (flowNode.getCurrentDescTuple().startsWith(prefix)) {
396         recurReachableSetFrom(flowNode, reachableSet);
397       }
398     }
399
400     return reachableSet;
401   }
402
403   // private void getReachFlowNodeSetFrom(FlowNode fn, Set<FlowNode> visited) {
404   //
405   // for (Iterator iterator = fn.getOutEdgeSet().iterator();
406   // iterator.hasNext();) {
407   // FlowEdge edge = (FlowEdge) iterator.next();
408   //
409   // if (fn.equals(getFlowNode(edge.getInitTuple()))) {
410   //
411   // FlowNode dstNode = getFlowNode(edge.getEndTuple());
412   //
413   // if (!visited.contains(dstNode)) {
414   // visited.add(dstNode);
415   // getReachFlowNodeSetFrom(dstNode, visited);
416   // }
417   // }
418   // }
419   //
420   // }
421
422   private void recurReachableSetFrom(FlowNode curNode, Set<FlowNode> reachableSet) {
423
424     Set<FlowEdge> edgeSet = getOutEdgeSet(curNode);
425     for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) {
426       FlowEdge edge = (FlowEdge) iterator.next();
427       FlowNode dstNode = getFlowNode(edge.getEndTuple());
428       if (!reachableSet.contains(dstNode)) {
429         reachableSet.add(dstNode);
430         recurReachableSetFrom(dstNode, reachableSet);
431       }
432     }
433
434   }
435
436   public Set<NTuple<Location>> getReachableFlowTupleSet(Set<NTuple<Location>> visited, FlowNode fn) {
437
438     Set<FlowEdge> outEdgeSet = getOutEdgeSet(fn);
439
440     for (Iterator iterator = outEdgeSet.iterator(); iterator.hasNext();) {
441       FlowEdge edge = (FlowEdge) iterator.next();
442
443       if (fn.getDescTuple().equals(edge.getInitTuple())) {
444         FlowNode dstNode = getFlowNode(edge.getEndTuple());
445         NTuple<Location> dstTuple = getLocationTuple(dstNode);
446
447         if (!visited.contains(dstTuple)) {
448           visited.add(dstTuple);
449           visited.addAll(getReachableFlowTupleSet(visited, dstNode));
450         }
451
452       }
453     }
454     return visited;
455   }
456
457   public NTuple<Location> getLocationTuple(NTuple<Descriptor> descTuple) {
458     return getLocationTuple(getFlowNode(descTuple));
459   }
460
461   public NTuple<Location> getLocationTuple(FlowNode fn) {
462
463     if (!mapFlowNodeToLocTuple.containsKey(fn)) {
464       NTuple<Descriptor> descTuple = fn.getDescTuple();
465       NTuple<Location> locTuple = new NTuple<Location>();
466       ClassDescriptor cd = null;
467
468       Descriptor localDesc = fn.getDescTuple().get(0);
469
470       if (fn.isIntermediate()) {
471         Location interLoc = new Location(md, localDesc.getSymbol());
472         interLoc.setLocDescriptor(localDesc);
473         locTuple.add(interLoc);
474       } else if (localDesc.getSymbol().equals(SSJavaAnalysis.TOP)) {
475         Location topLoc = new Location(md, Location.TOP);
476         topLoc.setLocDescriptor(LocationInference.TOPDESC);
477         locTuple.add(topLoc);
478       } else if (localDesc.getSymbol().equals(LocationInference.GLOBALLOC)) {
479         Location globalLoc = new Location(md, LocationInference.GLOBALLOC);
480         globalLoc.setLocDescriptor(LocationInference.GLOBALDESC);
481         locTuple.add(globalLoc);
482       } else {
483         // normal case
484         for (int i = 0; i < descTuple.size(); i++) {
485           Descriptor curDesc = descTuple.get(i);
486           Location loc;
487           if (i == 0) {
488             loc = new Location(md, curDesc.getSymbol());
489             loc.setLocDescriptor(curDesc);
490             if (curDesc instanceof VarDescriptor) {
491               cd = ((VarDescriptor) curDesc).getType().getClassDesc();
492             } else {
493               // otherwise it should be the last element
494               cd = null;
495             }
496           } else {
497             loc = new Location(cd, curDesc.getSymbol());
498             loc.setLocDescriptor(curDesc);
499
500             if (curDesc instanceof FieldDescriptor) {
501               cd = ((FieldDescriptor) curDesc).getType().getClassDesc();
502             } else if (curDesc instanceof LocationDescriptor) {
503               cd = ((LocationDescriptor) curDesc).getEnclosingClassDesc();
504             } else {
505               // otherwise it should be the last element of the tuple
506               cd = null;
507             }
508
509           }
510           locTuple.add(loc);
511         }
512       }
513
514       mapFlowNodeToLocTuple.put(fn, locTuple);
515     }
516     return mapFlowNodeToLocTuple.get(fn);
517   }
518
519   public Set<FlowNode> getIncomingFlowNodeSet(FlowNode node) {
520     Set<FlowNode> set = new HashSet<FlowNode>();
521     getIncomingFlowNodeSet(node, set);
522     return set;
523   }
524
525   public void getIncomingFlowNodeSet(FlowNode node, Set<FlowNode> visited) {
526
527     for (Iterator iterator = getNodeSet().iterator(); iterator.hasNext();) {
528       FlowNode curNode = (FlowNode) iterator.next();
529       Set<FlowEdge> edgeSet = getOutEdgeSet(curNode);
530
531       for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
532         FlowEdge flowEdge = (FlowEdge) iterator2.next();
533
534         if (node.equals(getFlowNode(flowEdge.getEndTuple()))) {
535           FlowNode incomingNode = getFlowNode(flowEdge.getInitTuple());
536
537           if (!visited.contains(incomingNode)) {
538             visited.add(incomingNode);
539             getIncomingFlowNodeSet(incomingNode, visited);
540           }
541         }
542       }
543     }
544
545   }
546
547   public Set<NTuple<Location>> getIncomingFlowTupleSet(FlowNode fn) {
548
549     NTuple<Descriptor> dstTuple = fn.getDescTuple();
550
551     Set<NTuple<Location>> set = new HashSet<NTuple<Location>>();
552
553     ClassDescriptor cd = null;
554
555     for (Iterator iterator = getNodeSet().iterator(); iterator.hasNext();) {
556       FlowNode node = (FlowNode) iterator.next();
557
558       Set<FlowEdge> edgeSet = getOutEdgeSet(node);
559       for (Iterator iterator2 = edgeSet.iterator(); iterator2.hasNext();) {
560         FlowEdge flowEdge = (FlowEdge) iterator2.next();
561         if (dstTuple.equals(flowEdge.getEndTuple())) {
562           NTuple<Descriptor> initTuple = flowEdge.getInitTuple();
563           NTuple<Location> locTuple = new NTuple<Location>();
564           for (int i = 0; i < initTuple.size(); i++) {
565             Descriptor d = initTuple.get(i);
566             Location loc;
567             if (i == 0) {
568               loc = new Location(md, d.getSymbol());
569               cd = ((VarDescriptor) d).getType().getClassDesc();
570             } else {
571               loc = new Location(cd, d.getSymbol());
572               cd = ((FieldDescriptor) d).getType().getClassDesc();
573             }
574             locTuple.add(loc);
575           }
576           set.add(locTuple);
577         }
578       }
579     }
580     return set;
581   }
582
583   public boolean isParameter(NTuple<Descriptor> tuple) {
584     // return true if a descriptor tuple is started with a parameter descriptor
585     Descriptor firstIdxDesc = tuple.get(0);
586     return mapParamDescToIdx.containsKey(firstIdxDesc);
587   }
588
589   public int getParamIdx(NTuple<Descriptor> tuple) {
590     Descriptor firstIdxDesc = tuple.get(0);
591     return mapParamDescToIdx.get(firstIdxDesc);
592   }
593
594   public FlowGraph clone() {
595     FlowGraph clone = new FlowGraph(md, mapParamDescToIdx);
596
597     // clone.setNodeSet(getNodeSet());
598     clone.setMapLocTupleToFlowNode(getMapLocTupleToFlowNode());
599     clone.setMapFlowNodeToLocTuple(getMapFlowNodeToLocTuple());
600     clone.setMapDescTupleToInferNode(getMapDescTupleToInferNode());
601
602     clone.setMapFlowNodeToOutEdgeSet(getMapFlowNodeToOutEdgeSet());
603     clone.setReturnNodeSet(getReturnNodeSet());
604     clone.setThisVarNode(getThisVarNode());
605
606     return clone;
607   }
608
609   public Map<FlowNode, NTuple<Location>> getMapFlowNodeToLocTuple() {
610     return mapFlowNodeToLocTuple;
611   }
612
613   public void setMapFlowNodeToLocTuple(Map<FlowNode, NTuple<Location>> in) {
614     this.mapFlowNodeToLocTuple.putAll(in);
615   }
616
617   public Map<FlowNode, Set<FlowEdge>> getMapFlowNodeToOutEdgeSet() {
618     return mapFlowNodeToOutEdgeSet;
619   }
620
621   public Set<FlowNode> getIncomingNodeSetByPrefix(Descriptor prefix) {
622
623     Set<FlowNode> incomingNodeSet = new HashSet<FlowNode>();
624
625     for (Iterator iterator = getNodeSet().iterator(); iterator.hasNext();) {
626       FlowNode curNode = (FlowNode) iterator.next();
627       Set<FlowEdge> outEdgeSet = getOutEdgeSet(curNode);
628
629       for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) {
630         FlowEdge outEdge = (FlowEdge) iterator2.next();
631
632         if (outEdge.getEndTuple().startsWith(prefix)) {
633           incomingNodeSet.add(curNode);
634           recurIncomingNodeSetByPrefix(prefix, curNode, incomingNodeSet);
635
636         }
637
638       }
639     }
640
641     return incomingNodeSet;
642
643   }
644
645   private void recurIncomingNodeSetByPrefix(Descriptor prefix, FlowNode node, Set<FlowNode> visited) {
646
647     Set<FlowEdge> inEdgeSet = getInEdgeSet(node);
648
649     for (Iterator iterator = inEdgeSet.iterator(); iterator.hasNext();) {
650       FlowEdge inEdge = (FlowEdge) iterator.next();
651
652       FlowNode inNode = getFlowNode(inEdge.getInitTuple());
653       if (!inEdge.getInitTuple().startsWith(prefix) && !visited.contains(inNode)) {
654         visited.add(inNode);
655         recurIncomingNodeSetByPrefix(prefix, inNode, visited);
656       }
657     }
658
659   }
660
661   public void setMapFlowNodeToOutEdgeSet(Map<FlowNode, Set<FlowEdge>> inMap) {
662     Set<FlowNode> keySet = inMap.keySet();
663     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
664       FlowNode key = (FlowNode) iterator.next();
665       Set<FlowEdge> newEdgeSet = new HashSet<FlowEdge>();
666       newEdgeSet.addAll(inMap.get(key));
667       mapFlowNodeToOutEdgeSet.put(key, newEdgeSet);
668     }
669   }
670
671   private void drawEdges(FlowNode node, BufferedWriter bw, Set<FlowNode> addedNodeSet,
672       Set<FlowEdge> addedEdgeSet) throws IOException {
673
674     Set<FlowEdge> edgeSet = getOutEdgeSet(node);
675
676     for (Iterator<FlowEdge> iterator = edgeSet.iterator(); iterator.hasNext();) {
677       FlowEdge flowEdge = iterator.next();
678
679       FlowNode u = flowEdge.getSrc();
680       FlowNode v = flowEdge.getDst();
681
682       if (u.getDescTuple().equals(flowEdge.getInitTuple())
683           && v.getDescTuple().equals(flowEdge.getEndTuple())) {
684         // only draw an edge of the actual value flow
685
686         if (!addedEdgeSet.contains(flowEdge)) {
687
688           if (!addedNodeSet.contains(u)) {
689             drawNode(u, bw);
690             addedNodeSet.add(u);
691           }
692           if (!addedNodeSet.contains(v)) {
693             drawNode(v, bw);
694             addedNodeSet.add(v);
695           }
696
697           bw.write("" + u.getID() + " -> " + v.getID() + ";\n");
698           addedEdgeSet.add(flowEdge);
699         }
700       }
701
702     }
703
704   }
705
706   private void drawNode(FlowNode node, BufferedWriter bw) throws IOException {
707     bw.write(node.getID() + " [label=\"" + node.getPrettyID() + "\"]" + ";\n");
708   }
709
710   public void writeGraph() throws java.io.IOException {
711     writeGraph("");
712   }
713
714   public void writeGraph(String suffix) throws java.io.IOException {
715
716     String graphName = "flowgraph_" + md.toString() + suffix;
717     graphName = graphName.replaceAll("[\\W]", "");
718
719     BufferedWriter bw = new BufferedWriter(new FileWriter(graphName + ".dot"));
720     bw.write("digraph " + graphName + " {\n");
721     bw.write("compound=true;\n");
722
723     // then visit every flow node
724
725     // Iterator<FlowNode> iter = nodeSet.iterator();
726     Iterator<FlowNode> iter = getNodeSet().iterator();
727
728     Set<FlowEdge> addedEdgeSet = new HashSet<FlowEdge>();
729     Set<FlowNode> addedNodeSet = new HashSet<FlowNode>();
730
731     while (iter.hasNext()) {
732       FlowNode node = iter.next();
733
734       if (node.getDescTuple().size() == 1) {
735         // here, we just care about the local variable
736         if (node.getFieldNodeSet().size() > 0) {
737           drawSubgraph(node, bw, addedEdgeSet);
738         }
739       }
740       drawEdges(node, bw, addedNodeSet, addedEdgeSet);
741
742     }
743
744     bw.write("}\n");
745     bw.close();
746
747   }
748
749   public boolean constainsNode(FlowNode node) {
750     return getNodeSet().contains(node);
751   }
752
753   private void drawSubgraph(FlowNode node, BufferedWriter bw, Set<FlowEdge> addedSet)
754       throws IOException {
755
756     bw.write("subgraph cluster_" + node.getID() + "{\n");
757     bw.write("label=\"" + node.getPrettyID() + "\";\n");
758
759     Set<FlowNode> fieldNodeSet = node.getFieldNodeSet();
760     for (Iterator iterator = fieldNodeSet.iterator(); iterator.hasNext();) {
761       FlowNode fieldNode = (FlowNode) iterator.next();
762       if (fieldNode.getFieldNodeSet().size() > 0) {
763         drawSubgraph(fieldNode, bw, addedSet);
764       } else {
765         Descriptor desc = fieldNode.getDescTuple().getLastElement();
766         if (desc instanceof VarDescriptor) {
767           VarDescriptor varDesc = (VarDescriptor) desc;
768           if (varDesc.getType().isPrimitive()) {
769             bw.write(fieldNode.getID() + " [label=\"" + fieldNode.getPrettyID() + "\"];\n");
770           }
771         } else if (desc instanceof FieldDescriptor) {
772           FieldDescriptor fieldDesc = (FieldDescriptor) desc;
773           if (fieldDesc.getType().isPrimitive()) {
774             bw.write(fieldNode.getID() + " [label=\"" + fieldNode.getPrettyID() + "\"];\n");
775           }
776         }
777       }
778     }
779
780     bw.write("}\n");
781   }
782
783 }