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