Skip to content
Closed
12 changes: 12 additions & 0 deletions src/hotspot/share/code/nmethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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
4 changes: 4 additions & 0 deletions src/hotspot/share/code/nmethod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); }
Expand Down
11 changes: 7 additions & 4 deletions src/hotspot/share/jvmci/jvmciRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,23 +746,25 @@ 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;
_nmethod_mirror_index = 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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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,
Expand Down
31 changes: 26 additions & 5 deletions src/hotspot/share/jvmci/jvmciRuntime.hpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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.
Expand All @@ -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.
Expand Down
9 changes: 8 additions & 1 deletion src/hotspot/share/runtime/deoptimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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() >
Expand Down