1 salcianu 1.1.2.1  // ParIntGraph.java, created Sun Jan  9 15:40:59 2000 by salcianu
  2 salcianu 1.10     // Copyright (C) 2000 Alexandru SALCIANU <salcianu@mit.edu>
  3 salcianu 1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 salcianu 1.1.2.1  package harpoon.Analysis.PointerAnalysis;
  5 salcianu 1.1.2.1  
  6 salcianu 1.1.2.3  
  7 salcianu 1.1.2.3  import java.util.Set;
  8 salcianu 1.1.2.3  import java.util.HashSet;
  9 salcianu 1.1.2.18 import java.util.Map;
 10 salcianu 1.1.2.18 import java.util.HashMap;
 11 salcianu 1.1.2.18 import java.util.Iterator;
 12 salcianu 1.1.2.9  import java.util.Collections;
 13 salcianu 1.1.2.36 import java.util.LinkedList;
 14 salcianu 1.1.2.36 
 15 salcianu 1.10     import net.cscott.jutil.PersistentSet;
 16 salcianu 1.1.2.3  
 17 salcianu 1.1.2.12 import harpoon.Temp.Temp;
 18 salcianu 1.1.2.14 import harpoon.IR.Quads.CALL;
 19 salcianu 1.1.2.20 import harpoon.Analysis.MetaMethods.MetaMethod;
 20 salcianu 1.1.2.25 import harpoon.Util.Util;
 21 salcianu 1.1.2.12 
 22 salcianu 1.1.2.35 import harpoon.Util.DataStructs.Relation;
 23 salcianu 1.1.2.48 import harpoon.Util.DataStructs.RelationImpl;
 24 salcianu 1.1.2.35 import harpoon.Util.DataStructs.LightRelation;
 25 salcianu 1.1.2.35 import harpoon.Util.DataStructs.RelationEntryVisitor;
 26 salcianu 1.1.2.35 
 27 salcianu 1.1.2.35 
 28 salcianu 1.1.2.1  /**
 29 salcianu 1.1.2.24  * <code>ParIntGraph</code> models a Parallel Interaction Graph data
 30 salcianu 1.1.2.24  structure. Most of its fields retain the original name from the paper
 31 salcianu 1.1.2.24  of Martin and John Whaley.
 32 salcianu 1.1.2.1   * 
 33 cananian 1.1.2.49  * @author  Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
 34 cananian 1.11      * @version $Id: ParIntGraph.java,v 1.11 2004/03/20 02:25:23 cananian Exp $
 35 salcianu 1.1.2.1   */
 36 salcianu 1.10     public class ParIntGraph implements java.io.Serializable, Cloneable {
 37 salcianu 1.1.2.1  
 38 salcianu 1.1.2.24     public static boolean DEBUG = false;
 39 salcianu 1.1.2.24     public static boolean DEBUG2 = false;
 40 salcianu 1.1.2.12 
 41 salcianu 1.1.2.25     /** Debug for the aggressive shrinking. */
 42 salcianu 1.1.2.25     public static boolean DEBUG_AS = false;
 43 salcianu 1.1.2.27 
 44 salcianu 1.4          /** Display the gains due to AGGRESSIVE_SHRINKING. */
 45 salcianu 1.6          public static boolean MEASURE_AS = true;
 46 salcianu 1.1.2.44 
 47 salcianu 1.1.2.27     /** Activates the aggressive shrinking. Buggy for the moment ... */
 48 salcianu 1.6          public static boolean AGGRESSIVE_SHRINKING = false;
 49 salcianu 1.1.2.25 
 50 salcianu 1.1.2.2      /** Default (empty) graph. It doesn't contain any information.  */
 51 salcianu 1.1.2.2      public static final ParIntGraph EMPTY_GRAPH = new ParIntGraph();
 52 salcianu 1.1.2.2  
 53 salcianu 1.1.2.7      /** Points-to escape graph that summarizes the points-to and escape
 54 salcianu 1.1.2.7          information for the current thread. */
 55 salcianu 1.1.2.1      public PointsToGraph G;
 56 salcianu 1.1.2.1      
 57 salcianu 1.1.2.24     /** The paralel thread map; it attaches to each thread node nT, an 
 58 salcianu 1.1.2.7          integer from the set {0,1,2} where 2 signifies the possibility
 59 salcianu 1.1.2.7          that multiple instances of nT execute in parallel with the current
 60 salcianu 1.1.2.7          thread. */
 61 salcianu 1.1.2.1      public PAThreadMap tau;
 62 salcianu 1.1.2.1      
 63 salcianu 1.1.2.24     /** Maintains the actions executed by the analysed code and the parallel
 64 salcianu 1.1.2.7          action relation. <code>alpha</code> and <code>pi</code> from the 
 65 salcianu 1.1.2.7          original paper have been merged into this single field for efficiency
 66 salcianu 1.1.2.7          reasons. */
 67 salcianu 1.1.2.7      public ActionRepository ar;
 68 salcianu 1.1.2.11 
 69 salcianu 1.1.2.11     /** Maintains the (conservative) ordering relations between the inside
 70 salcianu 1.1.2.11         and the outside edges. <code>before(ei,eo)</code> is true if the
 71 salcianu 1.1.2.24         inside edge ei might be created before the ouside edge eo was read. */
 72 salcianu 1.1.2.11     public EdgeOrdering eo;
 73 salcianu 1.8      
 74 salcianu 1.10         /** Contains mutated fields. */
 75 cananian 1.11         public PersistentSet/*<PAField>*/ mutated;
 76 salcianu 1.10     
 77 salcianu 1.1.2.1      /** Creates a <code>ParIntGraph</code>. */
 78 salcianu 1.1.2.1      public ParIntGraph() {
 79 salcianu 1.1.2.7          G   = new PointsToGraph();
 80 salcianu 1.1.2.1          tau = new PAThreadMap();
 81 salcianu 1.1.2.42         ar  = PointerAnalysis.RECORD_ACTIONS ? new ActionRepository() : null;
 82 salcianu 1.1.2.42         eo  = PointerAnalysis.IGNORE_EO ? null : new EdgeOrdering();
 83 salcianu 1.1.2.1      }
 84 salcianu 1.1.2.10 
 85 salcianu 1.1.2.7      /** <code>join</code> combines two <code>ParIntGraph</code>s in \
 86 salcianu 1.1.2.7          a control-flow join point. */
 87 salcianu 1.1.2.1      public void join(ParIntGraph pig2){
 88 salcianu 1.1.2.36         if(pig2 == null) return;
 89 salcianu 1.1.2.36 
 90 salcianu 1.7              long b_time = PointerAnalysis.FINE_TIMING ? 
 91 salcianu 1.7                  System.currentTimeMillis() : 0;
 92 salcianu 1.7      
 93 salcianu 1.1.2.1          G.join(pig2.G);
 94 salcianu 1.1.2.1          tau.join(pig2.tau);
 95 salcianu 1.8      
 96 salcianu 1.1.2.42         if(PointerAnalysis.RECORD_ACTIONS)
 97 salcianu 1.1.2.42             ar.join(pig2.ar);
 98 salcianu 1.1.2.26 
 99 salcianu 1.1.2.26         if(!PointerAnalysis.IGNORE_EO)
100 salcianu 1.1.2.26             eo.join(pig2.eo);
101 salcianu 1.7      
102 salcianu 1.7              if(PointerAnalysis.FINE_TIMING) {
103 salcianu 1.7                  long delta = System.currentTimeMillis() - b_time;
104 salcianu 1.7                  total_join_time += delta;
105 salcianu 1.7              }   
106 salcianu 1.1.2.1      }
107 salcianu 1.1.2.9  
108 salcianu 1.1.2.9  
109 salcianu 1.1.2.9      /** Inserts the image of <code>pig2</code> parallel interaction graph
110 salcianu 1.1.2.44         through the <code>mu</code> node mapping into <code>this</code>
111 salcianu 1.1.2.44         object.
112 salcianu 1.1.2.10         This method is designed to be called at the end of the caller/callee
113 salcianu 1.1.2.10         or starter/startee interaction. It is *not* manipulating the action
114 salcianu 1.1.2.14         repository nor the edge ordering; those manipulations are too complex
115 salcianu 1.1.2.14         and variate to be done here.<br>
116 salcianu 1.1.2.14         <code>principal</code> controls whether the return and exception set
117 salcianu 1.1.2.14         are inserted. */
118 salcianu 1.1.2.14     void insertAllButArEo(ParIntGraph pig2, Relation mu,
119 salcianu 1.7                                boolean principal, Set noholes) {
120 salcianu 1.7              insertAllButArEo(pig2, mu, principal, noholes, null, false);
121 salcianu 1.7          }
122 salcianu 1.7      
123 salcianu 1.7          // If ppgRoots != null, collect in ppgRoots all nodes that we need
124 salcianu 1.7          // to re-propagate escape info from:
125 salcianu 1.7          // 1. starting points for new edges
126 salcianu 1.7          // 2. nodes whose escape info has changed
127 salcianu 1.7          // Note: works only if !fullProj
128 salcianu 1.7          void insertAllButArEo(ParIntGraph pig2, Relation mu, boolean principal,
129 salcianu 1.7                                Set noholes, Set ppgRoots, boolean fullProj) {
130 salcianu 1.7              G.insert(pig2.G, mu, principal, noholes, ppgRoots, fullProj);
131 salcianu 1.1.2.35         tau.insert(pig2.tau, mu);
132 salcianu 1.1.2.9      }
133 salcianu 1.1.2.9  
134 salcianu 1.1.2.9      /** Convenient function equivalent to 
135 salcianu 1.1.2.14         <code>insertAllButArEo(pig2,mu,principal,Collections.EMPTY_SET). */
136 salcianu 1.1.2.14     void insertAllButArEo(ParIntGraph pig2, Relation mu, boolean principal){
137 salcianu 1.1.2.42         insertAllButArEo(pig2, mu, principal, Collections.EMPTY_SET);
138 salcianu 1.1.2.9      }
139 salcianu 1.1.2.9  
140 salcianu 1.1.2.1  
141 salcianu 1.1.2.48     ParIntGraph getBarVersion() {
142 salcianu 1.1.2.48         ParIntGraph bar_pig = new ParIntGraph();
143 salcianu 1.1.2.48         bar_pig.G = this.G.specialize(get_g2b_map(allNodes()));
144 salcianu 1.1.2.48         return bar_pig;
145 salcianu 1.1.2.48     }
146 salcianu 1.1.2.48 
147 salcianu 1.1.2.48     // Get the mapping "genuine node -> bar node" for node \in nodes
148 salcianu 1.1.2.48     private Map get_g2b_map(Set nodes) {
149 salcianu 1.1.2.48         Map g2b = new HashMap();
150 cananian 1.9              for(Object nodeO : nodes) {
151 cananian 1.9                  PANode node = (PANode) nodeO;
152 cananian 1.3.2.1              assert node.isGenuine() : node + " is not genuine!";
153 salcianu 1.1.2.48             PANode bar_node = node.getBarVersion();
154 salcianu 1.1.2.48             g2b.put(node, bar_node);
155 salcianu 1.1.2.48         }
156 salcianu 1.1.2.48 
157 salcianu 1.1.2.48         System.out.println("g2b = " + g2b);
158 salcianu 1.1.2.48 
159 salcianu 1.1.2.48         return g2b;
160 salcianu 1.1.2.48     }
161 salcianu 1.1.2.48 
162 salcianu 1.7          
163 salcianu 1.7      
164 salcianu 1.1.2.7      /** Check the equality of two <code>ParIntGraph</code>s. */
165 salcianu 1.7          public boolean equals(Object obj) {
166 salcianu 1.7              long b_time = PointerAnalysis.FINE_TIMING ? 
167 salcianu 1.7                  System.currentTimeMillis() : 0;
168 salcianu 1.7      
169 salcianu 1.7              boolean result = equals2(obj);
170 salcianu 1.7      
171 salcianu 1.7              if(PointerAnalysis.FINE_TIMING) {
172 salcianu 1.7                  long delta = System.currentTimeMillis() - b_time;
173 salcianu 1.7                  total_equals_time += delta;
174 salcianu 1.7              }   
175 salcianu 1.7      
176 salcianu 1.7              return result;
177 salcianu 1.7          }
178 salcianu 1.7      
179 salcianu 1.7          private boolean equals2(Object obj) {
180 salcianu 1.1.2.24         if(obj == null) return false;
181 salcianu 1.1.2.24 
182 salcianu 1.1.2.24         ParIntGraph pig2 = (ParIntGraph) obj;
183 salcianu 1.7              if(!G.equals(pig2.G)) {
184 salcianu 1.1.2.13             if(DEBUG2)
185 salcianu 1.1.2.8                  System.out.println("The graphs are different");
186 salcianu 1.1.2.5              return false;
187 salcianu 1.1.2.5          }
188 salcianu 1.7              if(!tau.equals(pig2.tau)) {
189 salcianu 1.1.2.13             if(DEBUG2)
190 salcianu 1.1.2.8                  System.out.println("The tau's are different");
191 salcianu 1.1.2.5              return false;
192 salcianu 1.1.2.7          }
193 salcianu 1.1.2.42 
194 salcianu 1.1.2.42         if(PointerAnalysis.RECORD_ACTIONS)
195 salcianu 1.7                  if(!ar.equals(pig2.ar)) {
196 salcianu 1.1.2.42                 if(DEBUG2){
197 salcianu 1.1.2.42                     System.out.println("The ar's are different");
198 salcianu 1.1.2.42                     ar.show_evolution(pig2.ar);
199 salcianu 1.1.2.42                 }
200 salcianu 1.1.2.42                 return false;
201 salcianu 1.1.2.31             }
202 salcianu 1.1.2.26 
203 salcianu 1.1.2.26         if(!PointerAnalysis.IGNORE_EO)
204 salcianu 1.1.2.42             if(!eo.equals(pig2.eo)) {
205 salcianu 1.1.2.26                 if(DEBUG2)
206 salcianu 1.1.2.26                     System.out.println("The eo's are different");
207 salcianu 1.1.2.26                 return false;
208 salcianu 1.1.2.26             }
209 salcianu 1.1.2.26 
210 salcianu 1.1.2.5          return true;
211 salcianu 1.1.2.2      }
212 salcianu 1.1.2.2  
213 salcianu 1.10         /** Private constructor for <code>keepTheEssential</code>. */
214 salcianu 1.1.2.17     private ParIntGraph(PointsToGraph G, PAThreadMap tau, ActionRepository ar,
215 salcianu 1.1.2.42                         EdgeOrdering eo) {
216 salcianu 1.1.2.7          this.G   = G;
217 salcianu 1.1.2.7          this.tau = tau;
218 salcianu 1.1.2.7          this.ar  = ar;
219 salcianu 1.1.2.11         this.eo  = eo;
220 salcianu 1.1.2.1      }
221 salcianu 1.1.2.1  
222 salcianu 1.1.2.1      /** <code>clone</code> produces a copy of the <code>this</code>
223 salcianu 1.1.2.24         Parallel Interaction Graph. */
224 salcianu 1.1.2.42     public Object clone() {
225 salcianu 1.7              long b_time = 
226 salcianu 1.7                  PointerAnalysis.FINE_TIMING? System.currentTimeMillis() : 0;
227 salcianu 1.7      
228 salcianu 1.10             ParIntGraph clone = null;
229 salcianu 1.10     
230 salcianu 1.10             try {
231 salcianu 1.10                 clone     = (ParIntGraph) super.clone();
232 salcianu 1.10                 clone.G   = (PointsToGraph) G.clone();
233 salcianu 1.10                 clone.tau = (PAThreadMap) tau.clone();
234 salcianu 1.10                 clone.ar  = 
235 salcianu 1.10                     PointerAnalysis.RECORD_ACTIONS ?
236 salcianu 1.10                     (ActionRepository) ar.clone() : null;
237 salcianu 1.10                 clone.eo  =
238 salcianu 1.10                     PointerAnalysis.IGNORE_EO ? null : 
239 salcianu 1.10                     (EdgeOrdering) eo.clone();          
240 salcianu 1.10             }
241 salcianu 1.10             catch(CloneNotSupportedException e) {
242 salcianu 1.10                 assert false; // should never happen
243 salcianu 1.10             }
244 salcianu 1.7      
245 salcianu 1.7              if(PointerAnalysis.FINE_TIMING) {
246 salcianu 1.7                  long delta = System.currentTimeMillis() - b_time;
247 salcianu 1.7                  total_cloning_time += delta;
248 salcianu 1.7              }
249 salcianu 1.7      
250 salcianu 1.10             return clone;
251 salcianu 1.1.2.1      }
252 salcianu 1.1.2.3  
253 salcianu 1.7          static long total_cloning_time = 0;
254 salcianu 1.7          static long total_equals_time  = 0;
255 salcianu 1.7          static long total_join_time  = 0;
256 salcianu 1.7      
257 salcianu 1.7      
258 salcianu 1.6      
259 salcianu 1.7          String stats() {
260 salcianu 1.6              Set/*<PANode>*/ nodes = allNodes();
261 salcianu 1.6              int nb_param  = 0;
262 salcianu 1.6              int nb_inside = 0;
263 salcianu 1.6              int nb_load   = 0;
264 salcianu 1.7              int nb_compressable = 0;
265 salcianu 1.6              int nb_static = 0;
266 salcianu 1.6              int nb_return = 0;
267 salcianu 1.6              int nb_except = 0;
268 salcianu 1.7              int nb_other  = 0;
269 cananian 1.9              for(Object nodeO : nodes) {
270 cananian 1.9                  PANode node = (PANode) nodeO;
271 salcianu 1.6                  switch(node.type()) {
272 salcianu 1.6                  case PANode.PARAM:  nb_param++; break;
273 salcianu 1.7                  case PANode.INSIDE2:
274 salcianu 1.6                  case PANode.INSIDE: nb_inside++; break;
275 salcianu 1.7                  case PANode.LOAD:   nb_load++;   break;
276 salcianu 1.6                  case PANode.STATIC: nb_static++; break;
277 salcianu 1.6                  case PANode.RETURN: nb_return++; break;
278 salcianu 1.6                  case PANode.EXCEPT: nb_except++; break;
279 salcianu 1.7                  case PANode.LOST:
280 salcianu 1.7                  case PANode.NULL:   nb_other++; break;
281 salcianu 1.6                  default: // do nothing
282 salcianu 1.6                  }
283 salcianu 1.7                  if(compressable_node(node))
284 salcianu 1.7                      nb_compressable++;
285 salcianu 1.6              }
286 salcianu 1.7      
287 salcianu 1.7              StringBuffer buff = new StringBuffer();
288 salcianu 1.7              buff.append
289 salcianu 1.7                  (nodes.size() + " nodes " + 
290 salcianu 1.7                   "\t(P:" + nb_param  + ", I:" + nb_inside + 
291 salcianu 1.7                   ", L:" + nb_load   + ", S:" + nb_static + 
292 salcianu 1.7                   ", R:" + nb_return + ", E:" + nb_except + 
293 salcianu 1.7                   ", O:" + nb_other + "; " +
294 salcianu 1.7                   nb_compressable + ");");
295 salcianu 1.7      
296 salcianu 1.7              edge_visitor.reset();
297 salcianu 1.7              G.I.forAllEdges(edge_visitor);
298 salcianu 1.7              buff.append("\tv->n: " + edge_visitor.v2n_edges +
299 salcianu 1.7                          ";\tn->n: (" + edge_visitor.n2n_edges + " inside;  " );
300 salcianu 1.7      
301 salcianu 1.7              edge_visitor.reset();
302 salcianu 1.7              G.O.forAllEdges(edge_visitor);
303 salcianu 1.7              assert edge_visitor.v2n_edges == 0;
304 salcianu 1.7              buff.append(edge_visitor.n2n_edges + " outside)");
305 salcianu 1.7      
306 salcianu 1.7              return buff.toString();
307 salcianu 1.7          }
308 salcianu 1.7          private static class StatEdgeVisitor implements PAEdgeVisitor {
309 salcianu 1.7              int v2n_edges;
310 salcianu 1.7              int n2n_edges;
311 salcianu 1.7              void reset() { v2n_edges = 0; n2n_edges = 0; }
312 salcianu 1.7              public void visit(Temp v, PANode node) { v2n_edges++; }
313 salcianu 1.7              public void visit(PANode n1, String f, PANode n2) { n2n_edges++; }
314 salcianu 1.6          }
315 salcianu 1.7          private static final StatEdgeVisitor edge_visitor = new StatEdgeVisitor();
316 salcianu 1.6      
317 salcianu 1.1.2.3      
318 salcianu 1.1.2.24     /** Produces a <code>ParIntGraph</code> containing only the
319 salcianu 1.1.2.6          nodes that could be reached from the outside.
320 salcianu 1.1.2.6          (i.e. via parameters,
321 salcianu 1.1.2.6          class nodes, normally or exceptionally returned nodes or the
322 salcianu 1.1.2.6          started thread nodes) */
323 salcianu 1.7          public ParIntGraph keepTheEssential(PANode[] params, boolean is_main) {
324 salcianu 1.7              return keepTheEssential(params, is_main, null);
325 salcianu 1.7          }
326 salcianu 1.7      
327 salcianu 1.7      
328 salcianu 1.7          public ParIntGraph keepTheEssential
329 salcianu 1.8              (PANode[] params, boolean is_main, Set/*<PANode>*/ lost_nodes) {
330 salcianu 1.7      
331 salcianu 1.7              Relation new_mu = null;
332 salcianu 1.7              if(PointerAnalysis.MEGA_DEBUG)
333 salcianu 1.7                  System.out.println("Before kTE graph is " + this);
334 salcianu 1.7      
335 salcianu 1.1.2.26         ParIntGraph pig2 = retain_essential(params, is_main);
336 salcianu 1.1.2.26 
337 salcianu 1.7              if(AGGRESSIVE_SHRINKING) {
338 salcianu 1.1.2.36             pig2.shrinking();
339 salcianu 1.6                  pig2 = pig2.retain_essential(params, is_main);
340 salcianu 1.1.2.26         }
341 salcianu 1.1.2.26 
342 salcianu 1.8              if(lost_nodes != null)
343 salcianu 1.8                  pig2 = pig2.compressLostNodes(lost_nodes);
344 salcianu 1.6      
345 salcianu 1.1.2.26         return pig2;
346 salcianu 1.1.2.26     }
347 salcianu 1.1.2.26 
348 salcianu 1.7      
349 salcianu 1.8          public ParIntGraph compressLostNodes(Set/*<PANode>*/ lost) {
350 salcianu 1.7              System.out.println("Before cmprss: " + stats());
351 salcianu 1.7      
352 salcianu 1.7              // don't do any optimization in this case
353 salcianu 1.7              if(PointerAnalysis.RECORD_ACTIONS || !PointerAnalysis.IGNORE_EO)
354 salcianu 1.7                  return this;
355 salcianu 1.7      
356 salcianu 1.8              Relation compression_mu = get_compression_map(lost);
357 salcianu 1.7      
358 salcianu 1.7              if(PointerAnalysis.MEGA_DEBUG)
359 salcianu 1.7                  System.out.println("Compress relation mu = " + compression_mu);
360 salcianu 1.7      
361 salcianu 1.7              ParIntGraph pig2 = new ParIntGraph();
362 salcianu 1.7              pig2.insertAllButArEo
363 salcianu 1.7                  (this, compression_mu, true, Collections.EMPTY_SET, null, true);
364 salcianu 1.7              
365 salcianu 1.7              return pig2;
366 salcianu 1.7          }
367 salcianu 1.7      
368 salcianu 1.7          
369 salcianu 1.10         // returns null if compresion is useless (i.e., no node is mapped
370 salcianu 1.10         // to LOST except LOST itself).
371 salcianu 1.8          private Relation get_compression_map(final Set/*<PANode>*/ lost) {
372 salcianu 1.8              // extend "lost" with newly discovered lost nodes
373 cananian 1.9              for(Object nodeO : allNodes()) {
374 cananian 1.9                  PANode node = (PANode) nodeO;
375 salcianu 1.7                  if(compressable_node(node))
376 salcianu 1.8                      lost.add(node);
377 salcianu 1.8              }
378 salcianu 1.8              // build the compression map mu
379 salcianu 1.8              Relation mu = new LightRelation();
380 cananian 1.9              for(Object nodeO : allNodes()) {
381 cananian 1.9                  PANode node = (PANode) nodeO;
382 salcianu 1.8                  if(lost.contains(node))
383 salcianu 1.7                      mu.add(node, NodeRepository.LOST_SUMMARY);
384 salcianu 1.7                  else
385 salcianu 1.7                      mu.add(node, node);
386 salcianu 1.7              }
387 salcianu 1.8              return mu;
388 salcianu 1.7          }
389 salcianu 1.7      
390 salcianu 1.7          // checks whether "node" escapes globally (i.e., in an unanalyzed
391 salcianu 1.7          // method or in a static field).
392 salcianu 1.7          private boolean compressable_node(PANode node) {
393 salcianu 1.7              return
394 salcianu 1.7                  ((node.type == PANode.INSIDE) || 
395 salcianu 1.7                   (node.type == PANode.INSIDE2) ||
396 salcianu 1.7                   (node.type == PANode.LOAD)) &&
397 salcianu 1.7                  G.e.hasEscaped(node) && !G.e.escapesOnlyInCaller(node);
398 salcianu 1.7          }
399 salcianu 1.7      
400 salcianu 1.1.2.28     private final ParIntGraph retain_essential(PANode[] params,
401 salcianu 1.1.2.28                                                boolean is_main){
402 salcianu 1.1.2.3          HashSet remaining_nodes = new HashSet();
403 salcianu 1.1.2.6          remaining_nodes.addAll(tau.activeThreadSet());
404 salcianu 1.1.2.12 
405 salcianu 1.1.2.3          PointsToGraph _G = 
406 salcianu 1.1.2.3              G.keepTheEssential(params, remaining_nodes, is_main);
407 salcianu 1.1.2.12 
408 salcianu 1.1.2.12         PAThreadMap _tau = (PAThreadMap) tau.clone();
409 salcianu 1.1.2.12 
410 salcianu 1.1.2.42         ActionRepository _ar =
411 salcianu 1.1.2.42             PointerAnalysis.RECORD_ACTIONS ?
412 salcianu 1.1.2.42             ar.keepTheEssential(remaining_nodes) : null;
413 salcianu 1.1.2.12 
414 salcianu 1.1.2.26         EdgeOrdering _eo = 
415 salcianu 1.1.2.26             PointerAnalysis.IGNORE_EO ? null : 
416 salcianu 1.1.2.26             eo.keepTheEssential(remaining_nodes);
417 salcianu 1.1.2.26 
418 salcianu 1.1.2.42         return new ParIntGraph(_G, _tau, _ar, _eo);
419 salcianu 1.1.2.25     }
420 salcianu 1.1.2.25 
421 salcianu 1.1.2.38 
422 salcianu 1.1.2.38     private ParIntGraph external_view(PANode[] params) {
423 salcianu 1.1.2.39         return copy_from_roots(Collections.EMPTY_SET,
424 salcianu 1.1.2.39                                get_external_view_roots(params));
425 salcianu 1.1.2.38     }
426 salcianu 1.1.2.38 
427 salcianu 1.1.2.38 
428 salcianu 1.1.2.39     // Constructs a new ParIntGraph that contains all the elements of this
429 salcianu 1.1.2.39     // one that are reachable from the Temps vars and the PANodes roots.
430 salcianu 1.1.2.39     private ParIntGraph copy_from_roots(Set vars, Set roots) {
431 salcianu 1.1.2.38         Set remaining_nodes = new HashSet();
432 salcianu 1.1.2.38 
433 salcianu 1.1.2.38         PointsToGraph _G =
434 salcianu 1.1.2.39             G.copy_from_roots(vars, roots, remaining_nodes);
435 salcianu 1.1.2.38 
436 salcianu 1.1.2.38         PAThreadMap _tau = (PAThreadMap) tau.clone();
437 salcianu 1.1.2.38 
438 salcianu 1.1.2.42         ActionRepository _ar =
439 salcianu 1.1.2.42             PointerAnalysis.RECORD_ACTIONS ? 
440 salcianu 1.1.2.42             ar.keepTheEssential(remaining_nodes) : null;
441 salcianu 1.1.2.38 
442 salcianu 1.1.2.38         EdgeOrdering _eo = 
443 salcianu 1.1.2.38             PointerAnalysis.IGNORE_EO ? null : 
444 salcianu 1.1.2.38             eo.keepTheEssential(remaining_nodes);
445 salcianu 1.1.2.38 
446 salcianu 1.1.2.42         return new ParIntGraph(_G, _tau, _ar, _eo);
447 salcianu 1.1.2.38     }
448 salcianu 1.1.2.38 
449 salcianu 1.1.2.38 
450 salcianu 1.1.2.39     // Returns the set of the nodes that can be directly accessed from
451 salcianu 1.1.2.39     // the outside. This are basically the points through which an external
452 salcianu 1.1.2.39     // entity can "look" into the parallel interaction graph.
453 salcianu 1.1.2.39     private Set get_external_view_roots(PANode[] params) {
454 salcianu 1.1.2.38         Set roots = new HashSet();
455 salcianu 1.1.2.38         // 1. param nodes +
456 salcianu 1.1.2.38         for(int i = 0; i < params.length; i++)
457 salcianu 1.1.2.38             roots.add(params[i]);
458 salcianu 1.1.2.38         // 2. returned nodes +
459 salcianu 1.1.2.38         roots.addAll(G.r);
460 salcianu 1.1.2.38         // 3. excp. returned nodes +
461 salcianu 1.1.2.38         roots.addAll(G.excp);
462 salcianu 1.1.2.38         // 4. active thread nodes +
463 salcianu 1.1.2.38         roots.addAll(tau.activeThreadSet());
464 salcianu 1.1.2.39         // 5. static nodes
465 cananian 1.9              for(Object nodeO : allNodes()) {
466 cananian 1.9                  PANode node = (PANode) nodeO;
467 salcianu 1.1.2.38             if(node.type == PANode.STATIC)
468 salcianu 1.1.2.38                 roots.add(node);
469 salcianu 1.1.2.38         }
470 salcianu 1.1.2.39         return roots;
471 salcianu 1.1.2.39     }
472 salcianu 1.1.2.38 
473 salcianu 1.1.2.38 
474 salcianu 1.1.2.39     ParIntGraph intra_proc_trimming(PANode[] params) {
475 salcianu 1.1.2.39         Set roots = get_external_view_roots(params);
476 salcianu 1.1.2.39 
477 salcianu 1.1.2.39         // TODO: in the future, only the live vars should be put here
478 salcianu 1.1.2.39         Set remaining_vars = new HashSet(G.I.allVariables());
479 salcianu 1.1.2.39         ParIntGraph newpig = copy_from_roots(remaining_vars,roots);
480 salcianu 1.1.2.39 
481 salcianu 1.1.2.38         System.out.println("ipt: " + this.allNodes().size() + " -> " +
482 salcianu 1.1.2.39                            newpig.allNodes().size() + " delta=" +
483 salcianu 1.1.2.39                            (this.allNodes().size() -
484 salcianu 1.1.2.42                             newpig.allNodes().size()));
485 salcianu 1.1.2.42         /* + 
486 salcianu 1.1.2.39                            " r = " + G.r + " " + newpig.G.r +  
487 salcianu 1.1.2.39                            " excp = " + G.excp + " " + newpig.G.excp);
488 salcianu 1.1.2.39         */
489 salcianu 1.1.2.38 
490 salcianu 1.1.2.38         return newpig;
491 salcianu 1.1.2.38     }
492 salcianu 1.1.2.38     
493 salcianu 1.1.2.38 
494 salcianu 1.1.2.38     private void add_pointed_by_vars(Set roots, PAEdgeSet E) {
495 cananian 1.9              for(Object vO : E.allVariables()) {
496 cananian 1.9                  Temp v = (Temp) vO;
497 salcianu 1.1.2.38             roots.addAll(E.pointedNodes(v));
498 salcianu 1.1.2.38         }
499 salcianu 1.1.2.38     }
500 salcianu 1.1.2.36 
501 salcianu 1.1.2.36     /** Aggressive shrinking: get rid of some unnecessary information.
502 salcianu 1.1.2.36         TODO: write some better comments. */
503 salcianu 1.1.2.36     private void shrinking() {
504 salcianu 1.1.2.36         final Set nodes = new HashSet(allNodes());
505 salcianu 1.1.2.36         final Set useful_nodes = new HashSet();
506 salcianu 1.1.2.36         final LinkedList Q = new LinkedList();
507 salcianu 1.1.2.25         
508 salcianu 1.6              //System.out.println("shrink0: nodes = " + nodes);
509 salcianu 1.6      
510 salcianu 1.1.2.36         init_queue(Q, useful_nodes, nodes);
511 salcianu 1.6      
512 salcianu 1.6              //System.out.println("shrink1: useful_nodes = " + useful_nodes);
513 salcianu 1.6      
514 salcianu 1.1.2.36         final Relation pred_rel = G.O.getPrecedenceRelation();
515 salcianu 1.1.2.36 
516 salcianu 1.1.2.36         while(!Q.isEmpty()) {
517 salcianu 1.1.2.36             PANode node = (PANode) Q.removeFirst();
518 salcianu 1.1.2.36             
519 cananian 1.9                  for(Object predO : pred_rel.getValues(node)) {
520 cananian 1.9                      PANode pred = (PANode) predO;
521 salcianu 1.1.2.36                 if(useful_nodes.add(pred))
522 salcianu 1.1.2.36                     Q.addLast(pred);
523 salcianu 1.1.2.25             }
524 salcianu 1.1.2.25         }
525 salcianu 1.1.2.36 
526 salcianu 1.6              //System.out.println("shrink2: useful_nodes = " + useful_nodes);
527 salcianu 1.6      
528 salcianu 1.6              if(MEASURE_AS) {
529 salcianu 1.6                  System.out.println
530 salcianu 1.6                      ("\nas: " + nodes.size() + " -> " +
531 salcianu 1.6                       useful_nodes.size() + " delta=" +
532 salcianu 1.6                       (nodes.size() - useful_nodes.size()));
533 salcianu 1.6              }
534 salcianu 1.1.2.44         
535 salcianu 1.1.2.36         // unuseful_nodes = nodes - useful_nodes
536 salcianu 1.1.2.36         nodes.removeAll(useful_nodes);
537 salcianu 1.1.2.36 
538 salcianu 1.6              //System.out.println("shrink3: nodes to remove = " + nodes);
539 salcianu 1.6      
540 salcianu 1.1.2.36         remove(nodes);
541 salcianu 1.1.2.3      }
542 salcianu 1.1.2.25     
543 salcianu 1.1.2.25 
544 salcianu 1.1.2.36     private void init_queue(final LinkedList Q, final Set useful_nodes,
545 salcianu 1.1.2.36                             final Set nodes) {
546 cananian 1.9              for(Object nodeO : nodes) {
547 cananian 1.9                  PANode node = (PANode) nodeO;
548 salcianu 1.1.2.36             if(relevant_node(node))
549 salcianu 1.1.2.36                 if(useful_nodes.add(node))
550 salcianu 1.1.2.36                     Q.addLast(node);
551 salcianu 1.1.2.36         }
552 salcianu 1.1.2.36         G.I.forAllEdges(new PAEdgeVisitor(){
553 salcianu 1.1.2.36                 public void visit(Temp var, PANode node) {}
554 salcianu 1.1.2.36                 public void visit(PANode node1, String f, PANode node2) {
555 salcianu 1.1.2.36                     if(useful_nodes.add(node1))
556 salcianu 1.1.2.36                         Q.addLast(node1);
557 salcianu 1.1.2.36                     if(useful_nodes.add(node2))
558 salcianu 1.1.2.36                         Q.addLast(node2);
559 salcianu 1.1.2.36                 }
560 salcianu 1.1.2.36             });
561 salcianu 1.1.2.36     }
562 salcianu 1.1.2.25 
563 salcianu 1.1.2.25 
564 salcianu 1.1.2.36     private boolean relevant_node(PANode node) {
565 salcianu 1.6              switch(node.type()) {
566 salcianu 1.1.2.36         case PANode.INSIDE:
567 salcianu 1.1.2.36         case PANode.PARAM:
568 salcianu 1.1.2.36         case PANode.STATIC:
569 salcianu 1.6              case PANode.CONST:
570 salcianu 1.6              case PANode.NULL:
571 salcianu 1.1.2.36             return true;
572 salcianu 1.1.2.36         case PANode.LOAD:
573 salcianu 1.6                  // see if we do something interesting with the LOAD node
574 salcianu 1.6                  return
575 salcianu 1.6                      !G.e.escapesOnlyInCaller(node) ||
576 salcianu 1.6                      (PointerAnalysis.RECORD_ACTIONS && ar.isSyncOn(node)) ||
577 salcianu 1.6                      G.r.contains(node) || G.excp.contains(node);
578 salcianu 1.6              default: // should never happen
579 salcianu 1.1.2.36             if(G.willEscape(node))
580 salcianu 1.1.2.36                 return true;
581 salcianu 1.1.2.25         }
582 salcianu 1.1.2.25 
583 salcianu 1.1.2.25         return false;
584 salcianu 1.1.2.25     }
585 salcianu 1.1.2.36     
586 salcianu 1.1.2.3  
587 salcianu 1.1.2.12     // Visits all the nodes from set_nodes.
588 salcianu 1.1.2.12     private void forSet(Set set_nodes, PANodeVisitor visitor){
589 salcianu 1.1.2.12         Iterator it_nodes = set_nodes.iterator();
590 salcianu 1.1.2.12         while(it_nodes.hasNext())
591 salcianu 1.1.2.12             visitor.visit((PANode) it_nodes.next());
592 salcianu 1.1.2.12     }
593 salcianu 1.1.2.12 
594 salcianu 1.1.2.12     /** Visits all the nodes that appear in <code>this</code> graph. */
595 salcianu 1.1.2.46     public void forAllNodes(final PANodeVisitor visitor) {
596 salcianu 1.1.2.12         G.O.forAllNodes(visitor);
597 salcianu 1.1.2.12         G.I.forAllNodes(visitor);
598 salcianu 1.1.2.12         forSet(G.r,visitor);
599 salcianu 1.1.2.12         forSet(G.excp,visitor);
600 salcianu 1.1.2.12         forSet(G.e.escapedNodes(),visitor);
601 salcianu 1.1.2.12         forSet(tau.activeThreadSet(),visitor);
602 salcianu 1.1.2.12 
603 salcianu 1.1.2.42         if(PointerAnalysis.RECORD_ACTIONS) {
604 salcianu 1.1.2.42             ar.forAllActions(new ActionVisitor(){
605 salcianu 1.1.2.42                     public void visit_ld(PALoad load){
606 salcianu 1.1.2.42                         visitor.visit(load.n1);
607 salcianu 1.1.2.42                         visitor.visit(load.n2);
608 salcianu 1.1.2.42                         visitor.visit(load.nt);
609 salcianu 1.1.2.42                     }
610 salcianu 1.1.2.42                     public void visit_sync(PASync sync){
611 salcianu 1.1.2.42                         visitor.visit(sync.n);
612 salcianu 1.1.2.42                         visitor.visit(sync.nt);
613 salcianu 1.1.2.42                     }
614 salcianu 1.1.2.42                 });
615 salcianu 1.1.2.42             
616 salcianu 1.1.2.42             ar.forAllParActions(new ParActionVisitor() {
617 salcianu 1.1.2.42                     public void visit_par_ld(PALoad load, PANode nt2) {
618 salcianu 1.1.2.42                         visitor.visit(nt2);
619 salcianu 1.1.2.42                     }
620 salcianu 1.1.2.42                     public void visit_par_sync(PASync sync, PANode nt2) {
621 salcianu 1.1.2.42                         visitor.visit(nt2);
622 salcianu 1.1.2.42                     }
623 salcianu 1.1.2.42                 });
624 salcianu 1.1.2.42         }
625 salcianu 1.1.2.33         // the edges appearing in the edge ordering relation are also
626 salcianu 1.1.2.12         // present into G.O and G.I and so, they have been already visited
627 salcianu 1.1.2.12     }
628 salcianu 1.1.2.14 
629 salcianu 1.7          /** Returns the set of all nodes that appear in <code>this</code>
630 salcianu 1.1.2.39         parallel interaction graph.<br> */
631 salcianu 1.7          public Set/*<PANode>*/ allNodes() {
632 salcianu 1.1.2.39         final Set nodes = new HashSet();
633 salcianu 1.1.2.39         forAllNodes(new PANodeVisitor(){
634 salcianu 1.1.2.39                 public void visit(PANode node){
635 salcianu 1.1.2.39                     nodes.add(node);
636 salcianu 1.1.2.39                 }
637 salcianu 1.1.2.39             });
638 salcianu 1.1.2.39         nodes.remove(ActionRepository.THIS_THREAD);
639 salcianu 1.1.2.39         return nodes;
640 salcianu 1.1.2.14     }
641 salcianu 1.1.2.14 
642 salcianu 1.1.2.18     /* Specialize <code>this</code> <code>ParIntGraph</code> for the call
643 salcianu 1.1.2.18        site <code>q</code>. */
644 salcianu 1.1.2.23     final ParIntGraph csSpecialize(final CALL call){
645 salcianu 1.1.2.32         /* contains mappings old node -> specialized node; each unmapped
646 salcianu 1.1.2.23            node is supposed to be mapped to itself. */
647 salcianu 1.1.2.20         final Map map = new HashMap();
648 cananian 1.9              for(Object nodeO : allNodes()){
649 cananian 1.9                  PANode node = (PANode) nodeO;
650 salcianu 1.1.2.16             if(node.type == PANode.INSIDE)
651 salcianu 1.1.2.23                 map.put(node, node.csSpecialize(call));
652 salcianu 1.1.2.18         } 
653 salcianu 1.1.2.23 
654 salcianu 1.1.2.42         ActionRepository _ar = PointerAnalysis.RECORD_ACTIONS ?
655 salcianu 1.1.2.42             ar.csSpecialize(map, call) : null;
656 salcianu 1.1.2.33 
657 salcianu 1.1.2.42         EdgeOrdering _eo = PointerAnalysis.IGNORE_EO ?
658 salcianu 1.1.2.42             null : eo.specialize(map);
659 salcianu 1.1.2.33 
660 salcianu 1.1.2.42         ParIntGraph new_graph = 
661 salcianu 1.1.2.42             new ParIntGraph(G.specialize(map), tau.specialize(map), _ar, _eo);
662 salcianu 1.1.2.33 
663 salcianu 1.1.2.33         return new_graph;
664 salcianu 1.1.2.14     }
665 salcianu 1.1.2.14 
666 salcianu 1.1.2.23     /* Specializes <code>this</code> <code>ActionRepository</code> for the
667 salcianu 1.1.2.24        thread whose run method is <code>run</code>. */
668 salcianu 1.1.2.23     final ParIntGraph tSpecialize(final MetaMethod run){
669 salcianu 1.1.2.24         // contains mappings old node -> speciaized node; each unmapped
670 salcianu 1.1.2.24         // node is supposed to be mapped to itself.
671 salcianu 1.1.2.20         final Map map = new HashMap();
672 cananian 1.9              for(Object nodeO : allNodes()){
673 cananian 1.9                  PANode node = (PANode) nodeO;
674 salcianu 1.1.2.24             if((node.type != PANode.PARAM) && (node.type != PANode.STATIC)){
675 salcianu 1.1.2.23                 PANode node2 = node.tSpecialize(run);
676 salcianu 1.1.2.20                 map.put(node, node2);
677 salcianu 1.1.2.20             }
678 salcianu 1.1.2.20         }
679 salcianu 1.1.2.23         
680 salcianu 1.1.2.47         ActionRepository _ar = PointerAnalysis.RECORD_ACTIONS ?
681 salcianu 1.1.2.47             ar.tSpecialize(map, run) : null;
682 salcianu 1.1.2.47 
683 salcianu 1.1.2.47         EdgeOrdering _eo = PointerAnalysis.IGNORE_EO ?
684 salcianu 1.1.2.47             null : eo.specialize(map);
685 salcianu 1.1.2.47 
686 salcianu 1.1.2.23         return
687 salcianu 1.1.2.47             new ParIntGraph(G.specialize(map), tau.specialize(map), _ar, _eo);
688 salcianu 1.1.2.20     }
689 salcianu 1.1.2.20 
690 salcianu 1.1.2.20     // weak thread specialization
691 salcianu 1.1.2.23     final ParIntGraph wtSpecialize(final MetaMethod run){
692 salcianu 1.1.2.24         // contains mappings old node -> speciaized node; each unmapped
693 salcianu 1.1.2.24         // node is supposed to be mapped to itself.
694 salcianu 1.1.2.23         final Map map = new HashMap();
695 cananian 1.9              for(Object nodeO : allNodes()){
696 cananian 1.9                  PANode node = (PANode) nodeO;
697 salcianu 1.1.2.24             if((node.type != PANode.PARAM) && (node.type != PANode.STATIC)){
698 salcianu 1.1.2.20                 PANode node2 = node.wtSpecialize();
699 salcianu 1.1.2.20                 map.put(node, node2);
700 salcianu 1.1.2.20             }
701 salcianu 1.1.2.20         }
702 salcianu 1.1.2.42 
703 salcianu 1.1.2.42         ActionRepository _ar = PointerAnalysis.RECORD_ACTIONS ?
704 salcianu 1.1.2.42             ar.tSpecialize(map, run) : null;
705 salcianu 1.1.2.42 
706 salcianu 1.1.2.42         EdgeOrdering _eo = PointerAnalysis.IGNORE_EO ?
707 salcianu 1.1.2.42             null : eo.specialize(map);
708 salcianu 1.1.2.23         
709 salcianu 1.1.2.18         return
710 salcianu 1.1.2.42             new ParIntGraph(G.specialize(map), tau.specialize(map), _ar, _eo);
711 salcianu 1.1.2.18     }
712 salcianu 1.1.2.23 
713 salcianu 1.1.2.12 
714 salcianu 1.1.2.12     /** Removes the nodes from <code>nodes</code> from <code>this</code>
715 salcianu 1.1.2.12         graph. */
716 salcianu 1.1.2.12     public void remove(Set nodes){
717 salcianu 1.1.2.12         G.remove(nodes);
718 salcianu 1.1.2.12         tau.remove(nodes);
719 salcianu 1.1.2.42         
720 salcianu 1.1.2.42         if(PointerAnalysis.RECORD_ACTIONS)
721 salcianu 1.1.2.42             ar.removeNodes(nodes);
722 salcianu 1.1.2.26 
723 salcianu 1.1.2.26         if(!PointerAnalysis.IGNORE_EO)
724 salcianu 1.1.2.26             eo.removeNodes(nodes);
725 salcianu 1.1.2.12     }
726 salcianu 1.1.2.12 
727 salcianu 1.1.2.12     /** Simplify <code>this</code> parallel interaction graph by removing the
728 salcianu 1.1.2.12         loads that don't escape anywhere (and hence, don't represent any
729 salcianu 1.1.2.12         object). In addition, the <code>&lt;&lt;n1,f&gt;,n2&gt;</code>
730 salcianu 1.1.2.12         ouside (load) edges where <code>n1</code> is an unescaped node are
731 salcianu 1.1.2.48         removed too. */
732 salcianu 1.1.2.12     public void removeEmptyLoads(){
733 salcianu 1.1.2.12         final Set empty_loads = new HashSet();
734 salcianu 1.1.2.12         final Set fake_outside_edges = new HashSet();
735 salcianu 1.1.2.12         
736 cananian 1.9              for(Object nodeO : allNodes()) {
737 cananian 1.9                  PANode node = (PANode) nodeO;
738 salcianu 1.7                  if((node.type == PANode.LOAD) && !G.e.hasEscaped(node))
739 salcianu 1.7                      empty_loads.add(node);
740 salcianu 1.7              }
741 salcianu 1.7      
742 salcianu 1.1.2.12         G.O.forAllEdges(new PAEdgeVisitor(){
743 salcianu 1.1.2.12                 public void visit(Temp var, PANode node){}
744 salcianu 1.1.2.12                 public void visit(PANode node1, String f, PANode node2){
745 salcianu 1.1.2.12                     if(!G.e.hasEscaped(node1))
746 salcianu 1.1.2.12                         fake_outside_edges.add(new PAEdge(node1,f,node2));
747 salcianu 1.1.2.12                 }
748 salcianu 1.1.2.12             });
749 salcianu 1.7              
750 salcianu 1.7              if(DEBUG) {
751 salcianu 1.1.2.12             System.out.println("Empty loads:" + empty_loads);
752 salcianu 1.1.2.12             System.out.println("Fake outside edges: " + fake_outside_edges);
753 salcianu 1.1.2.12         }
754 salcianu 1.1.2.12 
755 salcianu 1.1.2.12         remove(empty_loads);
756 salcianu 1.1.2.12 
757 cananian 1.9              for (Object edgeO : fake_outside_edges){
758 cananian 1.9                  PAEdge edge = (PAEdge) edgeO;
759 salcianu 1.1.2.12             G.O.removeEdge(edge.n1,edge.f,edge.n2);
760 salcianu 1.1.2.12         }
761 salcianu 1.1.2.12 
762 salcianu 1.1.2.42         if(PointerAnalysis.RECORD_ACTIONS)
763 salcianu 1.1.2.42             ar.removeEdges(fake_outside_edges);
764 salcianu 1.1.2.26 
765 salcianu 1.1.2.26         if(!PointerAnalysis.IGNORE_EO)
766 salcianu 1.1.2.26             eo.removeEdges(fake_outside_edges);
767 salcianu 1.1.2.12     }
768 salcianu 1.1.2.1  
769 salcianu 1.1.2.45     public static boolean SHOW_ACTIONS = false;
770 salcianu 1.1.2.45 
771 salcianu 1.1.2.8      /** Pretty-print function for debug purposes. 
772 salcianu 1.1.2.8          Two equal <code>ParIntGraph</code>s are guaranteed to have the same
773 salcianu 1.1.2.8          string representation. */
774 salcianu 1.1.2.1      public String toString(){
775 salcianu 1.1.2.17         return
776 salcianu 1.1.2.42             "\nParIntGraph{\n" + G + " " + tau +
777 salcianu 1.1.2.45             (PointerAnalysis.RECORD_ACTIONS && SHOW_ACTIONS ? 
778 salcianu 1.1.2.45              ar.toString() : "") + 
779 salcianu 1.1.2.44             (PointerAnalysis.IGNORE_EO ? "" : eo.toString())  + 
780 salcianu 1.1.2.26             "}";
781 salcianu 1.1.2.17     }
782 salcianu 1.1.2.22 
783 salcianu 1.1.2.22     /** Checks whether two <code>ParIntGraph</code>s are equal or not. In
784 salcianu 1.1.2.22         addition to the <code>equals</code> method, this handles the 
785 salcianu 1.1.2.22         comparisom of <code>null</code> objects. */
786 salcianu 1.1.2.22     public static boolean identical(ParIntGraph pig1, ParIntGraph pig2){
787 salcianu 1.1.2.22         if((pig1 == null) || (pig2 == null))
788 salcianu 1.1.2.22             return (pig1 == pig2);
789 salcianu 1.1.2.22         return pig1.equals(pig2);
790 salcianu 1.1.2.22     }
791 cananian 1.2      }