/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.adaptive.controller;
import java.util.Enumeration;
import org.jikesrvm.VM;
import org.jikesrvm.adaptive.OSR_OnStackReplacementEvent;
import org.jikesrvm.adaptive.OSR_OrganizerThread;
import org.jikesrvm.adaptive.database.methodsamples.VM_MethodCountData;
import org.jikesrvm.adaptive.measurements.listeners.VM_EdgeListener;
import org.jikesrvm.adaptive.measurements.listeners.VM_YieldCounterListener;
import org.jikesrvm.adaptive.measurements.organizers.VM_AccumulatingMethodSampleOrganizer;
import org.jikesrvm.adaptive.measurements.organizers.VM_DecayOrganizer;
import org.jikesrvm.adaptive.measurements.organizers.VM_DynamicCallGraphOrganizer;
import org.jikesrvm.adaptive.measurements.organizers.VM_MethodSampleOrganizer;
import org.jikesrvm.adaptive.measurements.organizers.VM_Organizer;
import org.jikesrvm.adaptive.recompilation.VM_CompilationThread;
import org.jikesrvm.adaptive.recompilation.VM_CompilerDNA;
import org.jikesrvm.adaptive.recompilation.VM_InvocationCounts;
import org.jikesrvm.adaptive.util.VM_AOSGenerator;
import org.jikesrvm.adaptive.util.VM_AOSLogging;
import org.jikesrvm.adaptive.util.VM_AOSOptions;
import org.jikesrvm.scheduler.VM_Scheduler.ThreadModel;
/**
* This class implements the controller thread. This entity is the brains of
* the adaptive optimization system. It communicates with the runtime
* measurements subsystem to instruct and gather profiling information.
* It also talks to the compilation threads to generate
* a) instrumented executables;
* b) optimized executables;
* c) static information about a method; or
* d) all of the above.
*/
public final class VM_ControllerThread extends ThreadModel {
/**
* constructor
* @param sentinel An object to signal when up and running
*/
VM_ControllerThread(Object sentinel) {
super("VM_ControllerThread");
this.sentinel = sentinel;
makeDaemon(true);
}
private final Object sentinel;
/**
* There are several ways in which a dcg organizer might
* be created; keep track of it once it is created so that
* we only create one instance of it.
*/
private VM_DynamicCallGraphOrganizer dcgOrg;
/**
* This method is the entry point to the controller, it is called when
* the controllerThread is created.
*/
public void run() {
// save this object so others can access it, if needed
VM_Controller.controllerThread = this;
// Bring up the logging system
VM_AOSLogging.boot();
if (VM_Controller.options.ENABLE_ADVICE_GENERATION) {
VM_AOSGenerator.boot();
}
VM_AOSLogging.controllerStarted();
// Create measurement entities that are NOT related to
// adaptive recompilation
createProfilers();
if (!VM_Controller.options.ENABLE_RECOMPILATION) {
// We're running an AOS bootimage with a non-adaptive primary strategy.
// We already set up any requested profiling infrastructure, so nothing
// left to do but exit.
controllerInitDone();
VM.sysWriteln("AOS: In non-adaptive mode; controller thread exiting.");
return; // controller thread exits.
}
if ((VM_Controller.options.ENABLE_REPLAY_COMPILE) || (VM_Controller.options.ENABLE_PRECOMPILE)) {
// if we want to do precompile, we need to initial optimization plans
// just allow the advice to be the max opt level 2
VM_Controller.options.DERIVED_MAX_OPT_LEVEL = 2;
if (VM_Controller.options.sampling()) {
// Create our set of standard optimization plans.
VM_Controller.recompilationStrategy.init();
} else if (VM_Controller.options.counters()) {
VM_InvocationCounts.init();
}
VM_Controller.osrOrganizer = new OSR_OrganizerThread();
VM_Controller.osrOrganizer.start();
createCompilationThread();
// We're running an AOS bootimage with a non-adaptive primary strategy.
// We already set up any requested profiling infrastructure, so nothing
// left to do but exit.
controllerInitDone();
// to have a fair comparison, we need to create the data structures
// of organizers
createOrganizerThreads();
VM.sysWriteln("AOS: In replay mode; controller thread only runs for OSR inlining.");
while (true) {
if (VM_Controller.options.EARLY_EXIT && VM_Controller.options.EARLY_EXIT_TIME < VM_Controller.controllerClock) {
VM_Controller.stop();
}
Object event = VM_Controller.controllerInputQueue.deleteMin();
((OSR_OnStackReplacementEvent) event).process();
}
}
// Initialize the CompilerDNA class
// This computes some internal options, must be done early in boot process
VM_CompilerDNA.init();
// Create the organizerThreads and schedule them
createOrganizerThreads();
// Create the compilationThread and schedule it
createCompilationThread();
if (VM_Controller.options.sampling()) {
// Create our set of standard optimization plans.
VM_Controller.recompilationStrategy.init();
} else if (VM_Controller.options.counters()) {
VM_InvocationCounts.init();
}
controllerInitDone();
// Enter main controller loop.
// Pull an event to process off of
// VM_Controller.controllerInputQueue and handle it.
// If no events are on the queue, then the deleteMin call will
// block until an event is available.
// Repeat forever.
while (true) {
if (VM_Controller.options.EARLY_EXIT && VM_Controller.options.EARLY_EXIT_TIME < VM_Controller.controllerClock) {
VM_Controller.stop();
}
Object event = VM_Controller.controllerInputQueue.deleteMin();
((VM_ControllerInputEvent) event).process();
}
}
// Now that we're done initializing, Schedule all the organizer threads
// and signal the sentinel object.
private void controllerInitDone() {
for (Enumeration<VM_Organizer> e = VM_Controller.organizers.elements(); e.hasMoreElements();) {
VM_Organizer o = e.nextElement();
o.start();
}
try {
synchronized (sentinel) {
sentinel.notify();
}
} catch (Exception e) {
e.printStackTrace();
VM.sysFail("Failed to start up controller subsystem");
}
}
/**
* Called when the controller thread is about to wait on
* VM_Controller.controllerInputQueue
*/
public void aboutToWait() {
}
/**
* Called when the controller thread is woken after waiting on
* VM_Controller.controllerInputQueue
*/
public void doneWaiting() {
VM_ControllerMemory.incrementNumAwoken();
}
///////////////////////
// Initialization.
// Create AOS threads.
// Initialize AOS data structures that depend on command line arguments.
///////////////////////
/**
* Create the compilationThread and schedule it
*/
private void createCompilationThread() {
VM_CompilationThread ct = new VM_CompilationThread();
VM_Controller.compilationThread = ct;
ct.start();
}
/**
* Create a dynamic call graph organizer of one doesn't already exist
*/
private void createDynamicCallGraphOrganizer() {
if (dcgOrg == null) {
dcgOrg = new VM_DynamicCallGraphOrganizer(new VM_EdgeListener());
VM_Controller.organizers.addElement(dcgOrg);
}
}
/**
* Create profiling entities that are independent of whether or not
* adaptive recompilation is actually enabled.
*/
private void createProfilers() {
VM_AOSOptions opts = VM_Controller.options;
if (opts.GATHER_PROFILE_DATA) {
VM_Controller.organizers.addElement(new VM_AccumulatingMethodSampleOrganizer());
createDynamicCallGraphOrganizer();
}
}
/**
* Create the organizerThreads and schedule them
*/
private void createOrganizerThreads() {
VM_AOSOptions opts = VM_Controller.options;
if (opts.sampling()) {
// Primary backing store for method sample data
VM_Controller.methodSamples = new VM_MethodCountData();
// Install organizer to drive method recompilation
VM_Controller.organizers.addElement(new VM_MethodSampleOrganizer(opts.DERIVED_FILTER_OPT_LEVEL));
// Additional set up for feedback directed inlining
if (opts.ADAPTIVE_INLINING) {
VM_Organizer decayOrganizer = new VM_DecayOrganizer(new VM_YieldCounterListener(opts.DECAY_FREQUENCY));
VM_Controller.organizers.addElement(decayOrganizer);
createDynamicCallGraphOrganizer();
}
}
if ((!VM_Controller.options.ENABLE_REPLAY_COMPILE) && (!VM_Controller.options.ENABLE_PRECOMPILE)) {
VM_Controller.osrOrganizer = new OSR_OrganizerThread();
VM_Controller.osrOrganizer.start();
}
}
/**
* Final report
*/
public static void report() {
VM_AOSLogging.controllerCompleted();
}
}