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