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