changes on global composite assignment translation and pcloc generation
[IRC.git] / Robust / src / Analysis / SSJava / LocationInference.java
1 package Analysis.SSJava;
2
3 import java.io.BufferedReader;
4 import java.io.BufferedWriter;
5 import java.io.FileReader;
6 import java.io.FileWriter;
7 import java.io.IOException;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.Comparator;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.Iterator;
14 import java.util.LinkedList;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.Stack;
19 import java.util.Vector;
20
21 import IR.ClassDescriptor;
22 import IR.Descriptor;
23 import IR.FieldDescriptor;
24 import IR.MethodDescriptor;
25 import IR.NameDescriptor;
26 import IR.Operation;
27 import IR.State;
28 import IR.SymbolTable;
29 import IR.TypeDescriptor;
30 import IR.VarDescriptor;
31 import IR.Tree.ArrayAccessNode;
32 import IR.Tree.AssignmentNode;
33 import IR.Tree.BlockExpressionNode;
34 import IR.Tree.BlockNode;
35 import IR.Tree.BlockStatementNode;
36 import IR.Tree.CastNode;
37 import IR.Tree.CreateObjectNode;
38 import IR.Tree.DeclarationNode;
39 import IR.Tree.ExpressionNode;
40 import IR.Tree.FieldAccessNode;
41 import IR.Tree.IfStatementNode;
42 import IR.Tree.Kind;
43 import IR.Tree.LiteralNode;
44 import IR.Tree.LoopNode;
45 import IR.Tree.MethodInvokeNode;
46 import IR.Tree.NameNode;
47 import IR.Tree.OpNode;
48 import IR.Tree.ReturnNode;
49 import IR.Tree.SubBlockNode;
50 import IR.Tree.SwitchBlockNode;
51 import IR.Tree.SwitchStatementNode;
52 import IR.Tree.TertiaryNode;
53 import IR.Tree.TreeNode;
54 import Util.Pair;
55
56 public class LocationInference {
57
58   State state;
59   SSJavaAnalysis ssjava;
60
61   List<ClassDescriptor> temp_toanalyzeList;
62   List<MethodDescriptor> temp_toanalyzeMethodList;
63   Map<MethodDescriptor, FlowGraph> mapMethodDescriptorToFlowGraph;
64
65   LinkedList<MethodDescriptor> toanalyze_methodDescList;
66
67   // map a method descriptor to its set of parameter descriptors
68   Map<MethodDescriptor, Set<Descriptor>> mapMethodDescriptorToParamDescSet;
69
70   // keep current descriptors to visit in fixed-point interprocedural analysis,
71   private Stack<MethodDescriptor> methodDescriptorsToVisitStack;
72
73   // map a class descriptor to a field lattice
74   private Map<ClassDescriptor, SSJavaLattice<String>> cd2lattice;
75
76   // map a method descriptor to a method lattice
77   private Map<MethodDescriptor, SSJavaLattice<String>> md2lattice;
78
79   // map a method/class descriptor to a hierarchy graph
80   private Map<Descriptor, HierarchyGraph> mapDescriptorToHierarchyGraph;
81
82   // map a method/class descriptor to a skeleton hierarchy graph
83   private Map<Descriptor, HierarchyGraph> mapDescriptorToSkeletonHierarchyGraph;
84
85   private Map<Descriptor, HierarchyGraph> mapDescriptorToSimpleHierarchyGraph;
86
87   // map a method/class descriptor to a skeleton hierarchy graph with combination nodes
88   private Map<Descriptor, HierarchyGraph> mapDescriptorToCombineSkeletonHierarchyGraph;
89
90   // map a descriptor to a simple lattice
91   private Map<Descriptor, SSJavaLattice<String>> mapDescriptorToSimpleLattice;
92
93   // map a method descriptor to the set of method invocation nodes which are
94   // invoked by the method descriptor
95   private Map<MethodDescriptor, Set<MethodInvokeNode>> mapMethodDescriptorToMethodInvokeNodeSet;
96
97   private Map<MethodInvokeNode, Map<Integer, NTuple<Descriptor>>> mapMethodInvokeNodeToArgIdxMap;
98
99   private Map<MethodInvokeNode, NTuple<Descriptor>> mapMethodInvokeNodeToBaseTuple;
100
101   private Map<MethodDescriptor, MethodLocationInfo> mapMethodDescToMethodLocationInfo;
102
103   private Map<ClassDescriptor, LocationInfo> mapClassToLocationInfo;
104
105   private Map<MethodDescriptor, Set<MethodDescriptor>> mapMethodToCalleeSet;
106
107   private Map<MethodDescriptor, Set<FlowNode>> mapMethodDescToParamNodeFlowsToReturnValue;
108
109   private Map<String, Vector<String>> mapFileNameToLineVector;
110
111   private Map<Descriptor, Integer> mapDescToDefinitionLine;
112
113   private Map<Descriptor, LocationSummary> mapDescToLocationSummary;
114
115   // maps a method descriptor to a sub global flow graph that captures all value flows caused by the
116   // set of callees reachable from the method
117   private Map<MethodDescriptor, GlobalFlowGraph> mapMethodDescriptorToSubGlobalFlowGraph;
118
119   private Map<MethodInvokeNode, Map<NTuple<Descriptor>, NTuple<Descriptor>>> mapMethodInvokeNodeToMapCallerArgToCalleeArg;
120
121   public static final String GLOBALLOC = "GLOBALLOC";
122
123   public static final String INTERLOC = "INTERLOC";
124
125   public static final String PCLOC = "_PCLOC_";
126
127   public static final String RLOC = "_RLOC_";
128
129   public static final Descriptor GLOBALDESC = new NameDescriptor(GLOBALLOC);
130
131   public static final Descriptor TOPDESC = new NameDescriptor(SSJavaAnalysis.TOP);
132
133   public static final Descriptor BOTTOMDESC = new NameDescriptor(SSJavaAnalysis.BOTTOM);
134
135   public static final Descriptor RETURNLOC = new NameDescriptor(RLOC);
136
137   public static final Descriptor LITERALDESC = new NameDescriptor("LITERAL");
138
139   public static final HNode TOPHNODE = new HNode(TOPDESC);
140
141   public static final HNode BOTTOMHNODE = new HNode(BOTTOMDESC);
142
143   public static String newline = System.getProperty("line.separator");
144
145   LocationInfo curMethodInfo;
146
147   boolean debug = true;
148
149   public static int locSeed = 0;
150
151   public LocationInference(SSJavaAnalysis ssjava, State state) {
152     this.ssjava = ssjava;
153     this.state = state;
154     this.temp_toanalyzeList = new ArrayList<ClassDescriptor>();
155     this.temp_toanalyzeMethodList = new ArrayList<MethodDescriptor>();
156     this.mapMethodDescriptorToFlowGraph = new HashMap<MethodDescriptor, FlowGraph>();
157     this.cd2lattice = new HashMap<ClassDescriptor, SSJavaLattice<String>>();
158     this.md2lattice = new HashMap<MethodDescriptor, SSJavaLattice<String>>();
159     this.methodDescriptorsToVisitStack = new Stack<MethodDescriptor>();
160     this.mapMethodDescriptorToMethodInvokeNodeSet =
161         new HashMap<MethodDescriptor, Set<MethodInvokeNode>>();
162     this.mapMethodInvokeNodeToArgIdxMap =
163         new HashMap<MethodInvokeNode, Map<Integer, NTuple<Descriptor>>>();
164     this.mapMethodDescToMethodLocationInfo = new HashMap<MethodDescriptor, MethodLocationInfo>();
165     this.mapMethodToCalleeSet = new HashMap<MethodDescriptor, Set<MethodDescriptor>>();
166     this.mapClassToLocationInfo = new HashMap<ClassDescriptor, LocationInfo>();
167
168     this.mapFileNameToLineVector = new HashMap<String, Vector<String>>();
169     this.mapDescToDefinitionLine = new HashMap<Descriptor, Integer>();
170     this.mapMethodDescToParamNodeFlowsToReturnValue =
171         new HashMap<MethodDescriptor, Set<FlowNode>>();
172
173     this.mapDescriptorToHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
174     this.mapMethodInvokeNodeToBaseTuple = new HashMap<MethodInvokeNode, NTuple<Descriptor>>();
175
176     this.mapDescriptorToSkeletonHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
177     this.mapDescriptorToCombineSkeletonHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
178     this.mapDescriptorToSimpleHierarchyGraph = new HashMap<Descriptor, HierarchyGraph>();
179
180     this.mapDescriptorToSimpleLattice = new HashMap<Descriptor, SSJavaLattice<String>>();
181
182     this.mapDescToLocationSummary = new HashMap<Descriptor, LocationSummary>();
183
184     this.mapMethodDescriptorToSubGlobalFlowGraph = new HashMap<MethodDescriptor, GlobalFlowGraph>();
185
186     this.mapMethodInvokeNodeToMapCallerArgToCalleeArg =
187         new HashMap<MethodInvokeNode, Map<NTuple<Descriptor>, NTuple<Descriptor>>>();
188
189   }
190
191   public void setupToAnalyze() {
192     SymbolTable classtable = state.getClassSymbolTable();
193     temp_toanalyzeList.clear();
194     temp_toanalyzeList.addAll(classtable.getValueSet());
195     // Collections.sort(toanalyzeList, new Comparator<ClassDescriptor>() {
196     // public int compare(ClassDescriptor o1, ClassDescriptor o2) {
197     // return o1.getClassName().compareToIgnoreCase(o2.getClassName());
198     // }
199     // });
200   }
201
202   public void setupToAnalazeMethod(ClassDescriptor cd) {
203
204     SymbolTable methodtable = cd.getMethodTable();
205     temp_toanalyzeMethodList.clear();
206     temp_toanalyzeMethodList.addAll(methodtable.getValueSet());
207     Collections.sort(temp_toanalyzeMethodList, new Comparator<MethodDescriptor>() {
208       public int compare(MethodDescriptor o1, MethodDescriptor o2) {
209         return o1.getSymbol().compareToIgnoreCase(o2.getSymbol());
210       }
211     });
212   }
213
214   public boolean toAnalyzeMethodIsEmpty() {
215     return temp_toanalyzeMethodList.isEmpty();
216   }
217
218   public boolean toAnalyzeIsEmpty() {
219     return temp_toanalyzeList.isEmpty();
220   }
221
222   public ClassDescriptor toAnalyzeNext() {
223     return temp_toanalyzeList.remove(0);
224   }
225
226   public MethodDescriptor toAnalyzeMethodNext() {
227     return temp_toanalyzeMethodList.remove(0);
228   }
229
230   public void inference() {
231
232     ssjava.init();
233
234     // construct value flow graph
235     constructFlowGraph();
236
237     assignCompositeLocation();
238
239     updateFlowGraph();
240
241     // calculate RETURNLOC,PCLOC
242     calculateExtraLocations();
243
244     _debug_writeFlowGraph();
245
246     // System.exit(0);
247
248     constructHierarchyGraph();
249
250     debug_writeHierarchyDotFiles();
251
252     simplifyHierarchyGraph();
253
254     debug_writeSimpleHierarchyDotFiles();
255
256     constructSkeletonHierarchyGraph();
257
258     debug_writeSkeletonHierarchyDotFiles();
259
260     insertCombinationNodes();
261
262     debug_writeSkeletonCombinationHierarchyDotFiles();
263
264     buildLattice();
265
266     debug_writeLattices();
267
268     updateCompositeLocationAssignments();
269
270     generateMethodSummary();
271
272     generateAnnoatedCode();
273
274     System.exit(0);
275
276   }
277
278   private void updateFlowGraph() {
279
280     LinkedList<MethodDescriptor> methodDescList =
281         (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
282
283     while (!methodDescList.isEmpty()) {
284       MethodDescriptor md = methodDescList.removeLast();
285       if (state.SSJAVADEBUG) {
286         System.out.println();
287         System.out.println("SSJAVA: Updating a flow graph: " + md);
288         propagateFlowsFromCalleesWithNoCompositeLocation(md);
289       }
290     }
291   }
292
293   public Map<NTuple<Descriptor>, NTuple<Descriptor>> getMapCallerArgToCalleeParam(
294       MethodInvokeNode min) {
295
296     if (!mapMethodInvokeNodeToMapCallerArgToCalleeArg.containsKey(min)) {
297       mapMethodInvokeNodeToMapCallerArgToCalleeArg.put(min,
298           new HashMap<NTuple<Descriptor>, NTuple<Descriptor>>());
299     }
300
301     return mapMethodInvokeNodeToMapCallerArgToCalleeArg.get(min);
302   }
303
304   public void addMapCallerArgToCalleeParam(MethodInvokeNode min, NTuple<Descriptor> callerArg,
305       NTuple<Descriptor> calleeParam) {
306     getMapCallerArgToCalleeParam(min).put(callerArg, calleeParam);
307   }
308
309   private void assignCompositeLocation() {
310     calculateGlobalValueFlowCompositeLocation();
311     translateCompositeLocationAssignmentToFlowGraph();
312   }
313
314   private void translateCompositeLocationAssignmentToFlowGraph() {
315     System.out.println("\nSSJAVA: Translate composite location assignments to flow graphs:");
316     MethodDescriptor methodEventLoopDesc = ssjava.getMethodContainingSSJavaLoop();
317     translateCompositeLocationAssignmentToFlowGraph(methodEventLoopDesc);
318   }
319
320   private void updateCompositeLocationAssignments() {
321
322     LinkedList<MethodDescriptor> methodDescList =
323         (LinkedList<MethodDescriptor>) toanalyze_methodDescList.clone();
324
325     while (!methodDescList.isEmpty()) {
326       MethodDescriptor md = methodDescList.removeLast();
327
328       System.out.println("\n#updateCompositeLocationAssignments=" + md);
329
330       FlowGraph flowGraph = getFlowGraph(md);
331
332       MethodSummary methodSummary = getMethodSummary(md);
333
334       Set<FlowNode> nodeSet = flowGraph.getNodeSet();
335       for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
336         FlowNode node = (FlowNode) iterator.next();
337         System.out.println("-node=" + node + "   node.getDescTuple=" + node.getDescTuple());
338         if (node.getCompositeLocation() != null) {
339           CompositeLocation compLoc = node.getCompositeLocation();
340           CompositeLocation updatedCompLoc = updateCompositeLocation(compLoc);
341           node.setCompositeLocation(updatedCompLoc);
342           System.out.println("---updatedCompLoc1=" + updatedCompLoc);
343         } else {
344           NTuple<Descriptor> descTuple = node.getDescTuple();
345           System.out.println("update desc=" + descTuple);
346           CompositeLocation compLoc = convertToCompositeLocation(md, descTuple);
347           compLoc = updateCompositeLocation(compLoc);
348           node.setCompositeLocation(compLoc);
349           System.out.println("---updatedCompLoc2=" + compLoc);
350         }
351
352         if (node.isDeclaratonNode()) {
353           Descriptor localVarDesc = node.getDescTuple().get(0);
354           CompositeLocation compLoc = updateCompositeLocation(node.getCompositeLocation());
355           methodSummary.addMapVarNameToInferCompLoc(localVarDesc, compLoc);
356         }
357       }
358
359       // update PCLOC and RETURNLOC if they have a composite location assignment
360       if (methodSummary.getRETURNLoc() != null) {
361         methodSummary.setRETURNLoc(updateCompositeLocation(methodSummary.getRETURNLoc()));
362       }
363       if (methodSummary.getPCLoc() != null) {
364         methodSummary.setPCLoc(updateCompositeLocation(methodSummary.getPCLoc()));
365       }
366
367     }
368
369   }
370
371   private CompositeLocation updateCompositeLocation(CompositeLocation compLoc) {
372     CompositeLocation updatedCompLoc = new CompositeLocation();
373     for (int i = 0; i < compLoc.getSize(); i++) {
374       Location loc = compLoc.get(i);
375       String nodeIdentifier = loc.getLocIdentifier();
376       Descriptor enclosingDesc = loc.getDescriptor();
377       String locName;
378       if (!enclosingDesc.equals(GLOBALDESC)) {
379         LocationSummary locSummary = getLocationSummary(enclosingDesc);
380         HierarchyGraph scGraph = getSkeletonCombinationHierarchyGraph(enclosingDesc);
381         if (scGraph != null) {
382           HNode curNode = scGraph.getCurrentHNode(nodeIdentifier);
383           if (curNode != null) {
384             nodeIdentifier = curNode.getName();
385           }
386         }
387         locName = locSummary.getLocationName(nodeIdentifier);
388       } else {
389         locName = nodeIdentifier;
390       }
391       Location updatedLoc = new Location(enclosingDesc, locName);
392       updatedCompLoc.addLocation(updatedLoc);
393     }
394
395     return updatedCompLoc;
396   }
397
398   private void translateCompositeLocationAssignmentToFlowGraph(MethodDescriptor mdCaller) {
399
400     // First, assign a composite location to a node in the flow graph
401     GlobalFlowGraph callerGlobalFlowGraph = getSubGlobalFlowGraph(mdCaller);
402
403     FlowGraph callerFlowGraph = getFlowGraph(mdCaller);
404     Map<Location, CompositeLocation> callerMapLocToCompLoc =
405         callerGlobalFlowGraph.getMapLocationToInferCompositeLocation();
406     Set<Location> methodLocSet = callerMapLocToCompLoc.keySet();
407     for (Iterator iterator = methodLocSet.iterator(); iterator.hasNext();) {
408       Location methodLoc = (Location) iterator.next();
409       if (methodLoc.getDescriptor().equals(mdCaller)) {
410         CompositeLocation inferCompLoc = callerMapLocToCompLoc.get(methodLoc);
411         assignCompositeLocationToFlowGraph(callerFlowGraph, methodLoc, inferCompLoc);
412       }
413     }
414
415     Set<MethodInvokeNode> minSet = mapMethodDescriptorToMethodInvokeNodeSet.get(mdCaller);
416
417     Set<MethodDescriptor> calleeSet = new HashSet<MethodDescriptor>();
418     for (Iterator iterator = minSet.iterator(); iterator.hasNext();) {
419       MethodInvokeNode min = (MethodInvokeNode) iterator.next();
420       // need to translate a composite location that is started with the base
421       // tuple of 'min'.
422       translateMapLocationToInferCompositeLocationToCalleeGraph(callerGlobalFlowGraph, min);
423       calleeSet.add(min.getMethod());
424     }
425
426     for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
427       MethodDescriptor callee = (MethodDescriptor) iterator.next();
428       translateCompositeLocationAssignmentToFlowGraph(callee);
429     }
430
431   }
432
433   public void assignCompositeLocationToFlowGraph(FlowGraph flowGraph, Location loc,
434       CompositeLocation inferCompLoc) {
435     Descriptor localDesc = loc.getLocDescriptor();
436
437     Set<FlowNode> nodeSet = flowGraph.getNodeSet();
438     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
439       FlowNode node = (FlowNode) iterator.next();
440       if (node.getDescTuple().startsWith(localDesc)
441           && !node.getDescTuple().get(0).equals(LITERALDESC)) {
442         // need to assign the inferred composite location to this node
443         CompositeLocation newCompLoc = generateCompositeLocation(node.getDescTuple(), inferCompLoc);
444         node.setCompositeLocation(newCompLoc);
445         System.out.println("SET Node=" + node + "  inferCompLoc=" + newCompLoc);
446       }
447     }
448   }
449
450   private CompositeLocation generateCompositeLocation(NTuple<Descriptor> nodeDescTuple,
451       CompositeLocation inferCompLoc) {
452
453     System.out.println("generateCompositeLocation=" + nodeDescTuple + " with inferCompLoc="
454         + inferCompLoc);
455
456     CompositeLocation newCompLoc = new CompositeLocation();
457     for (int i = 0; i < inferCompLoc.getSize(); i++) {
458       newCompLoc.addLocation(inferCompLoc.get(i));
459     }
460
461     Descriptor lastDescOfPrefix = nodeDescTuple.get(0);
462     Descriptor enclosingDescriptor;
463     if (lastDescOfPrefix instanceof InterDescriptor) {
464       enclosingDescriptor = null;
465     } else {
466       enclosingDescriptor = ((VarDescriptor) lastDescOfPrefix).getType().getClassDesc();
467     }
468
469     for (int i = 1; i < nodeDescTuple.size(); i++) {
470       Descriptor desc = nodeDescTuple.get(i);
471       Location locElement = new Location(enclosingDescriptor, desc);
472       newCompLoc.addLocation(locElement);
473
474       enclosingDescriptor = ((FieldDescriptor) desc).getClassDescriptor();
475     }
476
477     return newCompLoc;
478   }
479
480   private void translateMapLocationToInferCompositeLocationToCalleeGraph(
481       GlobalFlowGraph callerGraph, MethodInvokeNode min) {
482
483     MethodDescriptor mdCallee = min.getMethod();
484     MethodDescriptor mdCaller = callerGraph.getMethodDescriptor();
485     Map<Location, CompositeLocation> callerMapLocToCompLoc =
486         callerGraph.getMapLocationToInferCompositeLocation();
487
488     Map<Integer, NTuple<Descriptor>> mapIdxToArgTuple = mapMethodInvokeNodeToArgIdxMap.get(min);
489
490     FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
491     GlobalFlowGraph calleeGlobalGraph = getSubGlobalFlowGraph(mdCallee);
492
493     NTuple<Location> baseLocTuple = null;
494     if (mapMethodInvokeNodeToBaseTuple.containsKey(min)) {
495       baseLocTuple = translateToLocTuple(mdCaller, mapMethodInvokeNodeToBaseTuple.get(min));
496     }
497
498     System.out.println("\n-#translate caller=" + mdCaller + " infer composite loc to callee="
499         + mdCallee + " baseLocTuple=" + baseLocTuple);
500     // System.out.println("-mapIdxToArgTuple=" + mapIdxToArgTuple);
501     // System.out.println("-callerMapLocToCompLoc=" + callerMapLocToCompLoc);
502
503     Set<Location> keySet = callerMapLocToCompLoc.keySet();
504     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
505       Location key = (Location) iterator.next();
506       CompositeLocation callerCompLoc = callerMapLocToCompLoc.get(key);
507
508       if (!key.getDescriptor().equals(mdCaller)) {
509
510         CompositeLocation newCalleeCompLoc;
511         if (baseLocTuple != null && callerCompLoc.getTuple().startsWith(baseLocTuple)) {
512           // System.out.println("-----need to translate callerCompLoc=" + callerCompLoc
513           // + " with baseTuple=" + baseLocTuple);
514           newCalleeCompLoc =
515               translateCompositeLocationToCallee(callerCompLoc, baseLocTuple, mdCallee);
516
517           calleeGlobalGraph.addMapLocationToInferCompositeLocation(key, newCalleeCompLoc);
518           System.out.println("---key=" + key + "  callerCompLoc=" + callerCompLoc
519               + "  newCalleeCompLoc=" + newCalleeCompLoc);
520           System.out.println("-----baseLoctuple=" + baseLocTuple);
521           System.out.println("-----caller=" + mdCaller + "    callee=" + mdCallee);
522         } else {
523           System.out.println("2");
524           // check if it is the global access
525           Location compLocFirstElement = callerCompLoc.getTuple().get(0);
526           if (compLocFirstElement.getDescriptor().equals(mdCallee)
527               && compLocFirstElement.getLocDescriptor().equals(GLOBALDESC)) {
528
529             newCalleeCompLoc = new CompositeLocation();
530             Location newMethodLoc = new Location(mdCallee, GLOBALDESC);
531
532             newCalleeCompLoc.addLocation(newMethodLoc);
533             for (int i = 1; i < callerCompLoc.getSize(); i++) {
534               newCalleeCompLoc.addLocation(callerCompLoc.get(i));
535             }
536             calleeGlobalGraph.addMapLocationToInferCompositeLocation(key, newCalleeCompLoc);
537             System.out.println("---key=" + key + "  callerCompLoc=" + callerCompLoc
538                 + "  newCalleeCompLoc=" + newCalleeCompLoc);
539             System.out.println("-----caller=" + mdCaller + "    callee=" + mdCallee);
540
541           } else {
542             int paramIdx = getParamIdx(callerCompLoc, mapIdxToArgTuple);
543             if (paramIdx == -1) {
544               continue;
545             }
546             NTuple<Descriptor> argTuple = mapIdxToArgTuple.get(paramIdx);
547
548             FlowNode paramFlowNode = calleeFlowGraph.getParamFlowNode(paramIdx);
549             System.out.println("-----paramIdx=" + paramIdx + "  paramFlowNode=" + paramFlowNode);
550             NTuple<Location> paramLocTuple =
551                 translateToLocTuple(mdCallee, paramFlowNode.getDescTuple());
552             newCalleeCompLoc = new CompositeLocation();
553             for (int i = 0; i < paramLocTuple.size(); i++) {
554               newCalleeCompLoc.addLocation(paramLocTuple.get(i));
555             }
556             for (int i = argTuple.size(); i < callerCompLoc.getSize(); i++) {
557               newCalleeCompLoc.addLocation(callerCompLoc.get(i));
558             }
559             calleeGlobalGraph.addMapLocationToInferCompositeLocation(key, newCalleeCompLoc);
560             System.out.println("---key=" + key + "  callerCompLoc=" + callerCompLoc
561                 + "  newCalleeCompLoc=" + newCalleeCompLoc);
562             System.out.println("------argTuple=" + argTuple);
563             System.out.println("-----caller=" + mdCaller + "    callee=" + mdCallee);
564
565           }
566
567         }
568
569       }
570     }
571
572     // System.out.println("-----*AFTER TRANSLATING COMP LOC MAPPING, CALLEE MAPPING="
573     // + calleeGlobalGraph.getMapLocationToInferCompositeLocation());
574
575     // If the location of an argument has a composite location
576     // need to assign a proper composite location to the corresponding callee parameter
577     // System.out.println("---translate arg composite location to callee param. min="
578     // + min.printNode(0));
579     Set<Integer> idxSet = mapIdxToArgTuple.keySet();
580     for (Iterator iterator = idxSet.iterator(); iterator.hasNext();) {
581       Integer idx = (Integer) iterator.next();
582
583       if (idx == 0 && !min.getMethod().isStatic()) {
584         continue;
585       }
586
587       NTuple<Descriptor> argTuple = mapIdxToArgTuple.get(idx);
588       if (argTuple.size() > 0) {
589         // check if an arg tuple has been already assigned to a composite location
590         NTuple<Location> argLocTuple = translateToLocTuple(mdCaller, argTuple);
591         Location argLocalLoc = argLocTuple.get(0);
592
593         // if (!isPrimitiveType(argTuple)) {
594         if (callerMapLocToCompLoc.containsKey(argLocalLoc)) {
595
596           CompositeLocation callerCompLoc = callerMapLocToCompLoc.get(argLocalLoc);
597           for (int i = 1; i < argLocTuple.size(); i++) {
598             callerCompLoc.addLocation(argLocTuple.get(i));
599           }
600
601           if (baseLocTuple != null && callerCompLoc.getTuple().startsWith(baseLocTuple)) {
602
603             FlowNode calleeParamFlowNode = calleeFlowGraph.getParamFlowNode(idx);
604             NTuple<Descriptor> calleeParamDescTuple = calleeParamFlowNode.getDescTuple();
605             NTuple<Location> calleeParamLocTuple =
606                 translateToLocTuple(mdCallee, calleeParamDescTuple);
607
608             System.out.println("---need to translate callerCompLoc=" + callerCompLoc
609                 + " with baseTuple=" + baseLocTuple + "   calleeParamLocTuple="
610                 + calleeParamLocTuple);
611
612             CompositeLocation newCalleeCompLoc =
613                 translateCompositeLocationToCallee(callerCompLoc, baseLocTuple, mdCallee);
614
615             calleeGlobalGraph.addMapLocationToInferCompositeLocation(calleeParamLocTuple.get(0),
616                 newCalleeCompLoc);
617
618             System.out.println("---callee loc=" + calleeParamLocTuple.get(0)
619                 + "  newCalleeCompLoc=" + newCalleeCompLoc);
620
621             // System.out.println("###need to assign composite location to=" + calleeParamDescTuple
622             // + " with baseTuple=" + baseLocTuple);
623           }
624
625         }
626       }
627
628     }
629
630   }
631
632   private int getParamIdx(CompositeLocation compLoc,
633       Map<Integer, NTuple<Descriptor>> mapIdxToArgTuple) {
634
635     // if the composite location is started with the argument descriptor
636     // return the argument's index. o.t. return -1
637
638     Set<Integer> keySet = mapIdxToArgTuple.keySet();
639     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
640       Integer key = (Integer) iterator.next();
641       NTuple<Descriptor> argTuple = mapIdxToArgTuple.get(key);
642       if (translateToDescTuple(compLoc.getTuple()).startsWith(argTuple)) {
643         return key.intValue();
644       }
645     }
646
647     return -1;
648   }
649
650   private boolean isPrimitiveType(NTuple<Descriptor> argTuple) {
651
652     Descriptor lastDesc = argTuple.get(argTuple.size() - 1);
653
654     if (lastDesc instanceof FieldDescriptor) {
655       return ((FieldDescriptor) lastDesc).getType().isPrimitive();
656     } else if (lastDesc instanceof VarDescriptor) {
657       return ((VarDescriptor) lastDesc).getType().isPrimitive();
658     } else if (lastDesc instanceof InterDescriptor) {
659       return true;
660     }
661
662     return false;
663   }
664
665   private CompositeLocation translateCompositeLocationToCallee(CompositeLocation callerCompLoc,
666       NTuple<Location> baseLocTuple, MethodDescriptor mdCallee) {
667
668     CompositeLocation newCalleeCompLoc = new CompositeLocation();
669
670     Location calleeThisLoc = new Location(mdCallee, mdCallee.getThis());
671     newCalleeCompLoc.addLocation(calleeThisLoc);
672
673     // remove the base tuple from the caller
674     // ex; In the method invoation foo.bar.methodA(), the callee will have the composite location
675     // ,which is relative to the 'this' variable, <THIS,...>
676     for (int i = baseLocTuple.size(); i < callerCompLoc.getSize(); i++) {
677       newCalleeCompLoc.addLocation(callerCompLoc.get(i));
678     }
679
680     return newCalleeCompLoc;
681
682   }
683
684   private void calculateGlobalValueFlowCompositeLocation() {
685
686     System.out.println("SSJAVA: Calculate composite locations in the global value flow graph");
687     MethodDescriptor methodDescEventLoop = ssjava.getMethodContainingSSJavaLoop();
688     GlobalFlowGraph globalFlowGraph = getSubGlobalFlowGraph(methodDescEventLoop);
689
690     Set<Location> calculatedPrefixSet = new HashSet<Location>();
691
692     Set<GlobalFlowNode> nodeSet = globalFlowGraph.getNodeSet();
693
694     next: for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
695       GlobalFlowNode node = (GlobalFlowNode) iterator.next();
696
697       Location prefixLoc = node.getLocTuple().get(0);
698
699       if (calculatedPrefixSet.contains(prefixLoc)) {
700         // the prefix loc has been already assigned to a composite location
701         continue;
702       }
703
704       calculatedPrefixSet.add(prefixLoc);
705
706       // Set<GlobalFlowNode> incomingNodeSet = globalFlowGraph.getIncomingNodeSet(node);
707       List<NTuple<Location>> prefixList = calculatePrefixList(globalFlowGraph, node);
708
709       Set<GlobalFlowNode> reachableNodeSet =
710           globalFlowGraph.getReachableNodeSetByPrefix(node.getLocTuple().get(0));
711       // Set<GlobalFlowNode> reachNodeSet = globalFlowGraph.getReachableNodeSetFrom(node);
712
713       // System.out.println("node=" + node + "    prefixList=" + prefixList + "   reachableNodeSet="
714       // + reachableNodeSet);
715
716       for (int i = 0; i < prefixList.size(); i++) {
717         NTuple<Location> curPrefix = prefixList.get(i);
718         Set<NTuple<Location>> reachableCommonPrefixSet = new HashSet<NTuple<Location>>();
719
720         for (Iterator iterator2 = reachableNodeSet.iterator(); iterator2.hasNext();) {
721           GlobalFlowNode reachNode = (GlobalFlowNode) iterator2.next();
722           if (reachNode.getLocTuple().startsWith(curPrefix)) {
723             reachableCommonPrefixSet.add(reachNode.getLocTuple());
724           }
725         }
726
727         if (!reachableCommonPrefixSet.isEmpty()) {
728
729           MethodDescriptor curPrefixFirstElementMethodDesc =
730               (MethodDescriptor) curPrefix.get(0).getDescriptor();
731
732           MethodDescriptor nodePrefixLocFirstElementMethodDesc =
733               (MethodDescriptor) prefixLoc.getDescriptor();
734
735           if (curPrefixFirstElementMethodDesc.equals(nodePrefixLocFirstElementMethodDesc)
736               || isTransitivelyCalledFrom(nodePrefixLocFirstElementMethodDesc,
737                   curPrefixFirstElementMethodDesc)) {
738
739             // TODO
740             // if (!node.getLocTuple().startsWith(curPrefix.get(0))) {
741
742             Location curPrefixLocalLoc = curPrefix.get(0);
743             if (globalFlowGraph.mapLocationToInferCompositeLocation.containsKey(curPrefixLocalLoc)) {
744               // in this case, the local variable of the current prefix has already got a composite
745               // location
746               // so we just ignore the current composite location.
747
748               // System.out.println("HERE WE DO NOT ASSIGN A COMPOSITE LOCATION TO =" + node
749               // + " DUE TO " + curPrefix);
750
751               continue next;
752             }
753
754             Location targetLocalLoc = node.getLocTuple().get(0);
755             // CompositeLocation curCompLoc = globalFlowGraph.getCompositeLocation(targetLocalLoc);
756             // if ((curPrefix.size() + 1) > curCompLoc.getSize()) {
757
758             CompositeLocation newCompLoc = generateCompositeLocation(curPrefix);
759             System.out.println("NEED TO ASSIGN COMP LOC TO " + node + " with prefix=" + curPrefix);
760             System.out.println("- newCompLoc=" + newCompLoc);
761             globalFlowGraph.addMapLocationToInferCompositeLocation(targetLocalLoc, newCompLoc);
762             // }
763
764             continue next;
765             // }
766
767           }
768
769         }
770
771       }
772
773     }
774     // Set<GlobalFlowNode> inNodeSet =
775     // graph.getIncomingNodeSetWithPrefix(prefix);
776     // System.out.println("inNodeSet=" + inNodeSet + "  from=" + node);
777   }
778
779   private void assignCompositeLocation(CompositeLocation compLocPrefix, GlobalFlowNode node) {
780     CompositeLocation newCompLoc = compLocPrefix.clone();
781     NTuple<Location> locTuple = node.getLocTuple();
782     for (int i = 1; i < locTuple.size(); i++) {
783       newCompLoc.addLocation(locTuple.get(i));
784     }
785     node.setInferCompositeLocation(newCompLoc);
786   }
787
788   private List<NTuple<Location>> calculatePrefixList(GlobalFlowGraph graph, GlobalFlowNode node) {
789
790     System.out.println("\n##### calculatePrefixList node=" + node);
791
792     Set<GlobalFlowNode> incomingNodeSetPrefix =
793         graph.getIncomingNodeSetByPrefix(node.getLocTuple().get(0));
794     // System.out.println("incomingNodeSetPrefix=" + incomingNodeSetPrefix);
795     //
796     // Set<GlobalFlowNode> reachableNodeSetPrefix =
797     // graph.getReachableNodeSetByPrefix(node.getLocTuple().get(0));
798     // System.out.println("reachableNodeSetPrefix=" + reachableNodeSetPrefix);
799
800     List<NTuple<Location>> prefixList = new ArrayList<NTuple<Location>>();
801
802     for (Iterator iterator = incomingNodeSetPrefix.iterator(); iterator.hasNext();) {
803       GlobalFlowNode inNode = (GlobalFlowNode) iterator.next();
804       NTuple<Location> inNodeTuple = inNode.getLocTuple();
805
806       for (int i = 1; i < inNodeTuple.size(); i++) {
807         NTuple<Location> prefix = inNodeTuple.subList(0, i);
808         if (!prefixList.contains(prefix)) {
809           prefixList.add(prefix);
810         }
811       }
812     }
813
814     Collections.sort(prefixList, new Comparator<NTuple<Location>>() {
815       public int compare(NTuple<Location> arg0, NTuple<Location> arg1) {
816         int s0 = arg0.size();
817         int s1 = arg1.size();
818         if (s0 > s1) {
819           return -1;
820         } else if (s0 == s1) {
821           return 0;
822         } else {
823           return 1;
824         }
825       }
826     });
827
828     // remove a prefix which is not suitable for generating composite location
829     Location localVarLoc = node.getLocTuple().get(0);
830     MethodDescriptor md = (MethodDescriptor) localVarLoc.getDescriptor();
831     ClassDescriptor cd = md.getClassDesc();
832
833     int idx = 0;
834
835     Set<NTuple<Location>> toberemoved = new HashSet<NTuple<Location>>();
836     for (int i = 0; i < prefixList.size(); i++) {
837       NTuple<Location> prefixLocTuple = prefixList.get(i);
838       if (!containsClassDesc(cd, prefixLocTuple)) {
839         toberemoved.add(prefixLocTuple);
840       }
841     }
842
843     prefixList.removeAll(toberemoved);
844
845     return prefixList;
846
847     // List<NTuple<Location>> prefixList = new ArrayList<NTuple<Location>>();
848     //
849     // for (Iterator iterator = incomingNodeSet.iterator(); iterator.hasNext();) {
850     // GlobalFlowNode inNode = (GlobalFlowNode) iterator.next();
851     // NTuple<Location> inNodeTuple = inNode.getLocTuple();
852     //
853     // for (int i = 1; i < inNodeTuple.size(); i++) {
854     // NTuple<Location> prefix = inNodeTuple.subList(0, i);
855     // if (!prefixList.contains(prefix)) {
856     // prefixList.add(prefix);
857     // }
858     // }
859     // }
860     //
861     // Collections.sort(prefixList, new Comparator<NTuple<Location>>() {
862     // public int compare(NTuple<Location> arg0, NTuple<Location> arg1) {
863     // int s0 = arg0.size();
864     // int s1 = arg1.size();
865     // if (s0 > s1) {
866     // return -1;
867     // } else if (s0 == s1) {
868     // return 0;
869     // } else {
870     // return 1;
871     // }
872     // }
873     // });
874     // return prefixList;
875   }
876
877   private boolean containsClassDesc(ClassDescriptor cd, NTuple<Location> prefixLocTuple) {
878     for (int i = 0; i < prefixLocTuple.size(); i++) {
879       Location loc = prefixLocTuple.get(i);
880       Descriptor locDesc = loc.getLocDescriptor();
881       if (locDesc != null) {
882         ClassDescriptor type = getClassTypeDescriptor(locDesc);
883         if (type != null && type.equals(cd)) {
884           return true;
885         }
886       }
887     }
888     return false;
889   }
890
891   private GlobalFlowGraph constructSubGlobalFlowGraph(FlowGraph flowGraph) {
892
893     MethodDescriptor md = flowGraph.getMethodDescriptor();
894
895     GlobalFlowGraph globalGraph = new GlobalFlowGraph(md);
896
897     // Set<FlowNode> nodeSet = flowGraph.getNodeSet();
898     Set<FlowEdge> edgeSet = flowGraph.getEdgeSet();
899
900     for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) {
901
902       FlowEdge edge = (FlowEdge) iterator.next();
903       NTuple<Descriptor> srcDescTuple = edge.getInitTuple();
904       NTuple<Descriptor> dstDescTuple = edge.getEndTuple();
905
906       // here only keep the first element(method location) of the descriptor
907       // tuple
908       NTuple<Location> srcLocTuple = translateToLocTuple(md, srcDescTuple);
909       // Location srcMethodLoc = srcLocTuple.get(0);
910       // Descriptor srcVarDesc = srcMethodLoc.getLocDescriptor();
911       // // if (flowGraph.isParamDesc(srcVarDesc) &&
912       // (!srcVarDesc.equals(md.getThis()))) {
913       // if (!srcVarDesc.equals(md.getThis())) {
914       // srcLocTuple = new NTuple<Location>();
915       // Location loc = new Location(md, srcVarDesc);
916       // srcLocTuple.add(loc);
917       // }
918       //
919       NTuple<Location> dstLocTuple = translateToLocTuple(md, dstDescTuple);
920       // Location dstMethodLoc = dstLocTuple.get(0);
921       // Descriptor dstVarDesc = dstMethodLoc.getLocDescriptor();
922       // if (!dstVarDesc.equals(md.getThis())) {
923       // dstLocTuple = new NTuple<Location>();
924       // Location loc = new Location(md, dstVarDesc);
925       // dstLocTuple.add(loc);
926       // }
927
928       globalGraph.addValueFlowEdge(srcLocTuple, dstLocTuple);
929
930     }
931
932     return globalGraph;
933   }
934
935   private NTuple<Location> translateToLocTuple(MethodDescriptor md, NTuple<Descriptor> descTuple) {
936
937     NTuple<Location> locTuple = new NTuple<Location>();
938
939     Descriptor enclosingDesc = md;
940     // System.out.println("md=" + md + "  descTuple=" + descTuple);
941     for (int i = 0; i < descTuple.size(); i++) {
942       Descriptor desc = descTuple.get(i);
943
944       Location loc = new Location(enclosingDesc, desc);
945       locTuple.add(loc);
946
947       if (desc instanceof VarDescriptor) {
948         enclosingDesc = ((VarDescriptor) desc).getType().getClassDesc();
949       } else if (desc instanceof FieldDescriptor) {
950         enclosingDesc = ((FieldDescriptor) desc).getType().getClassDesc();
951       } else {
952         // TODO: inter descriptor case
953         enclosingDesc = desc;
954       }
955
956     }
957
958     return locTuple;
959
960   }
961
962   private void addValueFlowsFromCalleeSubGlobalFlowGraph(MethodDescriptor mdCaller,
963       GlobalFlowGraph subGlobalFlowGraph) {
964
965     // the transformation for a call site propagates flows through parameters
966     // if the method is virtual, it also grab all relations from any possible
967     // callees
968
969     Set<MethodInvokeNode> setMethodInvokeNode = getMethodInvokeNodeSet(mdCaller);
970
971     for (Iterator iterator = setMethodInvokeNode.iterator(); iterator.hasNext();) {
972       MethodInvokeNode min = (MethodInvokeNode) iterator.next();
973       MethodDescriptor mdCallee = min.getMethod();
974       Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
975       if (mdCallee.isStatic()) {
976         setPossibleCallees.add(mdCallee);
977       } else {
978         Set<MethodDescriptor> calleeSet = ssjava.getCallGraph().getMethods(mdCallee);
979         // removes method descriptors that are not invoked by the caller
980         calleeSet.retainAll(mapMethodToCalleeSet.get(mdCaller));
981         setPossibleCallees.addAll(calleeSet);
982       }
983
984       for (Iterator iterator2 = setPossibleCallees.iterator(); iterator2.hasNext();) {
985         MethodDescriptor possibleMdCallee = (MethodDescriptor) iterator2.next();
986         propagateValueFlowsToCallerFromSubGlobalFlowGraph(min, mdCaller, possibleMdCallee);
987       }
988
989     }
990
991   }
992
993   private void propagateValueFlowsToCallerFromSubGlobalFlowGraph(MethodInvokeNode min,
994       MethodDescriptor mdCaller, MethodDescriptor possibleMdCallee) {
995
996     System.out.println("---propagate from " + min.printNode(0) + " to caller=" + mdCaller);
997     FlowGraph calleeFlowGraph = getFlowGraph(possibleMdCallee);
998     Map<Integer, NTuple<Descriptor>> mapIdxToArg = mapMethodInvokeNodeToArgIdxMap.get(min);
999
1000     System.out.println("-----mapMethodInvokeNodeToArgIdxMap.get(min)="
1001         + mapMethodInvokeNodeToArgIdxMap.get(min));
1002     Set<Integer> keySet = mapIdxToArg.keySet();
1003     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1004       Integer idx = (Integer) iterator.next();
1005       NTuple<Descriptor> argDescTuple = mapIdxToArg.get(idx);
1006       if (argDescTuple.size() > 0) {
1007         NTuple<Location> argLocTuple = translateToLocTuple(mdCaller, argDescTuple);
1008         NTuple<Descriptor> paramDescTuple = calleeFlowGraph.getParamFlowNode(idx).getDescTuple();
1009         NTuple<Location> paramLocTuple = translateToLocTuple(possibleMdCallee, paramDescTuple);
1010         addMapCallerArgToCalleeParam(min, argDescTuple, paramDescTuple);
1011       }
1012     }
1013
1014     NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
1015     GlobalFlowGraph calleeSubGlobalGraph = getSubGlobalFlowGraph(possibleMdCallee);
1016     Set<GlobalFlowNode> calleeNodeSet = calleeSubGlobalGraph.getNodeSet();
1017     for (Iterator iterator = calleeNodeSet.iterator(); iterator.hasNext();) {
1018       GlobalFlowNode calleeNode = (GlobalFlowNode) iterator.next();
1019       addValueFlowFromCalleeNode(min, mdCaller, possibleMdCallee, calleeNode);
1020     }
1021
1022     // int numParam = calleeFlowGraph.getNumParameters();
1023     // for (int idx = 0; idx < numParam; idx++) {
1024     //
1025     // FlowNode paramNode = calleeFlowGraph.getParamFlowNode(idx);
1026     //
1027     // NTuple<Location> paramLocTuple =
1028     // translateToLocTuple(possibleMdCallee, paramNode.getCurrentDescTuple());
1029     //
1030     // GlobalFlowNode globalParamNode =
1031     // calleeSubGlobalGraph.getFlowNode(paramLocTuple);
1032     //
1033     // NTuple<Descriptor> argTuple =
1034     // mapMethodInvokeNodeToArgIdxMap.get(min).get(idx);
1035     //
1036     // NTuple<Location> argLocTuple = translateToLocTuple(mdCaller, argTuple);
1037     //
1038     // System.out.println("argTupleSet=" + argLocTuple + "   param=" +
1039     // paramLocTuple);
1040     // // here, it adds all value flows reachable from the paramNode in the
1041     // callee's flow graph
1042     //
1043     // addValueFlowsFromCalleeParam(mdCaller, argLocTuple, baseLocTuple,
1044     // possibleMdCallee,
1045     // globalParamNode);
1046     // }
1047     //
1048     // // TODO
1049     // // FlowGraph callerSubGlobalGraph = getSubGlobalFlowGraph(mdCaller);
1050     // // FlowGraph calleeSubGlobalGraph =
1051     // getSubGlobalFlowGraph(possibleMdCallee);
1052     // //
1053     // // int numParam = calleeSubGlobalGraph.getNumParameters();
1054     // // for (int idx = 0; idx < numParam; idx++) {
1055     // // FlowNode paramNode = calleeSubGlobalGraph.getParamFlowNode(idx);
1056     // // NTuple<Descriptor> argTuple =
1057     // mapMethodInvokeNodeToArgIdxMap.get(min).get(idx);
1058     // // System.out.println("argTupleSet=" + argTuple + "   param=" +
1059     // paramNode);
1060     // // // here, it adds all value flows reachable from the paramNode in the
1061     // callee's flow graph
1062     // // addValueFlowsFromCalleeParam(min, calleeSubGlobalGraph, paramNode,
1063     // callerSubGlobalGraph,
1064     // // argTuple, baseTuple);
1065     // // }
1066
1067   }
1068
1069   private void addValueFlowFromCalleeNode(MethodInvokeNode min, MethodDescriptor mdCaller,
1070       MethodDescriptor mdCallee, GlobalFlowNode calleeSrcNode) {
1071
1072     GlobalFlowGraph calleeSubGlobalGraph = getSubGlobalFlowGraph(mdCallee);
1073     GlobalFlowGraph callerSubGlobalGraph = getSubGlobalFlowGraph(mdCaller);
1074
1075     NTuple<Location> callerSrcNodeLocTuple =
1076         translateToCallerLocTuple(min, mdCallee, mdCaller, calleeSrcNode.getLocTuple());
1077
1078     if (callerSrcNodeLocTuple != null) {
1079       Set<GlobalFlowNode> outNodeSet = calleeSubGlobalGraph.getOutNodeSet(calleeSrcNode);
1080
1081       for (Iterator iterator = outNodeSet.iterator(); iterator.hasNext();) {
1082         GlobalFlowNode outNode = (GlobalFlowNode) iterator.next();
1083         NTuple<Location> callerDstNodeLocTuple =
1084             translateToCallerLocTuple(min, mdCallee, mdCaller, outNode.getLocTuple());
1085         if (callerDstNodeLocTuple != null) {
1086           callerSubGlobalGraph.addValueFlowEdge(callerSrcNodeLocTuple, callerDstNodeLocTuple);
1087         }
1088       }
1089     }
1090
1091   }
1092
1093   private NTuple<Location> translateToCallerLocTuple(MethodInvokeNode min,
1094       MethodDescriptor mdCallee, MethodDescriptor mdCaller, NTuple<Location> nodeLocTuple) {
1095     // this method will return the same nodeLocTuple if the corresponding argument is literal
1096     // value.
1097
1098     FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
1099
1100     NTuple<Descriptor> nodeDescTuple = translateToDescTuple(nodeLocTuple);
1101     if (calleeFlowGraph.isParameter(nodeDescTuple)) {
1102       int paramIdx = calleeFlowGraph.getParamIdx(nodeDescTuple);
1103       NTuple<Descriptor> argDescTuple = mapMethodInvokeNodeToArgIdxMap.get(min).get(paramIdx);
1104
1105       if (isPrimitive(nodeLocTuple.get(0).getLocDescriptor())) {
1106         // the type of argument is primitive.
1107         return nodeLocTuple.clone();
1108       }
1109       NTuple<Location> argLocTuple = translateToLocTuple(mdCaller, argDescTuple);
1110
1111       NTuple<Location> callerLocTuple = new NTuple<Location>();
1112
1113       callerLocTuple.addAll(argLocTuple);
1114       for (int i = 1; i < nodeLocTuple.size(); i++) {
1115         callerLocTuple.add(nodeLocTuple.get(i));
1116       }
1117       return callerLocTuple;
1118     } else {
1119       return nodeLocTuple.clone();
1120     }
1121
1122   }
1123
1124   public static boolean isPrimitive(Descriptor desc) {
1125
1126     if (desc instanceof FieldDescriptor) {
1127       return ((FieldDescriptor) desc).getType().isPrimitive();
1128     } else if (desc instanceof VarDescriptor) {
1129       return ((VarDescriptor) desc).getType().isPrimitive();
1130     } else if (desc instanceof InterDescriptor) {
1131       return true;
1132     }
1133
1134     return false;
1135   }
1136
1137   private NTuple<Descriptor> translateToDescTuple(NTuple<Location> locTuple) {
1138
1139     NTuple<Descriptor> descTuple = new NTuple<Descriptor>();
1140     for (int i = 0; i < locTuple.size(); i++) {
1141       descTuple.add(locTuple.get(i).getLocDescriptor());
1142     }
1143     return descTuple;
1144
1145   }
1146
1147   private void addValueFlowsFromCalleeParam(MethodDescriptor mdCaller,
1148       NTuple<Location> argLocTuple, NTuple<Location> baseLocTuple, MethodDescriptor mdCallee,
1149       GlobalFlowNode globalParamNode) {
1150
1151     Set<GlobalFlowNode> visited = new HashSet<GlobalFlowNode>();
1152     visited.add(globalParamNode);
1153     recurAddValueFlowsFromCalleeParam(mdCaller, argLocTuple, baseLocTuple, mdCallee,
1154         globalParamNode);
1155
1156   }
1157
1158   private void recurAddValueFlowsFromCalleeParam(MethodDescriptor mdCaller,
1159       NTuple<Location> argLocTuple, NTuple<Location> baseLocTuple, MethodDescriptor mdCallee,
1160       GlobalFlowNode calleeCurNode) {
1161
1162     // FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
1163     // GlobalFlowGraph calleeSubGlobalGraph = getSubGlobalFlowGraph(mdCallee);
1164     //
1165     // NTuple<Location> curNodeLocTuple = calleeCurNode.getLocTuple();
1166     // NTuple<Descriptor> curNodeDescTuple = calleeCurNode.getDescTuple();
1167     // if (calleeFlowGraph.isParameter(curNodeDescTuple)) {
1168     // curNodeLocTuple = translateToCaller(argLocTuple, curNodeLocTuple);
1169     // }
1170     //
1171     // Set<GlobalFlowNode> outNodeSet =
1172     // calleeSubGlobalGraph.getOutNodeSet(calleeCurNode);
1173     // for (Iterator iterator = outNodeSet.iterator(); iterator.hasNext();) {
1174     // GlobalFlowNode outNode = (GlobalFlowNode) iterator.next();
1175     //
1176     // NTuple<Location> curNodeLocTuple = calleeCurNode.getLocTuple();
1177     // NTuple<Descriptor> curNodeDescTuple = calleeCurNode.getDescTuple();
1178     // if (calleeFlowGraph.isParameter(curNodeDescTuple)) {
1179     // curNodeLocTuple = translateToCaller(argLocTuple, curNodeLocTuple);
1180     // }
1181     //
1182     // outNode.getDescTuple();
1183     //
1184     // if (calleeFlowGraph.is)
1185     //
1186     // if (calleeSubGlobalGraph.isParameter(srcDescTuple)) {
1187     // // destination node is started with 'parameter'
1188     // // need to translate it in terms of the caller's a node
1189     // srcDescTuple =
1190     // translateToCaller(min, calleeSubGlobalGraph.getParamIdx(srcDescTuple),
1191     // srcDescTuple);
1192     // }
1193     //
1194     // }
1195     //
1196     // Set<FlowEdge> edgeSet =
1197     // calleeSubGlobalGraph.getOutEdgeSetStartingFrom(calleeSrcNode);
1198     // for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) {
1199     // FlowEdge flowEdge = (FlowEdge) iterator.next();
1200     //
1201     // NTuple<Descriptor> srcDescTuple = flowEdge.getInitTuple();
1202     // NTuple<Descriptor> dstDescTuple = flowEdge.getEndTuple();
1203     //
1204     // FlowNode dstNode = calleeSubGlobalGraph.getFlowNode(dstDescTuple);
1205     //
1206     // if (calleeSubGlobalGraph.isParameter(srcDescTuple)) {
1207     // // destination node is started with 'parameter'
1208     // // need to translate it in terms of the caller's a node
1209     // srcDescTuple =
1210     // translateToCaller(min, calleeSubGlobalGraph.getParamIdx(srcDescTuple),
1211     // srcDescTuple);
1212     // }
1213     //
1214     // if (calleeSubGlobalGraph.isParameter(dstDescTuple)) {
1215     // // destination node is started with 'parameter'
1216     // // need to translate it in terms of the caller's a node
1217     // dstDescTuple =
1218     // translateToCaller(min, calleeSubGlobalGraph.getParamIdx(dstDescTuple),
1219     // dstDescTuple);
1220     // }
1221     //
1222     // callerSubGlobalGraph.addValueFlowEdge(srcDescTuple, dstDescTuple);
1223     //
1224     // if (!visited.contains(dstNode)) {
1225     // visited.add(dstNode);
1226     // recurAddValueFlowsFromCalleeParam(min, calleeSubGlobalGraph, dstNode,
1227     // callerSubGlobalGraph,
1228     // dstDescTuple, visited, baseTuple);
1229     // }
1230     //
1231     // }
1232
1233   }
1234
1235   private NTuple<Location> translateToCaller(NTuple<Location> argLocTuple,
1236       NTuple<Location> curNodeLocTuple) {
1237
1238     NTuple<Location> callerLocTuple = new NTuple<Location>();
1239
1240     callerLocTuple.addAll(argLocTuple);
1241     for (int i = 1; i < curNodeLocTuple.size(); i++) {
1242       callerLocTuple.add(curNodeLocTuple.get(i));
1243     }
1244
1245     return callerLocTuple;
1246   }
1247
1248   private void recurAddValueFlowsFromCalleeParam(MethodInvokeNode min,
1249       FlowGraph calleeSubGlobalGraph, FlowNode calleeSrcNode, FlowGraph callerSubGlobalGraph,
1250       NTuple<Descriptor> callerSrcTuple, Set<FlowNode> visited, NTuple<Descriptor> baseTuple) {
1251
1252     MethodDescriptor mdCallee = calleeSubGlobalGraph.getMethodDescriptor();
1253
1254     // Set<FlowEdge> edgeSet =
1255     // calleeSubGlobalGraph.getOutEdgeSet(calleeSrcNode);
1256     Set<FlowEdge> edgeSet = calleeSubGlobalGraph.getOutEdgeSetStartingFrom(calleeSrcNode);
1257     for (Iterator iterator = edgeSet.iterator(); iterator.hasNext();) {
1258       FlowEdge flowEdge = (FlowEdge) iterator.next();
1259
1260       NTuple<Descriptor> srcDescTuple = flowEdge.getInitTuple();
1261       NTuple<Descriptor> dstDescTuple = flowEdge.getEndTuple();
1262
1263       FlowNode dstNode = calleeSubGlobalGraph.getFlowNode(dstDescTuple);
1264
1265       if (calleeSubGlobalGraph.isParameter(srcDescTuple)) {
1266         // destination node is started with 'parameter'
1267         // need to translate it in terms of the caller's a node
1268         srcDescTuple =
1269             translateToCaller(min, calleeSubGlobalGraph.getParamIdx(srcDescTuple), srcDescTuple);
1270       }
1271
1272       if (calleeSubGlobalGraph.isParameter(dstDescTuple)) {
1273         // destination node is started with 'parameter'
1274         // need to translate it in terms of the caller's a node
1275         dstDescTuple =
1276             translateToCaller(min, calleeSubGlobalGraph.getParamIdx(dstDescTuple), dstDescTuple);
1277       }
1278
1279       callerSubGlobalGraph.addValueFlowEdge(srcDescTuple, dstDescTuple);
1280
1281       if (!visited.contains(dstNode)) {
1282         visited.add(dstNode);
1283         recurAddValueFlowsFromCalleeParam(min, calleeSubGlobalGraph, dstNode, callerSubGlobalGraph,
1284             dstDescTuple, visited, baseTuple);
1285       }
1286
1287     }
1288
1289   }
1290
1291   private NTuple<Descriptor> translateToCaller(MethodInvokeNode min, int paramIdx,
1292       NTuple<Descriptor> srcDescTuple) {
1293
1294     NTuple<Descriptor> callerTuple = new NTuple<Descriptor>();
1295
1296     NTuple<Descriptor> argTuple = mapMethodInvokeNodeToArgIdxMap.get(min).get(paramIdx);
1297
1298     for (int i = 0; i < argTuple.size(); i++) {
1299       callerTuple.add(argTuple.get(i));
1300     }
1301
1302     for (int i = 1; i < srcDescTuple.size(); i++) {
1303       callerTuple.add(srcDescTuple.get(i));
1304     }
1305
1306     return callerTuple;
1307   }
1308
1309   private NTuple<Descriptor> traslateToCalleeParamTupleToCallerArgTuple(
1310       NTuple<Descriptor> calleeInitTuple, NTuple<Descriptor> callerSrcTuple) {
1311
1312     NTuple<Descriptor> callerInitTuple = new NTuple<Descriptor>();
1313
1314     for (int i = 0; i < callerSrcTuple.size(); i++) {
1315       callerInitTuple.add(callerSrcTuple.get(i));
1316     }
1317
1318     for (int i = 1; i < calleeInitTuple.size(); i++) {
1319       callerInitTuple.add(calleeInitTuple.get(i));
1320     }
1321
1322     return callerInitTuple;
1323   }
1324
1325   public LocationSummary getLocationSummary(Descriptor d) {
1326     if (!mapDescToLocationSummary.containsKey(d)) {
1327       if (d instanceof MethodDescriptor) {
1328         mapDescToLocationSummary.put(d, new MethodSummary((MethodDescriptor) d));
1329       } else if (d instanceof ClassDescriptor) {
1330         mapDescToLocationSummary.put(d, new FieldSummary());
1331       }
1332     }
1333     return mapDescToLocationSummary.get(d);
1334   }
1335
1336   private void generateMethodSummary() {
1337
1338     Set<MethodDescriptor> keySet = md2lattice.keySet();
1339     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1340       MethodDescriptor md = (MethodDescriptor) iterator.next();
1341
1342       System.out.println("\nSSJAVA: generate method summary: " + md);
1343
1344       FlowGraph flowGraph = getFlowGraph(md);
1345       MethodSummary methodSummary = getMethodSummary(md);
1346
1347       HierarchyGraph scGraph = getSkeletonCombinationHierarchyGraph(md);
1348
1349       // set the 'this' reference location
1350       if (!md.isStatic()) {
1351         System.out.println("setThisLocName=" + scGraph.getHNode(md.getThis()).getName());
1352         methodSummary.setThisLocName(scGraph.getHNode(md.getThis()).getName());
1353       }
1354
1355       // set the 'global' reference location if needed
1356       if (methodSummary.hasGlobalAccess()) {
1357         methodSummary.setGlobalLocName(scGraph.getHNode(GLOBALDESC).getName());
1358       }
1359
1360       // construct a parameter mapping that maps a parameter descriptor to an
1361       // inferred composite location
1362       for (int paramIdx = 0; paramIdx < flowGraph.getNumParameters(); paramIdx++) {
1363         FlowNode flowNode = flowGraph.getParamFlowNode(paramIdx);
1364         CompositeLocation inferredCompLoc =
1365             updateCompositeLocation(flowNode.getCompositeLocation());
1366         // NTuple<Descriptor> descTuple = flowNode.getDescTuple();
1367         //
1368         // CompositeLocation assignedCompLoc = flowNode.getCompositeLocation();
1369         // CompositeLocation inferredCompLoc;
1370         // if (assignedCompLoc != null) {
1371         // inferredCompLoc = translateCompositeLocation(assignedCompLoc);
1372         // } else {
1373         // Descriptor locDesc = descTuple.get(0);
1374         // Location loc = new Location(md, locDesc.getSymbol());
1375         // loc.setLocDescriptor(locDesc);
1376         // inferredCompLoc = new CompositeLocation(loc);
1377         // }
1378         System.out.println("-paramIdx=" + paramIdx + "   infer=" + inferredCompLoc + " original="
1379             + flowNode.getCompositeLocation());
1380
1381         Descriptor localVarDesc = flowNode.getDescTuple().get(0);
1382         methodSummary.addMapVarNameToInferCompLoc(localVarDesc, inferredCompLoc);
1383         methodSummary.addMapParamIdxToInferLoc(paramIdx, inferredCompLoc);
1384       }
1385
1386     }
1387
1388   }
1389
1390   private boolean hasOrderingRelation(NTuple<Location> locTuple1, NTuple<Location> locTuple2) {
1391
1392     int size = locTuple1.size() >= locTuple2.size() ? locTuple2.size() : locTuple1.size();
1393
1394     for (int idx = 0; idx < size; idx++) {
1395       Location loc1 = locTuple1.get(idx);
1396       Location loc2 = locTuple2.get(idx);
1397
1398       Descriptor desc1 = loc1.getDescriptor();
1399       Descriptor desc2 = loc2.getDescriptor();
1400
1401       if (!desc1.equals(desc2)) {
1402         throw new Error("Fail to compare " + locTuple1 + " and " + locTuple2);
1403       }
1404
1405       Descriptor locDesc1 = loc1.getLocDescriptor();
1406       Descriptor locDesc2 = loc2.getLocDescriptor();
1407
1408       HierarchyGraph hierarchyGraph = getHierarchyGraph(desc1);
1409
1410       HNode node1 = hierarchyGraph.getHNode(locDesc1);
1411       HNode node2 = hierarchyGraph.getHNode(locDesc2);
1412
1413       System.out.println("---node1=" + node1 + "  node2=" + node2);
1414       System.out.println("---hierarchyGraph.getIncomingNodeSet(node2)="
1415           + hierarchyGraph.getIncomingNodeSet(node2));
1416
1417       if (locDesc1.equals(locDesc2)) {
1418         continue;
1419       } else if (!hierarchyGraph.getIncomingNodeSet(node2).contains(node1)
1420           && !hierarchyGraph.getIncomingNodeSet(node1).contains(node2)) {
1421         return false;
1422       } else {
1423         return true;
1424       }
1425
1426     }
1427
1428     return false;
1429
1430   }
1431
1432   private boolean isHigherThan(NTuple<Location> locTuple1, NTuple<Location> locTuple2) {
1433
1434     int size = locTuple1.size() >= locTuple2.size() ? locTuple2.size() : locTuple1.size();
1435
1436     for (int idx = 0; idx < size; idx++) {
1437       Location loc1 = locTuple1.get(idx);
1438       Location loc2 = locTuple2.get(idx);
1439
1440       Descriptor desc1 = loc1.getDescriptor();
1441       Descriptor desc2 = loc2.getDescriptor();
1442
1443       if (!desc1.equals(desc2)) {
1444         throw new Error("Fail to compare " + locTuple1 + " and " + locTuple2);
1445       }
1446
1447       Descriptor locDesc1 = loc1.getLocDescriptor();
1448       Descriptor locDesc2 = loc2.getLocDescriptor();
1449
1450       HierarchyGraph hierarchyGraph = getHierarchyGraph(desc1);
1451
1452       HNode node1 = hierarchyGraph.getHNode(locDesc1);
1453       HNode node2 = hierarchyGraph.getHNode(locDesc2);
1454
1455       System.out.println("---node1=" + node1 + "  node2=" + node2);
1456       System.out.println("---hierarchyGraph.getIncomingNodeSet(node2)="
1457           + hierarchyGraph.getIncomingNodeSet(node2));
1458
1459       if (locDesc1.equals(locDesc2)) {
1460         continue;
1461       } else if (hierarchyGraph.getIncomingNodeSet(node2).contains(node1)) {
1462         return true;
1463       } else {
1464         return false;
1465       }
1466
1467     }
1468
1469     return false;
1470   }
1471
1472   private CompositeLocation translateCompositeLocation(CompositeLocation compLoc) {
1473     CompositeLocation newCompLoc = new CompositeLocation();
1474
1475     // System.out.println("compLoc=" + compLoc);
1476     for (int i = 0; i < compLoc.getSize(); i++) {
1477       Location loc = compLoc.get(i);
1478       Descriptor enclosingDescriptor = loc.getDescriptor();
1479       Descriptor locDescriptor = loc.getLocDescriptor();
1480
1481       HNode hnode = getHierarchyGraph(enclosingDescriptor).getHNode(locDescriptor);
1482       // System.out.println("-hnode=" + hnode + "    from=" + locDescriptor +
1483       // " enclosingDescriptor="
1484       // + enclosingDescriptor);
1485       // System.out.println("-getLocationSummary(enclosingDescriptor)="
1486       // + getLocationSummary(enclosingDescriptor));
1487       String locName = getLocationSummary(enclosingDescriptor).getLocationName(hnode.getName());
1488       // System.out.println("-locName=" + locName);
1489       Location newLoc = new Location(enclosingDescriptor, locName);
1490       newLoc.setLocDescriptor(locDescriptor);
1491       newCompLoc.addLocation(newLoc);
1492     }
1493
1494     return newCompLoc;
1495   }
1496
1497   private void debug_writeLattices() {
1498
1499     Set<Descriptor> keySet = mapDescriptorToSimpleLattice.keySet();
1500     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1501       Descriptor key = (Descriptor) iterator.next();
1502       SSJavaLattice<String> simpleLattice = mapDescriptorToSimpleLattice.get(key);
1503       // HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(key);
1504       HierarchyGraph scHierarchyGraph = getSkeletonCombinationHierarchyGraph(key);
1505       if (key instanceof ClassDescriptor) {
1506         writeInferredLatticeDotFile((ClassDescriptor) key, scHierarchyGraph, simpleLattice,
1507             "_SIMPLE");
1508       } else if (key instanceof MethodDescriptor) {
1509         MethodDescriptor md = (MethodDescriptor) key;
1510         writeInferredLatticeDotFile(md.getClassDesc(), md, scHierarchyGraph, simpleLattice,
1511             "_SIMPLE");
1512       }
1513
1514       LocationSummary ls = getLocationSummary(key);
1515       System.out.println("####LOC SUMMARY=" + key + "\n" + ls.getMapHNodeNameToLocationName());
1516     }
1517
1518     Set<ClassDescriptor> cdKeySet = cd2lattice.keySet();
1519     for (Iterator iterator = cdKeySet.iterator(); iterator.hasNext();) {
1520       ClassDescriptor cd = (ClassDescriptor) iterator.next();
1521       writeInferredLatticeDotFile((ClassDescriptor) cd, getSkeletonCombinationHierarchyGraph(cd),
1522           cd2lattice.get(cd), "");
1523     }
1524
1525     Set<MethodDescriptor> mdKeySet = md2lattice.keySet();
1526     for (Iterator iterator = mdKeySet.iterator(); iterator.hasNext();) {
1527       MethodDescriptor md = (MethodDescriptor) iterator.next();
1528       writeInferredLatticeDotFile(md.getClassDesc(), md, getSkeletonCombinationHierarchyGraph(md),
1529           md2lattice.get(md), "");
1530     }
1531
1532   }
1533
1534   private void buildLattice() {
1535
1536     BuildLattice buildLattice = new BuildLattice(this);
1537
1538     Set<Descriptor> keySet = mapDescriptorToCombineSkeletonHierarchyGraph.keySet();
1539     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1540       Descriptor desc = (Descriptor) iterator.next();
1541
1542       SSJavaLattice<String> simpleLattice = buildLattice.buildLattice(desc);
1543
1544       addMapDescToSimpleLattice(desc, simpleLattice);
1545
1546       HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(desc);
1547       System.out.println("\n## insertIntermediateNodesToStraightLine:"
1548           + simpleHierarchyGraph.getName());
1549       SSJavaLattice<String> lattice =
1550           buildLattice.insertIntermediateNodesToStraightLine(desc, simpleLattice);
1551       lattice.removeRedundantEdges();
1552
1553       if (desc instanceof ClassDescriptor) {
1554         // field lattice
1555         cd2lattice.put((ClassDescriptor) desc, lattice);
1556         // ssjava.writeLatticeDotFile((ClassDescriptor) desc, null, lattice);
1557       } else if (desc instanceof MethodDescriptor) {
1558         // method lattice
1559         md2lattice.put((MethodDescriptor) desc, lattice);
1560         MethodDescriptor md = (MethodDescriptor) desc;
1561         ClassDescriptor cd = md.getClassDesc();
1562         // ssjava.writeLatticeDotFile(cd, md, lattice);
1563       }
1564
1565       // System.out.println("\nSSJAVA: Insering Combination Nodes:" + desc);
1566       // HierarchyGraph skeletonGraph = getSkeletonHierarchyGraph(desc);
1567       // HierarchyGraph skeletonGraphWithCombinationNode =
1568       // skeletonGraph.clone();
1569       // skeletonGraphWithCombinationNode.setName(desc + "_SC");
1570       //
1571       // HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(desc);
1572       // System.out.println("Identifying Combination Nodes:");
1573       // skeletonGraphWithCombinationNode.insertCombinationNodesToGraph(simpleHierarchyGraph);
1574       // skeletonGraphWithCombinationNode.simplifySkeletonCombinationHierarchyGraph();
1575       // mapDescriptorToCombineSkeletonHierarchyGraph.put(desc,
1576       // skeletonGraphWithCombinationNode);
1577     }
1578
1579   }
1580
1581   public void addMapDescToSimpleLattice(Descriptor desc, SSJavaLattice<String> lattice) {
1582     mapDescriptorToSimpleLattice.put(desc, lattice);
1583   }
1584
1585   public SSJavaLattice<String> getSimpleLattice(Descriptor desc) {
1586     return mapDescriptorToSimpleLattice.get(desc);
1587   }
1588
1589   private void simplifyHierarchyGraph() {
1590     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
1591     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1592       Descriptor desc = (Descriptor) iterator.next();
1593       System.out.println("SSJAVA: remove redundant edges: " + desc);
1594       HierarchyGraph simpleHierarchyGraph = getHierarchyGraph(desc).clone();
1595       simpleHierarchyGraph.setName(desc + "_SIMPLE");
1596       simpleHierarchyGraph.removeRedundantEdges();
1597       mapDescriptorToSimpleHierarchyGraph.put(desc, simpleHierarchyGraph);
1598     }
1599   }
1600
1601   private void insertCombinationNodes() {
1602     Set<Descriptor> keySet = mapDescriptorToSkeletonHierarchyGraph.keySet();
1603     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1604       Descriptor desc = (Descriptor) iterator.next();
1605       System.out.println("\nSSJAVA: Insering Combination Nodes:" + desc);
1606       HierarchyGraph skeletonGraph = getSkeletonHierarchyGraph(desc);
1607       HierarchyGraph skeletonGraphWithCombinationNode = skeletonGraph.clone();
1608       skeletonGraphWithCombinationNode.setName(desc + "_SC");
1609
1610       HierarchyGraph simpleHierarchyGraph = getSimpleHierarchyGraph(desc);
1611       System.out.println("Identifying Combination Nodes:");
1612       skeletonGraphWithCombinationNode.insertCombinationNodesToGraph(simpleHierarchyGraph);
1613       skeletonGraphWithCombinationNode.simplifySkeletonCombinationHierarchyGraph();
1614       mapDescriptorToCombineSkeletonHierarchyGraph.put(desc, skeletonGraphWithCombinationNode);
1615     }
1616   }
1617
1618   private void constructSkeletonHierarchyGraph() {
1619     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
1620     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1621       Descriptor desc = (Descriptor) iterator.next();
1622       System.out.println("SSJAVA: Constructing Skeleton Hierarchy Graph: " + desc);
1623       HierarchyGraph simpleGraph = getSimpleHierarchyGraph(desc);
1624       HierarchyGraph skeletonGraph = simpleGraph.generateSkeletonGraph();
1625       skeletonGraph.setMapDescToHNode(simpleGraph.getMapDescToHNode());
1626       skeletonGraph.setMapHNodeToDescSet(simpleGraph.getMapHNodeToDescSet());
1627       skeletonGraph.simplifyHierarchyGraph();
1628       // skeletonGraph.combineRedundantNodes(false);
1629       // skeletonGraph.removeRedundantEdges();
1630       mapDescriptorToSkeletonHierarchyGraph.put(desc, skeletonGraph);
1631     }
1632   }
1633
1634   private void debug_writeHierarchyDotFiles() {
1635
1636     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
1637     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1638       Descriptor desc = (Descriptor) iterator.next();
1639       getHierarchyGraph(desc).writeGraph();
1640     }
1641
1642   }
1643
1644   private void debug_writeSimpleHierarchyDotFiles() {
1645
1646     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
1647     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1648       Descriptor desc = (Descriptor) iterator.next();
1649       getHierarchyGraph(desc).writeGraph();
1650       getSimpleHierarchyGraph(desc).writeGraph();
1651     }
1652
1653   }
1654
1655   private void debug_writeSkeletonHierarchyDotFiles() {
1656
1657     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
1658     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1659       Descriptor desc = (Descriptor) iterator.next();
1660       getSkeletonHierarchyGraph(desc).writeGraph();
1661     }
1662
1663   }
1664
1665   private void debug_writeSkeletonCombinationHierarchyDotFiles() {
1666
1667     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
1668     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1669       Descriptor desc = (Descriptor) iterator.next();
1670       getSkeletonCombinationHierarchyGraph(desc).writeGraph();
1671     }
1672
1673   }
1674
1675   public HierarchyGraph getSimpleHierarchyGraph(Descriptor d) {
1676     return mapDescriptorToSimpleHierarchyGraph.get(d);
1677   }
1678
1679   private HierarchyGraph getSkeletonHierarchyGraph(Descriptor d) {
1680     if (!mapDescriptorToSkeletonHierarchyGraph.containsKey(d)) {
1681       mapDescriptorToSkeletonHierarchyGraph.put(d, new HierarchyGraph(d));
1682     }
1683     return mapDescriptorToSkeletonHierarchyGraph.get(d);
1684   }
1685
1686   public HierarchyGraph getSkeletonCombinationHierarchyGraph(Descriptor d) {
1687     if (!mapDescriptorToCombineSkeletonHierarchyGraph.containsKey(d)) {
1688       mapDescriptorToCombineSkeletonHierarchyGraph.put(d, new HierarchyGraph(d));
1689     }
1690     return mapDescriptorToCombineSkeletonHierarchyGraph.get(d);
1691   }
1692
1693   private void constructHierarchyGraph() {
1694
1695     // do fixed-point analysis
1696
1697     LinkedList<MethodDescriptor> descriptorListToAnalyze = ssjava.getSortedDescriptors();
1698
1699     // Collections.sort(descriptorListToAnalyze, new
1700     // Comparator<MethodDescriptor>() {
1701     // public int compare(MethodDescriptor o1, MethodDescriptor o2) {
1702     // return o1.getSymbol().compareToIgnoreCase(o2.getSymbol());
1703     // }
1704     // });
1705
1706     // current descriptors to visit in fixed-point interprocedural analysis,
1707     // prioritized by dependency in the call graph
1708     methodDescriptorsToVisitStack.clear();
1709
1710     Set<MethodDescriptor> methodDescriptorToVistSet = new HashSet<MethodDescriptor>();
1711     methodDescriptorToVistSet.addAll(descriptorListToAnalyze);
1712
1713     while (!descriptorListToAnalyze.isEmpty()) {
1714       MethodDescriptor md = descriptorListToAnalyze.removeFirst();
1715       methodDescriptorsToVisitStack.add(md);
1716     }
1717
1718     // analyze scheduled methods until there are no more to visit
1719     while (!methodDescriptorsToVisitStack.isEmpty()) {
1720       // start to analyze leaf node
1721       MethodDescriptor md = methodDescriptorsToVisitStack.pop();
1722
1723       HierarchyGraph hierarchyGraph = new HierarchyGraph(md);
1724       // MethodSummary methodSummary = new MethodSummary(md);
1725
1726       // MethodLocationInfo methodInfo = new MethodLocationInfo(md);
1727       // curMethodInfo = methodInfo;
1728
1729       System.out.println();
1730       System.out.println("SSJAVA: Construcing the hierarchy graph from " + md);
1731
1732       constructHierarchyGraph(md, hierarchyGraph);
1733
1734       HierarchyGraph prevHierarchyGraph = getHierarchyGraph(md);
1735       // MethodSummary prevMethodSummary = getMethodSummary(md);
1736
1737       if (!hierarchyGraph.equals(prevHierarchyGraph)) {
1738
1739         mapDescriptorToHierarchyGraph.put(md, hierarchyGraph);
1740         // mapDescToLocationSummary.put(md, methodSummary);
1741
1742         // results for callee changed, so enqueue dependents caller for
1743         // further analysis
1744         Iterator<MethodDescriptor> depsItr = ssjava.getDependents(md).iterator();
1745         while (depsItr.hasNext()) {
1746           MethodDescriptor methodNext = depsItr.next();
1747           if (!methodDescriptorsToVisitStack.contains(methodNext)
1748               && methodDescriptorToVistSet.contains(methodNext)) {
1749             methodDescriptorsToVisitStack.add(methodNext);
1750           }
1751         }
1752
1753       }
1754
1755     }
1756
1757     setupToAnalyze();
1758     while (!toAnalyzeIsEmpty()) {
1759       ClassDescriptor cd = toAnalyzeNext();
1760       HierarchyGraph graph = getHierarchyGraph(cd);
1761       for (Iterator iter = cd.getFields(); iter.hasNext();) {
1762         FieldDescriptor fieldDesc = (FieldDescriptor) iter.next();
1763         if (!(fieldDesc.isStatic() && fieldDesc.isFinal())) {
1764           graph.getHNode(fieldDesc);
1765         }
1766       }
1767     }
1768
1769     Set<Descriptor> keySet = mapDescriptorToHierarchyGraph.keySet();
1770     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1771       Descriptor key = (Descriptor) iterator.next();
1772       HierarchyGraph graph = getHierarchyGraph(key);
1773
1774       Set<HNode> nodeToBeConnected = new HashSet<HNode>();
1775       for (Iterator iterator2 = graph.getNodeSet().iterator(); iterator2.hasNext();) {
1776         HNode node = (HNode) iterator2.next();
1777         if (!node.isSkeleton() && !node.isCombinationNode()) {
1778           if (graph.getIncomingNodeSet(node).size() == 0) {
1779             nodeToBeConnected.add(node);
1780           }
1781         }
1782       }
1783
1784       for (Iterator iterator2 = nodeToBeConnected.iterator(); iterator2.hasNext();) {
1785         HNode node = (HNode) iterator2.next();
1786         System.out.println("NEED TO BE CONNECTED TO TOP=" + node);
1787         graph.addEdge(graph.getHNode(TOPDESC), node);
1788       }
1789
1790     }
1791
1792   }
1793
1794   private HierarchyGraph getHierarchyGraph(Descriptor d) {
1795     if (!mapDescriptorToHierarchyGraph.containsKey(d)) {
1796       mapDescriptorToHierarchyGraph.put(d, new HierarchyGraph(d));
1797     }
1798     return mapDescriptorToHierarchyGraph.get(d);
1799   }
1800
1801   private void constructHierarchyGraph(MethodDescriptor md, HierarchyGraph methodGraph) {
1802
1803     // visit each node of method flow graph
1804     FlowGraph fg = getFlowGraph(md);
1805     Set<FlowNode> nodeSet = fg.getNodeSet();
1806
1807     Set<Descriptor> paramDescSet = fg.getMapParamDescToIdx().keySet();
1808     for (Iterator iterator = paramDescSet.iterator(); iterator.hasNext();) {
1809       Descriptor desc = (Descriptor) iterator.next();
1810       methodGraph.getHNode(desc).setSkeleton(true);
1811     }
1812
1813     // for the method lattice, we need to look at the first element of
1814     // NTuple<Descriptor>
1815     boolean hasGlobalAccess = false;
1816     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
1817       FlowNode srcNode = (FlowNode) iterator.next();
1818
1819       // if the srcNode is started with the global descriptor
1820       // need to set as a skeleton node
1821       if (!hasGlobalAccess && srcNode.getDescTuple().startsWith(GLOBALDESC)) {
1822         hasGlobalAccess = true;
1823       }
1824
1825       Set<FlowEdge> outEdgeSet = fg.getOutEdgeSet(srcNode);
1826       for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) {
1827         FlowEdge outEdge = (FlowEdge) iterator2.next();
1828         FlowNode dstNode = outEdge.getDst();
1829
1830         NTuple<Descriptor> srcNodeTuple = srcNode.getDescTuple();
1831         NTuple<Descriptor> dstNodeTuple = dstNode.getDescTuple();
1832
1833         if (outEdge.getInitTuple().equals(srcNodeTuple)
1834             && outEdge.getEndTuple().equals(dstNodeTuple)) {
1835
1836           NTuple<Descriptor> srcCurTuple = srcNode.getCurrentDescTuple();
1837           NTuple<Descriptor> dstCurTuple = dstNode.getCurrentDescTuple();
1838
1839           if ((srcCurTuple.size() > 1 && dstCurTuple.size() > 1)
1840               && srcCurTuple.get(0).equals(dstCurTuple.get(0))) {
1841
1842             // value flows between fields
1843             Descriptor desc = srcCurTuple.get(0);
1844             ClassDescriptor classDesc;
1845
1846             if (desc.equals(GLOBALDESC)) {
1847               classDesc = md.getClassDesc();
1848             } else {
1849               VarDescriptor varDesc = (VarDescriptor) srcCurTuple.get(0);
1850               classDesc = varDesc.getType().getClassDesc();
1851             }
1852             extractFlowsBetweenFields(classDesc, srcNode, dstNode, 1);
1853
1854           } else {
1855             // value flow between local var - local var or local var - field
1856
1857             Descriptor srcDesc = srcCurTuple.get(0);
1858             Descriptor dstDesc = dstCurTuple.get(0);
1859
1860             methodGraph.addEdge(srcDesc, dstDesc);
1861
1862             if (fg.isParamDesc(srcDesc)) {
1863               methodGraph.setParamHNode(srcDesc);
1864             }
1865             if (fg.isParamDesc(dstDesc)) {
1866               methodGraph.setParamHNode(dstDesc);
1867             }
1868
1869           }
1870
1871         }
1872       }
1873     }
1874
1875     // If the method accesses static fields
1876     // set hasGloabalAccess true in the method summary.
1877     if (hasGlobalAccess) {
1878       getMethodSummary(md).setHasGlobalAccess();
1879     }
1880     methodGraph.getHNode(GLOBALDESC).setSkeleton(true);
1881
1882     if (ssjava.getMethodContainingSSJavaLoop().equals(md)) {
1883       // if the current method contains the event loop
1884       // we need to set all nodes of the hierarchy graph as a skeleton node
1885       Set<HNode> hnodeSet = methodGraph.getNodeSet();
1886       for (Iterator iterator = hnodeSet.iterator(); iterator.hasNext();) {
1887         HNode hnode = (HNode) iterator.next();
1888         hnode.setSkeleton(true);
1889       }
1890     }
1891
1892   }
1893
1894   private MethodSummary getMethodSummary(MethodDescriptor md) {
1895     if (!mapDescToLocationSummary.containsKey(md)) {
1896       mapDescToLocationSummary.put(md, new MethodSummary(md));
1897     }
1898     return (MethodSummary) mapDescToLocationSummary.get(md);
1899   }
1900
1901   private void addMapClassDefinitionToLineNum(ClassDescriptor cd, String strLine, int lineNum) {
1902
1903     String classSymbol = cd.getSymbol();
1904     int idx = classSymbol.lastIndexOf("$");
1905     if (idx != -1) {
1906       classSymbol = classSymbol.substring(idx + 1);
1907     }
1908
1909     String pattern = "class " + classSymbol + " ";
1910     if (strLine.indexOf(pattern) != -1) {
1911       mapDescToDefinitionLine.put(cd, lineNum);
1912     }
1913   }
1914
1915   private void addMapMethodDefinitionToLineNum(Set<MethodDescriptor> methodSet, String strLine,
1916       int lineNum) {
1917     for (Iterator iterator = methodSet.iterator(); iterator.hasNext();) {
1918       MethodDescriptor md = (MethodDescriptor) iterator.next();
1919       String pattern = md.getMethodDeclaration();
1920       if (strLine.indexOf(pattern) != -1) {
1921         mapDescToDefinitionLine.put(md, lineNum);
1922         methodSet.remove(md);
1923         return;
1924       }
1925     }
1926
1927   }
1928
1929   private void readOriginalSourceFiles() {
1930
1931     SymbolTable classtable = state.getClassSymbolTable();
1932
1933     Set<ClassDescriptor> classDescSet = new HashSet<ClassDescriptor>();
1934     classDescSet.addAll(classtable.getValueSet());
1935
1936     try {
1937       // inefficient implement. it may re-visit the same file if the file
1938       // contains more than one class definitions.
1939       for (Iterator iterator = classDescSet.iterator(); iterator.hasNext();) {
1940         ClassDescriptor cd = (ClassDescriptor) iterator.next();
1941
1942         Set<MethodDescriptor> methodSet = new HashSet<MethodDescriptor>();
1943         methodSet.addAll(cd.getMethodTable().getValueSet());
1944
1945         String sourceFileName = cd.getSourceFileName();
1946         Vector<String> lineVec = new Vector<String>();
1947
1948         mapFileNameToLineVector.put(sourceFileName, lineVec);
1949
1950         BufferedReader in = new BufferedReader(new FileReader(sourceFileName));
1951         String strLine;
1952         int lineNum = 1;
1953         lineVec.add(""); // the index is started from 1.
1954         while ((strLine = in.readLine()) != null) {
1955           lineVec.add(lineNum, strLine);
1956           addMapClassDefinitionToLineNum(cd, strLine, lineNum);
1957           addMapMethodDefinitionToLineNum(methodSet, strLine, lineNum);
1958           lineNum++;
1959         }
1960
1961       }
1962
1963     } catch (IOException e) {
1964       e.printStackTrace();
1965     }
1966
1967   }
1968
1969   private String generateLatticeDefinition(Descriptor desc) {
1970
1971     Set<String> sharedLocSet = new HashSet<String>();
1972
1973     SSJavaLattice<String> lattice = getLattice(desc);
1974     String rtr = "@LATTICE(\"";
1975
1976     Map<String, Set<String>> map = lattice.getTable();
1977     Set<String> keySet = map.keySet();
1978     boolean first = true;
1979     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
1980       String key = (String) iterator.next();
1981       if (!key.equals(lattice.getTopItem())) {
1982         Set<String> connectedSet = map.get(key);
1983
1984         if (connectedSet.size() == 1) {
1985           if (connectedSet.iterator().next().equals(lattice.getBottomItem())) {
1986             if (!first) {
1987               rtr += ",";
1988             } else {
1989               rtr += "LOC,";
1990               first = false;
1991             }
1992             rtr += key;
1993             if (lattice.isSharedLoc(key)) {
1994               rtr += "," + key + "*";
1995             }
1996           }
1997         }
1998
1999         for (Iterator iterator2 = connectedSet.iterator(); iterator2.hasNext();) {
2000           String loc = (String) iterator2.next();
2001           if (!loc.equals(lattice.getBottomItem())) {
2002             if (!first) {
2003               rtr += ",";
2004             } else {
2005               rtr += "LOC,";
2006               first = false;
2007             }
2008             rtr += loc + "<" + key;
2009             if (lattice.isSharedLoc(key) && (!sharedLocSet.contains(key))) {
2010               rtr += "," + key + "*";
2011               sharedLocSet.add(key);
2012             }
2013             if (lattice.isSharedLoc(loc) && (!sharedLocSet.contains(loc))) {
2014               rtr += "," + loc + "*";
2015               sharedLocSet.add(loc);
2016             }
2017
2018           }
2019         }
2020       }
2021     }
2022
2023     rtr += "\")";
2024
2025     if (desc instanceof MethodDescriptor) {
2026       System.out.println("#EXTRA LOC DECLARATION GEN=" + desc);
2027
2028       MethodDescriptor md = (MethodDescriptor) desc;
2029       MethodSummary methodSummary = getMethodSummary(md);
2030
2031       if (!ssjava.getMethodContainingSSJavaLoop().equals(desc)) {
2032         TypeDescriptor returnType = ((MethodDescriptor) desc).getReturnType();
2033         if (returnType != null && (!returnType.isVoid())) {
2034           rtr +=
2035               "\n@RETURNLOC(\"" + generateLocationAnnoatation(methodSummary.getRETURNLoc()) + "\")";
2036         }
2037         CompositeLocation pcLoc = methodSummary.getPCLoc();
2038         if ((pcLoc != null) && (!pcLoc.get(0).isTop())) {
2039           rtr += "\n@PCLOC(\"" + generateLocationAnnoatation(pcLoc) + "\")";
2040         }
2041       }
2042
2043       if (!md.isStatic()) {
2044         rtr += "\n@THISLOC(\"" + methodSummary.getThisLocName() + "\")";
2045       }
2046       rtr += "\n@GLOBALLOC(\"" + methodSummary.getGlobalLocName() + "\")";
2047
2048     }
2049
2050     return rtr;
2051   }
2052
2053   private void generateAnnoatedCode() {
2054
2055     readOriginalSourceFiles();
2056
2057     setupToAnalyze();
2058     while (!toAnalyzeIsEmpty()) {
2059       ClassDescriptor cd = toAnalyzeNext();
2060
2061       setupToAnalazeMethod(cd);
2062
2063       String sourceFileName = cd.getSourceFileName();
2064
2065       if (cd.isInterface()) {
2066         continue;
2067       }
2068
2069       int classDefLine = mapDescToDefinitionLine.get(cd);
2070       Vector<String> sourceVec = mapFileNameToLineVector.get(sourceFileName);
2071
2072       LocationSummary fieldLocSummary = getLocationSummary(cd);
2073
2074       String fieldLatticeDefStr = generateLatticeDefinition(cd);
2075       String annoatedSrc = fieldLatticeDefStr + newline + sourceVec.get(classDefLine);
2076       sourceVec.set(classDefLine, annoatedSrc);
2077
2078       // generate annotations for field declarations
2079       // Map<Descriptor, CompositeLocation> inferLocMap = fieldLocInfo.getMapDescToInferLocation();
2080       Map<String, String> mapFieldNameToLocName = fieldLocSummary.getMapHNodeNameToLocationName();
2081
2082       for (Iterator iter = cd.getFields(); iter.hasNext();) {
2083         FieldDescriptor fd = (FieldDescriptor) iter.next();
2084
2085         String locAnnotationStr;
2086         // CompositeLocation inferLoc = inferLocMap.get(fd);
2087         String locName = mapFieldNameToLocName.get(fd.getSymbol());
2088
2089         if (locName != null) {
2090           // infer loc is null if the corresponding field is static and final
2091           // locAnnotationStr = "@LOC(\"" + generateLocationAnnoatation(inferLoc) + "\")";
2092           locAnnotationStr = "@LOC(\"" + locName + "\")";
2093           int fdLineNum = fd.getLineNum();
2094           String orgFieldDeclarationStr = sourceVec.get(fdLineNum);
2095           String fieldDeclaration = fd.toString();
2096           fieldDeclaration = fieldDeclaration.substring(0, fieldDeclaration.length() - 1);
2097           String annoatedStr = locAnnotationStr + " " + orgFieldDeclarationStr;
2098           sourceVec.set(fdLineNum, annoatedStr);
2099         }
2100
2101       }
2102
2103       while (!toAnalyzeMethodIsEmpty()) {
2104         MethodDescriptor md = toAnalyzeMethodNext();
2105
2106         if (!ssjava.needTobeAnnotated(md)) {
2107           continue;
2108         }
2109
2110         SSJavaLattice<String> methodLattice = md2lattice.get(md);
2111         if (methodLattice != null) {
2112
2113           int methodDefLine = md.getLineNum();
2114
2115           // MethodLocationInfo methodLocInfo = getMethodLocationInfo(md);
2116           // Map<Descriptor, CompositeLocation> methodInferLocMap =
2117           // methodLocInfo.getMapDescToInferLocation();
2118
2119           MethodSummary methodSummary = getMethodSummary(md);
2120
2121           Map<Descriptor, CompositeLocation> mapVarDescToInferLoc =
2122               methodSummary.getMapVarDescToInferCompositeLocation();
2123           System.out.println("-----md=" + md);
2124           System.out.println("-----mapVarDescToInferLoc=" + mapVarDescToInferLoc);
2125
2126           Set<Descriptor> localVarDescSet = mapVarDescToInferLoc.keySet();
2127
2128           Set<String> localLocElementSet = methodLattice.getElementSet();
2129
2130           for (Iterator iterator = localVarDescSet.iterator(); iterator.hasNext();) {
2131             Descriptor localVarDesc = (Descriptor) iterator.next();
2132             System.out.println("-------localVarDesc=" + localVarDesc);
2133             CompositeLocation inferLoc = mapVarDescToInferLoc.get(localVarDesc);
2134
2135             String localLocIdentifier = inferLoc.get(0).getLocIdentifier();
2136             if (!localLocElementSet.contains(localLocIdentifier)) {
2137               methodLattice.put(localLocIdentifier);
2138             }
2139
2140             String locAnnotationStr = "@LOC(\"" + generateLocationAnnoatation(inferLoc) + "\")";
2141
2142             if (!isParameter(md, localVarDesc)) {
2143               if (mapDescToDefinitionLine.containsKey(localVarDesc)) {
2144                 int varLineNum = mapDescToDefinitionLine.get(localVarDesc);
2145                 String orgSourceLine = sourceVec.get(varLineNum);
2146                 int idx =
2147                     orgSourceLine.indexOf(generateVarDeclaration((VarDescriptor) localVarDesc));
2148                 assert (idx != -1);
2149                 String annoatedStr =
2150                     orgSourceLine.substring(0, idx) + locAnnotationStr + " "
2151                         + orgSourceLine.substring(idx);
2152                 sourceVec.set(varLineNum, annoatedStr);
2153               }
2154             } else {
2155               String methodDefStr = sourceVec.get(methodDefLine);
2156
2157               int idx =
2158                   getParamLocation(methodDefStr,
2159                       generateVarDeclaration((VarDescriptor) localVarDesc));
2160               System.out.println("methodDefStr=" + methodDefStr + " localVarDesc=" + localVarDesc
2161                   + " idx=" + idx);
2162               assert (idx != -1);
2163
2164               String annoatedStr =
2165                   methodDefStr.substring(0, idx) + locAnnotationStr + " "
2166                       + methodDefStr.substring(idx);
2167               sourceVec.set(methodDefLine, annoatedStr);
2168             }
2169
2170           }
2171
2172           // check if the lattice has to have the location type for the this
2173           // reference...
2174
2175           // boolean needToAddthisRef = hasThisReference(md);
2176           // if (localLocElementSet.contains("this")) {
2177           // methodLattice.put("this");
2178           // }
2179
2180           String methodLatticeDefStr = generateLatticeDefinition(md);
2181           String annoatedStr = methodLatticeDefStr + newline + sourceVec.get(methodDefLine);
2182           sourceVec.set(methodDefLine, annoatedStr);
2183
2184         }
2185       }
2186
2187     }
2188
2189     codeGen();
2190   }
2191
2192   private boolean hasThisReference(MethodDescriptor md) {
2193
2194     FlowGraph fg = getFlowGraph(md);
2195     Set<FlowNode> nodeSet = fg.getNodeSet();
2196     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
2197       FlowNode flowNode = (FlowNode) iterator.next();
2198       if (flowNode.getDescTuple().get(0).equals(md.getThis())) {
2199         return true;
2200       }
2201     }
2202
2203     return false;
2204   }
2205
2206   private int getParamLocation(String methodStr, String paramStr) {
2207
2208     String pattern = paramStr + ",";
2209
2210     int idx = methodStr.indexOf(pattern);
2211     if (idx != -1) {
2212       return idx;
2213     } else {
2214       pattern = paramStr + ")";
2215       return methodStr.indexOf(pattern);
2216     }
2217
2218   }
2219
2220   private String generateVarDeclaration(VarDescriptor varDesc) {
2221
2222     TypeDescriptor td = varDesc.getType();
2223     String rtr = td.toString();
2224     if (td.isArray()) {
2225       for (int i = 0; i < td.getArrayCount(); i++) {
2226         rtr += "[]";
2227       }
2228     }
2229     rtr += " " + varDesc.getName();
2230     return rtr;
2231
2232   }
2233
2234   private String generateLocationAnnoatation(CompositeLocation loc) {
2235     System.out.println("loc=" + loc);
2236     String rtr = "";
2237     // method location
2238     Location methodLoc = loc.get(0);
2239     rtr += methodLoc.getLocIdentifier();
2240
2241     for (int i = 1; i < loc.getSize(); i++) {
2242       Location element = loc.get(i);
2243       rtr += "," + element.getDescriptor().getSymbol() + "." + element.getLocIdentifier();
2244     }
2245
2246     return rtr;
2247   }
2248
2249   private boolean isParameter(MethodDescriptor md, Descriptor localVarDesc) {
2250     return getFlowGraph(md).isParamDesc(localVarDesc);
2251   }
2252
2253   private String extractFileName(String fileName) {
2254     int idx = fileName.lastIndexOf("/");
2255     if (idx == -1) {
2256       return fileName;
2257     } else {
2258       return fileName.substring(idx + 1);
2259     }
2260
2261   }
2262
2263   private void codeGen() {
2264
2265     Set<String> originalFileNameSet = mapFileNameToLineVector.keySet();
2266     for (Iterator iterator = originalFileNameSet.iterator(); iterator.hasNext();) {
2267       String orgFileName = (String) iterator.next();
2268       String outputFileName = extractFileName(orgFileName);
2269
2270       Vector<String> sourceVec = mapFileNameToLineVector.get(orgFileName);
2271
2272       try {
2273
2274         FileWriter fileWriter = new FileWriter("./infer/" + outputFileName);
2275         BufferedWriter out = new BufferedWriter(fileWriter);
2276
2277         for (int i = 0; i < sourceVec.size(); i++) {
2278           out.write(sourceVec.get(i));
2279           out.newLine();
2280         }
2281         out.close();
2282       } catch (IOException e) {
2283         e.printStackTrace();
2284       }
2285
2286     }
2287
2288   }
2289
2290   private void checkLattices() {
2291
2292     LinkedList<MethodDescriptor> descriptorListToAnalyze = ssjava.getSortedDescriptors();
2293
2294     // current descriptors to visit in fixed-point interprocedural analysis,
2295     // prioritized by
2296     // dependency in the call graph
2297     methodDescriptorsToVisitStack.clear();
2298
2299     // descriptorListToAnalyze.removeFirst();
2300
2301     Set<MethodDescriptor> methodDescriptorToVistSet = new HashSet<MethodDescriptor>();
2302     methodDescriptorToVistSet.addAll(descriptorListToAnalyze);
2303
2304     while (!descriptorListToAnalyze.isEmpty()) {
2305       MethodDescriptor md = descriptorListToAnalyze.removeFirst();
2306       checkLatticesOfVirtualMethods(md);
2307     }
2308
2309   }
2310
2311   private void debug_writeLatticeDotFile() {
2312     // generate lattice dot file
2313
2314     setupToAnalyze();
2315
2316     while (!toAnalyzeIsEmpty()) {
2317       ClassDescriptor cd = toAnalyzeNext();
2318
2319       setupToAnalazeMethod(cd);
2320
2321       SSJavaLattice<String> classLattice = cd2lattice.get(cd);
2322       if (classLattice != null) {
2323         ssjava.writeLatticeDotFile(cd, null, classLattice);
2324         debug_printDescriptorToLocNameMapping(cd);
2325       }
2326
2327       while (!toAnalyzeMethodIsEmpty()) {
2328         MethodDescriptor md = toAnalyzeMethodNext();
2329         SSJavaLattice<String> methodLattice = md2lattice.get(md);
2330         if (methodLattice != null) {
2331           ssjava.writeLatticeDotFile(cd, md, methodLattice);
2332           debug_printDescriptorToLocNameMapping(md);
2333         }
2334       }
2335     }
2336
2337   }
2338
2339   private void debug_printDescriptorToLocNameMapping(Descriptor desc) {
2340
2341     LocationInfo info = getLocationInfo(desc);
2342     System.out.println("## " + desc + " ##");
2343     System.out.println(info.getMapDescToInferLocation());
2344     LocationInfo locInfo = getLocationInfo(desc);
2345     System.out.println("mapping=" + locInfo.getMapLocSymbolToDescSet());
2346     System.out.println("###################");
2347
2348   }
2349
2350   private void calculateExtraLocations() {
2351
2352     LinkedList<MethodDescriptor> methodDescList = ssjava.getSortedDescriptors();
2353     for (Iterator iterator = methodDescList.iterator(); iterator.hasNext();) {
2354       MethodDescriptor md = (MethodDescriptor) iterator.next();
2355       if (!ssjava.getMethodContainingSSJavaLoop().equals(md)) {
2356         calculateExtraLocations(md);
2357       }
2358     }
2359
2360   }
2361
2362   private void checkLatticesOfVirtualMethods(MethodDescriptor md) {
2363
2364     if (!md.isStatic()) {
2365       Set<MethodDescriptor> setPossibleCallees = new HashSet<MethodDescriptor>();
2366       setPossibleCallees.addAll(ssjava.getCallGraph().getMethods(md));
2367
2368       for (Iterator iterator = setPossibleCallees.iterator(); iterator.hasNext();) {
2369         MethodDescriptor mdCallee = (MethodDescriptor) iterator.next();
2370         if (!md.equals(mdCallee)) {
2371           checkConsistency(md, mdCallee);
2372         }
2373       }
2374
2375     }
2376
2377   }
2378
2379   private void checkConsistency(MethodDescriptor md1, MethodDescriptor md2) {
2380
2381     // check that two lattice have the same relations between parameters(+PC
2382     // LOC, GLOBAL_LOC RETURN LOC)
2383
2384     List<CompositeLocation> list1 = new ArrayList<CompositeLocation>();
2385     List<CompositeLocation> list2 = new ArrayList<CompositeLocation>();
2386
2387     MethodLocationInfo locInfo1 = getMethodLocationInfo(md1);
2388     MethodLocationInfo locInfo2 = getMethodLocationInfo(md2);
2389
2390     Map<Integer, CompositeLocation> paramMap1 = locInfo1.getMapParamIdxToInferLoc();
2391     Map<Integer, CompositeLocation> paramMap2 = locInfo2.getMapParamIdxToInferLoc();
2392
2393     int numParam = locInfo1.getMapParamIdxToInferLoc().keySet().size();
2394
2395     // add location types of paramters
2396     for (int idx = 0; idx < numParam; idx++) {
2397       list1.add(paramMap1.get(Integer.valueOf(idx)));
2398       list2.add(paramMap2.get(Integer.valueOf(idx)));
2399     }
2400
2401     // add program counter location
2402     list1.add(locInfo1.getPCLoc());
2403     list2.add(locInfo2.getPCLoc());
2404
2405     if (!md1.getReturnType().isVoid()) {
2406       // add return value location
2407       CompositeLocation rtrLoc1 = getMethodLocationInfo(md1).getReturnLoc();
2408       CompositeLocation rtrLoc2 = getMethodLocationInfo(md2).getReturnLoc();
2409       list1.add(rtrLoc1);
2410       list2.add(rtrLoc2);
2411     }
2412
2413     // add global location type
2414     if (md1.isStatic()) {
2415       CompositeLocation globalLoc1 =
2416           new CompositeLocation(new Location(md1, locInfo1.getGlobalLocName()));
2417       CompositeLocation globalLoc2 =
2418           new CompositeLocation(new Location(md2, locInfo2.getGlobalLocName()));
2419       list1.add(globalLoc1);
2420       list2.add(globalLoc2);
2421     }
2422
2423     for (int i = 0; i < list1.size(); i++) {
2424       CompositeLocation locA1 = list1.get(i);
2425       CompositeLocation locA2 = list2.get(i);
2426       for (int k = 0; k < list1.size(); k++) {
2427         if (i != k) {
2428           CompositeLocation locB1 = list1.get(k);
2429           CompositeLocation locB2 = list2.get(k);
2430           boolean r1 = isGreaterThan(getLattice(md1), locA1, locB1);
2431
2432           boolean r2 = isGreaterThan(getLattice(md1), locA2, locB2);
2433
2434           if (r1 != r2) {
2435             throw new Error("The method " + md1 + " is not consistent with the method " + md2
2436                 + ".:: They have a different ordering relation between locations (" + locA1 + ","
2437                 + locB1 + ") and (" + locA2 + "," + locB2 + ").");
2438           }
2439         }
2440       }
2441     }
2442
2443   }
2444
2445   private String getSymbol(int idx, FlowNode node) {
2446     Descriptor desc = node.getDescTuple().get(idx);
2447     return desc.getSymbol();
2448   }
2449
2450   private Descriptor getDescriptor(int idx, FlowNode node) {
2451     Descriptor desc = node.getDescTuple().get(idx);
2452     return desc;
2453   }
2454
2455   private void calculatePCLOC(MethodDescriptor md) {
2456
2457     System.out.println("#CalculatePCLOC");
2458     MethodSummary methodSummary = getMethodSummary(md);
2459     FlowGraph fg = getFlowGraph(md);
2460     Map<Integer, CompositeLocation> mapParamToLoc = methodSummary.getMapParamIdxToInferLoc();
2461
2462     // calculate the initial program counter location
2463     // PC location is higher than location types of parameters which has incoming flows.
2464
2465     Set<NTuple<Location>> paramLocTupleHavingInFlowSet = new HashSet<NTuple<Location>>();
2466     Set<Descriptor> paramDescNOTHavingInFlowSet = new HashSet<Descriptor>();
2467     // Set<FlowNode> paramNodeNOThavingInFlowSet = new HashSet<FlowNode>();
2468
2469     int numParams = fg.getNumParameters();
2470     for (int i = 0; i < numParams; i++) {
2471       FlowNode paramFlowNode = fg.getParamFlowNode(i);
2472       Descriptor prefix = paramFlowNode.getDescTuple().get(0);
2473       NTuple<Descriptor> paramDescTuple = paramFlowNode.getCurrentDescTuple();
2474       NTuple<Location> paramLocTuple = translateToLocTuple(md, paramDescTuple);
2475
2476       Set<FlowNode> inNodeToParamSet = fg.getIncomingNodeSetByPrefix(prefix);
2477       if (inNodeToParamSet.size() > 0) {
2478         // parameter has in-value flows
2479
2480         for (Iterator iterator = inNodeToParamSet.iterator(); iterator.hasNext();) {
2481           FlowNode inNode = (FlowNode) iterator.next();
2482           Set<FlowEdge> outEdgeSet = fg.getOutEdgeSet(inNode);
2483           for (Iterator iterator2 = outEdgeSet.iterator(); iterator2.hasNext();) {
2484             FlowEdge flowEdge = (FlowEdge) iterator2.next();
2485             if (flowEdge.getEndTuple().startsWith(prefix)) {
2486               NTuple<Location> paramLocTupleWithIncomingFlow =
2487                   translateToLocTuple(md, flowEdge.getEndTuple());
2488               paramLocTupleHavingInFlowSet.add(paramLocTupleWithIncomingFlow);
2489             }
2490           }
2491         }
2492
2493         // paramLocTupleHavingInFlowSet.add(paramLocTuple);
2494       } else {
2495         // paramNodeNOThavingInFlowSet.add(fg.getFlowNode(paramDescTuple));
2496         paramDescNOTHavingInFlowSet.add(prefix);
2497       }
2498     }
2499
2500     System.out.println("paramLocTupleHavingInFlowSet=" + paramLocTupleHavingInFlowSet);
2501
2502     if (paramLocTupleHavingInFlowSet.size() > 0
2503     /* && !coversAllParamters(md, fg, paramLocTupleHavingInFlowSet) */) {
2504
2505       // Here, generates a location in the method lattice that is higher than the
2506       // paramLocTupleHavingInFlowSet
2507       NTuple<Location> pcLocTuple =
2508           generateLocTupleRelativeTo(md, paramLocTupleHavingInFlowSet, PCLOC);
2509
2510       NTuple<Descriptor> pcDescTuple = translateToDescTuple(pcLocTuple);
2511
2512       // add ordering relations s.t. PCLOC is higher than all flow nodes except the set of
2513       // parameters that do not have incoming flows
2514
2515       for (Iterator iterator = fg.getNodeSet().iterator(); iterator.hasNext();) {
2516         FlowNode node = (FlowNode) iterator.next();
2517
2518         if (!paramDescNOTHavingInFlowSet.contains(node.getCurrentDescTuple().get(0))) {
2519           fg.addValueFlowEdge(pcDescTuple, node.getDescTuple());
2520         }
2521       }
2522
2523       System.out.println("pcLoc=" + pcLocTuple);
2524
2525       methodSummary.setPCLoc(new CompositeLocation(pcLocTuple));
2526     }
2527   }
2528
2529   private boolean coversAllParamters(MethodDescriptor md, FlowGraph fg,
2530       Set<NTuple<Location>> paramLocTupleHavingInFlowSet) {
2531
2532     int numParam = fg.getNumParameters();
2533     int size = paramLocTupleHavingInFlowSet.size();
2534
2535     if (!md.isStatic()) {
2536
2537       // if the method is not static && there is a parameter composite location &&
2538       // it is started with 'this',
2539       // paramLocTupleHavingInFlowSet need to have 'this' parameter.
2540
2541       FlowNode thisParamNode = fg.getParamFlowNode(0);
2542       NTuple<Location> thisParamLocTuple =
2543           translateToLocTuple(md, thisParamNode.getCurrentDescTuple());
2544
2545       if (!paramLocTupleHavingInFlowSet.contains(thisParamLocTuple)) {
2546
2547         for (Iterator iterator = paramLocTupleHavingInFlowSet.iterator(); iterator.hasNext();) {
2548           NTuple<Location> paramTuple = (NTuple<Location>) iterator.next();
2549           if (paramTuple.size() > 1 && paramTuple.get(0).getLocDescriptor().equals(md.getThis())) {
2550             // paramLocTupleHavingInFlowSet.add(thisParamLocTuple);
2551             // break;
2552             size++;
2553           }
2554         }
2555
2556       }
2557     }
2558
2559     if (size == numParam) {
2560       return true;
2561     } else {
2562       return false;
2563     }
2564
2565   }
2566
2567   private void calculateRETURNLOC(MethodDescriptor md) {
2568
2569     System.out.println("#calculateRETURNLOC= " + md);
2570     // calculate a return location:
2571     // the return location type is lower than all parameters and the location of return values
2572     MethodSummary methodSummary = getMethodSummary(md);
2573     FlowGraph fg = getFlowGraph(md);
2574     Map<Integer, CompositeLocation> mapParamToLoc = methodSummary.getMapParamIdxToInferLoc();
2575     Set<Integer> paramIdxSet = mapParamToLoc.keySet();
2576
2577     if (!md.getReturnType().isVoid()) {
2578       // first, generate the set of return value location types that starts
2579       // with 'this' reference
2580
2581       Set<FlowNode> paramFlowNodeFlowingToReturnValueSet = getParamNodeFlowingToReturnValue(md);
2582       System.out.println("paramFlowNodeFlowingToReturnValueSet="
2583           + paramFlowNodeFlowingToReturnValueSet);
2584
2585       Set<NTuple<Location>> tupleToBeHigherThanReturnLocSet = new HashSet<NTuple<Location>>();
2586       for (Iterator iterator = paramFlowNodeFlowingToReturnValueSet.iterator(); iterator.hasNext();) {
2587         FlowNode fn = (FlowNode) iterator.next();
2588         NTuple<Descriptor> paramDescTuple = fn.getCurrentDescTuple();
2589         tupleToBeHigherThanReturnLocSet.add(translateToLocTuple(md, paramDescTuple));
2590       }
2591
2592       Set<FlowNode> returnNodeSet = fg.getReturnNodeSet();
2593       for (Iterator iterator = returnNodeSet.iterator(); iterator.hasNext();) {
2594         FlowNode returnNode = (FlowNode) iterator.next();
2595         NTuple<Descriptor> returnDescTuple = returnNode.getCurrentDescTuple();
2596         tupleToBeHigherThanReturnLocSet.add(translateToLocTuple(md, returnDescTuple));
2597       }
2598       System.out.println("-flow graph's returnNodeSet=" + returnNodeSet);
2599       System.out.println("tupleSetToBeHigherThanReturnLoc=" + tupleToBeHigherThanReturnLocSet);
2600
2601       // Here, generates a return location in the method lattice that is lower than the
2602       // locFlowingToReturnValueSet
2603       NTuple<Location> returnLocTuple =
2604           generateLocTupleRelativeTo(md, tupleToBeHigherThanReturnLocSet, RLOC);
2605
2606       System.out.println("returnLocTuple=" + returnLocTuple);
2607
2608       NTuple<Descriptor> returnDescTuple = translateToDescTuple(returnLocTuple);
2609       for (Iterator iterator = tupleToBeHigherThanReturnLocSet.iterator(); iterator.hasNext();) {
2610         NTuple<Location> higherTuple = (NTuple<Location>) iterator.next();
2611         fg.addValueFlowEdge(translateToDescTuple(higherTuple), returnDescTuple);
2612       }
2613
2614       fg.getFlowNode(returnDescTuple).setSkeleton(true);
2615       System.out.println("fg node set=" + fg.getNodeSet());
2616
2617       methodSummary.setRETURNLoc(new CompositeLocation(returnLocTuple));
2618
2619       // skip: for (Iterator iterator = returnNodeSet.iterator(); iterator.hasNext();) {
2620       // FlowNode returnNode = (FlowNode) iterator.next();
2621       //
2622       // NTuple<Descriptor> returnDescTuple = returnNode.getCurrentDescTuple();
2623       // NTuple<Location> returnLocTuple = translateToLocTuple(md, returnDescTuple);
2624       //
2625       // if (returnLocTuple.get(0).getLocDescriptor().equals(md.getThis())) {
2626       // // if the location type of the return value matches "this" reference
2627       // // then, check whether this return value is equal to/lower than all
2628       // // of parameters that possibly flow into the return values
2629       // for (Iterator iterator2 = inferParamLocSet.iterator(); iterator2.hasNext();) {
2630       // CompositeLocation paramInferLoc = (CompositeLocation) iterator2.next();
2631       //
2632       // if ((!paramInferLoc.equals(returnLocTuple))
2633       // && !isGreaterThan(methodLattice, paramInferLoc, inferReturnLoc)) {
2634       // continue skip;
2635       // }
2636       // }
2637       // inferFieldReturnLocSet.add(returnLocTuple);
2638       //
2639       // }
2640       // }
2641
2642       // if (inferFieldReturnLocSet.size() > 0) {
2643       //
2644       // // CompositeLocation returnLoc = getLowest(methodLattice, inferFieldReturnLocSet);
2645       // CompositeLocation returnLoc = null;
2646       // if (returnLoc == null) {
2647       // // in this case, assign <'this',bottom> to the RETURNLOC
2648       // returnLoc = new CompositeLocation(new Location(md, md.getThis().getSymbol()));
2649       // returnLoc.addLocation(new Location(md.getClassDesc(), getLattice(md.getClassDesc())
2650       // .getBottomItem()));
2651       // }
2652       // methodInfo.setReturnLoc(returnLoc);
2653       //
2654       // } else {
2655       // String returnLocSymbol = "RETURNLOC";
2656       // CompositeLocation returnLocInferLoc =
2657       // new CompositeLocation(new Location(md, returnLocSymbol));
2658       // methodInfo.setReturnLoc(returnLocInferLoc);
2659       //
2660       // for (Iterator iterator = paramIdxSet.iterator(); iterator.hasNext();) {
2661       // Integer paramIdx = (Integer) iterator.next();
2662       // CompositeLocation inferLoc = mapParamToLoc.get(paramIdx);
2663       // String paramLocLocalSymbol = inferLoc.get(0).getLocIdentifier();
2664       // if (!methodLattice.isGreaterThan(paramLocLocalSymbol, returnLocSymbol)) {
2665       // // TODO
2666       // // addRelationHigherToLower(methodLattice, methodInfo,
2667       // // paramLocLocalSymbol,
2668       // // returnLocSymbol);
2669       // }
2670       // }
2671       //
2672       // for (Iterator iterator = returnNodeSet.iterator(); iterator.hasNext();) {
2673       // FlowNode returnNode = (FlowNode) iterator.next();
2674       // CompositeLocation inferLoc =
2675       // generateInferredCompositeLocation(methodInfo, fg.getLocationTuple(returnNode));
2676       // if (!isGreaterThan(methodLattice, inferLoc, returnLocInferLoc)) {
2677       // // TODO
2678       // // addRelation(methodLattice, methodInfo, inferLoc,
2679       // // returnLocInferLoc);
2680       // }
2681       // }
2682       //
2683       // }
2684
2685     }
2686   }
2687
2688   private void calculateExtraLocations(MethodDescriptor md) {
2689     // calcualte pcloc, returnloc,...
2690
2691     System.out.println("\nSSJAVA:Calculate PCLOC/RETURNLOC locations: " + md);
2692
2693     calculatePCLOC(md);
2694     calculateRETURNLOC(md);
2695
2696   }
2697
2698   private NTuple<Location> generateLocTupleRelativeTo(MethodDescriptor md,
2699       Set<NTuple<Location>> paramLocTupleHavingInFlowSet, String locNamePrefix) {
2700
2701     System.out.println("-generateLocTupleRelativeTo=" + paramLocTupleHavingInFlowSet);
2702
2703     NTuple<Location> higherLocTuple = new NTuple<Location>();
2704
2705     VarDescriptor thisVarDesc = md.getThis();
2706     // check if all paramter loc tuple is started with 'this' reference
2707     boolean hasParamNotStartedWithThisRef = false;
2708
2709     int minSize = 0;
2710
2711     Set<NTuple<Location>> paramLocTupleStartedWithThis = new HashSet<NTuple<Location>>();
2712
2713     next: for (Iterator iterator = paramLocTupleHavingInFlowSet.iterator(); iterator.hasNext();) {
2714       NTuple<Location> paramLocTuple = (NTuple<Location>) iterator.next();
2715       Descriptor paramLocalDesc = paramLocTuple.get(0).getLocDescriptor();
2716       if (!paramLocalDesc.equals(thisVarDesc)) {
2717
2718         Set<FlowNode> inNodeSet = getFlowGraph(md).getIncomingNodeSetByPrefix(paramLocalDesc);
2719         for (Iterator iterator2 = inNodeSet.iterator(); iterator2.hasNext();) {
2720           FlowNode flowNode = (FlowNode) iterator2.next();
2721           if (flowNode.getDescTuple().startsWith(thisVarDesc)) {
2722             System.out.println("paramLocTuple=" + paramLocTuple + " is lower than THIS");
2723             continue next;
2724           }
2725         }
2726         hasParamNotStartedWithThisRef = true;
2727
2728       } else if (paramLocTuple.size() > 1) {
2729         paramLocTupleStartedWithThis.add(paramLocTuple);
2730         if (minSize == 0 || minSize > paramLocTuple.size()) {
2731           minSize = paramLocTuple.size();
2732         }
2733       }
2734     }
2735
2736     System.out.println("---paramLocTupleStartedWithThis=" + paramLocTupleStartedWithThis);
2737     Descriptor enclosingDesc = md;
2738     if (hasParamNotStartedWithThisRef) {
2739       // in this case, PCLOC will be the local location
2740     } else {
2741       // all parameter is started with 'this', so PCLOC will be set relative to the composite
2742       // location started with 'this'.
2743       for (int idx = 0; idx < minSize - 1; idx++) {
2744         Set<Descriptor> locDescSet = new HashSet<Descriptor>();
2745         Location curLoc = null;
2746         NTuple<Location> paramLocTuple = null;
2747         for (Iterator iterator = paramLocTupleStartedWithThis.iterator(); iterator.hasNext();) {
2748           paramLocTuple = (NTuple<Location>) iterator.next();
2749           System.out.println("-----paramLocTuple=" + paramLocTuple + "  idx=" + idx);
2750           curLoc = paramLocTuple.get(idx);
2751           Descriptor locDesc = curLoc.getLocDescriptor();
2752           locDescSet.add(locDesc);
2753         }
2754         System.out.println("-----locDescSet=" + locDescSet + " idx=" + idx);
2755         if (locDescSet.size() != 1) {
2756           break;
2757         }
2758         Location newLocElement = new Location(curLoc.getDescriptor(), curLoc.getLocDescriptor());
2759         higherLocTuple.add(newLocElement);
2760         enclosingDesc = getClassTypeDescriptor(curLoc.getLocDescriptor());
2761       }
2762
2763     }
2764
2765     String pcLocIdentifier = locNamePrefix + (locSeed++);
2766     NameDescriptor pcLocDesc = new NameDescriptor(pcLocIdentifier);
2767     Location newLoc = new Location(enclosingDesc, pcLocDesc);
2768     higherLocTuple.add(newLoc);
2769
2770     System.out.println("---new loc tuple=" + higherLocTuple);
2771
2772     return higherLocTuple;
2773
2774   }
2775
2776   public ClassDescriptor getClassTypeDescriptor(Descriptor in) {
2777
2778     if (in instanceof VarDescriptor) {
2779       return ((VarDescriptor) in).getType().getClassDesc();
2780     } else if (in instanceof FieldDescriptor) {
2781       return ((FieldDescriptor) in).getType().getClassDesc();
2782     }
2783     // else if (in instanceof LocationDescriptor) {
2784     // // here is the case that the descriptor 'in' is the last element of the assigned composite
2785     // // location
2786     // return ((VarDescriptor) locTuple.get(0).getLocDescriptor()).getType().getClassDesc();
2787     // }
2788     else {
2789       return null;
2790     }
2791
2792   }
2793
2794   private Set<NTuple<Location>> calculateHighestLocTupleSet(
2795       Set<NTuple<Location>> paramLocTupleHavingInFlowSet) {
2796
2797     Set<NTuple<Location>> highestSet = new HashSet<NTuple<Location>>();
2798
2799     Iterator<NTuple<Location>> iterator = paramLocTupleHavingInFlowSet.iterator();
2800     NTuple<Location> highest = iterator.next();
2801
2802     for (; iterator.hasNext();) {
2803       NTuple<Location> curLocTuple = (NTuple<Location>) iterator.next();
2804       if (isHigherThan(curLocTuple, highest)) {
2805         System.out.println(curLocTuple + " is greater than " + highest);
2806         highest = curLocTuple;
2807       }
2808     }
2809
2810     highestSet.add(highest);
2811
2812     MethodDescriptor md = (MethodDescriptor) highest.get(0).getDescriptor();
2813     VarDescriptor thisVarDesc = md.getThis();
2814
2815     System.out.println("highest=" + highest);
2816
2817     for (Iterator<NTuple<Location>> iter = paramLocTupleHavingInFlowSet.iterator(); iter.hasNext();) {
2818       NTuple<Location> curLocTuple = iter.next();
2819
2820       if (!curLocTuple.equals(highest) && !hasOrderingRelation(highest, curLocTuple)) {
2821
2822         System.out.println("add it to the highest set=" + curLocTuple);
2823         highestSet.add(curLocTuple);
2824
2825       }
2826     }
2827
2828     return highestSet;
2829
2830   }
2831
2832   private void calculateExtraLocations2(MethodDescriptor md) {
2833     // calcualte pcloc, returnloc,...
2834
2835     SSJavaLattice<String> methodLattice = getMethodLattice(md);
2836     MethodLocationInfo methodInfo = getMethodLocationInfo(md);
2837     FlowGraph fg = getFlowGraph(md);
2838     Set<FlowNode> nodeSet = fg.getNodeSet();
2839
2840     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
2841       FlowNode flowNode = (FlowNode) iterator.next();
2842       if (flowNode.isDeclaratonNode()) {
2843         CompositeLocation inferLoc = methodInfo.getInferLocation(flowNode.getDescTuple().get(0));
2844         String locIdentifier = inferLoc.get(0).getLocIdentifier();
2845         if (!methodLattice.containsKey(locIdentifier)) {
2846           methodLattice.put(locIdentifier);
2847         }
2848
2849       }
2850     }
2851
2852     Map<Integer, CompositeLocation> mapParamToLoc = methodInfo.getMapParamIdxToInferLoc();
2853     Set<Integer> paramIdxSet = mapParamToLoc.keySet();
2854
2855     if (!ssjava.getMethodContainingSSJavaLoop().equals(md)) {
2856       // calculate the initial program counter location
2857       // PC location is higher than location types of all parameters
2858       String pcLocSymbol = "PCLOC";
2859
2860       Set<CompositeLocation> paramInFlowSet = new HashSet<CompositeLocation>();
2861
2862       for (Iterator iterator = paramIdxSet.iterator(); iterator.hasNext();) {
2863         Integer paramIdx = (Integer) iterator.next();
2864
2865         FlowNode paramFlowNode = fg.getParamFlowNode(paramIdx);
2866
2867         if (fg.getIncomingFlowNodeSet(paramFlowNode).size() > 0) {
2868           // parameter has in-value flows
2869           CompositeLocation inferLoc = mapParamToLoc.get(paramIdx);
2870           paramInFlowSet.add(inferLoc);
2871         }
2872       }
2873
2874       if (paramInFlowSet.size() > 0) {
2875         CompositeLocation lowestLoc = getLowest(methodLattice, paramInFlowSet);
2876         assert (lowestLoc != null);
2877         methodInfo.setPCLoc(lowestLoc);
2878       }
2879
2880     }
2881
2882     // calculate a return location
2883     // the return location type is lower than all parameters and location
2884     // types
2885     // of return values
2886     if (!md.getReturnType().isVoid()) {
2887       // first, generate the set of return value location types that starts
2888       // with
2889       // 'this' reference
2890
2891       Set<CompositeLocation> inferFieldReturnLocSet = new HashSet<CompositeLocation>();
2892
2893       Set<FlowNode> paramFlowNode = getParamNodeFlowingToReturnValue(md);
2894       Set<CompositeLocation> inferParamLocSet = new HashSet<CompositeLocation>();
2895       if (paramFlowNode != null) {
2896         for (Iterator iterator = paramFlowNode.iterator(); iterator.hasNext();) {
2897           FlowNode fn = (FlowNode) iterator.next();
2898           CompositeLocation inferLoc =
2899               generateInferredCompositeLocation(methodInfo, getFlowGraph(md).getLocationTuple(fn));
2900           inferParamLocSet.add(inferLoc);
2901         }
2902       }
2903
2904       Set<FlowNode> returnNodeSet = fg.getReturnNodeSet();
2905
2906       skip: for (Iterator iterator = returnNodeSet.iterator(); iterator.hasNext();) {
2907         FlowNode returnNode = (FlowNode) iterator.next();
2908         CompositeLocation inferReturnLoc =
2909             generateInferredCompositeLocation(methodInfo, fg.getLocationTuple(returnNode));
2910         if (inferReturnLoc.get(0).getLocIdentifier().equals("this")) {
2911           // if the location type of the return value matches "this" reference
2912           // then, check whether this return value is equal to/lower than all
2913           // of
2914           // parameters that possibly flow into the return values
2915           for (Iterator iterator2 = inferParamLocSet.iterator(); iterator2.hasNext();) {
2916             CompositeLocation paramInferLoc = (CompositeLocation) iterator2.next();
2917
2918             if ((!paramInferLoc.equals(inferReturnLoc))
2919                 && !isGreaterThan(methodLattice, paramInferLoc, inferReturnLoc)) {
2920               continue skip;
2921             }
2922           }
2923           inferFieldReturnLocSet.add(inferReturnLoc);
2924
2925         }
2926       }
2927
2928       if (inferFieldReturnLocSet.size() > 0) {
2929
2930         CompositeLocation returnLoc = getLowest(methodLattice, inferFieldReturnLocSet);
2931         if (returnLoc == null) {
2932           // in this case, assign <'this',bottom> to the RETURNLOC
2933           returnLoc = new CompositeLocation(new Location(md, md.getThis().getSymbol()));
2934           returnLoc.addLocation(new Location(md.getClassDesc(), getLattice(md.getClassDesc())
2935               .getBottomItem()));
2936         }
2937         methodInfo.setReturnLoc(returnLoc);
2938
2939       } else {
2940         String returnLocSymbol = "RETURNLOC";
2941         CompositeLocation returnLocInferLoc =
2942             new CompositeLocation(new Location(md, returnLocSymbol));
2943         methodInfo.setReturnLoc(returnLocInferLoc);
2944
2945         for (Iterator iterator = paramIdxSet.iterator(); iterator.hasNext();) {
2946           Integer paramIdx = (Integer) iterator.next();
2947           CompositeLocation inferLoc = mapParamToLoc.get(paramIdx);
2948           String paramLocLocalSymbol = inferLoc.get(0).getLocIdentifier();
2949           if (!methodLattice.isGreaterThan(paramLocLocalSymbol, returnLocSymbol)) {
2950             // TODO
2951             // addRelationHigherToLower(methodLattice, methodInfo,
2952             // paramLocLocalSymbol,
2953             // returnLocSymbol);
2954           }
2955         }
2956
2957         for (Iterator iterator = returnNodeSet.iterator(); iterator.hasNext();) {
2958           FlowNode returnNode = (FlowNode) iterator.next();
2959           CompositeLocation inferLoc =
2960               generateInferredCompositeLocation(methodInfo, fg.getLocationTuple(returnNode));
2961           if (!isGreaterThan(methodLattice, inferLoc, returnLocInferLoc)) {
2962             // TODO
2963             // addRelation(methodLattice, methodInfo, inferLoc,
2964             // returnLocInferLoc);
2965           }
2966         }
2967
2968       }
2969
2970     }
2971   }
2972
2973   private Set<String> getHigherLocSymbolThan(SSJavaLattice<String> lattice, String loc) {
2974     Set<String> higherLocSet = new HashSet<String>();
2975
2976     Set<String> locSet = lattice.getTable().keySet();
2977     for (Iterator iterator = locSet.iterator(); iterator.hasNext();) {
2978       String element = (String) iterator.next();
2979       if (lattice.isGreaterThan(element, loc) && (!element.equals(lattice.getTopItem()))) {
2980         higherLocSet.add(element);
2981       }
2982     }
2983     return higherLocSet;
2984   }
2985
2986   private CompositeLocation getLowest(SSJavaLattice<String> methodLattice,
2987       Set<CompositeLocation> set) {
2988
2989     CompositeLocation lowest = set.iterator().next();
2990
2991     if (set.size() == 1) {
2992       return lowest;
2993     }
2994
2995     for (Iterator iterator = set.iterator(); iterator.hasNext();) {
2996       CompositeLocation loc = (CompositeLocation) iterator.next();
2997
2998       if ((!loc.equals(lowest)) && (!isComparable(methodLattice, lowest, loc))) {
2999         // if there is a case where composite locations are incomparable, just
3000         // return null
3001         return null;
3002       }
3003
3004       if ((!loc.equals(lowest)) && isGreaterThan(methodLattice, lowest, loc)) {
3005         lowest = loc;
3006       }
3007     }
3008     return lowest;
3009   }
3010
3011   private boolean isComparable(SSJavaLattice<String> methodLattice, CompositeLocation comp1,
3012       CompositeLocation comp2) {
3013
3014     int size = comp1.getSize() >= comp2.getSize() ? comp2.getSize() : comp1.getSize();
3015
3016     for (int idx = 0; idx < size; idx++) {
3017       Location loc1 = comp1.get(idx);
3018       Location loc2 = comp2.get(idx);
3019
3020       Descriptor desc1 = loc1.getDescriptor();
3021       Descriptor desc2 = loc2.getDescriptor();
3022
3023       if (!desc1.equals(desc2)) {
3024         throw new Error("Fail to compare " + comp1 + " and " + comp2);
3025       }
3026
3027       String symbol1 = loc1.getLocIdentifier();
3028       String symbol2 = loc2.getLocIdentifier();
3029
3030       SSJavaLattice<String> lattice;
3031       if (idx == 0) {
3032         lattice = methodLattice;
3033       } else {
3034         lattice = getLattice(desc1);
3035       }
3036
3037       if (symbol1.equals(symbol2)) {
3038         continue;
3039       } else if (!lattice.isComparable(symbol1, symbol2)) {
3040         return false;
3041       }
3042
3043     }
3044
3045     return true;
3046   }
3047
3048   private boolean isGreaterThan(SSJavaLattice<String> methodLattice, CompositeLocation comp1,
3049       CompositeLocation comp2) {
3050
3051     int size = comp1.getSize() >= comp2.getSize() ? comp2.getSize() : comp1.getSize();
3052
3053     for (int idx = 0; idx < size; idx++) {
3054       Location loc1 = comp1.get(idx);
3055       Location loc2 = comp2.get(idx);
3056
3057       Descriptor desc1 = loc1.getDescriptor();
3058       Descriptor desc2 = loc2.getDescriptor();
3059
3060       if (!desc1.equals(desc2)) {
3061         throw new Error("Fail to compare " + comp1 + " and " + comp2);
3062       }
3063
3064       String symbol1 = loc1.getLocIdentifier();
3065       String symbol2 = loc2.getLocIdentifier();
3066
3067       SSJavaLattice<String> lattice;
3068       if (idx == 0) {
3069         lattice = methodLattice;
3070       } else {
3071         lattice = getLattice(desc1);
3072       }
3073
3074       if (symbol1.equals(symbol2)) {
3075         continue;
3076       } else if (lattice.isGreaterThan(symbol1, symbol2)) {
3077         return true;
3078       } else {
3079         return false;
3080       }
3081
3082     }
3083
3084     return false;
3085   }
3086
3087   private void contributeCalleeFlows(MethodInvokeNode min, MethodDescriptor mdCaller,
3088       MethodDescriptor mdCallee) {
3089
3090     System.out.println("\n##contributeCalleeFlows callee=" + mdCallee + "TO caller=" + mdCaller);
3091
3092     getSubGlobalFlowGraph(mdCallee);
3093
3094   }
3095
3096   private GlobalFlowGraph getSubGlobalFlowGraph(MethodDescriptor md) {
3097     return mapMethodDescriptorToSubGlobalFlowGraph.get(md);
3098   }
3099
3100   private void propagateFlowsToCallerWithNoCompositeLocation(MethodInvokeNode min,
3101       MethodDescriptor mdCaller, MethodDescriptor mdCallee) {
3102
3103     // if the parameter A reaches to the parameter B
3104     // then, add an edge the argument A -> the argument B to the caller's flow
3105     // graph
3106
3107     FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
3108     FlowGraph callerFlowGraph = getFlowGraph(mdCaller);
3109     int numParam = calleeFlowGraph.getNumParameters();
3110
3111     for (int i = 0; i < numParam; i++) {
3112       for (int k = 0; k < numParam; k++) {
3113
3114         if (i != k) {
3115
3116           FlowNode paramNode1 = calleeFlowGraph.getParamFlowNode(i);
3117           FlowNode paramNode2 = calleeFlowGraph.getParamFlowNode(k);
3118
3119           NTuple<Descriptor> arg1Tuple = getNodeTupleByArgIdx(min, i);
3120           NTuple<Descriptor> arg2Tuple = getNodeTupleByArgIdx(min, k);
3121
3122           // check if the callee propagates an ordering constraints through
3123           // parameters
3124
3125           Set<FlowNode> localReachSet = calleeFlowGraph.getLocalReachFlowNodeSetFrom(paramNode1);
3126           System.out.println("-param1=" + paramNode1 + " is higher than param2=" + paramNode2);
3127           // System.out.println("-- localReachSet from param1=" + localReachSet);
3128
3129           NTuple<Descriptor> paramDescTuple1 = paramNode1.getCurrentDescTuple();
3130           NTuple<Descriptor> paramDescTuple2 = paramNode2.getCurrentDescTuple();
3131
3132           System.out.println("-param1CurTuple=" + paramDescTuple1 + " param2CurTuple="
3133               + paramDescTuple2);
3134           if (paramDescTuple1.get(0).equals(paramDescTuple2.get(0))) {
3135             // if two parameters share the same prefix
3136             // it already has been assigned to a composite location
3137             // so we don't need to add an additional ordering relation caused by these two
3138             // paramters.
3139             continue;
3140           }
3141
3142           if (arg1Tuple.size() > 0 && arg2Tuple.size() > 0 && localReachSet.contains(paramNode2)) {
3143             // need to propagate an ordering relation s.t. arg1 is higher
3144             // than arg2
3145
3146             // add a new flow between the corresponding arguments.
3147             callerFlowGraph.addValueFlowEdge(arg1Tuple, arg2Tuple);
3148             System.out.println("arg1=" + arg1Tuple + "   arg2=" + arg2Tuple);
3149
3150             // System.out
3151             // .println("-arg1Tuple=" + arg1Tuple + " is higher than arg2Tuple=" + arg2Tuple);
3152
3153           }
3154
3155           System.out.println();
3156         }
3157       }
3158     }
3159
3160     // if a parameter has a composite location and the first element of the parameter location
3161     // matches the callee's 'this'
3162     // we have a more specific constraint: the caller's corresponding argument is higher than the
3163     // parameter location which is translated into the caller
3164
3165     for (int idx = 0; idx < numParam; idx++) {
3166       FlowNode paramNode = calleeFlowGraph.getParamFlowNode(idx);
3167       CompositeLocation compLoc = paramNode.getCompositeLocation();
3168       if (compLoc != null) {
3169         System.out.println("$$$COMPLOC CASE=" + compLoc);
3170         NTuple<Descriptor> argTuple = getNodeTupleByArgIdx(min, idx);
3171         NTuple<Descriptor> translatedParamTuple = translateCompositeLocationToCaller(min, compLoc);
3172         System.out.println("add a flow edge= " + argTuple + "->" + translatedParamTuple);
3173         callerFlowGraph.addValueFlowEdge(argTuple, translatedParamTuple);
3174       }
3175     }
3176
3177   }
3178
3179   private void propagateFlowsToCaller(MethodInvokeNode min, MethodDescriptor mdCaller,
3180       MethodDescriptor mdCallee) {
3181
3182     System.out.println("\n##PROPAGATE callee=" + mdCallee + "TO caller=" + mdCaller);
3183
3184     // if the parameter A reaches to the parameter B
3185     // then, add an edge the argument A -> the argument B to the caller's flow
3186     // graph
3187
3188     // TODO
3189     // also if a parameter is a composite location and is started with "this"
3190     // reference,
3191     // need to make sure that the corresponding argument is higher than the
3192     // translated location of
3193     // the parameter.
3194
3195     FlowGraph calleeFlowGraph = getFlowGraph(mdCallee);
3196     FlowGraph callerFlowGraph = getFlowGraph(mdCaller);
3197     int numParam = calleeFlowGraph.getNumParameters();
3198
3199     for (int i = 0; i < numParam; i++) {
3200       for (int k = 0; k < numParam; k++) {
3201
3202         if (i != k) {
3203
3204           FlowNode paramNode1 = calleeFlowGraph.getParamFlowNode(i);
3205           FlowNode paramNode2 = calleeFlowGraph.getParamFlowNode(k);
3206
3207           System.out.println("param1=" + paramNode1 + " curDescTuple="
3208               + paramNode1.getCurrentDescTuple());
3209           System.out.println("param2=" + paramNode2 + " curDescTuple="
3210               + paramNode2.getCurrentDescTuple());
3211
3212           // TODO: deprecated method
3213           // NodeTupleSet tupleSetArg1 = getNodeTupleSetByArgIdx(min, i);
3214           // NodeTupleSet tupleSetArg2 = getNodeTupleSetByArgIdx(min, k);
3215           NodeTupleSet tupleSetArg1 = null;
3216           NodeTupleSet tupleSetArg2 = null;
3217
3218           for (Iterator<NTuple<Descriptor>> iter1 = tupleSetArg1.iterator(); iter1.hasNext();) {
3219             NTuple<Descriptor> arg1Tuple = iter1.next();
3220
3221             for (Iterator<NTuple<Descriptor>> iter2 = tupleSetArg2.iterator(); iter2.hasNext();) {
3222               NTuple<Descriptor> arg2Tuple = iter2.next();
3223
3224               // check if the callee propagates an ordering constraints through
3225               // parameters
3226
3227               Set<FlowNode> localReachSet =
3228                   calleeFlowGraph.getLocalReachFlowNodeSetFrom(paramNode1);
3229
3230               if (localReachSet.contains(paramNode2)) {
3231                 // need to propagate an ordering relation s.t. arg1 is higher
3232                 // than arg2
3233
3234                 System.out
3235                     .println("-param1=" + paramNode1 + " is higher than param2=" + paramNode2);
3236                 System.out.println("-arg1Tuple=" + arg1Tuple + " is higher than arg2Tuple="
3237                     + arg2Tuple);
3238
3239                 if (!min.getMethod().isStatic()) {
3240                   // check if this is the case that values flow to/from the
3241                   // current object reference 'this'
3242
3243                   NTuple<Descriptor> baseTuple = mapMethodInvokeNodeToBaseTuple.get(min);
3244                   Descriptor baseRef = baseTuple.get(baseTuple.size() - 1);
3245
3246                   System.out.println("paramNode1.getCurrentDescTuple()="
3247                       + paramNode1.getCurrentDescTuple());
3248                   // calculate the prefix of the argument
3249
3250                   if (arg2Tuple.size() == 1 && arg2Tuple.get(0).equals(baseRef)) {
3251                     // in this case, the callee flow causes a caller flow to the
3252                     // object whose method
3253                     // is invoked.
3254
3255                     if (!paramNode1.getCurrentDescTuple().startsWith(mdCallee.getThis())) {
3256                       // check whether ???
3257
3258                       NTuple<Descriptor> param1Prefix =
3259                           calculatePrefixForParam(callerFlowGraph, calleeFlowGraph, min, arg1Tuple,
3260                               paramNode1);
3261
3262                       if (param1Prefix != null && param1Prefix.startsWith(mdCallee.getThis())) {
3263                         // in this case, we need to create a new edge
3264                         // 'this.FIELD'->'this'
3265                         // but we couldn't... instead we assign a new composite
3266                         // location started
3267                         // with 'this' reference to the corresponding parameter
3268
3269                         CompositeLocation compLocForParam1 =
3270                             generateCompositeLocation(mdCallee, param1Prefix);
3271
3272                         System.out
3273                             .println("set comp loc=" + compLocForParam1 + " to " + paramNode1);
3274                         paramNode1.setCompositeLocation(compLocForParam1);
3275
3276                         // then, we need to make sure that the corresponding
3277                         // argument in the caller
3278                         // is required to be higher than or equal to the
3279                         // translated parameter
3280                         // location
3281
3282                         NTuple<Descriptor> translatedParamTuple =
3283                             translateCompositeLocationToCaller(min, compLocForParam1);
3284
3285                         // TODO : check if the arg >= the tranlated parameter
3286
3287                         System.out.println("add a flow edge= " + arg1Tuple + "->"
3288                             + translatedParamTuple);
3289                         callerFlowGraph.addValueFlowEdge(arg1Tuple, translatedParamTuple);
3290
3291                         continue;
3292
3293                       }
3294
3295                     } else {
3296                       // param1 has already been assigned a composite location
3297
3298                       System.out.println("--param1 has already been assigned a composite location");
3299                       CompositeLocation compLocForParam1 = paramNode1.getCompositeLocation();
3300                       NTuple<Descriptor> translatedParamTuple =
3301                           translateCompositeLocationToCaller(min, compLocForParam1);
3302
3303                       // TODO : check if the arg >= the tranlated parameter
3304
3305                       System.out.println("add a flow edge= " + arg1Tuple + "->"
3306                           + translatedParamTuple);
3307                       callerFlowGraph.addValueFlowEdge(arg1Tuple, translatedParamTuple);
3308
3309                       continue;
3310
3311                     }
3312
3313                   } else if (arg1Tuple.size() == 1 && arg1Tuple.get(0).equals(baseRef)) {
3314                     // in this case, the callee flow causes a caller flow
3315                     // originated from the object
3316                     // whose
3317                     // method is invoked.
3318
3319                     System.out.println("###FROM CASE");
3320
3321                     if (!paramNode2.getCurrentDescTuple().startsWith(mdCallee.getThis())) {
3322
3323                       NTuple<Descriptor> param2Prefix =
3324                           calculatePrefixForParam(callerFlowGraph, calleeFlowGraph, min, arg2Tuple,
3325                               paramNode2);
3326
3327                       if (param2Prefix != null && param2Prefix.startsWith(mdCallee.getThis())) {
3328                         // in this case, we need to create a new edge 'this' ->
3329                         // 'this.FIELD' but we couldn't... instead we assign the
3330                         // corresponding
3331                         // parameter a new composite location started with
3332                         // 'this' reference
3333
3334                         CompositeLocation compLocForParam2 =
3335                             generateCompositeLocation(mdCallee, param2Prefix);
3336
3337                         // System.out.println("set comp loc=" + compLocForParam2
3338                         // +
3339                         // " to " + paramNode2);
3340                         paramNode1.setCompositeLocation(compLocForParam2);
3341                         continue;
3342                       }
3343                     }
3344
3345                   }
3346                 }
3347