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