1 salcianu 1.1.2.1  // NodeRepository.java, created Wed Jan 12 14:14:27 2000 by salcianu
  2 cananian 1.1.2.3  // 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.1  import java.util.Hashtable;
  7 salcianu 1.1.2.11 import java.util.Set;
  8 salcianu 1.1.2.5  import java.util.Iterator;
  9 salcianu 1.1.2.13 import java.util.Map;
 10 salcianu 1.1.2.1  
 11 salcianu 1.1.2.21 import java.lang.reflect.Modifier;
 12 salcianu 1.1.2.21 
 13 salcianu 1.7      import harpoon.ClassFile.Linker;
 14 salcianu 1.1.2.1  import harpoon.ClassFile.HMethod;
 15 salcianu 1.1.2.26 import harpoon.ClassFile.HClass;
 16 salcianu 1.1.2.1  import harpoon.ClassFile.HCodeElement;
 17 salcianu 1.1.2.5  import harpoon.IR.Quads.Quad;
 18 salcianu 1.1.2.26 import harpoon.IR.Quads.QuadVisitor;
 19 salcianu 1.1.2.11 import harpoon.IR.Quads.CALL;
 20 salcianu 1.1.2.26 import harpoon.IR.Quads.NEW;
 21 salcianu 1.1.2.26 import harpoon.IR.Quads.ANEW;
 22 salcianu 1.1.2.26 import harpoon.IR.Quads.GET;
 23 salcianu 1.1.2.26 import harpoon.IR.Quads.AGET;
 24 salcianu 1.1.2.1  
 25 salcianu 1.1.2.12 import harpoon.Analysis.MetaMethods.MetaMethod;
 26 salcianu 1.1.2.26 import harpoon.Analysis.MetaMethods.GenType;
 27 salcianu 1.1.2.26 
 28 salcianu 1.1.2.26 import harpoon.Util.Util;
 29 salcianu 1.1.2.12 
 30 salcianu 1.1.2.1  /**
 31 salcianu 1.1.2.1   * <code>NodeRepository</code>
 32 salcianu 1.1.2.1   * 
 33 cananian 1.1.2.33  * @author  Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
 34 cananian 1.10      * @version $Id: NodeRepository.java,v 1.10 2004/02/08 03:20:02 cananian Exp $
 35 salcianu 1.1.2.1   */
 36 salcianu 1.1.2.30 public class NodeRepository implements java.io.Serializable {
 37 salcianu 1.1.2.34 
 38 salcianu 1.8          public final static PANode NULL_NODE    = getNewNode(PANode.NULL);
 39 salcianu 1.8      
 40 salcianu 1.8          // this node acts as a summary for all load nodes that escape into
 41 salcianu 1.8          // an unanalyzed method or into a static node.
 42 salcianu 1.8          public final static PANode LOST_SUMMARY = getNewNode(PANode.LOST);
 43 salcianu 1.1.2.1      
 44 salcianu 1.7          private Hashtable/*<String,PANode>*/    static_nodes;
 45 salcianu 1.7          private Hashtable/*<HMethod,PANode[]>*/ param_nodes;
 46 salcianu 1.7          private Hashtable/*<Quad,PANode>*/      code_nodes;
 47 salcianu 1.7          private Hashtable/*<CFPair,PANode>*/    cf_nodes;
 48 salcianu 1.7          private Hashtable/*<Quad,PANode>*/      except_nodes;
 49 salcianu 1.7          private Hashtable/*<PANode,Quad>*/      node2code;
 50 salcianu 1.1.2.1  
 51 salcianu 1.1.2.1      /** Creates a <code>NodeRepository</code>. */
 52 salcianu 1.7          public NodeRepository(Linker linker) {
 53 salcianu 1.1.2.1          static_nodes = new Hashtable();
 54 salcianu 1.1.2.1          param_nodes  = new Hashtable();
 55 salcianu 1.1.2.1          code_nodes   = new Hashtable();
 56 salcianu 1.1.2.20         cf_nodes     = new Hashtable();
 57 salcianu 1.1.2.9          except_nodes = new Hashtable();
 58 salcianu 1.1.2.7          node2code    = new Hashtable();
 59 salcianu 1.8              jl_Throwable = linker.forName("java.lang.Throwable");
 60 salcianu 1.8              jl_Object    = linker.forName("java.lang.Object");
 61 salcianu 1.1.2.1      }
 62 salcianu 1.1.2.1  
 63 salcianu 1.1.2.31     // debug flag: if it's set on, it shows how each node is created
 64 salcianu 1.8          private final static boolean SHOW_NODE_CREATION = true;
 65 salcianu 1.1.2.31 
 66 salcianu 1.7      
 67 salcianu 1.7          /** Returns the node that models the constant object
 68 salcianu 1.7              <code>value</code>.  Currently, all constant objects are
 69 salcianu 1.7              modelled by a single node. */
 70 salcianu 1.7          public final PANode getConstNode(Object value) {
 71 salcianu 1.8              if(value == null)
 72 salcianu 1.8                  return NULL_NODE;
 73 salcianu 1.7              return CONST_NODE;
 74 salcianu 1.7          }
 75 salcianu 1.8          // should be private
 76 salcianu 1.8          static final PANode CONST_NODE = getNewNode(PANode.CONST);
 77 salcianu 1.7      
 78 salcianu 1.1.2.4      /** Returns the static node associated with the class
 79 salcianu 1.1.2.4       * <code>class_name</code>. The node is automatically created if it
 80 salcianu 1.1.2.4       * doesn't exist yet. <code>class_name</code> MUST be the full
 81 salcianu 1.1.2.4       * (and hence unique) name of the class */
 82 salcianu 1.8          public final PANode getStaticNode(String class_name) {
 83 salcianu 1.8      
 84 salcianu 1.8              if(PointerAnalysis.COMPRESS_LOST_NODES)
 85 salcianu 1.8                  return LOST_SUMMARY;
 86 salcianu 1.8      
 87 salcianu 1.1.2.5          PANode node = (PANode) static_nodes.get(class_name);
 88 salcianu 1.1.2.26         if(node == null) {
 89 salcianu 1.1.2.26             node = getNewNode(PANode.STATIC, null); // TODO
 90 salcianu 1.1.2.26             static_nodes.put(class_name, node);
 91 salcianu 1.1.2.31 
 92 salcianu 1.1.2.31             if(SHOW_NODE_CREATION)
 93 salcianu 1.1.2.31                 System.out.println("CREATED NODE " + node +
 94 salcianu 1.1.2.31                                    " for " + class_name);
 95 salcianu 1.1.2.26         }
 96 salcianu 1.1.2.4          return node;
 97 salcianu 1.1.2.1      }
 98 salcianu 1.1.2.1  
 99 salcianu 1.1.2.12     /** Creates all the parameter nodes associated with <code>mmethod</code>.
100 salcianu 1.1.2.1       *  <code>param_number</code> must contain the number of formal
101 salcianu 1.1.2.12      *  parameters of the meta-method. */
102 salcianu 1.8          public final void addParamNodes(MetaMethod mmethod, int param_number) {
103 salcianu 1.1.2.4          // do not create the parameter nodes twice for the same procedure
104 salcianu 1.1.2.12         if(param_nodes.containsKey(mmethod)) return;
105 salcianu 1.1.2.27         // grab the types for the method's object parameters
106 salcianu 1.1.2.27         GenType[] gts = new GenType[param_number];
107 salcianu 1.1.2.27         int count = 0;
108 salcianu 1.1.2.27         for(int i = 0; i < mmethod.nbParams(); i++) {
109 salcianu 1.1.2.27             GenType gt = mmethod.getType(i);
110 salcianu 1.1.2.27             if(!gt.getHClass().isPrimitive()) {
111 salcianu 1.7                      assert count < param_number : 
112 salcianu 1.7                          "Strange number of params for " + mmethod;
113 salcianu 1.1.2.27                 gts[count] = gt;
114 salcianu 1.1.2.27                 count++;
115 salcianu 1.1.2.27             }
116 salcianu 1.1.2.27         }
117 salcianu 1.1.2.27         // do the essential thing: create the nodes
118 salcianu 1.1.2.1          PANode nodes[] = new PANode[param_number];
119 salcianu 1.1.2.26         for(int i = 0; i < param_number; i++)
120 salcianu 1.1.2.27             nodes[i] = getNewNode(PANode.PARAM, new GenType[]{gts[i]});
121 salcianu 1.1.2.12         param_nodes.put(mmethod,nodes);
122 salcianu 1.1.2.31 
123 salcianu 1.1.2.31         if(SHOW_NODE_CREATION && (nodes.length > 0)) {
124 salcianu 1.1.2.31             System.out.print("\nCREATED NODES ");
125 salcianu 1.1.2.31             for(int i = 0; i < nodes.length; i++)
126 salcianu 1.1.2.31                 System.out.print(" " + nodes[i]);
127 salcianu 1.1.2.31             System.out.println("; parameters for " + mmethod.getHMethod());
128 salcianu 1.1.2.31         }
129 salcianu 1.1.2.1      }
130 salcianu 1.1.2.1  
131 salcianu 1.1.2.4      /** Returns the parameter node associated with the <code>count</code>th
132 salcianu 1.1.2.12      * formal parameter of <code>mmethod</code>. The parameter nodes for
133 salcianu 1.1.2.12      * <code>mmethod</code> should be created in advance, using
134 salcianu 1.1.2.4       * <code>addParamNodes</code>. */
135 salcianu 1.1.2.12     public final PANode getParamNode(MetaMethod mmethod, int count){
136 salcianu 1.1.2.1          // The runtime system will take care of all the debug messages ...
137 salcianu 1.1.2.12         return getAllParams(mmethod)[count];
138 salcianu 1.1.2.1      }
139 salcianu 1.1.2.1  
140 salcianu 1.1.2.4      /** Returns all the parameter nodes associated with the
141 salcianu 1.1.2.12      * formal parameters of <code>mmethod</code>. The parameter nodes for
142 salcianu 1.1.2.12      * <code>mmethod</code> should be
143 salcianu 1.1.2.4       * created in advance, using <code>addParamNodes</code>. */
144 salcianu 1.1.2.12     public final PANode[] getAllParams(MetaMethod mmethod){
145 salcianu 1.1.2.1          if(PointerAnalysis.DEBUG){
146 salcianu 1.1.2.21             if(!param_nodes.containsKey(mmethod) &&
147 salcianu 1.1.2.21                !Modifier.isNative(mmethod.getHMethod().getModifiers())) {
148 salcianu 1.1.2.1                  System.out.println("getAllParams: inexistent nodes");
149 salcianu 1.1.2.1                  System.exit(1);
150 salcianu 1.1.2.21            }
151 salcianu 1.1.2.1          }
152 salcianu 1.1.2.12         return (PANode[]) param_nodes.get(mmethod);
153 salcianu 1.1.2.1      }
154 salcianu 1.1.2.1  
155 salcianu 1.1.2.26     private final GenType[] get_exceptions(HMethod callee) {
156 salcianu 1.1.2.26         HClass[] excs = callee.getExceptionTypes();
157 salcianu 1.1.2.26         GenType[] retval = new GenType[excs.length];
158 salcianu 1.1.2.26         for(int i = 0; i < excs.length; i++)
159 salcianu 1.1.2.26             retval[i] = new GenType(excs[i], GenType.POLY);
160 salcianu 1.1.2.26         return retval;
161 salcianu 1.1.2.26     }
162 salcianu 1.1.2.26 
163 salcianu 1.1.2.9      // Returns the EXCEPT node associated with a CALL instruction
164 salcianu 1.1.2.9      private final PANode getExceptNode(HCodeElement hce){
165 salcianu 1.7              if(COALESCE_RESULTS_FROM_NATIVES) {
166 salcianu 1.7                  if(coalesced_native_excp == null)
167 salcianu 1.7                      coalesced_native_excp = getNewNode(PANode.EXCEPT);
168 salcianu 1.7                  return coalesced_native_excp;
169 salcianu 1.7              }
170 salcianu 1.7      
171 salcianu 1.1.2.9          PANode node = (PANode) except_nodes.get(hce);
172 salcianu 1.1.2.26         if(node == null) {
173 salcianu 1.1.2.26             HMethod callee = ((CALL) hce).method();
174 salcianu 1.1.2.26             node = getNewNode(PANode.EXCEPT, get_exceptions(callee));
175 salcianu 1.1.2.26             except_nodes.put(hce, node);
176 salcianu 1.1.2.26             node2code.put(node, hce);
177 salcianu 1.1.2.9          }
178 salcianu 1.1.2.9          return node;    
179 salcianu 1.1.2.9      }
180 salcianu 1.7          private PANode coalesced_native_excp = null;
181 salcianu 1.7          private PANode coalesced_native_ret  = null;
182 salcianu 1.7          private final boolean COALESCE_RESULTS_FROM_NATIVES = true;
183 salcianu 1.7          private PANode coalesced_excp = null;
184 salcianu 1.8          private final HClass jl_Throwable;
185 salcianu 1.8          private final HClass jl_Object;
186 salcianu 1.7          private final boolean COALESCE_EXCEPTIONS = true;
187 salcianu 1.1.2.9  
188 salcianu 1.1.2.20     // Auxiliary class: the key type for the "cf_nodes" hashtable.
189 salcianu 1.1.2.30     private static class CFPair implements java.io.Serializable {
190 salcianu 1.1.2.20         HCodeElement hce;
191 salcianu 1.1.2.20         String f;
192 salcianu 1.1.2.20         CFPair(HCodeElement hce, String f){
193 salcianu 1.1.2.20             this.hce = hce;
194 salcianu 1.1.2.20             this.f   = f;
195 salcianu 1.1.2.20         }
196 salcianu 1.1.2.20 
197 salcianu 1.1.2.20         int hash = 0; // small caching hack
198 salcianu 1.1.2.20         public int hashCode(){
199 salcianu 1.1.2.20             if(hash == 0)
200 salcianu 1.1.2.20                 hash = hce.hashCode() + f.hashCode();
201 salcianu 1.1.2.20             return hash;
202 salcianu 1.1.2.20         }
203 salcianu 1.1.2.20 
204 salcianu 1.1.2.20         public boolean equals(Object obj){
205 salcianu 1.1.2.20             CFPair hf2 = (CFPair) obj;
206 salcianu 1.1.2.20             return (hf2.hce.equals(hce) && hf2.f.equals(f));
207 salcianu 1.1.2.20         }
208 salcianu 1.1.2.20 
209 salcianu 1.1.2.20         public String toString(){
210 salcianu 1.1.2.20             return hce.toString() + f.toString();
211 salcianu 1.1.2.20         }
212 salcianu 1.1.2.20     }
213 salcianu 1.1.2.20 
214 salcianu 1.1.2.20     /** Special function for load instructions that read multiple fields
215 salcianu 1.1.2.20         in the same time (the motivating example is that of "clone()")
216 salcianu 1.1.2.20         For such an instruction, a load node is generated for each field
217 salcianu 1.1.2.20         that is read (<code>f</code> in the parameter list). */
218 salcianu 1.1.2.20     public final PANode getLoadNodeSpecial(HCodeElement hce, String f){
219 salcianu 1.1.2.20         CFPair key = new CFPair(hce, f); 
220 salcianu 1.1.2.20         PANode retval = (PANode) cf_nodes.get(key);
221 salcianu 1.1.2.26         if(retval == null) {
222 salcianu 1.1.2.20             retval = new PANode(PANode.LOAD);
223 salcianu 1.1.2.20             cf_nodes.put(key, retval);
224 salcianu 1.1.2.20         }
225 salcianu 1.1.2.20         return retval;
226 salcianu 1.1.2.20     }
227 salcianu 1.1.2.20 
228 salcianu 1.1.2.20 
229 salcianu 1.8          public final PANode getCodeNode(HCodeElement hce, int type) {
230 salcianu 1.8              return getCodeNode(hce, type, null, true);
231 salcianu 1.8          }
232 salcianu 1.8      
233 salcianu 1.8          public final PANode getCodeNode(HCodeElement hce, int type, boolean make) {
234 salcianu 1.8              return getCodeNode(hce, type, null, make);
235 salcianu 1.8          }
236 salcianu 1.8      
237 salcianu 1.1.2.24     /** Returns a <i>code</i> node: a node associated with the
238 salcianu 1.1.2.4       * instruction <code>hce</code>: a load node 
239 salcianu 1.1.2.4       * (associated with a <code>GET</code> quad), a return node (associated
240 salcianu 1.1.2.4       * with a <code>CALL</code>) or an inside node (thread or not) associated
241 salcianu 1.1.2.4       * with a <code>NEW</code>). The node is automatically created if it
242 salcianu 1.1.2.4       * doesn't exist yet. The type of the node should be passed in the
243 salcianu 1.1.2.4       * <code>type</code> argument. */
244 salcianu 1.8          public final PANode getCodeNode(HCodeElement hce, int type, GenType[] gts){
245 salcianu 1.8              return getCodeNode(hce, type, gts, true);
246 salcianu 1.1.2.24     }
247 salcianu 1.1.2.24 
248 salcianu 1.1.2.24     /** Returns a <i>code</i> node: a node associated with an instruction.
249 salcianu 1.1.2.24         The boolean parameter <code>make</code> controls the generation of
250 salcianu 1.1.2.24         such a node in case it doesn't exist yet. */
251 salcianu 1.8          public final PANode getCodeNode(HCodeElement hce, int type, GenType[] gts,
252 salcianu 1.8                                          boolean make) {
253 salcianu 1.8      
254 salcianu 1.9              if(((type == PANode.RETURN) || (type == PANode.EXCEPT)) &&
255 salcianu 1.8                 PointerAnalysis.COMPRESS_LOST_NODES)
256 salcianu 1.8                  return LOST_SUMMARY;
257 salcianu 1.8      
258 salcianu 1.1.2.9          // we can have a RETURN node and an EXCEPT node associated to the
259 salcianu 1.1.2.9          // same code instruction. This is the only case where we have
260 salcianu 1.1.2.9          // two nodes associated with an instruction. We fix this by handling
261 salcianu 1.1.2.9          // EXCEPT nodes separately.
262 salcianu 1.1.2.9          if(type == PANode.EXCEPT) return getExceptNode(hce);
263 salcianu 1.1.2.9  
264 salcianu 1.7              if(type == PANode.RETURN && COALESCE_RESULTS_FROM_NATIVES) {
265 salcianu 1.7                  if(coalesced_native_ret == null)
266 salcianu 1.8                      coalesced_native_ret = 
267 salcianu 1.8                          getNewNode
268 salcianu 1.8                          (PANode.RETURN,
269 salcianu 1.8                           new GenType[] { new GenType(jl_Object, GenType.POLY) });
270 salcianu 1.7                  return coalesced_native_ret;
271 salcianu 1.7              }
272 salcianu 1.7      
273 salcianu 1.7              if((type == PANode.INSIDE) && COALESCE_EXCEPTIONS &&
274 salcianu 1.8                 ((hce instanceof NEW) || (hce instanceof ANEW)) &&
275 salcianu 1.8                 getAllocatedType(hce).isInstanceOf(jl_Throwable)) {
276 salcianu 1.7                  if(coalesced_excp == null)
277 salcianu 1.7                      coalesced_excp = 
278 salcianu 1.8                          getNewNode
279 salcianu 1.8                          (PANode.INSIDE, 
280 salcianu 1.8                           new GenType[] { new GenType(jl_Throwable, GenType.POLY)});
281 salcianu 1.7                  return coalesced_excp;
282 salcianu 1.7              }
283 salcianu 1.7      
284 salcianu 1.1.2.1          PANode node = (PANode) code_nodes.get(hce);
285 salcianu 1.1.2.31         if((node == null) && make) {
286 salcianu 1.8                  if(gts == null)
287 salcianu 1.8                      gts = new GenType[] { get_code_node_type(hce) };
288 salcianu 1.8                  node = getNewNode(type, gts);
289 salcianu 1.1.2.26             code_nodes.put(hce, node);
290 salcianu 1.1.2.23             node2code.put(node, hce);
291 salcianu 1.1.2.29 
292 salcianu 1.1.2.31             if(SHOW_NODE_CREATION)
293 salcianu 1.1.2.31                 System.out.println("CREATED NODE " + node + " for " +
294 salcianu 1.6                                         Util.code2str(hce));
295 salcianu 1.1.2.6          }
296 salcianu 1.1.2.1          return node;
297 salcianu 1.1.2.10     }
298 salcianu 1.1.2.10 
299 salcianu 1.1.2.26     private final GenType get_code_node_type(HCodeElement hce) {
300 salcianu 1.1.2.26         Quad quad = (Quad) hce;
301 salcianu 1.1.2.26 
302 salcianu 1.1.2.26         class GenTypeWrapper{
303 salcianu 1.1.2.26             GenType gt = null;
304 salcianu 1.1.2.26         }
305 salcianu 1.1.2.26         final GenTypeWrapper retval = new GenTypeWrapper();
306 salcianu 1.1.2.26 
307 salcianu 1.1.2.26         quad.accept(new QuadVisitor() {
308 salcianu 1.1.2.26                 public void visit(NEW q) { // INSIDE nodes
309 salcianu 1.1.2.26                     retval.gt = new GenType(q.hclass(), GenType.MONO);
310 salcianu 1.1.2.26                 }
311 salcianu 1.1.2.26                 
312 salcianu 1.1.2.26                 public void visit(ANEW q) { // array INSIDE nodes
313 salcianu 1.1.2.26                     retval.gt = new GenType(q.hclass(), GenType.MONO);
314 salcianu 1.1.2.26                 }
315 salcianu 1.1.2.26 
316 salcianu 1.1.2.26                 public void visit(CALL q) { // RETURN nodes
317 salcianu 1.1.2.26                     retval.gt =
318 salcianu 1.1.2.26                         new GenType(q.method().getReturnType(), GenType.POLY);
319 salcianu 1.1.2.26                 }
320 salcianu 1.1.2.26 
321 salcianu 1.1.2.26                 public void visit(GET q) { // LOAD nodes
322 salcianu 1.7                          retval.gt = new GenType(q.field().getType(), GenType.POLY);
323 salcianu 1.1.2.26                 }
324 salcianu 1.1.2.26 
325 salcianu 1.1.2.26                 public void visit(AGET q) { // LOAD nodes from array ops
326 salcianu 1.7                          retval.gt = new GenType(q.type(), GenType.POLY);
327 salcianu 1.1.2.26                 }
328 salcianu 1.1.2.26 
329 salcianu 1.1.2.26                 public void visit(Quad q) {
330 salcianu 1.1.2.26                     // this should not happen
331 cananian 1.3.2.1                      assert false : "Unknown quad " + q;
332 salcianu 1.1.2.26                 }
333 salcianu 1.1.2.26             });
334 salcianu 1.1.2.26 
335 salcianu 1.1.2.26         return retval.gt;
336 salcianu 1.1.2.26     }
337 salcianu 1.1.2.26 
338 salcianu 1.1.2.26 
339 salcianu 1.1.2.15     // all the nodes are produced by this method. So, if we want them
340 salcianu 1.1.2.15     // to have a common characteristic, here is THE place to add things.
341 salcianu 1.1.2.26     static final PANode getNewNode(int type, GenType[] node_class) {
342 salcianu 1.9              PANode node = new PANode(type, node_class);
343 salcianu 1.9      
344 salcianu 1.9              if(number2node == null)
345 salcianu 1.9                  number2node = new Hashtable();
346 salcianu 1.9              number2node.put(new Integer(node.number), node);
347 salcianu 1.9      
348 salcianu 1.9              return node;
349 salcianu 1.1.2.26     } 
350 salcianu 1.9      
351 salcianu 1.9          private static Hashtable/*<Integer,PANode>*/ number2node;
352 salcianu 1.9          static PANode nodeForNumber(int number) {
353 salcianu 1.9              if(number2node == null)
354 salcianu 1.9                  return null;
355 salcianu 1.9              return (PANode) number2node.get(new Integer(number));
356 salcianu 1.9          }
357 salcianu 1.9      
358 salcianu 1.1.2.26 
359 salcianu 1.1.2.26     // default parameter for the node_class array.
360 salcianu 1.1.2.26     static final PANode getNewNode(int type) {
361 salcianu 1.1.2.26         return getNewNode(type, null);
362 salcianu 1.1.2.1      }
363 salcianu 1.1.2.26         
364 salcianu 1.1.2.28     /** Returns the instruction that created <code>node</code>. */
365 salcianu 1.1.2.28     public final HCodeElement node2Code(PANode node){
366 salcianu 1.1.2.28         if(node == null) return null;
367 salcianu 1.1.2.28         return (HCodeElement) node2code.get(node);
368 salcianu 1.1.2.22     }
369 salcianu 1.1.2.32 
370 salcianu 1.1.2.32 
371 salcianu 1.1.2.32     /** Gets the type of an inside node. */
372 salcianu 1.1.2.32     public final HClass getInsideNodeType(PANode node) {
373 cananian 1.3.2.1          assert node.type == PANode.INSIDE : "Not an inside node!";
374 salcianu 1.1.2.32         PANode root = node.getRoot();
375 salcianu 1.1.2.32         System.out.println("getInsideNodeType: " + root);
376 salcianu 1.1.2.32         HCodeElement hce = node2Code(root);
377 salcianu 1.6              System.out.println("getInsideNodeType: " + Util.code2str(hce));
378 salcianu 1.1.2.32         return getAllocatedType(hce);
379 salcianu 1.1.2.32     }
380 salcianu 1.1.2.32 
381 salcianu 1.1.2.32 
382 salcianu 1.1.2.32     // get the type of the object allocated by the object creation site hce;
383 salcianu 1.1.2.32     // hce should be NEW or ANEW.
384 salcianu 1.1.2.32     public static HClass getAllocatedType(final HCodeElement hce){
385 salcianu 1.1.2.32         if(hce instanceof NEW)
386 salcianu 1.1.2.32             return ((NEW) hce).hclass();
387 salcianu 1.1.2.32         if(hce instanceof ANEW)
388 salcianu 1.1.2.32             return ((ANEW) hce).hclass();
389 cananian 1.3.2.1          assert false : ("Not a NEW or ANEW: " + hce);
390 salcianu 1.1.2.32         return null; // should never happen
391 salcianu 1.1.2.32     }
392 salcianu 1.1.2.32 
393 salcianu 1.1.2.22 
394 salcianu 1.1.2.22     /** Modify the node2code mapping such that now node is associated
395 salcianu 1.1.2.22         with hce. */
396 salcianu 1.1.2.22     public final void updateNode2Code(PANode node, HCodeElement hce){
397 salcianu 1.1.2.22         // put the new one
398 salcianu 1.1.2.22         node2code.put(node, hce);
399 salcianu 1.1.2.6      }
400 salcianu 1.1.2.6  
401 salcianu 1.1.2.6      /** Pretty-printer for debug purposes. */
402 salcianu 1.1.2.5      public final String toString(){
403 salcianu 1.1.2.5          StringBuffer buffer = new StringBuffer();
404 salcianu 1.1.2.5  
405 salcianu 1.1.2.5          buffer.append("PARAMETER NODES:\n");
406 salcianu 1.1.2.12         Object[] mmethods = Debug.sortedSet(param_nodes.keySet());
407 salcianu 1.1.2.12         for(int i = 0 ; i < mmethods.length ; i++){
408 salcianu 1.1.2.12             MetaMethod mmethod = (MetaMethod) mmethods[i];
409 salcianu 1.1.2.12             buffer.append(mmethod);
410 salcianu 1.1.2.12             // buffer.append(method.getDeclaringClass().getName());
411 salcianu 1.1.2.12             // buffer.append(".");
412 salcianu 1.1.2.12             // buffer.append(method.getName());
413 salcianu 1.1.2.5              buffer.append(":\t");
414 salcianu 1.1.2.12             PANode[] nodes = getAllParams(mmethod);
415 salcianu 1.1.2.6              for(int j = 0 ; j < nodes.length ; j++){
416 salcianu 1.1.2.6                  buffer.append(nodes[j]);
417 salcianu 1.1.2.5                  buffer.append(" ");
418 salcianu 1.1.2.5              }
419 salcianu 1.1.2.5              buffer.append("\n");
420 salcianu 1.1.2.5          }
421 salcianu 1.1.2.5  
422 salcianu 1.1.2.5          buffer.append("STATIC NODES:\n");
423 salcianu 1.1.2.6          Object[] statics = Debug.sortedSet(static_nodes.keySet());
424 salcianu 1.1.2.6          for(int i = 0; i < statics.length ; i++){
425 salcianu 1.1.2.6              String class_name = (String) statics[i];
426 salcianu 1.1.2.5              buffer.append(class_name);
427 salcianu 1.1.2.5              buffer.append(":\t");
428 salcianu 1.1.2.5              buffer.append(getStaticNode(class_name));
429 salcianu 1.1.2.5              buffer.append("\n");
430 salcianu 1.1.2.5          }
431 salcianu 1.1.2.5  
432 salcianu 1.1.2.5          buffer.append("CODE NODES:\n");
433 salcianu 1.1.2.6          Object[] codes = Debug.sortedSet(code_nodes.keySet());
434 salcianu 1.1.2.6          for(int i = 0 ; i < codes.length ; i++){
435 salcianu 1.1.2.6              HCodeElement hce = (HCodeElement) codes[i];
436 salcianu 1.1.2.5              Quad q = (Quad) hce;
437 salcianu 1.1.2.5              buffer.append((PANode)code_nodes.get(hce));
438 salcianu 1.1.2.5              buffer.append("\t");
439 salcianu 1.1.2.5              buffer.append(hce.getSourceFile());
440 salcianu 1.1.2.5              buffer.append(":");
441 salcianu 1.1.2.5              buffer.append(hce.getLineNumber());
442 salcianu 1.1.2.5              buffer.append(" ");
443 salcianu 1.1.2.5              buffer.append(hce);
444 salcianu 1.1.2.5              buffer.append("\n");
445 salcianu 1.1.2.5          }
446 salcianu 1.1.2.5  
447 salcianu 1.1.2.9          codes = Debug.sortedSet(except_nodes.keySet());
448 salcianu 1.1.2.9          for(int i = 0 ; i < codes.length ; i++){
449 salcianu 1.1.2.9              HCodeElement hce = (HCodeElement) codes[i];
450 salcianu 1.1.2.9              Quad q = (Quad) hce;
451 salcianu 1.1.2.9              buffer.append((PANode)except_nodes.get(hce));
452 salcianu 1.1.2.9              buffer.append("\t");
453 salcianu 1.1.2.9              buffer.append(hce.getSourceFile());
454 salcianu 1.1.2.9              buffer.append(":");
455 salcianu 1.1.2.9              buffer.append(hce.getLineNumber());
456 salcianu 1.1.2.9              buffer.append(" ");
457 salcianu 1.1.2.9              buffer.append(hce);
458 salcianu 1.1.2.9              buffer.append("\n");
459 salcianu 1.1.2.20         }
460 salcianu 1.1.2.20 
461 salcianu 1.1.2.20         Object cfs[] = Debug.sortedSet(cf_nodes.keySet());
462 salcianu 1.1.2.20         for(int i = 0; i < cfs.length; i++){
463 salcianu 1.1.2.20             CFPair cfp = (CFPair) cfs[i];
464 salcianu 1.1.2.20             HCodeElement hce = cfp.hce;
465 salcianu 1.1.2.20             buffer.append((PANode) cf_nodes.get(cfp) + "\t" + 
466 salcianu 1.1.2.20                           hce.getSourceFile() + ":" + hce.getLineNumber() +
467 salcianu 1.1.2.20                           " " + cfp.hce + "\n");
468 salcianu 1.1.2.9          }
469 salcianu 1.1.2.9  
470 salcianu 1.1.2.5          return buffer.toString();
471 salcianu 1.1.2.5      }
472 salcianu 1.1.2.5  
473 salcianu 1.1.2.9      /** Prints some statistics. */
474 salcianu 1.1.2.9      public void print_stats(){
475 salcianu 1.1.2.11         int nb_total   = PANode.count - 1;
476 salcianu 1.1.2.11         // the last -1 is for the InterThreadPA.THIS_THREAD conventional node
477 salcianu 1.1.2.9          int nb_excepts = except_nodes.size();
478 salcianu 1.1.2.9          int nb_statics = static_nodes.size();
479 salcianu 1.1.2.9  
480 salcianu 1.1.2.9          int nb_insides = 0;
481 salcianu 1.1.2.9          int nb_loads   = 0;
482 salcianu 1.1.2.9          int nb_returns = 0;
483 salcianu 1.7              int nb_consts  = 1; // no other way of computing it
484 salcianu 1.7              int nb_nulls   = 1; // no other way of computing it
485 salcianu 1.1.2.9          
486 salcianu 1.7              for(Iterator it = code_nodes.keySet().iterator(); it.hasNext(); ) {
487 salcianu 1.1.2.9              PANode node = (PANode) code_nodes.get(it.next());
488 salcianu 1.7                  switch(node.type) {
489 salcianu 1.1.2.9              case PANode.INSIDE:
490 salcianu 1.1.2.9                  nb_insides++;
491 salcianu 1.1.2.9                  break;
492 salcianu 1.1.2.9              case PANode.LOAD:
493 salcianu 1.1.2.9                  nb_loads++;
494 salcianu 1.1.2.9                  break;
495 salcianu 1.1.2.9              case PANode.RETURN:
496 salcianu 1.1.2.9                  nb_returns++;
497 salcianu 1.1.2.9                  break;
498 salcianu 1.1.2.9              }
499 salcianu 1.1.2.9          }
500 salcianu 1.1.2.9  
501 salcianu 1.1.2.9          int nb_params = 0;
502 salcianu 1.7              for(Iterator it = param_nodes.keySet().iterator(); it.hasNext(); )
503 salcianu 1.1.2.9              nb_params += ((PANode[])(param_nodes.get(it.next()))).length;
504 salcianu 1.1.2.9  
505 salcianu 1.1.2.11         int nb_roots = 
506 salcianu 1.1.2.11             nb_insides + nb_returns + nb_excepts +
507 salcianu 1.7                  nb_statics + nb_loads + nb_params + nb_consts + nb_nulls;
508 salcianu 1.1.2.11 
509 salcianu 1.1.2.9          System.out.println("-NODE STATS-------------------------------");
510 salcianu 1.1.2.11         System.out.println("INSIDE node(s) : " + nb_insides + " roots, " +
511 salcianu 1.7                                 (nb_total - nb_roots) + " specializations");
512 salcianu 1.1.2.9          System.out.println("RETURN node(s) : " + nb_returns);
513 salcianu 1.1.2.9          System.out.println("EXCEPT node(s) : " + nb_excepts);
514 salcianu 1.1.2.9          System.out.println("STATIC node(s) : " + nb_statics);
515 salcianu 1.1.2.9          System.out.println("LOAD   node(s) : " + nb_loads);
516 salcianu 1.1.2.9          System.out.println("PARAM  node(s) : " + nb_params);
517 salcianu 1.7              System.out.println("CONST  node(s) : " + nb_consts);
518 salcianu 1.7              System.out.println("NULL   node(s) : " + nb_nulls);
519 salcianu 1.1.2.9          System.out.println("-------------------------");
520 salcianu 1.1.2.9          System.out.println("TOTAL          : " + nb_total);
521 salcianu 1.1.2.9      }
522 salcianu 1.1.2.9  
523 salcianu 1.1.2.11     /** Nice looking info for debug purposes. */
524 salcianu 1.1.2.11     public void show_specializations(){
525 salcianu 1.1.2.11         System.out.println("-SPECIALIZATIONS--------------------------");
526 salcianu 1.1.2.11 
527 salcianu 1.1.2.11         Iterator it = code_nodes.keySet().iterator();
528 salcianu 1.1.2.11         while(it.hasNext()){
529 salcianu 1.1.2.11             PANode node = (PANode) code_nodes.get(it.next());
530 salcianu 1.1.2.13             if(node.type == PANode.INSIDE){
531 salcianu 1.1.2.13                 System.out.print(node);
532 salcianu 1.1.2.13                 HCodeElement hce = node2Code(node);
533 salcianu 1.1.2.16                 System.out.println(" created at " + hce.getSourceFile() + 
534 salcianu 1.1.2.16                                  ":" + hce.getLineNumber() + " " + hce);
535 salcianu 1.1.2.13                 show_node_specs(node, 1);
536 salcianu 1.1.2.13             }
537 salcianu 1.1.2.11         }
538 salcianu 1.1.2.11     }
539 salcianu 1.1.2.11 
540 salcianu 1.1.2.13     // shows the specializations (call site and thread specs) for node.
541 salcianu 1.1.2.13     private void show_node_specs(PANode node, int ident){
542 salcianu 1.1.2.11 
543 salcianu 1.1.2.19         if(PointerAnalysis.CALL_CONTEXT_SENSITIVE){
544 cananian 1.10                 for(Object entryO : node.getAllCSSpecs()){
545 cananian 1.10                     Map.Entry entry = (Map.Entry) entryO;
546 salcianu 1.1.2.13                 CALL       q = (CALL) entry.getKey();
547 salcianu 1.1.2.13                 PANode snode = (PANode) entry.getValue();
548 salcianu 1.1.2.13                 
549 salcianu 1.1.2.13                 for(int i = 0; i < ident ; i++)
550 salcianu 1.1.2.13                     System.out.print(" ");
551 salcianu 1.1.2.13                 System.out.print(snode);
552 salcianu 1.1.2.13                 
553 salcianu 1.1.2.13                 System.out.print(" CallS from " + node +
554 salcianu 1.1.2.16                                  " at " + q.getSourceFile() +
555 salcianu 1.1.2.13                                  ":" + q.getLineNumber());          
556 salcianu 1.1.2.16                 //if(PointerAnalysis.DETAILS2){
557 salcianu 1.1.2.13                     HMethod method = q.method();
558 salcianu 1.1.2.13                     System.out.print(" (CALL " + 
559 salcianu 1.1.2.13                                      method.getDeclaringClass().getName()+"."+
560 salcianu 1.1.2.13                                      method.getName() + ") ");
561 salcianu 1.1.2.16                     //}
562 salcianu 1.1.2.13                 System.out.println();
563 salcianu 1.1.2.13                 show_node_specs(snode, ident+1);
564 salcianu 1.1.2.13             }
565 salcianu 1.1.2.19             PANode bottom = node.getBottom();
566 salcianu 1.1.2.19             if(bottom != null){
567 salcianu 1.1.2.19                 for(int i = 0; i < ident ; i++)
568 salcianu 1.1.2.19                     System.out.print(" ");
569 salcianu 1.1.2.19                 System.out.print(bottom);
570 salcianu 1.1.2.19                 System.out.println("B");
571 salcianu 1.1.2.19             }
572 salcianu 1.1.2.19         }
573 salcianu 1.1.2.11 
574 salcianu 1.1.2.13         if(PointerAnalysis.THREAD_SENSITIVE)
575 cananian 1.10                 for(Object entryO : node.getAllTSpecs()){
576 cananian 1.10                     Map.Entry entry = (Map.Entry) entryO;
577 salcianu 1.1.2.13                 MetaMethod  run = (MetaMethod) entry.getKey();
578 salcianu 1.1.2.13                 PANode    snode = (PANode) entry.getValue();
579 salcianu 1.1.2.13                 
580 salcianu 1.1.2.13                 for(int i = 0; i < ident ; i++)
581 salcianu 1.1.2.13                     System.out.print(" ");
582 salcianu 1.1.2.13                 System.out.print(snode);
583 salcianu 1.1.2.13                 System.out.println(" FTS from " + node +
584 salcianu 1.1.2.13                                    " for " + run);
585 salcianu 1.1.2.13                 show_node_specs(snode, ident+1);            
586 salcianu 1.1.2.13             }
587 salcianu 1.1.2.11 
588 salcianu 1.1.2.13         if(PointerAnalysis.WEAKLY_THREAD_SENSITIVE){
589 salcianu 1.1.2.14             PANode snode = node.getWTSpec();
590 salcianu 1.1.2.13             if(snode != null){
591 salcianu 1.1.2.13                 for(int i = 0; i < ident ; i++)
592 salcianu 1.1.2.13                     System.out.print(" ");
593 salcianu 1.1.2.13                 System.out.print(snode);
594 salcianu 1.1.2.13                 System.out.println(" WTS from " + node);
595 salcianu 1.1.2.13                 show_node_specs(snode, ident+1);            
596 salcianu 1.1.2.13             }
597 salcianu 1.1.2.11         }
598 salcianu 1.1.2.11     }
599 salcianu 1.1.2.11 
600 cananian 1.2      }