diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index cfd31b8104afd..c1cab42dfa68d 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1935,6 +1935,14 @@ bool nmethod::is_maybe_on_stack() { void nmethod::inc_decompile_count() { if (!is_compiled_by_c2() && !is_compiled_by_jvmci()) return; // Could be gated by ProfileTraps, but do not bother... +#if INCLUDE_JVMCI + // Deoptimization count is used by the CompileBroker to reason about compilations + // it requests so do not pollute the count for deoptimizations in non-default (i.e. + // non-CompilerBroker) compilations. + if (is_jvmci_hosted()) { + return; + } +#endif Method* m = method(); if (m == nullptr) return; MethodData* mdo = m->method_data(); @@ -4050,4 +4058,8 @@ const char* nmethod::jvmci_name() { } return nullptr; } + +bool nmethod::is_jvmci_hosted() const { + return jvmci_nmethod_data() != nullptr && !jvmci_nmethod_data()->is_default(); +} #endif diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 55e63c33e1ab2..4b63f37ed3fc6 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -913,6 +913,10 @@ class nmethod : public CodeBlob { JVMCINMethodData* jvmci_nmethod_data() const { return jvmci_data_size() == 0 ? nullptr : (JVMCINMethodData*) jvmci_data_begin(); } + + // Returns true if a JVMCI compiled method is non-default, + // i.e., not triggered by CompilerBroker + bool is_jvmci_hosted() const; #endif void oops_do(OopClosure* f) { oops_do(f, false); } diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 24ea4936822ce..ad848998823f2 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -746,6 +746,7 @@ JVM_END void JVMCINMethodData::initialize(int nmethod_mirror_index, int nmethod_entry_patch_offset, const char* nmethod_mirror_name, + bool is_default, FailedSpeculation** failed_speculations) { _failed_speculations = failed_speculations; @@ -753,16 +754,17 @@ void JVMCINMethodData::initialize(int nmethod_mirror_index, guarantee(nmethod_entry_patch_offset != -1, "missing entry barrier"); _nmethod_entry_patch_offset = nmethod_entry_patch_offset; if (nmethod_mirror_name != nullptr) { - _has_name = true; + _properties.bits._has_name = 1; char* dest = (char*) name(); strcpy(dest, nmethod_mirror_name); } else { - _has_name = false; + _properties.bits._has_name = 0; } + _properties.bits._is_default = is_default; } void JVMCINMethodData::copy(JVMCINMethodData* data) { - initialize(data->_nmethod_mirror_index, data->_nmethod_entry_patch_offset, data->name(), data->_failed_speculations); + initialize(data->_nmethod_mirror_index, data->_nmethod_entry_patch_offset, data->name(), data->_properties.bits._is_default, data->_failed_speculations); } void JVMCINMethodData::add_failed_speculation(nmethod* nm, jlong speculation) { @@ -2130,7 +2132,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, JVMCICompileState* compile_state = JVMCIENV->compile_state(); bool failing_dep_is_call_site; result = validate_compile_task_dependencies(dependencies, compile_state, &failure_detail, failing_dep_is_call_site); - if (result != JVMCI::ok) { + if (install_default && result != JVMCI::ok) { // While not a true deoptimization, it is a preemptive decompile. MethodData* mdp = method()->method_data(); if (mdp != nullptr && !failing_dep_is_call_site) { @@ -2151,6 +2153,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, JVMCINMethodData* data = JVMCINMethodData::create(nmethod_mirror_index, nmethod_entry_patch_offset, nmethod_mirror_name, + install_default, failed_speculations); nm = nmethod::new_nmethod(method, compile_id, diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index 95c7d32f928d3..2bb223d8376b4 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -48,9 +48,19 @@ class MetadataHandles; class JVMCINMethodData : public ResourceObj { friend class JVMCIVMStructs; - // Is HotSpotNmethod.name non-null? If so, the value is - // embedded in the end of this object. - bool _has_name; + union JVMCINMethodProperties { + uint8_t value; + struct { + // Is HotSpotNmethod.name non-null? If so, the value is + // embedded in the end of this object. + uint8_t _has_name : 1, + // HotSpotNmethod.isDefault (e.g., compilation scheduled by CompileBroker) + _is_default : 1, + : 6; + } bits; + }; + + JVMCINMethodProperties _properties; // Index for the HotSpotNmethod mirror in the nmethod's oops table. // This is -1 if there is no mirror in the oops table. @@ -76,6 +86,7 @@ class JVMCINMethodData : public ResourceObj { void initialize(int nmethod_mirror_index, int nmethod_entry_patch_offset, const char* nmethod_mirror_name, + bool is_default, FailedSpeculation** failed_speculations); void* operator new(size_t size, const char* nmethod_mirror_name) { @@ -88,11 +99,13 @@ class JVMCINMethodData : public ResourceObj { static JVMCINMethodData* create(int nmethod_mirror_index, int nmethod_entry_patch_offset, const char* nmethod_mirror_name, + bool is_default, FailedSpeculation** failed_speculations) { JVMCINMethodData* result = new (nmethod_mirror_name) JVMCINMethodData(); result->initialize(nmethod_mirror_index, nmethod_entry_patch_offset, nmethod_mirror_name, + is_default, failed_speculations); return result; } @@ -117,7 +130,7 @@ class JVMCINMethodData : public ResourceObj { void add_failed_speculation(nmethod* nm, jlong speculation); // Gets the JVMCI name of the nmethod (which may be null). - const char* name() { return _has_name ? (char*)(((address) this) + sizeof(JVMCINMethodData)) : nullptr; } + const char* name() { return has_name() ? (char*)(((address) this) + sizeof(JVMCINMethodData)) : nullptr; } // Clears the HotSpotNmethod.address field in the mirror. If nm // is dead, the HotSpotNmethod.entryPoint field is also cleared. @@ -132,6 +145,14 @@ class JVMCINMethodData : public ResourceObj { int nmethod_entry_patch_offset() { return _nmethod_entry_patch_offset; } + + bool has_name() { + return _properties.bits._has_name; + } + + bool is_default() { + return _properties.bits._is_default; + } }; // A top level class that represents an initialized JVMCI runtime. diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index ae5a81cf3ac96..b392fecab29f0 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -2363,6 +2363,14 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr ShouldNotReachHere(); } +#if INCLUDE_JVMCI + // Deoptimization count is used by the CompileBroker to reason about compilations + // it requests so do not pollute the count for deoptimizations in non-default (i.e. + // non-CompilerBroker) compilations. + if (nm->is_jvmci_hosted()) { + update_trap_state = false; + } +#endif // Setting +ProfileTraps fixes the following, on all platforms: // The result is infinite heroic-opt-uncommon-trap/deopt/recompile cycles, since the // recompile relies on a MethodData* to record heroic opt failures. @@ -2473,7 +2481,6 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr trap_mdo->inc_tenure_traps(); } } - if (inc_recompile_count) { trap_mdo->inc_overflow_recompile_count(); if ((uint)trap_mdo->overflow_recompile_count() >