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