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