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      }