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     }