changes.
[IRC.git] / Robust / src / Analysis / SSJava / LocationInference.java
1 package Analysis.SSJava;
2
3 import java.io.BufferedReader;
4 import java.io.BufferedWriter;
5 import java.io.FileReader;
6 import java.io.FileWriter;
7 import java.io.IOException;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.Comparator;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.Iterator;
14 import java.util.LinkedList;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.Stack;
19 import java.util.Vector;
20
21 import IR.ClassDescriptor;
22 import IR.Descriptor;
23 import IR.FieldDescriptor;
24 import IR.MethodDescriptor;
25 import IR.NameDescriptor;
26 import IR.Operation;
27 import IR.State;
28 import IR.SymbolTable;
29 import IR.TypeDescriptor;
30 import IR.VarDescriptor;
31 import IR.Tree.ArrayAccessNode;
32 import IR.Tree.AssignmentNode;
33 import IR.Tree.BlockExpressionNode;
34 import IR.Tree.BlockNode;
35 import IR.Tree.BlockStatementNode;
36 import IR.Tree.CastNode;
37 import IR.Tree.CreateObjectNode;
38 import IR.Tree.DeclarationNode;
39 import IR.Tree.ExpressionNode;
40 import IR.Tree.FieldAccessNode;
41 import IR.Tree.IfStatementNode;
42 import IR.Tree.Kind;
43 import IR.Tree.LiteralNode;
44 import IR.Tree.LoopNode;
45 import IR.Tree.MethodInvokeNode;
46 import IR.Tree.NameNode;
47 import IR.Tree.OpNode;
48 import IR.Tree.ReturnNode;
49 import IR.Tree.SubBlockNode;
50 import IR.Tree.SwitchBlockNode;
51 import IR.Tree.SwitchStatementNode;
52 import IR.Tree.TertiaryNode;
53 import IR.Tree.TreeNode;
54 import Util.Pair;
55
56 public class LocationInference {
57
58   State state;
59   SSJavaAnalysis ssjava;
60
61   List<ClassDescriptor> temp_toanalyzeList;
62   List<MethodDescriptor> temp_toanalyzeMethodList;
63   Map<MethodDescriptor, FlowGraph> mapMethodDescriptorToFlowGraph;
64
65   LinkedList<MethodDescriptor> toanalyze_methodDescList;
66
67   // map a method descriptor to its set of parameter descriptors
68   Map<MethodDescriptor, Set<Descriptor>> mapMethodDescriptorToParamDescSet;
69
70   // keep current descriptors to visit in fixed-point interprocedural analysis,
71   private Stack<MethodDescriptor> methodDescriptorsToVisitStack;
72
73   // map a class descriptor to a field lattice
74   private Map<ClassDescriptor, SSJavaLattice<String>> cd2lattice;
75
76   // map a method descriptor to a method lattice
77   private Map<MethodDescriptor, SSJavaLattice<String>> md2lattice;
78
79   // map a method/class descriptor to a hierarchy graph
80   private Map<Descriptor, HierarchyGraph> mapDescriptorToHierarchyGraph;
81
82   // map a method/class descriptor to a skeleton hierarchy graph
83   private Map<Descriptor, HierarchyGraph> mapDescriptorToSkeletonHierarchyGraph;
84
85   private Map<Descriptor, HierarchyGraph> mapDescriptorToSimpleHierarchyGraph;
86
87   // map a method/class descriptor to a skeleton hierarchy graph with combination nodes
88   private Map<Descriptor, HierarchyGraph> mapDescriptorToCombineSkeletonHierarchyGraph;
89
90   // map a descriptor to a simple lattice
91   private Map<Descriptor, SSJavaLattice<String>> mapDescriptorToSimpleLattice;
92
93   // map a method descriptor to the set of method invocation nodes which are
94   // invoked by the method descriptor
95   private Map<MethodDescriptor, Set<MethodInvokeNode>> mapMethodDescriptorToMethodInvokeNodeSet;
96
97   private Map<MethodInvokeNode, Map<Integer, NodeTupleSet>> mapMethodInvokeNodeToArgIdxMap;
98
99   private Map<MethodInvokeNode, NTuple<Descriptor>> mapMethodInvokeNodeToBaseTuple;
100
101   private Map<MethodDescriptor, MethodLocationInfo> mapMethodDescToMethodLocationInfo;
102
103   private Map<ClassDescriptor, LocationInfo> mapClassToLocationInfo;
104
105   private Map<MethodDescriptor, Set<MethodDescriptor>> mapMethodToCalleeSet;
106
107   private Map<MethodDescriptor, Set<FlowNode>> mapMethodDescToParamNodeFlowsToReturnValue;
108
109   private Map<String, Vector<String>> mapFileNameToLineVector;
110
111   private Map<Descriptor, Integer> mapDescToDefinitionLine;
112
113   private Map<Descriptor, LocationSummary> mapDescToLocationSummary;
114
115   // maps a method descriptor to a sub global flow graph that captures all value flows caused by the
116   // set of callees reachable from the method
117   private Map<MethodDescriptor, FlowGraph> mapMethodDescriptorToSubGlobalFlowGraph;
118
119   public static final String GLOBALLOC = "GLOBALLOC";
120
121   public static final String TOPLOC = "TOPLOC";
122
123   public static final String INTERLOC = "INTERLOC";
124
125   public static final Descriptor GLOBALDESC = new NameDescriptor(GLOBALLOC);
126
127   public static final Descriptor TOPDESC = new NameDescriptor(TOPLOC);
128
129   public static String newline = System.getProperty("line.separator");
130
131   LocationInfo curMethodInfo;
132
133   boolean debug = true;
134
135   private static int locSeed = 0;
136
137   public LocationInference(SSJavaAnalysis ssjava, State state) {
138     this.ssjava = ssjava;
139     this.state = state;
140     this.temp_toanalyzeList = new ArrayList<ClassDescriptor>();
141     this.temp_toanalyzeMethodList = new ArrayList<MethodDescriptor>();
142     this.mapMethodDescriptorToFlowGraph = new HashMap<MethodDescriptor, FlowGraph>();
143     this.cd2lattice = new HashMap<ClassDescriptor, SSJavaLattice<String>>();
144     this.md2lattice = new HashMap<MethodDescriptor, SSJavaLattice<String>>();
145     this.methodDescriptorsToVisitStack = new Stack<MethodDescriptor>();
146     this.mapMethodDescriptorToMethodInvokeNodeSet =
147         new HashMap<MethodDescriptor, Set<MethodInvokeNode>>();
148     this.mapMethodInvokeNodeToArgIdxMap =
149         new HashMap<MethodInvokeNode, Map<Integer, NodeTupleSet>>();
150     this.mapMethodDescToMethodLocationInfo = new HashMap<MethodDescriptor, MethodLocationInfo>();
151     this.mapMethodToCalleeSet = new HashMap<MethodDescriptor, Set<MethodDescriptor>>();
152     this.mapClassToLocationInfo = new HashMap<ClassDescriptor, LocationInfo>();
153
154     this.mapFileNameToLineVector = new HashMap<String, Vector<String>>();
155     this.mapDescToDefinitionLine = new HashMap<Descriptor, Integer>();
156     this.mapMethodDescToParamNodeFlowsToReturnValue =
157         new HashMap<MethodDescriptor, Set<FlowNode>>();
158
159     this.mapDescriptorToHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
160     this.mapMethodInvokeNodeToBaseTuple = new HashMap<MethodInvokeNode, NTuple<Descriptor>>();
161
162     this.mapDescriptorToSkeletonHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
163     this.mapDescriptorToCombineSkeletonHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
164     this.mapDescriptorToSimpleHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
165
166     this.mapDescriptorToSimpleLattice = new HashMap<Descriptor, SSJavaLattice<String>>();
167
168     this.mapDescToLocationSummary = new HashMap<Descriptor, LocationSummary>();
169
170     mapMethodDescriptorToSubGlobalFlowGraph = new HashMap<MethodDescriptor, FlowGraph>();
171
172   }
173
174   public void setupToAnalyze() {
175     SymbolTable classtable = state.getClassSymbolTable();
176     temp_toanalyzeList.clear();
177     temp_toanalyzeList.addAll(classtable.getValueSet());
178     // Collections.sort(toanalyzeList, new Comparator<ClassDescriptor>() {
179     // public int compare(ClassDescriptor o1, ClassDescriptor o2) {
180     // return o1.getClassName().compareToIgnoreCase(o2.getClassName());
181     // }
182     // });
183   }
184
185   public void setupToAnalazeMethod(ClassDescriptor cd) {
186
187     SymbolTable methodtable = cd.getMethodTable();
188     temp_toanalyzeMethodList.clear();
189     temp_toanalyzeMethodList.addAll(methodtable.getValueSet());
190     Collections.sort(temp_toanalyzeMethodList, new Comparator<MethodDescriptor>() {
191       public int compare(MethodDescriptor o1, MethodDescriptor o2) {
192         return o1.getSymbol().compareToIgnoreCase(o2.getSymbol());
193       }
194     });
195   }
196
197   public boolean toAnalyzeMethodIsEmpty() {
198     return temp_toanalyzeMethodList.isEmpty();
199   }
200
201   public boolean toAnalyzeIsEmpty() {
202     return temp_toanalyzeList.isEmpty();
203   }
204
205   public ClassDescriptor toAnalyzeNext() {
206     return temp_toanalyzeList.remove(0);
207   }
208
209   public MethodDescriptor toAnalyzeMethodNext() {
210     return temp_toanalyzeMethodList.remove(0);
211   }
212
213   public void inference() {
214
215     // 1) construct value flow graph
216     constructFlowGraph();
217
218     constructGlobalFlowGraph();
219
220     System.exit(0);
221
222     constructHierarchyGraph();
223
224     debug_writeHierarchyDotFiles();
225
226     simplifyHierarchyGraph();
227
228     debug_writeSimpleHierarchyDotFiles();
229
230     constructSkeletonHierarchyGraph();
231
232     debug_writeSkeletonHierarchyDotFiles();
233
234     insertCombinationNodes();
235
236     debug_writeSkeletonCombinationHierarchyDotFiles();
237
238     buildLattice();
239
240     debug_writeLattices();
241
242     generateMethodSummary();
243
244     System.exit(0);
245
246     // 2) construct lattices
247     inferLattices();
248
249     simplifyLattices();
250
251     // 3) check properties
252     checkLattices();
253
254     // calculate RETURNLOC,PCLOC
255     calculateExtraLocations();
256
257     debug_writeLatticeDotFile();
258
259     // 4) generate annotated source codes
260     generateAnnoatedCode();
261
262   }
263
264   private void constructGlobalFlowGraph() {
265
266     System.out.println("");
267     LinkedList<MethodDescriptor> methodDescList =
268         (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
269
270     System.out.println("@@@methodDescList=" + methodDescList);
271     // System.exit(0);
272
273     while (!methodDescList.isEmpty()) {
274       MethodDescriptor md = methodDescList.removeLast();
275       if (state.SSJAVADEBUG) {
276         System.out.println();
277         System.out.println("SSJAVA: Constructing a global flow graph: " + md);
278
279         FlowGraph flowGraph = getFlowGraph(md);
280         FlowGraph subGlobalFlowGraph = flowGraph.clone();
281         mapMethodDescriptorToSubGlobalFlowGraph.put(md, subGlobalFlowGraph);
282
283         addValueFlowsFromCalleeSubGlobalFlowGraph(md, subGlobalFlowGraph);
284
285         try {
286           subGlobalFlowGraph.writeGraph("_SUBGLOBAL");
287         } catch (IOException e) {
288           e.printStackTrace();
289         }
290         // FlowGraph fg = new FlowGraph(md, mapParamDescToIdx);
291         // mapMethodDescriptorToFlowGraph.put(md, fg);
292         // analyzeMethodBody(md.getClassDesc(), md);
293
294       }
295     }
296     // _debug_printGraph();
297
298   }
299
300   private void addValueFlowsFromCalleeSubGlobalFlowGraph(MethodDescriptor mdCaller,
301       FlowGraph subGlobalFlowGraph) {
302
303     // the transformation for a call site propagates flows through parameters
304     // if the method is virtual, it also grab all relations from any possible
305     // callees
306
307     Set<MethodInvokeNode> setMethodInvokeNode = getMethodInvokeNodeSet(mdCaller);
308
309     for (Iterator iterator = setMethodInvokeNode.iterator(); iterator.hasNext();) {
310       MethodInvokeNode min = (MethodInvokeNode) iterator.next();
311       MethodDescriptor mdCallee = min.getMethod();
312       Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
313       if (mdCallee.isStatic()) {
314         setPossibleCallees.add(mdCallee);
315       } else {
316         Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
317         // removes method descriptors that are not invoked by the caller
318         calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
319         setPossibleCallees.addAll(calleeSet);
320       }
321
322       for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
323         MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
324         propagateValueFlowsToCallerFromSubGlobalFlowGraph(min, mdCaller, possibleMdCallee);
325         // propagateFlowsToCallerWithNoCompositeLocation(min, mdCaller, possibleMdCallee);
326       }
327
328     }
329
330   }
331
332   private void propagateValueFlowsToCallerFromSubGlobalFlowGraph(MethodInvokeNode min,
333       MethodDescriptor mdCaller, MethodDescriptor possibleMdCallee) {
334
335     NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
336
337     FlowGraph callerSubGlobalGraph = getSubGlobalFlowGraph(mdCaller);
338     FlowGraph calleeSubGlobalGraph = getSubGlobalFlowGraph(possibleMdCallee);
339
340     int numParam = calleeSubGlobalGraph.getNumParameters();
341     for (int idx = 0; idx < numParam; idx++) {
342       FlowNode paramNode = calleeSubGlobalGraph.getParamFlowNode(idx);
343       NodeTupleSet argTupleSet = mapMethodInvokeNodeToArgIdxMap.get(min).get(idx);
344       System.out.println("argTupleSet=" + argTupleSet + "   param=" + paramNode);
345       for (Iterator<NTuple<Descriptor>> iter = argTupleSet.iterator(); iter.hasNext();) {
346         NTuple<Descriptor> argTuple = iter.next();
347         addValueFlowsFromCalleeParam(calleeSubGlobalGraph, paramNode, callerSubGlobalGraph,
348             argTuple, baseTuple);
349       }
350     }
351
352   }
353
354   private void addValueFlowsFromCalleeParam(FlowGraph calleeSubGlobalGraph, FlowNode paramNode,
355       FlowGraph callerSubGlobalGraph, NTuple<Descriptor> argTuple, NTuple<Descriptor> baseTuple) {
356
357     Set<FlowNode> visited = new HashSet<FlowNode>();
358
359     visited.add(paramNode);
360     recurAddValueFlowsFromCalleeParam(calleeSubGlobalGraph, paramNode, callerSubGlobalGraph,
361         argTuple, visited, baseTuple);
362   }
363
364   private void recurAddValueFlowsFromCalleeParam(FlowGraph calleeSubGlobalGraph,
365       FlowNode calleeSrcNode, FlowGraph callerSubGlobalGraph, NTuple<Descriptor> callerSrcTuple,
366       Set<FlowNode> visited, NTuple<Descriptor> baseTuple) {
367
368     MethodDescriptor mdCallee = calleeSubGlobalGraph.getMethodDescriptor();
369
370     Set<FlowEdge> edgeSet = calleeSubGlobalGraph.getOutEdgeSet(calleeSrcNode);
371     for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) {
372       FlowEdge flowEdge = (FlowEdge) iterator.next();
373       FlowNode dstNode = flowEdge.getDst();
374
375       NTuple<Descriptor> dstDescTuple = dstNode.getCurrentDescTuple();
376       if (dstDescTuple.get(0).equals(mdCallee.getThis())) {
377         // destination node is started with 'this' variable
378         // need to translate it in terms of the caller's base node
379         dstDescTuple = translateToCaller(dstDescTuple, baseTuple);
380       }
381
382       callerSubGlobalGraph.addValueFlowEdge(callerSrcTuple, dstDescTuple);
383
384       if (!visited.contains(dstNode)) {
385         visited.add(dstNode);
386         recurAddValueFlowsFromCalleeParam(calleeSubGlobalGraph, dstNode, callerSubGlobalGraph,
387             dstDescTuple, visited, baseTuple);
388       }
389
390     }
391
392   }
393
394   private NTuple<Descriptor> translateToCaller(NTuple<Descriptor> dstDescTuple,
395       NTuple<Descriptor> baseTuple) {
396     NTuple<Descriptor> callerDescTuple = new NTuple<Descriptor>();
397
398     callerDescTuple.addAll(baseTuple);
399     for (int i = 1; i < dstDescTuple.size(); i++) {
400       callerDescTuple.add(dstDescTuple.get(i));
401     }
402
403     return callerDescTuple;
404   }
405
406   public LocationSummary getLocationSummary(Descriptor d) {
407     if (!mapDescToLocationSummary.containsKey(d)) {
408       if (d instanceof MethodDescriptor) {
409         mapDescToLocationSummary.put(d, new MethodSummary((MethodDescriptor) d));
410       } else if (d instanceof ClassDescriptor) {
411         mapDescToLocationSummary.put(d, new FieldSummary());
412       }
413     }
414     return mapDescToLocationSummary.get(d);
415   }
416
417   private void generateMethodSummary() {
418
419     Set<MethodDescriptor> keySet = md2lattice.keySet();
420     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
421       MethodDescriptor md = (MethodDescriptor) iterator.next();
422
423       System.out.println("\nSSJAVA: generate method summary: " + md);
424
425       FlowGraph flowGraph = getFlowGraph(md);
426       MethodSummary methodSummary = getMethodSummary(md);
427
428       // construct a parameter mapping that maps a parameter descriptor to an inferred composite
429       // location
430
431       for (int paramIdx = 0; paramIdx < flowGraph.getNumParameters(); paramIdx++) {
432         FlowNode flowNode = flowGraph.getParamFlowNode(paramIdx);
433         NTuple<Descriptor> descTuple = flowNode.getDescTuple();
434
435         CompositeLocation assignedCompLoc = flowNode.getCompositeLocation();
436         CompositeLocation inferredCompLoc;
437         if (assignedCompLoc != null) {
438           inferredCompLoc = translateCompositeLocation(assignedCompLoc);
439         } else {
440           Descriptor locDesc = descTuple.get(0);
441           Location loc = new Location(md, locDesc.getSymbol());
442           loc.setLocDescriptor(locDesc);
443           inferredCompLoc = new CompositeLocation(loc);
444         }
445         System.out.println("-paramIdx=" + paramIdx + "   infer=" + inferredCompLoc);
446         methodSummary.addMapParamIdxToInferLoc(paramIdx, inferredCompLoc);
447       }
448
449     }
450
451   }
452
453   private CompositeLocation translateCompositeLocation(CompositeLocation compLoc) {
454     CompositeLocation newCompLoc = new CompositeLocation();
455
456     // System.out.println("compLoc=" + compLoc);
457     for (int i = 0; i < compLoc.getSize(); i++) {
458       Location loc = compLoc.get(i);
459       Descriptor enclosingDescriptor = loc.getDescriptor();
460       Descriptor locDescriptor = loc.getLocDescriptor();
461
462       HNode hnode = getHierarchyGraph(enclosingDescriptor).getHNode(locDescriptor);
463       // System.out.println("-hnode=" + hnode + "    from=" + locDescriptor +
464       // " enclosingDescriptor="
465       // + enclosingDescriptor);
466       // System.out.println("-getLocationSummary(enclosingDescriptor)="
467       // + getLocationSummary(enclosingDescriptor));
468       String locName = getLocationSummary(enclosingDescriptor).getLocationName(hnode.getName());
469       // System.out.println("-locName=" + locName);
470       Location newLoc = new Location(enclosingDescriptor, locName);
471       newLoc.setLocDescriptor(locDescriptor);
472       newCompLoc.addLocation(newLoc);
473     }
474
475     return newCompLoc;
476   }
477
478   private void debug_writeLattices() {
479
480     Set<Descriptor> keySet = mapDescriptorToSimpleLattice.keySet();
481     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
482       Descriptor key = (Descriptor) iterator.next();
483       SSJavaLattice<String> simpleLattice = mapDescriptorToSimpleLattice.get(key);
484       // HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(key);
485       HierarchyGraph scHierarchyGraph = getSkeletonCombinationHierarchyGraph(key);
486       if (key instanceof ClassDescriptor) {
487         writeInferredLatticeDotFile((ClassDescriptor) key, scHierarchyGraph, simpleLattice,
488             "_SIMPLE");
489       } else if (key instanceof MethodDescriptor) {
490         MethodDescriptor md = (MethodDescriptor) key;
491         writeInferredLatticeDotFile(md.getClassDesc(), md, scHierarchyGraph, simpleLattice,
492             "_SIMPLE");
493       }
494
495       LocationSummary ls = getLocationSummary(key);
496       System.out.println("####LOC SUMMARY=" + key + "\n" + ls.getMapHNodeNameToLocationName());
497     }
498
499     Set<ClassDescriptor> cdKeySet = cd2lattice.keySet();
500     for (Iterator iterator = cdKeySet.iterator(); iterator.hasNext();) {
501       ClassDescriptor cd = (ClassDescriptor) iterator.next();
502       writeInferredLatticeDotFile((ClassDescriptor) cd, getSkeletonCombinationHierarchyGraph(cd),
503           cd2lattice.get(cd), "");
504     }
505
506     Set<MethodDescriptor> mdKeySet = md2lattice.keySet();
507     for (Iterator iterator = mdKeySet.iterator(); iterator.hasNext();) {
508       MethodDescriptor md = (MethodDescriptor) iterator.next();
509       writeInferredLatticeDotFile(md.getClassDesc(), md, getSkeletonCombinationHierarchyGraph(md),
510           md2lattice.get(md), "");
511     }
512
513   }
514
515   private void buildLattice() {
516
517     BuildLattice buildLattice = new BuildLattice(this);
518
519     Set<Descriptor> keySet = mapDescriptorToCombineSkeletonHierarchyGraph.keySet();
520     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
521       Descriptor desc = (Descriptor) iterator.next();
522
523       SSJavaLattice<String> simpleLattice = buildLattice.buildLattice(desc);
524
525       addMapDescToSimpleLattice(desc, simpleLattice);
526
527       HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(desc);
528       System.out.println("## insertIntermediateNodesToStraightLine:"
529           + simpleHierarchyGraph.getName());
530       SSJavaLattice<String> lattice =
531           buildLattice.insertIntermediateNodesToStraightLine(desc, simpleLattice);
532       lattice.removeRedundantEdges();
533
534       if (desc instanceof ClassDescriptor) {
535         // field lattice
536         cd2lattice.put((ClassDescriptor) desc, lattice);
537         // ssjava.writeLatticeDotFile((ClassDescriptor) desc, null, lattice);
538       } else if (desc instanceof MethodDescriptor) {
539         // method lattice
540         md2lattice.put((MethodDescriptor) desc, lattice);
541         MethodDescriptor md = (MethodDescriptor) desc;
542         ClassDescriptor cd = md.getClassDesc();
543         // ssjava.writeLatticeDotFile(cd, md, lattice);
544       }
545
546       // System.out.println("\nSSJAVA: Insering Combination Nodes:" + desc);
547       // HierarchyGraph skeletonGraph = getSkeletonHierarchyGraph(desc);
548       // HierarchyGraph skeletonGraphWithCombinationNode = skeletonGraph.clone();
549       // skeletonGraphWithCombinationNode.setName(desc + "_SC");
550       //
551       // HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(desc);
552       // System.out.println("Identifying Combination Nodes:");
553       // skeletonGraphWithCombinationNode.insertCombinationNodesToGraph(simpleHierarchyGraph);
554       // skeletonGraphWithCombinationNode.simplifySkeletonCombinationHierarchyGraph();
555       // mapDescriptorToCombineSkeletonHierarchyGraph.put(desc, skeletonGraphWithCombinationNode);
556     }
557
558   }
559
560   public void addMapDescToSimpleLattice(Descriptor desc, SSJavaLattice<String> lattice) {
561     mapDescriptorToSimpleLattice.put(desc, lattice);
562   }
563
564   public SSJavaLattice<String> getSimpleLattice(Descriptor desc) {
565     return mapDescriptorToSimpleLattice.get(desc);
566   }
567
568   private void simplifyHierarchyGraph() {
569     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
570     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
571       Descriptor desc = (Descriptor) iterator.next();
572       HierarchyGraph simpleHierarchyGraph = getHierarchyGraph(desc).clone();
573       simpleHierarchyGraph.setName(desc + "_SIMPLE");
574       simpleHierarchyGraph.removeRedundantEdges();
575       // simpleHierarchyGraph.simplifyHierarchyGraph();
576       mapDescriptorToSimpleHierarchyGraph.put(desc, simpleHierarchyGraph);
577     }
578   }
579
580   private void insertCombinationNodes() {
581     Set<Descriptor> keySet = mapDescriptorToSkeletonHierarchyGraph.keySet();
582     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
583       Descriptor desc = (Descriptor) iterator.next();
584       System.out.println("\nSSJAVA: Insering Combination Nodes:" + desc);
585       HierarchyGraph skeletonGraph = getSkeletonHierarchyGraph(desc);
586       HierarchyGraph skeletonGraphWithCombinationNode = skeletonGraph.clone();
587       skeletonGraphWithCombinationNode.setName(desc + "_SC");
588
589       HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(desc);
590       System.out.println("Identifying Combination Nodes:");
591       skeletonGraphWithCombinationNode.insertCombinationNodesToGraph(simpleHierarchyGraph);
592       skeletonGraphWithCombinationNode.simplifySkeletonCombinationHierarchyGraph();
593       mapDescriptorToCombineSkeletonHierarchyGraph.put(desc, skeletonGraphWithCombinationNode);
594     }
595   }
596
597   private void constructSkeletonHierarchyGraph() {
598     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
599     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
600       Descriptor desc = (Descriptor) iterator.next();
601       HierarchyGraph simpleGraph = getSimpleHierarchyGraph(desc);
602       HierarchyGraph skeletonGraph = simpleGraph.generateSkeletonGraph();
603       skeletonGraph.setMapDescToHNode(simpleGraph.getMapDescToHNode());
604       skeletonGraph.setMapHNodeToDescSet(simpleGraph.getMapHNodeToDescSet());
605       skeletonGraph.simplifyHierarchyGraph();
606       // skeletonGraph.combineRedundantNodes(false);
607       // skeletonGraph.removeRedundantEdges();
608       mapDescriptorToSkeletonHierarchyGraph.put(desc, skeletonGraph);
609     }
610   }
611
612   private void debug_writeHierarchyDotFiles() {
613
614     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
615     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
616       Descriptor desc = (Descriptor) iterator.next();
617       getHierarchyGraph(desc).writeGraph();
618     }
619
620   }
621
622   private void debug_writeSimpleHierarchyDotFiles() {
623
624     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
625     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
626       Descriptor desc = (Descriptor) iterator.next();
627       getHierarchyGraph(desc).writeGraph();
628       getSimpleHierarchyGraph(desc).writeGraph();
629     }
630
631   }
632
633   private void debug_writeSkeletonHierarchyDotFiles() {
634
635     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
636     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
637       Descriptor desc = (Descriptor) iterator.next();
638       getSkeletonHierarchyGraph(desc).writeGraph();
639     }
640
641   }
642
643   private void debug_writeSkeletonCombinationHierarchyDotFiles() {
644
645     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
646     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
647       Descriptor desc = (Descriptor) iterator.next();
648       getSkeletonCombinationHierarchyGraph(desc).writeGraph();
649     }
650
651   }
652
653   public HierarchyGraph getSimpleHierarchyGraph(Descriptor d) {
654     return mapDescriptorToSimpleHierarchyGraph.get(d);
655   }
656
657   private HierarchyGraph getSkeletonHierarchyGraph(Descriptor d) {
658     if (!mapDescriptorToSkeletonHierarchyGraph.containsKey(d)) {
659       mapDescriptorToSkeletonHierarchyGraph.put(d, new HierarchyGraph(d));
660     }
661     return mapDescriptorToSkeletonHierarchyGraph.get(d);
662   }
663
664   public HierarchyGraph getSkeletonCombinationHierarchyGraph(Descriptor d) {
665     if (!mapDescriptorToCombineSkeletonHierarchyGraph.containsKey(d)) {
666       mapDescriptorToCombineSkeletonHierarchyGraph.put(d, new HierarchyGraph(d));
667     }
668     return mapDescriptorToCombineSkeletonHierarchyGraph.get(d);
669   }
670
671   private void constructHierarchyGraph() {
672
673     // do fixed-point analysis
674
675     ssjava.init();
676     LinkedList<MethodDescriptor> descriptorListToAnalyze = ssjava.getSortedDescriptors();
677
678     // Collections.sort(descriptorListToAnalyze, new
679     // Comparator<MethodDescriptor>() {
680     // public int compare(MethodDescriptor o1, MethodDescriptor o2) {
681     // return o1.getSymbol().compareToIgnoreCase(o2.getSymbol());
682     // }
683     // });
684
685     // current descriptors to visit in fixed-point interprocedural analysis,
686     // prioritized by dependency in the call graph
687     methodDescriptorsToVisitStack.clear();
688
689     Set<MethodDescriptor> methodDescriptorToVistSet = new HashSet<MethodDescriptor>();
690     methodDescriptorToVistSet.addAll(descriptorListToAnalyze);
691
692     while (!descriptorListToAnalyze.isEmpty()) {
693       MethodDescriptor md = descriptorListToAnalyze.removeFirst();
694       methodDescriptorsToVisitStack.add(md);
695     }
696
697     // analyze scheduled methods until there are no more to visit
698     while (!methodDescriptorsToVisitStack.isEmpty()) {
699       // start to analyze leaf node
700       MethodDescriptor md = methodDescriptorsToVisitStack.pop();
701
702       HierarchyGraph hierarchyGraph = new HierarchyGraph(md);
703       // MethodSummary methodSummary = new MethodSummary(md);
704
705       // MethodLocationInfo methodInfo = new MethodLocationInfo(md);
706       // curMethodInfo = methodInfo;
707
708       System.out.println();
709       System.out.println("SSJAVA: Construcing the hierarchy graph from " + md);
710
711       constructHierarchyGraph(md, hierarchyGraph);
712
713       HierarchyGraph prevHierarchyGraph = getHierarchyGraph(md);
714       // MethodSummary prevMethodSummary = getMethodSummary(md);
715
716       if (!hierarchyGraph.equals(prevHierarchyGraph)) {
717
718         mapDescriptorToHierarchyGraph.put(md, hierarchyGraph);
719         // mapDescToLocationSummary.put(md, methodSummary);
720
721         // results for callee changed, so enqueue dependents caller for
722         // further analysis
723         Iterator<MethodDescriptor> depsItr = ssjava.getDependents(md).iterator();
724         while (depsItr.hasNext()) {
725           MethodDescriptor methodNext = depsItr.next();
726           if (!methodDescriptorsToVisitStack.contains(methodNext)
727               && methodDescriptorToVistSet.contains(methodNext)) {
728             methodDescriptorsToVisitStack.add(methodNext);
729           }
730         }
731
732       }
733
734     }
735
736   }
737
738   private HierarchyGraph getHierarchyGraph(Descriptor d) {
739     if (!mapDescriptorToHierarchyGraph.containsKey(d)) {
740       mapDescriptorToHierarchyGraph.put(d, new HierarchyGraph(d));
741     }
742     return mapDescriptorToHierarchyGraph.get(d);
743   }
744
745   private void constructHierarchyGraph(MethodDescriptor md, HierarchyGraph methodGraph) {
746
747     // visit each node of method flow graph
748     FlowGraph fg = getFlowGraph(md);
749     Set<FlowNode> nodeSet = fg.getNodeSet();
750
751     Set<Descriptor> paramDescSet = fg.getMapParamDescToIdx().keySet();
752     for (Iterator iterator = paramDescSet.iterator(); iterator.hasNext();) {
753       Descriptor desc = (Descriptor) iterator.next();
754       methodGraph.getHNode(desc).setSkeleton(true);
755     }
756
757     // for the method lattice, we need to look at the first element of
758     // NTuple<Descriptor>
759     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
760       FlowNode srcNode = (FlowNode) iterator.next();
761
762       Set<FlowEdge> outEdgeSet = fg.getOutEdgeSet(srcNode);
763       for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) {
764         FlowEdge outEdge = (FlowEdge) iterator2.next();
765         FlowNode dstNode = outEdge.getDst();
766
767         NTuple<Descriptor> srcNodeTuple = srcNode.getDescTuple();
768         NTuple<Descriptor> dstNodeTuple = dstNode.getDescTuple();
769
770         if (outEdge.getInitTuple().equals(srcNodeTuple)
771             && outEdge.getEndTuple().equals(dstNodeTuple)) {
772
773           NTuple<Descriptor> srcCurTuple = srcNode.getCurrentDescTuple();
774           NTuple<Descriptor> dstCurTuple = dstNode.getCurrentDescTuple();
775
776           if ((srcCurTuple.size() > 1 && dstCurTuple.size() > 1)
777               && srcCurTuple.get(0).equals(dstCurTuple.get(0))) {
778
779             // value flows between fields
780             Descriptor desc = srcCurTuple.get(0);
781             ClassDescriptor classDesc;
782
783             if (desc.equals(GLOBALDESC)) {
784               classDesc = md.getClassDesc();
785             } else {
786               VarDescriptor varDesc = (VarDescriptor) srcCurTuple.get(0);
787               classDesc = varDesc.getType().getClassDesc();
788             }
789             extractFlowsBetweenFields(classDesc, srcNode, dstNode, 1);
790
791           } else {
792             // value flow between local var - local var or local var - field
793
794             Descriptor srcDesc = srcCurTuple.get(0);
795             Descriptor dstDesc = dstCurTuple.get(0);
796
797             methodGraph.addEdge(srcDesc, dstDesc);
798
799             if (fg.isParamDesc(srcDesc)) {
800               methodGraph.setParamHNode(srcDesc);
801             }
802             if (fg.isParamDesc(dstDesc)) {
803               methodGraph.setParamHNode(dstDesc);
804             }
805
806           }
807
808         }
809       }
810     }
811
812   }
813
814   private MethodSummary getMethodSummary(MethodDescriptor md) {
815     if (!mapDescToLocationSummary.containsKey(md)) {
816       mapDescToLocationSummary.put(md, new MethodSummary(md));
817     }
818     return (MethodSummary) mapDescToLocationSummary.get(md);
819   }
820
821   private void addMapClassDefinitionToLineNum(ClassDescriptor cd, String strLine, int lineNum) {
822
823     String classSymbol = cd.getSymbol();
824     int idx = classSymbol.lastIndexOf("$");
825     if (idx != -1) {
826       classSymbol = classSymbol.substring(idx + 1);
827     }
828
829     String pattern = "class " + classSymbol + " ";
830     if (strLine.indexOf(pattern) != -1) {
831       mapDescToDefinitionLine.put(cd, lineNum);
832     }
833   }
834
835   private void addMapMethodDefinitionToLineNum(Set<MethodDescriptor> methodSet, String strLine,
836       int lineNum) {
837     for (Iterator iterator = methodSet.iterator(); iterator.hasNext();) {
838       MethodDescriptor md = (MethodDescriptor) iterator.next();
839       String pattern = md.getMethodDeclaration();
840       if (strLine.indexOf(pattern) != -1) {
841         mapDescToDefinitionLine.put(md, lineNum);
842         methodSet.remove(md);
843         return;
844       }
845     }
846
847   }
848
849   private void readOriginalSourceFiles() {
850
851     SymbolTable classtable = state.getClassSymbolTable();
852
853     Set<ClassDescriptor> classDescSet = new HashSet<ClassDescriptor>();
854     classDescSet.addAll(classtable.getValueSet());
855
856     try {
857       // inefficient implement. it may re-visit the same file if the file
858       // contains more than one class definitions.
859       for (Iterator iterator = classDescSet.iterator(); iterator.hasNext();) {
860         ClassDescriptor cd = (ClassDescriptor) iterator.next();
861
862         Set<MethodDescriptor> methodSet = new HashSet<MethodDescriptor>();
863         methodSet.addAll(cd.getMethodTable().getValueSet());
864
865         String sourceFileName = cd.getSourceFileName();
866         Vector<String> lineVec = new Vector<String>();
867
868         mapFileNameToLineVector.put(sourceFileName, lineVec);
869
870         BufferedReader in = new BufferedReader(new FileReader(sourceFileName));
871         String strLine;
872         int lineNum = 1;
873         lineVec.add(""); // the index is started from 1.
874         while ((strLine = in.readLine()) != null) {
875           lineVec.add(lineNum, strLine);
876           addMapClassDefinitionToLineNum(cd, strLine, lineNum);
877           addMapMethodDefinitionToLineNum(methodSet, strLine, lineNum);
878           lineNum++;
879         }
880
881       }
882
883     } catch (IOException e) {
884       e.printStackTrace();
885     }
886
887   }
888
889   private String generateLatticeDefinition(Descriptor desc) {
890
891     Set<String> sharedLocSet = new HashSet<String>();
892
893     SSJavaLattice<String> lattice = getLattice(desc);
894     String rtr = "@LATTICE(\"";
895
896     Map<String, Set<String>> map = lattice.getTable();
897     Set<String> keySet = map.keySet();
898     boolean first = true;
899     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
900       String key = (String) iterator.next();
901       if (!key.equals(lattice.getTopItem())) {
902         Set<String> connectedSet = map.get(key);
903
904         if (connectedSet.size() == 1) {
905           if (connectedSet.iterator().next().equals(lattice.getBottomItem())) {
906             if (!first) {
907               rtr += ",";
908             } else {
909               rtr += "LOC,";
910               first = false;
911             }
912             rtr += key;
913             if (lattice.isSharedLoc(key)) {
914               rtr += "," + key + "*";
915             }
916           }
917         }
918
919         for (Iterator iterator2 = connectedSet.iterator(); iterator2.hasNext();) {
920           String loc = (String) iterator2.next();
921           if (!loc.equals(lattice.getBottomItem())) {
922             if (!first) {
923               rtr += ",";
924             } else {
925               rtr += "LOC,";
926               first = false;
927             }
928             rtr += loc + "<" + key;
929             if (lattice.isSharedLoc(key) && (!sharedLocSet.contains(key))) {
930               rtr += "," + key + "*";
931               sharedLocSet.add(key);
932             }
933             if (lattice.isSharedLoc(loc) && (!sharedLocSet.contains(loc))) {
934               rtr += "," + loc + "*";
935               sharedLocSet.add(loc);
936             }
937
938           }
939         }
940       }
941     }
942
943     rtr += "\")";
944
945     if (desc instanceof MethodDescriptor) {
946       TypeDescriptor returnType = ((MethodDescriptor) desc).getReturnType();
947
948       MethodLocationInfo methodLocInfo = getMethodLocationInfo((MethodDescriptor) desc);
949
950       if (returnType != null && (!returnType.isVoid())) {
951         rtr +=
952             "\n@RETURNLOC(\"" + generateLocationAnnoatation(methodLocInfo.getReturnLoc()) + "\")";
953       }
954
955       rtr += "\n@THISLOC(\"this\")";
956       rtr += "\n@GLOBALLOC(\"GLOBALLOC\")";
957
958       CompositeLocation pcLoc = methodLocInfo.getPCLoc();
959       if ((pcLoc != null) && (!pcLoc.get(0).isTop())) {
960         rtr += "\n@PCLOC(\"" + generateLocationAnnoatation(pcLoc) + "\")";
961       }
962
963     }
964
965     return rtr;
966   }
967
968   private void generateAnnoatedCode() {
969
970     readOriginalSourceFiles();
971
972     setupToAnalyze();
973     while (!toAnalyzeIsEmpty()) {
974       ClassDescriptor cd = toAnalyzeNext();
975
976       setupToAnalazeMethod(cd);
977
978       LocationInfo locInfo = mapClassToLocationInfo.get(cd);
979       String sourceFileName = cd.getSourceFileName();
980
981       if (cd.isInterface()) {
982         continue;
983       }
984
985       int classDefLine = mapDescToDefinitionLine.get(cd);
986       Vector<String> sourceVec = mapFileNameToLineVector.get(sourceFileName);
987
988       if (locInfo == null) {
989         locInfo = getLocationInfo(cd);
990       }
991
992       for (Iterator iter = cd.getFields(); iter.hasNext();) {
993         FieldDescriptor fieldDesc = (FieldDescriptor) iter.next();
994         if (!(fieldDesc.isStatic() && fieldDesc.isFinal())) {
995           String locIdentifier = locInfo.getFieldInferLocation(fieldDesc).getLocIdentifier();
996           if (!getLattice(cd).getElementSet().contains(locIdentifier)) {
997             getLattice(cd).put(locIdentifier);
998           }
999         }
1000       }
1001
1002       String fieldLatticeDefStr = generateLatticeDefinition(cd);
1003       String annoatedSrc = fieldLatticeDefStr + newline + sourceVec.get(classDefLine);
1004       sourceVec.set(classDefLine, annoatedSrc);
1005
1006       // generate annotations for field declarations
1007       LocationInfo fieldLocInfo = getLocationInfo(cd);
1008       Map<Descriptor, CompositeLocation> inferLocMap = fieldLocInfo.getMapDescToInferLocation();
1009
1010       for (Iterator iter = cd.getFields(); iter.hasNext();) {
1011         FieldDescriptor fd = (FieldDescriptor) iter.next();
1012
1013         String locAnnotationStr;
1014         CompositeLocation inferLoc = inferLocMap.get(fd);
1015
1016         if (inferLoc != null) {
1017           // infer loc is null if the corresponding field is static and final
1018           locAnnotationStr = "@LOC(\"" + generateLocationAnnoatation(inferLoc) + "\")";
1019           int fdLineNum = fd.getLineNum();
1020           String orgFieldDeclarationStr = sourceVec.get(fdLineNum);
1021           String fieldDeclaration = fd.toString();
1022           fieldDeclaration = fieldDeclaration.substring(0, fieldDeclaration.length() - 1);
1023           String annoatedStr = locAnnotationStr + " " + orgFieldDeclarationStr;
1024           sourceVec.set(fdLineNum, annoatedStr);
1025         }
1026
1027       }
1028
1029       while (!toAnalyzeMethodIsEmpty()) {
1030         MethodDescriptor md = toAnalyzeMethodNext();
1031
1032         if (!ssjava.needTobeAnnotated(md)) {
1033           continue;
1034         }
1035
1036         SSJavaLattice<String> methodLattice = md2lattice.get(md);
1037         if (methodLattice != null) {
1038
1039           int methodDefLine = md.getLineNum();
1040
1041           MethodLocationInfo methodLocInfo = getMethodLocationInfo(md);
1042
1043           Map<Descriptor, CompositeLocation> methodInferLocMap =
1044               methodLocInfo.getMapDescToInferLocation();
1045           Set<Descriptor> localVarDescSet = methodInferLocMap.keySet();
1046
1047           Set<String> localLocElementSet = methodLattice.getElementSet();
1048
1049           for (Iterator iterator = localVarDescSet.iterator(); iterator.hasNext();) {
1050             Descriptor localVarDesc = (Descriptor) iterator.next();
1051             CompositeLocation inferLoc = methodInferLocMap.get(localVarDesc);
1052
1053             String localLocIdentifier = inferLoc.get(0).getLocIdentifier();
1054             if (!localLocElementSet.contains(localLocIdentifier)) {
1055               methodLattice.put(localLocIdentifier);
1056             }
1057
1058             String locAnnotationStr = "@LOC(\"" + generateLocationAnnoatation(inferLoc) + "\")";
1059
1060             if (!isParameter(md, localVarDesc)) {
1061               if (mapDescToDefinitionLine.containsKey(localVarDesc)) {
1062                 int varLineNum = mapDescToDefinitionLine.get(localVarDesc);
1063                 String orgSourceLine = sourceVec.get(varLineNum);
1064                 int idx =
1065                     orgSourceLine.indexOf(generateVarDeclaration((VarDescriptor) localVarDesc));
1066                 assert (idx != -1);
1067                 String annoatedStr =
1068                     orgSourceLine.substring(0, idx) + locAnnotationStr + " "
1069                         + orgSourceLine.substring(idx);
1070                 sourceVec.set(varLineNum, annoatedStr);
1071               }
1072             } else {
1073               String methodDefStr = sourceVec.get(methodDefLine);
1074
1075               int idx =
1076                   getParamLocation(methodDefStr,
1077                       generateVarDeclaration((VarDescriptor) localVarDesc));
1078
1079               assert (idx != -1);
1080
1081               String annoatedStr =
1082                   methodDefStr.substring(0, idx) + locAnnotationStr + " "
1083                       + methodDefStr.substring(idx);
1084               sourceVec.set(methodDefLine, annoatedStr);
1085             }
1086
1087           }
1088
1089           // check if the lattice has to have the location type for the this
1090           // reference...
1091
1092           // boolean needToAddthisRef = hasThisReference(md);
1093           if (localLocElementSet.contains("this")) {
1094             methodLattice.put("this");
1095           }
1096
1097           String methodLatticeDefStr = generateLatticeDefinition(md);
1098           String annoatedStr = methodLatticeDefStr + newline + sourceVec.get(methodDefLine);
1099           sourceVec.set(methodDefLine, annoatedStr);
1100
1101         }
1102       }
1103
1104     }
1105
1106     codeGen();
1107   }
1108
1109   private boolean hasThisReference(MethodDescriptor md) {
1110
1111     FlowGraph fg = getFlowGraph(md);
1112     Set<FlowNode> nodeSet = fg.getNodeSet();
1113     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
1114       FlowNode flowNode = (FlowNode) iterator.next();
1115       if (flowNode.getDescTuple().get(0).equals(md.getThis())) {
1116         return true;
1117       }
1118     }
1119
1120     return false;
1121   }
1122
1123   private int getParamLocation(String methodStr, String paramStr) {
1124
1125     String pattern = paramStr + ",";
1126
1127     int idx = methodStr.indexOf(pattern);
1128     if (idx != -1) {
1129       return idx;
1130     } else {
1131       pattern = paramStr + ")";
1132       return methodStr.indexOf(pattern);
1133     }
1134
1135   }
1136
1137   private String generateVarDeclaration(VarDescriptor varDesc) {
1138
1139     TypeDescriptor td = varDesc.getType();
1140     String rtr = td.toString();
1141     if (td.isArray()) {
1142       for (int i = 0; i < td.getArrayCount(); i++) {
1143         rtr += "[]";
1144       }
1145     }
1146     rtr += " " + varDesc.getName();
1147     return rtr;
1148
1149   }
1150
1151   private String generateLocationAnnoatation(CompositeLocation loc) {
1152     String rtr = "";
1153     // method location
1154     Location methodLoc = loc.get(0);
1155     rtr += methodLoc.getLocIdentifier();
1156
1157     for (int i = 1; i < loc.getSize(); i++) {
1158       Location element = loc.get(i);
1159       rtr += "," + element.getDescriptor().getSymbol() + "." + element.getLocIdentifier();
1160     }
1161
1162     return rtr;
1163   }
1164
1165   private boolean isParameter(MethodDescriptor md, Descriptor localVarDesc) {
1166     return getFlowGraph(md).isParamDesc(localVarDesc);
1167   }
1168
1169   private String extractFileName(String fileName) {
1170     int idx = fileName.lastIndexOf("/");
1171     if (idx == -1) {
1172       return fileName;
1173     } else {
1174       return fileName.substring(idx + 1);
1175     }
1176
1177   }
1178
1179   private void codeGen() {
1180
1181     Set<String> originalFileNameSet = mapFileNameToLineVector.keySet();
1182     for (Iterator iterator = originalFileNameSet.iterator(); iterator.hasNext();) {
1183       String orgFileName = (String) iterator.next();
1184       String outputFileName = extractFileName(orgFileName);
1185
1186       Vector<String> sourceVec = mapFileNameToLineVector.get(orgFileName);
1187
1188       try {
1189
1190         FileWriter fileWriter = new FileWriter("./infer/" + outputFileName);
1191         BufferedWriter out = new BufferedWriter(fileWriter);
1192
1193         for (int i = 0; i < sourceVec.size(); i++) {
1194           out.write(sourceVec.get(i));
1195           out.newLine();
1196         }
1197         out.close();
1198       } catch (IOException e) {
1199         e.printStackTrace();
1200       }
1201
1202     }
1203
1204   }
1205
1206   private void simplifyLattices() {
1207
1208     setupToAnalyze();
1209
1210     while (!toAnalyzeIsEmpty()) {
1211       ClassDescriptor cd = toAnalyzeNext();
1212       setupToAnalazeMethod(cd);
1213
1214       SSJavaLattice<String> classLattice = cd2lattice.get(cd);
1215       if (classLattice != null) {
1216         System.out.println("@@@check lattice=" + cd);
1217         checkLatticeProperty(cd, classLattice);
1218       }
1219
1220       while (!toAnalyzeMethodIsEmpty()) {
1221         MethodDescriptor md = toAnalyzeMethodNext();
1222         SSJavaLattice<String> methodLattice = md2lattice.get(md);
1223         if (methodLattice != null) {
1224           System.out.println("@@@check lattice=" + md);
1225           checkLatticeProperty(md, methodLattice);
1226         }
1227       }
1228     }
1229
1230     setupToAnalyze();
1231
1232     while (!toAnalyzeIsEmpty()) {
1233       ClassDescriptor cd = toAnalyzeNext();
1234
1235       setupToAnalazeMethod(cd);
1236
1237       SSJavaLattice<String> classLattice = cd2lattice.get(cd);
1238       if (classLattice != null) {
1239         classLattice.removeRedundantEdges();
1240       }
1241
1242       while (!toAnalyzeMethodIsEmpty()) {
1243         MethodDescriptor md = toAnalyzeMethodNext();
1244         SSJavaLattice<String> methodLattice = md2lattice.get(md);
1245         if (methodLattice != null) {
1246           methodLattice.removeRedundantEdges();
1247         }
1248       }
1249     }
1250
1251   }
1252
1253   private boolean checkLatticeProperty(Descriptor d, SSJavaLattice<String> lattice) {
1254     // if two elements has the same incoming node set,
1255     // we need to merge two elements ...
1256
1257     boolean isUpdated;
1258     boolean isModified = false;
1259     do {
1260       isUpdated = removeNodeSharingSameIncomingNodes(d, lattice);
1261       if (!isModified && isUpdated) {
1262         isModified = true;
1263       }
1264     } while (isUpdated);
1265
1266     return isModified;
1267   }
1268
1269   private boolean removeNodeSharingSameIncomingNodes(Descriptor d, SSJavaLattice<String> lattice) {
1270     LocationInfo locInfo = getLocationInfo(d);
1271     Map<String, Set<String>> map = lattice.getIncomingElementMap();
1272     Set<String> keySet = map.keySet();
1273     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1274       String key = (String) iterator.next();
1275       Set<String> incomingSetKey = map.get(key);
1276
1277       // System.out.println("key=" + key + "   incomingSetKey=" +
1278       // incomingSetKey);
1279       if (incomingSetKey.size() > 0) {
1280         for (Iterator iterator2 = keySet.iterator(); iterator2.hasNext();) {
1281           String cur = (String) iterator2.next();
1282           if (!cur.equals(key)) {
1283             Set<String> incomingSetCur = map.get(cur);
1284             if (incomingSetCur.equals(incomingSetKey)) {
1285               if (!(incomingSetCur.size() == 1 && incomingSetCur.contains(lattice.getTopItem()))) {
1286                 // NEED TO MERGE HERE!!!!
1287                 System.out.println("@@@Try merge=" + cur + "  " + key);
1288
1289                 Set<String> mergeSet = new HashSet<String>();
1290                 mergeSet.add(cur);
1291                 mergeSet.add(key);
1292
1293                 String newMergeLoc = "MLoc" + (SSJavaLattice.seed++);
1294
1295                 System.out.println("---ASSIGN NEW MERGE LOC=" + newMergeLoc + "   to  " + mergeSet);
1296                 lattice.mergeIntoNewLocation(mergeSet, newMergeLoc);
1297
1298                 for (Iterator miterator = mergeSet.iterator(); miterator.hasNext();) {
1299                   String oldLocSymbol = (String) miterator.next();
1300
1301                   Set<Pair<Descriptor, Descriptor>> inferLocSet =
1302                       locInfo.getRelatedInferLocSet(oldLocSymbol);
1303                   System.out.println("---update related locations=" + inferLocSet
1304                       + " oldLocSymbol=" + oldLocSymbol);
1305
1306                   for (Iterator miterator2 = inferLocSet.iterator(); miterator2.hasNext();) {
1307                     Pair<Descriptor, Descriptor> pair =
1308                         (Pair<Descriptor, Descriptor>) miterator2.next();
1309                     Descriptor enclosingDesc = pair.getFirst();
1310                     Descriptor desc = pair.getSecond();
1311
1312                     System.out.println("---inferLoc pair=" + pair);
1313
1314                     CompositeLocation inferLoc =
1315                         getLocationInfo(enclosingDesc).getInferLocation(desc);
1316                     System.out.println("oldLoc=" + inferLoc);
1317                     // if (curMethodInfo.md.equals(enclosingDesc)) {
1318                     // inferLoc = curMethodInfo.getInferLocation(desc);
1319                     // } else {
1320                     // inferLoc =
1321                     // getLocationInfo(enclosingDesc).getInferLocation(desc);
1322                     // }
1323
1324                     Location locElement = inferLoc.get(inferLoc.getSize() - 1);
1325
1326                     locElement.setLocIdentifier(newMergeLoc);
1327                     locInfo.addMapLocSymbolToRelatedInferLoc(newMergeLoc, enclosingDesc, desc);
1328
1329                     // if (curMethodInfo.md.equals(enclosingDesc)) {
1330                     // inferLoc = curMethodInfo.getInferLocation(desc);
1331                     // } else {
1332                     // inferLoc =
1333                     // getLocationInfo(enclosingDesc).getInferLocation(desc);
1334                     // }
1335
1336                     inferLoc = getLocationInfo(enclosingDesc).getInferLocation(desc);
1337                     System.out.println("---New Infer Loc=" + inferLoc);
1338
1339                   }
1340
1341                   locInfo.removeRelatedInferLocSet(oldLocSymbol, newMergeLoc);
1342
1343                 }
1344
1345                 for (Iterator iterator3 = mergeSet.iterator(); iterator3.hasNext();) {
1346                   String oldLoc = (String) iterator3.next();
1347                   lattice.remove(oldLoc);
1348                 }
1349                 return true;
1350               }
1351             }
1352           }
1353         }
1354       }
1355
1356     }
1357     return false;
1358   }
1359
1360   private void checkLattices() {
1361
1362     LinkedList<MethodDescriptor> descriptorListToAnalyze = ssjava.getSortedDescriptors();
1363
1364     // current descriptors to visit in fixed-point interprocedural analysis,
1365     // prioritized by
1366     // dependency in the call graph
1367     methodDescriptorsToVisitStack.clear();
1368
1369     // descriptorListToAnalyze.removeFirst();
1370
1371     Set<MethodDescriptor> methodDescriptorToVistSet = new HashSet<MethodDescriptor>();
1372     methodDescriptorToVistSet.addAll(descriptorListToAnalyze);
1373
1374     while (!descriptorListToAnalyze.isEmpty()) {
1375       MethodDescriptor md = descriptorListToAnalyze.removeFirst();
1376       checkLatticesOfVirtualMethods(md);
1377     }
1378
1379   }
1380
1381   private void debug_writeLatticeDotFile() {
1382     // generate lattice dot file
1383
1384     setupToAnalyze();
1385
1386     while (!toAnalyzeIsEmpty()) {
1387       ClassDescriptor cd = toAnalyzeNext();
1388
1389       setupToAnalazeMethod(cd);
1390
1391       SSJavaLattice<String> classLattice = cd2lattice.get(cd);
1392       if (classLattice != null) {
1393         ssjava.writeLatticeDotFile(cd, null, classLattice);
1394         debug_printDescriptorToLocNameMapping(cd);
1395       }
1396
1397       while (!toAnalyzeMethodIsEmpty()) {
1398         MethodDescriptor md = toAnalyzeMethodNext();
1399         SSJavaLattice<String> methodLattice = md2lattice.get(md);
1400         if (methodLattice != null) {
1401           ssjava.writeLatticeDotFile(cd, md, methodLattice);
1402           debug_printDescriptorToLocNameMapping(md);
1403         }
1404       }
1405     }
1406
1407   }
1408
1409   private void debug_printDescriptorToLocNameMapping(Descriptor desc) {
1410
1411     LocationInfo info = getLocationInfo(desc);
1412     System.out.println("## " + desc + " ##");
1413     System.out.println(info.getMapDescToInferLocation());
1414     LocationInfo locInfo = getLocationInfo(desc);
1415     System.out.println("mapping=" + locInfo.getMapLocSymbolToDescSet());
1416     System.out.println("###################");
1417
1418   }
1419
1420   private void inferLattices() {
1421
1422     // do fixed-point analysis
1423
1424     ssjava.init();
1425     LinkedList<MethodDescriptor> descriptorListToAnalyze = ssjava.getSortedDescriptors();
1426
1427     // Collections.sort(descriptorListToAnalyze, new
1428     // Comparator<MethodDescriptor>() {
1429     // public int compare(MethodDescriptor o1, MethodDescriptor o2) {
1430     // return o1.getSymbol().compareToIgnoreCase(o2.getSymbol());
1431     // }
1432     // });
1433
1434     // current descriptors to visit in fixed-point interprocedural analysis,
1435     // prioritized by
1436     // dependency in the call graph
1437     methodDescriptorsToVisitStack.clear();
1438
1439     // descriptorListToAnalyze.removeFirst();
1440
1441     Set<MethodDescriptor> methodDescriptorToVistSet = new HashSet<MethodDescriptor>();
1442     methodDescriptorToVistSet.addAll(descriptorListToAnalyze);
1443
1444     while (!descriptorListToAnalyze.isEmpty()) {
1445       MethodDescriptor md = descriptorListToAnalyze.removeFirst();
1446       methodDescriptorsToVisitStack.add(md);
1447     }
1448
1449     // analyze scheduled methods until there are no more to visit
1450     while (!methodDescriptorsToVisitStack.isEmpty()) {
1451       // start to analyze leaf node
1452       MethodDescriptor md = methodDescriptorsToVisitStack.pop();
1453
1454       SSJavaLattice<String> methodLattice =
1455           new SSJavaLattice<String>(SSJavaAnalysis.TOP, SSJavaAnalysis.BOTTOM);
1456
1457       MethodLocationInfo methodInfo = new MethodLocationInfo(md);
1458       curMethodInfo = methodInfo;
1459
1460       System.out.println();
1461       System.out.println("SSJAVA: Inferencing the lattice from " + md);
1462
1463       try {
1464         analyzeMethodLattice(md, methodLattice, methodInfo);
1465       } catch (CyclicFlowException e) {
1466         throw new Error("Fail to generate the method lattice for " + md);
1467       }
1468
1469       SSJavaLattice<String> prevMethodLattice = getMethodLattice(md);
1470       MethodLocationInfo prevMethodInfo = getMethodLocationInfo(md);
1471
1472       if ((!methodLattice.equals(prevMethodLattice)) || (!methodInfo.equals(prevMethodInfo))) {
1473
1474         setMethodLattice(md, methodLattice);
1475         setMethodLocInfo(md, methodInfo);
1476
1477         // results for callee changed, so enqueue dependents caller for
1478         // further analysis
1479         Iterator<MethodDescriptor> depsItr = ssjava.getDependents(md).iterator();
1480         while (depsItr.hasNext()) {
1481           MethodDescriptor methodNext = depsItr.next();
1482           if (!methodDescriptorsToVisitStack.contains(methodNext)
1483               && methodDescriptorToVistSet.contains(methodNext)) {
1484             methodDescriptorsToVisitStack.add(methodNext);
1485           }
1486         }
1487
1488       }
1489
1490     }
1491
1492   }
1493
1494   private void calculateExtraLocations() {
1495     LinkedList<MethodDescriptor> descriptorListToAnalyze = ssjava.getSortedDescriptors();
1496     for (Iterator iterator = descriptorListToAnalyze.iterator(); iterator.hasNext();) {
1497       MethodDescriptor md = (MethodDescriptor) iterator.next();
1498       calculateExtraLocations(md);
1499     }
1500   }
1501
1502   private void setMethodLocInfo(MethodDescriptor md, MethodLocationInfo methodInfo) {
1503     mapMethodDescToMethodLocationInfo.put(md, methodInfo);
1504   }
1505
1506   private void checkLatticesOfVirtualMethods(MethodDescriptor md) {
1507
1508     if (!md.isStatic()) {
1509       Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
1510       setPossibleCallees.addAll(ssjava.getCallGraph().getMethods(md));
1511
1512       for (Iterator iterator = setPossibleCallees.iterator(); iterator.hasNext();) {
1513         MethodDescriptor mdCallee = (MethodDescriptor) iterator.next();
1514         if (!md.equals(mdCallee)) {
1515           checkConsistency(md, mdCallee);
1516         }
1517       }
1518
1519     }
1520
1521   }
1522
1523   private void checkConsistency(MethodDescriptor md1, MethodDescriptor md2) {
1524
1525     // check that two lattice have the same relations between parameters(+PC
1526     // LOC, GLOBAL_LOC RETURN LOC)
1527
1528     List<CompositeLocation> list1 = new ArrayList<CompositeLocation>();
1529     List<CompositeLocation> list2 = new ArrayList<CompositeLocation>();
1530
1531     MethodLocationInfo locInfo1 = getMethodLocationInfo(md1);
1532     MethodLocationInfo locInfo2 = getMethodLocationInfo(md2);
1533
1534     Map<Integer, CompositeLocation> paramMap1 = locInfo1.getMapParamIdxToInferLoc();
1535     Map<Integer, CompositeLocation> paramMap2 = locInfo2.getMapParamIdxToInferLoc();
1536
1537     int numParam = locInfo1.getMapParamIdxToInferLoc().keySet().size();
1538
1539     // add location types of paramters
1540     for (int idx = 0; idx < numParam; idx++) {
1541       list1.add(paramMap1.get(Integer.valueOf(idx)));
1542       list2.add(paramMap2.get(Integer.valueOf(idx)));
1543     }
1544
1545     // add program counter location
1546     list1.add(locInfo1.getPCLoc());
1547     list2.add(locInfo2.getPCLoc());
1548
1549     if (!md1.getReturnType().isVoid()) {
1550       // add return value location
1551       CompositeLocation rtrLoc1 = getMethodLocationInfo(md1).getReturnLoc();
1552       CompositeLocation rtrLoc2 = getMethodLocationInfo(md2).getReturnLoc();
1553       list1.add(rtrLoc1);
1554       list2.add(rtrLoc2);
1555     }
1556
1557     // add global location type
1558     if (md1.isStatic()) {
1559       CompositeLocation globalLoc1 =
1560           new CompositeLocation(new Location(md1, locInfo1.getGlobalLocName()));
1561       CompositeLocation globalLoc2 =
1562           new CompositeLocation(new Location(md2, locInfo2.getGlobalLocName()));
1563       list1.add(globalLoc1);
1564       list2.add(globalLoc2);
1565     }
1566
1567     for (int i = 0; i < list1.size(); i++) {
1568       CompositeLocation locA1 = list1.get(i);
1569       CompositeLocation locA2 = list2.get(i);
1570       for (int k = 0; k < list1.size(); k++) {
1571         if (i != k) {
1572           CompositeLocation locB1 = list1.get(k);
1573           CompositeLocation locB2 = list2.get(k);
1574           boolean r1 = isGreaterThan(getLattice(md1), locA1, locB1);
1575
1576           boolean r2 = isGreaterThan(getLattice(md1), locA2, locB2);
1577
1578           if (r1 != r2) {
1579             throw new Error("The method " + md1 + " is not consistent with the method " + md2
1580                 + ".:: They have a different ordering relation between locations (" + locA1 + ","
1581                 + locB1 + ") and (" + locA2 + "," + locB2 + ").");
1582           }
1583         }
1584       }
1585     }
1586
1587   }
1588
1589   private String getSymbol(int idx, FlowNode node) {
1590     Descriptor desc = node.getDescTuple().get(idx);
1591     return desc.getSymbol();
1592   }
1593
1594   private Descriptor getDescriptor(int idx, FlowNode node) {
1595     Descriptor desc = node.getDescTuple().get(idx);
1596     return desc;
1597   }
1598
1599   private void analyzeMethodLattice(MethodDescriptor md, SSJavaLattice<String> methodLattice,
1600       MethodLocationInfo methodInfo) throws CyclicFlowException {
1601
1602     // first take a look at method invocation nodes to newly added relations
1603     // from the callee
1604     analyzeLatticeMethodInvocationNode(md, methodLattice, methodInfo);
1605
1606     if (!md.isStatic()) {
1607       // set the this location
1608       String thisLocSymbol = md.getThis().getSymbol();
1609       methodInfo.setThisLocName(thisLocSymbol);
1610     }
1611
1612     // set the global location
1613     methodInfo.setGlobalLocName(LocationInference.GLOBALLOC);
1614     methodInfo.mapDescriptorToLocation(GLOBALDESC, new CompositeLocation(
1615         new Location(md, GLOBALLOC)));
1616
1617     // visit each node of method flow graph
1618     FlowGraph fg = getFlowGraph(md);
1619     Set<FlowNode> nodeSet = fg.getNodeSet();
1620
1621     // for the method lattice, we need to look at the first element of
1622     // NTuple<Descriptor>
1623     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
1624       FlowNode srcNode = (FlowNode) iterator.next();
1625
1626       Set<FlowEdge> outEdgeSet = fg.getOutEdgeSet(srcNode);
1627       for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) {
1628         FlowEdge outEdge = (FlowEdge) iterator2.next();
1629         FlowNode dstNode = outEdge.getDst();
1630
1631         NTuple<Descriptor> srcNodeTuple = srcNode.getDescTuple();
1632         NTuple<Descriptor> dstNodeTuple = dstNode.getDescTuple();
1633
1634         if (outEdge.getInitTuple().equals(srcNodeTuple)
1635             && outEdge.getEndTuple().equals(dstNodeTuple)) {
1636
1637           if ((srcNodeTuple.size() > 1 && dstNodeTuple.size() > 1)
1638               && srcNodeTuple.get(0).equals(dstNodeTuple.get(0))) {
1639
1640             // value flows between fields
1641             Descriptor desc = srcNodeTuple.get(0);
1642             ClassDescriptor classDesc;
1643
1644             if (desc.equals(GLOBALDESC)) {
1645               classDesc = md.getClassDesc();
1646             } else {
1647               VarDescriptor varDesc = (VarDescriptor) srcNodeTuple.get(0);
1648               classDesc = varDesc.getType().getClassDesc();
1649             }
1650             extractRelationFromFieldFlows(classDesc, srcNode, dstNode, 1);
1651
1652           } else {
1653             // value flow between local var - local var or local var - field
1654             addRelationToLattice(md, methodLattice, methodInfo, srcNode, dstNode);
1655           }
1656         }
1657       }
1658     }
1659
1660     // create mapping from param idx to inferred composite location
1661
1662     int offset;
1663     if (!md.isStatic()) {
1664       // add 'this' reference location
1665       offset = 1;
1666       methodInfo.addMapParamIdxToInferLoc(0, methodInfo.getInferLocation(md.getThis()));
1667     } else {
1668       offset = 0;
1669     }
1670
1671     for (int idx = 0; idx < md.numParameters(); idx++) {
1672       Descriptor paramDesc = md.getParameter(idx);
1673       CompositeLocation inferParamLoc = methodInfo.getInferLocation(paramDesc);
1674       methodInfo.addMapParamIdxToInferLoc(idx + offset, inferParamLoc);
1675     }
1676
1677   }
1678
1679   private void calculateExtraLocations(MethodDescriptor md) {
1680     // calcualte pcloc, returnloc,...
1681
1682     SSJavaLattice<String> methodLattice = getMethodLattice(md);
1683     MethodLocationInfo methodInfo = getMethodLocationInfo(md);
1684     FlowGraph fg = getFlowGraph(md);
1685     Set<FlowNode> nodeSet = fg.getNodeSet();
1686
1687     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
1688       FlowNode flowNode = (FlowNode) iterator.next();
1689       if (flowNode.isDeclaratonNode()) {
1690         CompositeLocation inferLoc = methodInfo.getInferLocation(flowNode.getDescTuple().get(0));
1691         String locIdentifier = inferLoc.get(0).getLocIdentifier();
1692         if (!methodLattice.containsKey(locIdentifier)) {
1693           methodLattice.put(locIdentifier);
1694         }
1695
1696       }
1697     }
1698
1699     Map<Integer, CompositeLocation> mapParamToLoc = methodInfo.getMapParamIdxToInferLoc();
1700     Set<Integer> paramIdxSet = mapParamToLoc.keySet();
1701
1702     try {
1703       if (!ssjava.getMethodContainingSSJavaLoop().equals(md)) {
1704         // calculate the initial program counter location
1705         // PC location is higher than location types of all parameters
1706         String pcLocSymbol = "PCLOC";
1707
1708         Set<CompositeLocation> paramInFlowSet = new HashSet<CompositeLocation>();
1709
1710         for (Iterator iterator = paramIdxSet.iterator(); iterator.hasNext();) {
1711           Integer paramIdx = (Integer) iterator.next();
1712
1713           FlowNode paramFlowNode = fg.getParamFlowNode(paramIdx);
1714
1715           if (fg.getIncomingFlowNodeSet(paramFlowNode).size() > 0) {
1716             // parameter has in-value flows
1717             CompositeLocation inferLoc = mapParamToLoc.get(paramIdx);
1718             paramInFlowSet.add(inferLoc);
1719           }
1720         }
1721
1722         if (paramInFlowSet.size() > 0) {
1723           CompositeLocation lowestLoc = getLowest(methodLattice, paramInFlowSet);
1724           assert (lowestLoc != null);
1725           methodInfo.setPCLoc(lowestLoc);
1726         }
1727
1728       }
1729
1730       // calculate a return location
1731       // the return location type is lower than all parameters and location
1732       // types
1733       // of return values
1734       if (!md.getReturnType().isVoid()) {
1735         // first, generate the set of return value location types that starts
1736         // with
1737         // 'this' reference
1738
1739         Set<CompositeLocation> inferFieldReturnLocSet = new HashSet<CompositeLocation>();
1740
1741         Set<FlowNode> paramFlowNode = getParamNodeFlowingToReturnValue(md);
1742         Set<CompositeLocation> inferParamLocSet = new HashSet<CompositeLocation>();
1743         if (paramFlowNode != null) {
1744           for (Iterator iterator = paramFlowNode.iterator(); iterator.hasNext();) {
1745             FlowNode fn = (FlowNode) iterator.next();
1746             CompositeLocation inferLoc =
1747                 generateInferredCompositeLocation(methodInfo, getFlowGraph(md).getLocationTuple(fn));
1748             inferParamLocSet.add(inferLoc);
1749           }
1750         }
1751
1752         Set<FlowNode> returnNodeSet = fg.getReturnNodeSet();
1753
1754         skip: for (Iterator iterator = returnNodeSet.iterator(); iterator.hasNext();) {
1755           FlowNode returnNode = (FlowNode) iterator.next();
1756           CompositeLocation inferReturnLoc =
1757               generateInferredCompositeLocation(methodInfo, fg.getLocationTuple(returnNode));
1758           if (inferReturnLoc.get(0).getLocIdentifier().equals("this")) {
1759             // if the location type of the return value matches "this" reference
1760             // then, check whether this return value is equal to/lower than all
1761             // of
1762             // parameters that possibly flow into the return values
1763             for (Iterator iterator2 = inferParamLocSet.iterator(); iterator2.hasNext();) {
1764               CompositeLocation paramInferLoc = (CompositeLocation) iterator2.next();
1765
1766               if ((!paramInferLoc.equals(inferReturnLoc))
1767                   && !isGreaterThan(methodLattice, paramInferLoc, inferReturnLoc)) {
1768                 continue skip;
1769               }
1770             }
1771             inferFieldReturnLocSet.add(inferReturnLoc);
1772
1773           }
1774         }
1775
1776         if (inferFieldReturnLocSet.size() > 0) {
1777
1778           CompositeLocation returnLoc = getLowest(methodLattice, inferFieldReturnLocSet);
1779           if (returnLoc == null) {
1780             // in this case, assign <'this',bottom> to the RETURNLOC
1781             returnLoc = new CompositeLocation(new Location(md, md.getThis().getSymbol()));
1782             returnLoc.addLocation(new Location(md.getClassDesc(), getLattice(md.getClassDesc())
1783                 .getBottomItem()));
1784           }
1785           methodInfo.setReturnLoc(returnLoc);
1786
1787         } else {
1788           String returnLocSymbol = "RETURNLOC";
1789           CompositeLocation returnLocInferLoc =
1790               new CompositeLocation(new Location(md, returnLocSymbol));
1791           methodInfo.setReturnLoc(returnLocInferLoc);
1792
1793           for (Iterator iterator = paramIdxSet.iterator(); iterator.hasNext();) {
1794             Integer paramIdx = (Integer) iterator.next();
1795             CompositeLocation inferLoc = mapParamToLoc.get(paramIdx);
1796             String paramLocLocalSymbol = inferLoc.get(0).getLocIdentifier();
1797             if (!methodLattice.isGreaterThan(paramLocLocalSymbol, returnLocSymbol)) {
1798               addRelationHigherToLower(methodLattice, methodInfo, paramLocLocalSymbol,
1799                   returnLocSymbol);
1800             }
1801           }
1802
1803           for (Iterator iterator = returnNodeSet.iterator(); iterator.hasNext();) {
1804             FlowNode returnNode = (FlowNode) iterator.next();
1805             CompositeLocation inferLoc =
1806                 generateInferredCompositeLocation(methodInfo, fg.getLocationTuple(returnNode));
1807             if (!isGreaterThan(methodLattice, inferLoc, returnLocInferLoc)) {
1808               addRelation(methodLattice, methodInfo, inferLoc, returnLocInferLoc);
1809             }
1810           }
1811
1812         }
1813
1814       }
1815     } catch (CyclicFlowException e) {
1816       e.printStackTrace();
1817     }
1818
1819   }
1820
1821   private Set<String> getHigherLocSymbolThan(SSJavaLattice<String> lattice, String loc) {
1822     Set<String> higherLocSet = new HashSet<String>();
1823
1824     Set<String> locSet = lattice.getTable().keySet();
1825     for (Iterator iterator = locSet.iterator(); iterator.hasNext();) {
1826       String element = (String) iterator.next();
1827       if (lattice.isGreaterThan(element, loc) && (!element.equals(lattice.getTopItem()))) {
1828         higherLocSet.add(element);
1829       }
1830     }
1831     return higherLocSet;
1832   }
1833
1834   private CompositeLocation getLowest(SSJavaLattice<String> methodLattice,
1835       Set<CompositeLocation> set) {
1836
1837     CompositeLocation lowest = set.iterator().next();
1838
1839     if (set.size() == 1) {
1840       return lowest;
1841     }
1842
1843     for (Iterator iterator = set.iterator(); iterator.hasNext();) {
1844       CompositeLocation loc = (CompositeLocation) iterator.next();
1845
1846       if ((!loc.equals(lowest)) && (!isComparable(methodLattice, lowest, loc))) {
1847         // if there is a case where composite locations are incomparable, just
1848         // return null
1849         return null;
1850       }
1851
1852       if ((!loc.equals(lowest)) && isGreaterThan(methodLattice, lowest, loc)) {
1853         lowest = loc;
1854       }
1855     }
1856     return lowest;
1857   }
1858
1859   private boolean isComparable(SSJavaLattice<String> methodLattice, CompositeLocation comp1,
1860       CompositeLocation comp2) {
1861
1862     int size = comp1.getSize() >= comp2.getSize() ? comp2.getSize() : comp1.getSize();
1863
1864     for (int idx = 0; idx < size; idx++) {
1865       Location loc1 = comp1.get(idx);
1866       Location loc2 = comp2.get(idx);
1867
1868       Descriptor desc1 = loc1.getDescriptor();
1869       Descriptor desc2 = loc2.getDescriptor();
1870
1871       if (!desc1.equals(desc2)) {
1872         throw new Error("Fail to compare " + comp1 + " and " + comp2);
1873       }
1874
1875       String symbol1 = loc1.getLocIdentifier();
1876       String symbol2 = loc2.getLocIdentifier();
1877
1878       SSJavaLattice<String> lattice;
1879       if (idx == 0) {
1880         lattice = methodLattice;
1881       } else {
1882         lattice = getLattice(desc1);
1883       }
1884
1885       if (symbol1.equals(symbol2)) {
1886         continue;
1887       } else if (!lattice.isComparable(symbol1, symbol2)) {
1888         return false;
1889       }
1890
1891     }
1892
1893     return true;
1894   }
1895
1896   private boolean isGreaterThan(SSJavaLattice<String> methodLattice, CompositeLocation comp1,
1897       CompositeLocation comp2) {
1898
1899     int size = comp1.getSize() >= comp2.getSize() ? comp2.getSize() : comp1.getSize();
1900
1901     for (int idx = 0; idx < size; idx++) {
1902       Location loc1 = comp1.get(idx);
1903       Location loc2 = comp2.get(idx);
1904
1905       Descriptor desc1 = loc1.getDescriptor();
1906       Descriptor desc2 = loc2.getDescriptor();
1907
1908       if (!desc1.equals(desc2)) {
1909         throw new Error("Fail to compare " + comp1 + " and " + comp2);
1910       }
1911
1912       String symbol1 = loc1.getLocIdentifier();
1913       String symbol2 = loc2.getLocIdentifier();
1914
1915       SSJavaLattice<String> lattice;
1916       if (idx == 0) {
1917         lattice = methodLattice;
1918       } else {
1919         lattice = getLattice(desc1);
1920       }
1921
1922       if (symbol1.equals(symbol2)) {
1923         continue;
1924       } else if (lattice.isGreaterThan(symbol1, symbol2)) {
1925         return true;
1926       } else {
1927         return false;
1928       }
1929
1930     }
1931
1932     return false;
1933   }
1934
1935   private void recursiveAddRelationToLattice(int idx, MethodDescriptor md,
1936       CompositeLocation srcInferLoc, CompositeLocation dstInferLoc) throws CyclicFlowException {
1937
1938     String srcLocSymbol = srcInferLoc.get(idx).getLocIdentifier();
1939     String dstLocSymbol = dstInferLoc.get(idx).getLocIdentifier();
1940
1941     if (srcLocSymbol.equals(dstLocSymbol)) {
1942       recursiveAddRelationToLattice(idx + 1, md, srcInferLoc, dstInferLoc);
1943     } else {
1944
1945       Descriptor parentDesc = srcInferLoc.get(idx).getDescriptor();
1946       LocationInfo locInfo = getLocationInfo(parentDesc);
1947
1948       addRelationHigherToLower(getLattice(parentDesc), getLocationInfo(parentDesc), srcLocSymbol,
1949           dstLocSymbol);
1950     }
1951
1952   }
1953
1954   // private void propagateFlowsFromCallee(MethodInvokeNode min, MethodDescriptor mdCaller,
1955   // MethodDescriptor mdCallee) {
1956   //
1957   // // the transformation for a call site propagates all relations between
1958   // // parameters from the callee
1959   // // if the method is virtual, it also grab all relations from any possible
1960   // // callees
1961   //
1962   // Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
1963   // if (mdCallee.isStatic()) {
1964   // setPossibleCallees.add(mdCallee);
1965   // } else {
1966   // Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
1967   // // removes method descriptors that are not invoked by the caller
1968   // calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
1969   // setPossibleCallees.addAll(calleeSet);
1970   // }
1971   //
1972   // for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
1973   // MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
1974   // propagateFlowsToCaller(min, mdCaller, possibleMdCallee);
1975   // }
1976   //
1977   // }
1978
1979   private void contributeCalleeFlows(MethodInvokeNode min, MethodDescriptor mdCaller,
1980       MethodDescriptor mdCallee) {
1981
1982     System.out.println("\n##contributeCalleeFlows callee=" + mdCallee + "TO caller=" + mdCaller);
1983
1984     getSubGlobalFlowGraph(mdCallee);
1985
1986   }
1987
1988   private FlowGraph getSubGlobalFlowGraph(MethodDescriptor md) {
1989     return mapMethodDescriptorToSubGlobalFlowGraph.get(md);
1990   }
1991
1992   private void propagateFlowsToCallerWithNoCompositeLocation(MethodInvokeNode min,
1993       MethodDescriptor mdCaller, MethodDescriptor mdCallee) {
1994
1995     System.out.println("\n##PROPAGATE callee=" + mdCallee + "TO caller=" + mdCaller);
1996
1997     // if the parameter A reaches to the parameter B
1998     // then, add an edge the argument A -> the argument B to the caller's flow
1999     // graph
2000
2001     FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
2002     FlowGraph callerFlowGraph = getFlowGraph(mdCaller);
2003     int numParam = calleeFlowGraph.getNumParameters();
2004
2005     for (int i = 0; i < numParam; i++) {
2006       for (int k = 0; k < numParam; k++) {
2007
2008         if (i != k) {
2009
2010           FlowNode paramNode1 = calleeFlowGraph.getParamFlowNode(i);
2011           FlowNode paramNode2 = calleeFlowGraph.getParamFlowNode(k);
2012
2013           NodeTupleSet tupleSetArg1 = getNodeTupleSetByArgIdx(min, i);
2014           NodeTupleSet tupleSetArg2 = getNodeTupleSetByArgIdx(min, k);
2015
2016           for (Iterator<NTuple<Descriptor>> iter1 = tupleSetArg1.iterator(); iter1.hasNext();) {
2017             NTuple<Descriptor> arg1Tuple = iter1.next();
2018
2019             for (Iterator<NTuple<Descriptor>> iter2 = tupleSetArg2.iterator(); iter2.hasNext();) {
2020               NTuple<Descriptor> arg2Tuple = iter2.next();
2021
2022               // check if the callee propagates an ordering constraints through
2023               // parameters
2024
2025               Set<FlowNode> localReachSet =
2026                   calleeFlowGraph.getLocalReachFlowNodeSetFrom(paramNode1);
2027
2028               if (localReachSet.contains(paramNode2)) {
2029                 // need to propagate an ordering relation s.t. arg1 is higher
2030                 // than arg2
2031
2032                 System.out
2033                     .println("-param1=" + paramNode1 + " is higher than param2=" + paramNode2);
2034                 System.out.println("-arg1Tuple=" + arg1Tuple + " is higher than arg2Tuple="
2035                     + arg2Tuple);
2036
2037                 // otherwise, flows between method/field locations...
2038                 callerFlowGraph.addValueFlowEdge(arg1Tuple, arg2Tuple);
2039                 System.out.println("arg1=" + arg1Tuple + "   arg2=" + arg2Tuple);
2040
2041               }
2042
2043             }
2044
2045           }
2046           System.out.println();
2047         }
2048       }
2049     }
2050     System.out.println("##\n");
2051
2052   }
2053
2054   private void propagateFlowsToCaller(MethodInvokeNode min, MethodDescriptor mdCaller,
2055       MethodDescriptor mdCallee) {
2056
2057     System.out.println("\n##PROPAGATE callee=" + mdCallee + "TO caller=" + mdCaller);
2058
2059     // if the parameter A reaches to the parameter B
2060     // then, add an edge the argument A -> the argument B to the caller's flow
2061     // graph
2062
2063     // TODO
2064     // also if a parameter is a composite location and is started with "this" reference,
2065     // need to make sure that the corresponding argument is higher than the translated location of
2066     // the parameter.
2067
2068     FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
2069     FlowGraph callerFlowGraph = getFlowGraph(mdCaller);
2070     int numParam = calleeFlowGraph.getNumParameters();
2071
2072     for (int i = 0; i < numParam; i++) {
2073       for (int k = 0; k < numParam; k++) {
2074
2075         if (i != k) {
2076
2077           FlowNode paramNode1 = calleeFlowGraph.getParamFlowNode(i);
2078           FlowNode paramNode2 = calleeFlowGraph.getParamFlowNode(k);
2079
2080           System.out.println("param1=" + paramNode1 + " curDescTuple="
2081               + paramNode1.getCurrentDescTuple());
2082           System.out.println("param2=" + paramNode2 + " curDescTuple="
2083               + paramNode2.getCurrentDescTuple());
2084
2085           NodeTupleSet tupleSetArg1 = getNodeTupleSetByArgIdx(min, i);
2086           NodeTupleSet tupleSetArg2 = getNodeTupleSetByArgIdx(min, k);
2087
2088           for (Iterator<NTuple<Descriptor>> iter1 = tupleSetArg1.iterator(); iter1.hasNext();) {
2089             NTuple<Descriptor> arg1Tuple = iter1.next();
2090
2091             for (Iterator<NTuple<Descriptor>> iter2 = tupleSetArg2.iterator(); iter2.hasNext();) {
2092               NTuple<Descriptor> arg2Tuple = iter2.next();
2093
2094               // check if the callee propagates an ordering constraints through
2095               // parameters
2096
2097               Set<FlowNode> localReachSet =
2098                   calleeFlowGraph.getLocalReachFlowNodeSetFrom(paramNode1);
2099
2100               if (localReachSet.contains(paramNode2)) {
2101                 // need to propagate an ordering relation s.t. arg1 is higher
2102                 // than arg2
2103
2104                 System.out
2105                     .println("-param1=" + paramNode1 + " is higher than param2=" + paramNode2);
2106                 System.out.println("-arg1Tuple=" + arg1Tuple + " is higher than arg2Tuple="
2107                     + arg2Tuple);
2108
2109                 if (!min.getMethod().isStatic()) {
2110                   // check if this is the case that values flow to/from the
2111                   // current object reference 'this'
2112
2113                   NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
2114                   Descriptor baseRef = baseTuple.get(baseTuple.size() - 1);
2115
2116                   System.out.println("paramNode1.getCurrentDescTuple()="
2117                       + paramNode1.getCurrentDescTuple());
2118                   // calculate the prefix of the argument
2119
2120                   if (arg2Tuple.size() == 1 && arg2Tuple.get(0).equals(baseRef)) {
2121                     // in this case, the callee flow causes a caller flow to the object whose method
2122                     // is invoked.
2123
2124                     if (!paramNode1.getCurrentDescTuple().startsWith(mdCallee.getThis())) {
2125                       // check whether ???
2126
2127                       NTuple<Descriptor> param1Prefix =
2128                           calculatePrefixForParam(callerFlowGraph, calleeFlowGraph, min, arg1Tuple,
2129                               paramNode1);
2130
2131                       if (param1Prefix != null && param1Prefix.startsWith(mdCallee.getThis())) {
2132                         // in this case, we need to create a new edge 'this.FIELD'->'this'
2133                         // but we couldn't... instead we assign a new composite location started
2134                         // with 'this' reference to the corresponding parameter
2135
2136                         CompositeLocation compLocForParam1 =
2137                             generateCompositeLocation(mdCallee, param1Prefix);
2138
2139                         System.out
2140                             .println("set comp loc=" + compLocForParam1 + " to " + paramNode1);
2141                         paramNode1.setCompositeLocation(compLocForParam1);
2142
2143                         // then, we need to make sure that the corresponding argument in the caller
2144                         // is required to be higher than or equal to the translated parameter
2145                         // location
2146
2147                         NTuple<Descriptor> translatedParamTuple =
2148                             translateCompositeLocationToCaller(min, compLocForParam1);
2149
2150                         // TODO : check if the arg >= the tranlated parameter
2151
2152                         System.out.println("add a flow edge= " + arg1Tuple + "->"
2153                             + translatedParamTuple);
2154                         callerFlowGraph.addValueFlowEdge(arg1Tuple, translatedParamTuple);
2155
2156                         continue;
2157
2158                       }
2159
2160                     } else {
2161                       // param1 has already been assigned a composite location
2162
2163                       System.out.println("--param1 has already been assigned a composite location");
2164                       CompositeLocation compLocForParam1 = paramNode1.getCompositeLocation();
2165                       NTuple<Descriptor> translatedParamTuple =
2166                           translateCompositeLocationToCaller(min, compLocForParam1);
2167
2168                       // TODO : check if the arg >= the tranlated parameter
2169
2170                       System.out.println("add a flow edge= " + arg1Tuple + "->"
2171                           + translatedParamTuple);
2172                       callerFlowGraph.addValueFlowEdge(arg1Tuple, translatedParamTuple);
2173
2174                       continue;
2175
2176                     }
2177
2178                   } else if (arg1Tuple.size() == 1 && arg1Tuple.get(0).equals(baseRef)) {
2179                     // in this case, the callee flow causes a caller flow originated from the object
2180                     // whose
2181                     // method is invoked.
2182
2183                     System.out.println("###FROM CASE");
2184
2185                     if (!paramNode2.getCurrentDescTuple().startsWith(mdCallee.getThis())) {
2186
2187                       NTuple<Descriptor> param2Prefix =
2188                           calculatePrefixForParam(callerFlowGraph, calleeFlowGraph, min, arg2Tuple,
2189                               paramNode2);
2190
2191                       if (param2Prefix != null && param2Prefix.startsWith(mdCallee.getThis())) {
2192                         // in this case, we need to create a new edge 'this' ->
2193                         // 'this.FIELD' but we couldn't... instead we assign the corresponding
2194                         // parameter a new composite location started with 'this' reference
2195
2196                         CompositeLocation compLocForParam2 =
2197                             generateCompositeLocation(mdCallee, param2Prefix);
2198
2199                         // System.out.println("set comp loc=" + compLocForParam2
2200                         // +
2201                         // " to " + paramNode2);
2202                         paramNode1.setCompositeLocation(compLocForParam2);
2203                         continue;
2204                       }
2205                     }
2206
2207                   }
2208                 }
2209
2210                 // otherwise, flows between method/field locations...
2211                 callerFlowGraph.addValueFlowEdge(arg1Tuple, arg2Tuple);
2212                 System.out.println("arg1=" + arg1Tuple + "   arg2=" + arg2Tuple);
2213
2214               }
2215
2216             }
2217
2218           }
2219           System.out.println();
2220         }
2221       }
2222     }
2223     System.out.println("##\n");
2224   }
2225
2226   private NTuple<Descriptor> translateCompositeLocationToCaller(MethodInvokeNode min,
2227       CompositeLocation compLocForParam1) {
2228     NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
2229
2230     NTuple<Descriptor> tuple = new NTuple<Descriptor>();
2231
2232     for (int i = 0; i < baseTuple.size(); i++) {
2233       tuple.add(baseTuple.get(i));
2234     }
2235
2236     for (int i = 1; i < compLocForParam1.getSize(); i++) {
2237       Location loc = compLocForParam1.get(i);
2238       tuple.add(loc.getLocDescriptor());
2239     }
2240
2241     return tuple;
2242   }
2243
2244   private CompositeLocation generateCompositeLocation(MethodDescriptor md,
2245       NTuple<Descriptor> paramPrefix) {
2246
2247     System.out.println("generateCompositeLocation=" + paramPrefix);
2248
2249     CompositeLocation newCompLoc = convertToCompositeLocation(md, paramPrefix);
2250
2251     Descriptor lastDescOfPrefix = paramPrefix.get(paramPrefix.size() - 1);
2252     // System.out.println("lastDescOfPrefix=" + lastDescOfPrefix + "  kind="
2253     // + lastDescOfPrefix.getClass());
2254     ClassDescriptor enclosingDescriptor;
2255     if (lastDescOfPrefix instanceof FieldDescriptor) {
2256       enclosingDescriptor = ((FieldDescriptor) lastDescOfPrefix).getType().getClassDesc();
2257       // System.out.println("enclosingDescriptor0=" + enclosingDescriptor);
2258     } else {
2259       // var descriptor case
2260       enclosingDescriptor = ((VarDescriptor) lastDescOfPrefix).getType().getClassDesc();
2261     }
2262     // System.out.println("enclosingDescriptor=" + enclosingDescriptor);
2263
2264     LocationDescriptor newLocDescriptor = generateNewLocationDescriptor();
2265     newLocDescriptor.setEnclosingClassDesc(enclosingDescriptor);
2266
2267     Location newLoc = new Location(enclosingDescriptor, newLocDescriptor.getSymbol());
2268     newLoc.setLocDescriptor(newLocDescriptor);
2269     newCompLoc.addLocation(newLoc);
2270
2271     // System.out.println("--newCompLoc=" + newCompLoc);
2272     return newCompLoc;
2273   }
2274
2275   private NTuple<Descriptor> calculatePrefixForParam(FlowGraph callerFlowGraph,
2276       FlowGraph calleeFlowGraph, MethodInvokeNode min, NTuple<Descriptor> arg1Tuple,
2277       FlowNode paramNode1) {
2278
2279     NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
2280     Descriptor baseRef = baseTuple.get(baseTuple.size() - 1);
2281     System.out.println("baseRef=" + baseRef);
2282
2283     FlowNode flowNodeArg1 = callerFlowGraph.getFlowNode(arg1Tuple);
2284     List<NTuple<Descriptor>> callerPrefixList = calculatePrefixList(callerFlowGraph, flowNodeArg1);
2285     System.out.println("callerPrefixList=" + callerPrefixList);
2286
2287     List<NTuple<Descriptor>> prefixList = calculatePrefixList(calleeFlowGraph, paramNode1);
2288     System.out.println("###prefixList from node=" + paramNode1 + " =" + prefixList);
2289
2290     List<NTuple<Descriptor>> calleePrefixList =
2291         translatePrefixListToCallee(baseRef, min.getMethod(), callerPrefixList);
2292
2293     System.out.println("calleePrefixList=" + calleePrefixList);
2294
2295     Set<FlowNode> reachNodeSetFromParam1 = calleeFlowGraph.getReachFlowNodeSetFrom(paramNode1);
2296     System.out.println("reachNodeSetFromParam1=" + reachNodeSetFromParam1);
2297
2298     for (int i = 0; i < calleePrefixList.size(); i++) {
2299       NTuple<Descriptor> curPrefix = calleePrefixList.get(i);
2300       Set<NTuple<Descriptor>> reachableCommonPrefixSet = new HashSet<NTuple<Descriptor>>();
2301
2302       for (Iterator iterator2 = reachNodeSetFromParam1.iterator(); iterator2.hasNext();) {
2303         FlowNode reachNode = (FlowNode) iterator2.next();
2304         if (reachNode.getCurrentDescTuple().startsWith(curPrefix)) {
2305           reachableCommonPrefixSet.add(reachNode.getCurrentDescTuple());
2306         }
2307       }
2308
2309       if (!reachableCommonPrefixSet.isEmpty()) {
2310         System.out.println("###REACHABLECOMONPREFIX=" + reachableCommonPrefixSet
2311             + " with curPreFix=" + curPrefix);
2312         return curPrefix;
2313       }
2314
2315     }
2316
2317     return null;
2318   }
2319
2320   private List<NTuple<Descriptor>> translatePrefixListToCallee(Descriptor baseRef,
2321       MethodDescriptor mdCallee, List<NTuple<Descriptor>> callerPrefixList) {
2322
2323     List<NTuple<Descriptor>> calleePrefixList = new ArrayList<NTuple<Descriptor>>();
2324
2325     for (int i = 0; i < callerPrefixList.size(); i++) {
2326       NTuple<Descriptor> prefix = callerPrefixList.get(i);
2327       if (prefix.startsWith(baseRef)) {
2328         NTuple<Descriptor> calleePrefix = new NTuple<Descriptor>();
2329         calleePrefix.add(mdCallee.getThis());
2330         for (int k = 1; k < prefix.size(); k++) {
2331           calleePrefix.add(prefix.get(k));
2332         }
2333         calleePrefixList.add(calleePrefix);
2334       }
2335     }
2336
2337     return calleePrefixList;
2338
2339   }
2340
2341   private List<NTuple<Descriptor>> calculatePrefixList(FlowGraph flowGraph, FlowNode flowNode) {
2342
2343     System.out.println("\n##### calculatePrefixList=" + flowNode);
2344
2345     Set<FlowNode> inNodeSet = flowGraph.getIncomingFlowNodeSet(flowNode);
2346     inNodeSet.add(flowNode);
2347
2348     System.out.println("inNodeSet=" + inNodeSet);
2349
2350     List<NTuple<Descriptor>> prefixList = new ArrayList<NTuple<Descriptor>>();
2351
2352     for (Iterator iterator = inNodeSet.iterator(); iterator.hasNext();) {
2353       FlowNode inNode = (FlowNode) iterator.next();
2354
2355       NTuple<Descriptor> inNodeTuple = inNode.getCurrentDescTuple();
2356
2357       // CompositeLocation inNodeInferredLoc =
2358       // generateInferredCompositeLocation(methodInfo, inNodeTuple);
2359       // NTuple<Location> inNodeInferredLocTuple = inNodeInferredLoc.getTuple();
2360
2361       for (int i = 1; i < inNodeTuple.size(); i++) {
2362         NTuple<Descriptor> prefix = inNodeTuple.subList(0, i);
2363         if (!prefixList.contains(prefix)) {
2364           prefixList.add(prefix);
2365         }
2366       }
2367     }
2368
2369     Collections.sort(prefixList, new Comparator<NTuple<Descriptor>>() {
2370       public int compare(NTuple<Descriptor> arg0, NTuple<Descriptor> arg1) {
2371         int s0 = arg0.size();
2372         int s1 = arg1.size();
2373         if (s0 > s1) {
2374           return -1;
2375         } else if (s0 == s1) {
2376           return 0;
2377         } else {
2378           return 1;
2379         }
2380       }
2381     });
2382
2383     return prefixList;
2384
2385   }
2386
2387   public CompositeLocation convertToCompositeLocation(MethodDescriptor md, NTuple<Descriptor> tuple) {
2388
2389     CompositeLocation compLoc = new CompositeLocation();
2390
2391     Descriptor enclosingDescriptor = md;
2392
2393     for (int i = 0; i < tuple.size(); i++) {
2394       Descriptor curDescriptor = tuple.get(i);
2395       Location locElement = new Location(enclosingDescriptor, curDescriptor.getSymbol());
2396       locElement.setLocDescriptor(curDescriptor);
2397       compLoc.addLocation(locElement);
2398
2399       if (curDescriptor instanceof VarDescriptor) {
2400         enclosingDescriptor = md.getClassDesc();
2401       } else if (curDescriptor instanceof NameDescriptor) {
2402         // it is "GLOBAL LOC" case!
2403         enclosingDescriptor = GLOBALDESC;
2404       } else {
2405         enclosingDescriptor = ((FieldDescriptor) curDescriptor).getClassDescriptor();
2406       }
2407
2408     }
2409
2410     System.out.println("-convertToCompositeLocation from=" + tuple + " to " + compLoc);
2411
2412     return compLoc;
2413   }
2414
2415   private LocationDescriptor generateNewLocationDescriptor() {
2416     return new LocationDescriptor("Loc" + (locSeed++));
2417   }
2418
2419   private int getPrefixIndex(NTuple<Descriptor> tuple1, NTuple<Descriptor> tuple2) {
2420
2421     // return the index where the prefix shared by tuple1 and tuple2 is ended
2422     // if there is no prefix shared by both of them, return -1
2423
2424     int minSize = tuple1.size();
2425     if (minSize > tuple2.size()) {
2426       minSize = tuple2.size();
2427     }
2428
2429     int idx = -1;
2430     for (int i = 0; i < minSize; i++) {
2431       if (!tuple1.get(i).equals(tuple2.get(i))) {
2432         break;
2433       } else {
2434         idx++;
2435       }
2436     }
2437
2438     return idx;
2439   }
2440
2441   private void analyzeLatticeMethodInvocationNode(MethodDescriptor mdCaller,
2442       SSJavaLattice<String> methodLattice, MethodLocationInfo methodInfo)
2443       throws CyclicFlowException {
2444
2445     // the transformation for a call site propagates all relations between
2446     // parameters from the callee
2447     // if the method is virtual, it also grab all relations from any possible
2448     // callees
2449
2450     Set<MethodInvokeNode> setMethodInvokeNode =
2451         mapMethodDescriptorToMethodInvokeNodeSet.get(mdCaller);
2452
2453     if (setMethodInvokeNode != null) {
2454
2455       for (Iterator iterator = setMethodInvokeNode.iterator(); iterator.hasNext();) {
2456         MethodInvokeNode min = (MethodInvokeNode) iterator.next();
2457         MethodDescriptor mdCallee = min.getMethod();
2458         Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
2459         if (mdCallee.isStatic()) {
2460           setPossibleCallees.add(mdCallee);
2461         } else {
2462           Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
2463           // removes method descriptors that are not invoked by the caller
2464           calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
2465           setPossibleCallees.addAll(calleeSet);
2466         }
2467
2468         for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
2469           MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
2470           propagateRelationToCaller(min, mdCaller, possibleMdCallee, methodLattice, methodInfo);
2471         }
2472
2473       }
2474     }
2475
2476   }
2477
2478   private void propagateRelationToCaller(MethodInvokeNode min, MethodDescriptor mdCaller,
2479       MethodDescriptor possibleMdCallee, SSJavaLattice<String> methodLattice,
2480       MethodLocationInfo methodInfo) throws CyclicFlowException {
2481
2482     SSJavaLattice<String> calleeLattice = getMethodLattice(possibleMdCallee);
2483     MethodLocationInfo calleeLocInfo = getMethodLocationInfo(possibleMdCallee);
2484     FlowGraph calleeFlowGraph = getFlowGraph(possibleMdCallee);
2485
2486     int numParam = calleeLocInfo.getNumParam();
2487     for (int i = 0; i < numParam; i++) {
2488       CompositeLocation param1 = calleeLocInfo.getParamCompositeLocation(i);
2489       for (int k = 0; k < numParam; k++) {
2490         if (i != k) {
2491           CompositeLocation param2 = calleeLocInfo.getParamCompositeLocation(k);
2492
2493           if (isGreaterThan(getLattice(possibleMdCallee), param1, param2)) {
2494             NodeTupleSet argDescTupleSet1 = getNodeTupleSetByArgIdx(min, i);
2495             NodeTupleSet argDescTupleSet2 = getNodeTupleSetByArgIdx(min, k);
2496
2497             // the callee has the relation in which param1 is higher than param2
2498             // therefore, the caller has to have the relation in which arg1 is
2499             // higher than arg2
2500
2501             for (Iterator<NTuple<Descriptor>> iterator = argDescTupleSet1.iterator(); iterator
2502                 .hasNext();) {
2503               NTuple<Descriptor> argDescTuple1 = iterator.next();
2504
2505               for (Iterator<NTuple<Descriptor>> iterator2 = argDescTupleSet2.iterator(); iterator2
2506                   .hasNext();) {
2507                 NTuple<Descriptor> argDescTuple2 = iterator2.next();
2508
2509                 // retreive inferred location by the local var descriptor
2510
2511                 NTuple<Location> tuple1 = getFlowGraph(mdCaller).getLocationTuple(argDescTuple1);
2512                 NTuple<Location> tuple2 = getFlowGraph(mdCaller).getLocationTuple(argDescTuple2);
2513
2514                 // CompositeLocation higherInferLoc =
2515                 // methodInfo.getInferLocation(argTuple1.get(0));
2516                 // CompositeLocation lowerInferLoc =
2517                 // methodInfo.getInferLocation(argTuple2.get(0));
2518
2519                 CompositeLocation inferLoc1 = generateInferredCompositeLocation(methodInfo, tuple1);
2520                 CompositeLocation inferLoc2 = generateInferredCompositeLocation(methodInfo, tuple2);
2521
2522                 // addRelation(methodLattice, methodInfo, inferLoc1, inferLoc2);
2523
2524                 addFlowGraphEdge(mdCaller, argDescTuple1, argDescTuple2);
2525
2526               }
2527
2528             }
2529
2530           }
2531         }
2532       }
2533     }
2534
2535   }
2536
2537   private CompositeLocation generateInferredCompositeLocation(MethodLocationInfo methodInfo,
2538       NTuple<Location> tuple) {
2539
2540     // first, retrieve inferred location by the local var descriptor
2541     CompositeLocation inferLoc = new CompositeLocation();
2542
2543     CompositeLocation localVarInferLoc =
2544         methodInfo.getInferLocation(tuple.get(0).getLocDescriptor());
2545
2546     localVarInferLoc.get(0).setLocDescriptor(tuple.get(0).getLocDescriptor());
2547
2548     for (int i = 0; i < localVarInferLoc.getSize(); i++) {
2549       inferLoc.addLocation(localVarInferLoc.get(i));
2550     }
2551
2552     for (int i = 1; i < tuple.size(); i++) {
2553       Location cur = tuple.get(i);
2554       Descriptor enclosingDesc = cur.getDescriptor();
2555       Descriptor curDesc = cur.getLocDescriptor();
2556
2557       Location inferLocElement;
2558       if (curDesc == null) {
2559         // in this case, we have a newly generated location.
2560         inferLocElement = new Location(enclosingDesc, cur.getLocIdentifier());
2561       } else {
2562         String fieldLocSymbol =
2563             getLocationInfo(enclosingDesc).getInferLocation(curDesc).get(0).getLocIdentifier();
2564         inferLocElement = new Location(enclosingDesc, fieldLocSymbol);
2565         inferLocElement.setLocDescriptor(curDesc);
2566       }
2567
2568       inferLoc.addLocation(inferLocElement);
2569
2570     }
2571
2572     assert (inferLoc.get(0).getLocDescriptor().getSymbol() == inferLoc.get(0).getLocIdentifier());
2573     return inferLoc;
2574   }
2575
2576   private void addRelation(SSJavaLattice<String> methodLattice, MethodLocationInfo methodInfo,
2577       CompositeLocation srcInferLoc, CompositeLocation dstInferLoc) throws CyclicFlowException {
2578
2579     System.out.println("addRelation --- srcInferLoc=" + srcInferLoc + "  dstInferLoc="
2580         + dstInferLoc);
2581     String srcLocalLocSymbol = srcInferLoc.get(0).getLocIdentifier();
2582     String dstLocalLocSymbol = dstInferLoc.get(0).getLocIdentifier();
2583
2584     if (srcInferLoc.getSize() == 1 && dstInferLoc.getSize() == 1) {
2585       // add a new relation to the local lattice
2586       addRelationHigherToLower(methodLattice, methodInfo, srcLocalLocSymbol, dstLocalLocSymbol);
2587     } else if (srcInferLoc.getSize() > 1 && dstInferLoc.getSize() > 1) {
2588       // both src and dst have assigned to a composite location
2589
2590       if (!srcLocalLocSymbol.equals(dstLocalLocSymbol)) {
2591         addRelationHigherToLower(methodLattice, methodInfo, srcLocalLocSymbol, dstLocalLocSymbol);
2592       } else {
2593         recursivelyAddRelation(1, srcInferLoc, dstInferLoc);
2594       }
2595     } else {
2596       // either src or dst has assigned to a composite location
2597       if (!srcLocalLocSymbol.equals(dstLocalLocSymbol)) {
2598         addRelationHigherToLower(methodLattice, methodInfo, srcLocalLocSymbol, dstLocalLocSymbol);
2599       }
2600     }
2601
2602     System.out.println();
2603
2604   }
2605
2606   public LocationInfo getLocationInfo(Descriptor d) {
2607     if (d instanceof MethodDescriptor) {
2608       return getMethodLocationInfo((MethodDescriptor) d);
2609     } else {
2610       return getFieldLocationInfo((ClassDescriptor) d);
2611     }
2612   }
2613
2614   private MethodLocationInfo getMethodLocationInfo(MethodDescriptor md) {
2615
2616     if (!mapMethodDescToMethodLocationInfo.containsKey(md)) {
2617       mapMethodDescToMethodLocationInfo.put(md, new MethodLocationInfo(md));
2618     }
2619
2620     return mapMethodDescToMethodLocationInfo.get(md);
2621
2622   }
2623
2624   private LocationInfo getFieldLocationInfo(ClassDescriptor cd) {
2625
2626     if (!mapClassToLocationInfo.containsKey(cd)) {
2627       mapClassToLocationInfo.put(cd, new LocationInfo(cd));
2628     }
2629
2630     return mapClassToLocationInfo.get(cd);
2631
2632   }
2633
2634   private void addRelationToLattice(MethodDescriptor md, SSJavaLattice<String> methodLattice,
2635       MethodLocationInfo methodInfo, FlowNode srcNode, FlowNode dstNode) throws CyclicFlowException {
2636
2637     System.out.println();
2638     System.out.println("### addRelationToLattice src=" + srcNode + " dst=" + dstNode);
2639
2640     // add a new binary relation of dstNode < srcNode
2641     FlowGraph flowGraph = getFlowGraph(md);
2642     try {
2643       System.out.println("***** src composite case::");
2644       calculateCompositeLocation(flowGraph, methodLattice, methodInfo, srcNode, null);
2645
2646       CompositeLocation srcInferLoc =
2647           generateInferredCompositeLocation(methodInfo, flowGraph.getLocationTuple(srcNode));
2648       CompositeLocation dstInferLoc =
2649           generateInferredCompositeLocation(methodInfo, flowGraph.getLocationTuple(dstNode));
2650       addRelation(methodLattice, methodInfo, srcInferLoc, dstInferLoc);
2651     } catch (CyclicFlowException e) {
2652       // there is a cyclic value flow... try to calculate a composite location
2653       // for the destination node
2654       System.out.println("***** dst composite case::");
2655       calculateCompositeLocation(flowGraph, methodLattice, methodInfo, dstNode, srcNode);
2656       CompositeLocation srcInferLoc =
2657           generateInferredCompositeLocation(methodInfo, flowGraph.getLocationTuple(srcNode));
2658       CompositeLocation dstInferLoc =
2659           generateInferredCompositeLocation(methodInfo, flowGraph.getLocationTuple(dstNode));
2660       try {
2661         addRelation(methodLattice, methodInfo, srcInferLoc, dstInferLoc);
2662       } catch (CyclicFlowException e1) {
2663         throw new Error("Failed to merge cyclic value flows into a shared location.");
2664       }
2665     }
2666
2667   }
2668
2669   private void recursivelyAddRelation(int idx, CompositeLocation srcInferLoc,
2670       CompositeLocation dstInferLoc) throws CyclicFlowException {
2671
2672     String srcLocSymbol = srcInferLoc.get(idx).getLocIdentifier();
2673     String dstLocSymbol = dstInferLoc.get(idx).getLocIdentifier();
2674
2675     Descriptor parentDesc = srcInferLoc.get(idx).getDescriptor();
2676
2677     if (srcLocSymbol.equals(dstLocSymbol)) {
2678       // check if it is the case of shared location
2679       if (srcInferLoc.getSize() == (idx + 1) && dstInferLoc.getSize() == (idx + 1)) {
2680         Location inferLocElement = srcInferLoc.get(idx);
2681         System.out.println("SET SHARED LOCATION=" + inferLocElement);
2682         getLattice(inferLocElement.getDescriptor())
2683             .addSharedLoc(inferLocElement.getLocIdentifier());
2684       } else if (srcInferLoc.getSize() > (idx + 1) && dstInferLoc.getSize() > (idx + 1)) {
2685         recursivelyAddRelation(idx + 1, srcInferLoc, dstInferLoc);
2686       }
2687     } else {
2688       addRelationHigherToLower(getLattice(parentDesc), getLocationInfo(parentDesc), srcLocSymbol,
2689           dstLocSymbol);
2690     }
2691   }
2692
2693   private void recursivelyAddCompositeRelation(MethodDescriptor md, FlowGraph flowGraph,
2694       MethodLocationInfo methodInfo, FlowNode srcNode, FlowNode dstNode, Descriptor srcDesc,
2695       Descriptor dstDesc) throws CyclicFlowException {
2696
2697     CompositeLocation inferSrcLoc;
2698     CompositeLocation inferDstLoc = methodInfo.getInferLocation(dstDesc);
2699
2700     if (srcNode.getDescTuple().size() > 1) {
2701       // field access
2702       inferSrcLoc = new CompositeLocation();
2703
2704       NTuple<Location> locTuple = flowGraph.getLocationTuple(srcNode);
2705       for (int i = 0; i < locTuple.size(); i++) {
2706         inferSrcLoc.addLocation(locTuple.get(i));
2707       }
2708
2709     } else {
2710       inferSrcLoc = methodInfo.getInferLocation(srcDesc);
2711     }
2712
2713     if (dstNode.getDescTuple().size() > 1) {
2714       // field access
2715       inferDstLoc = new CompositeLocation();
2716
2717       NTuple<Location> locTuple = flowGraph.getLocationTuple(dstNode);
2718       for (int i = 0; i < locTuple.size(); i++) {
2719         inferDstLoc.addLocation(locTuple.get(i));
2720       }
2721
2722     } else {
2723       inferDstLoc = methodInfo.getInferLocation(dstDesc);
2724     }
2725
2726     recursiveAddRelationToLattice(1, md, inferSrcLoc, inferDstLoc);
2727   }
2728
2729   private void addPrefixMapping(Map<NTuple<Location>, Set<NTuple<Location>>> map,
2730       NTuple<Location> prefix, NTuple<Location> element) {
2731
2732     if (!map.containsKey(prefix)) {
2733       map.put(prefix, new HashSet<NTuple<Location>>());
2734     }
2735     map.get(prefix).add(element);
2736   }
2737
2738   private boolean calculateCompositeLocation(FlowGraph flowGraph,
2739       SSJavaLattice<String> methodLattice, MethodLocationInfo methodInfo, FlowNode flowNode,
2740       FlowNode srcNode) throws CyclicFlowException {
2741
2742     Descriptor localVarDesc = flowNode.getDescTuple().get(0);
2743     NTuple<Location> flowNodelocTuple = flowGraph.getLocationTuple(flowNode);
2744
2745     if (localVarDesc.equals(methodInfo.getMethodDesc())) {
2746       return false;
2747     }
2748
2749     Set<FlowNode> inNodeSet = flowGraph.getIncomingFlowNodeSet(flowNode);
2750     Set<FlowNode> reachableNodeSet = flowGraph.getReachFlowNodeSetFrom(flowNode);
2751
2752     Map<NTuple<Location>, Set<NTuple<Location>>> mapPrefixToIncomingLocTupleSet =
2753         new HashMap<NTuple<Location>, Set<NTuple<Location>>>();
2754
2755     List<NTuple<Location>> prefixList = new ArrayList<NTuple<Location>>();
2756
2757     for (Iterator iterator = inNodeSet.iterator(); iterator.hasNext();) {
2758       FlowNode inNode = (FlowNode) iterator.next();
2759       NTuple<Location> inNodeTuple = flowGraph.getLocationTuple(inNode);
2760
2761       CompositeLocation inNodeInferredLoc =
2762           generateInferredCompositeLocation(methodInfo, inNodeTuple);
2763
2764       NTuple<Location> inNodeInferredLocTuple = inNodeInferredLoc.getTuple();
2765
2766       for (int i = 1; i < inNodeInferredLocTuple.size(); i++) {
2767         NTuple<Location> prefix = inNodeInferredLocTuple.subList(0, i);
2768         if (!prefixList.contains(prefix)) {
2769           prefixList.add(prefix);
2770         }
2771         addPrefixMapping(mapPrefixToIncomingLocTupleSet, prefix, inNodeInferredLocTuple);
2772       }
2773     }
2774
2775     Collections.sort(prefixList, new Comparator<NTuple<Location>>() {
2776       public int compare(NTuple<Location> arg0, NTuple<Location> arg1) {
2777         int s0 = arg0.size();
2778         int s1 = arg1.size();
2779         if (s0 > s1) {
2780           return -1;
2781         } else if (s0 == s1) {
2782           return 0;
2783         } else {
2784           return 1;
2785         }
2786       }
2787     });
2788
2789     // System.out.println("prefixList=" + prefixList);
2790     // System.out.println("reachableNodeSet=" + reachableNodeSet);
2791
2792     // find out reachable nodes that have the longest common prefix
2793     for (int i = 0; i < prefixList.size(); i++) {
2794       NTuple<Location> curPrefix = prefixList.get(i);
2795       Set<NTuple<Location>> reachableCommonPrefixSet = new HashSet<NTuple<Location>>();
2796
2797       for (Iterator iterator2 = reachableNodeSet.iterator(); iterator2.hasNext();) {
2798         FlowNode reachableNode = (FlowNode) iterator2.next();
2799         NTuple<Location> reachLocTuple = flowGraph.getLocationTuple(reachableNode);
2800         CompositeLocation reachLocInferLoc =
2801             generateInferredCompositeLocation(methodInfo, reachLocTuple);
2802         if (reachLocInferLoc.getTuple().startsWith(curPrefix)) {
2803           reachableCommonPrefixSet.add(reachLocTuple);
2804         }
2805       }
2806
2807       if (!reachableCommonPrefixSet.isEmpty()) {
2808         // found reachable nodes that start with the prefix curPrefix
2809         // need to assign a composite location
2810
2811         // first, check if there are more than one the set of locations that has
2812         // the same length of the longest reachable prefix, no way to assign
2813         // a composite location to the input local var
2814         prefixSanityCheck(prefixList, i, flowGraph, reachableNodeSet);
2815
2816         Set<NTuple<Location>> incomingCommonPrefixSet =
2817             mapPrefixToIncomingLocTupleSet.get(curPrefix);
2818
2819         int idx = curPrefix.size();
2820         NTuple<Location> element = incomingCommonPrefixSet.iterator().next();
2821         Descriptor desc = element.get(idx).getDescriptor();
2822
2823         SSJavaLattice<String> lattice = getLattice(desc);
2824         LocationInfo locInfo = getLocationInfo(desc);
2825
2826         CompositeLocation inferLocation =
2827             generateInferredCompositeLocation(methodInfo, flowNodelocTuple);
2828
2829         // methodInfo.getInferLocation(localVarDesc);
2830         CompositeLocation newInferLocation = new CompositeLocation();
2831
2832         if (inferLocation.getTuple().startsWith(curPrefix)) {
2833           // the same infer location is already existed. no need to do
2834           // anything
2835           System.out.println("NO ATTEMPT TO MAKE A COMPOSITE LOCATION curPrefix=" + curPrefix);
2836
2837           // TODO: refactoring!
2838           if (srcNode != null) {
2839             CompositeLocation newLoc = new CompositeLocation();
2840             String newLocSymbol = "Loc" + (SSJavaLattice.seed++);
2841             for (int locIdx = 0; locIdx < curPrefix.size(); locIdx++) {
2842               newLoc.addLocation(curPrefix.get(locIdx));
2843             }
2844             Location newLocationElement = new Location(desc, newLocSymbol);
2845             newLoc.addLocation(newLocationElement);
2846
2847             Descriptor srcLocalVar = srcNode.getDescTuple().get(0);
2848             methodInfo.mapDescriptorToLocation(srcLocalVar, newLoc.clone());
2849             addMapLocSymbolToInferredLocation(methodInfo.getMethodDesc(), srcLocalVar, newLoc);
2850             methodInfo.removeMaplocalVarToLocSet(srcLocalVar);
2851
2852             // add the field/var descriptor to the set of the location symbol
2853             int lastIdx = srcNode.getDescTuple().size() - 1;
2854             Descriptor lastFlowNodeDesc = srcNode.getDescTuple().get(lastIdx);
2855             NTuple<Location> srcNodelocTuple = flowGraph.getLocationTuple(srcNode);
2856             Descriptor enclosinglastLastFlowNodeDesc = srcNodelocTuple.get(lastIdx).getDescriptor();
2857
2858             CompositeLocation newlyInferredLocForFlowNode =
2859                 generateInferredCompositeLocation(methodInfo, srcNodelocTuple);
2860             Location lastInferLocElement =
2861                 newlyInferredLocForFlowNode.get(newlyInferredLocForFlowNode.getSize() - 1);
2862             Descriptor enclosingLastInferLocElement = lastInferLocElement.getDescriptor();
2863
2864             // getLocationInfo(enclosingLastInferLocElement).addMapLocSymbolToDescSet(
2865             // lastInferLocElement.getLocIdentifier(), lastFlowNodeDesc);
2866             getLocationInfo(enclosingLastInferLocElement).addMapLocSymbolToRelatedInferLoc(
2867                 lastInferLocElement.getLocIdentifier(), enclosinglastLastFlowNodeDesc,
2868                 lastFlowNodeDesc);
2869
2870             System.out.println("@@@@@@@ ASSIGN " + newLoc + " to SRC=" + srcNode);
2871           }
2872
2873           return true;
2874         } else {
2875           // assign a new composite location
2876
2877           // String oldMethodLocationSymbol =
2878           // inferLocation.get(0).getLocIdentifier();
2879           String newLocSymbol = "Loc" + (SSJavaLattice.seed++);
2880           for (int locIdx = 0; locIdx < curPrefix.size(); locIdx++) {
2881             newInferLocation.addLocation(curPrefix.get(locIdx));
2882           }
2883           Location newLocationElement = new Location(desc, newLocSymbol);
2884           newInferLocation.addLocation(newLocationElement);
2885
2886           // maps local variable to location types of the common prefix
2887           methodInfo.mapDescriptorToLocation(localVarDesc, newInferLocation.clone());
2888
2889           // methodInfo.mapDescriptorToLocation(localVarDesc, newInferLocation);
2890           addMapLocSymbolToInferredLocation(methodInfo.getMethodDesc(), localVarDesc,
2891               newInferLocation);
2892           methodInfo.removeMaplocalVarToLocSet(localVarDesc);
2893
2894           // add the field/var descriptor to the set of the location symbol
2895           int lastIdx = flowNode.getDescTuple().size() - 1;
2896           Descriptor lastFlowNodeDesc = flowNode.getDescTuple().get(lastIdx);
2897           Descriptor enclosinglastLastFlowNodeDesc = flowNodelocTuple.get(lastIdx).getDescriptor();
2898
2899           CompositeLocation newlyInferredLocForFlowNode =
2900               generateInferredCompositeLocation(methodInfo, flowNodelocTuple);
2901           Location lastInferLocElement =
2902               newlyInferredLocForFlowNode.get(newlyInferredLocForFlowNode.getSize() - 1);
2903           Descriptor enclosingLastInferLocElement = lastInferLocElement.getDescriptor();
2904
2905           // getLocationInfo(enclosingLastInferLocElement).addMapLocSymbolToDescSet(
2906           // lastInferLocElement.getLocIdentifier(), lastFlowNodeDesc);
2907           getLocationInfo(enclosingLastInferLocElement).addMapLocSymbolToRelatedInferLoc(
2908               lastInferLocElement.getLocIdentifier(), enclosinglastLastFlowNodeDesc,
2909               lastFlowNodeDesc);
2910
2911           // clean up the previous location
2912           // Location prevInferLocElement =
2913           // inferLocation.get(inferLocation.getSize() - 1);
2914           // Descriptor prevEnclosingDesc = prevInferLocElement.getDescriptor();
2915           //
2916           // SSJavaLattice<String> targetLattice;
2917           // LocationInfo targetInfo;
2918           // if (prevEnclosingDesc.equals(methodInfo.getMethodDesc())) {
2919           // targetLattice = methodLattice;
2920           // targetInfo = methodInfo;
2921           // } else {
2922           // targetLattice = getLattice(prevInferLocElement.getDescriptor());
2923           // targetInfo = getLocationInfo(prevInferLocElement.getDescriptor());
2924           // }
2925           //
2926           // Set<Pair<Descriptor, Descriptor>> associstedDescSet =
2927           // targetInfo.getRelatedInferLocSet(prevInferLocElement.getLocIdentifier());
2928           //
2929           // if (associstedDescSet.size() == 1) {
2930           // targetLattice.remove(prevInferLocElement.getLocIdentifier());
2931           // } else {
2932           // associstedDescSet.remove(lastFlowNodeDesc);
2933           // }
2934
2935         }
2936
2937         System.out.println("curPrefix=" + curPrefix);
2938         System.out.println("ASSIGN NEW COMPOSITE LOCATION =" + newInferLocation + "    to "
2939             + flowNode);
2940
2941         String newlyInsertedLocName =
2942             newInferLocation.get(newInferLocation.getSize() - 1).getLocIdentifier();
2943
2944         System.out.println("-- add in-flow");
2945         for (Iterator iterator = incomingCommonPrefixSet.iterator(); iterator.hasNext();) {
2946           NTuple<Location> tuple = (NTuple<Location>) iterator.next();
2947           Location loc = tuple.get(idx);
2948           String higher = loc.getLocIdentifier();
2949           addRelationHigherToLower(lattice, locInfo, higher, newlyInsertedLocName);
2950         }
2951
2952         System.out.println("-- add out flow");
2953         for (Iterator iterator = reachableCommonPrefixSet.iterator(); iterator.hasNext();) {
2954           NTuple<Location> tuple = (NTuple<Location>) iterator.next();
2955           if (tuple.size() > idx) {
2956             Location loc = tuple.get(idx);
2957             String lower = loc.getLocIdentifier();
2958             // String lower =
2959             // locInfo.getFieldInferLocation(loc.getLocDescriptor()).getLocIdentifier();
2960             addRelationHigherToLower(lattice, locInfo, newlyInsertedLocName, lower);
2961           }
2962         }
2963
2964         return true;
2965       }
2966
2967     }
2968
2969     return false;
2970
2971   }
2972
2973   private void addMapLocSymbolToInferredLocation(MethodDescriptor md, Descriptor localVar,
2974       CompositeLocation inferLoc) {
2975
2976     Location locElement = inferLoc.get((inferLoc.getSize() - 1));
2977     Descriptor enclosingDesc = locElement.getDescriptor();
2978     LocationInfo locInfo = getLocationInfo(enclosingDesc);
2979     locInfo.addMapLocSymbolToRelatedInferLoc(locElement.getLocIdentifier(), md, localVar);
2980   }
2981
2982   private boolean isCompositeLocation(CompositeLocation cl) {
2983     return cl.getSize() > 1;
2984   }
2985
2986   private boolean containsNonPrimitiveElement(Set<Descriptor> descSet) {
2987     for (Iterator iterator = descSet.iterator(); iterator.hasNext();) {
2988       Descriptor desc = (Descriptor) iterator.next();
2989
2990       if (desc.equals(LocationInference.GLOBALDESC)) {
2991         return true;
2992       } else if (desc instanceof VarDescriptor) {
2993         if (!((VarDescriptor) desc).getType().isPrimitive()) {
2994           return true;
2995         }
2996       } else if (desc instanceof FieldDescriptor) {
2997         if (!((FieldDescriptor) desc).getType().isPrimitive()) {
2998           return true;
2999         }
3000       }
3001
3002     }
3003     return false;
3004   }
3005
3006   private void addRelationHigherToLower(SSJavaLattice<String> lattice, LocationInfo locInfo,
3007       String higher, String lower) throws CyclicFlowException {
3008
3009     System.out.println("---addRelationHigherToLower " + higher + " -> " + lower
3010         + " to the lattice of " + locInfo.getDescIdentifier());
3011     // if (higher.equals(lower) && lattice.isSharedLoc(higher)) {
3012     // return;
3013     // }
3014     Set<String> cycleElementSet = lattice.getPossibleCycleElements(higher, lower);
3015
3016     boolean hasNonPrimitiveElement = false;
3017     for (Iterator iterator = cycleElementSet.iterator(); iterator.hasNext();) {
3018       String cycleElementLocSymbol = (String) iterator.next();
3019
3020       Set<Descriptor> descSet = locInfo.getDescSet(cycleElementLocSymbol);
3021       if (containsNonPrimitiveElement(descSet)) {
3022         hasNonPrimitiveElement = true;
3023         break;
3024       }
3025     }
3026
3027     if (hasNonPrimitiveElement) {
3028       System.out.println("#Check cycle= " + lower + " < " + higher + "     cycleElementSet="
3029           + cycleElementSet);
3030       // if there is non-primitive element in the cycle, no way to merge cyclic
3031       // elements into the shared location
3032       throw new CyclicFlowException();
3033     }
3034
3035     if (cycleElementSet.size() > 0) {
3036
3037       String newSharedLoc = "SharedLoc" + (SSJavaLattice.seed++);
3038
3039       System.out.println("---ASSIGN NEW SHARED LOC=" + newSharedLoc + "   to  " + cycleElementSet);
3040       lattice.mergeIntoNewLocation(cycleElementSet, newSharedLoc);
3041       lattice.addSharedLoc(newSharedLoc);
3042
3043       for (Iterator iterator = cycleElementSet.iterator(); iterator.hasNext();) {
3044         String oldLocSymbol = (String) iterator.next();
3045
3046         Set<Pair<Descriptor, Descriptor>> inferLocSet = locInfo.getRelatedInferLocSet(oldLocSymbol);
3047         System.out.println("---update related locations=" + inferLocSet);
3048         for (Iterator iterator2 = inferLocSet.iterator(); iterator2.hasNext();) {
3049           Pair<Descriptor, Descriptor> pair = (Pair<Descriptor, Descriptor>) iterator2.next();
3050           Descriptor enclosingDesc = pair.getFirst();
3051           Descriptor desc = pair.getSecond();
3052
3053           CompositeLocation inferLoc;
3054           if (curMethodInfo.md.equals(enclosingDesc)) {
3055             inferLoc = curMethodInfo.getInferLocation(desc);
3056           } else {
3057             inferLoc = getLocationInfo(enclosingDesc).getInferLocation(desc);
3058           }
3059
3060           Location locElement = inferLoc.get(inferLoc.getSize() - 1);
3061
3062           locElement.setLocIdentifier(newSharedLoc);
3063           locInfo.addMapLocSymbolToRelatedInferLoc(newSharedLoc, enclosingDesc, desc);
3064
3065           if (curMethodInfo.md.equals(enclosingDesc)) {
3066             inferLoc = curMethodInfo.getInferLocation(desc);
3067           } else {
3068             inferLoc = getLocationInfo(enclosingDesc).getInferLocation(desc);
3069           }
3070           System.out.println("---New Infer Loc=" + inferLoc);
3071
3072         }
3073         locInfo.removeRelatedInferLocSet(oldLocSymbol, newSharedLoc);
3074
3075       }
3076
3077       lattice.addSharedLoc(newSharedLoc);
3078
3079     } else if (!lattice.isGreaterThan(higher, lower)) {
3080       lattice.addRelationHigherToLower(higher, lower);
3081     }
3082   }
3083
3084   private void replaceOldLocWithNewLoc(SSJavaLattice<String> methodLattice, String oldLocSymbol,
3085       String newLocSymbol) {
3086
3087     if (methodLattice.containsKey(oldLocSymbol)) {
3088       methodLattice.substituteLocation(oldLocSymbol, newLocSymbol);
3089     }
3090
3091   }
3092
3093   private void prefixSanityCheck(List<NTuple<Location>> prefixList, int curIdx,
3094       FlowGraph flowGraph, Set<FlowNode> reachableNodeSet) {
3095
3096     NTuple<Location> curPrefix = prefixList.get(curIdx);
3097
3098     for (int i = curIdx + 1; i < prefixList.size(); i++) {
3099       NTuple<Location> prefixTuple = prefixList.get(i);
3100
3101       if (curPrefix.startsWith(prefixTuple)) {
3102         continue;
3103       }
3104
3105       for (Iterator iterator2 = reachableNodeSet.iterator(); iterator2.hasNext();) {
3106         FlowNode reachableNode = (FlowNode) iterator2.next();
3107         NTuple<Location> reachLocTuple = flowGraph.getLocationTuple(reachableNode);
3108         if (reachLocTuple.startsWith(prefixTuple)) {
3109           // TODO
3110           throw new Error("Failed to generate a composite location");
3111         }
3112       }
3113     }
3114   }
3115
3116   public boolean isPrimitiveLocalVariable(FlowNode node) {
3117     VarDescriptor varDesc = (VarDescriptor) node.getDescTuple().get(0);
3118     return varDesc.getType().isPrimitive();
3119   }
3120
3121   private SSJavaLattice<String> getLattice(Descriptor d) {
3122     if (d instanceof MethodDescriptor) {
3123       return getMethodLattice((MethodDescriptor) d);
3124     } else {
3125       return getFieldLattice((ClassDescriptor) d);
3126     }
3127   }
3128
3129   private SSJavaLattice<String> getMethodLattice(MethodDescriptor md) {
3130     if (!md2lattice.containsKey(md)) {
3131       md2lattice.put(md, new SSJavaLattice<String>(SSJavaAnalysis.TOP, SSJavaAnalysis.BOTTOM));
3132     }
3133     return md2lattice.get(md);
3134   }
3135
3136   private void setMethodLattice(MethodDescriptor md, SSJavaLattice<String> lattice) {
3137     md2lattice.put(md, lattice);
3138   }
3139
3140   private void extractFlowsBetweenFields(ClassDescriptor cd, FlowNode srcNode, FlowNode dstNode,
3141       int idx) {
3142
3143     NTuple<Descriptor> srcCurTuple = srcNode.getCurrentDescTuple();
3144     NTuple<Descriptor> dstCurTuple = dstNode.getCurrentDescTuple();
3145
3146     if (srcCurTuple.get(idx).equals(dstCurTuple.get(idx)) && srcCurTuple.size() > (idx + 1)
3147         && dstCurTuple.size() > (idx + 1)) {
3148       // value flow between fields: we don't need to add a binary relation
3149       // for this case
3150
3151       Descriptor desc = srcCurTuple.get(idx);
3152       ClassDescriptor classDesc;
3153
3154       if (idx == 0) {
3155         classDesc = ((VarDescriptor) desc).getType().getClassDesc();
3156       } else {
3157         classDesc = ((FieldDescriptor) desc).getType().getClassDesc();
3158       }
3159
3160       extractFlowsBetweenFields(classDesc, srcNode, dstNode, idx + 1);
3161
3162     } else {
3163
3164       Descriptor srcFieldDesc = srcCurTuple.get(idx);
3165       Descriptor dstFieldDesc = dstCurTuple.get(idx);
3166
3167       // add a new edge
3168       getHierarchyGraph(cd).addEdge(srcFieldDesc, dstFieldDesc);
3169
3170     }
3171
3172   }
3173
3174   private void extractRelationFromFieldFlows(ClassDescriptor cd, FlowNode srcNode,
3175       FlowNode dstNode, int idx) throws CyclicFlowException {
3176
3177     if (srcNode.getDescTuple().get(idx).equals(dstNode.getDescTuple().get(idx))
3178         && srcNode.getDescTuple().size() > (idx + 1) && dstNode.getDescTuple().size() > (idx + 1)) {
3179       // value flow between fields: we don't need to add a binary relation
3180       // for this case
3181
3182       Descriptor desc = srcNode.getDescTuple().get(idx);
3183       ClassDescriptor classDesc;
3184
3185       if (idx == 0) {
3186         classDesc = ((VarDescriptor) desc).getType().getClassDesc();
3187       } else {
3188         classDesc = ((FieldDescriptor) desc).getType().getClassDesc();
3189       }
3190
3191       extractRelationFromFieldFlows(classDesc, srcNode, dstNode, idx + 1);
3192
3193     } else {
3194
3195       Descriptor srcFieldDesc = srcNode.getDescTuple().get(idx);
3196       Descriptor dstFieldDesc = dstNode.getDescTuple().get(idx);
3197
3198       // add a new binary relation of dstNode < srcNode
3199       SSJavaLattice<String> fieldLattice = getFieldLattice(cd);
3200       LocationInfo fieldInfo = getFieldLocationInfo(cd);
3201
3202       String srcSymbol = fieldInfo.getFieldInferLocation(srcFieldDesc).getLocIdentifier();
3203       String dstSymbol = fieldInfo.getFieldInferLocation(dstFieldDesc).getLocIdentifier();
3204
3205       addRelationHigherToLower(fieldLattice, fieldInfo, srcSymbol, dstSymbol);
3206
3207     }
3208
3209   }
3210
3211   public SSJavaLattice<String> getFieldLattice(ClassDescriptor cd) {
3212     if (!cd2lattice.containsKey(cd)) {
3213       cd2lattice.put(cd, new SSJavaLattice<String>(SSJavaAnalysis.TOP, SSJavaAnalysis.BOTTOM));
3214     }
3215     return cd2lattice.get(cd);
3216   }
3217
3218   public LinkedList<MethodDescriptor> computeMethodList() {
3219
3220     Set<MethodDescriptor> toSort = new HashSet<MethodDescriptor>();
3221
3222     setupToAnalyze();
3223
3224     Set<MethodDescriptor> visited = new HashSet<MethodDescriptor>();
3225     Set<MethodDescriptor> reachableCallee = new HashSet<MethodDescriptor>();
3226
3227     while (!toAnalyzeIsEmpty()) {
3228       ClassDescriptor cd = toAnalyzeNext();
3229
3230       setupToAnalazeMethod(cd);
3231       temp_toanalyzeMethodList.removeAll(visited);
3232
3233       while (!toAnalyzeMethodIsEmpty()) {
3234         MethodDescriptor md = toAnalyzeMethodNext();
3235         if ((!visited.contains(md))
3236             && (ssjava.needTobeAnnotated(md) || reachableCallee.contains(md))) {
3237
3238           // creates a mapping from a method descriptor to virtual methods
3239           Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
3240           if (md.isStatic()) {
3241             setPossibleCallees.add(md);
3242           } else {
3243             setPossibleCallees.addAll(ssjava.getCallGraph().getMethods(md));
3244           }
3245
3246           Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getCalleeSet(md);
3247           Set<MethodDescriptor> needToAnalyzeCalleeSet = new HashSet<MethodDescriptor>();
3248
3249           for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
3250             MethodDescriptor calleemd = (MethodDescriptor) iterator.next();
3251             if ((!ssjava.isTrustMethod(calleemd))
3252                 && (!ssjava.isSSJavaUtil(calleemd.getClassDesc()))) {
3253               if (!visited.contains(calleemd)) {
3254                 temp_toanalyzeMethodList.add(calleemd);
3255               }
3256               reachableCallee.add(calleemd);
3257               needToAnalyzeCalleeSet.add(calleemd);
3258             }
3259           }
3260
3261           mapMethodToCalleeSet.put(md, needToAnalyzeCalleeSet);
3262
3263           visited.add(md);
3264
3265           toSort.add(md);
3266         }
3267       }
3268     }
3269
3270     return ssjava.topologicalSort(toSort);
3271
3272   }
3273
3274   public void constructFlowGraph() {
3275
3276     System.out.println("");
3277     toanalyze_methodDescList = computeMethodList();
3278
3279     LinkedList<MethodDescriptor> methodDescList =
3280         (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
3281
3282     System.out.println("@@@methodDescList=" + methodDescList);
3283     // System.exit(0);
3284
3285     while (!methodDescList.isEmpty()) {
3286       MethodDescriptor md = methodDescList.removeLast();
3287       if (state.SSJAVADEBUG) {
3288         System.out.println();
3289         System.out.println("SSJAVA: Constructing a flow graph: " + md);
3290
3291         // creates a mapping from a parameter descriptor to its index
3292         Map<Descriptor, Integer> mapParamDescToIdx = new HashMap<Descriptor, Integer>();
3293         int offset = 0;
3294         if (!md.isStatic()) {
3295           offset = 1;
3296           mapParamDescToIdx.put(md.getThis(), 0);
3297         }
3298
3299         for (int i = 0; i < md.numParameters(); i++) {
3300           Descriptor paramDesc = (Descriptor) md.getParameter(i);
3301           mapParamDescToIdx.put(paramDesc, new Integer(i + offset));
3302         }
3303
3304         FlowGraph fg = new FlowGraph(md, mapParamDescToIdx);
3305         mapMethodDescriptorToFlowGraph.put(md, fg);
3306
3307         analyzeMethodBody(md.getClassDesc(), md);
3308         propagateFlowsFromCalleesWithNoCompositeLocation(md);
3309         // assignCompositeLocation(md);
3310
3311       }
3312     }
3313     _debug_printGraph();
3314
3315   }
3316
3317   private Set<MethodInvokeNode> getMethodInvokeNodeSet(MethodDescriptor md) {
3318     if (!mapMethodDescriptorToMethodInvokeNodeSet.containsKey(md)) {
3319       mapMethodDescriptorToMethodInvokeNodeSet.put(md, new HashSet<MethodInvokeNode>());
3320     }
3321     return mapMethodDescriptorToMethodInvokeNodeSet.get(md);
3322   }
3323
3324   private void constructSubGlobalFlowGraph(MethodDescriptor md) {
3325
3326     FlowGraph flowGraph = getFlowGraph(md);
3327
3328     Set<MethodInvokeNode> setMethodInvokeNode = getMethodInvokeNodeSet(md);
3329
3330     for (Iterator<MethodInvokeNode> iter = setMethodInvokeNode.iterator(); iter.hasNext();) {
3331       MethodInvokeNode min = iter.next();
3332       propagateFlowsFromMethodInvokeNode(md, min);
3333     }
3334
3335   }
3336
3337   private void propagateFlowsFromMethodInvokeNode(MethodDescriptor mdCaller, MethodInvokeNode min) {
3338     // the transformation for a call site propagates flows through parameters
3339     // if the method is virtual, it also grab all relations from any possible
3340     // callees
3341
3342     MethodDescriptor mdCallee = min.getMethod();
3343     Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
3344     if (mdCallee.isStatic()) {
3345       setPossibleCallees.add(mdCallee);
3346     } else {
3347       Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
3348       // removes method descriptors that are not invoked by the caller
3349       calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
3350       setPossibleCallees.addAll(calleeSet);
3351     }
3352
3353     for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
3354       MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
3355       contributeCalleeFlows(min, mdCaller, possibleMdCallee);
3356     }
3357
3358   }
3359
3360   private void assignCompositeLocation(MethodDescriptor md) {
3361
3362     FlowGraph flowGraph = getFlowGraph(md);
3363
3364     Set<FlowNode> nodeSet = flowGraph.getNodeSet();
3365
3366     next: for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
3367       FlowNode flowNode = (FlowNode) iterator.next();
3368
3369       // assign a composite location only to the local variable
3370       if (flowNode.getCurrentDescTuple().size() == 1) {
3371
3372         List<NTuple<Descriptor>> prefixList = calculatePrefixList(flowGraph, flowNode);
3373         Set<FlowNode> reachSet = flowGraph.getReachFlowNodeSetFrom(flowNode);
3374
3375         for (int i = 0; i < prefixList.size(); i++) {
3376           NTuple<Descriptor> curPrefix = prefixList.get(i);
3377           Set<NTuple<Descriptor>> reachableCommonPrefixSet = new HashSet<NTuple<Descriptor>>();
3378
3379           for (Iterator iterator2 = reachSet.iterator(); iterator2.hasNext();) {
3380             FlowNode reachNode = (FlowNode) iterator2.next();
3381             if (reachNode.getCurrentDescTuple().startsWith(curPrefix)) {
3382               reachableCommonPrefixSet.add(reachNode.getCurrentDescTuple());
3383             }
3384           }
3385
3386           if (!reachableCommonPrefixSet.isEmpty()) {
3387             System.out.println("NEED TO ASSIGN COMP LOC TO " + flowNode + " with prefix="
3388                 + curPrefix);
3389             CompositeLocation newCompLoc = generateCompositeLocation(md, curPrefix);
3390             flowNode.setCompositeLocation(newCompLoc);
3391             continue next;
3392           }
3393
3394         }
3395       }
3396
3397     }
3398
3399   }
3400
3401   private void propagateFlowsFromCalleesWithNoCompositeLocation(MethodDescriptor mdCaller) {
3402
3403     // the transformation for a call site propagates flows through parameters
3404     // if the method is virtual, it also grab all relations from any possible
3405     // callees
3406
3407     Set<MethodInvokeNode> setMethodInvokeNode =
3408         mapMethodDescriptorToMethodInvokeNodeSet.get(mdCaller);
3409
3410     if (setMethodInvokeNode != null) {
3411
3412       for (Iterator iterator = setMethodInvokeNode.iterator(); iterator.hasNext();) {
3413         MethodInvokeNode min = (MethodInvokeNode) iterator.next();
3414         MethodDescriptor mdCallee = min.getMethod();
3415         Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
3416         if (mdCallee.isStatic()) {
3417           setPossibleCallees.add(mdCallee);
3418         } else {
3419           Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
3420           // removes method descriptors that are not invoked by the caller
3421           calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
3422           setPossibleCallees.addAll(calleeSet);
3423         }
3424
3425         for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
3426           MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
3427           propagateFlowsToCallerWithNoCompositeLocation(min, mdCaller, possibleMdCallee);
3428         }
3429
3430       }
3431     }
3432
3433   }
3434
3435   private void propagateFlowsFromCallees(MethodDescriptor mdCaller) {
3436
3437     // the transformation for a call site propagates flows through parameters
3438     // if the method is virtual, it also grab all relations from any possible
3439     // callees
3440
3441     Set<MethodInvokeNode> setMethodInvokeNode =
3442         mapMethodDescriptorToMethodInvokeNodeSet.get(mdCaller);
3443
3444     if (setMethodInvokeNode != null) {
3445
3446       for (Iterator iterator = setMethodInvokeNode.iterator(); iterator.hasNext();) {
3447         MethodInvokeNode min = (MethodInvokeNode) iterator.next();
3448         MethodDescriptor mdCallee = min.getMethod();
3449         Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
3450         if (mdCallee.isStatic()) {
3451           setPossibleCallees.add(mdCallee);
3452         } else {
3453           Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
3454           // removes method descriptors that are not invoked by the caller
3455           calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
3456           setPossibleCallees.addAll(calleeSet);
3457         }
3458
3459         for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
3460           MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
3461           propagateFlowsToCaller(min, mdCaller, possibleMdCallee);
3462         }
3463
3464       }
3465     }
3466
3467   }
3468
3469   private void analyzeMethodBody(ClassDescriptor cd, MethodDescriptor md) {
3470     BlockNode bn = state.getMethodBody(md);
3471     NodeTupleSet implicitFlowTupleSet = new NodeTupleSet();
3472     analyzeFlowBlockNode(md, md.getParameterTable(), bn, implicitFlowTupleSet);
3473   }
3474
3475   private void analyzeFlowBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn,
3476       NodeTupleSet implicitFlowTupleSet) {
3477
3478     bn.getVarTable().setParent(nametable);
3479     for (int i = 0; i < bn.size(); i++) {
3480       BlockStatementNode bsn = bn.get(i);
3481       analyzeBlockStatementNode(md, bn.getVarTable(), bsn, implicitFlowTupleSet);
3482     }
3483
3484   }
3485
3486   private void analyzeBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
3487       BlockStatementNode bsn, NodeTupleSet implicitFlowTupleSet) {
3488
3489     switch (bsn.kind()) {
3490     case Kind.BlockExpressionNode:
3491       analyzeBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn, implicitFlowTupleSet);
3492       break;
3493
3494     case Kind.DeclarationNode:
3495       analyzeFlowDeclarationNode(md, nametable, (DeclarationNode) bsn, implicitFlowTupleSet);
3496       break;
3497
3498     case Kind.IfStatementNode:
3499       analyzeFlowIfStatementNode(md, nametable, (IfStatementNode) bsn, implicitFlowTupleSet);
3500       break;
3501
3502     case Kind.LoopNode:
3503       analyzeFlowLoopNode(md, nametable, (LoopNode) bsn, implicitFlowTupleSet);
3504       break;
3505
3506     case Kind.ReturnNode:
3507       analyzeFlowReturnNode(md, nametable, (ReturnNode) bsn, implicitFlowTupleSet);
3508       break;
3509
3510     case Kind.SubBlockNode:
3511       analyzeFlowSubBlockNode(md, nametable, (SubBlockNode) bsn, implicitFlowTupleSet);
3512       break;
3513
3514     case Kind.ContinueBreakNode:
3515       break;
3516
3517     case Kind.SwitchStatementNode:
3518       analyzeSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn, implicitFlowTupleSet);
3519       break;
3520
3521     }
3522
3523   }
3524
3525   private void analyzeSwitchBlockNode(MethodDescriptor md, SymbolTable nametable,
3526       SwitchBlockNode sbn, NodeTupleSet implicitFlowTupleSet) {
3527
3528     analyzeFlowBlockNode(md, nametable, sbn.getSwitchBlockStatement(), implicitFlowTupleSet);
3529
3530   }
3531
3532   private void analyzeSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
3533       SwitchStatementNode ssn, NodeTupleSet implicitFlowTupleSet) {
3534
3535     NodeTupleSet condTupleNode = new NodeTupleSet();
3536     analyzeFlowExpressionNode(md, nametable, ssn.getCondition(), condTupleNode, null,
3537         implicitFlowTupleSet, false);
3538
3539     NodeTupleSet newImplicitTupleSet = new NodeTupleSet();
3540
3541     newImplicitTupleSet.addTupleSet(implicitFlowTupleSet);
3542     newImplicitTupleSet.addTupleSet(condTupleNode);
3543
3544     if (newImplicitTupleSet.size() > 1) {
3545       // need to create an intermediate node for the GLB of conditional locations & implicit flows
3546       NTuple<Descriptor> interTuple = getFlowGraph(md).createIntermediateNode().getDescTuple();
3547       for (Iterator<NTuple<Descriptor>> idxIter = newImplicitTupleSet.iterator(); idxIter.hasNext();) {
3548         NTuple<Descriptor> tuple = idxIter.next();
3549         addFlowGraphEdge(md, tuple, interTuple);
3550       }
3551       newImplicitTupleSet.clear();
3552       newImplicitTupleSet.addTuple(interTuple);
3553     }
3554
3555     BlockNode sbn = ssn.getSwitchBody();
3556     for (int i = 0; i < sbn.size(); i++) {
3557       analyzeSwitchBlockNode(md, nametable, (SwitchBlockNode) sbn.get(i), newImplicitTupleSet);
3558     }
3559
3560   }
3561
3562   private void analyzeFlowSubBlockNode(MethodDescriptor md, SymbolTable nametable,
3563       SubBlockNode sbn, NodeTupleSet implicitFlowTupleSet) {
3564     analyzeFlowBlockNode(md, nametable, sbn.getBlockNode(), implicitFlowTupleSet);
3565   }
3566
3567   private void analyzeFlowReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn,
3568       NodeTupleSet implicitFlowTupleSet) {
3569
3570     ExpressionNode returnExp = rn.getReturnExpression();
3571
3572     if (returnExp != null) {
3573       NodeTupleSet nodeSet = new NodeTupleSet();
3574       // if a return expression returns a literal value, nodeSet is empty
3575       analyzeFlowExpressionNode(md, nametable, returnExp, nodeSet, false);
3576       FlowGraph fg = getFlowGraph(md);
3577
3578       // if (implicitFlowTupleSet.size() == 1
3579       // && fg.getFlowNode(implicitFlowTupleSet.iterator().next()).isIntermediate()) {
3580       //
3581       // // since there is already an intermediate node for the GLB of implicit flows
3582       // // we don't need to create another intermediate node.
3583       // // just re-use the intermediate node for implicit flows.
3584       //
3585       // FlowNode meetNode = fg.getFlowNode(implicitFlowTupleSet.iterator().next());
3586       //
3587       // for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
3588       // NTuple<Descriptor> returnNodeTuple = (NTuple<Descriptor>) iterator.next();
3589       // fg.addValueFlowEdge(returnNodeTuple, meetNode.getDescTuple());
3590       // }
3591       //
3592       // }
3593
3594       NodeTupleSet currentFlowTupleSet = new NodeTupleSet();
3595
3596       // add tuples from return node
3597       currentFlowTupleSet.addTupleSet(nodeSet);
3598
3599       // add tuples corresponding to the current implicit flows
3600       currentFlowTupleSet.addTupleSet(implicitFlowTupleSet);
3601
3602       if (currentFlowTupleSet.size() > 1) {
3603         FlowNode meetNode = fg.createIntermediateNode();
3604         for (Iterator iterator = currentFlowTupleSet.iterator(); iterator.hasNext();) {
3605           NTuple<Descriptor> currentFlowTuple = (NTuple<Descriptor>) iterator.next();
3606           fg.addValueFlowEdge(currentFlowTuple, meetNode.getDescTuple());
3607         }
3608         fg.addReturnFlowNode(meetNode.getDescTuple());
3609       } else if (currentFlowTupleSet.size() == 1) {
3610         NTuple<Descriptor> tuple = currentFlowTupleSet.iterator().next();
3611         fg.addReturnFlowNode(tuple);
3612       }
3613
3614     }
3615
3616   }
3617
3618   private void analyzeFlowLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln,
3619       NodeTupleSet implicitFlowTupleSet) {
3620
3621     if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
3622
3623       NodeTupleSet condTupleNode = new NodeTupleSet();
3624       analyzeFlowExpressionNode(md, nametable, ln.getCondition(), condTupleNode, null,
3625           implicitFlowTupleSet, false);
3626
3627       NodeTupleSet newImplicitTupleSet = new NodeTupleSet();
3628
3629       newImplicitTupleSet.addTupleSet(implicitFlowTupleSet);
3630       newImplicitTupleSet.addTupleSet(condTupleNode);
3631
3632       if (newImplicitTupleSet.size() > 1) {
3633         // need to create an intermediate node for the GLB of conditional locations & implicit flows
3634         NTuple<Descriptor> interTuple = getFlowGraph(md).createIntermediateNode().getDescTuple();
3635         for (Iterator<NTuple<Descriptor>> idxIter = newImplicitTupleSet.iterator(); idxIter
3636             .hasNext();) {
3637           NTuple<Descriptor> tuple = idxIter.next();
3638           addFlowGraphEdge(md, tuple, interTuple);
3639         }
3640         newImplicitTupleSet.clear();
3641         newImplicitTupleSet.addTuple(interTuple);
3642
3643       }
3644
3645       // ///////////
3646       // System.out.println("condTupleNode="+condTupleNode);
3647       // NTuple<Descriptor> interTuple = getFlowGraph(md).createIntermediateNode().getDescTuple();
3648       //
3649       // for (Iterator<NTuple<Descriptor>> idxIter = condTupleNode.iterator(); idxIter.hasNext();) {
3650       // NTuple<Descriptor> tuple = idxIter.next();
3651       // addFlowGraphEdge(md, tuple, interTuple);
3652       // }
3653
3654       // for (Iterator<NTuple<Descriptor>> idxIter = implicitFlowTupleSet.iterator(); idxIter
3655       // .hasNext();) {
3656       // NTuple<Descriptor> tuple = idxIter.next();
3657       // addFlowGraphEdge(md, tuple, interTuple);
3658       // }
3659
3660       // NodeTupleSet newImplicitSet = new NodeTupleSet();
3661       // newImplicitSet.addTuple(interTuple);
3662       analyzeFlowBlockNode(md, nametable, ln.getBody(), newImplicitTupleSet);
3663       // ///////////
3664
3665       // condTupleNode.addTupleSet(implicitFlowTupleSet);
3666
3667       // add edges from condNodeTupleSet to all nodes of conditional nodes
3668       // analyzeFlowBlockNode(md, nametable, ln.getBody(), condTupleNode);
3669
3670     } else {
3671       // check 'for loop' case
3672       BlockNode bn = ln.getInitializer();
3673       bn.getVarTable().setParent(nametable);
3674       for (int i = 0; i < bn.size(); i++) {
3675         BlockStatementNode bsn = bn.get(i);
3676         analyzeBlockStatementNode(md, bn.getVarTable(), bsn, implicitFlowTupleSet);
3677       }
3678
3679       NodeTupleSet condTupleNode = new NodeTupleSet();
3680       analyzeFlowExpressionNode(md, bn.getVarTable(), ln.getCondition(), condTupleNode, null,
3681           implicitFlowTupleSet, false);
3682
3683       // ///////////
3684       NTuple<Descriptor> interTuple = getFlowGraph(md).createIntermediateNode().getDescTuple();
3685
3686       for (Iterator<NTuple<Descriptor>> idxIter = condTupleNode.iterator(); idxIter.hasNext();) {
3687         NTuple<Descriptor> tuple = idxIter.next();
3688         addFlowGraphEdge(md, tuple, interTuple);
3689       }
3690
3691       for (Iterator<NTuple<Descriptor>> idxIter = implicitFlowTupleSet.iterator(); idxIter
3692           .hasNext();) {
3693         NTuple<Descriptor> tuple = idxIter.next();
3694         addFlowGraphEdge(md, tuple, interTuple);
3695       }
3696
3697       NodeTupleSet newImplicitSet = new NodeTupleSet();
3698       newImplicitSet.addTuple(interTuple);
3699       analyzeFlowBlockNode(md, bn.getVarTable(), ln.getUpdate(), newImplicitSet);
3700       analyzeFlowBlockNode(md, bn.getVarTable(), ln.getBody(), newImplicitSet);
3701       // ///////////
3702
3703       // condTupleNode.addTupleSet(implicitFlowTupleSet);
3704       //
3705       // analyzeFlowBlockNode(md, bn.getVarTable(), ln.getUpdate(),
3706       // condTupleNode);
3707       // analyzeFlowBlockNode(md, bn.getVarTable(), ln.getBody(),
3708       // condTupleNode);
3709
3710     }
3711
3712   }
3713
3714   private void analyzeFlowIfStatementNode(MethodDescriptor md, SymbolTable nametable,
3715       IfStatementNode isn, NodeTupleSet implicitFlowTupleSet) {
3716
3717     System.out.println("analyzeFlowIfStatementNode=" + isn.printNode(0));
3718
3719     NodeTupleSet condTupleNode = new NodeTupleSet();
3720     analyzeFlowExpressionNode(md, nametable, isn.getCondition(), condTupleNode, null,
3721         implicitFlowTupleSet, false);
3722
3723     NodeTupleSet newImplicitTupleSet = new NodeTupleSet();
3724
3725     newImplicitTupleSet.addTupleSet(implicitFlowTupleSet);
3726     newImplicitTupleSet.addTupleSet(condTupleNode);
3727
3728     System.out.println("condTupleNode=" + condTupleNode);
3729     System.out.println("implicitFlowTupleSet=" + implicitFlowTupleSet);
3730     System.out.println("newImplicitTupleSet=" + newImplicitTupleSet);
3731
3732     if (newImplicitTupleSet.size() > 1) {
3733
3734       // need to create an intermediate node for the GLB of conditional locations & implicit flows
3735       NTuple<Descriptor> interTuple = getFlowGraph(md).createIntermediateNode().getDescTuple();
3736       for (Iterator<NTuple<Descriptor>> idxIter = newImplicitTupleSet.iterator(); idxIter.hasNext();) {
3737         NTuple<Descriptor> tuple = idxIter.next();
3738         addFlowGraphEdge(md, tuple, interTuple);
3739       }
3740       newImplicitTupleSet.clear();
3741       newImplicitTupleSet.addTuple(interTuple);
3742     }
3743
3744     analyzeFlowBlockNode(md, nametable, isn.getTrueBlock(), newImplicitTupleSet);
3745
3746     if (isn.getFalseBlock() != null) {
3747       analyzeFlowBlockNode(md, nametable, isn.getFalseBlock(), newImplicitTupleSet);
3748     }
3749
3750   }
3751
3752   private void analyzeFlowDeclarationNode(MethodDescriptor md, SymbolTable nametable,
3753       DeclarationNode dn, NodeTupleSet implicitFlowTupleSet) {
3754
3755     VarDescriptor vd = dn.getVarDescriptor();
3756     mapDescToDefinitionLine.put(vd, dn.getNumLine());
3757     NTuple<Descriptor> tupleLHS = new NTuple<Descriptor>();
3758     tupleLHS.add(vd);
3759     FlowNode fn = getFlowGraph(md).createNewFlowNode(tupleLHS);
3760     fn.setDeclarationNode();
3761
3762     if (dn.getExpression() != null) {
3763
3764       NodeTupleSet nodeSetRHS = new NodeTupleSet();
3765       analyzeFlowExpressionNode(md, nametable, dn.getExpression(), nodeSetRHS, null,
3766           implicitFlowTupleSet, false);
3767
3768       // creates edges from RHS to LHS
3769       NTuple<Descriptor> interTuple = null;
3770       if (nodeSetRHS.size() > 1) {
3771         interTuple = getFlowGraph(md).createIntermediateNode().getDescTuple();
3772       }
3773
3774       for (Iterator<NTuple<Descriptor>> iter = nodeSetRHS.iterator(); iter.hasNext();) {
3775         NTuple<Descriptor> fromTuple = iter.next();
3776         addFlowGraphEdge(md, fromTuple, interTuple, tupleLHS);
3777       }
3778
3779       // creates edges from implicitFlowTupleSet to LHS
3780       for (Iterator<NTuple<Descriptor>> iter = implicitFlowTupleSet.iterator(); iter.hasNext();) {
3781         NTuple<Descriptor> implicitTuple = iter.next();
3782         addFlowGraphEdge(md, implicitTuple, tupleLHS);
3783       }
3784
3785     }
3786
3787   }
3788
3789   private void analyzeBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
3790       BlockExpressionNode ben, NodeTupleSet implicitFlowTupleSet) {
3791     analyzeFlowExpressionNode(md, nametable, ben.getExpression(), null, null, implicitFlowTupleSet,
3792         false);
3793   }
3794
3795   private NTuple<Descriptor> analyzeFlowExpressionNode(MethodDescriptor md, SymbolTable nametable,
3796       ExpressionNode en, NodeTupleSet nodeSet, boolean isLHS) {
3797     return analyzeFlowExpressionNode(md, nametable, en, nodeSet, null, new NodeTupleSet(), isLHS);
3798   }
3799
3800   private NTuple<Descriptor> analyzeFlowExpressionNode(MethodDescriptor md, SymbolTable nametable,
3801       ExpressionNode en, NodeTupleSet nodeSet, NTuple<Descriptor> base,
3802       NodeTupleSet implicitFlowTupleSet, boolean isLHS) {
3803
3804     // note that expression node can create more than one flow node
3805     // nodeSet contains of flow nodes
3806     // base is always assigned to null except the case of a name node!
3807
3808     NTuple<Descriptor> flowTuple;
3809
3810     switch (en.kind()) {
3811
3812     case Kind.AssignmentNode:
3813       analyzeFlowAssignmentNode(md, nametable, (AssignmentNode) en, nodeSet, base,
3814           implicitFlowTupleSet);
3815       break;
3816
3817     case Kind.FieldAccessNode:
3818       flowTuple =
3819           analyzeFlowFieldAccessNode(md, nametable, (FieldAccessNode) en, nodeSet, base,
3820               implicitFlowTupleSet, isLHS);
3821       if (flowTuple != null) {
3822         nodeSet.addTuple(flowTuple);
3823       }
3824       return flowTuple;
3825
3826     case Kind.NameNode:
3827       NodeTupleSet nameNodeSet = new NodeTupleSet();
3828       flowTuple =
3829           analyzeFlowNameNode(md, nametable, (NameNode) en, nameNodeSet, base, implicitFlowTupleSet);
3830       if (flowTuple != null) {
3831         nodeSet.addTuple(flowTuple);
3832       }
3833       return flowTuple;
3834
3835     case Kind.OpNode:
3836       analyzeFlowOpNode(md, nametable, (OpNode) en, nodeSet, implicitFlowTupleSet);
3837       break;
3838
3839     case Kind.CreateObjectNode:
3840       analyzeCreateObjectNode(md, nametable, (CreateObjectNode) en);
3841       break;
3842
3843     case Kind.ArrayAccessNode:
3844       analyzeFlowArrayAccessNode(md, nametable, (ArrayAccessNode) en, nodeSet, isLHS);
3845       break;
3846
3847     case Kind.LiteralNode:
3848       analyzeLiteralNode(md, nametable, (LiteralNode) en);
3849       break;
3850
3851     case Kind.MethodInvokeNode:
3852       analyzeFlowMethodInvokeNode(md, nametable, (MethodInvokeNode) en, nodeSet,
3853           implicitFlowTupleSet);
3854       break;
3855
3856     case Kind.TertiaryNode:
3857       analyzeFlowTertiaryNode(md, nametable, (TertiaryNode) en, nodeSet, implicitFlowTupleSet);
3858       break;
3859
3860     case Kind.CastNode:
3861       analyzeFlowCastNode(md, nametable, (CastNode) en, nodeSet, base, implicitFlowTupleSet);
3862       break;
3863     // case Kind.InstanceOfNode:
3864     // checkInstanceOfNode(md, nametable, (InstanceOfNode) en, td);
3865     // return null;
3866
3867     // case Kind.ArrayInitializerNode:
3868     // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en,
3869     // td);
3870     // return null;
3871
3872     // case Kind.ClassTypeNode:
3873     // checkClassTypeNode(md, nametable, (ClassTypeNode) en, td);
3874     // return null;
3875
3876     // case Kind.OffsetNode:
3877     // checkOffsetNode(md, nametable, (OffsetNode)en, td);
3878     // return null;
3879
3880     }
3881     return null;
3882
3883   }
3884
3885   private void analyzeFlowCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn,
3886       NodeTupleSet nodeSet, NTuple<Descriptor> base, NodeTupleSet implicitFlowTupleSet) {
3887
3888     analyzeFlowExpressionNode(md, nametable, cn.getExpression(), nodeSet, base,
3889         implicitFlowTupleSet, false);
3890
3891   }
3892
3893   private void analyzeFlowTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode tn,
3894       NodeTupleSet nodeSet, NodeTupleSet implicitFlowTupleSet) {
3895
3896     NodeTupleSet tertiaryTupleNode = new NodeTupleSet();
3897     analyzeFlowExpressionNode(md, nametable, tn.getCond(), tertiaryTupleNode, null,
3898         implicitFlowTupleSet, false);
3899
3900     // add edges from tertiaryTupleNode to all nodes of conditional nodes
3901     tertiaryTupleNode.addTupleSet(implicitFlowTupleSet);
3902     analyzeFlowExpressionNode(md, nametable, tn.getTrueExpr(), tertiaryTupleNode, null,
3903         implicitFlowTupleSet, false);
3904
3905     analyzeFlowExpressionNode(md, nametable, tn.getFalseExpr(), tertiaryTupleNode, null,
3906         implicitFlowTupleSet, false);
3907
3908     nodeSet.addTupleSet(tertiaryTupleNode);
3909
3910   }
3911
3912   private void addMapCallerMethodDescToMethodInvokeNodeSet(MethodDescriptor caller,
3913       MethodInvokeNode min) {
3914     Set<MethodInvokeNode> set = mapMethodDescriptorToMethodInvokeNodeSet.get(caller);
3915     if (set == null) {
3916       set = new HashSet<MethodInvokeNode>();
3917       mapMethodDescriptorToMethodInvokeNodeSet.put(caller, set);
3918     }
3919     set.add(min);
3920   }
3921
3922   private void addParamNodeFlowingToReturnValue(MethodDescriptor md, FlowNode fn) {
3923
3924     if (!mapMethodDescToParamNodeFlowsToReturnValue.containsKey(md)) {
3925       mapMethodDescToParamNodeFlowsToReturnValue.put(md, new HashSet<FlowNode>());
3926     }
3927     mapMethodDescToParamNodeFlowsToReturnValue.get(md).add(fn);
3928   }
3929
3930   private Set<FlowNode> getParamNodeFlowingToReturnValue(MethodDescriptor md) {
3931     return mapMethodDescToParamNodeFlowsToReturnValue.get(md);
3932   }
3933
3934   private void analyzeFlowMethodInvokeNode(MethodDescriptor md, SymbolTable nametable,
3935       MethodInvokeNode min, NodeTupleSet nodeSet, NodeTupleSet implicitFlowTupleSet) {
3936
3937     if (nodeSet == null) {
3938       nodeSet = new NodeTupleSet();
3939     }
3940
3941     MethodDescriptor calleeMethodDesc = min.getMethod();
3942
3943     NameDescriptor baseName = min.getBaseName();
3944     boolean isSystemout = false;
3945     if (baseName != null) {
3946       isSystemout = baseName.getSymbol().equals("System.out");
3947     }
3948
3949     if (!ssjava.isSSJavaUtil(calleeMethodDesc.getClassDesc())
3950         && !ssjava.isTrustMethod(calleeMethodDesc) && !isSystemout) {
3951
3952       addMapCallerMethodDescToMethodInvokeNodeSet(md, min);
3953
3954       FlowGraph calleeFlowGraph = getFlowGraph(calleeMethodDesc);
3955       Set<FlowNode> calleeReturnSet = calleeFlowGraph.getReturnNodeSet();
3956
3957       System.out.println("#calleeReturnSet=" + calleeReturnSet);
3958
3959       if (min.getExpression() != null) {
3960
3961         NodeTupleSet baseNodeSet = new NodeTupleSet();
3962         analyzeFlowExpressionNode(md, nametable, min.getExpression(), baseNodeSet, null,
3963             implicitFlowTupleSet, false);
3964
3965         assert (baseNodeSet.size() == 1);
3966         mapMethodInvokeNodeToBaseTuple.put(min, baseNodeSet.iterator().next());
3967
3968         if (!min.getMethod().isStatic()) {
3969           addArgIdxMap(min, 0, baseNodeSet);
3970
3971           for (Iterator iterator = calleeReturnSet.iterator(); iterator.hasNext();) {
3972             FlowNode returnNode = (FlowNode) iterator.next();
3973             NTuple<Descriptor> returnDescTuple = returnNode.getDescTuple();
3974             if (returnDescTuple.startsWith(calleeMethodDesc.getThis())) {
3975               // the location type of the return value is started with 'this'
3976               // reference
3977               for (Iterator<NTuple<Descriptor>> baseIter = baseNodeSet.iterator(); baseIter
3978                   .hasNext();) {
3979                 NTuple<Descriptor> baseTuple = baseIter.next();
3980                 NTuple<Descriptor> inFlowTuple = new NTuple<Descriptor>(baseTuple.getList());
3981                 inFlowTuple.addAll(returnDescTuple.subList(1, returnDescTuple.size()));
3982                 nodeSet.addTuple(inFlowTuple);
3983               }
3984             } else {
3985               Set<FlowNode> inFlowSet = calleeFlowGraph.getIncomingFlowNodeSet(returnNode);
3986               for (Iterator iterator2 = inFlowSet.iterator(); iterator2.hasNext();) {
3987                 FlowNode inFlowNode = (FlowNode) iterator2.next();
3988                 if (inFlowNode.getDescTuple().startsWith(calleeMethodDesc.getThis())) {
3989                   nodeSet.addTupleSet(baseNodeSet);
3990                 }
3991               }
3992             }
3993           }
3994         }
3995
3996       }
3997
3998       // analyze parameter flows
3999
4000       if (min.numArgs() > 0) {
4001
4002         int offset;
4003         if (min.getMethod().isStatic()) {
4004           offset = 0;
4005         } else {
4006           offset = 1;
4007         }
4008
4009         for (int i = 0; i < min.numArgs(); i++) {
4010           ExpressionNode en = min.getArg(i);
4011           int idx = i + offset;
4012           NodeTupleSet argTupleSet = new NodeTupleSet();
4013           analyzeFlowExpressionNode(md, nametable, en, argTupleSet, false);
4014           // if argument is liternal node, argTuple is set to NULL.
4015           addArgIdxMap(min, idx, argTupleSet);
4016           FlowNode paramNode = calleeFlowGraph.getParamFlowNode(idx);
4017           if (hasInFlowTo(calleeFlowGraph, paramNode, calleeReturnSet)
4018               || calleeMethodDesc.getModifiers().isNative()) {
4019             addParamNodeFlowingToReturnValue(calleeMethodDesc, paramNode);
4020             nodeSet.addTupleSet(argTupleSet);
4021           }
4022         }
4023
4024       }
4025
4026       // propagateFlowsFromCallee(min, md, min.getMethod());
4027
4028     }
4029
4030   }
4031
4032   private boolean hasInFlowTo(FlowGraph fg, FlowNode inNode, Set<FlowNode> nodeSet) {
4033     // return true if inNode has in-flows to nodeSet
4034     Set<FlowNode> reachableSet = fg.getReachFlowNodeSetFrom(inNode);
4035     for (Iterator iterator = reachableSet.iterator(); iterator.hasNext();) {
4036       FlowNode fn = (FlowNode) iterator.next();
4037       if (nodeSet.contains(fn)) {
4038         return true;
4039       }
4040     }
4041     return false;
4042   }
4043
4044   private NodeTupleSet getNodeTupleSetByArgIdx(MethodInvokeNode min, int idx) {
4045     return mapMethodInvokeNodeToArgIdxMap.get(min).get(new Integer(idx));
4046   }
4047
4048   private void addArgIdxMap(MethodInvokeNode min, int idx, NodeTupleSet tupleSet) {
4049     Map<Integer, NodeTupleSet> mapIdxToTupleSet = mapMethodInvokeNodeToArgIdxMap.get(min);
4050     if (mapIdxToTupleSet == null) {
4051       mapIdxToTupleSet = new HashMap<Integer, NodeTupleSet>();
4052       mapMethodInvokeNodeToArgIdxMap.put(min, mapIdxToTupleSet);
4053     }
4054     mapIdxToTupleSet.put(new Integer(idx), tupleSet);
4055   }
4056
4057   private void analyzeFlowMethodParameters(MethodDescriptor callermd, SymbolTable nametable,
4058       MethodInvokeNode min, NodeTupleSet nodeSet) {
4059
4060     if (min.numArgs() > 0) {
4061
4062       int offset;
4063       if (min.getMethod().isStatic()) {
4064         offset = 0;
4065       } else {
4066         offset = 1;
4067         // NTuple<Descriptor> thisArgTuple = new NTuple<Descriptor>();
4068         // thisArgTuple.add(callermd.getThis());
4069         // NodeTupleSet argTupleSet = new NodeTupleSet();
4070         // argTupleSet.addTuple(thisArgTuple);
4071         // addArgIdxMap(min, 0, argTupleSet);
4072         // nodeSet.addTuple(thisArgTuple);
4073       }
4074
4075       for (int i = 0; i < min.numArgs(); i++) {
4076         ExpressionNode en = min.getArg(i);
4077         NodeTupleSet argTupleSet = new NodeTupleSet();
4078         analyzeFlowExpressionNode(callermd, nametable, en, argTupleSet, false);
4079         // if argument is liternal node, argTuple is set to NULL.
4080         addArgIdxMap(min, i + offset, argTupleSet);
4081         nodeSet.addTupleSet(argTupleSet);
4082       }
4083
4084     }
4085
4086   }
4087
4088   private void analyzeLiteralNode(MethodDescriptor md, SymbolTable nametable, LiteralNode en) {
4089
4090   }
4091
4092   private void analyzeFlowArrayAccessNode(MethodDescriptor md, SymbolTable nametable,
4093       ArrayAccessNode aan, NodeTupleSet nodeSet, boolean isLHS) {
4094
4095     NodeTupleSet expNodeTupleSet = new NodeTupleSet();
4096     NTuple<Descriptor> base =
4097         analyzeFlowExpressionNode(md, nametable, aan.getExpression(), expNodeTupleSet, isLHS);
4098
4099     NodeTupleSet idxNodeTupleSet = new NodeTupleSet();
4100     analyzeFlowExpressionNode(md, nametable, aan.getIndex(), idxNodeTupleSet, isLHS);
4101
4102     if (isLHS) {
4103       // need to create an edge from idx to array
4104       for (Iterator<NTuple<Descriptor>> idxIter = idxNodeTupleSet.iterator(); idxIter.hasNext();) {
4105         NTuple<Descriptor> idxTuple = idxIter.next();
4106         for (Iterator<NTuple<Descriptor>> arrIter = expNodeTupleSet.iterator(); arrIter.hasNext();) {
4107           NTuple<Descriptor> arrTuple = arrIter.next();
4108           getFlowGraph(md).addValueFlowEdge(idxTuple, arrTuple);
4109         }
4110       }
4111
4112       nodeSet.addTupleSet(expNodeTupleSet);
4113     } else {
4114       nodeSet.addTupleSet(expNodeTupleSet);
4115       nodeSet.addTupleSet(idxNodeTupleSet);
4116     }
4117   }
4118
4119   private void analyzeCreateObjectNode(MethodDescriptor md, SymbolTable nametable,
4120       CreateObjectNode en) {
4121     // TODO Auto-generated method stub
4122
4123   }
4124
4125   private void analyzeFlowOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,
4126       NodeTupleSet nodeSet, NodeTupleSet implicitFlowTupleSet) {
4127
4128     NodeTupleSet leftOpSet = new NodeTupleSet();
4129     NodeTupleSet rightOpSet = new NodeTupleSet();
4130
4131     // left operand
4132     analyzeFlowExpressionNode(md, nametable, on.getLeft(), leftOpSet, null, implicitFlowTupleSet,
4133         false);
4134
4135     if (on.getRight() != null) {
4136       // right operand
4137       analyzeFlowExpressionNode(md, nametable, on.getRight(), rightOpSet, null,
4138           implicitFlowTupleSet, false);
4139     }
4140
4141     Operation op = on.getOp();
4142
4143     switch (op.getOp()) {
4144
4145     case Operation.UNARYPLUS:
4146     case Operation.UNARYMINUS:
4147     case Operation.LOGIC_NOT:
4148       // single operand
4149       nodeSet.addTupleSet(leftOpSet);
4150       break;
4151
4152     case Operation.LOGIC_OR:
4153     case Operation.LOGIC_AND:
4154     case Operation.COMP:
4155     case Operation.BIT_OR:
4156     case Operation.BIT_XOR:
4157     case Operation.BIT_AND:
4158     case Operation.ISAVAILABLE:
4159     case Operation.EQUAL:
4160     case Operation.NOTEQUAL:
4161     case Operation.LT:
4162     case Operation.GT:
4163     case Operation.LTE:
4164     case Operation.GTE:
4165     case Operation.ADD:
4166     case Operation.SUB:
4167     case Operation.MULT:
4168     case Operation.DIV:
4169     case Operation.MOD:
4170     case Operation.LEFTSHIFT:
4171     case Operation.RIGHTSHIFT:
4172     case Operation.URIGHTSHIFT:
4173
4174       // there are two operands
4175       nodeSet.addTupleSet(leftOpSet);
4176       nodeSet.addTupleSet(rightOpSet);
4177       break;
4178
4179     default:
4180       throw new Error(op.toString());
4181     }
4182
4183   }
4184
4185   private NTuple<Descriptor> analyzeFlowNameNode(MethodDescriptor md, SymbolTable nametable,
4186       NameNode nn, NodeTupleSet nodeSet, NTuple<Descriptor> base, NodeTupleSet implicitFlowTupleSet) {
4187
4188     // System.out.println("analyzeFlowNameNode=" + nn.printNode(0));
4189
4190     if (base == null) {
4191       base = new NTuple<Descriptor>();
4192     }
4193
4194     NameDescriptor nd = nn.getName();
4195
4196     if (nd.getBase() != null) {
4197       base =
4198           analyzeFlowExpressionNode(md, nametable, nn.getExpression(), nodeSet, base,
4199               implicitFlowTupleSet, false);
4200       if (base == null) {
4201         // base node has the top location
4202         return base;
4203       }
4204     } else {
4205       String varname = nd.toString();
4206       if (varname.equals("this")) {
4207         // 'this' itself!
4208         base.add(md.getThis());
4209         return base;
4210       }
4211
4212       Descriptor d = (Descriptor) nametable.get(varname);
4213
4214       if (d instanceof VarDescriptor) {
4215         VarDescriptor vd = (VarDescriptor) d;
4216         base.add(vd);
4217       } else if (d instanceof FieldDescriptor) {
4218         // the type of field descriptor has a location!
4219         FieldDescriptor fd = (FieldDescriptor) d;
4220         if (fd.isStatic()) {
4221           if (fd.isFinal()) {
4222             // if it is 'static final', no need to have flow node for the TOP
4223             // location
4224             return null;
4225           } else {
4226             // if 'static', assign the default GLOBAL LOCATION to the first
4227             // element of the tuple
4228             base.add(GLOBALDESC);
4229           }
4230         } else {
4231           // the location of field access starts from this, followed by field
4232           // location
4233           base.add(md.getThis());
4234         }
4235
4236         base.add(fd);
4237       } else if (d == null) {
4238         // access static field
4239         base.add(GLOBALDESC);
4240         base.add(nn.getField());
4241         return base;
4242
4243         // FieldDescriptor fd = nn.getField();addFlowGraphEdge
4244         //
4245         // MethodLattice<String> localLattice = ssjava.getMethodLattice(md);
4246         // String globalLocId = localLattice.getGlobalLoc();
4247         // if (globalLocId == null) {
4248         // throw new
4249         // Error("Method lattice does not define global variable location at "
4250         // + generateErrorMessage(md.getClassDesc(), nn));
4251         // }
4252         // loc.addLocation(new Location(md, globalLocId));
4253         //
4254         // Location fieldLoc = (Location) fd.getType().getExtension();
4255         // loc.addLocation(fieldLoc);
4256         //
4257         // return loc;
4258
4259       }
4260     }
4261     getFlowGraph(md).createNewFlowNode(base);
4262
4263     return base;
4264
4265   }
4266
4267   private NTuple<Descriptor> analyzeFlowFieldAccessNode(MethodDescriptor md, SymbolTable nametable,
4268       FieldAccessNode fan, NodeTupleSet nodeSet, NTuple<Descriptor> base,
4269       NodeTupleSet implicitFlowTupleSet, boolean isLHS) {
4270
4271     ExpressionNode left = fan.getExpression();
4272     TypeDescriptor ltd = left.getType();
4273     FieldDescriptor fd = fan.getField();
4274
4275     String varName = null;
4276     if (left.kind() == Kind.NameNode) {
4277       NameDescriptor nd = ((NameNode) left).getName();
4278       varName = nd.toString();
4279     }
4280
4281     if (ltd.isClassNameRef() || (varName != null && varName.equals("this"))) {
4282       // using a class name directly or access using this
4283       if (fd.isStatic() && fd.isFinal()) {
4284         return null;
4285       }
4286     }
4287
4288     NodeTupleSet idxNodeTupleSet = new NodeTupleSet();
4289
4290     if (left instanceof ArrayAccessNode) {
4291
4292       ArrayAccessNode aan = (ArrayAccessNode) left;
4293       left = aan.getExpression();
4294       analyzeFlowExpressionNode(md, nametable, aan.getIndex(), idxNodeTupleSet, base,
4295           implicitFlowTupleSet, isLHS);
4296
4297       nodeSet.addTupleSet(idxNodeTupleSet);
4298     }
4299     base =
4300         analyzeFlowExpressionNode(md, nametable, left, nodeSet, base, implicitFlowTupleSet, isLHS);
4301
4302     if (base == null) {
4303       // in this case, field is TOP location
4304       return null;
4305     } else {
4306
4307       NTuple<Descriptor> flowFieldTuple = new NTuple<Descriptor>(base.toList());
4308
4309       if (!left.getType().isPrimitive()) {
4310
4311         if (!fd.getSymbol().equals("length")) {
4312           // array.length access, just have the location of the array
4313           flowFieldTuple.add(fd);
4314           nodeSet.removeTuple(base);
4315         }
4316
4317       }
4318       getFlowGraph(md).createNewFlowNode(flowFieldTuple);
4319
4320       if (isLHS) {
4321         for (Iterator<NTuple<Descriptor>> idxIter = idxNodeTupleSet.iterator(); idxIter.hasNext();) {
4322           NTuple<Descriptor> idxTuple = idxIter.next();
4323           getFlowGraph(md).addValueFlowEdge(idxTuple, flowFieldTuple);
4324         }
4325       }
4326       return flowFieldTuple;
4327
4328     }
4329
4330   }
4331
4332   private void debug_printTreeNode(TreeNode tn) {
4333
4334     System.out.println("DEBUG: " + tn.printNode(0) + "                line#=" + tn.getNumLine());
4335
4336   }
4337
4338   private void analyzeFlowAssignmentNode(MethodDescriptor md, SymbolTable nametable,
4339       AssignmentNode an, NodeTupleSet nodeSet, NTuple<Descriptor> base,
4340       NodeTupleSet implicitFlowTupleSet) {
4341
4342     NodeTupleSet nodeSetRHS = new NodeTupleSet();
4343     NodeTupleSet nodeSetLHS = new NodeTupleSet();
4344
4345     boolean postinc = true;
4346     if (an.getOperation().getBaseOp() == null
4347         || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
4348             .getBaseOp().getOp() != Operation.POSTDEC)) {
4349       postinc = false;
4350     }
4351     // if LHS is array access node, need to capture value flows between an array
4352     // and its index value
4353     analyzeFlowExpressionNode(md, nametable, an.getDest(), nodeSetLHS, null, implicitFlowTupleSet,
4354         true);
4355
4356     if (!postinc) {
4357       // analyze value flows of rhs expression
4358       analyzeFlowExpressionNode(md, nametable, an.getSrc(), nodeSetRHS, null, implicitFlowTupleSet,
4359           false);
4360
4361       // System.out.println("-analyzeFlowAssignmentNode=" + an.printNode(0));
4362       // System.out.println("-nodeSetLHS=" + nodeSetLHS);
4363       // System.out.println("-nodeSetRHS=" + nodeSetRHS);
4364       // System.out.println("-implicitFlowTupleSet=" + implicitFlowTupleSet);
4365       // System.out.println("-");
4366
4367       if (an.getOperation().getOp() >= 2 && an.getOperation().getOp() <= 12) {
4368         // if assignment contains OP+EQ operator, creates edges from LHS to LHS
4369
4370         for (Iterator<NTuple<Descriptor>> iter = nodeSetLHS.iterator(); iter.hasNext();) {
4371           NTuple<Descriptor> fromTuple = iter.next();
4372           for (Iterator<NTuple<Descriptor>> iter2 = nodeSetLHS.iterator(); iter2.hasNext();) {
4373             NTuple<Descriptor> toTuple = iter2.next();
4374             addFlowGraphEdge(md, fromTuple, toTuple);
4375           }
4376         }
4377       }
4378
4379       // creates edges from RHS to LHS
4380       NTuple<Descriptor> interTuple = null;
4381       if (nodeSetRHS.size() > 1) {
4382         interTuple = getFlowGraph(md).createIntermediateNode().getDescTuple();
4383       }
4384
4385       for (Iterator<NTuple<Descriptor>> iter = nodeSetRHS.iterator(); iter.hasNext();) {
4386         NTuple<Descriptor> fromTuple = iter.next();
4387         for (Iterator<NTuple<Descriptor>> iter2 = nodeSetLHS.iterator(); iter2.hasNext();) {
4388           NTuple<Descriptor> toTuple = iter2.next();
4389           addFlowGraphEdge(md, fromTuple, interTuple, toTuple);
4390         }
4391       }
4392
4393       // creates edges from implicitFlowTupleSet to LHS
4394       for (Iterator<NTuple<Descriptor>> iter = implicitFlowTupleSet.iterator(); iter.hasNext();) {
4395         NTuple<Descriptor> fromTuple = iter.next();
4396         for (Iterator<NTuple<Descriptor>> iter2 = nodeSetLHS.iterator(); iter2.hasNext();) {
4397           NTuple<Descriptor> toTuple = iter2.next();
4398           addFlowGraphEdge(md, fromTuple, toTuple);
4399         }
4400       }
4401
4402     } else {
4403       // postinc case
4404
4405       for (Iterator<NTuple<Descriptor>> iter2 = nodeSetLHS.iterator(); iter2.hasNext();) {
4406         NTuple<Descriptor> tuple = iter2.next();
4407         addFlowGraphEdge(md, tuple, tuple);
4408       }
4409
4410       // creates edges from implicitFlowTupleSet to LHS
4411       for (Iterator<NTuple<Descriptor>> iter = implicitFlowTupleSet.iterator(); iter.hasNext();) {
4412         NTuple<Descriptor> fromTuple = iter.next();
4413         for (Iterator<NTuple<Descriptor>> iter2 = nodeSetLHS.iterator(); iter2.hasNext();) {
4414           NTuple<Descriptor> toTuple = iter2.next();
4415           addFlowGraphEdge(md, fromTuple, toTuple);
4416         }
4417       }
4418
4419     }
4420
4421     if (nodeSet != null) {
4422       nodeSet.addTupleSet(nodeSetLHS);
4423     }
4424   }
4425
4426   public FlowGraph getFlowGraph(MethodDescriptor md) {
4427     return mapMethodDescriptorToFlowGraph.get(md);
4428   }
4429
4430   private boolean addFlowGraphEdge(MethodDescriptor md, NTuple<Descriptor> from,
4431       NTuple<Descriptor> to) {
4432     FlowGraph graph = getFlowGraph(md);
4433     graph.addValueFlowEdge(from, to);
4434     return true;
4435   }
4436
4437   private void addFlowGraphEdge(MethodDescriptor md, NTuple<Descriptor> from,
4438       NTuple<Descriptor> inter, NTuple<Descriptor> to) {
4439
4440     FlowGraph graph = getFlowGraph(md);
4441
4442     if (inter != null) {
4443       graph.addValueFlowEdge(from, inter);
4444       graph.addValueFlowEdge(inter, to);
4445     } else {
4446       graph.addValueFlowEdge(from, to);
4447     }
4448
4449   }
4450
4451   public void writeInferredLatticeDotFile(ClassDescriptor cd, HierarchyGraph simpleHierarchyGraph,
4452       SSJavaLattice<String> locOrder, String nameSuffix) {
4453     writeInferredLatticeDotFile(cd, null, simpleHierarchyGraph, locOrder, nameSuffix);
4454   }
4455
4456   public void writeInferredLatticeDotFile(ClassDescriptor cd, MethodDescriptor md,
4457       HierarchyGraph simpleHierarchyGraph, SSJavaLattice<String> locOrder, String nameSuffix) {
4458
4459     String fileName = "lattice_";
4460     if (md != null) {
4461       fileName +=
4462           cd.getSymbol().replaceAll("[\\W_]", "") + "_" + md.toString().replaceAll("[\\W_]", "");
4463     } else {
4464       fileName += cd.getSymbol().replaceAll("[\\W_]", "");
4465     }
4466
4467     fileName += nameSuffix;
4468
4469     Set<Pair<String, String>> pairSet = locOrder.getOrderingPairSet();
4470
4471     Set<String> addedLocSet = new HashSet<String>();
4472
4473     if (pairSet.size() > 0) {
4474       try {
4475         BufferedWriter bw = new BufferedWriter(new FileWriter(fileName + ".dot"));
4476
4477         bw.write("digraph " + fileName + " {\n");
4478
4479         for (Iterator iterator = pairSet.iterator(); iterator.hasNext();) {
4480           // pair is in the form of <higher, lower>
4481           Pair<String, String> pair = (Pair<String, String>) iterator.next();
4482
4483           String highLocId = pair.getFirst();
4484           String lowLocId = pair.getSecond();
4485
4486           if (!addedLocSet.contains(highLocId)) {
4487             addedLocSet.add(highLocId);
4488             drawNode(bw, locOrder, simpleHierarchyGraph, highLocId);
4489           }
4490
4491           if (!addedLocSet.contains(lowLocId)) {
4492             addedLocSet.add(lowLocId);
4493             drawNode(bw, locOrder, simpleHierarchyGraph, lowLocId);
4494           }
4495
4496           bw.write(highLocId + " -> " + lowLocId + ";\n");
4497         }
4498         bw.write("}\n");
4499         bw.close();
4500
4501       } catch (IOException e) {
4502         e.printStackTrace();
4503       }
4504
4505     }
4506
4507   }
4508
4509   private String convertMergeSetToString(HierarchyGraph graph, Set<HNode> mergeSet) {
4510     String str = "";
4511     for (Iterator iterator = mergeSet.iterator(); iterator.hasNext();) {
4512       HNode merged = (HNode) iterator.next();
4513       if (merged.isMergeNode()) {
4514         str += convertMergeSetToString(graph, graph.getMapHNodetoMergeSet().get(merged));
4515       } else {
4516         str += " " + merged.getName();
4517       }
4518     }
4519     return str;
4520   }
4521
4522   private void drawNode(BufferedWriter bw, SSJavaLattice<String> lattice, HierarchyGraph graph,
4523       String locName) throws IOException {
4524
4525     HNode node = graph.getHNode(locName);
4526
4527     if (node == null) {
4528       return;
4529     }
4530
4531     String prettyStr;
4532     if (lattice.isSharedLoc(locName)) {
4533       prettyStr = locName + "*";
4534     } else {
4535       prettyStr = locName;
4536     }
4537
4538     if (node.isMergeNode()) {
4539       Set<HNode> mergeSet = graph.getMapHNodetoMergeSet().get(node);
4540       prettyStr += ":" + convertMergeSetToString(graph, mergeSet);
4541     }
4542     bw.write(locName + " [label=\"" + prettyStr + "\"]" + ";\n");
4543   }
4544
4545   public void _debug_printGraph() {
4546     Set<MethodDescriptor> keySet = mapMethodDescriptorToFlowGraph.keySet();
4547
4548     for (Iterator<MethodDescriptor> iterator = keySet.iterator(); iterator.hasNext();) {
4549       MethodDescriptor md = (MethodDescriptor) iterator.next();
4550       FlowGraph fg = mapMethodDescriptorToFlowGraph.get(md);
4551       try {
4552         fg.writeGraph();
4553       } catch (IOException e) {
4554         e.printStackTrace();
4555       }
4556     }
4557
4558   }
4559
4560 }
4561
4562 class CyclicFlowException extends Exception {
4563
4564 }
4565
4566 class InterDescriptor extends Descriptor {
4567
4568   public InterDescriptor(String name) {
4569     super(name);
4570   }
4571
4572 }