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.controller;
014    
015    import java.util.LinkedList;
016    import org.jikesrvm.VM;
017    import org.jikesrvm.adaptive.util.AOSGenerator;
018    import org.jikesrvm.adaptive.util.AOSLogging;
019    import org.jikesrvm.compilers.common.CompiledMethod;
020    import org.jikesrvm.compilers.common.CompiledMethods;
021    import org.jikesrvm.compilers.common.RuntimeCompiler;
022    import org.jikesrvm.compilers.opt.driver.CompilationPlan;
023    
024    /**
025     * An instance of this class describes a compilation decision made by
026     * the controller.<p>
027     *
028     * Constraints: Given the plan list of a method:
029     * <ul>
030     *   <li>Only one plan will have status COMPLETED
031     *   <li>Multiple plans may have status OUTDATED
032     *   <li>Only one plan will have status IN_PROGRESS
033     * </ul>
034     * <p>
035     * status states:
036     * <pre>
037     * UNINITIALIZED -> IN_PROGRESS -> COMPLETED -> OUTDATED
038     *             \              \--> ABORTED_COMPILATION_ERROR (never recompile method)
039     * </pre>
040     */
041    public final class ControllerPlan {
042    
043      /** The plan was created, but the setStatus method was never called */
044      public static final byte UNINITIALIZED = 0;
045    
046      /** The plan was successfully completed, i.e., the method was recompiled */
047      public static final byte COMPLETED = 1;
048    
049      /** Compilation for the method was begun, but failed in an error */
050      public static final byte ABORTED_COMPILATION_ERROR = 2;
051    
052      /** The compilation is still in progress */
053      public static final byte IN_PROGRESS = 3;
054    
055      /** The compilation completed, but a new plan for the same method also
056        * completed, so this is not the most recent completed plan */
057      public static final byte OUTDATED = 4;
058    
059      /** The compilation plan is for a promotion from BASE to OPT */
060      public static final byte OSR_BASE_2_OPT = 5;
061    
062      /** This is used by clients to initialize local variables for Java semantics */
063      public static final byte UNKNOWN = 99;
064    
065      /**
066       *  The associate compilation plan
067       */
068      private CompilationPlan compPlan;
069    
070      /**
071       *  The time we created this plan
072       */
073      private int timeCreated;
074    
075      /**
076       *  The time compilation began
077       */
078      private int timeInitiated = -1;
079    
080      /**
081       *  The time compilation end
082       */
083      private int timeCompleted = -1;
084    
085      /**
086       *  The speedup we were expecting
087       */
088      private double expectedSpeedup;
089    
090      /**
091       *  The compilation time we were expecting
092       */
093      private double expectedCompilationTime;
094    
095      /**
096       *  The priority associated with this plan
097       */
098      private double priority;
099    
100      /**
101       *  The compiled method ID for this plan
102       */
103      private int CMID;
104    
105      /**
106       *  The compiled method ID for the previous plan for this method
107       */
108      private int prevCMID;
109    
110      /**
111       *  The status of this plan
112       */
113      private byte status;
114    
115      /**
116       *  The list that we are onstatus of this plan
117       */
118      private LinkedList<ControllerPlan> planList;
119    
120      /**
121       * Construct a controller plan
122       *
123       * @param compPlan     The compilation plan
124       * @param timeCreated  The "time" this plan was created
125       * @param prevCMID     The previous compiled method ID
126       * @param expectedSpeedup     Expected recompilation benefit
127       * @param expectedCompilationTime     Expected recompilation cost
128       * @param priority     How important is executing this plan?
129       */
130      public ControllerPlan(CompilationPlan compPlan, int timeCreated, int prevCMID, double expectedSpeedup,
131                               double expectedCompilationTime, double priority) {
132        this.compPlan = compPlan;
133        this.timeCreated = timeCreated;
134        this.prevCMID = prevCMID;
135        this.status = ControllerPlan.UNINITIALIZED;
136        this.expectedSpeedup = expectedSpeedup;
137        this.expectedCompilationTime = expectedCompilationTime;
138        this.priority = priority;
139      }
140    
141      /**
142       * Execute the plan.
143       *
144       * @return {@code true} on success, {@code false} on failure
145       */
146      public boolean execute() {
147        // mark plan as in progress and insert it into controller memory
148        setStatus(ControllerPlan.IN_PROGRESS);
149        ControllerMemory.insert(this);
150    
151        if (Controller.options
152            .BACKGROUND_RECOMPILATION ||
153                                      getCompPlan().getMethod().getDeclaringClass().isInBootImage()) {
154          Controller.compilationQueue.insert(getPriority(), this);
155          AOSLogging.logger.recompilationScheduled(getCompPlan(), getPriority());
156          return true;
157        } else {
158          getCompPlan().getMethod().replaceCompiledMethod(null);
159          return true;
160        }
161      }
162    
163      /**
164       * This method will recompile the method designated by the controller plan
165       * {@link #getCompPlan}.  It also
166       * <ol>
167       *   <li>credits the samples associated with the old compiled method
168       *     ID to the new method ID and clears the old value.
169       *   <li>clears inlining information
170       *   <li>updates the status of the controller plan
171       * </ol>
172       */
173      public CompiledMethod doRecompile() {
174        CompilationPlan cp = getCompPlan();
175    
176        setTimeInitiated(Controller.controllerClock);
177        AOSLogging.logger.recompilationStarted(cp);
178    
179        if (cp.options.PRINT_METHOD) {
180          VM.sysWrite("-oc:O" + cp.options.getOptLevel() + " \n");
181        }
182    
183        // Compile the method.
184        int newCMID = RuntimeCompiler.recompileWithOpt(cp);
185        int prevCMID = getPrevCMID();
186    
187        if (Controller.options.sampling()) {
188          // transfer the samples from the old CMID to the new CMID.
189          // scale the number of samples down by the expected speedup
190          // in the newly compiled method.
191          double expectedSpeedup = getExpectedSpeedup();
192          double oldNumSamples = Controller.methodSamples.getData(prevCMID);
193          double newNumSamples = oldNumSamples / expectedSpeedup;
194          Controller.methodSamples.reset(prevCMID);
195          if (newCMID > -1) {
196            Controller.methodSamples.augmentData(newCMID, newNumSamples);
197          }
198        }
199    
200        // set the status of the plan accordingly
201        if (newCMID != -1) {
202          setStatus(ControllerPlan.COMPLETED);
203        } else {
204          setStatus(ControllerPlan.ABORTED_COMPILATION_ERROR);
205        }
206    
207        setCMID(newCMID);
208        setTimeCompleted(Controller.controllerClock);
209        CompiledMethod cm = newCMID == -1 ? null : CompiledMethods.getCompiledMethod(newCMID);
210        if (newCMID == -1) {
211          AOSLogging.logger.recompilationAborted(cp);
212        } else {
213          AOSLogging.logger.recompilationCompleted(cp);
214          AOSLogging.logger.recordCompileTime(cm, getExpectedCompilationTime());
215        }
216        if (Controller.options.ENABLE_ADVICE_GENERATION && (newCMID != -1)) {
217          AOSGenerator.reCompilationWithOpt(cp);
218        }
219        return cm;
220      }
221    
222      /**
223       * The compilation plan
224       */
225      public CompilationPlan getCompPlan() { return compPlan; }
226    
227      /**
228       * The expected speedup <em>for this method </em> due to this recompilation
229       */
230      public double getExpectedSpeedup() { return expectedSpeedup; }
231    
232      /**
233       * The expected compilation time for this method
234       */
235      public double getExpectedCompilationTime() { return expectedCompilationTime; }
236    
237      /**
238       * The priority (how important is it that this plan be executed)
239       */
240      public double getPriority() { return priority; }
241    
242      /**
243       * The time this plan was created
244       */
245      public int getTimeCreated() { return timeCreated; }
246    
247      /**
248       * The time (according to the controller clock) compilation of this plan
249       * began.
250       */
251      public int getTimeInitiated() { return timeInitiated; }
252    
253      public void setTimeInitiated(int t) { timeInitiated = t; }
254    
255      /**
256       * The time (according to the controller clock) compilation of this plan
257       * completed.
258       */
259      public int getTimeCompleted() { return timeCompleted; }
260    
261      public void setTimeCompleted(int t) { timeCompleted = t; }
262    
263      /**
264       * CMID (compiled method id) associated with the code produced
265       * by executing this plan
266       */
267      public int getCMID() { return CMID; }
268    
269      public void setCMID(int x) { CMID = x; }
270    
271      /**
272       * CMID (compiled method id) associated with the *PREVIOUS* compiled
273       * version of this method
274       */
275      public int getPrevCMID() { return prevCMID; }
276    
277      /**
278       * Status of this compilation plan, choose from the values above
279       */
280      public byte getStatus() { return status; }
281    
282      public void setStatus(byte newStatus) {
283        status = newStatus;
284    
285        // if we are marking this plan as completed, all previous completed plans
286        // for this method should be marked as OUTDATED
287        if (newStatus == COMPLETED) {
288          // iterate over the planList until we get to this item
289          synchronized (planList) {
290            for (ControllerPlan curPlan : planList) {
291              // exit when we find ourselves
292              if (curPlan == this) break;
293    
294              if (curPlan.getStatus() == COMPLETED) {
295                curPlan.status = OUTDATED;
296              }
297            } // more to process
298          }
299        }
300      }
301    
302      /**
303       * List of plans for a source method
304       */
305      public void setPlanList(LinkedList<ControllerPlan> list) { planList = list; }
306    
307      public String getStatusString() {
308        switch (status) {
309          case UNINITIALIZED:
310            return "UNINITIALIZED";
311          case COMPLETED:
312            return "COMPLETED";
313          case ABORTED_COMPILATION_ERROR:
314            return "ABORTED_COMPILATION_ERROR";
315          case IN_PROGRESS:
316            return "IN_PROGRESS";
317          case OUTDATED:
318            return "OUTDATED";
319          case OSR_BASE_2_OPT:
320            return "OSR_BASE_2_OPT";
321          case UNKNOWN:
322            return "UNKNOWN (not error)";
323          default:
324            return "**** ERROR, UNKNOWN STATUS ****";
325        }
326      }
327    
328      @Override
329      public String toString() {
330        StringBuilder buf = new StringBuilder();
331    
332        buf.append("Method: ").append(getCompPlan().method).append("\n\tCompiled Method ID: ").append(CMID).append(
333            "\n\tPrevious Compiled Method ID: ").append(prevCMID).append("\n\tCreated at ").append(timeCreated).append(
334            "\n\tInitiated at ").append(timeInitiated).append("\n\tCompleted at ").append(timeCompleted).append(
335            "\n\tExpected Speedup: ").append(expectedSpeedup).append("\n\tExpected Compilation Time: ").append(
336            expectedCompilationTime).append("\n\tPriority: ").append(priority).append("\n\tStatus: ").append(getStatusString()).append(
337            "\n\tComp. Plan Level: ").append(compPlan.options.getOptLevel()).append("\n");
338        return buf.toString();
339      }
340    
341    }