changes + bring up uncommited previous changes.
[IRC.git] / Robust / src / Analysis / SSJava / BuildLattice.java
1 package Analysis.SSJava;
2
3 import java.util.HashMap;
4 import java.util.HashSet;
5 import java.util.Iterator;
6 import java.util.Map;
7 import java.util.Set;
8
9 import IR.ClassDescriptor;
10 import IR.Descriptor;
11 import IR.MethodDescriptor;
12 import IR.NameDescriptor;
13 import Util.Pair;
14
15 public class BuildLattice {
16
17   private LocationInference infer;
18   private Map<HNode, TripleItem> mapSharedNodeToTripleItem;
19   private Map<HNode, Integer> mapHNodeToHighestIndex;
20
21   private Map<Descriptor, Map<TripleItem, String>> mapDescToIntermediateLocMap;
22
23   private Map<Pair<HNode, HNode>, Integer> mapItemToHighestIndex;
24
25   public BuildLattice(LocationInference infer) {
26     this.infer = infer;
27     this.mapSharedNodeToTripleItem = new HashMap<HNode, TripleItem>();
28     this.mapHNodeToHighestIndex = new HashMap<HNode, Integer>();
29     this.mapItemToHighestIndex = new HashMap<Pair<HNode, HNode>, Integer>();
30     this.mapDescToIntermediateLocMap = new HashMap<Descriptor, Map<TripleItem, String>>();
31   }
32
33   public SSJavaLattice<String> buildLattice(Descriptor desc) {
34
35     HierarchyGraph inputGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
36     LocationSummary locSummary = infer.getLocationSummary(desc);
37
38     HierarchyGraph naiveGraph = infer.getSimpleHierarchyGraph(desc);
39
40     // I don't think we need to keep the below if statement anymore
41     // because hierarchy graph does not have any composite location
42     Set<HNode> nodeSetWithCompositeLocation = new HashSet<HNode>();
43     if (desc instanceof MethodDescriptor) {
44       FlowGraph flowGraph = infer.getFlowGraph((MethodDescriptor) desc);
45
46       for (Iterator iterator = inputGraph.getNodeSet().iterator(); iterator.hasNext();) {
47         HNode hnode = (HNode) iterator.next();
48         Descriptor hnodeDesc = hnode.getDescriptor();
49         if (hnodeDesc != null) {
50           NTuple<Descriptor> descTuple = new NTuple<Descriptor>();
51           descTuple.add(hnodeDesc);
52
53           if (flowGraph.contains(descTuple)) {
54             FlowNode flowNode = flowGraph.getFlowNode(descTuple);
55             if (flowNode.getCompositeLocation() != null) {
56               nodeSetWithCompositeLocation.add(hnode);
57             }
58           }
59
60         }
61       }
62
63     }
64
65     // lattice generation for the native approach
66     BasisSet naiveBasisSet = naiveGraph.computeBasisSet(nodeSetWithCompositeLocation);
67     // debug_print(inputGraph);
68
69     Family naiveFamily = generateFamily(naiveBasisSet);
70     Map<Set<Integer>, Set<Set<Integer>>> naive_mapImSucc =
71         coveringGraph(naiveBasisSet, naiveFamily);
72
73     SSJavaLattice<String> naive_lattice =
74         buildLattice(desc, naiveBasisSet, naiveGraph, null, naive_mapImSucc);
75     LocationInference.numLocationsNaive += naive_lattice.getKeySet().size();
76
77     // lattice generation for the proposed approach
78     BasisSet basisSet = inputGraph.computeBasisSet(nodeSetWithCompositeLocation);
79     // debug_print(inputGraph);
80
81     Family family = generateFamily(basisSet);
82     Map<Set<Integer>, Set<Set<Integer>>> mapImSucc = coveringGraph(basisSet, family);
83
84     SSJavaLattice<String> lattice = buildLattice(desc, basisSet, inputGraph, locSummary, mapImSucc);
85     return lattice;
86
87   }
88
89   public void setIntermediateLocMap(Descriptor desc, Map<TripleItem, String> map) {
90     mapDescToIntermediateLocMap.put(desc, map);
91   }
92
93   public Map<TripleItem, String> getIntermediateLocMap(Descriptor desc) {
94     if (!mapDescToIntermediateLocMap.containsKey(desc)) {
95       mapDescToIntermediateLocMap.put(desc, new HashMap<TripleItem, String>());
96     }
97     return mapDescToIntermediateLocMap.get(desc);
98   }
99
100   private Descriptor getParent(Descriptor desc) {
101     if (desc instanceof MethodDescriptor) {
102       MethodDescriptor md = (MethodDescriptor) desc;
103       ClassDescriptor cd = md.getClassDesc();
104       return infer.getParentMethodDesc(cd, md);
105     } else {
106       return ((ClassDescriptor) desc).getSuperDesc();
107     }
108   }
109
110   private SSJavaLattice<String> buildLattice(Descriptor desc, BasisSet basisSet,
111       HierarchyGraph inputGraph, LocationSummary locSummary,
112       Map<Set<Integer>, Set<Set<Integer>>> mapImSucc) {
113
114     System.out.println("\nBuild Lattice:" + inputGraph.getName());
115
116     SSJavaLattice<String> lattice =
117         new SSJavaLattice<String>(SSJavaAnalysis.TOP, SSJavaAnalysis.BOTTOM);
118
119     Map<Set<Integer>, String> mapFToLocName = new HashMap<Set<Integer>, String>();
120
121     Set<Set<Integer>> keySet = mapImSucc.keySet();
122     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
123       Set<Integer> higher = (Set<Integer>) iterator.next();
124
125       String higherName = generateElementName(basisSet, inputGraph, mapFToLocName, higher);
126
127       HNode higherNode = inputGraph.getHNode(higherName);
128
129       if (higherNode == null) {
130         NameDescriptor d = new NameDescriptor(higherName);
131         higherNode = inputGraph.getHNode(d);
132         higherNode.setSkeleton(true);
133       }
134
135       if (higherNode != null && higherNode.isSharedNode()) {
136         lattice.addSharedLoc(higherName);
137       }
138       Set<Descriptor> descSet = inputGraph.getDescSetOfNode(higherNode);
139       // System.out.println("higherName=" + higherName + "  higherNode=" + higherNode + "  descSet="
140       // + descSet);
141
142       if (locSummary != null) {
143         for (Iterator iterator2 = descSet.iterator(); iterator2.hasNext();) {
144           Descriptor d = (Descriptor) iterator2.next();
145           locSummary.addMapHNodeNameToLocationName(d.getSymbol(), higherName);
146         }
147       }
148
149       // locSummary.addMapHNodeNameToLocationName(higherName, higherName);
150
151       Set<Set<Integer>> lowerSet = mapImSucc.get(higher);
152       for (Iterator iterator2 = lowerSet.iterator(); iterator2.hasNext();) {
153         Set<Integer> lower = (Set<Integer>) iterator2.next();
154
155         String lowerName = generateElementName(basisSet, inputGraph, mapFToLocName, lower);
156         HNode lowerNode = inputGraph.getHNode(lowerName);
157
158         if (lowerNode == null && !lowerName.equals(SSJavaAnalysis.BOTTOM)) {
159           NameDescriptor d = new NameDescriptor(lowerName);
160           lowerNode = inputGraph.getHNode(d);
161           lowerNode.setSkeleton(true);
162         }
163
164         if (lowerNode != null && !inputGraph.isDirectlyConnectedTo(higherNode, lowerNode)) {
165           inputGraph.addEdge(higherNode, lowerNode);
166         }
167
168         if (lowerNode != null && lowerNode.isSharedNode()) {
169           lattice.addSharedLoc(lowerName);
170         }
171
172         Set<Descriptor> lowerDescSet = inputGraph.getDescSetOfNode(lowerNode);
173         // System.out.println("lowerName=" + lowerName + "  lowerNode=" + lowerNode + "  descSet="
174         // + lowerDescSet);
175         if (locSummary != null) {
176           for (Iterator iterator3 = lowerDescSet.iterator(); iterator3.hasNext();) {
177             Descriptor d = (Descriptor) iterator3.next();
178             locSummary.addMapHNodeNameToLocationName(d.getSymbol(), lowerName);
179           }
180         }
181         // locSummary.addMapHNodeNameToLocationName(lowerName, lowerName);
182
183         if (higher.size() == 0) {
184           // empty case
185           lattice.put(lowerName);
186         } else {
187           lattice.addRelationHigherToLower(higherName, lowerName);
188         }
189
190       }
191
192     }
193
194     inputGraph.removeRedundantEdges();
195     return lattice;
196   }
197
198   public HNode getCombinationNodeInSCGraph(Descriptor desc, HNode nodeFromSimpleGraph) {
199
200     HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
201
202     if (nodeFromSimpleGraph.isSkeleton()) {
203       return scGraph.getCurrentHNode(nodeFromSimpleGraph);
204     }
205
206     Set<HNode> combineSkeletonNodeSet =
207         infer.getSimpleHierarchyGraph(desc).getCombineSetByCombinationNode(nodeFromSimpleGraph);
208     HNode combinationNodeInSCGraph =
209         infer.getSkeletonCombinationHierarchyGraph(desc).getMapCombineNodeSetToCombinationNode()
210             .get(combineSkeletonNodeSet);
211
212     // Set<HNode> combineSkeletonNodeSet =
213     // infer.getSimpleHierarchyGraph(desc).getCombineSetByCombinationNode(simpleGraphNode);
214     // HNode combinationNodeInSCGraph =
215     // infer.getSkeletonCombinationHierarchyGraph(desc).getCombinationNode(combineSkeletonNodeSet);
216     return combinationNodeInSCGraph;
217   }
218
219   public SSJavaLattice<String> insertIntermediateNodesToStraightLine(Descriptor desc,
220       SSJavaLattice<String> skeletonLattice) {
221     // copy nodes/edges from the parent method/class if possible
222     SSJavaLattice<String> lattice = skeletonLattice.clone();
223
224     Descriptor parentDesc = getParent(desc);
225     if (parentDesc != null) {
226       SSJavaLattice<String> parentLattice = infer.getLattice(parentDesc);
227
228       Map<String, Set<String>> parentMap = parentLattice.getTable();
229       Set<String> parentKeySet = parentMap.keySet();
230       for (Iterator iterator = parentKeySet.iterator(); iterator.hasNext();) {
231         String parentKey = (String) iterator.next();
232         Set<String> parentValueSet = parentMap.get(parentKey);
233         for (Iterator iterator2 = parentValueSet.iterator(); iterator2.hasNext();) {
234           String value = (String) iterator2.next();
235           lattice.put(parentKey, value);
236         }
237       }
238
239       Set<String> parentSharedLocSet = parentLattice.getSharedLocSet();
240       for (Iterator iterator = parentSharedLocSet.iterator(); iterator.hasNext();) {
241         String parentSharedLoc = (String) iterator.next();
242         lattice.addSharedLoc(parentSharedLoc);
243       }
244     }
245
246     // ////
247
248     // perform DFS that starts from each skeleton/combination node and ends by another
249     // skeleton/combination node
250
251     mapSharedNodeToTripleItem.clear();
252
253     HierarchyGraph simpleGraph = infer.getSimpleHierarchyGraph(desc);
254     HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
255     LocationSummary locSummary = infer.getLocationSummary(desc);
256
257     Set<HNode> visited = new HashSet<HNode>();
258
259     Set<HNode> nodeSet = simpleGraph.getNodeSet();
260
261     Map<TripleItem, String> mapIntermediateLoc = getIntermediateLocMap(desc);
262     // Map<TripleItem, String> mapIntermediateLoc = new HashMap<TripleItem, String>();
263
264     // System.out.println("*insert=" + desc);
265     // System.out.println("***nodeSet=" + nodeSet);
266     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
267       HNode node = (HNode) iterator.next();
268       // System.out.println("node=" + node);
269
270       if (node.isSkeleton() && (!visited.contains(node))) {
271         visited.add(node);
272
273         Set<HNode> outSet = simpleGraph.getOutgoingNodeSet(node);
274         for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
275           HNode outNode = (HNode) iterator2.next();
276
277           if (!outNode.isSkeleton()) {
278             if (outNode.isCombinationNode()) {
279               if (visited.containsAll(simpleGraph.getIncomingNodeSet(outNode))) {
280                 // if (needToExpandCombinationNode(desc, outNode)) {
281                 expandCombinationNode(desc, lattice, visited, mapIntermediateLoc, locSummary,
282                     outNode);
283                 // }
284               }
285             } else {
286               // we have a node that is neither combination or skeleton node
287               // System.out.println("%%%skeleton node=" + node + "  outNode=" + outNode);
288               HNode startNode = scGraph.getCurrentHNode(node);
289
290               // if (node.getDescriptor() != null) {
291               // // node is a skeleton node and it might be merged into another node in the SC
292               // graph.
293               // startNode = scGraph.getHNode(node.getDescriptor());
294               // } else {
295               // // this node has already been merged before the SC graph.
296               // startNode = node;
297               // }
298
299               // TODO
300               // Set<HNode> endNodeSetFromSimpleGraph =
301               // simpleGraph.getDirectlyReachableSkeletonCombinationNodeFrom(outNode, null);
302               // Set<HNode> endCombNodeSet = new HashSet<HNode>();
303               // for (Iterator iterator3 = endNodeSetFromSimpleGraph.iterator();
304               // iterator3.hasNext();) {
305               // HNode endNode = (HNode) iterator3.next();
306               // endCombNodeSet.add(getCombinationNodeInSCGraph(desc, endNode));
307               // }
308
309               Set<HNode> endCombNodeSet = scGraph.getOutgoingNodeSet(startNode);
310
311               // System.out.println("endCombNodeSet=" + endCombNodeSet);
312               visited.add(outNode);
313               if (endCombNodeSet.size() > 0) {
314                 // follows the straight line up to another skeleton/combination node
315                 endCombNodeSet = removeTransitivelyReachToNode(desc, startNode, endCombNodeSet);
316               } else if (endCombNodeSet.size() == 0) {
317                 // the outNode is (directly/transitively) connected to the bottom node
318                 // therefore, we just add a dummy bottom HNode to the endCombNodeSet.
319                 endCombNodeSet.add(LocationInference.BOTTOMHNODE);
320               }
321
322               recurDFSNormalNode(desc, lattice, startNode, endCombNodeSet, visited,
323                   mapIntermediateLoc, 1, locSummary, outNode);
324             }
325
326           }
327
328         }
329       } else if (!node.isSkeleton() && !node.isCombinationNode() && !node.isMergeNode()
330           && !visited.contains(node)) {
331
332         System.out.println("n=" + node);
333
334         // an intermediate node 'node' may be located between "TOP" location and a skeleton node
335         if (simpleGraph.getIncomingNodeSet(node).size() == 0) {
336
337           // this node will be directly connected to the TOP location
338           // start adding the following nodes from this node
339
340           Set<HNode> endNodeSetFromSimpleGraph =
341               simpleGraph.getDirectlyReachableSkeletonCombinationNodeFrom(node, null);
342
343           Set<HNode> endCombNodeSet = new HashSet<HNode>();
344           for (Iterator iterator3 = endNodeSetFromSimpleGraph.iterator(); iterator3.hasNext();) {
345             HNode endNode = (HNode) iterator3.next();
346             endCombNodeSet.add(getCombinationNodeInSCGraph(desc, endNode));
347           }
348
349           System.out.println("endCombNodeSet=" + endCombNodeSet);
350           HNode startNode = LocationInference.TOPHNODE;
351           visited.add(startNode);
352           if (endCombNodeSet.size() > 0) {
353             // follows the straight line up to another skeleton/combination node
354             // endCombNodeSet = removeTransitivelyReachToNode(desc, node, endCombNodeSet);
355             recurDFSNormalNode(desc, lattice, startNode, endCombNodeSet, visited,
356                 mapIntermediateLoc, 1, locSummary, node);
357           }
358
359         }
360
361       }
362     }
363
364     // add shared locations
365     Set<HNode> sharedNodeSet = mapSharedNodeToTripleItem.keySet();
366     for (Iterator iterator = sharedNodeSet.iterator(); iterator.hasNext();) {
367       HNode sharedNode = (HNode) iterator.next();
368       TripleItem item = mapSharedNodeToTripleItem.get(sharedNode);
369       String nonSharedLocName = mapIntermediateLoc.get(item);
370
371       System.out.println("sharedNode=" + sharedNode + "    locName=" + nonSharedLocName);
372
373       String newLocName;
374       if (locSummary.getHNodeNameSetByLatticeLoationName(nonSharedLocName) != null
375           && !lattice.isSharedLoc(nonSharedLocName)) {
376         // need to generate a new shared location in the lattice, which is one level lower than the
377         // 'locName' location
378         newLocName = "ILOC" + (LocationInference.locSeed++);
379
380         // Set<String> aboveElementSet = getAboveElementSet(lattice, locName);
381         Set<String> belowElementSet = new HashSet<String>();
382         belowElementSet.addAll(lattice.get(nonSharedLocName));
383
384         System.out.println("nonSharedLocName=" + nonSharedLocName + "   belowElementSet="
385             + belowElementSet + "  newLocName=" + newLocName);
386
387         lattice.insertNewLocationBetween(nonSharedLocName, belowElementSet, newLocName);
388       } else {
389         newLocName = nonSharedLocName;
390       }
391
392       lattice.addSharedLoc(newLocName);
393       HierarchyGraph graph = infer.getSimpleHierarchyGraph(desc);
394       Set<Descriptor> descSet = graph.getDescSetOfNode(sharedNode);
395       for (Iterator iterator2 = descSet.iterator(); iterator2.hasNext();) {
396         Descriptor d = (Descriptor) iterator2.next();
397         locSummary.addMapHNodeNameToLocationName(d.getSymbol(), newLocName);
398       }
399       locSummary.addMapHNodeNameToLocationName(sharedNode.getName(), newLocName);
400
401     }
402
403     return lattice;
404
405   }
406
407   private Set<String> getAboveElementSet(SSJavaLattice<String> lattice, String loc) {
408
409     Set<String> aboveSet = new HashSet<String>();
410
411     Map<String, Set<String>> latticeMap = lattice.getTable();
412     Set<String> keySet = latticeMap.keySet();
413     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
414       String key = (String) iterator.next();
415       if (latticeMap.get(key).contains(loc)) {
416         aboveSet.add(key);
417       }
418     }
419
420     return aboveSet;
421   }
422
423   private boolean needToExpandCombinationNode(Descriptor desc, HNode cnode) {
424
425     System.out.println("needToExpandCombinationNode?=" + cnode);
426
427     HierarchyGraph simpleGraph = infer.getSimpleHierarchyGraph(desc);
428     // HNode combinationNodeInSCGraph = getCombinationNodeInSCGraph(desc, cnode);
429     Set<HNode> combineSkeletonNodeSet = simpleGraph.getCombineSetByCombinationNode(cnode);
430     Set<HNode> combinationNodeSetInSimpleGraph =
431         simpleGraph.getCombinationNodeSetByCombineNodeSet(combineSkeletonNodeSet);
432     System.out.println("---combinationNodeSetInSimpleGraph=" + combinationNodeSetInSimpleGraph);
433     Set<HNode> inNodeSetToCNode = simpleGraph.getIncomingNodeSet(cnode);
434     System.out.println("------inNodeSetToCNode=" + inNodeSetToCNode);
435     for (Iterator iterator = combinationNodeSetInSimpleGraph.iterator(); iterator.hasNext();) {
436       HNode nodeBelongToTheSameCombinationNode = (HNode) iterator.next();
437       if (inNodeSetToCNode.contains(nodeBelongToTheSameCombinationNode)) {
438         // the combination node 'cnode' is not the highest location among the same combination node
439         return false;
440       }
441     }
442
443     return true;
444   }
445
446   private void expandCombinationNode(Descriptor desc, SSJavaLattice<String> lattice,
447       Set<HNode> visited, Map<TripleItem, String> mapIntermediateLoc, LocationSummary locSummary,
448       HNode cnode) {
449
450     // expand the combination node 'outNode'
451     // here we need to expand the corresponding combination location in the lattice
452     HNode combinationNodeInSCGraph = getCombinationNodeInSCGraph(desc, cnode);
453
454     System.out.println("expandCombinationNode=" + cnode + "  cnode in scgraph="
455         + combinationNodeInSCGraph);
456
457     if (combinationNodeInSCGraph == null) {
458       return;
459     }
460
461     HierarchyGraph simpleGraph = infer.getSimpleHierarchyGraph(desc);
462     HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
463
464     Set<HNode> combineSkeletonNodeSet = simpleGraph.getCombineSetByCombinationNode(cnode);
465
466     // System.out.println("combineSkeletonNodeSet=" + combineSkeletonNodeSet);
467
468     Set<HNode> combinationNodeSet =
469         simpleGraph.getCombinationNodeSetByCombineNodeSet(combineSkeletonNodeSet);
470
471     // System.out.println("combinationNodeSet=" + combinationNodeSet);
472
473     // TODO
474     // Set<HNode> endNodeSetFromSimpleGraph =
475     // simpleGraph.getDirectlyReachableSkeletonCombinationNodeFrom(cnode, combinationNodeSet);
476     // System.out.println("-endNodeSetFromSimpleGraph=" + endNodeSetFromSimpleGraph);
477     // Set<HNode> endCombNodeSet = new HashSet<HNode>();
478     // for (Iterator iterator3 = endNodeSetFromSimpleGraph.iterator(); iterator3.hasNext();) {
479     // HNode endNode = (HNode) iterator3.next();
480     // endCombNodeSet.add(getCombinationNodeInSCGraph(desc, endNode));
481     // }
482
483     Set<HNode> endCombNodeSet = scGraph.getOutgoingNodeSet(combinationNodeInSCGraph);
484     visited.add(cnode);
485
486     // follows the straight line up to another skeleton/combination node
487     if (endCombNodeSet.size() > 0) {
488       // System.out.println("---endCombNodeSet=" + endCombNodeSet);
489       endCombNodeSet =
490           removeTransitivelyReachToNode(desc, combinationNodeInSCGraph, endCombNodeSet);
491
492       recurDFS(desc, lattice, combinationNodeInSCGraph, endCombNodeSet, visited,
493           mapIntermediateLoc, 1, locSummary, cnode);
494     } else {
495       endCombNodeSet.add(LocationInference.BOTTOMHNODE);
496       // System.out.println("---endCombNodeSet is zero");
497       // System.out.println("---endNodeSetFromSimpleGraph=" + endNodeSetFromSimpleGraph);
498       // System.out.println("---incoming=" + simpleGraph.getIncomingNodeSet(cnode));
499       recurDFS(desc, lattice, combinationNodeInSCGraph, endCombNodeSet, visited,
500           mapIntermediateLoc, 1, locSummary, cnode);
501
502     }
503
504   }
505
506   private Set<HNode> removeTransitivelyReachToNode(Descriptor desc, HNode startNode,
507       Set<HNode> endNodeSet) {
508
509     // if an end node is not directly connected to the start node in the SC graph
510     // replace it with a directly connected one which transitively reaches to it.
511
512     HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
513
514     Set<HNode> newEndNodeSet = new HashSet<HNode>();
515     for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
516       HNode endNode = (HNode) iterator.next();
517       if (scGraph.isDirectlyConnectedTo(startNode, endNode)) {
518         newEndNodeSet.add(endNode);
519       } else {
520         HNode newEndNode =
521             getDirectlyReachableNodeFromStartNodeReachToEndNode(scGraph, startNode, endNode);
522         // System.out.println("#### old END NODE=" + endNode + " --->" + newEndNode);
523         newEndNodeSet.add(newEndNode);
524       }
525     }
526
527     // System.out.println("removeTransitivelyReachToNode=" + endNodeSet + "  newSet=" +
528     // newEndNodeSet);
529
530     return newEndNodeSet;
531
532   }
533
534   private HNode getDirectlyReachableSCNodeFromEndNode(HierarchyGraph scGraph, HNode startNode,
535       Set<HNode> endNodeSet) {
536
537     // System.out.println("getDirectlyReachableSCNodeFromEndNode start=" + startNode +
538     // " endNodeSet="
539     // + endNodeSet);
540     Set<HNode> newStartNodeSet = new HashSet<HNode>();
541
542     for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
543       HNode endNode = (HNode) iterator.next();
544       Set<HNode> connectedToEndNodeSet = scGraph.getIncomingNodeSet(endNode);
545
546       for (Iterator iterator2 = connectedToEndNodeSet.iterator(); iterator2.hasNext();) {
547         HNode curNode = (HNode) iterator2.next();
548         if (recurConnectedFromStartNode(scGraph, startNode, curNode, new HashSet<HNode>())) {
549           newStartNodeSet.add(curNode);
550         }
551       }
552     }
553
554     // System.out.println("newStartNodeSet=" + newStartNodeSet);
555
556     if (newStartNodeSet.size() == 0) {
557       newStartNodeSet.add(startNode);
558     }
559
560     return newStartNodeSet.iterator().next();
561   }
562
563   private boolean recurConnectedFromStartNode(HierarchyGraph scGraph, HNode startNode,
564       HNode curNode, Set<HNode> visited) {
565     // return true if curNode is transitively connected from the startNode
566
567     boolean isConnected = false;
568     Set<HNode> inNodeSet = scGraph.getIncomingNodeSet(curNode);
569     for (Iterator iterator = inNodeSet.iterator(); iterator.hasNext();) {
570       HNode in = (HNode) iterator.next();
571       if (in.equals(startNode)) {
572         return true;
573       } else {
574         visited.add(in);
575         isConnected |= recurConnectedFromStartNode(scGraph, startNode, in, visited);
576       }
577     }
578
579     return isConnected;
580   }
581
582   private HNode getDirectlyReachableNodeFromStartNodeReachToEndNode(HierarchyGraph scGraph,
583       HNode startNode, HNode endNode) {
584     // System.out.println("getDirectlyReachableNodeFromStartNodeReachToEndNode start=" + startNode
585     // + " end=" + endNode);
586     Set<HNode> connected = new HashSet<HNode>();
587     recurDirectlyReachableNodeFromStartNodeReachToEndNode(scGraph, startNode, endNode, connected);
588     if (connected.size() == 0) {
589       connected.add(endNode);
590     }
591     // System.out.println("connected=" + connected);
592
593     return connected.iterator().next();
594   }
595
596   private void recurDirectlyReachableNodeFromStartNodeReachToEndNode(HierarchyGraph scGraph,
597       HNode startNode, HNode curNode, Set<HNode> connected) {
598
599     Set<HNode> inNodeSet = scGraph.getIncomingNodeSet(curNode);
600     for (Iterator iterator = inNodeSet.iterator(); iterator.hasNext();) {
601       HNode inNode = (HNode) iterator.next();
602       if (inNode.equals(startNode)) {
603         connected.add(curNode);
604       } else {
605         recurDirectlyReachableNodeFromStartNodeReachToEndNode(scGraph, startNode, inNode, connected);
606       }
607     }
608
609   }
610
611   private void recurDFSNormalNode(Descriptor desc, SSJavaLattice<String> lattice, HNode startNode,
612       Set<HNode> endNodeSet, Set<HNode> visited, Map<TripleItem, String> mapIntermediateLoc,
613       int idx, LocationSummary locSummary, HNode curNode) {
614
615     TripleItem item = new TripleItem(startNode, endNodeSet, idx);
616     if (!mapIntermediateLoc.containsKey(item)) {
617       // need to create a new intermediate location in the lattice
618       String newLocName = "ILOC" + (LocationInference.locSeed++);
619       String above;
620       if (idx == 1) {
621         above = startNode.getName();
622       } else {
623         int prevIdx = idx - 1;
624         TripleItem prevItem = new TripleItem(startNode, endNodeSet, prevIdx);
625         above = mapIntermediateLoc.get(prevItem);
626       }
627
628       Set<String> belowSet = new HashSet<String>();
629       for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
630         HNode endNode = (HNode) iterator.next();
631         String locName;
632         if (locSummary.getMapHNodeNameToLocationName().containsKey(endNode.getName())) {
633           locName = locSummary.getLocationName(endNode.getName());
634         } else {
635           locName = endNode.getName();
636         }
637         belowSet.add(locName);
638       }
639       lattice.insertNewLocationBetween(above, belowSet, newLocName);
640
641       mapIntermediateLoc.put(item, newLocName);
642     }
643
644     String locName = mapIntermediateLoc.get(item);
645     HierarchyGraph simpleHierarchyGraph = infer.getSimpleHierarchyGraph(desc);
646
647     if (curNode.isSharedNode()) {
648       // if the current node is shared location, add a shared location to the lattice later
649       System.out.println("###SHARED ITEM=" + item);
650       mapSharedNodeToTripleItem.put(curNode, item);
651     } else {
652       Set<Descriptor> descSet = simpleHierarchyGraph.getDescSetOfNode(curNode);
653       for (Iterator iterator = descSet.iterator(); iterator.hasNext();) {
654         Descriptor d = (Descriptor) iterator.next();
655         locSummary.addMapHNodeNameToLocationName(d.getSymbol(), locName);
656       }
657       locSummary.addMapHNodeNameToLocationName(curNode.getName(), locName);
658     }
659
660     System.out.println("-TripleItem normal=" + item);
661     System.out.println("-curNode=" + curNode.getName() + " S=" + curNode.isSharedNode()
662         + " locName=" + locName + "  isC=" + curNode.isCombinationNode());
663
664     Set<HNode> outSet = simpleHierarchyGraph.getOutgoingNodeSet(curNode);
665     for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
666       HNode outNode = (HNode) iterator2.next();
667
668       Set<HNode> incomingHNodeSetToOutNode = simpleHierarchyGraph.getIncomingNodeSet(outNode);
669       System.out.println("outNode=" + outNode);
670       System.out.println("---incomingHNodeSetToOutNode=" + incomingHNodeSetToOutNode);
671
672       if (!outNode.isSkeleton() && !outNode.isCombinationNode() && !visited.contains(outNode)) {
673         Pair<HNode, HNode> pair = new Pair(startNode, outNode);
674         if (visited.containsAll(simpleHierarchyGraph.getIncomingNodeSet(outNode))) {
675           visited.add(outNode);
676           int newidx = getCurrentHighestIndex(pair, idx + 1);
677           // int newidx = getCurrentHighestIndex(outNode, idx + 1);
678           recurDFSNormalNode(desc, lattice, startNode, endNodeSet, visited, mapIntermediateLoc,
679               newidx, locSummary, outNode);
680           // recurDFSNormalNode(desc, lattice, startNode, endNodeSet, visited, mapIntermediateLoc,
681           // idx + 1, locSummary, outNode);
682         } else {
683           updateHighestIndex(pair, idx + 1);
684           // updateHighestIndex(outNode, idx + 1);
685           System.out.println("NOT RECUR");
686         }
687       } else if (!outNode.isSkeleton() && outNode.isCombinationNode() && !visited.contains(outNode)) {
688         if (needToExpandCombinationNode(desc, outNode)) {
689           System.out.println("NEED TO");
690           expandCombinationNode(desc, lattice, visited, mapIntermediateLoc, locSummary, outNode);
691         } else {
692           System.out.println("NOT NEED TO");
693         }
694       }
695
696     }
697
698   }
699
700   private void recurDFS(Descriptor desc, SSJavaLattice<String> lattice,
701       HNode combinationNodeInSCGraph, Set<HNode> endNodeSet, Set<HNode> visited,
702       Map<TripleItem, String> mapIntermediateLoc, int idx, LocationSummary locSummary, HNode curNode) {
703
704     TripleItem item = new TripleItem(combinationNodeInSCGraph, endNodeSet, idx);
705
706     if (!mapIntermediateLoc.containsKey(item)) {
707       // need to create a new intermediate location in the lattice
708       String above;
709       if (idx == 1) {
710         String newLocName = combinationNodeInSCGraph.getName();
711         mapIntermediateLoc.put(item, newLocName);
712       } else {
713         String newLocName = "ILOC" + (LocationInference.locSeed++);
714         int prevIdx = idx - 1;
715         TripleItem prevItem = new TripleItem(combinationNodeInSCGraph, endNodeSet, prevIdx);
716         above = mapIntermediateLoc.get(prevItem);
717
718         Set<String> belowSet = new HashSet<String>();
719         for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
720           HNode endNode = (HNode) iterator.next();
721           belowSet.add(endNode.getName());
722         }
723         lattice.insertNewLocationBetween(above, belowSet, newLocName);
724         mapIntermediateLoc.put(item, newLocName);
725       }
726
727     }
728
729     // TODO
730     // Do we need to skip the combination node and assign a shared location to the next node?
731     // if (idx == 1 && curNode.isSharedNode()) {
732     // System.out.println("THE FIRST COMBINATION NODE EXPANSION IS SHARED!");
733     // recurDFS(desc, lattice, combinationNodeInSCGraph, endNodeSet, visited, mapIntermediateLoc,
734     // idx + 1, locSummary, curNode);
735     // return;
736     // }
737
738     HierarchyGraph simpleHierarchyGraph = infer.getSimpleHierarchyGraph(desc);
739     String locName = mapIntermediateLoc.get(item);
740     if (curNode.isSharedNode()) {
741       // if the current node is shared location, add a shared location to the lattice later
742       System.out.println("###SHARED ITEM=" + item);
743       mapSharedNodeToTripleItem.put(curNode, item);
744     } else {
745       Set<Descriptor> descSet = simpleHierarchyGraph.getDescSetOfNode(curNode);
746       for (Iterator iterator = descSet.iterator(); iterator.hasNext();) {
747         Descriptor d = (Descriptor) iterator.next();
748         locSummary.addMapHNodeNameToLocationName(d.getSymbol(), locName);
749       }
750       locSummary.addMapHNodeNameToLocationName(curNode.getName(), locName);
751     }
752
753     System.out.println("-TripleItem=" + item);
754     System.out.println("-curNode=" + curNode.getName() + " S=" + curNode.isSharedNode()
755         + " locName=" + locName);
756
757     Set<HNode> outSet = simpleHierarchyGraph.getOutgoingNodeSet(curNode);
758     for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
759       HNode outNode = (HNode) iterator2.next();
760       System.out.println("---recurDFS outNode=" + outNode);
761       System.out.println("---cur combinationNodeInSCGraph=" + combinationNodeInSCGraph);
762       System.out.println("---outNode combinationNodeInSCGraph="
763           + getCombinationNodeInSCGraph(desc, outNode));
764
765       if (!outNode.isSkeleton() && !visited.contains(outNode)) {
766         if (outNode.isCombinationNode()) {
767
768           Set<HNode> combineSkeletonNodeSet =
769               simpleHierarchyGraph.getCombineSetByCombinationNode(outNode);
770           Set<HNode> incomingHNodeSetToOutNode = simpleHierarchyGraph.getIncomingNodeSet(outNode);
771           // extract nodes belong to the same combine node
772           Set<HNode> incomingCombinedHNodeSet = new HashSet<HNode>();
773           for (Iterator iterator = incomingHNodeSetToOutNode.iterator(); iterator.hasNext();) {
774             HNode inNode = (HNode) iterator.next();
775             if (combineSkeletonNodeSet.contains(inNode)) {
776               incomingCombinedHNodeSet.add(inNode);
777             }
778           }
779           System.out.println("-----incomingCombinedHNodeSet=" + incomingCombinedHNodeSet);
780
781           // check whether the next combination node is different from the current node
782           if (combinationNodeInSCGraph.equals(getCombinationNodeInSCGraph(desc, outNode))) {
783             Pair<HNode, HNode> pair = new Pair(combinationNodeInSCGraph, outNode);
784             if (visited.containsAll(incomingCombinedHNodeSet)) {
785               visited.add(outNode);
786               System.out.println("-------curIdx=" + (idx + 1));
787
788               int newIdx = getCurrentHighestIndex(pair, idx + 1);
789               // int newIdx = getCurrentHighestIndex(outNode, idx + 1);
790               System.out.println("-------newIdx=" + newIdx);
791               recurDFS(desc, lattice, combinationNodeInSCGraph, endNodeSet, visited,
792                   mapIntermediateLoc, newIdx, locSummary, outNode);
793               // recurDFS(desc, lattice, combinationNodeInSCGraph, endNodeSet, visited,
794               // mapIntermediateLoc, idx + 1, locSummary, outNode);
795             } else {
796               updateHighestIndex(pair, idx + 1);
797               // updateHighestIndex(outNode, idx + 1);
798               System.out.println("-----NOT RECUR!");
799             }
800           } else {
801             if (needToExpandCombinationNode(desc, outNode)) {
802               System.out.println("NEED TO");
803               expandCombinationNode(desc, lattice, visited, mapIntermediateLoc, locSummary, outNode);
804             } else {
805               System.out.println("NOT NEED TO");
806             }
807
808           }
809         }
810       }
811       // }
812
813     }
814
815   }
816
817   private int getCurrentHighestIndex(Pair<HNode, HNode> pair, int curIdx) {
818     int recordedIdx = getCurrentHighestIndex(pair);
819     if (recordedIdx > curIdx) {
820       return recordedIdx;
821     } else {
822       return curIdx;
823     }
824   }
825
826   private int getCurrentHighestIndex(HNode node, int curIdx) {
827     int recordedIdx = getCurrentHighestIndex(node);
828     if (recordedIdx > curIdx) {
829       return recordedIdx;
830     } else {
831       return curIdx;
832     }
833   }
834
835   private int getCurrentHighestIndex(Pair<HNode, HNode> pair) {
836     if (!mapItemToHighestIndex.containsKey(pair)) {
837       mapItemToHighestIndex.put(pair, new Integer(-1));
838     }
839     return mapItemToHighestIndex.get(pair).intValue();
840   }
841
842   private void updateHighestIndex(Pair<HNode, HNode> pair, int idx) {
843     if (idx > getCurrentHighestIndex(pair)) {
844       mapItemToHighestIndex.put(pair, new Integer(idx));
845     }
846   }
847
848   private int getCurrentHighestIndex(HNode node) {
849     if (!mapHNodeToHighestIndex.containsKey(node)) {
850       mapHNodeToHighestIndex.put(node, new Integer(-1));
851     }
852     return mapHNodeToHighestIndex.get(node).intValue();
853   }
854
855   private void updateHighestIndex(HNode node, int idx) {
856     if (idx > getCurrentHighestIndex(node)) {
857       mapHNodeToHighestIndex.put(node, new Integer(idx));
858     }
859   }
860
861   private String generateElementName(BasisSet basisSet, HierarchyGraph inputGraph,
862       Map<Set<Integer>, String> mapF2LocName, Set<Integer> F) {
863
864     if (mapF2LocName.containsKey(F)) {
865       return mapF2LocName.get(F);
866     }
867
868     HNode node = basisSet.getHNode(F);
869     if (node != null) {
870       mapF2LocName.put(F, node.getName());
871       return node.getName();
872     } else {
873       if (inputGraph.BASISTOPELEMENT.equals(F)) {
874         return SSJavaAnalysis.BOTTOM;
875       } else {
876         String str = "LOC" + (LocationInference.locSeed++);
877         mapF2LocName.put(F, str);
878         return str;
879       }
880     }
881   }
882
883   private void resetCount(Map<Set<Integer>, Integer> mapFtoCount, Family family) {
884     for (Iterator<Set<Integer>> iter = family.FIterator(); iter.hasNext();) {
885       Set<Integer> F = iter.next();
886       mapFtoCount.put(F, 0);
887     }
888   }
889
890   private Map<Set<Integer>, Set<Set<Integer>>> coveringGraph(BasisSet basisSet, Family family) {
891
892     Map<Set<Integer>, Integer> mapFtoCount = new HashMap<Set<Integer>, Integer>();
893     Map<Set<Integer>, Set<Set<Integer>>> mapImSucc = new HashMap<Set<Integer>, Set<Set<Integer>>>();
894
895     // initialize COUNT(F) to 0 for all elements of the family
896     resetCount(mapFtoCount, family);
897
898     for (Iterator<Set<Integer>> iter = family.FIterator(); iter.hasNext();) {
899       Set<Integer> F = iter.next();
900       Set<HNode> gammaF = family.getGamma(F);
901
902       Set<HNode> curHNodeSet = basisSet.getHNodeSet();
903       curHNodeSet.removeAll(gammaF);
904       Set<Set<Integer>> Bset = basisSet.getBasisSetByHNodeSet(curHNodeSet);
905
906       for (Iterator iterator = Bset.iterator(); iterator.hasNext();) {
907         Set<Integer> B = (Set<Integer>) iterator.next();
908
909         Set<Integer> Fprime = new HashSet<Integer>();
910         Fprime.addAll(F);
911         Fprime.addAll(B);
912
913         // COUNT(F')++;
914         mapFtoCount.put(Fprime, mapFtoCount.get(Fprime) + 1);
915
916         // if |gamma(F')|==COUNT(F') + |gamma(F)|
917         int numGammaFprime = family.getGamma(Fprime).size();
918         int countFprime = mapFtoCount.get(Fprime);
919         int numGammaF = family.getGamma(F).size();
920         if (numGammaFprime == (countFprime + numGammaF)) {
921           // ImSucc(F)=IMSucc(F) union F'
922           addImSucc(mapImSucc, F, Fprime);
923         }
924
925       }
926       resetCount(mapFtoCount, family);
927     }
928
929     // System.out.println("mapImSucc=" + mapImSucc);
930
931     return mapImSucc;
932   }
933
934   private Set<Set<Integer>> getImSucc(Map<Set<Integer>, Set<Set<Integer>>> mapImSucc, Set<Integer> F) {
935     if (!mapImSucc.containsKey(F)) {
936       mapImSucc.put(F, new HashSet<Set<Integer>>());
937     }
938     return mapImSucc.get(F);
939   }
940
941   private void addImSucc(Map<Set<Integer>, Set<Set<Integer>>> mapImSucc, Set<Integer> F,
942       Set<Integer> Fprime) {
943
944     if (!mapImSucc.containsKey(F)) {
945       mapImSucc.put(F, new HashSet<Set<Integer>>());
946     }
947
948     mapImSucc.get(F).add(Fprime);
949
950   }
951
952   private Family generateFamily(BasisSet basisSet) {
953
954     Family family = new Family();
955
956     for (Iterator<Set<Integer>> iterator = basisSet.basisIterator(); iterator.hasNext();) {
957       Set<Integer> B = iterator.next();
958
959       Set<Pair<Set<Integer>, Set<HNode>>> tobeadded = new HashSet<Pair<Set<Integer>, Set<HNode>>>();
960
961       for (Iterator<Set<Integer>> iterator2 = family.FIterator(); iterator2.hasNext();) {
962         Set<Integer> F = iterator2.next();
963
964         Set<Integer> Fprime = new HashSet<Integer>();
965         Fprime.addAll(F);
966         Fprime.addAll(B);
967
968         Set<HNode> gammaFPrimeSet = new HashSet<HNode>();
969         gammaFPrimeSet.addAll(family.getGamma(F));
970         gammaFPrimeSet.add(basisSet.getHNode(B));
971
972         if (!family.containsF(Fprime)) {
973           Pair<Set<Integer>, Set<HNode>> pair =
974               new Pair<Set<Integer>, Set<HNode>>(Fprime, gammaFPrimeSet);
975           tobeadded.add(pair);
976         } else {
977           family.updateGammaF(Fprime, gammaFPrimeSet);
978         }
979       }
980
981       for (Iterator<Pair<Set<Integer>, Set<HNode>>> iterator2 = tobeadded.iterator(); iterator2
982           .hasNext();) {
983         Pair<Set<Integer>, Set<HNode>> pair = iterator2.next();
984         family.addFElement(pair.getFirst());
985         family.updateGammaF(pair.getFirst(), pair.getSecond());
986       }
987
988     }
989     return family;
990   }
991
992   private void debug_print(HierarchyGraph inputGraph) {
993     System.out.println("\nBuild Lattice:" + inputGraph.getName());
994     System.out.println("Node2Index:\n" + inputGraph.getMapHNodeToUniqueIndex());
995     System.out.println("Node2Basis:\n" + inputGraph.getMapHNodeToBasis());
996   }
997
998 }
999
1000 class Identifier {
1001   public HNode node;
1002   public int idx;
1003
1004   public Identifier(HNode n, int i) {
1005     node = n;
1006     idx = i;
1007   }
1008
1009   public int hashCode() {
1010     return node.hashCode() + idx;
1011   }
1012
1013   public boolean equals(Object obj) {
1014
1015     if (obj instanceof Identifier) {
1016       Identifier in = (Identifier) obj;
1017       if (node.equals(in.node) && idx == in.idx) {
1018         return true;
1019       }
1020     }
1021
1022     return false;
1023   }
1024
1025 }
1026
1027 class TripleItem {
1028   public HNode higherNode;
1029   public Set<HNode> lowerNodeSet;
1030   public int idx;
1031   public boolean isShared;
1032
1033   public TripleItem(HNode h, Set<HNode> l, int i) {
1034     higherNode = h;
1035     lowerNodeSet = l;
1036     idx = i;
1037     isShared = false;
1038   }
1039
1040   public void setShared(boolean in) {
1041     this.isShared = in;
1042   }
1043
1044   public boolean isShared() {
1045     return isShared;
1046   }
1047
1048   public int hashCode() {
1049
1050     int h = 0;
1051     if (higherNode != null) {
1052       h = higherNode.hashCode();
1053     }
1054
1055     if (isShared) {
1056       h++;
1057     }
1058
1059     return h + lowerNodeSet.hashCode() + idx;
1060   }
1061
1062   public boolean equals(Object obj) {
1063
1064     if (obj instanceof TripleItem) {
1065       TripleItem in = (TripleItem) obj;
1066       if ((higherNode == null || (higherNode != null && higherNode.equals(in.higherNode)))
1067           && lowerNodeSet.equals(in.lowerNodeSet) && idx == in.idx && isShared == in.isShared()) {
1068         return true;
1069       }
1070     }
1071
1072     return false;
1073   }
1074
1075   public String toString() {
1076     String rtr = higherNode + "-" + idx + "->" + lowerNodeSet;
1077     if (isShared) {
1078       rtr += " S";
1079     }
1080     return rtr;
1081   }
1082 }