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