001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.opt.driver; 014 015import org.jikesrvm.VM; 016import org.jikesrvm.classloader.NormalMethod; 017import org.jikesrvm.compilers.common.CompiledMethod; 018import org.jikesrvm.compilers.opt.MagicNotImplementedException; 019import org.jikesrvm.compilers.opt.OptOptions; 020import org.jikesrvm.compilers.opt.OptimizingCompilerException; 021import org.jikesrvm.compilers.opt.ir.IR; 022import org.jikesrvm.compilers.opt.specialization.InvokeeThreadLocalContext; 023import org.jikesrvm.compilers.opt.specialization.SpecializationDatabase; 024import org.jikesrvm.runtime.Callbacks; 025 026/** 027 * <p> The main driver of the Compiler. 028 * <p> External drivers are responsible for providing the policies; the 029 * role of this class is simply to take a CompilationPlan 030 * and execute it. 031 * 032 * <p> Currently, this class is invoked from four clients: 033 * <ul> 034 * <li> (1) Command line: ExecuteOptCode 035 * <li> (2) BootImageWriting: BootImageCompiler.compile (optimizing version) 036 * <li> (3) RuntimeCompiler: RuntimeCompiler.compile (optimizing version) 037 * <li> (4) AOS: Compilation threads execute controller plans by invoking 038 * the opt compiler. 039 * </ul> 040 * 041 * <p> Clients are responsible for ensuring that: 042 * <ul> 043 * <li> (1) the VM has been initialized 044 * <li> (2) Compiler.init has been called before the first opt compilation 045 * </ul> 046 * 047 * <p> This class is not meant to be instantiated. 048 */ 049public final class OptimizingCompiler implements Callbacks.StartupMonitor { 050 051 //////////////////////////////////////////// 052 // Initialization 053 //////////////////////////////////////////// 054 /** 055 * Prepare compiler for use. 056 * @param options options to use for compilations during initialization 057 */ 058 public static void init(OptOptions options) { 059 try { 060 if (!(VM.writingBootImage || VM.runningTool || VM.runningVM)) { 061 // Caller failed to ensure that the VM was initialized. 062 throw new OptimizingCompilerException("VM not initialized", true); 063 } 064 // Make a local copy so that some options can be forced off just for the 065 // duration of this initialization step. 066 options = options.dup(); 067 options.ESCAPE_SIMPLE_IPA = false; 068 069 initializeStatics(); 070 071 // want to be notified when VM boot is done and ready to start application 072 Callbacks.addStartupMonitor(new OptimizingCompiler()); 073 isInitialized = true; 074 } catch (OptimizingCompilerException e) { 075 // failures during initialization can't be ignored 076 e.isFatal = true; 077 throw e; 078 } catch (Throwable e) { 079 OptimizingCompilerException oe = new OptimizingCompilerException("Compiler", 080 "untrapped failure during init, " + 081 " Converting to OptimizingCompilerException"); 082 oe.initCause(e); 083 throw oe; 084 } 085 } 086 087 /* 088 * callback when application is about to start. 089 */ 090 @Override 091 public void notifyStartup() { 092 if (VM.TraceOnStackReplacement) { 093 VM.sysWriteln("Compiler got notified of app ready to begin"); 094 } 095 setAppStarted(); 096 } 097 098 /** 099 * indicate when the application has started 100 */ 101 private static boolean appStarted = false; 102 103 public static synchronized boolean getAppStarted() { 104 return appStarted; 105 } 106 107 public static synchronized void setAppStarted() { 108 appStarted = true; 109 } 110 111 /** 112 * Set up option used while compiling the boot image 113 * @param options the options to set 114 */ 115 public static void setBootOptions(OptOptions options) { 116 // Only do guarded inlining if we can use code patches. 117 // Early speculation with method test/class test can result in 118 // bad code that we can't recover from later. 119 options.INLINE_GUARDED = options.guardWithCodePatch(); 120 121 // Compute summaries of bootimage methods if we haven't encountered them yet. 122 // Does not handle unimplemented magics very well; disable until 123 // we can get a chance to either implement them on IA32 or fix the 124 // analysis to not be so brittle. 125 // options.SIMPLE_ESCAPE_IPA = true; 126 } 127 128 /** 129 * Call the static init functions for the Compiler subsystems 130 */ 131 private static void initializeStatics() { 132 InvokeeThreadLocalContext.init(); 133 } 134 135 /** 136 * Prevent instantiation by clients 137 */ 138 private OptimizingCompiler() { 139 } 140 141 /** 142 * Has the optimizing compiler been initialized? 143 */ 144 private static boolean isInitialized = false; 145 146 /** 147 * @return whether the the optimizing compiler has been initialized 148 */ 149 public static boolean isInitialized() { 150 return isInitialized; 151 } 152 153 /** 154 * Reset the optimizing compiler 155 */ 156 static void reset() { 157 isInitialized = false; 158 } 159 160 //////////////////////////////////////////// 161 // Public interface for compiling a method 162 //////////////////////////////////////////// 163 /** 164 * Invoke the opt compiler to execute a compilation plan. 165 * 166 * @param cp the compilation plan to be executed 167 * @return the CompiledMethod object that is the result of compilation 168 */ 169 public static CompiledMethod compile(CompilationPlan cp) { 170 NormalMethod method = cp.method; 171 OptOptions options = cp.options; 172 checkSupported(method, options); 173 try { 174 printMethodMessage(method, options); 175 IR ir = cp.execute(); 176 // if doing analysis only, don't try to return an object 177 if (cp.analyzeOnly || cp.irGeneration) { 178 return null; 179 } 180 // now that we're done compiling, give the specialization 181 // system a chance to eagerly compile any specialized version 182 // that are pending. TODO: use lazy compilation with specialization. 183 SpecializationDatabase.doDeferredSpecializations(); 184 ir.compiledMethod.compileComplete(ir.MIRInfo.machinecode); 185 return ir.compiledMethod; 186 } catch (OptimizingCompilerException e) { 187 throw e; 188 } catch (Throwable e) { 189 fail(e, method); 190 return null; 191 } 192 } 193 194 /** 195 * Debugging aid. 196 * @param what a string message to print 197 */ 198 public static void report(String what) { 199 VM.sysWrite(what + '\n'); 200 } 201 202 /** 203 * Debugging aid. 204 * @param what a string message to print 205 * @param time a timestamp to print 206 */ 207 public static void report(String what, long time) { 208 VM.sysWrite(what); 209 if (what.length() < 8) { 210 VM.sysWrite('\t'); 211 } 212 if (what.length() < 16) { 213 VM.sysWrite('\t'); 214 } 215 VM.sysWrite('\t' + time + " ms"); 216 } 217 218 /** 219 * Debugging aid to be called before printing the IR 220 * @param what a string message to print 221 * @param method the method being compiled 222 */ 223 public static void header(String what, NormalMethod method) { 224 System.out.println("********* START OF: " + what + " FOR " + method); 225 } 226 227 /** 228 * Debugging aid to be called after printing the IR 229 * @param what a string message to print 230 * @param method the method being compiled 231 */ 232 public static void bottom(String what, NormalMethod method) { 233 System.out.println("********* END OF: " + what + " FOR " + method); 234 } 235 236 /** 237 * Prints the IR along with a message. 238 * @param ir the IR to print 239 * @param message the message to print 240 */ 241 public static void printInstructions(IR ir, String message) { 242 header(message, ir.method); 243 ir.printInstructions(); 244 bottom(message, ir.method); 245 } 246 247 /** 248 * Prints a message of a method name. 249 * @param method the method to print 250 * @param options the print options for the optimizing compiler 251 */ 252 private static void printMethodMessage(NormalMethod method, OptOptions options) { 253 if (options.PRINT_METHOD || options.PRINT_INLINE_REPORT) { 254 VM.sysWrite("-methodOpt " + 255 method.getDeclaringClass() + 256 ' ' + 257 method.getName() + 258 ' ' + 259 method.getDescriptor() + 260 " \n"); 261 } 262 } 263 264 /** 265 * Abort a compilation with an error. 266 * @param e The exception thrown by a compiler phase 267 * @param method The method being compiled 268 */ 269 private static void fail(Throwable e, NormalMethod method) { 270 OptimizingCompilerException optExn = 271 new OptimizingCompilerException("Compiler", "failure during compilation of", method.toString()); 272 if (e instanceof OutOfMemoryError) { 273 VM.sysWriteln("Compiler ran out of memory during compilation of ", method.toString()); 274 optExn.isFatal = false; 275 } else { 276 VM.sysWriteln("Compiler failure during compilation of ", method.toString()); 277 e.printStackTrace(); 278 } 279 throw optExn; 280 } 281 282 /** 283 * Checks whether opt compilation of a particular method is supported. 284 * If not, throws a non-fatal run-time exception. 285 * 286 * @param method the method to check 287 * @param options options for printing 288 */ 289 private static void checkSupported(NormalMethod method, OptOptions options) { 290 if (method.getDeclaringClass().hasDynamicBridgeAnnotation()) { 291 String msg = "Dynamic Bridge register save protocol not implemented"; 292 throw MagicNotImplementedException.EXPECTED(msg); 293 } 294 if (method.getDeclaringClass().hasBridgeFromNativeAnnotation()) { 295 String msg = "Native Bridge prologue not implemented"; 296 throw MagicNotImplementedException.EXPECTED(msg); 297 } 298 if (method.hasNoOptCompileAnnotation()) { 299 String msg = "Method throws NoOptCompilePragma"; 300 throw MagicNotImplementedException.EXPECTED(msg); 301 } 302 if (options.hasDRIVER_EXCLUDE()) { 303 String name = method.getDeclaringClass().toString() + "." + method.getName(); 304 if (options.fuzzyMatchDRIVER_EXCLUDE(name)) { 305 if (!method.getDeclaringClass().hasSaveVolatileAnnotation()) { 306 throw new OptimizingCompilerException("method excluded", false); 307 } 308 } 309 } 310 } 311}