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 */ 013 package org.jikesrvm.adaptive.controller; 014 015 import java.util.Enumeration; 016 import java.util.Vector; 017 import org.jikesrvm.VM; 018 import org.jikesrvm.Callbacks; 019 import org.jikesrvm.adaptive.OSROrganizerThread; 020 import org.jikesrvm.adaptive.database.AOSDatabase; 021 import org.jikesrvm.adaptive.database.callgraph.PartialCallGraph; 022 import org.jikesrvm.adaptive.database.methodsamples.MethodCountData; 023 import org.jikesrvm.adaptive.measurements.RuntimeMeasurements; 024 import org.jikesrvm.adaptive.measurements.instrumentation.Instrumentation; 025 import org.jikesrvm.adaptive.measurements.organizers.Organizer; 026 import org.jikesrvm.adaptive.recompilation.CompilationThread; 027 import org.jikesrvm.adaptive.recompilation.instrumentation.CounterBasedSampling; 028 import org.jikesrvm.adaptive.util.AOSLogging; 029 import org.jikesrvm.adaptive.util.AOSOptions; 030 import org.jikesrvm.adaptive.util.BlockingPriorityQueue; 031 import org.jikesrvm.compilers.baseline.EdgeCounts; 032 import org.jikesrvm.compilers.common.RecompilationManager; 033 import org.jikesrvm.scheduler.RVMThread; 034 import org.jikesrvm.scheduler.SoftLatch; 035 036 /** 037 * This class contains top level adaptive compilation subsystem functions. 038 */ 039 public class Controller implements Callbacks.ExitMonitor, 040 Callbacks.RecompileAllDynamicallyLoadedMethodsMonitor { 041 042 /** 043 * Signals when the options and (optional) logging mechanism are enabled 044 */ 045 public static boolean enabled = false; 046 047 /** 048 * Controller subsystem control options 049 */ 050 public static final AOSOptions options = new AOSOptions(); 051 052 /** 053 * Deferred command line arguments for the opt compiler 054 */ 055 private static String[] optCompilerOptions = new String[0]; 056 057 /** 058 * Add a deferred command line argument 059 */ 060 public static void addOptCompilerOption(String arg) { 061 String[] tmp = new String[optCompilerOptions.length + 1]; 062 for (int i = 0; i < optCompilerOptions.length; i++) { 063 tmp[i] = optCompilerOptions[i]; 064 } 065 tmp[optCompilerOptions.length] = arg; 066 optCompilerOptions = tmp; 067 } 068 069 /** 070 * Get the deferred command line arguments 071 */ 072 public static String[] getOptCompilerOptions() {return optCompilerOptions;} 073 074 /** 075 * The controller thread, it makes all the decisions 076 * (the thread sets this field when it is created.) 077 */ 078 public static ControllerThread controllerThread = null; 079 080 /** 081 * Thread that will perform opt-compilations as directed by the controller 082 * (the thread sets this field when it is created.) 083 */ 084 public static CompilationThread compilationThread = null; 085 086 /** 087 * Thread collecting osr request and pass it to controllerThread 088 */ 089 public static OSROrganizerThread osrOrganizer = null; 090 091 /** 092 * Threads that will organize profile data as directed by the controller 093 */ 094 public static final Vector<Organizer> organizers = new Vector<Organizer>(); 095 096 /** 097 * A blocking priority queue where organizers place events to 098 * be processed by the controller 099 * (an input to the controller thread) 100 */ 101 public static BlockingPriorityQueue controllerInputQueue; 102 103 /** 104 * A blocking priority queue where the controller will place methods 105 * to be opt compiled 106 * (an output of the controller thread) 107 */ 108 public static BlockingPriorityQueue compilationQueue; 109 110 /** 111 * The strategy used to make recompilation decisions 112 */ 113 public static RecompilationStrategy recompilationStrategy; 114 115 /** 116 * Controller virtual clock, ticked every taken yieldpoint. 117 */ 118 public static int controllerClock = 0; 119 120 /** 121 * The main hot method raw data object. 122 */ 123 public static MethodCountData methodSamples; 124 /** 125 * The dynamic call graph 126 */ 127 public static PartialCallGraph dcg; 128 129 /** 130 * Used to shut down threads 131 */ 132 private static final ThreadDeath threadDeath = new ThreadDeath(); 133 134 /** 135 * Has the execution of boot completed successfully? 136 */ 137 private static boolean booted = false; 138 139 /** 140 * Initialize the controller subsystem (called from VM.boot) 141 * This method is called AFTER the command line options are processed. 142 */ 143 public static void boot() { 144 // Signal that the options and (optional) logging mechanism are set 145 // RuntimeCompiler checks this flag 146 enabled = true; 147 148 // Initialize the controller input queue 149 controllerInputQueue = new BlockingPriorityQueue(new BlockingPriorityQueue.CallBack() { 150 @Override 151 public void aboutToWait() { controllerThread.aboutToWait(); } 152 @Override 153 public void doneWaiting() { controllerThread.doneWaiting(); } 154 }); 155 156 compilationQueue = new BlockingPriorityQueue(); 157 158 // Create the analytic model used to make cost/benefit decisions. 159 recompilationStrategy = new MultiLevelAdaptiveModel(); 160 161 // boot the runtime measurement systems 162 RuntimeMeasurements.boot(); 163 164 // Initialize subsystems, if being used 165 AdaptiveInlining.boot(options); 166 167 // boot any instrumentation options 168 Instrumentation.boot(options); 169 170 // boot the AOS database 171 AOSDatabase.boot(options); 172 173 CounterBasedSampling.boot(options); 174 175 createControllerThread(); 176 177 Controller controller = new Controller(); 178 Callbacks.addExitMonitor(controller); 179 180 // make sure the user hasn't explicitly prohibited this functionality 181 if (!options.DISABLE_RECOMPILE_ALL_METHODS) { 182 Callbacks.addRecompileAllDynamicallyLoadedMethodsMonitor(controller); 183 } 184 185 booted = true; 186 } 187 188 /** 189 * To be called when the VM is about to exit. 190 * @param value the exit value 191 */ 192 @Override 193 public void notifyExit(int value) { 194 report(); 195 } 196 197 /** 198 * Called when the application wants to recompile all dynamically 199 * loaded methods. This can be expensive! 200 */ 201 @Override 202 public void notifyRecompileAll() { 203 AOSLogging.logger.recompilingAllDynamicallyLoadedMethods(); 204 RecompilationManager.recompileAllDynamicallyLoadedMethods(false); 205 } 206 207 // Create the ControllerThread 208 static void createControllerThread() { 209 SoftLatch sentinel = new SoftLatch(false); 210 ControllerThread tt = new ControllerThread(sentinel); 211 tt.start(); 212 // wait until controller threads are up and running. 213 try { 214 sentinel.waitAndClose(); 215 } catch (Exception e) { 216 e.printStackTrace(); 217 VM.sysFail("Failed to start up controller subsystem"); 218 } 219 } 220 221 /** 222 * Process any command line arguments passed to the controller subsystem. 223 * <p> 224 * This method has the responsibility of creating the options object 225 * if it does not already exist 226 * <p> 227 * NOTE: All command line argument processing should be handled via 228 * the automatically generated code in AOSOptions.java. 229 * Don't even think of adding handwritten stuff here! --dave 230 * 231 * @param arg the command line argument to be processed 232 */ 233 public static void processCommandLineArg(String arg) { 234 if (!options.processAsOption("-X:aos", arg)) { 235 VM.sysWrite("vm: illegal adaptive configuration directive \"" + arg + "\" specified as -X:aos:" + arg + "\n"); 236 VM.sysExit(VM.EXIT_STATUS_BOGUS_COMMAND_LINE_ARG); 237 } 238 } 239 240 /** 241 * This method is called when the VM is exiting to provide a hook to allow 242 * the adaptive optimization subsystem to generate a summary report. 243 * It can also be called directly from driver programs to allow 244 * reporting on a single run of a benchmark that the driver program 245 * is executing in a loop (in which case the adaptive system isn't actually 246 * exiting.....so some of the log messages may get a little weird). 247 */ 248 public static void report() { 249 if (!booted) return; 250 ControllerThread.report(); 251 RuntimeMeasurements.report(); 252 253 for (Enumeration<Organizer> e = organizers.elements(); e.hasMoreElements();) { 254 Organizer organizer = e.nextElement(); 255 organizer.report(); 256 } 257 258 if (options.FINAL_REPORT_LEVEL >= 2) { 259 EdgeCounts.dumpCounts(); 260 dcg.dumpGraph(); 261 } 262 263 if (options.REPORT_INTERRUPT_STATS) { 264 VM.sysWriteln("Timer Interrupt and Listener Stats"); 265 VM.sysWriteln("\tTotal number of clock ticks ", RVMThread.timerTicks); 266 VM.sysWriteln("\tController clock ", controllerClock); 267 VM.sysWriteln("\tNumber of method samples taken ", (int) methodSamples.getTotalNumberOfSamples()); 268 } 269 } 270 271 /** 272 * Stop all AOS threads and exit the adaptive system. 273 * Can be used to assess code quality in a steady state by 274 * allowing the adaptive system to run "for a while" and then 275 * stopping it 276 */ 277 public static void stop() { 278 if (!booted) return; 279 280 VM.sysWriteln("AOS: Killing all adaptive system threads"); 281 for (Enumeration<Organizer> e = organizers.elements(); e.hasMoreElements();) { 282 Organizer organizer = e.nextElement(); 283 organizer.stop(threadDeath); 284 } 285 compilationThread.stop(threadDeath); 286 controllerThread.stop(threadDeath); 287 RuntimeMeasurements.stop(); 288 report(); 289 } 290 } 291