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>&lt;foo,A&gt;</code> while in the second one we call the meta-method
 25 salcianu 1.1.2.1  <code>&lt;foo,B&gt;</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     }