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