1 cananian 1.1.2.1 // ConstructorClassifier.java, created Thu Nov 8 19:38:41 2001 by cananian 2 cananian 1.1.2.1 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Analysis.SizeOpt; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.Analysis.ClassHierarchy; 7 cananian 1.1.2.7 import harpoon.Analysis.Maps.ConstMap; 8 cananian 1.1.2.2 import harpoon.Analysis.Quads.MustParamOracle; 9 cananian 1.1.2.8 import harpoon.Analysis.Quads.SimpleConstMap; 10 cananian 1.1.2.2 import harpoon.ClassFile.HClass; 11 cananian 1.1.2.2 import harpoon.ClassFile.HCode; 12 cananian 1.1.2.2 import harpoon.ClassFile.HCodeElement; 13 cananian 1.1.2.2 import harpoon.ClassFile.HCodeFactory; 14 cananian 1.1.2.2 import harpoon.ClassFile.HConstructor; 15 cananian 1.1.2.2 import harpoon.ClassFile.HField; 16 cananian 1.1.2.2 import harpoon.ClassFile.HMethod; 17 cananian 1.1.2.2 import harpoon.IR.Quads.CALL; 18 cananian 1.1.2.2 import harpoon.IR.Quads.Quad; 19 cananian 1.1.2.2 import harpoon.IR.Quads.QuadFactory; 20 cananian 1.1.2.2 import harpoon.IR.Quads.SET; 21 cananian 1.1.2.3 import harpoon.Temp.Temp; 22 cananian 1.5 import net.cscott.jutil.AggregateMapFactory; 23 cananian 1.5 import net.cscott.jutil.MapFactory; 24 cananian 1.1.2.2 import harpoon.Util.Util; 25 cananian 1.1.2.1 26 cananian 1.1.2.4 import java.util.Arrays; 27 cananian 1.1.2.2 import java.util.Collections; 28 cananian 1.1.2.2 import java.util.HashMap; 29 cananian 1.1.2.2 import java.util.HashSet; 30 cananian 1.1.2.2 import java.util.Iterator; 31 cananian 1.1.2.4 import java.util.List; 32 cananian 1.1.2.2 import java.util.Map; 33 cananian 1.1.2.2 import java.util.Set; 34 cananian 1.1.2.1 /** 35 cananian 1.1.2.1 * The <code>ConstructorClassifier</code> class takes a look at 36 cananian 1.1.2.1 * constructor invocations and determines whether we can do one 37 cananian 1.1.2.1 * of several 'mostly-zero field' transformations. 38 cananian 1.1.2.1 * 39 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 40 cananian 1.6 * @version $Id: ConstructorClassifier.java,v 1.6 2004/02/08 03:20:22 cananian Exp $ 41 cananian 1.1.2.1 */ 42 cananian 1.1.2.1 public class ConstructorClassifier { 43 cananian 1.1.2.9 private static final boolean STATISTICS=true; 44 cananian 1.1.2.4 private static final boolean DEBUG=false; 45 cananian 1.1.2.1 /* Definitions: 46 cananian 1.1.2.1 * - a 'this-final' field is only written in constructors of its type. 47 cananian 1.1.2.1 * it is not written in subclass constructors. every write within 48 cananian 1.1.2.1 * its constructor *must* be to the 'this' object. 49 cananian 1.1.2.1 * - a 'subclass-final' field is only written in constructors of its type 50 cananian 1.1.2.1 * *and methods of subclasses*. Every write in its own constructors 51 cananian 1.1.2.1 * must be to the 'this' object as before. 52 cananian 1.1.2.1 * 53 cananian 1.1.2.1 * classes with 'subclass' final fields can be split into a 'small' 54 cananian 1.1.2.1 * version without the field, which is the superclass of a 'large' version 55 cananian 1.1.2.1 * with the field (and a setter method). Subclasses of the original 56 cananian 1.1.2.1 * class extend the 'large' version and so can write the extra field. 57 cananian 1.1.2.1 */ 58 cananian 1.1.2.2 private final HCodeFactory hcf; 59 cananian 1.1.2.4 private final ClassHierarchy ch; 60 cananian 1.1.2.2 private final MapFactory mf = new AggregateMapFactory(); 61 cananian 1.1.2.2 private final Set badFields; 62 cananian 1.1.2.9 /** statistics */ 63 cananian 1.1.2.9 private int one_constructor=0, one_const_field=0, one_param_field=0; 64 cananian 1.1.2.1 65 cananian 1.1.2.1 /** Creates a <code>ConstructorClassifier</code>. */ 66 cananian 1.1.2.2 public ConstructorClassifier(HCodeFactory hcf, ClassHierarchy ch) { 67 cananian 1.1.2.2 this.hcf = hcf; 68 cananian 1.1.2.4 this.ch = ch; 69 cananian 1.1.2.1 // first, find all the 'subclass-final' fields in the program. 70 cananian 1.1.2.1 // actually, we find the dual of this set. 71 cananian 1.1.2.2 this.badFields = findBadFields(hcf, ch); 72 cananian 1.1.2.2 // we're done! (the rest of the analysis is demand-driven) 73 cananian 1.1.2.4 if (DEBUG) { 74 cananian 1.1.2.4 // debug: 75 cananian 1.1.2.4 System.out.println("BAD FIELDS: "+badFields); 76 cananian 1.1.2.4 System.out.println("CONSTRUCTOR RESULTS:"); 77 cananian 1.6 for (Object hmO : ch.callableMethods()) { 78 cananian 1.6 HMethod hm = (HMethod) hmO; 79 cananian 1.1.2.4 if (!isConstructor(hm)) continue; 80 cananian 1.1.2.4 System.out.println(" "+hm+": "+classifyMethod(hm)); 81 cananian 1.1.2.4 } 82 cananian 1.1.2.4 } 83 cananian 1.1.2.9 // STATISTICS! 84 cananian 1.1.2.9 if (STATISTICS) { 85 cananian 1.6 for (Object hmO : ch.callableMethods()) { 86 cananian 1.6 HMethod hm = (HMethod) hmO; 87 cananian 1.1.2.9 if (isConstructor(hm)) classifyMethod(hm); 88 cananian 1.1.2.9 } 89 cananian 1.1.2.9 System.out.println("CLASSIFIER: "+one_constructor+" constructors, "+one_const_field+" have a constant, and "+one_param_field+" have a parameter-dependent, field."); 90 cananian 1.1.2.9 } 91 cananian 1.1.2.4 } 92 cananian 1.1.2.4 /** Returns <code>true</code> iff the given field is 'subclass-final' 93 cananian 1.1.2.4 * and there is at least one callable constructor where the field's 94 cananian 1.1.2.4 * content can be predicted. 95 cananian 1.1.2.4 */ 96 cananian 1.1.2.4 public boolean isGood(HField hf) { 97 cananian 1.1.2.4 if (hf.isStatic()) return false; 98 cananian 1.1.2.4 if (badFields.contains(hf)) return false; 99 cananian 1.1.2.4 // get declared methods of class (should include all constructors) 100 cananian 1.1.2.4 List l = Arrays.asList(hf.getDeclaringClass().getDeclaredMethods()); 101 cananian 1.1.2.4 // for each callable constructor... 102 cananian 1.6 for (Object hmO : l) { 103 cananian 1.6 HMethod hm = (HMethod) hmO; 104 cananian 1.1.2.4 if (!ch.callableMethods().contains(hm)) continue; 105 cananian 1.1.2.2 if (!isConstructor(hm)) continue; 106 cananian 1.1.2.4 // okay, hm is a callable constructor. 107 cananian 1.1.2.4 Map map = classifyMethod(hm); 108 cananian 1.1.2.4 if (!map.containsKey(hf) || 109 cananian 1.1.2.4 ((Classification) map.get(hf)).isGood()) 110 cananian 1.1.2.4 return true; // this is a good field. 111 cananian 1.1.2.2 } 112 cananian 1.1.2.4 return false; // nothing good about this. 113 cananian 1.1.2.1 } 114 cananian 1.1.2.5 /** Returns <code>true</code> iff there is at least one field whose 115 cananian 1.1.2.5 * value can be predicted when this constructor is called. */ 116 cananian 1.1.2.5 public boolean isGood(HMethod constructor) { 117 cananian 1.3.2.1 assert isConstructor(constructor); 118 cananian 1.1.2.5 Map m = classifyMethod(constructor); 119 cananian 1.1.2.5 for (Iterator it=m.values().iterator(); it.hasNext(); ) 120 cananian 1.1.2.5 if (((Classification)it.next()).isGood()) return true; 121 cananian 1.1.2.5 return false; 122 cananian 1.1.2.5 } 123 cananian 1.1.2.5 /** Returns <code>true</code> iff the given field <code>hf</code> 124 cananian 1.1.2.5 * is always set to a constant value when the given constructor 125 cananian 1.1.2.5 * is executed. */ 126 cananian 1.1.2.5 public boolean isConstant(HMethod constructor, HField hf) { 127 cananian 1.1.2.5 Classification c = (Classification) 128 cananian 1.1.2.5 classifyMethod(constructor).get(hf); 129 cananian 1.1.2.5 // if null, that means this is always '0' 130 cananian 1.1.2.5 return (c==null) || c.isConstant; 131 cananian 1.1.2.5 } 132 cananian 1.1.2.5 /** Returns the constant value which field <code>hf</code> is 133 cananian 1.1.2.5 * set to whenever the given constructor is executed. Requires 134 cananian 1.1.2.5 * that <code>isConstant(constructor,hf)</code> be <code>true</code>. 135 cananian 1.1.2.5 */ 136 cananian 1.1.2.5 public Object constantValue(HMethod constructor, HField hf) { 137 cananian 1.3.2.1 assert isConstant(constructor, hf); 138 cananian 1.1.2.5 Classification c = (Classification) 139 cananian 1.1.2.5 classifyMethod(constructor).get(hf); 140 cananian 1.1.2.5 return (c==null) ? makeZero(hf.getType()) : c.constant; 141 cananian 1.1.2.5 } 142 cananian 1.1.2.5 /** Returns <code>true</code> iff the given field <code>hf</code> 143 cananian 1.1.2.5 * is always set to the same value as one of the constructor's 144 cananian 1.1.2.5 * parameters whenever it is executed. */ 145 cananian 1.1.2.5 public boolean isParam(HMethod constructor, HField hf) { 146 cananian 1.1.2.5 Classification c = (Classification) 147 cananian 1.1.2.5 classifyMethod(constructor).get(hf); 148 cananian 1.1.2.5 return (c!=null) && (c.param!=-1); 149 cananian 1.1.2.5 } 150 cananian 1.1.2.5 /** Returns the number of the parameter (starting at 0) which 151 cananian 1.1.2.5 * holds the value which <code>hf</code> will be set to whenever 152 cananian 1.1.2.5 * the given constructor is executed. Requires that 153 cananian 1.1.2.5 * <code>isParam(constructor, hf</code> be <code>true</code>. 154 cananian 1.1.2.5 */ 155 cananian 1.1.2.5 public int paramNumber(HMethod constructor, HField hf) { 156 cananian 1.1.2.5 Classification c = (Classification) 157 cananian 1.1.2.5 classifyMethod(constructor).get(hf); 158 cananian 1.1.2.5 return c.param; 159 cananian 1.1.2.5 } 160 cananian 1.1.2.5 /** Find fields which are *not* subclass-final. */ 161 cananian 1.1.2.2 private Set findBadFields(HCodeFactory hcf, ClassHierarchy ch) { 162 cananian 1.1.2.1 Set badFields = new HashSet(); 163 cananian 1.1.2.1 // for each callable method... 164 cananian 1.6 for (Object hmO : ch.callableMethods()) { 165 cananian 1.6 HMethod hm = (HMethod) hmO; 166 cananian 1.1.2.1 HCode hc = hcf.convert(hm); 167 cananian 1.1.2.1 if (hc==null) continue; // xxx: native methods may write fields! 168 cananian 1.1.2.1 // construct a must-param oracle for constructors. 169 cananian 1.1.2.1 MustParamOracle mpo = 170 cananian 1.1.2.1 isConstructor(hm) ? new MustParamOracle(hc) : null; 171 cananian 1.1.2.1 // examine this method for writes 172 cananian 1.1.2.1 HClass thisClass = hc.getMethod().getDeclaringClass(); 173 cananian 1.1.2.1 for (Iterator it2=hc.getElementsI(); it2.hasNext(); ) { 174 cananian 1.1.2.1 Quad q = (Quad) it2.next(); 175 cananian 1.1.2.1 if (q instanceof SET) { 176 cananian 1.1.2.1 SET qq = (SET) q; 177 cananian 1.1.2.1 // ignore writes of static fields. 178 cananian 1.1.2.1 if (qq.isStatic()) continue; 179 cananian 1.1.2.1 // if this is a constructor, than it may write only 180 cananian 1.1.2.1 // to fields of 'this' 181 cananian 1.1.2.1 if (isConstructor(hm) && 182 cananian 1.1.2.1 mpo.isMustParam(qq.objectref()) && 183 cananian 1.1.2.1 mpo.whichMustParam(qq.objectref())==0) 184 cananian 1.1.2.1 continue; // this is a permitted write. 185 cananian 1.1.2.1 // writes by subclass methods to superclass fields are 186 cananian 1.1.2.1 // okay. (but not writes by 'this' methods to 'this' 187 cananian 1.1.2.1 // fields, unless the method is a constructor) 188 cananian 1.1.2.1 if (qq.field().getDeclaringClass() 189 cananian 1.1.2.1 .isInstanceOf(thisClass) && 190 cananian 1.3.2.2 // XXX i think the presence of the 'isConstructor' 191 cananian 1.3.2.2 // clause here is a bug. constructor writes 192 cananian 1.3.2.2 // should be taken care of by clause above. 193 cananian 1.1.2.1 (isConstructor(hm) || 194 cananian 1.1.2.1 !thisClass.equals(qq.field().getDeclaringClass()))) 195 cananian 1.1.2.1 continue; // subclass writes are permitted. 196 cananian 1.1.2.1 // non-permitted write! 197 cananian 1.1.2.1 badFields.add(qq.field()); 198 cananian 1.1.2.1 } 199 cananian 1.1.2.1 } 200 cananian 1.1.2.1 // on to the next! 201 cananian 1.1.2.1 } 202 cananian 1.1.2.1 // done! we have set of all bad (not subclass-final) fields. 203 cananian 1.1.2.1 return Collections.unmodifiableSet(badFields); 204 cananian 1.1.2.1 } 205 cananian 1.1.2.2 206 cananian 1.1.2.2 // per-constructor analysis..... 207 cananian 1.1.2.2 208 cananian 1.1.2.2 static class Classification { 209 cananian 1.1.2.2 int param; // -1 means 'not a param' 210 cananian 1.1.2.5 boolean isConstant; // false means 'not a constant' 211 cananian 1.1.2.5 Object constant; // if constant, then constant value. 'null' is legal. 212 cananian 1.1.2.5 Classification() { this.param=-1; this.isConstant=false; } 213 cananian 1.1.2.5 Classification(int param) { this.param=param; this.isConstant=false; } 214 cananian 1.1.2.5 Classification(Object constant) { 215 cananian 1.1.2.5 this.param=-1; this.isConstant=true; this.constant=constant; 216 cananian 1.1.2.5 } 217 cananian 1.1.2.5 boolean isGood() { return param>=0 || isConstant; } 218 cananian 1.1.2.2 void merge(Classification c) { 219 cananian 1.1.2.2 if (this.param != c.param || 220 cananian 1.1.2.5 this.isConstant != c.isConstant || 221 cananian 1.1.2.5 (this.isConstant && 222 cananian 1.1.2.5 (this.constant==null ? this.constant!=c.constant : 223 cananian 1.1.2.5 !this.constant.equals(c.constant)))) { 224 cananian 1.1.2.2 // goes to top. 225 cananian 1.1.2.5 this.param=-1; this.isConstant=false; 226 cananian 1.1.2.2 } 227 cananian 1.1.2.2 } 228 cananian 1.1.2.3 /** Take this classification and filter it through a mapping 229 cananian 1.1.2.3 * of params to other classifications. */ 230 cananian 1.1.2.3 void map(Classification[] mapping) { 231 cananian 1.1.2.3 if (this.param==-1) return; // not a parameter! nothing to do! 232 cananian 1.1.2.3 int p = this.param; // entry in the mapping to utilize. 233 cananian 1.1.2.3 // make this a clone of mapping[p] 234 cananian 1.1.2.3 this.param = mapping[p].param; 235 cananian 1.1.2.5 this.isConstant = mapping[p].isConstant; 236 cananian 1.1.2.3 this.constant = mapping[p].constant; 237 cananian 1.1.2.3 return; // done. 238 cananian 1.1.2.3 } 239 cananian 1.1.2.6 public Object clone() { 240 cananian 1.1.2.6 if (this.param>=0) return new Classification(this.param); 241 cananian 1.1.2.6 if (this.isConstant) return new Classification(this.constant); 242 cananian 1.1.2.6 return new Classification(); 243 cananian 1.1.2.6 } 244 cananian 1.1.2.2 public String toString() { 245 cananian 1.3.2.1 assert !(param>0 && constant!=null); 246 cananian 1.1.2.2 if (param>0) return "PARAM#"+param; 247 cananian 1.1.2.5 if (isConstant) return "CONSTANT "+constant; 248 cananian 1.1.2.2 return "NO INFO"; 249 cananian 1.1.2.2 } 250 cananian 1.1.2.2 } 251 cananian 1.1.2.7 Classification makeClassification(ConstMap cm, MustParamOracle mpo, 252 cananian 1.1.2.3 HCodeElement hce, Temp t) { 253 cananian 1.1.2.7 if (cm.isConst(hce, t)) // constant value? 254 cananian 1.1.2.7 return new Classification(cm.constMap(hce, t)); 255 cananian 1.1.2.3 if (mpo.isMustParam(t)) // must be a parameter? 256 cananian 1.1.2.3 return new Classification(mpo.whichMustParam(t)); 257 cananian 1.1.2.3 return new Classification(); // no info 258 cananian 1.1.2.3 } 259 cananian 1.1.2.3 260 cananian 1.1.2.2 /** caching infrastructure around 'doOne' */ 261 cananian 1.1.2.2 Map classifyMethod(HMethod hm) { 262 cananian 1.3.2.1 assert isConstructor(hm); 263 cananian 1.1.2.2 if (!cache.containsKey(hm)) { 264 cananian 1.1.2.2 HCode hc = hcf.convert(hm); 265 cananian 1.3.2.1 assert hc!=null; 266 cananian 1.1.2.2 cache.put(hm, doOne(hc)); 267 cananian 1.1.2.2 } 268 cananian 1.1.2.2 return (Map) cache.get(hm); 269 cananian 1.1.2.2 } 270 cananian 1.1.2.2 private final Map cache = new HashMap(); 271 cananian 1.1.2.2 272 cananian 1.1.2.2 /** returns a map from hfields to classification objects */ 273 cananian 1.1.2.2 private Map doOne(HCode hc) { 274 cananian 1.1.2.2 Map map = mf.makeMap(); 275 cananian 1.1.2.2 HMethod hm = hc.getMethod(); 276 cananian 1.3.2.1 assert isConstructor(hm); 277 cananian 1.1.2.2 HClass thisClass = hm.getDeclaringClass(); 278 cananian 1.1.2.8 // first, get a SimpleConstMap 279 cananian 1.1.2.8 ConstMap cm = new SimpleConstMap(hc); 280 cananian 1.1.2.2 // also create a MustParamOracle 281 cananian 1.1.2.2 MustParamOracle mpo = new MustParamOracle(hc); 282 cananian 1.1.2.2 // look at every SET and CALL. 283 cananian 1.1.2.2 for (Iterator it=hc.getElementsI(); it.hasNext(); ) { 284 cananian 1.1.2.2 Quad q = (Quad) it.next(); 285 cananian 1.1.2.2 if (q instanceof SET) { 286 cananian 1.1.2.2 SET qq = (SET) q; 287 cananian 1.1.2.2 // field set. 288 cananian 1.1.2.2 if (qq.field().getDeclaringClass().equals(thisClass)) { 289 cananian 1.1.2.2 Classification oc = (Classification) map.get(qq.field()); 290 cananian 1.1.2.2 // okay, is the value we're setting a constant? or param? 291 cananian 1.1.2.3 Classification nc = 292 cananian 1.1.2.8 makeClassification(cm, mpo, qq, qq.src()); 293 cananian 1.1.2.2 // XXX: CAN MERGE const with param if the const is 294 cananian 1.1.2.2 // the 'right' value (the one we're optimizing for) 295 cananian 1.1.2.2 if (oc!=null) //null means we haven't seen this field yet. 296 cananian 1.1.2.2 nc.merge(oc); 297 cananian 1.1.2.2 map.put(qq.field(), nc); 298 cananian 1.1.2.2 } 299 cananian 1.1.2.2 } 300 cananian 1.1.2.2 if (q instanceof CALL) { 301 cananian 1.1.2.2 // deal with call to 'this' constructor. 302 cananian 1.1.2.2 CALL qq = (CALL) q; 303 cananian 1.1.2.2 if (isThisConstructor(qq.method(), qq)) { 304 cananian 1.1.2.2 // recursively invoke! 305 cananian 1.1.2.2 Map m = classifyMethod(qq.method()); // this should cache. 306 cananian 1.1.2.3 // construct parameter mapping. 307 cananian 1.1.2.3 Classification pc[]= new Classification[qq.paramsLength()]; 308 cananian 1.1.2.3 for (int i=0; i<pc.length; i++) 309 cananian 1.1.2.8 pc[i] = makeClassification(cm, mpo, qq, qq.params(i)); 310 cananian 1.1.2.3 // filter method's classifications through the mapping and 311 cananian 1.1.2.3 // merge with our previous classifications. 312 cananian 1.6 for (Object meO : m.entrySet()){ 313 cananian 1.6 Map.Entry me = (Map.Entry) meO; 314 cananian 1.1.2.2 HField hf = (HField) me.getKey(); 315 cananian 1.1.2.2 Classification oc = (Classification) map.get(hf); 316 cananian 1.1.2.2 Classification nc = (Classification) me.getValue(); 317 cananian 1.1.2.6 // clone nc so we don't modify value in 'm'! 318 cananian 1.1.2.6 nc = (Classification) nc.clone(); 319 cananian 1.1.2.6 // map method's params to this' params. 320 cananian 1.1.2.6 nc.map(pc); 321 cananian 1.1.2.2 if (oc!=null) 322 cananian 1.1.2.3 nc.merge(oc); // merge if necessary. 323 cananian 1.1.2.2 map.put(hf, nc); 324 cananian 1.1.2.2 } 325 cananian 1.1.2.2 } 326 cananian 1.1.2.2 } 327 cananian 1.1.2.2 } 328 cananian 1.1.2.9 // collect statistics. 329 cananian 1.1.2.9 if (STATISTICS) { 330 cananian 1.1.2.9 boolean has_const=false, has_param=false; 331 cananian 1.6 for (Object cO : map.values()) { 332 cananian 1.6 Classification c = (Classification) cO; 333 cananian 1.1.2.9 if (c.param!=-1) has_param=true; 334 cananian 1.1.2.9 if (c.isConstant) has_const=true; 335 cananian 1.1.2.9 } 336 cananian 1.1.2.9 if (has_param) one_param_field++; 337 cananian 1.1.2.9 if (has_const) one_const_field++; 338 cananian 1.1.2.9 one_constructor++; 339 cananian 1.1.2.9 } 340 cananian 1.1.2.9 // okay, we're done! 341 cananian 1.1.2.2 return Collections.unmodifiableMap(map); 342 cananian 1.1.2.2 } 343 cananian 1.1.2.1 344 cananian 1.1.2.5 // make a wrapped 'zero' value of the specified type. 345 cananian 1.1.2.5 private Object makeZero(HClass hc) { 346 cananian 1.1.2.5 if (!hc.isPrimitive()) return null; 347 cananian 1.1.2.5 if (hc==HClass.Boolean || hc==HClass.Byte || 348 cananian 1.1.2.5 hc==HClass.Short || hc==HClass.Char || 349 cananian 1.1.2.5 hc==HClass.Int) return new Integer(0); 350 cananian 1.1.2.5 if (hc==HClass.Long) return new Long(0); 351 cananian 1.1.2.5 if (hc==HClass.Float) return new Float(0); 352 cananian 1.1.2.5 if (hc==HClass.Double) return new Double(0); 353 cananian 1.3.2.1 assert false : ("unknown type: "+hc); 354 cananian 1.1.2.5 return null; 355 cananian 1.1.2.5 } 356 cananian 1.1.2.1 ///////// copied from harpoon.Analysis.Quads.DefiniteInitOracle. 357 cananian 1.1.2.1 /** return a conservative approximation to whether this is a constructor 358 cananian 1.1.2.1 * or not. it's always safe to return true. */ 359 cananian 1.1.2.2 private boolean isConstructor(HMethod hm) { 360 cananian 1.1.2.1 // this is tricky, because we want split constructors to count, too, 361 cananian 1.1.2.1 // even though renamed constructors (such as generated by initcheck, 362 cananian 1.1.2.1 // for instance) won't always be instanceof HConstructor. Look 363 cananian 1.1.2.1 // for names starting with '<init>', as well. 364 cananian 1.1.2.1 if (hm instanceof HConstructor) return true; 365 cananian 1.1.2.1 if (hm.getName().startsWith("<init>")) return true; 366 cananian 1.1.2.1 // XXX: what about methods generated by RuntimeMethod Cloner? 367 cananian 1.1.2.1 // we could try methods ending with <init>, but then the 368 cananian 1.1.2.1 // declaringclass information would be wrong. 369 cananian 1.1.2.1 //if (hm.getName().endsWidth("<init>")) return true;//not safe yet. 370 cananian 1.1.2.1 return false; 371 cananian 1.1.2.1 } 372 cananian 1.1.2.2 /** Is this a 'this' constructor? Safe to return false if unsure. */ 373 cananian 1.1.2.2 private boolean isThisConstructor(HMethod hm, HCodeElement me) { 374 cananian 1.1.2.2 return isConstructor(hm) && // assumes this method is precise. 375 cananian 1.1.2.2 hm.getDeclaringClass().equals 376 cananian 1.1.2.2 (((Quad)me).getFactory().getMethod().getDeclaringClass()); 377 cananian 1.1.2.2 } 378 cananian 1.1.2.2 /** Is this a super constructor? Safe to return false if unsure. */ 379 cananian 1.1.2.2 private boolean isSuperConstructor(HMethod hm, HCodeElement me) { 380 cananian 1.1.2.2 return isConstructor(hm) && // assumes this method is precise. 381 cananian 1.1.2.2 hm.getDeclaringClass().equals 382 cananian 1.1.2.2 (((Quad)me).getFactory().getMethod().getDeclaringClass() 383 cananian 1.1.2.2 .getSuperclass()); 384 cananian 1.1.2.2 } 385 cananian 1.1.2.2 386 cananian 1.2 }