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 }