8147432: JVMCI should report bailouts in PrintCompilation output

Reviewed-by: kvn, twisti
This commit is contained in:
Tom Rodriguez 2016-01-22 11:08:07 -08:00
parent 0691fac50b
commit 87d68c21c4
16 changed files with 165 additions and 101 deletions

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.code;
/**
* Simple class to provide information about the result of a compile request.
*/
public final class CompilationRequestResult {
/**
* A user readable description of the failure.
*/
private final String failureMessage;
/**
* Whether this is a transient failure where retrying would help.
*/
private final boolean retry;
/**
* Number of bytecodes inlined into the compilation, exclusive of the bytecodes in the root
* method.
*/
private final int inlinedBytecodes;
private CompilationRequestResult(String failureMessage, boolean retry, int inlinedBytecodes) {
this.failureMessage = failureMessage;
this.retry = retry;
this.inlinedBytecodes = inlinedBytecodes;
}
public static CompilationRequestResult success(int inlinedBytecodes) {
return new CompilationRequestResult(null, true, inlinedBytecodes);
}
public static CompilationRequestResult failure(String failureMessage, boolean retry) {
return new CompilationRequestResult(failureMessage, retry, 0);
}
public String getFailureMessage() {
return failureMessage;
}
public boolean getRetry() {
return retry;
}
public int getInlinedBytecodes() {
return inlinedBytecodes;
}
}

View file

@ -316,21 +316,6 @@ final class CompilerToVM {
public native int getMetadata(TargetDescription target, HotSpotCompiledCode compiledCode, HotSpotMetaData metaData);
/**
* Notifies the VM of statistics for a completed compilation.
*
* @param id the identifier of the compilation
* @param method the method compiled
* @param osr specifies if the compilation was for on-stack-replacement
* @param processedBytecodes the number of bytecodes processed during the compilation, including
* the bytecodes of all inlined methods
* @param time the amount time spent compiling {@code method}
* @param timeUnitsPerSecond the granularity of the units for the {@code time} value
* @param installedCode the nmethod installed as a result of the compilation
*/
synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethodImpl method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond,
InstalledCode installedCode);
/**
* Resets all compilation statistics.
*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -169,22 +169,6 @@ public class HotSpotCodeCacheProvider implements CodeCacheProvider {
return runtime.getCompilerToVM().shouldDebugNonSafepoints();
}
/**
* Notifies the VM of statistics for a completed compilation.
*
* @param id the identifier of the compilation
* @param method the method compiled
* @param osr specifies if the compilation was for on-stack-replacement
* @param processedBytecodes the number of bytecodes processed during the compilation, including
* the bytecodes of all inlined methods
* @param time the amount time spent compiling {@code method}
* @param timeUnitsPerSecond the granularity of the units for the {@code time} value
* @param installedCode the nmethod installed as a result of the compilation
*/
public void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode) {
runtime.getCompilerToVM().notifyCompilationStatistics(id, (HotSpotResolvedJavaMethodImpl) method, osr, processedBytecodes, time, timeUnitsPerSecond, installedCode);
}
/**
* Resets all compilation statistics.
*/

View file

@ -23,6 +23,7 @@
package jdk.vm.ci.hotspot;
import jdk.vm.ci.code.CompilationRequest;
import jdk.vm.ci.code.CompilationRequestResult;
import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.runtime.JVMCICompiler;
import jdk.vm.ci.runtime.JVMCICompilerFactory;
@ -33,7 +34,7 @@ final class HotSpotJVMCICompilerConfig {
private static class DummyCompilerFactory implements JVMCICompilerFactory, JVMCICompiler {
public void compileMethod(CompilationRequest request) {
public CompilationRequestResult compileMethod(CompilationRequest request) {
throw new JVMCIError("no JVMCI compiler selected");
}

View file

@ -38,6 +38,7 @@ import java.util.Objects;
import java.util.TreeMap;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.CompilationRequestResult;
import jdk.vm.ci.code.CompiledCode;
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.common.JVMCIError;
@ -327,8 +328,10 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H
* Called from the VM.
*/
@SuppressWarnings({"unused"})
private void compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id));
private CompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id));
assert result != null : "compileMethod must always return something";
return result;
}
/**

View file

@ -23,6 +23,7 @@
package jdk.vm.ci.runtime;
import jdk.vm.ci.code.CompilationRequest;
import jdk.vm.ci.code.CompilationRequestResult;
public interface JVMCICompiler {
int INVOCATION_ENTRY_BCI = -1;
@ -31,5 +32,5 @@ public interface JVMCICompiler {
* Services a compilation request. This object should compile the method to machine code and
* install it in the code cache if the compilation is successful.
*/
void compileMethod(CompilationRequest request);
CompilationRequestResult compileMethod(CompilationRequest request);
}

View file

@ -1798,6 +1798,8 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
push_jni_handle_block();
Method* target_handle = task->method();
int compilable = ciEnv::MethodCompilable;
const char* failure_reason = NULL;
const char* retry_message = NULL;
AbstractCompiler *comp = compiler(task_level);
int system_dictionary_modification_counter;
@ -1817,10 +1819,16 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
jvmci->compile_method(method, osr_bci, &env);
post_compile(thread, task, event, task->code() != NULL, NULL);
failure_reason = env.failure_reason();
if (!env.retryable()) {
retry_message = "not retryable";
compilable = ciEnv::MethodCompilable_not_at_tier;
}
} else
#endif // INCLUDE_JVMCI
{
NoHandleMark nhm;
ThreadToNativeFromVM ttn(thread);
@ -1868,24 +1876,30 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
compilable = ci_env.compilable();
if (ci_env.failing()) {
task->set_failure_reason(ci_env.failure_reason());
ci_env.report_failure(ci_env.failure_reason());
const char* retry_message = ci_env.retry_message();
if (_compilation_log != NULL) {
_compilation_log->log_failure(thread, task, ci_env.failure_reason(), retry_message);
}
if (PrintCompilation) {
FormatBufferResource msg = retry_message != NULL ?
FormatBufferResource("COMPILE SKIPPED: %s (%s)", ci_env.failure_reason(), retry_message) :
FormatBufferResource("COMPILE SKIPPED: %s", ci_env.failure_reason());
task->print(tty, msg);
}
failure_reason = ci_env.failure_reason();
retry_message = ci_env.retry_message();
ci_env.report_failure(failure_reason);
}
post_compile(thread, task, event, !ci_env.failing(), &ci_env);
}
// Remove the JNI handle block after the ciEnv destructor has run in
// the previous block.
pop_jni_handle_block();
if (failure_reason != NULL) {
task->set_failure_reason(failure_reason);
if (_compilation_log != NULL) {
_compilation_log->log_failure(thread, task, failure_reason, retry_message);
}
if (PrintCompilation) {
FormatBufferResource msg = retry_message != NULL ?
FormatBufferResource("COMPILE SKIPPED: %s (%s)", failure_reason, retry_message) :
FormatBufferResource("COMPILE SKIPPED: %s", failure_reason);
task->print(tty, msg);
}
}
methodHandle method(thread, task->method());
DTRACE_METHOD_COMPILE_END_PROBE(method, compiler_name(task_level), task->is_success());

View file

@ -134,7 +134,6 @@ void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JV
JVMCIRuntime::initialize_well_known_classes(CHECK_ABORT);
HandleMark hm;
ResourceMark rm;
Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_ABORT);
JavaValue method_result(T_OBJECT);
@ -143,8 +142,8 @@ void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JV
JavaCalls::call_static(&method_result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(),
vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, THREAD);
JavaValue result(T_OBJECT);
if (!HAS_PENDING_EXCEPTION) {
JavaValue result(T_VOID);
JavaCallArguments args;
args.push_oop(receiver);
args.push_oop((oop)method_result.get_jobject());
@ -164,11 +163,26 @@ void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JV
java_lang_Throwable::java_printStackTrace(exception, THREAD);
// Something went wrong so disable compilation at this level
method->set_not_compilable(CompLevel_full_optimization);
env->set_failure("exception throw", false);
} else {
oop result_object = (oop) result.get_jobject();
if (result_object != NULL) {
oop failure_message = CompilationRequestResult::failureMessage(result_object);
if (failure_message != NULL) {
const char* failure_reason = java_lang_String::as_utf8_string(failure_message);
env->set_failure(failure_reason, CompilationRequestResult::retry(result_object) != 0);
} else {
if (env->task()->code() == NULL) {
env->set_failure("no nmethod produced", true);
} else {
env->task()->set_num_inlined_bytecodes(CompilationRequestResult::inlinedBytecodes(result_object));
_methodsCompiled++;
}
}
} else {
assert(false, "JVMCICompiler.compileMethod should always return non-null");
}
}
}
/**

View file

@ -834,30 +834,6 @@ C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject
return result;
C2V_END
C2V_VMENTRY(void, notifyCompilationStatistics, (JNIEnv *jniEnv, jobject, jint id, jobject hotspot_method, jboolean osr, jint processedBytecodes, jlong time, jlong timeUnitsPerSecond, jobject installed_code))
JVMCICompiler* compiler = JVMCICompiler::instance(CHECK);
CompilerStatistics* stats = compiler->stats();
elapsedTimer timer = elapsedTimer(time, timeUnitsPerSecond);
if (osr) {
stats->_osr.update(timer, processedBytecodes);
} else {
stats->_standard.update(timer, processedBytecodes);
}
Handle installed_code_handle = JNIHandles::resolve(installed_code);
if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
stats->_nmethods_size += HotSpotInstalledCode::size(installed_code_handle);
stats->_nmethods_code_size += HotSpotInstalledCode::codeSize(installed_code_handle);
}
if (CITimeEach) {
methodHandle method = CompilerToVM::asMethod(hotspot_method);
float bytes_per_sec = 1.0 * processedBytecodes / timer.seconds();
tty->print_cr("%3d seconds: %f bytes/sec: %f (bytes %d)",
id, timer.seconds(), bytes_per_sec, processedBytecodes);
}
C2V_END
C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject))
JVMCICompiler* compiler = JVMCICompiler::instance(CHECK);
CompilerStatistics* stats = compiler->stats();
@ -1447,7 +1423,6 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC"initializeConfiguration", CC"("HS_CONFIG")J", FN_PTR(initializeConfiguration)},
{CC"installCode", CC"("TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE HS_SPECULATION_LOG")I", FN_PTR(installCode)},
{CC"getMetadata", CC"("TARGET_DESCRIPTION HS_COMPILED_CODE HS_METADATA")I", FN_PTR(getMetadata)},
{CC"notifyCompilationStatistics", CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V", FN_PTR(notifyCompilationStatistics)},
{CC"resetCompilationStatistics", CC"()V", FN_PTR(resetCompilationStatistics)},
{CC"disassembleCodeBlob", CC"("INSTALLED_CODE")"STRING, FN_PTR(disassembleCodeBlob)},
{CC"executeInstalledCode", CC"(["OBJECT INSTALLED_CODE")"OBJECT, FN_PTR(executeInstalledCode)},

View file

@ -48,16 +48,17 @@
#include "jvmci/jvmciRuntime.hpp"
#include "jvmci/jvmciJavaClasses.hpp"
JVMCIEnv::JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter) {
_task = task;
_system_dictionary_modification_counter = system_dictionary_modification_counter;
{
JVMCIEnv::JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter):
_task(task),
_system_dictionary_modification_counter(system_dictionary_modification_counter),
_failure_reason(NULL),
_retryable(true)
{
// Get Jvmti capabilities under lock to get consistent values.
MutexLocker mu(JvmtiThreadState_lock);
_jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint();
_jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables();
_jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions();
}
}
// ------------------------------------------------------------------
@ -534,7 +535,9 @@ JVMCIEnv::CodeInstallResult JVMCIEnv::register_method(
// Record successful registration.
// (Put nm into the task handle *before* publishing to the Java heap.)
CompileTask* task = env == NULL ? NULL : env->task();
if (task != NULL) task->set_code(nm);
if (task != NULL) {
task->set_code(nm);
}
if (installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(installed_code())) {
if (entry_bci == InvocationEntryBci) {

View file

@ -100,6 +100,10 @@ private:
CompileTask* _task;
int _system_dictionary_modification_counter;
// Compilation result values
const char* _failure_reason;
bool _retryable;
// Cache JVMTI state
bool _jvmti_can_hotswap_or_post_breakpoint;
bool _jvmti_can_access_local_variables;
@ -141,6 +145,14 @@ private:
public:
CompileTask* task() { return _task; }
const char* failure_reason() { return _failure_reason; }
bool retryable() { return _retryable; }
void set_failure(const char* reason, bool retryable) {
_failure_reason = reason;
_retryable = retryable;
}
// Register the result of a compilation.
static JVMCIEnv::CodeInstallResult register_method(
const methodHandle& target,

View file

@ -161,6 +161,11 @@ class JVMCIJavaClasses : AllStatic {
start_class(site_Mark) \
oop_field(site_Mark, id, "Ljava/lang/Object;") \
end_class \
start_class(CompilationRequestResult) \
oop_field(CompilationRequestResult, failureMessage, "Ljava/lang/String;") \
boolean_field(CompilationRequestResult, retry) \
int_field(CompilationRequestResult, inlinedBytecodes) \
end_class \
start_class(DebugInfo) \
oop_field(DebugInfo, bytecodePosition, "Ljdk/vm/ci/code/BytecodePosition;") \
oop_field(DebugInfo, referenceMap, "Ljdk/vm/ci/code/ReferenceMap;") \

View file

@ -60,6 +60,7 @@
do_klass(DebugInfo_klass, jdk_vm_ci_code_DebugInfo, Jvmci) \
do_klass(RegisterSaveLayout_klass, jdk_vm_ci_code_RegisterSaveLayout, Jvmci) \
do_klass(BytecodeFrame_klass, jdk_vm_ci_code_BytecodeFrame, Jvmci) \
do_klass(CompilationRequestResult_klass, jdk_vm_ci_code_CompilationRequestResult, Jvmci) \
do_klass(InstalledCode_klass, jdk_vm_ci_code_InstalledCode, Jvmci) \
do_klass(code_Location_klass, jdk_vm_ci_code_Location, Jvmci) \
do_klass(code_Register_klass, jdk_vm_ci_code_Register, Jvmci) \

View file

@ -66,6 +66,7 @@
template(jdk_vm_ci_code_Architecture, "jdk/vm/ci/code/Architecture") \
template(jdk_vm_ci_code_BytecodeFrame, "jdk/vm/ci/code/BytecodeFrame") \
template(jdk_vm_ci_code_BytecodePosition, "jdk/vm/ci/code/BytecodePosition") \
template(jdk_vm_ci_code_CompilationRequestResult, "jdk/vm/ci/code/CompilationRequestResult") \
template(jdk_vm_ci_code_DebugInfo, "jdk/vm/ci/code/DebugInfo") \
template(jdk_vm_ci_code_InstalledCode, "jdk/vm/ci/code/InstalledCode") \
template(jdk_vm_ci_code_Location, "jdk/vm/ci/code/Location") \
@ -88,7 +89,7 @@
template(jdk_vm_ci_code_site_InfopointReason, "jdk/vm/ci/code/site/InfopointReason") \
template(jdk_vm_ci_common_JVMCIError, "jdk/vm/ci/common/JVMCIError") \
template(compileMethod_name, "compileMethod") \
template(compileMethod_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)V") \
template(compileMethod_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)Ljdk/vm/ci/code/CompilationRequestResult;") \
template(fromMetaspace_name, "fromMetaspace") \
template(method_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;") \
template(constantPool_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotConstantPool;") \

View file

@ -148,14 +148,6 @@ public class CompilerToVMHelper {
return CTVM.getMetadata(target, compiledCode, metaData);
}
public static void notifyCompilationStatistics(int id,
HotSpotResolvedJavaMethod method, boolean osr,
int processedBytecodes, long time, long timeUnitsPerSecond,
InstalledCode installedCode) {
CTVM.notifyCompilationStatistics(id, (HotSpotResolvedJavaMethodImpl) method, osr, processedBytecodes,
time, timeUnitsPerSecond, installedCode);
}
public static void resetCompilationStatistics() {
CTVM.resetCompilationStatistics();
}

View file

@ -25,6 +25,7 @@ package compiler.jvmci.common;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.CompilationRequest;
import jdk.vm.ci.code.CompilationRequestResult;
import jdk.vm.ci.hotspot.HotSpotVMEventListener;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.runtime.JVMCICompiler;
@ -43,8 +44,9 @@ public class JVMCIHelpers {
public static class EmptyHotspotCompiler implements JVMCICompiler {
@Override
public void compileMethod(CompilationRequest request) {
public CompilationRequestResult compileMethod(CompilationRequest request) {
// do nothing
return CompilationRequestResult.failure("no compiler configured", true);
}
}