1 salcianu 1.12 
  2 salcianu 1.1  // PreallocOpt.java, created Tue Nov 26 16:19:50 2002 by salcianu
  3 salcianu 1.1  // Copyright (C) 2000 Alexandru Salcianu <salcianu@MIT.EDU>
  4 salcianu 1.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  5 salcianu 1.1  package harpoon.Analysis.MemOpt;
  6 salcianu 1.1  
  7 salcianu 1.1  import java.util.Map;
  8 salcianu 1.1  import java.util.HashMap;
  9 salcianu 1.1  import java.util.Iterator;
 10 salcianu 1.1  import java.util.Collection;
 11 salcianu 1.1  import java.util.Set;
 12 salcianu 1.1  import java.util.HashSet;
 13 salcianu 1.3  import java.util.List;
 14 salcianu 1.3  import java.util.LinkedList;
 15 salcianu 1.18 import java.lang.reflect.Modifier;
 16 salcianu 1.1  
 17 salcianu 1.1  import harpoon.ClassFile.HClass;
 18 salcianu 1.4  import harpoon.ClassFile.HCodeElement;
 19 salcianu 1.1  import harpoon.ClassFile.HClassMutator;
 20 salcianu 1.1  import harpoon.ClassFile.HField;
 21 salcianu 1.1  import harpoon.ClassFile.HMethod;
 22 salcianu 1.1  import harpoon.ClassFile.Linker;
 23 salcianu 1.1  import harpoon.ClassFile.HCode;
 24 salcianu 1.16 import harpoon.ClassFile.HData;
 25 salcianu 1.1  import harpoon.ClassFile.HCodeFactory;
 26 salcianu 1.1  import harpoon.ClassFile.CachingCodeFactory;
 27 salcianu 1.1  import harpoon.ClassFile.SerializableCodeFactory;
 28 salcianu 1.1  
 29 salcianu 1.1  import harpoon.IR.Quads.QuadNoSSA;
 30 salcianu 1.1  import harpoon.IR.Quads.QuadSSI;
 31 salcianu 1.1  import harpoon.IR.Quads.QuadWithTry;
 32 salcianu 1.1  import harpoon.IR.Quads.NEW;
 33 salcianu 1.18 import harpoon.IR.Quads.METHOD;
 34 salcianu 1.18 import harpoon.IR.Quads.HEADER;
 35 salcianu 1.18 import harpoon.IR.Quads.RETURN;
 36 salcianu 1.18 import harpoon.IR.Quads.FOOTER;
 37 salcianu 1.16 import harpoon.IR.Quads.Quad;
 38 salcianu 1.18 import harpoon.IR.Quads.QuadWithTry;
 39 salcianu 1.4  import harpoon.IR.Quads.Code;
 40 salcianu 1.1  
 41 salcianu 1.1  import harpoon.Analysis.ClassHierarchy;
 42 salcianu 1.1  import harpoon.Analysis.Quads.CallGraph;
 43 salcianu 1.1  import harpoon.Analysis.MetaMethods.SmartCallGraph;
 44 salcianu 1.1  import harpoon.Analysis.MetaMethods.MetaCallGraphImpl;
 45 salcianu 1.4  import harpoon.Analysis.Maps.AllocationInformation;
 46 salcianu 1.4  import harpoon.Analysis.Maps.AllocationInformation.AllocationProperties;
 47 salcianu 1.12 import harpoon.Analysis.ChainedAllocationProperties;
 48 salcianu 1.4  import harpoon.Analysis.AllocationInformationMap;
 49 salcianu 1.12 import harpoon.Analysis.DefaultAllocationInformationMap;
 50 salcianu 1.4  import harpoon.Analysis.DefaultAllocationInformation;
 51 salcianu 1.11 import harpoon.Instrumentation.AllocationStatistics.AllocationStatistics;
 52 salcianu 1.20 import harpoon.Instrumentation.AllocationStatistics.AllocationInstrCompStage;
 53 salcianu 1.4  import harpoon.Analysis.Tree.Canonicalize;
 54 salcianu 1.4  import harpoon.Backend.Generic.Frame;
 55 salcianu 1.12 import harpoon.Backend.Generic.Runtime;
 56 salcianu 1.16 import harpoon.Temp.Label;
 57 salcianu 1.4  import harpoon.Temp.Temp;
 58 salcianu 1.1  
 59 salcianu 1.14 import harpoon.Util.Util;
 60 salcianu 1.14 
 61 salcianu 1.20 import harpoon.Main.CompilerStageEZ;
 62 salcianu 1.20 import harpoon.Util.Options.Option;
 63 salcianu 1.20 
 64 salcianu 1.1  /**
 65 salcianu 1.1   * <code>PreallocOpt</code>
 66 salcianu 1.1   * 
 67 salcianu 1.1   * @author  Alexandru Salcianu <salcianu@MIT.EDU>
 68 cananian 1.25  * @version $Id: PreallocOpt.java,v 1.25 2004/02/08 03:19:53 cananian Exp $
 69 salcianu 1.1   */
 70 salcianu 1.4  public abstract class PreallocOpt {
 71 salcianu 1.4  
 72 salcianu 1.5      /** If <code>true</code>, the compiler uses the static memory
 73 salcianu 1.5          pre-allocation optimization (via
 74 salcianu 1.5          <code>IncompatibilityAnalysis</code>.  Default is
 75 salcianu 1.5          <code>false</code>. */
 76 salcianu 1.4      public static boolean PREALLOC_OPT = false;
 77 salcianu 1.1  
 78 salcianu 1.16     /** Use the incompatibility analysis only to remove
 79 salcianu 1.16         syncronizations on the objects that can be preallocated (but
 80 salcianu 1.16         don't actually preallocate them).
 81 salcianu 1.16         
 82 salcianu 1.16         Useful when we want to measure the reduction of the memory
 83 salcianu 1.16         management overhead: the optimized program has to remove syncs
 84 salcianu 1.16         on the preallocated objects (for complicated reasons,
 85 salcianu 1.16         inflating them would make it crsah).  Therefore we want the
 86 salcianu 1.16         normal version to run without syncs on the preallocatable
 87 salcianu 1.16         objects, too. */
 88 salcianu 1.16     public static boolean ONLY_SYNC_REMOVAL = false;
 89 salcianu 1.16 
 90 salcianu 1.16     /** If true, we do not preallocate allocation sites whose unique
 91 salcianu 1.16         identifier is not between <code>lowBound</cde> and
 92 salcianu 1.16         <code>highBound</code>.  (The unique id is obtained from a
 93 salcianu 1.16         <code>AllocationStatistics</code> object. */
 94 salcianu 1.16     public static boolean RANGE_DEBUG = false;
 95 salcianu 1.16     // used for debugging code
 96 salcianu 1.16     public static int lowBound  = 0;
 97 salcianu 1.16     public static int highBound = 200000;
 98 salcianu 1.16 
 99 salcianu 1.14     /** Set this to true only if you use the hacked BDW GC version
100 salcianu 1.14         that has "GC_malloc_prealloc".  */
101 salcianu 1.16     public static boolean HACKED_GC = true;
102 salcianu 1.14 
103 salcianu 1.16     /** Map used by the optimization: assigns to each label the size
104 salcianu 1.16         of the pre-allocated memory chunk that that label points to
105 salcianu 1.16         (at runtime). */
106 salcianu 1.16     private static Map/*<Label,Integer>*/ label2size;
107 salcianu 1.18     /** Label for the beginning of the static data that holds the
108 salcianu 1.18         pointers to preallocated memory. */
109 salcianu 1.16     private static Label beginLabel = new Label("ptr2preallocmem_BEGIN");
110 salcianu 1.18     /** Label for the end of the static data that holds the pointers
111 salcianu 1.18         to preallocated memory. */
112 salcianu 1.16     private static Label endLabel   = new Label("ptr2preallocmem_END");
113 salcianu 1.5  
114 salcianu 1.16     /** Root for the names of the labels corresponding to locations
115 salcianu 1.16         that point (at runtime) to the pre-allocated memory chunks. */
116 salcianu 1.16     private static final String LABEL_ROOT_NAME = "ptr2preallocmem_";
117 salcianu 1.5  
118 salcianu 1.5      /** Name of the method that preallocates the memory chunks and
119 salcianu 1.5          initializes the static fields to point to them. */
120 salcianu 1.5      private static final String INIT_FIELDS_METHOD_NAME = "initFields";
121 salcianu 1.5  
122 salcianu 1.5  
123 salcianu 1.5      /** Adds to the set of roots the classes/methods that are called
124 salcianu 1.5          by the runtime when the preallocation optimization is used.
125 salcianu 1.5  
126 salcianu 1.5          @param roots set of roots
127 salcianu 1.5          @param linker linker used to get classes */
128 salcianu 1.5      public static void updateRoots(Set roots, Linker linker) {
129 salcianu 1.17 
130 salcianu 1.17         System.out.println("\n\nUPDATE ROOTS CALLED!\n");
131 salcianu 1.17 
132 salcianu 1.18         initMethod = 
133 salcianu 1.18             linker.forName("java.lang.Object").getMutator().addDeclaredMethod
134 salcianu 1.18             (INIT_FIELDS_METHOD_NAME, "()V");
135 salcianu 1.18         initMethod.getMutator().setModifiers
136 salcianu 1.18             (java.lang.reflect.Modifier.STATIC |
137 salcianu 1.18              java.lang.reflect.Modifier.PUBLIC |
138 salcianu 1.18              java.lang.reflect.Modifier.FINAL);
139 salcianu 1.18 
140 salcianu 1.18         System.out.println("Added initMethod = \"" + initMethod + "\"");
141 salcianu 1.18 
142 salcianu 1.18         roots.add(initMethod);
143 salcianu 1.5      }
144 salcianu 1.18     // method called at runtime to initialize the preallocated memory
145 salcianu 1.18     private static HMethod initMethod = null;
146 salcianu 1.5  
147 salcianu 1.18 
148 salcianu 1.18     private static class HCFWithEmptyInitMethod implements HCodeFactory {
149 salcianu 1.18         public HCFWithEmptyInitMethod(HCodeFactory parent_hcf) {
150 salcianu 1.18             this.parent_hcf = parent_hcf;
151 salcianu 1.18         }
152 salcianu 1.18         private final HCodeFactory parent_hcf;
153 salcianu 1.18         public void clear(HMethod hm) { parent_hcf.clear(hm); }
154 salcianu 1.18         public String getCodeName() { return parent_hcf.getCodeName(); }
155 salcianu 1.18         public HCode convert(HMethod hm) {
156 salcianu 1.18             if((initMethod == null) || (hm != initMethod))
157 salcianu 1.18                 return parent_hcf.convert(hm);
158 salcianu 1.18 
159 salcianu 1.18             /* based on the implementation from InitializerTransform */
160 salcianu 1.18             return new QuadWithTry(initMethod, null) {
161 salcianu 1.18                 /* constructor */ {
162 salcianu 1.18                     Quad q0 = new HEADER(qf, null);
163 salcianu 1.18                     Quad q1 = new METHOD(qf, null, new Temp[]{}, 1);
164 salcianu 1.18                     Quad q3 = new RETURN(qf, null, null); // no retval
165 salcianu 1.18                     Quad q4 = new FOOTER(qf, null, 2);
166 salcianu 1.18                     Quad.addEdge(q0, 0, q4, 0);
167 salcianu 1.18                     Quad.addEdge(q0, 1, q1, 0);
168 salcianu 1.18                     Quad.addEdge(q1, 0, q3, 0);
169 salcianu 1.18                     Quad.addEdge(q3, 0, q4, 1);
170 salcianu 1.18                     this.quads = q0;
171 salcianu 1.18                 }
172 salcianu 1.18             };
173 salcianu 1.18         }
174 salcianu 1.18     };
175 salcianu 1.18 
176 salcianu 1.18     /** Returns a code factory that provides an intermediate
177 salcianu 1.18         representation for the empty body of the preallocated memory
178 salcianu 1.18         initialization.
179 salcianu 1.18 
180 salcianu 1.18         @param hcf Code factory providing the code for the rest of the code
181 salcianu 1.18         (currently, it has to be quad-with-try).
182 salcianu 1.18 
183 salcianu 1.18         @return Code factory identical to the <code>hcf</code>
184 salcianu 1.18         parameter, except that it also provides a default, empty body
185 salcianu 1.18         for the preallocated memory initilaization. */
186 salcianu 1.18     public static HCodeFactory getHCFWithEmptyInitCode(HCodeFactory hcf) {
187 salcianu 1.18         assert
188 salcianu 1.18             hcf.getCodeName().equals("quad-with-try") :
189 salcianu 1.18             "hcf has to be quad-with-try, not " + hcf.getCodeName() ;
190 salcianu 1.18         return new HCFWithEmptyInitMethod(hcf);
191 salcianu 1.5      }
192 salcianu 1.5  
193 salcianu 1.5      /** Executes the <code>IncompatibilityAnalysis</code> and creates
194 salcianu 1.5          a (QuadSSI) code factory that produces code with the
195 salcianu 1.5          allocation properties set to reflect the fact that some
196 salcianu 1.5          allocation sites can use pre-allocated memory space.  In
197 salcianu 1.5          addition, it adds static fields to the class named by
198 salcianu 1.5          <code>PreallocOpt.PREALLOC_MEM_CLASS_NAME</code>; at runtime,
199 salcianu 1.5          these fields will point to pre-allocated chunks of memory, one
200 salcianu 1.5          for each compatibility class found by the analysis.
201 salcianu 1.5  
202 salcianu 1.5          @param linker linker used to get classes
203 salcianu 1.7  
204 salcianu 1.5          @param hcf initial code factory; it has to be convertible to a
205 salcianu 1.5          QuadSSI code factory.
206 salcianu 1.7  
207 salcianu 1.5          @param ch class hierarchy for the program
208 salcianu 1.7  
209 salcianu 1.5          @param mainM main method of the program
210 salcianu 1.7  
211 salcianu 1.5          @param roots set of roots
212 salcianu 1.5  
213 salcianu 1.7          @param as allocation (dynamic) statistics; if
214 salcianu 1.16         non-<code>null</code>, the method prints some static and
215 salcianu 1.7          dynamic statistics.
216 salcianu 1.7  
217 salcianu 1.12         @param frame Backend specific information for compilation
218 salcianu 1.12         (data size and data layout details).  Used only for
219 salcianu 1.12         statistics; in particular, unused if <code>as</code> is
220 salcianu 1.12         <code>null</code>.
221 salcianu 1.12 
222 salcianu 1.5          @return QuadSSI code factory; it produces <code>Code</code>s
223 salcianu 1.5          where allocation sites that can be pre-allocated have the
224 salcianu 1.5          attached <code>PreallocAllocationStrategy</code>. */
225 salcianu 1.4      public static HCodeFactory preallocAnalysis
226 salcianu 1.12         (Linker linker, HCodeFactory hcf, ClassHierarchy ch, HMethod mainM,
227 salcianu 1.12          Set roots, AllocationStatistics as, Frame frame) {
228 salcianu 1.1  
229 salcianu 1.16         if (HACKED_GC) System.out.println("HACKED_GC on");
230 salcianu 1.5          System.out.println("preallocAnalysis: " + hcf.getCodeName());
231 salcianu 1.16         if(RANGE_DEBUG) {
232 salcianu 1.16             assert as != null : "RANGE_DEBUG requires non-null as.";
233 salcianu 1.16             System.out.println("RANGE = [" + lowBound + "," + highBound + "]");
234 salcianu 1.16         }
235 salcianu 1.16         
236 salcianu 1.12         // The whole mumbo-jumbo with the QuadNoSSA/QuandSSI is due to
237 salcianu 1.12         // the fact that some analyses (e.g., smart call graph
238 salcianu 1.12         // constructor) work only with QuadNoSSA, while other works
239 salcianu 1.12         // with SSI (e.g., incompatibility analysis).  In addition, we
240 salcianu 1.12         // really need the intermediate representation (IR) to stay
241 salcianu 1.12         // still during the analysis, so no IR cache clearing is
242 salcianu 1.12         // allowed.
243 salcianu 1.4          CachingCodeFactory hcf_nossa = getCachingQuadNoSSA(hcf);
244 salcianu 1.1  
245 salcianu 1.1          boolean OLD_FLAG = QuadSSI.KEEP_QUAD_MAP_HACK;
246 salcianu 1.1          QuadSSI.KEEP_QUAD_MAP_HACK = true;
247 salcianu 1.18 
248 salcianu 1.5          CachingCodeFactory hcf_ssi = 
249 salcianu 1.5              new CachingCodeFactory(QuadSSI.codeFactory(hcf_nossa), true);
250 salcianu 1.1  
251 salcianu 1.22         MetaCallGraphImpl.COLL_HACK = false;
252 salcianu 1.22         CallGraph cg = new SmartCallGraph(hcf_nossa, linker, ch, roots);
253 salcianu 1.7  
254 salcianu 1.5          // execute Ovy's analysis
255 salcianu 1.5          IncompatibilityAnalysis ia = 
256 salcianu 1.10             new IncompatibilityAnalysis(mainM, hcf_ssi, cg, linker);
257 salcianu 1.6  
258 salcianu 1.12         if(as != null)
259 salcianu 1.12             IAStatistics.printStatistics(ia, as, hcf_nossa, linker, frame);
260 salcianu 1.1  
261 salcianu 1.16         label2size = new HashMap();
262 salcianu 1.16         setAllocationProperties(linker, ia, frame, as);
263 salcianu 1.14 
264 salcianu 1.7          // restore flag (the backend crashes without this ...)
265 salcianu 1.7          QuadSSI.KEEP_QUAD_MAP_HACK = OLD_FLAG;
266 salcianu 1.7  
267 salcianu 1.4          return hcf_ssi;
268 salcianu 1.1      }
269 salcianu 1.1  
270 salcianu 1.1  
271 salcianu 1.4      private static CachingCodeFactory getCachingQuadNoSSA(HCodeFactory hcf) {
272 salcianu 1.1          HCodeFactory hcf_nossa = 
273 salcianu 1.1              hcf.getCodeName().equals(QuadNoSSA.codename) ?
274 salcianu 1.1              hcf : QuadNoSSA.codeFactory(hcf);
275 salcianu 1.1  
276 salcianu 1.7          return 
277 salcianu 1.7              ((hcf_nossa instanceof SafeCachingCodeFactory) ?
278 salcianu 1.7               (SafeCachingCodeFactory) hcf_nossa :
279 salcianu 1.7               new SafeCachingCodeFactory(hcf_nossa, true));
280 salcianu 1.7      }
281 salcianu 1.7  
282 salcianu 1.7  
283 salcianu 1.12     /** A <code>CachingCodeFactory</code> that ignores all calls to
284 salcianu 1.12         <code>clear</code> (hence the name). */
285 salcianu 1.7      public static class SafeCachingCodeFactory extends CachingCodeFactory {
286 salcianu 1.7          public SafeCachingCodeFactory(HCodeFactory hcf, boolean saveCode) {
287 salcianu 1.7              super(hcf, saveCode);
288 salcianu 1.7          }
289 salcianu 1.7          public void clear(HMethod m)    { /* ignore */ }
290 salcianu 1.1      }
291 salcianu 1.1  
292 salcianu 1.1  
293 salcianu 1.16     private static void setAllocationProperties
294 salcianu 1.12         (Linker linker, IncompatibilityAnalysis ia, Frame frame,
295 salcianu 1.16          AllocationStatistics as) {
296 salcianu 1.4  
297 salcianu 1.16         // BDW allocates many objects of the same size.  Therefore, if
298 salcianu 1.16         // we allocate several objects of different sizes, the space
299 salcianu 1.16         // is several times bigger than if we allocate same size
300 salcianu 1.16         // objects.  So, we allocate the same amount of space
301 salcianu 1.16         // (maxSize) for all preallocated memory chunks.
302 salcianu 1.16         int maxSize = 0;
303 cananian 1.25         for(Object ccO : ia.getCompatibleClasses()) {
304 cananian 1.25             Collection cc = (Collection) ccO;
305 salcianu 1.16             int thisSize = sizeForCompatClass(frame, cc);           
306 salcianu 1.16             maxSize = Math.max(thisSize, maxSize);
307 salcianu 1.16         }
308 salcianu 1.16 
309 salcianu 1.16         int nbLabels = 0;
310 salcianu 1.1  
311 salcianu 1.1          for(Iterator it = ia.getCompatibleClasses().iterator();
312 salcianu 1.16             it.hasNext(); nbLabels++) {
313 salcianu 1.12             Collection cc = (Collection) it.next();
314 salcianu 1.16 
315 salcianu 1.16             Label label = new Label(LABEL_ROOT_NAME + nbLabels);
316 salcianu 1.16             // debug: I think we really want the second line
317 salcianu 1.16             label2size.put(label, new Integer(maxSize));
318 salcianu 1.16             //label2size.put(label, new Integer(sizeForCompatClass(frame,cc)));
319 salcianu 1.16 
320 cananian 1.25             for(Object siteO : cc) {
321 cananian 1.25                 NEW site = (NEW) siteO;
322 salcianu 1.14                 QuadSSI codeSSI = (QuadSSI) site.getFactory().getParent();
323 salcianu 1.14                 NEW siteNoSSA = (NEW) codeSSI.getQuadMapSSI2NoSSA().get(site);
324 salcianu 1.14 
325 salcianu 1.18                 if(hasFinalizer(site)) {
326 salcianu 1.18                     System.out.println
327 salcianu 1.18                         ("NO PREALLOC for\t" + Util.code2str(site) +
328 salcianu 1.18                          "\tallocates object with finalizer");
329 salcianu 1.18                     continue;
330 salcianu 1.18                 }
331 salcianu 1.18 
332 salcianu 1.18                 if(!extraCond(site)) {
333 salcianu 1.18                     System.out.println
334 salcianu 1.18                         ("\nNO PREALLOC for\t" + Util.code2str(site) +
335 salcianu 1.18                          "\textraCond");
336 salcianu 1.18                     continue;
337 salcianu 1.18                 }
338 salcianu 1.16 
339 salcianu 1.16                 if(RANGE_DEBUG) {
340 salcianu 1.16                     int id = as.allocID(siteNoSSA);
341 salcianu 1.17                     if((id < lowBound) || (id > highBound)) {
342 salcianu 1.17                         System.out.println("Skipping prealloc for " + id);
343 salcianu 1.17                         continue;
344 salcianu 1.17                     }
345 salcianu 1.16                     System.out.println
346 salcianu 1.16                         ("\nPREALLOCATE: " + id + " \"" + label + "\" " + 
347 salcianu 1.16                          Util.code2str(site));
348 salcianu 1.16                 }
349 salcianu 1.16 
350 salcianu 1.16                 setAllocationProperties(site, label);
351 salcianu 1.14             }
352 salcianu 1.1          }
353 salcianu 1.3  
354 salcianu 1.16         System.out.println("PreallocOpt: " + nbLabels + 
355 salcianu 1.16                            " label(s) generated; maxSize = " + maxSize);
356 salcianu 1.16     }
357 salcianu 1.16 
358 salcianu 1.16 
359 salcianu 1.16     // hack to go around some missing things in Ovy's
360 salcianu 1.16     // IncompatibilityAnalysis: IA analyzes only the program that
361 salcianu 1.16     // is rooted in the main method (no initialization code
362 salcianu 1.16     // considered; that code happen to allocate a PrintStream, and
363 salcianu 1.16     // some connected objects with it ...)
364 salcianu 1.16     // TODO: properly implement Ovy's stuff
365 salcianu 1.16     static boolean extraCond(Quad site) {
366 salcianu 1.16         String className = ((NEW) site).hclass().getName();
367 salcianu 1.16         if(className.equals("java.io.BufferedWriter") ||
368 salcianu 1.16            className.equals("java.io.OutputStreamWriter")) {
369 salcianu 1.18             HMethod enclosing_method = site.getFactory().getMethod();
370 salcianu 1.18             HClass hdeclc = enclosing_method.getDeclaringClass();
371 salcianu 1.18             return ! hdeclc.getName().equals("java.io.PrintStream");
372 salcianu 1.16         }
373 salcianu 1.18         return true;
374 salcianu 1.3      }
375 salcianu 1.3  
376 salcianu 1.12     // compute the size of the preallocated chunk of memory that will
377 salcianu 1.12     // be used by the allocation sites from the compatibility class cc
378 salcianu 1.12     private static int sizeForCompatClass(Frame frame, Collection cc) {
379 salcianu 1.12         Runtime runtime = frame.getRuntime();
380 salcianu 1.12         int max = -1;
381 salcianu 1.12         for(Iterator it_new = cc.iterator(); it_new.hasNext(); ) {
382 salcianu 1.12             HClass hc = ((NEW) it_new.next()).hclass();
383 salcianu 1.12             int size = sizeForClass(runtime, hc);
384 salcianu 1.12             if(size > max) max = size;
385 salcianu 1.12         }
386 salcianu 1.12         return max;
387 salcianu 1.12     }
388 salcianu 1.12 
389 salcianu 1.12     // compute the total size occupied by an object of class hclass
390 salcianu 1.12     static int sizeForClass(Runtime runtime, HClass hclass) {
391 salcianu 1.12         Runtime.TreeBuilder tree_builder = runtime.getTreeBuilder();
392 salcianu 1.12         int size =
393 salcianu 1.12             tree_builder.objectSize(hclass) +
394 salcianu 1.12             tree_builder.headerSize(hclass);
395 salcianu 1.12         // we allocate only multiples of 4 bytes
396 salcianu 1.13         if((size % 4) != 0)
397 salcianu 1.13             size += 4 - (size % 4);
398 salcianu 1.12         return size;
399 salcianu 1.1      }
400 salcianu 1.1  
401 salcianu 1.12     static int sizeForClass(Frame frame, HClass hclass) {
402 salcianu 1.12         return sizeForClass(frame.getRuntime(), hclass);
403 salcianu 1.12     }
404 salcianu 1.1  
405 salcianu 1.16     private static void setAllocationProperties(NEW qn, Label l) {
406 salcianu 1.4          Code code = qn.getFactory().getParent();
407 salcianu 1.4          AllocationInformationMap aim = 
408 salcianu 1.4              (AllocationInformationMap) code.getAllocationInformation();
409 salcianu 1.12         // Make sure there is an AllocationInfomationMap for "code"
410 salcianu 1.4          if(aim == null) {
411 salcianu 1.12             aim = new DefaultAllocationInformationMap();
412 salcianu 1.4              code.setAllocationInformation(aim);
413 salcianu 1.4          }
414 salcianu 1.4  
415 salcianu 1.4          AllocationInformation.AllocationProperties formerAP = aim.query(qn);
416 salcianu 1.4          if(formerAP == null)
417 salcianu 1.4              formerAP = DefaultAllocationInformation.SINGLETON.query(qn);
418 salcianu 1.4  
419 salcianu 1.14         AllocationInformation.AllocationProperties ap = 
420 salcianu 1.16             new PreallocAP(l, formerAP);
421 salcianu 1.14         aim.associate((HCodeElement) qn, ap);
422 salcianu 1.4      }
423 salcianu 1.4  
424 salcianu 1.4  
425 salcianu 1.12     private static class PreallocAP extends ChainedAllocationProperties {
426 salcianu 1.16         public PreallocAP(Label label, AllocationProperties formerAP) {
427 salcianu 1.12             super(formerAP);
428 salcianu 1.16             this.label = label;
429 salcianu 1.4          }
430 salcianu 1.16         private Label label;
431 salcianu 1.16         public  Temp    allocationHeap()       { return null;  }
432 salcianu 1.16         public  boolean canBeStackAllocated()  { return false; }
433 salcianu 1.4          public  boolean canBeThreadAllocated() { return false; }
434 salcianu 1.16         public  boolean makeHeap()             { return false; }
435 salcianu 1.16         // pre-allocated data is thread local (see paper) -> no sync!
436 salcianu 1.16         public  boolean noSync()               { return true; }
437 salcianu 1.16         public  Label   getLabelOfPtrToMemoryChunk() { return label; }
438 salcianu 1.4      }
439 salcianu 1.4  
440 salcianu 1.4  
441 salcianu 1.16     public static HData getData(HClass hclass, Frame frame) {
442 salcianu 1.16         return 
443 salcianu 1.16             new PreallocData(hclass, frame, label2size.keySet(),
444 salcianu 1.16                              beginLabel, endLabel);
445 salcianu 1.16     }
446 salcianu 1.16 
447 salcianu 1.18 
448 salcianu 1.12     /** Add the code that preallocates memory and initializes the
449 salcianu 1.12         static fields that point to the preallocated memory chunks.
450 salcianu 1.12         
451 salcianu 1.12         @param linker Linker for loading classes
452 salcianu 1.12 
453 salcianu 1.12         @param hcf    Code factory for the current vesrion of the program
454 salcianu 1.12         (without the memory preallocation code).
455 salcianu 1.12 
456 salcianu 1.12         @param frame  Backend specific information for compilation
457 salcianu 1.12         (data size and data layout details).
458 salcianu 1.12 
459 salcianu 1.12         @return A code factory that produces code that already contains the
460 salcianu 1.12         memory preallocation code.  */
461 salcianu 1.4      public static HCodeFactory addMemoryPreallocation
462 salcianu 1.4          (Linker linker, HCodeFactory hcf, Frame frame) {
463 salcianu 1.19  
464 salcianu 1.19         if(PREALLOC_OPT) { // real stuff
465 salcianu 1.19             assert initMethod != null : 
466 salcianu 1.19                 "initMethod is null; forgot to call PreallocOpt.updateRoots?";
467 salcianu 1.19             return
468 salcianu 1.19                 Canonicalize.codeFactory
469 salcianu 1.19                 (new AddMemoryPreallocation
470 salcianu 1.19                  (hcf, initMethod, label2size, frame, beginLabel, endLabel));
471 salcianu 1.19         }
472 salcianu 1.18 
473 salcianu 1.19         // return a code factory that is as close to the one returned
474 salcianu 1.19         // in the previous case a s possible (to insulate ourselves
475 salcianu 1.19         // against accidental variations of the runtime performances
476 salcianu 1.19         // when measuring speedups)
477 salcianu 1.19         if(ONLY_SYNC_REMOVAL)
478 salcianu 1.19             return Canonicalize.codeFactory(hcf);
479 salcianu 1.16 
480 salcianu 1.19         return hcf; // will never happen
481 salcianu 1.18     }
482 salcianu 1.18 
483 salcianu 1.18     /** Checks whether the class allocated by <code>site</code> has a
484 salcianu 1.18         finalizer. */
485 salcianu 1.18     static boolean hasFinalizer(Quad site) {
486 salcianu 1.18         HClass hc = ((NEW) site).hclass();
487 salcianu 1.18         HMethod[] methods = hc.getMethods();
488 salcianu 1.18         for(int i = 0; i < methods.length; i++) {
489 salcianu 1.18             if(isFinalizer(methods[i]))
490 salcianu 1.18                 return true;
491 salcianu 1.18         }
492 salcianu 1.18         return false;
493 salcianu 1.18     }
494 salcianu 1.18 
495 salcianu 1.18     /** Checks whether the method <code>hm</code> is a finalizer. */
496 salcianu 1.18     private static boolean isFinalizer(HMethod hm) {
497 salcianu 1.18         return
498 salcianu 1.18             !Modifier.isAbstract(hm.getModifiers()) &&
499 salcianu 1.18             !hm.isStatic() &&
500 salcianu 1.18             (hm.getParameterTypes().length == 0) &&
501 salcianu 1.18             (hm.getReturnType().equals(HClass.Void)) &&
502 salcianu 1.18             hm.getName().equals("finalize") &&
503 salcianu 1.18             // java.lang.Object.finalize() is not a real finalizer
504 salcianu 1.18             !hm.getDeclaringClass().getName().equals("java.lang.Object");
505 salcianu 1.20     }
506 salcianu 1.20 
507 salcianu 1.20 
508 salcianu 1.20 
509 salcianu 1.20     public static class QuadPass extends CompilerStageEZ {
510 salcianu 1.20 
511 salcianu 1.20         public QuadPass(AllocationInstrCompStage aics) {
512 salcianu 1.20             super("prealloc-opt-quad-pass");
513 salcianu 1.20             this.aics = aics;
514 salcianu 1.20         }
515 salcianu 1.20         private AllocationInstrCompStage aics;
516 salcianu 1.20 
517 salcianu 1.20         public List/*<Option>*/ getOptions() {
518 salcianu 1.20             List/*<Option>*/ opts = new LinkedList/*<Option>*/();
519 salcianu 1.20 
520 salcianu 1.20             opts.add(new Option("prealloc-opt",
521 salcianu 1.20                                 "Preallocation Optimization using Incompatibility Analysis; syncronizations on preallocated objects are removed (prealocated objects are anyway thread local)") {
522 salcianu 1.20                 public void action() {
523 salcianu 1.20                     PREALLOC_OPT = true;
524 salcianu 1.20                     // make sure we use Runtime2
525 salcianu 1.20                     System.setProperty("harpoon.runtime", "2");
526 salcianu 1.20                 }
527 salcianu 1.20             });
528 salcianu 1.20             
529 salcianu 1.20             opts.add(new Option("ia-only-sync-removal",
530 salcianu 1.20                                 "Uses the Incompatibility Analysis only to remove syncronizations on the preallocatable objects; no preallocation.") {
531 salcianu 1.20                 public void action() {
532 salcianu 1.20                     ONLY_SYNC_REMOVAL = true;
533 salcianu 1.20                     // make sure we use Runtime2
534 salcianu 1.20                     System.setProperty("harpoon.runtime", "2");
535 salcianu 1.20                 }
536 salcianu 1.20             });
537 salcianu 1.20             
538 salcianu 1.20             return opts;
539 salcianu 1.20         }
540 salcianu 1.20 
541 salcianu 1.23         public boolean enabled() {  return _enabled(); }
542 salcianu 1.20 
543 salcianu 1.20         protected void real_action() {
544 salcianu 1.20             hcf = PreallocOpt.preallocAnalysis
545 salcianu 1.20                 (linker, hcf, classHierarchy, mainM, roots,
546 salcianu 1.20                  aics.getAllocationStatistics(), frame);
547 salcianu 1.20         }
548 salcianu 1.20     };
549 salcianu 1.20 
550 salcianu 1.20 
551 salcianu 1.20     public static class TreePass extends CompilerStageEZ {
552 salcianu 1.20 
553 salcianu 1.20         public TreePass() { super("prealloc-opt-tree-pass"); }
554 salcianu 1.23 
555 salcianu 1.23         public boolean enabled() { return _enabled(); }
556 salcianu 1.20 
557 salcianu 1.20         protected void real_action() {
558 salcianu 1.24             hcf = PreallocOpt.addMemoryPreallocation(linker, hcf, frame);
559 salcianu 1.20         }
560 salcianu 1.20     };
561 salcianu 1.20 
562 salcianu 1.20     private static boolean _enabled() {
563 salcianu 1.20         return PREALLOC_OPT || ONLY_SYNC_REMOVAL;
564 salcianu 1.1      }
565 salcianu 1.1  }