diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index 2c6b7d7e96ec0..7871134e92349 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -90,7 +90,7 @@ typedef CodeBuffer::csize_t csize_t; // file-local definition // External buffer, in a predefined CodeBlob. // Important: The code_start must be taken exactly, and not realigned. -CodeBuffer::CodeBuffer(CodeBlob* blob) DEBUG_ONLY(: Scrubber(this, sizeof(*this))) { +CodeBuffer::CodeBuffer(const CodeBlob* blob) DEBUG_ONLY(: Scrubber(this, sizeof(*this))) { // Provide code buffer with meaningful name initialize_misc(blob->name()); initialize(blob->content_begin(), blob->content_size()); diff --git a/src/hotspot/share/asm/codeBuffer.hpp b/src/hotspot/share/asm/codeBuffer.hpp index 430d4949467d4..38e151273da95 100644 --- a/src/hotspot/share/asm/codeBuffer.hpp +++ b/src/hotspot/share/asm/codeBuffer.hpp @@ -672,7 +672,7 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) { } // (2) CodeBuffer referring to pre-allocated CodeBlob. - CodeBuffer(CodeBlob* blob); + CodeBuffer(const CodeBlob* blob); // (3) code buffer allocating codeBlob memory for code & relocation // info but with lazy initialization. The name must be something diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index d91af9b4991e1..6b231f13ca8ee 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1498,6 +1498,30 @@ nmethod::nmethod(const nmethod &nm) : CodeBlob(nm._name, nm._kind, nm._size, nm. // - OOP table memcpy(consts_begin(), nm.consts_begin(), nm.data_end() - nm.consts_begin()); + // Fix relocation + RelocIterator iter(this); + CodeBuffer src(&nm); + CodeBuffer dst(this); + while (iter.next()) { +#ifdef USE_TRAMPOLINE_STUB_FIX_OWNER + // Direct calls may no longer be in range and the use of a trampoline may now be required. + // Instead, allow trampoline relocations to update their owners and perform the necessary checks. + if (iter.reloc()->is_call()) { + address trampoline = trampoline_stub_Relocation::get_trampoline_for(iter.reloc()->addr(), this); + if (trampoline != nullptr) { + continue; + } + } +#endif + + iter.reloc()->fix_relocation_after_move(&src, &dst); + } + + { + MutexLocker ml(NMethodState_lock, Mutex::_no_safepoint_check_flag); + clear_inline_caches(); + } + post_init(); } @@ -1521,25 +1545,6 @@ nmethod* nmethod::relocate(CodeBlobType code_blob_type) { return nullptr; } - // Fix relocation - RelocIterator iter(nm_copy); - CodeBuffer src(this); - CodeBuffer dst(nm_copy); - while (iter.next()) { -#ifdef USE_TRAMPOLINE_STUB_FIX_OWNER - // Direct calls may no longer be in range and the use of a trampoline may now be required. - // Instead, allow trampoline relocations to update their owners and perform the necessary checks. - if (iter.reloc()->is_call()) { - address trampoline = trampoline_stub_Relocation::get_trampoline_for(iter.reloc()->addr(), nm_copy); - if (trampoline != nullptr) { - continue; - } - } -#endif - - iter.reloc()->fix_relocation_after_move(&src, &dst); - } - // To make dependency checking during class loading fast, record // the nmethod dependencies in the classes it is dependent on. // This allows the dependency checking code to simply walk the @@ -1569,8 +1574,6 @@ nmethod* nmethod::relocate(CodeBlobType code_blob_type) { if (!is_marked_for_deoptimization() && is_in_use()) { assert(method() != nullptr && method()->code() == this, "should be if is in use"); - nm_copy->clear_inline_caches(); - // Attempt to start using the copy if (nm_copy->make_in_use()) { ICache::invalidate_range(nm_copy->code_begin(), nm_copy->code_size()); @@ -1578,7 +1581,7 @@ nmethod* nmethod::relocate(CodeBlobType code_blob_type) { methodHandle mh(Thread::current(), nm_copy->method()); nm_copy->method()->set_code(mh, nm_copy); - make_not_used(); + make_not_entrant(InvalidationReason::RELOCATED); nm_copy->post_compiled_method_load_event(); diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 34accf428b690..01298842eebe6 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -499,6 +499,7 @@ class nmethod : public CodeBlob { UNCOMMON_TRAP, WHITEBOX_DEOPTIMIZATION, ZOMBIE, + RELOCATED, INVALIDATION_REASONS_COUNT }; @@ -543,6 +544,8 @@ class nmethod : public CodeBlob { return "whitebox deoptimization"; case InvalidationReason::ZOMBIE: return "zombie"; + case InvalidationReason::RELOCATED: + return "relocated"; default: { assert(false, "Unhandled reason"); return "Unknown"; diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 7ef16f6e32cdc..81d0188c162fa 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -585,6 +585,7 @@ declare_constant(nmethod::InvalidationReason::UNCOMMON_TRAP) \ declare_constant(nmethod::InvalidationReason::WHITEBOX_DEOPTIMIZATION) \ declare_constant(nmethod::InvalidationReason::ZOMBIE) \ + declare_constant(nmethod::InvalidationReason::RELOCATED) \ \ declare_constant(CodeInstaller::VERIFIED_ENTRY) \ declare_constant(CodeInstaller::UNVERIFIED_ENTRY) \ diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 8f0a2320288da..b14be889b6db5 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -1678,7 +1678,7 @@ WB_ENTRY(void, WB_RelocateNMethodFromAddr(JNIEnv* env, jobject o, jlong addr, ji CodeBlob* blob = CodeCache::find_blob(address); if (blob != nullptr && blob->is_nmethod()) { nmethod* code = blob->as_nmethod(); - if (code->is_in_use()) { + if (code->is_in_use() && !code->is_unloading()) { CompiledICLocker ic_locker(code); code->relocate(static_cast(blob_type)); }