1 cananian 1.1.2.3 // EdgesNCallees.java, created Mon Dec 11 17:58:49 2000 by vivien
  2 vivien   1.1.2.1 // Copyright (C) 
  3 vivien   1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 vivien   1.1.2.1 package harpoon.Analysis.PointerAnalysis;
  5 vivien   1.1.2.1 
  6 vivien   1.1.2.1 import java.util.HashSet;
  7 vivien   1.1.2.1 import java.util.Set;
  8 vivien   1.1.2.1 import java.util.Iterator;
  9 vivien   1.1.2.1 import java.util.Map;
 10 vivien   1.1.2.1 
 11 vivien   1.1.2.1 import harpoon.Util.Util;
 12 vivien   1.1.2.1 
 13 vivien   1.1.2.1 import harpoon.Util.DataStructs.Relation;
 14 vivien   1.1.2.1 import harpoon.Util.DataStructs.LightRelation;
 15 vivien   1.1.2.1 import harpoon.Util.DataStructs.LightMap;
 16 vivien   1.1.2.1 
 17 vivien   1.1.2.1 
 18 vivien   1.1.2.1 /**
 19 vivien   1.1.2.1  * <code>EdgesNCallees</code> models a precedence relation between
 20 vivien   1.1.2.1  * (inside or outside) edges and call sites skipped by an on demand
 21 vivien   1.1.2.1  * analysis. This precedence relation may be strict or not. 
 22 vivien   1.1.2.1  */
 23 salcianu 1.1.2.2 public class EdgesNCallees implements java.io.Serializable {
 24 vivien   1.1.2.1     public static final boolean DEBUG     = false;
 25 vivien   1.1.2.1 
 26 vivien   1.1.2.1     // Decide whether we do precise or conservative joins...
 27 vivien   1.1.2.1     private static final boolean VERY_PRECISE = false;
 28 vivien   1.1.2.1 
 29 vivien   1.1.2.1     // The data structure itself.
 30 vivien   1.1.2.1     public Map edges;
 31 vivien   1.1.2.1     
 32 vivien   1.1.2.1     // Flag which specifies if the precedence relation is an ``always
 33 vivien   1.1.2.1     // precedes'' relation (strict = true), or a ``may be precedes''
 34 vivien   1.1.2.1     // relation.
 35 vivien   1.1.2.1     private  boolean strict = true;
 36 vivien   1.1.2.1     
 37 vivien   1.1.2.1 
 38 vivien   1.1.2.1     /** Return the type of the precedence relation. true means "always
 39 vivien   1.1.2.1      * precedes".
 40 vivien   1.1.2.1      */
 41 vivien   1.1.2.1     public boolean strict()
 42 vivien   1.1.2.1     {
 43 vivien   1.1.2.1         return strict;
 44 vivien   1.1.2.1     }
 45 vivien   1.1.2.1 
 46 vivien   1.1.2.1 
 47 cananian 1.4         /** Creates a <code>EdgesNCallees</code> coding a strict precedence
 48 vivien   1.1.2.1      * relation.*/
 49 vivien   1.1.2.1     public EdgesNCallees(){
 50 vivien   1.1.2.1         edges = new LightMap();
 51 vivien   1.1.2.1         strict = true;
 52 vivien   1.1.2.1     }
 53 vivien   1.1.2.1 
 54 vivien   1.1.2.1         
 55 cananian 1.4         /** Creates a <code>EdgesNCallees</code> coding a strict precedence
 56 vivien   1.1.2.1      * relation iff the argument is true.*/
 57 vivien   1.1.2.1     public EdgesNCallees(boolean strictness){
 58 vivien   1.1.2.1         edges = new LightMap();
 59 vivien   1.1.2.1         strict = strictness;
 60 vivien   1.1.2.1     }
 61 vivien   1.1.2.1         
 62 vivien   1.1.2.1 
 63 cananian 1.4         /** Add the <code>callees</code> to the precedence relation of the
 64 cananian 1.4          * edge from a node in <code>heads</code> to a node in
 65 cananian 1.4          * <code>tails</code> via the field <code>f</code>, according to
 66 vivien   1.1.2.1      * the precedence policy (strict or not). */
 67 vivien   1.1.2.1     public void add(Set heads, String f, Set tails, Set callees)
 68 vivien   1.1.2.1     {
 69 vivien   1.1.2.1         if (callees==null) return;
 70 vivien   1.1.2.1 
 71 vivien   1.1.2.1         for(Iterator h_it=heads.iterator(); h_it.hasNext(); )
 72 vivien   1.1.2.1             add((PANode)h_it.next(), f, tails, callees);
 73 vivien   1.1.2.1     }
 74 vivien   1.1.2.1    
 75 vivien   1.1.2.1 
 76 cananian 1.4         /** Add the <code>callees</code> to the precedence relation of the
 77 cananian 1.4          * edge from a node in <code>heads</code> to <code>tail</code> via
 78 cananian 1.4          * the field <code>f</code>, according to the precedence policy
 79 vivien   1.1.2.1      * (strict or not). */
 80 vivien   1.1.2.1     public void add(Set heads, String f, PANode tail, Set callees)
 81 vivien   1.1.2.1     {
 82 vivien   1.1.2.1         if (callees==null) return;
 83 vivien   1.1.2.1 
 84 vivien   1.1.2.1         for(Iterator h_it=heads.iterator(); h_it.hasNext(); )
 85 vivien   1.1.2.1             add((PANode)h_it.next(), f, tail, callees);
 86 vivien   1.1.2.1     }
 87 vivien   1.1.2.1 
 88 vivien   1.1.2.1    
 89 cananian 1.4         /** Add the <code>callees</code> to the precedence relation of the
 90 cananian 1.4          * edge from <code>head</code> to <code>tail</code> via the field
 91 cananian 1.4          * <code>f</code>, according to the precedence policy (strict or
 92 vivien   1.1.2.1      * not). */
 93 vivien   1.1.2.1     public void add(PANode head, String f, PANode tail, Set callees)
 94 vivien   1.1.2.1     {
 95 vivien   1.1.2.1         if (callees==null) return;
 96 vivien   1.1.2.1 
 97 vivien   1.1.2.1         Map from_head = (Map) edges.get(head);
 98 vivien   1.1.2.1 
 99 vivien   1.1.2.1         // To avoid the empty set problem
100 vivien   1.1.2.1         HashSet holes = new HashSet(callees);
101 vivien   1.1.2.1         holes.add(ODPointerAnalysis.BottomHole);
102 vivien   1.1.2.1         //tbu the bottomhole should be an element of MethodHole class
103 vivien   1.1.2.1 
104 vivien   1.1.2.1         if (from_head==null){
105 vivien   1.1.2.1             Relation tails = (Relation) new LightRelation();
106 vivien   1.1.2.1             tails.addAll(tail,holes);
107 vivien   1.1.2.1             from_head = new LightMap();
108 vivien   1.1.2.1             from_head.put(f,tails);
109 vivien   1.1.2.1             edges.put(head,from_head);
110 vivien   1.1.2.1         }
111 vivien   1.1.2.1         else{
112 vivien   1.1.2.1             Relation tails = (Relation) from_head.get(f);
113 vivien   1.1.2.1             if (tails==null){
114 vivien   1.1.2.1                 tails = new LightRelation();
115 vivien   1.1.2.1                 tails.addAll(tail,holes);
116 vivien   1.1.2.1                 from_head.put(f,tails);
117 vivien   1.1.2.1             }
118 vivien   1.1.2.1             else{
119 vivien   1.1.2.1                 if (strict){
120 vivien   1.1.2.1                     Set sites = tails.getValues(tail);
121 vivien   1.1.2.1                     if (sites==null){
122 vivien   1.1.2.1                         tails.addAll(tail,holes);
123 vivien   1.1.2.1                     }
124 vivien   1.1.2.1                     else{
125 vivien   1.1.2.1                         HashSet for_trash = new HashSet();
126 vivien   1.1.2.1                         for(Iterator it=sites.iterator();it.hasNext();){
127 vivien   1.1.2.1                             Object hole =  it.next();
128 vivien   1.1.2.1                             if (!holes.contains(hole)) for_trash.add(hole);
129 vivien   1.1.2.1                         }
130 vivien   1.1.2.1                         tails.removeAll(tail,for_trash);
131 vivien   1.1.2.1                     }
132 vivien   1.1.2.1                 }
133 vivien   1.1.2.1                 else{
134 vivien   1.1.2.1                     tails.addAll(tail,holes);
135 vivien   1.1.2.1                 }
136 vivien   1.1.2.1             }
137 vivien   1.1.2.1         }
138 vivien   1.1.2.1         if (DEBUG){
139 vivien   1.1.2.1             System.out.println("New relation " + toString());
140 vivien   1.1.2.1         }
141 vivien   1.1.2.1     }
142 vivien   1.1.2.1 
143 vivien   1.1.2.1 
144 cananian 1.4         /** Add the <code>callees</code> to the precedence relation of all
145 cananian 1.4          * the edges from <code>head</code> to a node in
146 cananian 1.4          * <code>tails</code> via the field <code>f</code>, according to
147 vivien   1.1.2.1      * the precedence policy (strict or not). */
148 vivien   1.1.2.1     public void add(PANode head, String f, Set tails, Set callees)
149 vivien   1.1.2.1     {
150 vivien   1.1.2.1         if (callees==null) return;
151 vivien   1.1.2.1 
152 vivien   1.1.2.1         if (DEBUG)
153 vivien   1.1.2.1             {
154 vivien   1.1.2.1                 System.out.println("EdgesNCallees.add: " + 
155 vivien   1.1.2.1                                    head +" "+ f +" "+ tails 
156 vivien   1.1.2.1                                    + " (" + callees + " ) to \n" 
157 vivien   1.1.2.1                                    + toString());
158 vivien   1.1.2.1             }
159 vivien   1.1.2.1 
160 vivien   1.1.2.1         Map from_head = (Map) edges.get(head);
161 vivien   1.1.2.1 
162 vivien   1.1.2.1         // To avoid the empty set problem
163 vivien   1.1.2.1         HashSet holes = new HashSet(callees);
164 vivien   1.1.2.1         holes.add(ODPointerAnalysis.BottomHole);
165 vivien   1.1.2.1         //tbu the bottomhole should be an element of MethodHole class
166 vivien   1.1.2.1 
167 vivien   1.1.2.1         if (from_head==null){
168 vivien   1.1.2.1             from_head = new LightMap();
169 vivien   1.1.2.1             Relation tail_rel = (Relation) new LightRelation();
170 cananian 1.6                 for(Object tailO : tails){
171 cananian 1.6                     PANode tail = (PANode) tailO;
172 vivien   1.1.2.1                 tail_rel.addAll(tail,holes);
173 vivien   1.1.2.1             }
174 vivien   1.1.2.1             from_head.put(f,tail_rel);
175 vivien   1.1.2.1             edges.put(head,from_head);
176 vivien   1.1.2.1         }
177 vivien   1.1.2.1         else{
178 vivien   1.1.2.1             Relation tail_rel = (Relation) from_head.get(f);
179 vivien   1.1.2.1             if (tail_rel==null){
180 vivien   1.1.2.1                 tail_rel = new LightRelation();
181 cananian 1.6                     for(Object tailO : tails){
182 cananian 1.6                         PANode tail = (PANode) tailO;
183 vivien   1.1.2.1                     tail_rel.addAll(tail,holes);
184 vivien   1.1.2.1                 }
185 vivien   1.1.2.1                 from_head.put(f,tail_rel);
186 vivien   1.1.2.1             }
187 vivien   1.1.2.1             else{
188 vivien   1.1.2.1                 if (strict){
189 cananian 1.6                         for(Object tailO : tails){
190 cananian 1.6                             PANode tail = (PANode) tailO;
191 vivien   1.1.2.1                         Set sites = tail_rel.getValues(tail);
192 vivien   1.1.2.1                         if (sites==null){
193 vivien   1.1.2.1                             tail_rel.addAll(tail,holes);
194 vivien   1.1.2.1                         }
195 vivien   1.1.2.1                         else{
196 vivien   1.1.2.1                             HashSet for_trash = new HashSet();
197 vivien   1.1.2.1                             for(Iterator it=sites.iterator();it.hasNext();){
198 vivien   1.1.2.1                                 Object hole =  it.next();
199 vivien   1.1.2.1                                 if (!holes.contains(hole)) for_trash.add(hole);
200 vivien   1.1.2.1                             }
201 vivien   1.1.2.1                             tail_rel.removeAll(tail,for_trash);
202 vivien   1.1.2.1                         }
203 vivien   1.1.2.1                     }
204 vivien   1.1.2.1                 }
205 vivien   1.1.2.1                 else{
206 vivien   1.1.2.1                     for(Iterator t_it=tails.iterator(); t_it.hasNext(); )
207 vivien   1.1.2.1                         tail_rel.addAll(t_it.next(),holes);
208 vivien   1.1.2.1                 }
209 vivien   1.1.2.1             }
210 vivien   1.1.2.1         }
211 vivien   1.1.2.1         if (DEBUG){
212 vivien   1.1.2.1             System.out.println("New relation " + toString());
213 vivien   1.1.2.1         }
214 vivien   1.1.2.1     }
215 vivien   1.1.2.1 
216 vivien   1.1.2.1 
217 cananian 1.4         /** Set the <code>callees</code> to the precedence relation of the
218 cananian 1.4          * edge from <code>head</code> to <code>tail</code> via the field
219 cananian 1.4          * <code>f</code>.
220 vivien   1.1.2.1      */
221 vivien   1.1.2.1     public void set(PANode head, String f, PANode tail, Set callees)
222 vivien   1.1.2.1     {
223 vivien   1.1.2.1         if (callees==null) return;
224 vivien   1.1.2.1 
225 vivien   1.1.2.1         Map from_head = (Map) edges.get(head);
226 vivien   1.1.2.1 
227 vivien   1.1.2.1         // To avoid the empty set problem
228 vivien   1.1.2.1         HashSet holes = new HashSet(callees);
229 vivien   1.1.2.1         holes.add(ODPointerAnalysis.BottomHole);
230 vivien   1.1.2.1         //tbu the bottomhole should be an element of MethodHole class
231 vivien   1.1.2.1 
232 vivien   1.1.2.1         if (from_head==null){
233 vivien   1.1.2.1             Relation tails = (Relation) new LightRelation();
234 vivien   1.1.2.1             tails.addAll(tail,holes);
235 vivien   1.1.2.1             from_head = new LightMap();
236 vivien   1.1.2.1             from_head.put(f,tails);
237 vivien   1.1.2.1             edges.put(head,from_head);
238 vivien   1.1.2.1         }
239 vivien   1.1.2.1         else{
240 vivien   1.1.2.1             Relation tails = (Relation) from_head.get(f);
241 vivien   1.1.2.1             if (tails==null){
242 vivien   1.1.2.1                 tails = new LightRelation();
243 vivien   1.1.2.1                 tails.addAll(tail,holes);
244 vivien   1.1.2.1                 from_head.put(f,tails);
245 vivien   1.1.2.1             }
246 vivien   1.1.2.1             else{
247 vivien   1.1.2.1                 tails.removeKey(tail);
248 vivien   1.1.2.1                 tails.addAll(tail, holes);
249 vivien   1.1.2.1             }
250 vivien   1.1.2.1         }
251 vivien   1.1.2.1     }
252 vivien   1.1.2.1 
253 vivien   1.1.2.1 
254 vivien   1.1.2.1     /** Return the set of callees in relation with the edges from
255 cananian 1.4          * <code>head</code> to <code>tail</code> via the field
256 cananian 1.4          * <code>f</code>.*/
257 vivien   1.1.2.1     public Set callees(PANode head, String f, PANode tail)
258 vivien   1.1.2.1     {
259 vivien   1.1.2.1         Map from_head = (Map) edges.get(head);
260 vivien   1.1.2.1         
261 vivien   1.1.2.1         if (from_head==null){
262 vivien   1.1.2.1             System.err.println("Error in EdgesNCallees.callees (1): "
263 vivien   1.1.2.1                                + "Map should not be null");
264 vivien   1.1.2.1             System.out.println("Error in EdgesNCallees.callees (1): "
265 vivien   1.1.2.1                                + "Map should not be null");
266 vivien   1.1.2.1             System.out.println("Problem for: " + head + " --" + f + "-> " + tail);
267 vivien   1.1.2.1             System.out.println("in " + this);
268 vivien   1.1.2.1 
269 vivien   1.1.2.1             if(DEBUG){
270 vivien   1.1.2.1                 System.out.println(head + " - " + f + " -> " + tail);
271 vivien   1.1.2.1                 System.out.println(" " + head + "(" + head.details() + ")");
272 vivien   1.1.2.1                 if (head.isCSSpec()){
273 vivien   1.1.2.1                     System.out.println("This is a CS specialization");
274 vivien   1.1.2.1                 }
275 vivien   1.1.2.1                 else{
276 vivien   1.1.2.1                     System.out.println("This is **NOT** a CS specialization");
277 vivien   1.1.2.1                 }
278 vivien   1.1.2.1                 System.out.println("  " + head.getCSParent());
279 vivien   1.1.2.1                 System.out.println("  " + head.getTSParent());
280 vivien   1.1.2.1                 System.out.println(toString());
281 vivien   1.1.2.1             }
282 vivien   1.1.2.1             return null; 
283 vivien   1.1.2.1         }
284 vivien   1.1.2.1         else{
285 vivien   1.1.2.1             Relation tails = (Relation) from_head.get(f);
286 vivien   1.1.2.1             if (tails==null){
287 vivien   1.1.2.1                 System.err.println("Error in EdgesNCallees.callees (2): "
288 vivien   1.1.2.1                                    + "Relation should not be null");
289 vivien   1.1.2.1                 System.out.println("Error in EdgesNCallees.callees (2): "
290 vivien   1.1.2.1                                    + "Relation should not be null");
291 vivien   1.1.2.1                 if(DEBUG){
292 vivien   1.1.2.1                     System.out.println(head + " - " + f + " -> " + tail);
293 vivien   1.1.2.1                     System.out.println(" " + head + "(" + head.details() 
294 vivien   1.1.2.1                                        + ")\n " + toString());
295 vivien   1.1.2.1                 }
296 vivien   1.1.2.1                 return new HashSet();
297 vivien   1.1.2.1             }
298 vivien   1.1.2.1             else
299 vivien   1.1.2.1                 return new HashSet(tails.getValues(tail));
300 vivien   1.1.2.1         }
301 vivien   1.1.2.1     }
302 vivien   1.1.2.1 
303 vivien   1.1.2.1     /** Same as callees but whithout the error messages (this method
304 vivien   1.1.2.1      * is not used in the same context).
305 vivien   1.1.2.1      */
306 vivien   1.1.2.1     private Set calleessilent(PANode head, String f, PANode tail)
307 vivien   1.1.2.1     {
308 vivien   1.1.2.1         Map from_head = (Map) edges.get(head);
309 vivien   1.1.2.1         
310 vivien   1.1.2.1         if (from_head==null){
311 vivien   1.1.2.1             return null;
312 vivien   1.1.2.1         }
313 vivien   1.1.2.1         else{
314 vivien   1.1.2.1             Relation tails = (Relation) from_head.get(f);
315 vivien   1.1.2.1             if (tails==null)
316 vivien   1.1.2.1                 return null;
317 vivien   1.1.2.1             else
318 vivien   1.1.2.1                 return new HashSet(tails.getValues(tail));
319 vivien   1.1.2.1         }
320 vivien   1.1.2.1     }
321 vivien   1.1.2.1 
322 vivien   1.1.2.1 
323 vivien   1.1.2.1     /** Removes the MethodHole <code>hole</code> from all the sets of
324 vivien   1.1.2.1      * callees that may contain it.
325 vivien   1.1.2.1      */
326 vivien   1.1.2.1     public void remove(MethodHole hole)
327 vivien   1.1.2.1     {
328 vivien   1.1.2.1         if (edges==null) return;
329 vivien   1.1.2.1 
330 cananian 1.6             for(Object n1O : edges.keySet()){
331 cananian 1.6                 PANode n1 = (PANode) n1O;
332 vivien   1.1.2.1             Map n1_map = (Map) edges.get(n1);
333 cananian 1.6                 for(Object fO : n1_map.keySet()){
334 cananian 1.6                     String f = (String) fO; 
335 vivien   1.1.2.1                 Relation n1_f = (Relation) n1_map.get(f);
336 cananian 1.6                     for(Object n2O : n1_f.keys()){
337 cananian 1.6                         PANode n2 = (PANode) n2O;
338 vivien   1.1.2.1                     n1_f.remove(n2,hole);
339 vivien   1.1.2.1                 }
340 vivien   1.1.2.1             }
341 vivien   1.1.2.1         }
342 vivien   1.1.2.1     }
343 vivien   1.1.2.1 
344 vivien   1.1.2.1 
345 vivien   1.1.2.1     /** Conservative implementation */
346 vivien   1.1.2.1     public void join(Set firstHoles, EdgesNCallees second, Set secondHoles)
347 vivien   1.1.2.1     {
348 vivien   1.1.2.1         if (second==null) return;
349 vivien   1.1.2.1         
350 cananian 1.3.2.1         assert strict==second.strict() : "Attempt to join to EdgesNCallees "
351 cananian 1.3.2.1                     + "of different types"; 
352 vivien   1.1.2.1         
353 cananian 1.6             for(Object n1O : second.edges.keySet()){
354 cananian 1.6                 PANode n1 = (PANode) n1O;
355 vivien   1.1.2.1             Map n1_map = (Map) second.edges.get(n1);
356 vivien   1.1.2.1 
357 cananian 1.6                 for(Object fO : n1_map.keySet()){
358 cananian 1.6                     String f = (String) fO; 
359 vivien   1.1.2.1                 Relation n1_f = (Relation) n1_map.get(f);
360 vivien   1.1.2.1                 
361 cananian 1.6                     for(Object n2O : n1_f.keys()){
362 cananian 1.6                         PANode n2 = (PANode) n2O;
363 vivien   1.1.2.1                     if (strict){
364 vivien   1.1.2.1                         HashSet callees_1 = (HashSet) callees(n1, f, n2);
365 vivien   1.1.2.1                         if((callees_1==null)||(callees_1.isEmpty())){
366 vivien   1.1.2.1                             // simple addition as the edge does not
367 vivien   1.1.2.1                             // exist in the current object.
368 vivien   1.1.2.1                             add(n1, f, n2, n1_f.getValues(n2));
369 vivien   1.1.2.1                         }
370 vivien   1.1.2.1                         else{
371 vivien   1.1.2.1                             HashSet callees_2 = (HashSet) n1_f.getValues(n2);
372 vivien   1.1.2.1 
373 vivien   1.1.2.1                             // Intersection
374 vivien   1.1.2.1                             HashSet intersect = (HashSet) callees_1.clone();
375 vivien   1.1.2.1                             intersect.retainAll(callees_2);
376 vivien   1.1.2.1 
377 vivien   1.1.2.1                             // The holes in the current object but
378 vivien   1.1.2.1                             // unknown in "second" should be kept.
379 vivien   1.1.2.1                             HashSet firstMinusSecond = (HashSet) callees_1.clone();
380 vivien   1.1.2.1                             firstMinusSecond.removeAll(callees_2);
381 vivien   1.1.2.1 
382 vivien   1.1.2.1                             // Conversely
383 vivien   1.1.2.1                             callees_2.removeAll(callees_1);
384 vivien   1.1.2.1 
385 vivien   1.1.2.1                             // What should be kept, other than the
386 vivien   1.1.2.1                             // intersection
387 vivien   1.1.2.1                             firstMinusSecond.addAll(callees_2);
388 vivien   1.1.2.1 
389 vivien   1.1.2.1                             // The final set
390 vivien   1.1.2.1                             firstMinusSecond.addAll(intersect);
391 vivien   1.1.2.1                             
392 vivien   1.1.2.1                             set(n1, f, n2, firstMinusSecond);
393 vivien   1.1.2.1                         }
394 vivien   1.1.2.1                     }
395 vivien   1.1.2.1                     else
396 vivien   1.1.2.1                         add(n1, f, n2, n1_f.getValues(n2));
397 vivien   1.1.2.1                 }
398 vivien   1.1.2.1             }
399 vivien   1.1.2.1         }
400 vivien   1.1.2.1     }
401 vivien   1.1.2.1 
402 vivien   1.1.2.1     /** Conservative implementation */
403 vivien   1.1.2.1     public void joinbis(EdgesNCallees second)
404 vivien   1.1.2.1     {
405 vivien   1.1.2.1         if (second==null) return;
406 vivien   1.1.2.1         
407 cananian 1.3.2.1         assert strict==second.strict() : "Attempt to join to EdgesNCallees "
408 cananian 1.3.2.1                     + "of different types"; 
409 vivien   1.1.2.1         
410 cananian 1.6             for(Object n1O : second.edges.keySet()){
411 cananian 1.6                 PANode n1 = (PANode) n1O;
412 vivien   1.1.2.1             Map n1_map = (Map) second.edges.get(n1);
413 vivien   1.1.2.1 
414 cananian 1.6                 for(Object fO : n1_map.keySet()){
415 cananian 1.6                     String f = (String) fO; 
416 vivien   1.1.2.1                 Relation n1_f = (Relation) n1_map.get(f);
417 vivien   1.1.2.1                 
418 cananian 1.6                     for(Object n2O : n1_f.keys()){
419 cananian 1.6                         PANode n2 = (PANode) n2O;
420 vivien   1.1.2.1                     if (strict){
421 vivien   1.1.2.1                         // A real implementation should be more precise than that !
422 vivien   1.1.2.1                         add(n1, f, n2, n1_f.getValues(n2));
423 vivien   1.1.2.1                     }
424 vivien   1.1.2.1                     else
425 vivien   1.1.2.1                         add(n1, f, n2, n1_f.getValues(n2));
426 vivien   1.1.2.1                 }
427 vivien   1.1.2.1             }
428 vivien   1.1.2.1         }
429 vivien   1.1.2.1     }
430 vivien   1.1.2.1 
431 vivien   1.1.2.1 
432 vivien   1.1.2.1     /** Conservative implementation */
433 vivien   1.1.2.1     public void join(EdgesNCallees second, Map holeConversion, 
434 vivien   1.1.2.1                      Set firstholes, Set secondholes,
435 vivien   1.1.2.1                      Set control)
436 vivien   1.1.2.1     {
437 vivien   1.1.2.1         if (second==null) return;
438 vivien   1.1.2.1         
439 cananian 1.3.2.1         assert strict==second.strict() : "Attempt to join to EdgesNCallees "
440 cananian 1.3.2.1                     + "of different types"; 
441 vivien   1.1.2.1         
442 cananian 1.6             for(Object n1O : second.edges.keySet()){
443 cananian 1.6                 PANode n1 = (PANode) n1O;
444 vivien   1.1.2.1             Map n1_map = (Map) second.edges.get(n1);
445 vivien   1.1.2.1 
446 cananian 1.6                 for(Object fO : n1_map.keySet()){
447 cananian 1.6                     String f = (String) fO; 
448 vivien   1.1.2.1                 Relation n1_f = (Relation) n1_map.get(f);
449 vivien   1.1.2.1                 
450 cananian 1.6                     for(Object n2O : n1_f.keys()){
451 cananian 1.6                         PANode n2 = (PANode) n2O;
452 vivien   1.1.2.1                     if (strict){
453 vivien   1.1.2.1                         if (VERY_PRECISE){
454 vivien   1.1.2.1                             HashSet callees_1 = (HashSet) calleessilent(n1, f, n2);
455 vivien   1.1.2.1                             if((callees_1==null)||(callees_1.isEmpty())){
456 vivien   1.1.2.1                                 // simple addition as the edge does not
457 vivien   1.1.2.1                                 // exist in the current object.
458 vivien   1.1.2.1                                 set(n1, f, n2, project(n1_f.getValues(n2), holeConversion));
459 vivien   1.1.2.1                             }
460 vivien   1.1.2.1                             else{
461 vivien   1.1.2.1                                 HashSet callees_2 = 
462 vivien   1.1.2.1                                     (HashSet) project(n1_f.getValues(n2), holeConversion);
463 vivien   1.1.2.1                                 
464 vivien   1.1.2.1                                 // Intersection
465 vivien   1.1.2.1                                 HashSet intersect = (HashSet) callees_1.clone();
466 vivien   1.1.2.1                                 intersect.retainAll(callees_2);
467 vivien   1.1.2.1                                 
468 vivien   1.1.2.1                                 if ((intersect.size()!=callees_1.size())||
469 vivien   1.1.2.1                                     (intersect.size()!=callees_2.size())){
470 vivien   1.1.2.1                                     // The holes in the current object but
471 vivien   1.1.2.1                                     // unknown in "second" should be kept.
472 vivien   1.1.2.1                                     callees_1.removeAll(secondholes);
473 vivien   1.1.2.1                                     
474 vivien   1.1.2.1                                     // Conversely
475 vivien   1.1.2.1                                     callees_2.removeAll(firstholes);
476 vivien   1.1.2.1                                     
477 vivien   1.1.2.1                                     // What should be kept, other than the
478 vivien   1.1.2.1                                     // intersection
479 vivien   1.1.2.1                                     intersect.addAll(callees_2);
480 vivien   1.1.2.1                                     
481 vivien   1.1.2.1                                     // The final set
482 vivien   1.1.2.1                                     intersect.addAll(callees_1);
483 vivien   1.1.2.1                                 }
484 vivien   1.1.2.1 
485 vivien   1.1.2.1                             set(n1, f, n2, intersect);
486 vivien   1.1.2.1                             }
487 vivien   1.1.2.1                         }
488 vivien   1.1.2.1                         else{
489 vivien   1.1.2.1                             add(n1, f, n2, 
490 vivien   1.1.2.1                                 project(n1_f.getValues(n2), holeConversion));
491 vivien   1.1.2.1                         }
492 vivien   1.1.2.1                     }
493 vivien   1.1.2.1                     else
494 vivien   1.1.2.1                         add(n1, f, n2, project(n1_f.getValues(n2), holeConversion));
495 vivien   1.1.2.1                 }
496 vivien   1.1.2.1             }
497 vivien   1.1.2.1         }
498 vivien   1.1.2.1     }
499 vivien   1.1.2.1 
500 vivien   1.1.2.1     /** Simply clone an <code>EdgesNCallees</code> object.
501 vivien   1.1.2.1      */
502 vivien   1.1.2.1     public Object clone()
503 vivien   1.1.2.1     {
504 cananian 1.3.2.1         assert edges!=null : ("Problem in EdgesNCallees.clone: null map");
505 vivien   1.1.2.1 
506 vivien   1.1.2.1         EdgesNCallees new_enc = new EdgesNCallees(strict);
507 vivien   1.1.2.1 
508 cananian 1.6             for(Object n1O : edges.keySet()){
509 cananian 1.6                 PANode n1 = (PANode) n1O;
510 vivien   1.1.2.1             Map n1_map = (Map) edges.get(n1);
511 vivien   1.1.2.1             Map new_n1_map = new LightMap();
512 vivien   1.1.2.1 
513 cananian 1.6                 for(Object fO : n1_map.keySet()){
514 cananian 1.6                     String f = (String) fO; 
515 vivien   1.1.2.1                 Relation n1_f = (Relation) n1_map.get(f);
516 vivien   1.1.2.1                 Relation new_n1_f = new LightRelation();
517 vivien   1.1.2.1 
518 vivien   1.1.2.1                 for(Iterator it_n2=n1_f.keys().iterator(); it_n2.hasNext(); ){
519 vivien   1.1.2.1                     Object obj = it_n2.next();
520 vivien   1.1.2.1                     PANode n2 = (PANode) obj;
521 vivien   1.1.2.1                     new_n1_f.addAll(n2, n1_f.getValues(n2));
522 vivien   1.1.2.1                 }
523 vivien   1.1.2.1                 new_n1_map.put(f,new_n1_f);
524 vivien   1.1.2.1             }
525 vivien   1.1.2.1             new_enc.edges.put(n1,new_n1_map);
526 vivien   1.1.2.1         }
527 vivien   1.1.2.1         return new_enc;
528 vivien   1.1.2.1     }
529 vivien   1.1.2.1 
530 vivien   1.1.2.1 
531 vivien   1.1.2.1     /** clone the <code>EdgesNCallees</code> while transposing the
532 vivien   1.1.2.1      * callees using the <code>map</code>.
533 vivien   1.1.2.1      */
534 vivien   1.1.2.1     public EdgesNCallees clone(Map hole_conversion)
535 vivien   1.1.2.1     {
536 cananian 1.3.2.1         assert edges!=null : ("Problem in EdgesNCallees.clone: null map");
537 vivien   1.1.2.1 
538 vivien   1.1.2.1         EdgesNCallees new_enc = new EdgesNCallees(strict);
539 vivien   1.1.2.1 
540 cananian 1.6             for(Object n1O : edges.keySet()){
541 cananian 1.6                 PANode n1 = (PANode) n1O;
542 vivien   1.1.2.1             Map n1_map = (Map) edges.get(n1);
543 vivien   1.1.2.1             Map new_n1_map = new LightMap();
544 vivien   1.1.2.1 
545 cananian 1.6                 for(Object fO : n1_map.keySet()){
546 cananian 1.6                     String f = (String) fO; 
547 vivien   1.1.2.1                 Relation n1_f = (Relation) n1_map.get(f);
548 vivien   1.1.2.1                 Relation new_n1_f = new LightRelation();
549 vivien   1.1.2.1 
550 vivien   1.1.2.1                 for(Iterator it_n2=n1_f.keys().iterator(); it_n2.hasNext(); ){
551 vivien   1.1.2.1                     Object obj = it_n2.next();
552 vivien   1.1.2.1                     PANode n2 = (PANode) obj;
553 cananian 1.6                         for(Object mhO : n1_f.getValues(n2)){
554 cananian 1.6                             MethodHole mh = (MethodHole) mhO;
555 vivien   1.1.2.1                         if (mh==ODPointerAnalysis.BottomHole)
556 vivien   1.1.2.1                             new_n1_f.add(n2,ODPointerAnalysis.BottomHole);
557 vivien   1.1.2.1                         else {
558 vivien   1.1.2.1                             if (hole_conversion.get(mh)==null){
559 vivien   1.1.2.1                                 System.err.println("EdgesNCallees.clone: " +
560 vivien   1.1.2.1                                                    "no conversion for " + mh);
561 vivien   1.1.2.1                                 System.out.println("EdgesNCallees.clone: " + 
562 vivien   1.1.2.1                                                    "no conversion for " + mh
563 vivien   1.1.2.1                                                    + " in " + hole_conversion);
564 vivien   1.1.2.1                             }
565 vivien   1.1.2.1                             else
566 vivien   1.1.2.1                                 new_n1_f.add(n2,hole_conversion.get(mh));
567 vivien   1.1.2.1                         }
568 vivien   1.1.2.1                     }
569 vivien   1.1.2.1                 }
570 vivien   1.1.2.1                 new_n1_map.put(f,new_n1_f);
571 vivien   1.1.2.1             }
572 vivien   1.1.2.1             new_enc.edges.put(n1,new_n1_map);
573 vivien   1.1.2.1         }
574 vivien   1.1.2.1         return new_enc;
575 vivien   1.1.2.1     }
576 vivien   1.1.2.1 
577 vivien   1.1.2.1 
578 vivien   1.1.2.1 
579 vivien   1.1.2.1     /** clone the <code>EdgesNCallees</code> while transposing the
580 vivien   1.1.2.1      * callees using the first <code>map</code>, and the nodes using
581 vivien   1.1.2.1      * the second one.
582 vivien   1.1.2.1      */
583 vivien   1.1.2.1 
584 vivien   1.1.2.1     public EdgesNCallees clone(Map hole_conversion, Map node_conversion)
585 vivien   1.1.2.1     {
586 cananian 1.3.2.1         assert edges!=null : ("Problem in EdgesNCallees.clone: null map");
587 vivien   1.1.2.1 
588 vivien   1.1.2.1         EdgesNCallees new_enc = new EdgesNCallees(strict);
589 vivien   1.1.2.1 
590 cananian 1.6             for(Object n1O : edges.keySet()){
591 cananian 1.6                 PANode n1 = (PANode) n1O;
592 vivien   1.1.2.1             PANode new_n1  = (PANode) node_conversion.get(n1);
593 vivien   1.1.2.1             if (new_n1==null){
594 vivien   1.1.2.1                 System.err.println("Error in EdgesNCallees.clone with node_conversion");
595 vivien   1.1.2.1                 System.out.println("Error in EdgesNCallees.clone with node_conversion");
596 vivien   1.1.2.1                 System.out.println("Node with no translation: " + n1);
597 vivien   1.1.2.1                 System.out.println("Map: " + node_conversion);
598 vivien   1.1.2.1             }
599 vivien   1.1.2.1             Map n1_map = (Map) edges.get(n1);
600 vivien   1.1.2.1             Map new_n1_map = new LightMap();
601 vivien   1.1.2.1 
602 cananian 1.6                 for(Object fO : n1_map.keySet()){
603 cananian 1.6                     String f = (String) fO; 
604 vivien   1.1.2.1                 Relation n1_f = (Relation) n1_map.get(f);
605 vivien   1.1.2.1                 Relation new_n1_f = new LightRelation();
606 vivien   1.1.2.1 
607 cananian 1.6                     for(Object n2O : n1_f.keys()){
608 cananian 1.6                         PANode n2 = (PANode) n2O;
609 vivien   1.1.2.1                     PANode new_n2 = (PANode) node_conversion.get(n2);
610 vivien   1.1.2.1                     if (new_n2==null){
611 vivien   1.1.2.1                         System.err.println("Error in EdgesNCallees.clone " + 
612 vivien   1.1.2.1                                            "with node_conversion");
613 vivien   1.1.2.1                         System.out.println("Error in EdgesNCallees.clone " + 
614 vivien   1.1.2.1                                            "with node_conversion");
615 vivien   1.1.2.1                         System.out.println("Null node " + n2);
616 vivien   1.1.2.1                         System.out.println("Map: " + node_conversion);
617 vivien   1.1.2.1                     }
618 vivien   1.1.2.1 
619 cananian 1.6                         for(Object mhO : n1_f.getValues(n2)){
620 cananian 1.6                             MethodHole mh = (MethodHole) mhO;
621 vivien   1.1.2.1                         if (mh==ODPointerAnalysis.BottomHole)
622 vivien   1.1.2.1                             new_n1_f.add(new_n2,ODPointerAnalysis.BottomHole);
623 vivien   1.1.2.1                         else {
624 vivien   1.1.2.1                             if (hole_conversion.get(mh)==null){
625 vivien   1.1.2.1                                 System.err.println("EdgesNCallees.clone: " +
626 vivien   1.1.2.1                                                    "no conversion for " + mh
627 vivien   1.1.2.1                                                    + " in " + hole_conversion);
628 vivien   1.1.2.1                                 System.out.println("EdgesNCallees.clone: " +
629 vivien   1.1.2.1                                                    "no conversion for " + mh
630 vivien   1.1.2.1                                                    + " in " + hole_conversion);
631 vivien   1.1.2.1                             }
632 vivien   1.1.2.1                             else
633 vivien   1.1.2.1                                 new_n1_f.add(new_n2,hole_conversion.get(mh));
634 vivien   1.1.2.1                         }
635 vivien   1.1.2.1                     }
636 vivien   1.1.2.1                 }
637 vivien   1.1.2.1                 new_n1_map.put(f,new_n1_f);
638 vivien   1.1.2.1             }
639 vivien   1.1.2.1             new_enc.edges.put(new_n1,new_n1_map);
640 vivien   1.1.2.1         }
641 vivien   1.1.2.1         return new_enc;
642 vivien   1.1.2.1     }
643 vivien   1.1.2.1 
644 vivien   1.1.2.1 
645 vivien   1.1.2.1 
646 vivien   1.1.2.1     /** Pretty-print debug function.
647 vivien   1.1.2.1      */
648 vivien   1.1.2.1     public String toString()
649 vivien   1.1.2.1     {
650 vivien   1.1.2.1         return toString("");
651 vivien   1.1.2.1 
652 vivien   1.1.2.1     }
653 vivien   1.1.2.1 
654 vivien   1.1.2.1     /** Pretty-print debug function.
655 vivien   1.1.2.1      */
656 vivien   1.1.2.1     public String toString(String s)
657 vivien   1.1.2.1     {
658 vivien   1.1.2.1         StringBuffer buffer = new StringBuffer(" EdgesNCallees: " + s);
659 vivien   1.1.2.1 
660 vivien   1.1.2.1         if (edges==null) {
661 vivien   1.1.2.1             buffer.append("\n  --  empty --\n");
662 vivien   1.1.2.1             return buffer.toString();
663 vivien   1.1.2.1         }
664 vivien   1.1.2.1 
665 cananian 1.6             for(Object n1O : edges.keySet()){
666 cananian 1.6                 PANode n1 = (PANode) n1O;
667 vivien   1.1.2.1             buffer.append("\n" + n1 + "\t-> ");
668 vivien   1.1.2.1             Map n1_map = (Map) edges.get(n1);
669 vivien   1.1.2.1             boolean firstfield = true;
670 cananian 1.6                 for(Object fO : n1_map.keySet()){
671 cananian 1.6                     String f = (String) fO; 
672 vivien   1.1.2.1                 Relation n1_f = (Relation) n1_map.get(f);
673 vivien   1.1.2.1                 if (firstfield){
674 vivien   1.1.2.1                     buffer.append(f + "\t-> ");
675 vivien   1.1.2.1                     firstfield=false;
676 vivien   1.1.2.1                 }
677 vivien   1.1.2.1                 else
678 vivien   1.1.2.1                     buffer.append("\n\t    " + f + "\t -> ");
679 vivien   1.1.2.1                 boolean firstnode = true;
680 vivien   1.1.2.1                 for(Iterator it_n2=n1_f.keys().iterator(); it_n2.hasNext(); ){
681 vivien   1.1.2.1                     Object obj = it_n2.next();
682 vivien   1.1.2.1                     PANode n2 = (PANode) obj;
683 vivien   1.1.2.1                     if(firstnode){
684 vivien   1.1.2.1                         buffer.append(n2 + "\t-> " + 
685 vivien   1.1.2.1                                       n1_f.getValues(n2));
686 vivien   1.1.2.1                         firstnode = false;
687 vivien   1.1.2.1                     }
688 vivien   1.1.2.1                     else
689 vivien   1.1.2.1                         buffer.append("\n\t    \t    " + n2 + "\t-> " +
690 vivien   1.1.2.1                                       n1_f.getValues(n2));
691 vivien   1.1.2.1                 }
692 vivien   1.1.2.1             }
693 vivien   1.1.2.1         }
694 vivien   1.1.2.1         return buffer.toString();
695 vivien   1.1.2.1     }
696 vivien   1.1.2.1 
697 vivien   1.1.2.1     public Set project(Set holes, Map projection)
698 vivien   1.1.2.1     {
699 vivien   1.1.2.1         HashSet newHoles = new HashSet();
700 vivien   1.1.2.1 
701 vivien   1.1.2.1         for(Iterator it=holes.iterator(); it.hasNext(); )
702 vivien   1.1.2.1             newHoles.add(projection.get(it.next()));
703 vivien   1.1.2.1 
704 vivien   1.1.2.1         return newHoles;
705 vivien   1.1.2.1     }
706 vivien   1.1.2.1     
707 vivien   1.1.2.1 
708 cananian 1.2     }