/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* 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/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.adaptive;
import org.jikesrvm.VM;
import org.jikesrvm.adaptive.controller.Controller;
import org.jikesrvm.adaptive.controller.ControllerPlan;
import org.jikesrvm.adaptive.util.AOSLogging;
import org.jikesrvm.compilers.common.CompiledMethod;
import org.jikesrvm.compilers.common.CompiledMethods;
import org.jikesrvm.compilers.opt.driver.CompilationPlan;
import org.jikesrvm.osr.ExecutionStateExtractor;
import org.jikesrvm.osr.ExecutionState;
import org.jikesrvm.osr.OSRProfiler;
import org.jikesrvm.osr.SpecialCompiler;
import org.jikesrvm.scheduler.RVMThread;
import org.vmmagic.unboxed.Offset;
/**
* A OSR_ControllerOnStackReplacementPlan is scheduled by ControllerThread,
* and executed by the RecompilationThread.<p>
*
* It has the suspended thread whose activation being replaced,
* and a compilation plan.<p>
*
* The execution of this plan compiles the method, installs the new
* code, and reschedule the thread.
*/
public class OnStackReplacementPlan {
private final int CMID;
private final Offset tsFromFPoff;
private final Offset ypTakenFPoff;
/**
* Status is write-only at the moment, but I suspect it comes in
* handy for debugging -- RJG
*/
@SuppressWarnings("unused")
private byte status;
private final RVMThread suspendedThread;
private final CompilationPlan compPlan;
private int timeInitiated = 0;
private int timeCompleted = 0;
public OnStackReplacementPlan(RVMThread thread, CompilationPlan cp, int cmid, int source, Offset tsoff,
Offset ypoff, double priority) {
this.suspendedThread = thread;
this.compPlan = cp;
this.CMID = cmid;
this.tsFromFPoff = tsoff;
this.ypTakenFPoff = ypoff;
this.status = ControllerPlan.UNINITIALIZED;
}
public int getTimeInitiated() {
return timeInitiated;
}
public void setTimeInitiated(int t) {
timeInitiated = t;
}
public int getTimeCompleted() {
return timeCompleted;
}
public void setTimeCompleted(int t) {
timeCompleted = t;
}
public void setStatus(byte newStatus) {
status = newStatus;
}
public void execute() {
// 1. extract stack state
// 2. recompile the specialized method
// 3. install the code
// 4. reschedule the thread to new code.
AOSLogging.logger.logOsrEvent("OSR compiling " + compPlan.method);
setTimeInitiated(Controller.controllerClock);
{
ExecutionStateExtractor extractor = null;
CompiledMethod cm = CompiledMethods.getCompiledMethod(this.CMID);
boolean invalidate = true;
if (cm.getCompilerType() == CompiledMethod.BASELINE) {
if (VM.BuildForIA32) {
extractor = new org.jikesrvm.osr.ia32.BaselineExecutionStateExtractor();
} else {
if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC);
extractor = new org.jikesrvm.osr.ppc.BaselineExecutionStateExtractor();
}
// don't need to invalidate when transitioning from baseline
invalidate = false;
} else if (cm.getCompilerType() == CompiledMethod.OPT) {
if (VM.BuildForIA32) {
extractor = new org.jikesrvm.osr.ia32.OptExecutionStateExtractor();
} else {
if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC);
extractor = new org.jikesrvm.osr.ppc.OptExecutionStateExtractor();
}
} else {
if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
return;
}
////////
// states is a list of state: callee -> caller -> caller
ExecutionState state = extractor.extractState(suspendedThread, this.tsFromFPoff, this.ypTakenFPoff, CMID);
if (invalidate) {
AOSLogging.logger.debug("Invalidate cmid " + CMID);
OSRProfiler.notifyInvalidation(state);
}
// compile from callee to caller
CompiledMethod newCM = SpecialCompiler.recompileState(state, invalidate);
setTimeCompleted(Controller.controllerClock);
if (newCM == null) {
setStatus(ControllerPlan.ABORTED_COMPILATION_ERROR);
AOSLogging.logger.logOsrEvent("OSR compilation failed!");
} else {
setStatus(ControllerPlan.COMPLETED);
// now let CodeInstaller generate a code stub,
// and PostThreadSwitch will install the stub to run.
if (VM.BuildForIA32) {
org.jikesrvm.osr.ia32.CodeInstaller.install(state, newCM);
} else {
org.jikesrvm.osr.ppc.CodeInstaller.install(state, newCM);
}
AOSLogging.logger.logOsrEvent("OSR compilation succeeded! " + compPlan.method);
}
}
suspendedThread.monitor().lockNoHandshake();
suspendedThread.osr_done = true;
suspendedThread.monitor().broadcast();
suspendedThread.monitor().unlock();
}
}