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.controller; 014 015import java.util.LinkedList; 016import org.jikesrvm.VM; 017import org.jikesrvm.adaptive.util.AOSGenerator; 018import org.jikesrvm.adaptive.util.AOSLogging; 019import org.jikesrvm.compilers.common.CompiledMethod; 020import org.jikesrvm.compilers.common.CompiledMethods; 021import org.jikesrvm.compilers.common.RuntimeCompiler; 022import 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 */ 041public 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 final CompilationPlan compPlan; 069 070 /** 071 * The time we created this plan 072 */ 073 private final 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 final double expectedSpeedup; 089 090 /** 091 * The compilation time we were expecting 092 */ 093 private final double expectedCompilationTime; 094 095 /** 096 * The priority associated with this plan 097 */ 098 private final 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 final 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 * @return {@code null} if the compilation was aborted, the new compiled 174 * method otherwise 175 */ 176 public CompiledMethod doRecompile() { 177 CompilationPlan cp = getCompPlan(); 178 179 setTimeInitiated(Controller.controllerClock); 180 AOSLogging.logger.recompilationStarted(cp); 181 182 if (cp.options.PRINT_METHOD) { 183 VM.sysWrite("-oc:O" + cp.options.getOptLevel() + " \n"); 184 } 185 186 // Compile the method. 187 int newCMID = RuntimeCompiler.recompileWithOpt(cp); 188 int prevCMID = getPrevCMID(); 189 190 if (Controller.options.sampling()) { 191 // transfer the samples from the old CMID to the new CMID. 192 // scale the number of samples down by the expected speedup 193 // in the newly compiled method. 194 double expectedSpeedup = getExpectedSpeedup(); 195 double oldNumSamples = Controller.methodSamples.getData(prevCMID); 196 double newNumSamples = oldNumSamples / expectedSpeedup; 197 Controller.methodSamples.reset(prevCMID); 198 if (newCMID > -1) { 199 Controller.methodSamples.augmentData(newCMID, newNumSamples); 200 } 201 } 202 203 // set the status of the plan accordingly 204 if (newCMID != -1) { 205 setStatus(ControllerPlan.COMPLETED); 206 } else { 207 setStatus(ControllerPlan.ABORTED_COMPILATION_ERROR); 208 } 209 210 setCMID(newCMID); 211 setTimeCompleted(Controller.controllerClock); 212 CompiledMethod cm = newCMID == -1 ? null : CompiledMethods.getCompiledMethod(newCMID); 213 if (newCMID == -1) { 214 AOSLogging.logger.recompilationAborted(cp); 215 } else { 216 AOSLogging.logger.recompilationCompleted(cp); 217 AOSLogging.logger.recordCompileTime(cm, getExpectedCompilationTime()); 218 } 219 if (Controller.options.ENABLE_ADVICE_GENERATION && (newCMID != -1)) { 220 AOSGenerator.reCompilationWithOpt(cp); 221 } 222 return cm; 223 } 224 225 /** 226 * @return the compilation plan 227 */ 228 public CompilationPlan getCompPlan() { 229 return compPlan; 230 } 231 232 /** 233 * @return the expected speedup <em>for this method </em> due to this recompilation 234 */ 235 public double getExpectedSpeedup() { 236 return expectedSpeedup; 237 } 238 239 /** 240 * @return the expected compilation time for this method 241 */ 242 public double getExpectedCompilationTime() { 243 return expectedCompilationTime; 244 } 245 246 /** 247 * @return the priority (how important is it that this plan be executed) 248 */ 249 public double getPriority() { 250 return priority; 251 } 252 253 /** 254 * @return the time this plan was created 255 */ 256 public int getTimeCreated() { 257 return timeCreated; 258 } 259 260 /** 261 * @return the time (according to the controller clock) compilation of this plan 262 * began. 263 */ 264 public int getTimeInitiated() { 265 return timeInitiated; 266 } 267 268 public void setTimeInitiated(int t) { 269 timeInitiated = t; 270 } 271 272 /** 273 * @return the time (according to the controller clock) compilation of this plan 274 * completed. 275 */ 276 public int getTimeCompleted() { 277 return timeCompleted; 278 } 279 280 public void setTimeCompleted(int t) { 281 timeCompleted = t; 282 } 283 284 /** 285 * @return CMID (compiled method id) associated with the code produced 286 * by executing this plan 287 */ 288 public int getCMID() { 289 return CMID; 290 } 291 292 public void setCMID(int x) { 293 CMID = x; 294 } 295 296 /** 297 * @return CMID (compiled method id) associated with the *PREVIOUS* compiled 298 * version of this method 299 */ 300 public int getPrevCMID() { 301 return prevCMID; 302 } 303 304 /** 305 * @return status of this compilation plan, chosen from the values defined 306 * in this class 307 */ 308 public byte getStatus() { 309 return status; 310 } 311 312 public void setStatus(byte newStatus) { 313 status = newStatus; 314 315 // if we are marking this plan as completed, all previous completed plans 316 // for this method should be marked as OUTDATED 317 if (newStatus == COMPLETED) { 318 // iterate over the planList until we get to this item 319 synchronized (planList) { 320 for (ControllerPlan curPlan : planList) { 321 // exit when we find ourselves 322 if (curPlan == this) break; 323 324 if (curPlan.getStatus() == COMPLETED) { 325 curPlan.status = OUTDATED; 326 } 327 } // more to process 328 } 329 } 330 } 331 332 public void setPlanList(LinkedList<ControllerPlan> list) { 333 planList = list; 334 } 335 336 public String getStatusString() { 337 switch (status) { 338 case UNINITIALIZED: 339 return "UNINITIALIZED"; 340 case COMPLETED: 341 return "COMPLETED"; 342 case ABORTED_COMPILATION_ERROR: 343 return "ABORTED_COMPILATION_ERROR"; 344 case IN_PROGRESS: 345 return "IN_PROGRESS"; 346 case OUTDATED: 347 return "OUTDATED"; 348 case OSR_BASE_2_OPT: 349 return "OSR_BASE_2_OPT"; 350 case UNKNOWN: 351 return "UNKNOWN (not error)"; 352 default: 353 return "**** ERROR, UNKNOWN STATUS ****"; 354 } 355 } 356 357 @Override 358 public String toString() { 359 StringBuilder buf = new StringBuilder(); 360 361 buf.append("Method: ").append(getCompPlan().method).append("\n\tCompiled Method ID: ").append(CMID).append( 362 "\n\tPrevious Compiled Method ID: ").append(prevCMID).append("\n\tCreated at ").append(timeCreated).append( 363 "\n\tInitiated at ").append(timeInitiated).append("\n\tCompleted at ").append(timeCompleted).append( 364 "\n\tExpected Speedup: ").append(expectedSpeedup).append("\n\tExpected Compilation Time: ").append( 365 expectedCompilationTime).append("\n\tPriority: ").append(priority).append("\n\tStatus: ").append(getStatusString()).append( 366 "\n\tComp. Plan Level: ").append(compPlan.options.getOptLevel()).append("\n"); 367 return buf.toString(); 368 } 369 370}