1 salcianu 1.1.2.1 // MetaMethod.java, created Tue Mar 7 15:52:47 2000 by salcianu 2 cananian 1.1.2.6 // 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.MetaMethods; 5 salcianu 1.1.2.1 6 salcianu 1.1.2.1 import java.util.List; 7 salcianu 1.1.2.1 import java.util.Iterator; 8 salcianu 1.1.2.1 9 salcianu 1.1.2.1 import harpoon.ClassFile.HMethod; 10 salcianu 1.1.2.1 import harpoon.ClassFile.HClass; 11 salcianu 1.1.2.1 12 salcianu 1.1.2.1 import harpoon.Util.Util; 13 salcianu 1.1.2.1 14 salcianu 1.1.2.1 /** 15 salcianu 1.1.2.1 * <code>MetaMethod</code> is a specialization of a method, function of the 16 salcianu 1.1.2.1 types of its arguments.<br> 17 salcianu 1.1.2.1 18 salcianu 1.1.2.1 For example, if we have a method <code>foo</code> 19 salcianu 1.1.2.1 declared as having a single parameter of type <code>Object</code>, if we 20 salcianu 1.1.2.1 know that in a specific call site it is called with an argument of type 21 salcianu 1.1.2.1 <code>A</code> and in some other call site with an argument of type 22 salcianu 1.1.2.1 <code>B</code>, then we can 23 salcianu 1.1.2.1 say that in the first case we call the meta-method consisting of method 24 salcianu 1.1.2.1 <code><foo,A></code> while in the second one we call the meta-method 25 salcianu 1.1.2.1 <code><foo,B></code>.<br> 26 salcianu 1.1.2.1 27 salcianu 1.1.2.1 In languages that relies very heavily on 28 salcianu 1.1.2.1 inheritance and dynamic dispatch (virtual methods) such as Java, this will 29 salcianu 1.1.2.1 lead to a 30 salcianu 1.1.2.1 sparser call graph, removing some unrealizable call chains. In particular, 31 salcianu 1.1.2.1 it will simplify or even totally remove some artificial strongly connected 32 salcianu 1.1.2.1 components of pseudo mutually recursive methods.<br> 33 salcianu 1.1.2.1 34 salcianu 1.1.2.1 In short, a meta-method is simply a method plus some types for its 35 salcianu 1.1.2.1 parameters. These types are supposed to be identically to or, preferably, 36 salcianu 1.1.2.1 narrower than the declared types for that method. Something you should 37 salcianu 1.1.2.1 keep in mind if you plan to use meta-methods is that many meta-methods 38 salcianu 1.1.2.1 can be generated through specialization from the <i>same</i> method. So, 39 salcianu 1.1.2.1 if you decide to modify only one of them, you should first make a copy 40 salcianu 1.1.2.1 of it, do whatever optimizations you do on that copy and modify the 41 salcianu 1.1.2.1 concerned call-sites to point to it. 42 salcianu 1.1.2.1 * 43 cananian 1.1.2.6 * @author Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu> 44 cananian 1.4 * @version $Id: MetaMethod.java,v 1.4 2002/04/10 03:00:22 cananian Exp $ 45 salcianu 1.1.2.1 */ 46 cananian 1.1.2.3 public class MetaMethod implements java.io.Serializable { 47 salcianu 1.1.2.1 // Turns on some severe correctness tests. 48 salcianu 1.1.2.1 private static final boolean CAUTION = true; 49 salcianu 1.1.2.1 50 salcianu 1.1.2.1 private HMethod hm; 51 salcianu 1.1.2.1 private GenType[] types = null; 52 salcianu 1.1.2.1 53 salcianu 1.1.2.1 /** Creates a <code>MetaMethod</code> corresponding to the method 54 salcianu 1.1.2.1 <code>hm</code> and the types from the array "types". */ 55 salcianu 1.1.2.1 public MetaMethod(HMethod hm, GenType[] types){ 56 salcianu 1.1.2.1 this.hm = hm; 57 salcianu 1.1.2.1 if(CAUTION){ 58 salcianu 1.1.2.1 HClass[] param_types = hm.getParameterTypes(); 59 salcianu 1.1.2.1 int nb_params = param_types.length + (hm.isStatic()?0:1); 60 salcianu 1.1.2.1 if(nb_params != types.length) 61 cananian 1.3.2.1 assert false : "Wrong number of arguments"; 62 salcianu 1.1.2.1 } 63 salcianu 1.1.2.1 this.types = new GenType[types.length]; 64 salcianu 1.1.2.1 for(int i = 0 ; i < types.length ; i++) 65 salcianu 1.1.2.1 this.types[i] = types[i]; 66 salcianu 1.1.2.1 } 67 salcianu 1.1.2.1 68 salcianu 1.1.2.1 /** Creates a <code>MetaMethod</code> corresponding to the method 69 salcianu 1.1.2.1 <code>hm</code> and the types declared for it. The types appearing 70 salcianu 1.1.2.1 in the declaration of the method are considered to be polymorphic or 71 salcianu 1.1.2.1 not, depending whether <code>polymorphic</code> is switched on/off. */ 72 salcianu 1.1.2.1 public MetaMethod(HMethod hm, boolean polymorphic){ 73 salcianu 1.1.2.1 this.hm = hm; 74 salcianu 1.1.2.1 int type_kind = polymorphic?GenType.POLY:GenType.MONO; 75 salcianu 1.1.2.1 int skew = hm.isStatic()?0:1; 76 salcianu 1.1.2.1 HClass[] param_types = hm.getParameterTypes(); 77 salcianu 1.1.2.1 types = new GenType[param_types.length + skew]; 78 salcianu 1.1.2.1 if(!hm.isStatic()) 79 salcianu 1.1.2.1 types[0] = new GenType(hm.getDeclaringClass(),type_kind); 80 salcianu 1.1.2.1 for(int i = 0; i < param_types.length ; i++){ 81 salcianu 1.1.2.1 HClass hclass = param_types[i]; 82 salcianu 1.1.2.1 if(hclass.isPrimitive()) 83 salcianu 1.1.2.1 types[i + skew] = new GenType(hclass, GenType.MONO); 84 salcianu 1.1.2.1 else 85 salcianu 1.1.2.1 types[i + skew] = new GenType(hclass, type_kind); 86 salcianu 1.1.2.1 } 87 salcianu 1.1.2.1 } 88 salcianu 1.1.2.1 89 salcianu 1.1.2.1 /** Creates a <code>MetaMethod</code> corresponding to the method 90 salcianu 1.1.2.1 <code>hm</code> and the types declared for it. All the types appearing 91 salcianu 1.1.2.1 in the declaration of the method are considered to be polymorphic., 92 salcianu 1.1.2.1 that is we are maximally conservative in our initial estimation. 93 salcianu 1.1.2.1 The types of can be specialized to by using <code>setType</code>. */ 94 salcianu 1.1.2.1 public MetaMethod(HMethod hm){ 95 salcianu 1.1.2.5 this(hm, true); 96 salcianu 1.1.2.1 } 97 salcianu 1.1.2.1 98 salcianu 1.1.2.1 /** Returns the <code>HMethod</code> that <code>this</code> meta-method 99 salcianu 1.1.2.1 is a specialization of. */ 100 salcianu 1.1.2.1 public HMethod getHMethod(){ 101 salcianu 1.1.2.1 return hm; 102 salcianu 1.1.2.1 } 103 salcianu 1.1.2.1 104 salcianu 1.1.2.1 /** Returns the type of the <code>i</code>-th parameter. */ 105 salcianu 1.1.2.1 public GenType getType(int i){ 106 salcianu 1.1.2.1 return types[i]; 107 salcianu 1.1.2.1 } 108 salcianu 1.1.2.1 109 salcianu 1.1.2.1 /** Set the type of the <code>i</code>-th argument of <code>this</code> 110 salcianu 1.1.2.1 meta-method. The arguments are 0-indexed, with the receiver of the 111 salcianu 1.1.2.1 method in the first place if the method is non-static. This method 112 salcianu 1.1.2.1 should be used to specialize the types of the arguments. */ 113 salcianu 1.1.2.1 public void setType(int i, GenType gt){ 114 salcianu 1.1.2.1 types[i] = gt; 115 cananian 1.1.2.3 hash = 0; // invalidate the cashed hash code 116 salcianu 1.1.2.1 } 117 salcianu 1.1.2.1 118 salcianu 1.1.2.1 /** Returns the number of parameters of <code>this</code> metamethod. */ 119 salcianu 1.1.2.1 public int nbParams(){ 120 salcianu 1.1.2.1 return types.length; 121 salcianu 1.1.2.1 } 122 salcianu 1.1.2.1 123 salcianu 1.1.2.1 // some caching hack 124 cananian 1.1.2.3 private transient int hash = 0; 125 salcianu 1.1.2.1 /** Computes the hash code of <code>this</code> object. */ 126 salcianu 1.1.2.1 public int hashCode(){ 127 cananian 1.1.2.3 if(hash != 0) return hash; 128 salcianu 1.1.2.1 hash = hm.hashCode(); 129 salcianu 1.1.2.1 int nb_types = types.length; 130 salcianu 1.1.2.1 for(int i = 0; i < nb_types; i++) 131 salcianu 1.1.2.1 hash += types[i].hashCode(); 132 salcianu 1.1.2.1 return hash; 133 salcianu 1.1.2.1 } 134 salcianu 1.1.2.1 135 salcianu 1.1.2.1 /** Checks the equality of <code>this</code> object with object 136 salcianu 1.1.2.1 <code>o</code>. */ 137 salcianu 1.1.2.1 public boolean equals(Object o){ 138 salcianu 1.1.2.1 if (this == o) return true; 139 salcianu 1.1.2.1 MetaMethod mm2 = (MetaMethod) o; 140 salcianu 1.1.2.1 if(!hm.equals(mm2.hm)) return false; 141 salcianu 1.1.2.1 if(types.length != mm2.types.length) return false; 142 salcianu 1.1.2.1 for(int i = 0; i < types.length ; i++) 143 salcianu 1.1.2.1 if(!types[i].equals(mm2.types[i])) return false; 144 salcianu 1.1.2.1 return true; 145 salcianu 1.1.2.4 } 146 salcianu 1.1.2.4 147 salcianu 1.1.2.4 /** Checks whether two <code>MetaMethod</code>s are equal or not. 148 salcianu 1.1.2.4 handle <code>null</code> arguments. */ 149 salcianu 1.1.2.4 public static boolean identical(MetaMethod mm1, MetaMethod mm2){ 150 salcianu 1.1.2.4 if((mm1 == null) || (mm2 == null)) 151 salcianu 1.1.2.4 return mm1 == mm2; 152 salcianu 1.1.2.4 return mm1.equals(mm2); 153 salcianu 1.1.2.1 } 154 salcianu 1.1.2.1 155 salcianu 1.1.2.1 /** Pretty printer for debug purposes. */ 156 salcianu 1.1.2.1 public String toString(){ 157 salcianu 1.1.2.1 StringBuffer buffer = new StringBuffer(); 158 salcianu 1.1.2.1 buffer.append("< "); 159 salcianu 1.1.2.1 buffer.append(hm); 160 salcianu 1.1.2.1 buffer.append(" | "); 161 salcianu 1.1.2.1 for(int i = 0; i < types.length; i++){ 162 salcianu 1.1.2.1 if(i != 0) buffer.append(" ,"); 163 salcianu 1.1.2.1 buffer.append(types[i]); 164 salcianu 1.1.2.1 } 165 salcianu 1.1.2.1 buffer.append(" >"); 166 salcianu 1.1.2.1 return buffer.toString(); 167 salcianu 1.1.2.1 } 168 salcianu 1.1.2.2 169 salcianu 1.1.2.1 170 cananian 1.2 }