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 }