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.adaptive;
014
015import org.jikesrvm.VM;
016import org.jikesrvm.adaptive.controller.Controller;
017import org.jikesrvm.adaptive.controller.ControllerPlan;
018import org.jikesrvm.adaptive.util.AOSLogging;
019import org.jikesrvm.compilers.common.CompiledMethod;
020import org.jikesrvm.compilers.common.CompiledMethods;
021import org.jikesrvm.compilers.opt.driver.CompilationPlan;
022import org.jikesrvm.osr.ExecutionStateExtractor;
023import org.jikesrvm.osr.ExecutionState;
024import org.jikesrvm.osr.OSRProfiler;
025import org.jikesrvm.osr.SpecialCompiler;
026import org.jikesrvm.scheduler.RVMThread;
027import org.vmmagic.unboxed.Offset;
028
029/**
030 * A OSR_ControllerOnStackReplacementPlan is scheduled by ControllerThread,
031 * and executed by the RecompilationThread.<p>
032 *
033 * It has the suspended thread whose activation being replaced,
034 * and a compilation plan.<p>
035 *
036 * The execution of this plan compiles the method, installs the new
037 * code, and reschedule the thread.
038 */
039public class OnStackReplacementPlan {
040  private final int CMID;
041  private final Offset tsFromFPoff;
042  private final Offset ypTakenFPoff;
043
044  /**
045   * Status is write-only at the moment, but I suspect it comes in
046   * handy for debugging -- RJG
047   */
048  @SuppressWarnings("unused")
049  private byte status;
050
051  private final RVMThread suspendedThread;
052  private final CompilationPlan compPlan;
053
054  private int timeInitiated = 0;
055  private int timeCompleted = 0;
056
057  public OnStackReplacementPlan(RVMThread thread, CompilationPlan cp, int cmid, int source, Offset tsoff,
058                                Offset ypoff, double priority) {
059    this.suspendedThread = thread;
060    this.compPlan = cp;
061    this.CMID = cmid;
062    this.tsFromFPoff = tsoff;
063    this.ypTakenFPoff = ypoff;
064    this.status = ControllerPlan.UNINITIALIZED;
065  }
066
067  public int getTimeInitiated() {
068    return timeInitiated;
069  }
070
071  public void setTimeInitiated(int t) {
072    timeInitiated = t;
073  }
074
075  public int getTimeCompleted() {
076    return timeCompleted;
077  }
078
079  public void setTimeCompleted(int t) {
080    timeCompleted = t;
081  }
082
083  public void setStatus(byte newStatus) {
084    status = newStatus;
085  }
086
087  public void execute() {
088    // 1. extract stack state
089    // 2. recompile the specialized method
090    // 3. install the code
091    // 4. reschedule the thread to new code.
092
093    AOSLogging.logger.logOsrEvent("OSR compiling " + compPlan.method);
094
095    setTimeInitiated(Controller.controllerClock);
096
097    {
098      ExecutionStateExtractor extractor = null;
099
100      CompiledMethod cm = CompiledMethods.getCompiledMethod(this.CMID);
101
102      boolean invalidate = true;
103      if (cm.getCompilerType() == CompiledMethod.BASELINE) {
104        if (VM.BuildForIA32) {
105          extractor = new org.jikesrvm.osr.ia32.BaselineExecutionStateExtractor();
106        } else {
107          if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC);
108          extractor = new org.jikesrvm.osr.ppc.BaselineExecutionStateExtractor();
109        }
110        // don't need to invalidate when transitioning from baseline
111        invalidate = false;
112      } else if (cm.getCompilerType() == CompiledMethod.OPT) {
113        if (VM.BuildForIA32) {
114          extractor = new org.jikesrvm.osr.ia32.OptExecutionStateExtractor();
115        } else {
116          if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC);
117          extractor = new org.jikesrvm.osr.ppc.OptExecutionStateExtractor();
118        }
119      } else {
120        if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
121        return;
122      }
123
124      ////////
125      // states is a list of state: callee -> caller -> caller
126      ExecutionState state = extractor.extractState(suspendedThread, this.tsFromFPoff, this.ypTakenFPoff, CMID);
127
128      if (invalidate) {
129        AOSLogging.logger.debug("Invalidate cmid " + CMID);
130        OSRProfiler.notifyInvalidation(state);
131      }
132
133      // compile from callee to caller
134      CompiledMethod newCM = SpecialCompiler.recompileState(state, invalidate);
135
136      setTimeCompleted(Controller.controllerClock);
137
138      if (newCM == null) {
139        setStatus(ControllerPlan.ABORTED_COMPILATION_ERROR);
140        AOSLogging.logger.logOsrEvent("OSR compilation failed!");
141      } else {
142        setStatus(ControllerPlan.COMPLETED);
143        // now let CodeInstaller generate a code stub,
144        // and PostThreadSwitch will install the stub to run.
145        if (VM.BuildForIA32) {
146          org.jikesrvm.osr.ia32.CodeInstaller.install(state, newCM);
147        } else {
148          org.jikesrvm.osr.ppc.CodeInstaller.install(state, newCM);
149        }
150        AOSLogging.logger.logOsrEvent("OSR compilation succeeded! " + compPlan.method);
151      }
152    }
153
154    suspendedThread.monitor().lockNoHandshake();
155    suspendedThread.osr_done = true;
156    suspendedThread.monitor().broadcast();
157    suspendedThread.monitor().unlock();
158  }
159}