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.osr; 014 015 import org.jikesrvm.VM; 016 import org.jikesrvm.Callbacks; 017 import org.jikesrvm.adaptive.controller.Controller; 018 import org.jikesrvm.adaptive.controller.ControllerMemory; 019 import org.jikesrvm.adaptive.controller.ControllerPlan; 020 import org.jikesrvm.adaptive.recompilation.InvocationCounts; 021 import org.jikesrvm.adaptive.util.AOSLogging; 022 import org.jikesrvm.adaptive.util.CompilerAdviceAttribute; 023 import org.jikesrvm.compilers.common.CompiledMethod; 024 import org.jikesrvm.compilers.common.CompiledMethods; 025 import org.jikesrvm.compilers.common.RuntimeCompiler; 026 import org.jikesrvm.compilers.opt.driver.CompilationPlan; 027 import org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod; 028 029 /** 030 * Maintain statistic information about on stack replacement events 031 */ 032 public class OSRProfiler implements Callbacks.ExitMonitor { 033 034 private static int invalidations = 0; 035 private static boolean registered = false; 036 037 @Override 038 public void notifyExit(int value) { 039 VM.sysWriteln("OSR invalidations " + invalidations); 040 } 041 042 // we know which assumption is invalidated 043 // current we only reset the root caller method to be recompiled. 044 public static void notifyInvalidation(ExecutionState state) { 045 046 if (!registered && VM.MeasureCompilation) { 047 registered = true; 048 Callbacks.addExitMonitor(new OSRProfiler()); 049 } 050 051 if (VM.TraceOnStackReplacement || VM.MeasureCompilation) { 052 OSRProfiler.invalidations++; 053 } 054 055 // find the root state 056 while (state.callerState != null) { 057 state = state.callerState; 058 } 059 060 // only invalidate the root state 061 invalidateState(state); 062 } 063 064 // invalidate an execution state 065 private static synchronized void invalidateState(ExecutionState state) { 066 // step 1: invalidate the compiled method with this OSR assumption 067 // how does this affect the performance? 068 CompiledMethod mostRecentlyCompiledMethod = CompiledMethods.getCompiledMethod(state.cmid); 069 070 if (VM.VerifyAssertions) { 071 VM._assert(mostRecentlyCompiledMethod.getMethod() == state.meth); 072 } 073 074 // check if the compiled method is the latest still the latest one 075 // this is necessary to check because the same compiled method may 076 // be invalidated in more than one thread at the same time 077 if (mostRecentlyCompiledMethod != state.meth.getCurrentCompiledMethod()) { 078 return; 079 } 080 081 // make sure the compiled method is an opt one 082 if (!(mostRecentlyCompiledMethod instanceof OptCompiledMethod)) { 083 return; 084 } 085 086 // reset the compiled method to null first, if other thread invokes 087 // this method before following opt recompilation, it can avoid OSR 088 state.meth.invalidateCompiledMethod(mostRecentlyCompiledMethod); 089 090 // a list of state from callee -> caller 091 if (VM.TraceOnStackReplacement) { 092 VM.sysWriteln("OSR " + OSRProfiler.invalidations + " : " + state.bcIndex + "@" + state.meth); 093 } 094 095 // simply reset the compiled method to null is not good 096 // for long run loops, because invalidate may cause 097 // the method falls back to the baseline again... 098 // NOW, we look for the previous compilation plan, and reuse 099 // the compilation plan. 100 boolean recmplsucc = false; 101 if (Controller.enabled) { 102 CompilationPlan cmplplan = null; 103 if (Controller.options.ENABLE_PRECOMPILE && CompilerAdviceAttribute.hasAdvice()) { 104 CompilerAdviceAttribute attr = CompilerAdviceAttribute.getCompilerAdviceInfo(state.meth); 105 if (VM.VerifyAssertions) { 106 VM._assert(attr.getCompiler() == CompiledMethod.OPT); 107 } 108 if (Controller.options.counters()) { 109 // for invocation counter, we only use one optimization level 110 cmplplan = InvocationCounts.createCompilationPlan(state.meth); 111 } else { 112 // for now there is not two options for sampling, so 113 // we don't have to use: if (Controller.options.sampling()) 114 cmplplan = Controller.recompilationStrategy.createCompilationPlan(state.meth, attr.getOptLevel(), null); 115 } 116 } else { 117 ControllerPlan ctrlplan = ControllerMemory.findMatchingPlan(mostRecentlyCompiledMethod); 118 if (ctrlplan != null) { 119 cmplplan = ctrlplan.getCompPlan(); 120 } 121 } 122 if (cmplplan != null) { 123 if (VM.VerifyAssertions) {VM._assert(cmplplan.getMethod() == state.meth);} 124 125 // for invalidated method, we do not perform OSR guarded inlining anymore. 126 // the Options object may be shared by several methods, 127 // we have to reset it back 128 boolean savedOsr = cmplplan.options.OSR_GUARDED_INLINING; 129 cmplplan.options.OSR_GUARDED_INLINING = false; 130 int newcmid = RuntimeCompiler.recompileWithOpt(cmplplan); 131 cmplplan.options.OSR_GUARDED_INLINING = savedOsr; 132 133 if (newcmid != -1) { 134 AOSLogging.logger.debug("recompiling state with opt succeeded " + state.cmid); 135 AOSLogging.logger.debug("new cmid " + newcmid); 136 137 // transfer hotness to the new cmid 138 double oldSamples = Controller.methodSamples.getData(state.cmid); 139 Controller.methodSamples.reset(state.cmid); 140 Controller.methodSamples.augmentData(newcmid, oldSamples); 141 142 recmplsucc = true; 143 if (VM.TraceOnStackReplacement) { 144 VM.sysWriteln(" recompile " + state.meth + " at -O" + cmplplan.options.getOptLevel()); 145 } 146 } 147 } 148 } 149 150 if (!recmplsucc) { 151 int newcmid = RuntimeCompiler.recompileWithOpt(state.meth); 152 if (newcmid == -1) { 153 if (VM.TraceOnStackReplacement) {VM.sysWriteln(" opt recompilation failed!");} 154 state.meth.invalidateCompiledMethod(mostRecentlyCompiledMethod); 155 } 156 } 157 158 if (VM.TraceOnStackReplacement) {VM.sysWriteln(" opt recompilation done!");} 159 } 160 }