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