1 cananian 1.1.2.1 // MZFCompressor.java, created Fri Nov 9 21:23:56 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.4 import harpoon.Backend.Generic.Frame; 8 cananian 1.1.2.3 import harpoon.ClassFile.CachingCodeFactory; 9 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 10 cananian 1.1.2.3 import harpoon.ClassFile.HClassMutator; 11 cananian 1.1.2.3 import harpoon.ClassFile.HCode; 12 cananian 1.1.2.3 import harpoon.ClassFile.HCodeAndMaps; 13 cananian 1.1.2.1 import harpoon.ClassFile.HCodeFactory; 14 cananian 1.1.2.3 import harpoon.ClassFile.HConstructor; 15 cananian 1.1.2.1 import harpoon.ClassFile.HField; 16 cananian 1.1.2.3 import harpoon.ClassFile.HFieldMutator; 17 cananian 1.1.2.9 import harpoon.ClassFile.HInitializer; 18 cananian 1.1.2.3 import harpoon.ClassFile.HMethod; 19 cananian 1.1.2.1 import harpoon.ClassFile.Linker; 20 cananian 1.1.2.3 import harpoon.ClassFile.Relinker; 21 cananian 1.1.2.3 import harpoon.IR.Quads.CONST; 22 cananian 1.1.2.3 import harpoon.IR.Quads.Code; 23 cananian 1.1.2.3 import harpoon.IR.Quads.GET; 24 cananian 1.1.2.3 import harpoon.IR.Quads.Quad; 25 cananian 1.1.2.3 import harpoon.IR.Quads.SET; 26 cananian 1.8 import net.cscott.jutil.SnapshotIterator; 27 cananian 1.8 import net.cscott.jutil.Default; 28 cananian 1.8 import net.cscott.jutil.Default.PairList; 29 cananian 1.1.2.4 import harpoon.Util.ParseUtil; 30 cananian 1.1.2.4 import harpoon.Util.ParseUtil.BadLineException; 31 cananian 1.1.2.4 import harpoon.Util.ParseUtil.StringParser; 32 cananian 1.1.2.3 import harpoon.Util.Util; 33 cananian 1.1.2.1 34 cananian 1.1.2.3 import java.lang.reflect.Modifier; 35 cananian 1.1.2.1 import java.util.ArrayList; 36 cananian 1.1.2.1 import java.util.Arrays; 37 cananian 1.1.2.1 import java.util.Collections; 38 cananian 1.1.2.1 import java.util.Comparator; 39 cananian 1.1.2.3 import java.util.HashMap; 40 cananian 1.1.2.2 import java.util.HashSet; 41 cananian 1.1.2.1 import java.util.Iterator; 42 cananian 1.1.2.1 import java.util.List; 43 cananian 1.1.2.1 import java.util.Map; 44 cananian 1.1.2.2 import java.util.Set; 45 cananian 1.1.2.1 /** 46 cananian 1.1.2.1 * The <code>MZFCompressor</code> class implements a class transformation 47 cananian 1.1.2.1 * aimed at eliminating "mostly-zero" (or "mostly (any constant)") 48 cananian 1.1.2.1 * fields from classes (thus reducing memory consumption). Each class 49 cananian 1.1.2.1 * is transformed into several, each with one additional field added. 50 cananian 1.1.2.1 * Thus we only need allocate fields that this particular instance 51 cananian 1.1.2.1 * will actually use. 52 cananian 1.1.2.1 * 53 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 54 cananian 1.9 * @version $Id: MZFCompressor.java,v 1.9 2004/02/08 03:20:22 cananian Exp $ 55 cananian 1.1.2.1 */ 56 cananian 1.1.2.1 public class MZFCompressor { 57 cananian 1.1.2.5 final HCodeFactory parent; 58 cananian 1.5 final Set<HMethod> callable = new HashSet<HMethod>(); 59 cananian 1.5 final Set<HClass> allClasses = new HashSet<HClass>(); 60 cananian 1.1.2.1 61 cananian 1.1.2.1 /** Creates a <code>MZFCompressor</code>, using the field profiling 62 cananian 1.1.2.1 * information found in the resource at <code>resourcePath</code>. 63 cananian 1.1.2.1 * This resource should be a unprocessed file in the format output 64 cananian 1.1.2.1 * by the <code>SizeCounters</code> package. */ 65 cananian 1.1.2.4 public MZFCompressor(Frame frame, HCodeFactory hcf, ClassHierarchy ch, 66 cananian 1.1.2.1 String resourcePath) { 67 cananian 1.1.2.4 Relinker linker = (Relinker) frame.getLinker(); 68 cananian 1.1.2.1 ConstructorClassifier cc = new ConstructorClassifier(hcf, ch); 69 cananian 1.1.2.1 ProfileParser pp = new ProfileParser(linker, resourcePath); 70 cananian 1.1.2.4 // get 'stop list' of classes we should not touch. 71 cananian 1.5 Set<HClass> stoplist = 72 cananian 1.5 parseStopListResource(frame, "mzf-unsafe.properties"); 73 cananian 1.1.2.3 // process the profile data. 74 cananian 1.1.2.3 // collect all good fields; sort them (within class) by savedbytes. 75 cananian 1.5 Set<HField> flds = new HashSet<HField>(); 76 cananian 1.7 Map<HClass,List<PairList<HField,Number>>> listmap = 77 cananian 1.7 new HashMap<HClass,List<PairList<HField,Number>>>(); 78 cananian 1.9 for (HClass hc : ch.instantiatedClasses()){ 79 cananian 1.1.2.4 if (stoplist.contains(hc)) continue; // skip this class. 80 cananian 1.7 List<PairList<HField,Number>> sorted = sortFields(hc, pp, cc); 81 cananian 1.1.2.3 if (sorted.size()>0) listmap.put(hc, sorted); 82 cananian 1.7 for (Iterator<PairList<HField,Number>> it2=sorted.iterator(); 83 cananian 1.5 it2.hasNext(); ) 84 cananian 1.5 flds.add( (HField) it2.next().get(0) ); 85 cananian 1.1.2.2 } 86 cananian 1.1.2.5 flds = Collections.unmodifiableSet(flds); 87 cananian 1.1.2.5 listmap = Collections.unmodifiableMap(listmap); 88 cananian 1.1.2.8 // before we change any classes (in Field2Method, below) 89 cananian 1.1.2.8 // pull all callable constructors through the ConstructorClassifier 90 cananian 1.1.2.8 // to cache their results. 91 cananian 1.1.2.12 this.callable.addAll(ch.callableMethods()); 92 cananian 1.9 for (HMethod hm : callable) { 93 cananian 1.1.2.8 if (isConstructor(hm)) cc.isGood(hm); 94 cananian 1.1.2.8 } 95 cananian 1.1.2.8 // make accessors for the 'good' fields. 96 cananian 1.1.2.3 Field2Method f2m = new Field2Method(hcf, flds); 97 cananian 1.1.2.3 hcf = new CachingCodeFactory(f2m.codeFactory()); 98 cananian 1.1.2.12 // add getters and setters to 'callable' set. 99 cananian 1.1.2.12 callable.addAll(f2m.getter2field.keySet()); 100 cananian 1.1.2.12 callable.addAll(f2m.setter2field.keySet()); 101 cananian 1.1.2.12 // pull every callable method of each relevant class through hcf 102 cananian 1.9 for (HClass hc : listmap.keySet()) { 103 cananian 1.9 for (HMethod hm : hc.getDeclaredMethods()) { 104 cananian 1.1.2.12 if (callable.contains(hm)) 105 cananian 1.1.2.12 hcf.convert(hm); 106 cananian 1.1.2.12 } 107 cananian 1.1.2.3 } 108 cananian 1.1.2.3 // okay. foreach relevant class, split it. 109 cananian 1.5 Map<HField,HClass> field2class = new HashMap<HField,HClass>(); 110 cananian 1.1.2.13 this.allClasses.addAll(ch.classes()); 111 cananian 1.9 for (HClass hc : listmap.keySet()) { 112 cananian 1.1.2.5 splitOne(linker, (CachingCodeFactory) hcf, 113 cananian 1.5 hc, listmap.get(hc), f2m, field2class); 114 cananian 1.1.2.3 } 115 cananian 1.1.2.5 field2class = Collections.unmodifiableMap(field2class); 116 cananian 1.1.2.5 // chain through MZFWidenType to change INSTANCEOF, ANEW, and 117 cananian 1.1.2.5 // TYPESWITCH quads to use the new supertype of a split class. 118 cananian 1.1.2.13 hcf = new MZFWidenType(hcf,linker, listmap, field2class, 119 cananian 1.1.2.13 callable, allClasses).codeFactory(); 120 cananian 1.1.2.5 // chain through MZFChooser to pick the appropriate superclass 121 cananian 1.1.2.5 // at each instantiation site. 122 cananian 1.1.2.5 hcf = new MZFChooser(hcf, cc, listmap, field2class).codeFactory(); 123 cananian 1.1.2.10 // cache, to be safe. 124 cananian 1.1.2.10 hcf = new CachingCodeFactory(hcf); 125 cananian 1.1.2.10 // now delete fields which we can represent using an external hashtable 126 cananian 1.1.2.11 hcf = new MZFExternalize(hcf,linker, pp, stoplist, flds).codeFactory(); 127 cananian 1.1.2.3 // we should be done now. 128 cananian 1.1.2.6 this.parent = new CachingCodeFactory(hcf); 129 cananian 1.1.2.1 } 130 cananian 1.1.2.1 public HCodeFactory codeFactory() { return parent; } 131 cananian 1.1.2.1 132 cananian 1.1.2.1 /** Return a list. element 0 of the list is the field most likely 133 cananian 1.1.2.1 * to save the most bytes. Elements are pairs; first element is 134 cananian 1.1.2.1 * the field; second element is the 'mostly value'. */ 135 cananian 1.7 List<PairList<HField,Number>> sortFields(HClass hc, ProfileParser pp, 136 cananian 1.5 ConstructorClassifier cc) { 137 cananian 1.1.2.1 // make a comparator that operates on Map.Entries contained in the 138 cananian 1.1.2.10 // ProfileParser's savedBytesMap map, which sorts on 'saved bytes'. 139 cananian 1.1.2.1 final Comparator c = new Comparator() { 140 cananian 1.1.2.1 public int compare(Object o1, Object o2) { 141 cananian 1.1.2.1 // compare based on values in the entry; these 142 cananian 1.1.2.1 // are Longs representing 'saved bytes' 143 cananian 1.1.2.1 return ((Comparable) ((Map.Entry)o1).getValue()) 144 cananian 1.1.2.1 .compareTo(((Map.Entry)o2).getValue()); 145 cananian 1.1.2.1 } 146 cananian 1.1.2.1 }; 147 cananian 1.1.2.1 // okay, now make a list of fields and their maximal 'saved bytes' 148 cananian 1.1.2.1 // mostly-N entry. 149 cananian 1.1.2.1 HField[] flds = hc.getDeclaredFields(); 150 cananian 1.1.2.1 List l = new ArrayList(flds.length); 151 cananian 1.9 for (Object hfO : flds) { 152 cananian 1.9 HField hf = (HField) hfO; 153 cananian 1.1.2.1 // filter out 'bad' fields. 154 cananian 1.1.2.1 if (!cc.isGood(hf)) continue; 155 cananian 1.1.2.2 // some fields have no information? 156 cananian 1.1.2.10 if (pp.savedBytesMap(hf).entrySet().size()==0) 157 cananian 1.1.2.2 // we can end up with no information about a field if it is 158 cananian 1.1.2.2 // instantiable but never actually instantiated in the program 159 cananian 1.1.2.2 // (typically because it is instantiated in native code). 160 cananian 1.1.2.2 continue; // skip these fields. 161 cananian 1.1.2.1 // find the 'mostly value' which will save the most space. 162 cananian 1.1.2.1 Map.Entry me = (Map.Entry) 163 cananian 1.1.2.10 Collections.max(pp.savedBytesMap(hf).entrySet(), c); 164 cananian 1.1.2.1 // add an entry to l for sorting. 165 cananian 1.1.2.1 l.add(Default.pair(hf, me)); 166 cananian 1.1.2.1 } 167 cananian 1.1.2.1 // okay, now sort the fields by saved bytes. 168 cananian 1.1.2.1 Collections.sort(l, new Comparator() { 169 cananian 1.1.2.1 // compare second element of pair. 170 cananian 1.1.2.1 // (negate comparator so largest 'saved bytes' field is first) 171 cananian 1.1.2.1 public int compare(Object o1, Object o2) { 172 cananian 1.1.2.1 return -c.compare(((List)o1).get(1), ((List)o2).get(1)); 173 cananian 1.1.2.1 } 174 cananian 1.1.2.1 }); 175 cananian 1.1.2.1 // finally, create a final list by stripping the 'saved bytes' info 176 cananian 1.1.2.1 // (which we no longer need) and keeping only the field/mostlyN info. 177 cananian 1.7 List<PairList<HField,Number>> nl = 178 cananian 1.7 new ArrayList<PairList<HField,Number>>(l.size()); 179 cananian 1.9 for (Object pairO : l) { 180 cananian 1.9 List pair = (List) pairO; 181 cananian 1.1.2.1 HField hf = (HField) pair.get(0); 182 cananian 1.1.2.1 Map.Entry me = (Map.Entry) pair.get(1); 183 cananian 1.7 Number mostlyN = (Number) me.getKey(); 184 cananian 1.1.2.1 nl.add(Default.pair(hf, mostlyN)); 185 cananian 1.1.2.1 } 186 cananian 1.1.2.3 nl = Collections.unmodifiableList(nl); 187 cananian 1.1.2.1 // ta-da! 188 cananian 1.1.2.3 return nl; 189 cananian 1.1.2.3 } 190 cananian 1.1.2.3 191 cananian 1.1.2.3 // splits one class. 192 cananian 1.1.2.5 void splitOne(Relinker relinker, CachingCodeFactory hcf, 193 cananian 1.7 HClass hc, List<PairList<HField,Number>> sortedFields, 194 cananian 1.5 Field2Method f2m, Map<HField,HClass> field2class) { 195 cananian 1.3.2.1 assert sortedFields.size()>0; 196 cananian 1.1.2.3 // for each entry in the sorted fields list, make a split. 197 cananian 1.7 for (Iterator<PairList<HField,Number>> it=sortedFields.iterator(); 198 cananian 1.5 it.hasNext(); ) { 199 cananian 1.5 List pair = it.next(); 200 cananian 1.1.2.5 hc = moveOne(relinker, hcf, hc, 201 cananian 1.1.2.3 (HField)pair.get(0), 202 cananian 1.1.2.5 ((Number)pair.get(1)).longValue(), 203 cananian 1.1.2.5 f2m, field2class); 204 cananian 1.1.2.13 allClasses.add(hc); 205 cananian 1.1.2.3 } 206 cananian 1.1.2.3 // done! 207 cananian 1.1.2.3 } 208 cananian 1.1.2.3 /** Create a class with all the fields of <code>oldC</code> except for 209 cananian 1.1.2.3 * <code>hf</code>. In the new class, <code>hf</code> has constant 210 cananian 1.1.2.3 * value <code>val</code>. */ 211 cananian 1.1.2.5 HClass moveOne(Relinker relinker, CachingCodeFactory hcf, 212 cananian 1.1.2.5 HClass oldC, HField hf, long val, 213 cananian 1.5 Field2Method f2m, Map<HField,HClass> field2class) { 214 cananian 1.3.2.1 assert !field2class.containsKey(hf); 215 cananian 1.1.2.3 // make a copy of our empty Template class. 216 cananian 1.1.2.3 HClass hcT = relinker.forClass(Template.class); 217 cananian 1.1.2.4 HClass newC = relinker.createMutableClass 218 cananian 1.1.2.4 (oldC.getName()+"$$"+hf.getName(), hcT); 219 cananian 1.1.2.3 // remove all constructors from newC (since we're going to 220 cananian 1.1.2.3 // clone them from oldC) 221 cananian 1.5 for (Iterator<HConstructor> it = 222 cananian 1.5 Arrays.asList(newC.getConstructors()).iterator(); 223 cananian 1.1.2.3 it.hasNext(); ) 224 cananian 1.5 newC.getMutator().removeConstructor(it.next()); 225 cananian 1.1.2.3 // insert this new class between hcS and its superclass. 226 cananian 1.1.2.3 newC.getMutator().setSuperclass(oldC.getSuperclass()); 227 cananian 1.1.2.3 oldC.getMutator().setSuperclass(newC); 228 cananian 1.1.2.3 // move interfaces from oldC to newC. 229 cananian 1.5 for (Iterator<HClass> it = 230 cananian 1.5 Arrays.asList(oldC.getInterfaces()).iterator(); 231 cananian 1.1.2.3 it.hasNext(); ) 232 cananian 1.5 newC.getMutator().addInterface(it.next()); 233 cananian 1.1.2.3 oldC.getMutator().removeAllInterfaces(); 234 cananian 1.1.2.12 // fetch representations for everything callable before we start 235 cananian 1.1.2.12 // messing with the fields. 236 cananian 1.9 for (HMethod hm : oldC.getDeclaredMethods()) { 237 cananian 1.1.2.12 if (callable.contains(hm)) 238 cananian 1.1.2.12 hcf.convert(hm); 239 cananian 1.1.2.12 } 240 cananian 1.1.2.3 // move all but the desired field to newC 241 cananian 1.1.2.3 // (also strip 'private' modifier) 242 cananian 1.1.2.3 HField[] allF = oldC.getDeclaredFields(); 243 cananian 1.1.2.3 for (int i=0; i<allF.length; i++) 244 cananian 1.1.2.3 if (!hf.equals(allF[i])) { 245 cananian 1.1.2.3 relinker.move(allF[i], newC); 246 cananian 1.1.2.3 allF[i].getMutator().removeModifiers(Modifier.PRIVATE); 247 cananian 1.1.2.3 } 248 cananian 1.1.2.4 // move all non-constructor non-static methods of oldC to newC 249 cananian 1.1.2.9 // (move static initializers to newC, since it has the static fields) 250 cananian 1.1.2.12 // copy the constructors. 251 cananian 1.1.2.3 HMethod[] allM = oldC.getDeclaredMethods(); 252 cananian 1.5 HMethod getter = f2m.field2getter.get(hf); 253 cananian 1.5 HMethod setter = f2m.field2setter.get(hf); 254 cananian 1.1.2.3 for (int i=0; i<allM.length; i++) { 255 cananian 1.1.2.9 if (allM[i].isStatic() && !(allM[i] instanceof HInitializer)) 256 cananian 1.1.2.9 continue; 257 cananian 1.1.2.5 if (isConstructor(allM[i])) { 258 cananian 1.1.2.3 // copy, don't move. 259 cananian 1.1.2.5 HMethod newcon = (allM[i] instanceof HConstructor) ? 260 cananian 1.1.2.5 newC.getMutator().addConstructor 261 cananian 1.1.2.5 ((HConstructor)allM[i]) : 262 cananian 1.1.2.5 newC.getMutator().addDeclaredMethod 263 cananian 1.1.2.5 (allM[i].getName(), allM[i]); 264 cananian 1.1.2.13 if (callable.contains(allM[i])) { 265 cananian 1.1.2.13 harpoon.IR.Quads.Code hcode = 266 cananian 1.1.2.13 (harpoon.IR.Quads.Code) hcf.convert(allM[i]); 267 cananian 1.1.2.13 hcf.put(newcon, hcode.clone(newcon).hcode()); 268 cananian 1.1.2.13 callable.add(newcon); 269 cananian 1.1.2.13 } 270 cananian 1.1.2.3 } else relinker.move(allM[i], newC); 271 cananian 1.1.2.3 } 272 cananian 1.1.2.3 // getter and setter are now in newC. copy implementation to oldC. 273 cananian 1.1.2.3 HMethod fullgetter = 274 cananian 1.1.2.3 oldC.getMutator().addDeclaredMethod(getter.getName(), getter); 275 cananian 1.1.2.3 HMethod fullsetter = 276 cananian 1.1.2.3 oldC.getMutator().addDeclaredMethod(setter.getName(), setter); 277 cananian 1.1.2.3 harpoon.IR.Quads.Code gettercode = (harpoon.IR.Quads.Code) 278 cananian 1.1.2.5 hcf.convert(getter); 279 cananian 1.1.2.3 harpoon.IR.Quads.Code settercode = (harpoon.IR.Quads.Code) 280 cananian 1.1.2.5 hcf.convert(setter); 281 cananian 1.1.2.5 hcf.put(fullgetter, gettercode.clone(fullgetter).hcode()); 282 cananian 1.1.2.5 hcf.put(fullsetter, settercode.clone(fullsetter).hcode()); 283 cananian 1.1.2.3 // rewrite newC's getter and setter. 284 cananian 1.1.2.5 hcf.put(getter, makeGetter(hcf, getter, hf, val)); 285 cananian 1.1.2.5 hcf.put(setter, makeSetter(hcf, setter, hf, val)); 286 cananian 1.1.2.12 // add copied oldC getter/setter to callable set. 287 cananian 1.1.2.12 callable.add(fullgetter); 288 cananian 1.1.2.12 callable.add(fullsetter); 289 cananian 1.1.2.3 // done! 290 cananian 1.1.2.5 field2class.put(hf, newC); 291 cananian 1.1.2.3 return newC; 292 cananian 1.1.2.3 } 293 cananian 1.1.2.3 static class Template { } 294 cananian 1.1.2.3 295 cananian 1.1.2.3 /** make a getter method that returns constant 'val'. */ 296 cananian 1.5 HCode<Quad> makeGetter(HCodeFactory hcf, 297 cananian 1.5 HMethod getter, HField hf, long val) { 298 cananian 1.1.2.3 // xxx cheat: get old getter and replace GET with CONST. 299 cananian 1.1.2.3 // would be better to make this from scratch. 300 cananian 1.5 HCode<Quad> hc = hcf.convert(getter); 301 cananian 1.6 for (Iterator<Quad> it=new SnapshotIterator<Quad> 302 cananian 1.6 (hc.getElementsI()); it.hasNext(); ) { 303 cananian 1.6 Quad aquad = it.next(); 304 cananian 1.6 if (aquad instanceof GET) { 305 cananian 1.6 GET q = (GET) aquad; 306 cananian 1.3.2.1 assert q.field().equals(hf); 307 cananian 1.1.2.3 // type of CONST depends on type of hf. 308 cananian 1.1.2.3 HClass type=widen(hf.getType()); 309 cananian 1.1.2.3 CONST nc; 310 cananian 1.1.2.3 if (!type.isPrimitive()) { 311 cananian 1.1.2.3 // pointer. only val==0 makes sense. 312 cananian 1.3.2.1 assert val==0; 313 cananian 1.1.2.3 nc = new CONST(q.getFactory(), q, q.dst(), 314 cananian 1.1.2.3 null, HClass.Void); 315 cananian 1.1.2.3 } else 316 cananian 1.1.2.3 nc = new CONST(q.getFactory(), q, q.dst(), 317 cananian 1.1.2.3 wrap(type, val), type); 318 cananian 1.1.2.3 Quad.replace(q, nc); 319 cananian 1.1.2.3 } 320 cananian 1.6 } 321 cananian 1.1.2.3 // done! 322 cananian 1.1.2.3 return hc; 323 cananian 1.1.2.3 } 324 cananian 1.1.2.6 static HClass widen(HClass hc) { 325 cananian 1.1.2.3 if (hc==HClass.Boolean || hc==HClass.Byte || 326 cananian 1.1.2.3 hc==HClass.Short || hc==HClass.Char) 327 cananian 1.1.2.3 return HClass.Int; 328 cananian 1.1.2.3 else return hc; 329 cananian 1.1.2.3 } 330 cananian 1.1.2.6 static Object wrap(HClass type, long val) { 331 cananian 1.1.2.6 return wrap(type, new Long(val)); 332 cananian 1.1.2.6 } 333 cananian 1.1.2.6 static Object wrap(HClass type, Number n) { 334 cananian 1.3.2.1 assert type.isPrimitive() : type; 335 cananian 1.1.2.3 if (type==HClass.Int) return new Integer(n.intValue()); 336 cananian 1.1.2.3 if (type==HClass.Long) return new Long(n.longValue()); 337 cananian 1.1.2.3 if (type==HClass.Float) return new Float(n.floatValue()); 338 cananian 1.1.2.3 if (type==HClass.Double) return new Double(n.doubleValue()); 339 cananian 1.3.2.1 assert false : ("unknown type: "+type); 340 cananian 1.1.2.3 return null; 341 cananian 1.1.2.3 } 342 cananian 1.1.2.3 /** make a setter method that does nothing (but perhaps verifies 343 cananian 1.1.2.3 * that the value to set is equal to 'val'). */ 344 cananian 1.5 HCode<Quad> makeSetter(HCodeFactory hcf, 345 cananian 1.5 HMethod setter, HField hf, long val) { 346 cananian 1.1.2.3 // xxx cheat: get old setter and remove the SET operand. 347 cananian 1.1.2.3 // would be better to make this from scratch. 348 cananian 1.5 HCode<Quad> hc = hcf.convert(setter); 349 cananian 1.6 for (Iterator<Quad> it=new SnapshotIterator<Quad> 350 cananian 1.6 (hc.getElementsI()); it.hasNext(); ) { 351 cananian 1.6 Quad q = it.next(); 352 cananian 1.6 if (q instanceof SET) 353 cananian 1.6 q.remove(); 354 cananian 1.6 } 355 cananian 1.1.2.3 // done! 356 cananian 1.1.2.3 return hc; 357 cananian 1.1.2.5 } 358 cananian 1.1.2.5 // utility. 359 cananian 1.1.2.5 ///////// copied from harpoon.Analysis.Quads.DefiniteInitOracle. 360 cananian 1.1.2.5 /** return an approximation to whether this is a constructor 361 cananian 1.1.2.5 * or not. it's always safe to return false. */ 362 cananian 1.1.2.5 private static boolean isConstructor(HMethod hm) { 363 cananian 1.1.2.5 // this is tricky, because we want split constructors to 364 cananian 1.1.2.5 // count, too, even though renamed constructors (such as 365 cananian 1.1.2.5 // generated by initcheck, for instance) won't always be 366 cananian 1.1.2.5 // instanceof HConstructor. Look for names starting with 367 cananian 1.1.2.5 // '<init>', as well. 368 cananian 1.1.2.5 if (hm instanceof HConstructor) return true; 369 cananian 1.1.2.5 if (hm.getName().startsWith("<init>")) return true; 370 cananian 1.1.2.5 // XXX: what about methods generated by RuntimeMethod Cloner? 371 cananian 1.1.2.5 // we could try methods ending with <init>, but then the 372 cananian 1.1.2.5 // declaringclass information would be wrong. 373 cananian 1.1.2.5 //if (hm.getName().endsWidth("<init>")) return true;//not safe yet. 374 cananian 1.1.2.5 return false; 375 cananian 1.1.2.4 } 376 cananian 1.1.2.4 //--------------------------------------------- 377 cananian 1.1.2.4 /** Parse a "stop list" of classes we should not attempt to optimize */ 378 cananian 1.5 Set<HClass> parseStopListResource(final Frame frame, String resname) { 379 cananian 1.5 final Set<HClass> stoplist = new HashSet<HClass>(); 380 cananian 1.1.2.4 try { 381 cananian 1.1.2.4 ParseUtil.readResource 382 cananian 1.1.2.4 (frame.getRuntime().resourcePath(resname), 383 cananian 1.1.2.4 new StringParser() { 384 cananian 1.1.2.4 public void parseString(String s) throws BadLineException { 385 cananian 1.1.2.4 stoplist.add(ParseUtil.parseClass(frame.getLinker(), s)); 386 cananian 1.1.2.4 } 387 cananian 1.1.2.4 }); 388 cananian 1.1.2.4 } catch (java.io.IOException ioex) { 389 cananian 1.1.2.4 System.err.println("SKIPPING REST OF "+resname+": "+ioex); 390 cananian 1.1.2.4 } 391 cananian 1.1.2.4 return stoplist; 392 cananian 1.1.2.1 } 393 cananian 1.2 }