1 salcianu 1.1.2.1  // PANode.java, created Sun Jan  9 16:24:57 2000 by salcianu
  2 cananian 1.1.2.28 // Copyright (C) 2000 Alexandru SALCIANU <salcianu@retezat.lcs.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.8  import java.util.Set;
  7 salcianu 1.1.2.9  import java.util.HashSet;
  8 salcianu 1.1.2.9  import java.util.Iterator;
  9 salcianu 1.1.2.9  import java.util.Map;
 10 salcianu 1.1.2.8  import java.util.Collections;
 11 salcianu 1.1.2.8  
 12 salcianu 1.1.2.7  import harpoon.Util.Util;
 13 salcianu 1.1.2.7  import harpoon.IR.Quads.CALL;
 14 salcianu 1.1.2.7  
 15 salcianu 1.1.2.10 import harpoon.Analysis.MetaMethods.MetaMethod;
 16 salcianu 1.1.2.23 import harpoon.Analysis.MetaMethods.GenType;
 17 salcianu 1.1.2.13 import harpoon.Util.DataStructs.LightMap;
 18 salcianu 1.1.2.7  
 19 salcianu 1.1.2.1  /**
 20 salcianu 1.1.2.1   * <code>PANode</code> class models a node for the Pointer Analysis
 21 salcianu 1.1.2.1   * algorithm.
 22 salcianu 1.1.2.1   * 
 23 cananian 1.1.2.28  * @author  Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
 24 salcianu 1.7       * @version $Id: PANode.java,v 1.7 2003/06/04 18:44:32 salcianu Exp $
 25 salcianu 1.1.2.1   */
 26 salcianu 1.1.2.26 final public class PANode implements java.io.Serializable {
 27 salcianu 1.1.2.10     // activates some safety tests
 28 salcianu 1.1.2.10     private static final boolean CAUTION = true;
 29 salcianu 1.1.2.10 
 30 salcianu 1.1.2.10     /** Possible type: Inside node */
 31 salcianu 1.1.2.1      public static final int INSIDE          = 1;
 32 salcianu 1.1.2.10     /** Possible type: Load node */
 33 salcianu 1.5          public static final int LOAD            = 2;
 34 salcianu 1.1.2.10     /** Possible type: Parameter node */
 35 salcianu 1.5          public static final int PARAM           = 3;
 36 salcianu 1.1.2.10     /** Possible type: Return node. Nodes of this type are used to represent
 37 salcianu 1.1.2.10         the objects normally (i.e. not through a <code>throw</code>)
 38 salcianu 1.1.2.10         returned by an unanalyzed method. */
 39 salcianu 1.5          public static final int RETURN          = 4;
 40 salcianu 1.1.2.10     /** Possible type: Exception node. Nodes of this type are used to
 41 salcianu 1.1.2.10         represent the objects returned as exceptions from an unalyzed
 42 salcianu 1.1.2.10         method. */
 43 salcianu 1.5          public static final int EXCEPT          = 5;
 44 salcianu 1.1.2.10     /** Possible type: Static node. 
 45 salcianu 1.1.2.10         The class nodes from the original algorithm have been renamed
 46 salcianu 1.1.2.10         STATIC now (just for confusion :-)) */
 47 salcianu 1.5          public static final int STATIC          = 6;
 48 salcianu 1.1.2.1  
 49 salcianu 1.5          /** Possible type: null pointers. */
 50 salcianu 1.5          public static final int NULL            = 7;
 51 salcianu 1.5      
 52 salcianu 1.5          /** Possible type: constant objects (e.g., Strings) */
 53 salcianu 1.5          public static final int CONST           = 8;
 54 salcianu 1.1.2.1  
 55 salcianu 1.7          /** Possible type: lost objects (i.e., objects reachable from
 56 salcianu 1.7              unanalyzed parts of the program). */
 57 salcianu 1.7          public static final int LOST            = 9;
 58 salcianu 1.7      
 59 salcianu 1.7          /** Possible type: node returned by java.lang.Object.clone */
 60 salcianu 1.7          public static final int INSIDE2         = 10;
 61 salcianu 1.7      
 62 salcianu 1.1.2.1      /** The type of the node */
 63 salcianu 1.1.2.23     public int type;
 64 salcianu 1.1.2.1  
 65 salcianu 1.1.2.10     /** <code>count</code> is used to generate unique IDs
 66 salcianu 1.1.2.10         for debug purposes. */
 67 salcianu 1.1.2.8      static int count = 0;
 68 salcianu 1.1.2.1      /** Holds the unique ID */
 69 salcianu 1.1.2.20     /////private 
 70 salcianu 1.1.2.23     int number;
 71 salcianu 1.1.2.1  
 72 salcianu 1.1.2.12     // the depth of the call chain associated with this node
 73 salcianu 1.1.2.10     private int call_chain_depth = 0;
 74 salcianu 1.1.2.10     // call context sensitivity: the mapping CALL -> specialized node
 75 salcianu 1.1.2.27     private LightMap cs_specs = null;
 76 salcianu 1.1.2.12     // the parent of this PANode on the CALL specialization branch
 77 salcianu 1.1.2.12     private PANode cs_parent = null;
 78 salcianu 1.1.2.12     // the CALL site that specialized cs_parent into this node
 79 salcianu 1.1.2.12     private CALL call_site = null;
 80 salcianu 1.1.2.12 
 81 salcianu 1.1.2.17     // when trying to specialize this node for more than
 82 salcianu 1.1.2.17     // PointerAnalysis.MAX_SPEC_DEPTH-1 times, this node is returned
 83 salcianu 1.1.2.17     // (it is created the first time); basically, since we cannot make
 84 salcianu 1.1.2.17     // the difference between a node of depth MAX_SPEC_DEPTH and a node
 85 salcianu 1.1.2.17     // with some bigger call depth, all we need to know is that we have a node
 86 salcianu 1.1.2.17     // for which we canot infer where it was created.
 87 salcianu 1.1.2.17     private PANode bottom = null;
 88 salcianu 1.1.2.17 
 89 salcianu 1.1.2.12     // full thread sensitivity: the mapping MetaMethod -> specialized node
 90 salcianu 1.1.2.27     private LightMap ts_specs = null;
 91 salcianu 1.1.2.10     // the weak thread specialization of this node (if any)
 92 salcianu 1.1.2.10     private PANode wtspec = null;
 93 salcianu 1.1.2.12     // the parent of this PANode on the thread specialization branch
 94 salcianu 1.1.2.12     private PANode ts_parent = null;
 95 salcianu 1.1.2.12     // the run MetaMethod site that specialized cs_parent into this node
 96 salcianu 1.1.2.12     private MetaMethod run_mmethod = null;
 97 salcianu 1.1.2.10 
 98 salcianu 1.1.2.23     // the type of the objects represented by this node: it's either an
 99 salcianu 1.1.2.23     // exact type (ie <hclass, GenType.MONO>) or a type cone
100 salcianu 1.1.2.23     // (ie <hclass, GenType.POLY>).
101 salcianu 1.1.2.23     private GenType[] node_class = null;
102 salcianu 1.1.2.23 
103 salcianu 1.1.2.23     /** Creates a <code>PANode</code> of type <code>type</code>.
104 salcianu 1.1.2.10         <code>type</code> must be one of <code>PANode.INSIDE</code>,
105 salcianu 1.1.2.10         <code>PANode.LOAD</code> etc. */  
106 salcianu 1.1.2.23     public PANode(final int type, final GenType[] node_class) {
107 salcianu 1.1.2.27         this(type, node_class, true);
108 salcianu 1.1.2.23     }
109 salcianu 1.1.2.23 
110 salcianu 1.1.2.23     /** Constructor using the default <code>null</code> value for
111 salcianu 1.1.2.23         <code>node_class</code>. */
112 salcianu 1.1.2.10     public PANode(final int type) {
113 salcianu 1.1.2.27         this(type, null);
114 salcianu 1.1.2.27     }
115 salcianu 1.1.2.27 
116 salcianu 1.1.2.27     // Make sure nobody calls the void constructor.
117 salcianu 1.1.2.27     public PANode() {
118 cananian 1.3.2.1          assert false : "You should never call this void constructor!";
119 salcianu 1.1.2.27     }
120 salcianu 1.1.2.27 
121 salcianu 1.1.2.27 
122 salcianu 1.1.2.27     /** Returns the bar version of <code>this</code> node.
123 salcianu 1.1.2.27         Each node has two versions:
124 salcianu 1.1.2.27         <ul>
125 salcianu 1.1.2.27         <li>a <i>genuine</i> one - the node itself;
126 salcianu 1.1.2.27         <li>a <i>bar</i> one (the name comes from the way we
127 salcianu 1.1.2.27         depict it graphically).
128 salcianu 1.1.2.27         </ul>
129 salcianu 1.1.2.27 
130 salcianu 1.1.2.27         To avoid fake mappings, in the caller/callee and the
131 salcianu 1.1.2.27         starter/startee interaction, we work with the "bar" version of
132 salcianu 1.1.2.27         the callee/startee parallel interaction graph. After we determine
133 salcianu 1.1.2.27         the mapping, we go back to the "genuine" nodes.<br>
134 salcianu 1.1.2.27 
135 salcianu 1.1.2.27         This versions are different for (and only for) <code>LOAD</code>
136 salcianu 1.1.2.27         nodes. This makes sense because any non-trivial mappings are for
137 salcianu 1.1.2.27         <code>LOAD</code> nodes.<br>
138 salcianu 1.1.2.27     */
139 salcianu 1.1.2.27     public PANode getBarVersion() {
140 salcianu 1.1.2.27         return bar_version;
141 salcianu 1.1.2.27     } 
142 salcianu 1.1.2.27     private PANode bar_version = null;
143 salcianu 1.1.2.27 
144 salcianu 1.1.2.27     public PANode getGenuine() { 
145 salcianu 1.1.2.27         return isGenuine() ? this : genuine_version;
146 salcianu 1.1.2.27     }
147 salcianu 1.1.2.27     /** <code>null</code> for the genuine nodes. */
148 salcianu 1.1.2.27     private PANode genuine_version = null;
149 salcianu 1.1.2.27 
150 salcianu 1.1.2.27     /** Checks whether <code>this</code> node is a genuine one. */
151 salcianu 1.1.2.27     public boolean isGenuine() {
152 salcianu 1.1.2.27         return genuine_version == null;
153 salcianu 1.1.2.23     }
154 salcianu 1.1.2.23 
155 salcianu 1.1.2.23     // Does the real work!
156 salcianu 1.1.2.27     private PANode
157 salcianu 1.1.2.27         (final int type, final GenType[] node_class, boolean genuine) {
158 salcianu 1.1.2.23         this.type       = type;
159 salcianu 1.1.2.23         this.node_class = node_class;
160 salcianu 1.1.2.1          number = count++;
161 salcianu 1.1.2.16 
162 salcianu 1.1.2.17         if(PointerAnalysis.DEBUG)
163 salcianu 1.1.2.17             if((number % 100) == 0)
164 salcianu 1.1.2.17                 System.out.println("PANODE " + this);
165 salcianu 1.1.2.27 
166 salcianu 1.1.2.27         if(genuine) {
167 salcianu 1.1.2.27             if(PointerAnalysis.CALL_CONTEXT_SENSITIVE)
168 salcianu 1.1.2.27                 cs_specs = new LightMap();
169 salcianu 1.1.2.27 
170 salcianu 1.1.2.27             if(PointerAnalysis.THREAD_SENSITIVE)
171 salcianu 1.1.2.27                 ts_specs = new LightMap();
172 salcianu 1.1.2.27 
173 salcianu 1.1.2.27             bar_version = 
174 salcianu 1.1.2.27                 (type == LOAD) ? new PANode(type, node_class, this) : this;
175 salcianu 1.1.2.27         }
176 salcianu 1.1.2.1      }
177 salcianu 1.1.2.27 
178 salcianu 1.1.2.27     private PANode
179 salcianu 1.1.2.27         (final int type, final GenType[] node_class, PANode genuine) {
180 salcianu 1.1.2.27         this(type, node_class, false);
181 salcianu 1.1.2.27         this.genuine_version = genuine;
182 salcianu 1.1.2.27     }
183 salcianu 1.1.2.27 
184 salcianu 1.1.2.1  
185 salcianu 1.1.2.1      /** Returns the type of the node. */
186 salcianu 1.1.2.1      public final int type(){
187 salcianu 1.1.2.1          return type;
188 salcianu 1.1.2.1      }
189 salcianu 1.1.2.1  
190 salcianu 1.1.2.10     /** Checks if <code>this</code> node is an inside one. */
191 salcianu 1.1.2.1      public final boolean inside(){
192 salcianu 1.1.2.23         return type == INSIDE;
193 salcianu 1.1.2.23     }
194 salcianu 1.1.2.23 
195 salcianu 1.1.2.23     /** Returns an array of <code>GenType</code>s describing all
196 salcianu 1.1.2.23         the possible types (ie <code>HClass</code>es) this node can have.
197 salcianu 1.1.2.23         If we were unable to determine these types, <code>null</code> is
198 salcianu 1.1.2.24         returned instead; it stands for <i>any</i> type. */
199 salcianu 1.1.2.23     public final GenType[] getPossibleClasses() {
200 salcianu 1.1.2.25         if(getCallChainDepth() == 0)
201 salcianu 1.1.2.25             return node_class;
202 salcianu 1.1.2.25         else
203 salcianu 1.1.2.25             return getRoot().getPossibleClasses();
204 salcianu 1.1.2.7      }
205 salcianu 1.1.2.7  
206 salcianu 1.1.2.10     ////////////////////// CALL_CONTEXT_SENSITIVE /////////////////////////
207 salcianu 1.1.2.10 
208 salcianu 1.1.2.10     /** Returns the specialized node of <code>this</code> node for
209 salcianu 1.1.2.10         <code>call_site</code>. This method is guarranteed to return the
210 salcianu 1.1.2.11         same node if it's called on the same node, with the same argument.<br>
211 salcianu 1.1.2.10         This method makes sense iff
212 salcianu 1.1.2.10         <code>PointerAnalysis.CALL_CONTEXT_SENSITIVE</code> is on. */
213 salcianu 1.1.2.11     public final PANode csSpecialize(final CALL call_site){
214 salcianu 1.1.2.14 
215 cananian 1.3.2.1          assert call_site != null : "call_site == null";
216 salcianu 1.1.2.14 
217 salcianu 1.6              if(!PointerAnalysis.CALL_CONTEXT_SENSITIVE)
218 salcianu 1.6                  return this;
219 salcianu 1.6      
220 salcianu 1.6              /* // TODO: get rid of the following lines
221 salcianu 1.1.2.10         if(CAUTION)
222 salcianu 1.6                  assert PointerAnalysis.CALL_CONTEXT_SENSITIVE : 
223 salcianu 1.6                  "Turn on CALL_CONTEXT_SENSITIVE!"; */
224 salcianu 1.1.2.17 
225 salcianu 1.1.2.17         // a node with a maximal call_chain_depth doesn't have precise
226 salcianu 1.1.2.17         // info about the call path which produced it; so it's not worth
227 salcianu 1.1.2.17         // specializing one for each call site: one is enough
228 salcianu 1.1.2.17         if(call_chain_depth == PointerAnalysis.MAX_SPEC_DEPTH - 1){
229 salcianu 1.1.2.17             if(bottom == null){
230 salcianu 1.1.2.17                 bottom = new PANode(this.type);
231 salcianu 1.1.2.17                 bottom.call_chain_depth = this.call_chain_depth + 1;
232 salcianu 1.1.2.17                 bottom.call_site = call_site;
233 salcianu 1.1.2.17                 bottom.cs_parent = this;
234 salcianu 1.1.2.22                 bottom.bottom = bottom;
235 salcianu 1.1.2.17             }
236 salcianu 1.1.2.17             return bottom;
237 salcianu 1.1.2.17         }
238 salcianu 1.1.2.10             
239 salcianu 1.1.2.10         if(call_chain_depth >= PointerAnalysis.MAX_SPEC_DEPTH) return this;
240 salcianu 1.1.2.10 
241 salcianu 1.1.2.10         PANode spec = (PANode) cs_specs.get(call_site);
242 salcianu 1.1.2.10         if(spec == null){
243 salcianu 1.1.2.10             spec = new PANode(this.type);
244 salcianu 1.1.2.10             spec.call_chain_depth = this.call_chain_depth + 1;
245 salcianu 1.1.2.12             spec.cs_parent = this;
246 salcianu 1.1.2.12             spec.call_site = call_site;
247 salcianu 1.1.2.10             cs_specs.put(call_site, spec);
248 salcianu 1.1.2.10         }
249 salcianu 1.1.2.10 
250 salcianu 1.1.2.10         return spec;
251 salcianu 1.1.2.10     }
252 salcianu 1.1.2.10 
253 salcianu 1.1.2.10     /** Returns all the call site specializations of <code>this</code> node.
254 salcianu 1.1.2.10         It returns a set of <code>Map.Entry</code>s, each element consisting
255 salcianu 1.1.2.10         of a mapping from a <code>CALL</code> quad (the call site) to the
256 salcianu 1.1.2.11         specialized node.<br>
257 salcianu 1.1.2.10         This method makes sense iff
258 salcianu 1.1.2.10         <code>PointerAnalysis.CALL_CONTEXT_SENSITIVE</code> is on. */
259 salcianu 1.1.2.10     public final Set getAllCSSpecs(){
260 salcianu 1.1.2.10         return cs_specs.entrySet();
261 salcianu 1.1.2.10     }
262 salcianu 1.1.2.10 
263 salcianu 1.1.2.12     /** Checks whether this node is a call site specialization of
264 salcianu 1.1.2.12         another node. */
265 salcianu 1.1.2.12     public final boolean isCSSpec(){
266 salcianu 1.1.2.12         return cs_parent != null;
267 salcianu 1.1.2.12     }
268 salcianu 1.1.2.12 
269 salcianu 1.1.2.12     /** Returns the parent of this node, on the call site specialization
270 salcianu 1.1.2.12         brach. */
271 salcianu 1.1.2.12     public final PANode getCSParent(){
272 salcianu 1.1.2.12         return cs_parent;
273 salcianu 1.1.2.12     }
274 salcianu 1.1.2.12 
275 salcianu 1.1.2.18     /** Returns the bottom field: the last specialization. */ 
276 salcianu 1.1.2.18     public final PANode getBottom(){
277 salcianu 1.1.2.18         return bottom;
278 salcianu 1.1.2.18     }
279 salcianu 1.1.2.18 
280 salcianu 1.1.2.18     /** Returns the specialization depth of <code>this</code> node. */
281 salcianu 1.1.2.18     public final int getCallChainDepth(){
282 salcianu 1.1.2.18         return call_chain_depth;
283 salcianu 1.1.2.18     }
284 salcianu 1.1.2.18     
285 salcianu 1.1.2.10     //////////////////////// THREAD_SENSITIVE /////////////////////////////
286 salcianu 1.1.2.10 
287 salcianu 1.1.2.10     /** Returns the specialized node of <code>this</code> node for the
288 salcianu 1.1.2.10         thread body (ie the <code>run()</code> method) <code>run</code>.
289 salcianu 1.1.2.10         This method is guarranteed to return the same node if it's called
290 salcianu 1.1.2.11         on the same node, with the same argument.<br>
291 salcianu 1.1.2.10         This method makes sense iff
292 salcianu 1.1.2.10         <code>PointerAnalysis.THREAD_SENSITIVE</code> is on. */
293 salcianu 1.1.2.11     public final PANode tSpecialize(final MetaMethod run){
294 salcianu 1.1.2.10         if(CAUTION){
295 cananian 1.3.2.1              assert !isTSpec() : "Repeated thread specialization!";
296 cananian 1.3.2.1              assert PointerAnalysis.THREAD_SENSITIVE : "Turn on THREAD_SENSITIVE!";
297 salcianu 1.1.2.10         }
298 salcianu 1.1.2.10         PANode spec = (PANode) ts_specs.get(run);
299 salcianu 1.1.2.10         if(spec == null){
300 salcianu 1.1.2.10             spec = new PANode(this.type);
301 salcianu 1.1.2.12             spec.ts_parent = this;
302 salcianu 1.1.2.12             spec.run_mmethod = run;
303 salcianu 1.1.2.10             ts_specs.put(run,spec);
304 salcianu 1.1.2.10         }
305 salcianu 1.1.2.10 
306 salcianu 1.1.2.10         return spec;
307 salcianu 1.1.2.10     }
308 salcianu 1.1.2.10 
309 salcianu 1.1.2.10     /** Returns all the thread specializations of <code>this</code> node.
310 salcianu 1.1.2.10         It returns a set of <code>Map.Entry</code>s, each element consisting
311 salcianu 1.1.2.10         of a mapping from a <code>MetaMethod</code> (the body of a thread)
312 salcianu 1.1.2.11         to the specialized node.<br>
313 salcianu 1.1.2.10         This method makes sense iff
314 salcianu 1.1.2.10         <code>PointerAnalysis.THREAD_SENSITIVE</code> is on. */
315 salcianu 1.1.2.10     public final Set getAllTSpecs(){
316 salcianu 1.1.2.10         return ts_specs.entrySet();
317 salcianu 1.1.2.10     }
318 salcianu 1.1.2.10 
319 salcianu 1.1.2.10     
320 salcianu 1.1.2.10     ////////////////////// WEAKLY_THREAD_SENSITIVE /////////////////////////
321 salcianu 1.1.2.10 
322 salcianu 1.1.2.11     /** Returns the thread specialization of <code>this</code> node.<br>
323 salcianu 1.1.2.10         This method makes sense iff
324 salcianu 1.1.2.10         <code>PointerAnalysis.WEAKLY_THREAD_SENSITIVE</code> is on. */
325 salcianu 1.1.2.11     public final PANode wtSpecialize(){
326 salcianu 1.1.2.10         if(CAUTION){
327 cananian 1.3.2.1              assert !isTSpec() : "Repeated thread specialization!";
328 cananian 1.3.2.1              assert PointerAnalysis.WEAKLY_THREAD_SENSITIVE : "Turn on WEAKLY_THREAD_SENSITIVE!";
329 salcianu 1.1.2.10         }
330 salcianu 1.1.2.10         if(wtspec == null){
331 salcianu 1.1.2.10             wtspec = new PANode(this.type);
332 salcianu 1.1.2.12             wtspec.ts_parent = this;
333 salcianu 1.1.2.10         }
334 salcianu 1.1.2.10         return wtspec;
335 salcianu 1.1.2.8      }
336 salcianu 1.1.2.8  
337 salcianu 1.1.2.11     /** Returns the weak thread specialization of <code>this</code> node.
338 salcianu 1.1.2.11         (returns <code>null</code> if none).<br>
339 salcianu 1.1.2.11         This method makes sense iff
340 salcianu 1.1.2.10         <code>PointerAnalysis.WEAKLY_THREAD_SENSITIVE</code> is on. */
341 salcianu 1.1.2.11     public final PANode getWTSpec(){
342 salcianu 1.1.2.11         return wtspec;
343 salcianu 1.1.2.8      }
344 salcianu 1.1.2.8  
345 salcianu 1.1.2.12     /** Checks whether this node is a thread specialization of some other
346 salcianu 1.1.2.12         node. */
347 salcianu 1.1.2.12     public final boolean isTSpec(){
348 salcianu 1.1.2.12         return ts_parent != null;
349 salcianu 1.1.2.12     }
350 salcianu 1.1.2.12 
351 salcianu 1.1.2.12     /** Returns the parent of this node, on the thread specialization
352 salcianu 1.1.2.19         branch. */
353 salcianu 1.1.2.12     public final PANode getTSParent(){
354 salcianu 1.1.2.12         return ts_parent;
355 salcianu 1.1.2.12     }
356 salcianu 1.1.2.10     /////////////////////////////////////////////////////////////////////////
357 salcianu 1.1.2.10 
358 salcianu 1.1.2.10 
359 salcianu 1.1.2.10     /** Returns the set of nodes that were obtained by specializing
360 salcianu 1.1.2.10         <code>this</code> one function of some call sites. */
361 salcianu 1.1.2.10     public Set getAllCSSpecializations(){
362 salcianu 1.1.2.10         return new HashSet(cs_specs.values());
363 salcianu 1.1.2.8      }
364 salcianu 1.1.2.8  
365 salcianu 1.1.2.10     /** Checks whether <code>this</code> node is a specialization of some
366 salcianu 1.1.2.10         other node. Relevant only if the
367 salcianu 1.1.2.10         <code>PointerAnalysis.CALL_CONTEXT_SENSITIVE</code> flag is on. */
368 salcianu 1.1.2.10     public final boolean isSpecialized(){
369 salcianu 1.1.2.12         return isCSSpec() || isTSpec();
370 salcianu 1.1.2.10     }
371 salcianu 1.1.2.8  
372 salcianu 1.1.2.10     /** Checks whether <code>this</code> node is an unspecialized one
373 salcianu 1.1.2.10         (a root node in the chain of specialization). Relevant only if the
374 salcianu 1.1.2.10         <code>PointerAnalysis.CALL_CONTEXT_SENSITIVE</code> flag is on. */
375 salcianu 1.1.2.10     public final boolean isPrimitive(){
376 salcianu 1.1.2.10         return !isSpecialized();
377 salcianu 1.1.2.1      }
378 salcianu 1.1.2.1  
379 salcianu 1.1.2.15     /** Returns the root of <code>this</code> node. This is the root of the
380 salcianu 1.1.2.15         specialization chain which produced <code>this</code> node. */
381 salcianu 1.1.2.15     public final PANode getRoot(){
382 salcianu 1.1.2.15         PANode node = this;
383 salcianu 1.1.2.15         while(!node.isPrimitive()){
384 salcianu 1.1.2.15             if(node.isCSSpec()) node = node.getCSParent();
385 salcianu 1.1.2.15             else if(node.isTSpec()) node = node.getTSParent();
386 cananian 1.3.2.1              else assert false : "Specialized node but not CS or TS";
387 salcianu 1.1.2.15         }
388 salcianu 1.1.2.15         return node;
389 salcianu 1.1.2.15     }
390 salcianu 1.1.2.15 
391 salcianu 1.1.2.21     /** Tests whether <code>this</code> is the bottom of some specialization
392 salcianu 1.1.2.21         chain, i.e.
393 salcianu 1.1.2.21         <code>call_chain_depth == PointerAnalysis.MAX_SPEC_DEPTH</code>. */
394 salcianu 1.1.2.21     public boolean isBottom(){
395 salcianu 1.1.2.21         return call_chain_depth == PointerAnalysis.MAX_SPEC_DEPTH;
396 salcianu 1.1.2.21     }
397 salcianu 1.1.2.21 
398 salcianu 1.1.2.1      /** Pretty-print function for debug purposes */
399 salcianu 1.5          public final String toString() {
400 salcianu 1.1.2.1          String str = null;
401 salcianu 1.5              switch(type) {
402 salcianu 1.7              case INSIDE:  str="I"; break;
403 salcianu 1.7              case INSIDE2: str="IC"; break;
404 salcianu 1.7              case LOAD:    str="L"; break;
405 salcianu 1.7              case PARAM:   str="P"; break;
406 salcianu 1.7              case RETURN:  str="R"; break;
407 salcianu 1.7              case EXCEPT:  str="E"; break;
408 salcianu 1.7              case STATIC:  str="S"; break;
409 salcianu 1.7              case NULL:    str="NULL"; break;
410 salcianu 1.7              case CONST:   str="CONST"; break;
411 salcianu 1.7              case LOST:    str="LOST"; break;
412 salcianu 1.1.2.1          }
413 salcianu 1.7              if((type != NULL) && (type != CONST) && (type != LOST))
414 salcianu 1.5                  str = str + number;
415 salcianu 1.1.2.21         if(isBottom()) str += "B";
416 salcianu 1.1.2.21         return str;
417 salcianu 1.1.2.15     }
418 salcianu 1.1.2.15 
419 salcianu 1.1.2.15     /** Returns a detailed description of <code>this</code> node for debug
420 salcianu 1.1.2.15         purposes. */
421 salcianu 1.1.2.15     public final String details(){
422 salcianu 1.1.2.15         StringBuffer buffer = new StringBuffer();
423 salcianu 1.1.2.15         buffer.append(this);
424 salcianu 1.1.2.17         // print the ancestor on the thread specialization branch
425 salcianu 1.1.2.15         if(isTSpec()){
426 salcianu 1.1.2.15             buffer.append(" <-TS- "); 
427 salcianu 1.1.2.15             buffer.append(getTSParent().details());
428 salcianu 1.1.2.15         }
429 salcianu 1.1.2.17         // nodes that are at the limit of the maximal call chain depth
430 salcianu 1.1.2.17         // are signaled by attaching a B to them: they don't carry any
431 salcianu 1.1.2.17         // exact information about the call path so they are "bottom"
432 salcianu 1.1.2.22         if(call_chain_depth == PointerAnalysis.MAX_SPEC_DEPTH)
433 salcianu 1.1.2.17             return buffer.toString();
434 salcianu 1.1.2.17         // print the ancestors on the call specialization brach
435 salcianu 1.1.2.15         if(isCSSpec()){
436 salcianu 1.1.2.15             buffer.append(" <-CS- ");
437 salcianu 1.1.2.15             buffer.append(getCSParent().details());
438 salcianu 1.1.2.15         }
439 salcianu 1.1.2.15         return buffer.toString();
440 salcianu 1.1.2.9      }
441 salcianu 1.1.2.9  
442 salcianu 1.1.2.10     /** Translates node <code>n</code> according to the map <code>map</code>.
443 salcianu 1.1.2.9         An unmapped node is implicitly mapped to itself. */
444 salcianu 1.1.2.10     static final PANode translate(final PANode n, final Map map){
445 salcianu 1.1.2.9          PANode n2 = (PANode) map.get(n);
446 salcianu 1.1.2.9          if(n2 == null) return n;
447 salcianu 1.1.2.9          return n2;
448 salcianu 1.1.2.9      }
449 salcianu 1.1.2.9  
450 salcianu 1.1.2.10     /** Specializes a set of PANodes according to the node mapping map. */
451 salcianu 1.1.2.29     static Set specialize_set(final Set set, final Map map) {
452 salcianu 1.1.2.9          final Set set2 = new HashSet();
453 salcianu 1.1.2.9          for(Iterator it = set.iterator(); it.hasNext(); )
454 salcianu 1.1.2.9              set2.add(PANode.translate((PANode) it.next(), map));
455 salcianu 1.1.2.9          return set2;
456 salcianu 1.1.2.1      }
457 salcianu 1.1.2.1  
458 salcianu 1.1.2.1  }
459 cananian 1.2