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