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.osr; 014 015import org.jikesrvm.VM; 016import org.jikesrvm.adaptive.controller.Controller; 017import org.jikesrvm.adaptive.controller.ControllerMemory; 018import org.jikesrvm.adaptive.controller.ControllerPlan; 019import org.jikesrvm.adaptive.recompilation.InvocationCounts; 020import org.jikesrvm.adaptive.util.AOSLogging; 021import org.jikesrvm.adaptive.util.CompilerAdviceAttribute; 022import org.jikesrvm.compilers.common.CompiledMethod; 023import org.jikesrvm.compilers.common.CompiledMethods; 024import org.jikesrvm.compilers.common.RuntimeCompiler; 025import org.jikesrvm.compilers.opt.driver.CompilationPlan; 026import org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod; 027import org.jikesrvm.runtime.Callbacks; 028 029/** 030 * Maintain statistic information about on stack replacement events 031 */ 032public 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) { 124 VM._assert(cmplplan.getMethod() == state.meth); 125 } 126 127 // for invalidated method, we do not perform OSR guarded inlining anymore. 128 // the Options object may be shared by several methods, 129 // we have to reset it back 130 boolean savedOsr = cmplplan.options.OSR_GUARDED_INLINING; 131 cmplplan.options.OSR_GUARDED_INLINING = false; 132 int newcmid = RuntimeCompiler.recompileWithOpt(cmplplan); 133 cmplplan.options.OSR_GUARDED_INLINING = savedOsr; 134 135 if (newcmid != -1) { 136 AOSLogging.logger.debug("recompiling state with opt succeeded " + state.cmid); 137 AOSLogging.logger.debug("new cmid " + newcmid); 138 139 // transfer hotness to the new cmid 140 double oldSamples = Controller.methodSamples.getData(state.cmid); 141 Controller.methodSamples.reset(state.cmid); 142 Controller.methodSamples.augmentData(newcmid, oldSamples); 143 144 recmplsucc = true; 145 if (VM.TraceOnStackReplacement) { 146 VM.sysWriteln(" recompile " + state.meth + " at -O" + cmplplan.options.getOptLevel()); 147 } 148 } 149 } 150 } 151 152 if (!recmplsucc) { 153 int newcmid = RuntimeCompiler.recompileWithOpt(state.meth); 154 if (newcmid == -1) { 155 if (VM.TraceOnStackReplacement) { 156 VM.sysWriteln(" opt recompilation failed!"); 157 } 158 state.meth.invalidateCompiledMethod(mostRecentlyCompiledMethod); 159 } 160 } 161 162 if (VM.TraceOnStackReplacement) { 163 VM.sysWriteln(" opt recompilation done!"); 164 } 165 } 166}