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.Descriptor;
10 import Util.Pair;
11
12 public class BuildLattice {
13
14   public static int seed = 0;
15   private LocationInference infer;
16
17   public BuildLattice(LocationInference infer) {
18     this.infer = infer;
19   }
20
21   public SSJavaLattice<String> buildLattice(HierarchyGraph inputGraph) {
22
23     BasisSet basisSet = inputGraph.computeBasisSet();
24     debug_print(inputGraph);
25
26     Family family = generateFamily(basisSet);
27     Map<Set<Integer>, Set<Set<Integer>>> mapImSucc = coveringGraph(basisSet, family);
28
29     SSJavaLattice<String> lattice = buildLattice(basisSet, inputGraph, mapImSucc);
30     return lattice;
31
32   }
33
34   private SSJavaLattice<String> buildLattice(BasisSet basisSet, HierarchyGraph inputGraph,
35       Map<Set<Integer>, Set<Set<Integer>>> mapImSucc) {
36
37     SSJavaLattice<String> lattice =
38         new SSJavaLattice<String>(SSJavaAnalysis.TOP, SSJavaAnalysis.BOTTOM);
39
40     Map<Set<Integer>, String> mapFToLocName = new HashMap<Set<Integer>, String>();
41
42     Set<Set<Integer>> keySet = mapImSucc.keySet();
43     for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
44       Set<Integer> higher = (Set<Integer>) iterator.next();
45
46       String higherName = generateElementName(basisSet, inputGraph, mapFToLocName, higher);
47
48       Set<Set<Integer>> lowerSet = mapImSucc.get(higher);
49       for (Iterator iterator2 = lowerSet.iterator(); iterator2.hasNext();) {
50         Set<Integer> lower = (Set<Integer>) iterator2.next();
51
52         String lowerName = generateElementName(basisSet, inputGraph, mapFToLocName, lower);
53
54         if (higher.size() == 0) {
55           // empty case
56           lattice.put(lowerName);
57         } else {
58           lattice.addRelationHigherToLower(higherName, lowerName);
59         }
60
61       }
62
63     }
64
65     return lattice;
66   }
67
68   public HNode getCombinationNodeInSCGraph(Descriptor desc, HNode simpleGraphNode) {
69
70     Set<HNode> combineSkeletonNodeSet =
71         infer.getSimpleHierarchyGraph(desc).getCombineSetByCombinationNode(simpleGraphNode);
72     HNode combinationNodeInSCGraph =
73         infer.getSkeletonCombinationHierarchyGraph(desc).getCombinationNode(combineSkeletonNodeSet);
74     return combinationNodeInSCGraph;
75   }
76
77   public SSJavaLattice<String> insertIntermediateNodesToStraightLine(Descriptor desc,
78       SSJavaLattice<String> skeletonLattice) {
79
80     // perform DFS that starts from each skeleton/combination node and ends by another
81     // skeleton/combination node
82
83     HierarchyGraph simpleGraph = infer.getSimpleHierarchyGraph(desc);
84     HierarchyGraph scGraph = infer.getSkeletonCombinationHierarchyGraph(desc);
85
86     SSJavaLattice<String> lattice = skeletonLattice.clone();
87
88     Map<TripleItem, String> mapIntermediateLocation = new HashMap<TripleItem, String>();
89
90     Set<HNode> visited = new HashSet<HNode>();
91
92     Set<HNode> nodeSet = simpleGraph.getNodeSet();
93
94     // expand a combination node
95     Map<TripleItem, String> mapIntermediateLoc = new HashMap<TripleItem, String>();
96     for (Iterator iterator = nodeSet.iterator(); iterator.hasNext();) {
97       HNode node = (HNode) iterator.next();
98       if (node.isSkeleton() && (!visited.contains(node))) {
99         visited.add(node);
100
101         Set<HNode> outSet = simpleGraph.getOutgoingNodeSet(node);
102         for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
103           HNode outNode = (HNode) iterator2.next();
104
105           if (!outNode.isSkeleton()) {
106             if (outNode.isCombinationNode()) {
107               // here we need to expand the corresponding combination location in the lattice
108               HNode combinationNodeInSCGraph = getCombinationNodeInSCGraph(desc, outNode);
109
110               Set<HNode> combineSkeletonNodeSet =
111                   simpleGraph.getCombineSetByCombinationNode(outNode);
112               Set<HNode> combinationNodeSet =
113                   simpleGraph.getCombinationNodeSetByCombineNodeSet(combineSkeletonNodeSet);
114               Set<HNode> endNodeSetFromSimpleGraph =
115                   simpleGraph.getDirectlyReachableSkeletonCombinationNodeFrom(outNode,
116                       combinationNodeSet);
117               Set<HNode> endCombNodeSet = new HashSet<HNode>();
118               for (Iterator iterator3 = endNodeSetFromSimpleGraph.iterator(); iterator3.hasNext();) {
119                 HNode endNode = (HNode) iterator3.next();
120                 endCombNodeSet.add(getCombinationNodeInSCGraph(desc, endNode));
121               }
122               visited.add(outNode);
123               // follows the straight line up to another skeleton/combination node
124               if (endCombNodeSet.size() > 0) {
125                 recurDFS(desc, lattice, combinationNodeInSCGraph, endCombNodeSet, visited,
126                     mapIntermediateLoc, 1, outNode);
127               }
128
129             } else {
130               // we have a node that is neither combination or skeleton node
131               HNode startNode = node;
132               Set<HNode> endNodeSetFromSimpleGraph =
133                   simpleGraph.getDirectlyReachableSkeletonCombinationNodeFrom(outNode, null);
134
135               Set<HNode> endCombNodeSet = new HashSet<HNode>();
136               for (Iterator iterator3 = endNodeSetFromSimpleGraph.iterator(); iterator3.hasNext();) {
137                 HNode endNode = (HNode) iterator3.next();
138                 endCombNodeSet.add(getCombinationNodeInSCGraph(desc, endNode));
139               }
140
141               visited.add(outNode);
142               if (endCombNodeSet.size() > 0) {
143                 // follows the straight line up to another skeleton/combination node
144                 recurDFSNormalNode(desc, lattice, startNode, endCombNodeSet, visited,
145                     mapIntermediateLoc, 1, outNode);
146
147               }
148
149             }
150
151           }
152
153         }
154       }
155     }
156
157     return lattice;
158
159   }
160
161   private void recurDFSNormalNode(Descriptor desc, SSJavaLattice<String> lattice, HNode startNode,
162       Set<HNode> endNodeSet, Set<HNode> visited, Map<TripleItem, String> mapIntermediateLoc,
163       int idx, HNode curNode) {
164
165     TripleItem item = new TripleItem(startNode, endNodeSet, idx);
166
167     if (!mapIntermediateLoc.containsKey(item)) {
168       // need to create a new intermediate location in the lattice
169       String newLocName = "ILOC" + (seed++);
170       String above;
171       if (idx == 1) {
172         above = startNode.getName();
173       } else {
174         int prevIdx = idx - 1;
175         TripleItem prevItem = new TripleItem(startNode, endNodeSet, prevIdx);
176         above = mapIntermediateLoc.get(prevItem);
177       }
178
179       Set<String> belowSet = new HashSet<String>();
180       for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
181         HNode endNode = (HNode) iterator.next();
182         belowSet.add(endNode.getName());
183       }
184
185       lattice.insertNewLocationBetween(above, belowSet, newLocName);
186
187       mapIntermediateLoc.put(item, newLocName);
188     }
189
190     String locName = mapIntermediateLoc.get(item);
191
192     HierarchyGraph graph = infer.getSimpleHierarchyGraph(desc);
193     Set<HNode> outSet = graph.getOutgoingNodeSet(curNode);
194     for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
195       HNode outNode = (HNode) iterator2.next();
196       if (!outNode.isSkeleton() && !outNode.isCombinationNode() && !visited.contains(outNode)) {
197         visited.add(outNode);
198         recurDFSNormalNode(desc, lattice, startNode, endNodeSet, visited, mapIntermediateLoc,
199             idx + 1, outNode);
200       }
201     }
202
203   }
204
205   private void recurDFS(Descriptor desc, SSJavaLattice<String> lattice,
206       HNode combinationNodeInSCGraph, Set<HNode> endNodeSet, Set<HNode> visited,
207       Map<TripleItem, String> mapIntermediateLoc, int idx, HNode curNode) {
208
209     TripleItem item = new TripleItem(combinationNodeInSCGraph, endNodeSet, idx);
210
211     if (!mapIntermediateLoc.containsKey(item)) {
212       // need to create a new intermediate location in the lattice
213       String newLocName = "ILOC" + (seed++);
214       String above;
215       if (idx == 1) {
216         above = combinationNodeInSCGraph.getName();
217       } else {
218         int prevIdx = idx - 1;
219         TripleItem prevItem = new TripleItem(combinationNodeInSCGraph, endNodeSet, prevIdx);
220         above = mapIntermediateLoc.get(prevItem);
221       }
222
223       Set<String> belowSet = new HashSet<String>();
224       for (Iterator iterator = endNodeSet.iterator(); iterator.hasNext();) {
225         HNode endNode = (HNode) iterator.next();
226         belowSet.add(endNode.getName());
227       }
228       lattice.insertNewLocationBetween(above, belowSet, newLocName);
229
230       mapIntermediateLoc.put(item, newLocName);
231
232       String locName = mapIntermediateLoc.get(item);
233
234     }
235
236     HierarchyGraph graph = infer.getSimpleHierarchyGraph(desc);
237     Set<HNode> outSet = graph.getOutgoingNodeSet(curNode);
238     for (Iterator iterator2 = outSet.iterator(); iterator2.hasNext();) {
239       HNode outNode = (HNode) iterator2.next();
240       if (!outNode.isSkeleton() && !visited.contains(outNode)) {
241         if (combinationNodeInSCGraph.equals(getCombinationNodeInSCGraph(desc, outNode))) {
242           visited.add(outNode);
243           recurDFS(desc, lattice, combinationNodeInSCGraph, endNodeSet, visited,
244               mapIntermediateLoc, idx + 1, outNode);
245         }
246       }
247     }
248
249   }
250
251   private String generateElementName(BasisSet basisSet, HierarchyGraph inputGraph,
252       Map<Set<Integer>, String> mapF2LocName, Set<Integer> F) {
253
254     if (mapF2LocName.containsKey(F)) {
255       return mapF2LocName.get(F);
256     }
257
258     HNode node = basisSet.getHNode(F);
259     if (node != null) {
260       mapF2LocName.put(F, node.getName());
261       return node.getName();
262     } else {
263       if (inputGraph.BASISTOPELEMENT.equals(F)) {
264         return SSJavaAnalysis.BOTTOM;
265       } else {
266         String str = "LOC" + (seed++);
267         mapF2LocName.put(F, str);
268         return str;
269       }
270     }
271   }
272
273   private void resetCount(Map<Set<Integer>, Integer> mapFtoCount, Family family) {
274     for (Iterator<Set<Integer>> iter = family.FIterator(); iter.hasNext();) {
275       Set<Integer> F = iter.next();
276       mapFtoCount.put(F, 0);
277     }
278   }
279
280   private Map<Set<Integer>, Set<Set<Integer>>> coveringGraph(BasisSet basisSet, Family family) {
281
282     Map<Set<Integer>, Integer> mapFtoCount = new HashMap<Set<Integer>, Integer>();
283     Map<Set<Integer>, Set<Set<Integer>>> mapImSucc = new HashMap<Set<Integer>, Set<Set<Integer>>>();
284
285     // initialize COUNT(F) to 0 for all elements of the family
286     resetCount(mapFtoCount, family);
287
288     for (Iterator<Set<Integer>> iter = family.FIterator(); iter.hasNext();) {
289       Set<Integer> F = iter.next();
290       Set<HNode> gammaF = family.getGamma(F);
291
292       Set<HNode> curHNodeSet = basisSet.getHNodeSet();
293       curHNodeSet.removeAll(gammaF);
294       Set<Set<Integer>> Bset = basisSet.getBasisSetByHNodeSet(curHNodeSet);
295
296       for (Iterator iterator = Bset.iterator(); iterator.hasNext();) {
297         Set<Integer> B = (Set<Integer>) iterator.next();
298
299         Set<Integer> Fprime = new HashSet<Integer>();
300         Fprime.addAll(F);
301         Fprime.addAll(B);
302
303         // COUNT(F')++;
304         mapFtoCount.put(Fprime, mapFtoCount.get(Fprime) + 1);
305
306         // if |gamma(F')|==COUNT(F') + |gamma(F)|
307         int numGammaFprime = family.getGamma(Fprime).size();
308         int countFprime = mapFtoCount.get(Fprime);
309         int numGammaF = family.getGamma(F).size();
310         if (numGammaFprime == (countFprime + numGammaF)) {
311           // ImSucc(F)=IMSucc(F) union F'
312           addImSucc(mapImSucc, F, Fprime);
313         }
314
315       }
316       resetCount(mapFtoCount, family);
317     }
318
319     System.out.println("mapImSucc=" + mapImSucc);
320
321     return mapImSucc;
322   }
323
324   private Set<Set<Integer>> getImSucc(Map<Set<Integer>, Set<Set<Integer>>> mapImSucc, Set<Integer> F) {
325     if (!mapImSucc.containsKey(F)) {
326       mapImSucc.put(F, new HashSet<Set<Integer>>());
327     }
328     return mapImSucc.get(F);
329   }
330
331   private void addImSucc(Map<Set<Integer>, Set<Set<Integer>>> mapImSucc, Set<Integer> F,
332       Set<Integer> Fprime) {
333
334     if (!mapImSucc.containsKey(F)) {
335       mapImSucc.put(F, new HashSet<Set<Integer>>());
336     }
337
338     mapImSucc.get(F).add(Fprime);
339
340   }
341
342   private Family generateFamily(BasisSet basisSet) {
343
344     Family family = new Family();
345
346     for (Iterator<Set<Integer>> iterator = basisSet.basisIterator(); iterator.hasNext();) {
347       Set<Integer> B = iterator.next();
348
349       Set<Pair<Set<Integer>, Set<HNode>>> tobeadded = new HashSet<Pair<Set<Integer>, Set<HNode>>>();
350
351       for (Iterator<Set<Integer>> iterator2 = family.FIterator(); iterator2.hasNext();) {
352         Set<Integer> F = iterator2.next();
353
354         Set<Integer> Fprime = new HashSet<Integer>();
355         Fprime.addAll(F);
356         Fprime.addAll(B);
357
358         Set<HNode> gammaFPrimeSet = new HashSet<HNode>();
359         gammaFPrimeSet.addAll(family.getGamma(F));
360         gammaFPrimeSet.add(basisSet.getHNode(B));
361
362         if (!family.containsF(Fprime)) {
363           Pair<Set<Integer>, Set<HNode>> pair =
364               new Pair<Set<Integer>, Set<HNode>>(Fprime, gammaFPrimeSet);
365           tobeadded.add(pair);
366         } else {
367           family.updateGammaF(Fprime, gammaFPrimeSet);
368         }
369       }
370
371       for (Iterator<Pair<Set<Integer>, Set<HNode>>> iterator2 = tobeadded.iterator(); iterator2
372           .hasNext();) {
373         Pair<Set<Integer>, Set<HNode>> pair = iterator2.next();
374         family.addFElement(pair.getFirst());
375         family.updateGammaF(pair.getFirst(), pair.getSecond());
376       }
377
378     }
379     return family;
380   }
381
382   private void debug_print(HierarchyGraph inputGraph) {
383     System.out.println("\nBuild Lattice:" + inputGraph.getName());
384     System.out.println("Node2Index:\n" + inputGraph.getMapHNodeToUniqueIndex());
385     System.out.println("Node2Basis:\n" + inputGraph.getMapHNodeToBasis());
386   }
387
388 }
389
390 class Identifier {
391   public HNode node;
392   public int idx;
393
394   public Identifier(HNode n, int i) {
395     node = n;
396     idx = i;
397   }
398
399   public int hashCode() {
400     return node.hashCode() + idx;
401   }
402
403   public boolean equals(Object obj) {
404
405     if (obj instanceof Identifier) {
406       Identifier in = (Identifier) obj;
407       if (node.equals(in.node) && idx == in.idx) {
408         return true;
409       }
410     }
411
412     return false;
413   }
414
415 }
416
417 class TripleItem {
418   public HNode higherNode;
419   public Set<HNode> lowerNodeSet;
420   public int idx;
421
422   public TripleItem(HNode h, Set<HNode> l, int i) {
423     higherNode = h;
424     lowerNodeSet = l;
425     idx = i;
426   }
427
428   public int hashCode() {
429     return higherNode.hashCode() + lowerNodeSet.hashCode() + idx;
430   }
431
432   public boolean equals(Object obj) {
433
434     if (obj instanceof TripleItem) {
435       TripleItem in = (TripleItem) obj;
436       if (higherNode.equals(in.higherNode) && lowerNodeSet.equals(in.lowerNodeSet) && idx == in.idx) {
437         return true;
438       }
439     }
440
441     return false;
442   }
443
444   public String toString() {
445     return higherNode + "-" + idx + "->" + lowerNodeSet;
446   }
447 }