Skip to content

Commit 4856344

Browse files
chadrakoVladimir Kozlov
authored andcommitted
8371046: Segfault in compiler/whitebox/StressNMethodRelocation.java with -XX:+UseZGC
Reviewed-by: kvn, eastigeevich
1 parent 8f8fda7 commit 4856344

File tree

7 files changed

+43
-26
lines changed

7 files changed

+43
-26
lines changed

src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void Relocation::pd_set_call_destination(address x) {
8585
} else {
8686
MacroAssembler::pd_patch_instruction(addr(), x);
8787
}
88-
assert(pd_call_destination(addr()) == x, "fail in reloc");
88+
guarantee(pd_call_destination(addr()) == x, "fail in reloc");
8989
}
9090

9191
void trampoline_stub_Relocation::pd_fix_owner_after_move() {

src/hotspot/share/asm/codeBuffer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ typedef CodeBuffer::csize_t csize_t; // file-local definition
9090

9191
// External buffer, in a predefined CodeBlob.
9292
// Important: The code_start must be taken exactly, and not realigned.
93-
CodeBuffer::CodeBuffer(CodeBlob* blob) DEBUG_ONLY(: Scrubber(this, sizeof(*this))) {
93+
CodeBuffer::CodeBuffer(const CodeBlob* blob) DEBUG_ONLY(: Scrubber(this, sizeof(*this))) {
9494
// Provide code buffer with meaningful name
9595
initialize_misc(blob->name());
9696
initialize(blob->content_begin(), blob->content_size());

src/hotspot/share/asm/codeBuffer.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) {
672672
}
673673

674674
// (2) CodeBuffer referring to pre-allocated CodeBlob.
675-
CodeBuffer(CodeBlob* blob);
675+
CodeBuffer(const CodeBlob* blob);
676676

677677
// (3) code buffer allocating codeBlob memory for code & relocation
678678
// info but with lazy initialization. The name must be something

src/hotspot/share/code/nmethod.cpp

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,40 @@ nmethod::nmethod(const nmethod &nm) : CodeBlob(nm._name, nm._kind, nm._size, nm.
14981498
// - OOP table
14991499
memcpy(consts_begin(), nm.consts_begin(), nm.data_end() - nm.consts_begin());
15001500

1501+
// Fix relocation
1502+
RelocIterator iter(this);
1503+
CodeBuffer src(&nm);
1504+
CodeBuffer dst(this);
1505+
while (iter.next()) {
1506+
#ifdef USE_TRAMPOLINE_STUB_FIX_OWNER
1507+
// After an nmethod is moved, some direct call sites may end up out of range.
1508+
// CallRelocation::fix_relocation_after_move() assumes the target is always
1509+
// reachable and does not check branch range. Calling it without range checks
1510+
// could cause us to write an offset too large for the instruction.
1511+
//
1512+
// If a call site has a trampoline, we skip the normal call relocation. The
1513+
// associated trampoline_stub_Relocation will handle the call and the
1514+
// trampoline, including range checks and updating the branch as needed.
1515+
//
1516+
// If no trampoline exists, we can assume the call target is always
1517+
// reachable and therefore within direct branch range, so calling
1518+
// CallRelocation::fix_relocation_after_move() is safe.
1519+
if (iter.reloc()->is_call()) {
1520+
address trampoline = trampoline_stub_Relocation::get_trampoline_for(iter.reloc()->addr(), this);
1521+
if (trampoline != nullptr) {
1522+
continue;
1523+
}
1524+
}
1525+
#endif
1526+
1527+
iter.reloc()->fix_relocation_after_move(&src, &dst);
1528+
}
1529+
1530+
{
1531+
MutexLocker ml(NMethodState_lock, Mutex::_no_safepoint_check_flag);
1532+
clear_inline_caches();
1533+
}
1534+
15011535
post_init();
15021536
}
15031537

@@ -1521,25 +1555,6 @@ nmethod* nmethod::relocate(CodeBlobType code_blob_type) {
15211555
return nullptr;
15221556
}
15231557

1524-
// Fix relocation
1525-
RelocIterator iter(nm_copy);
1526-
CodeBuffer src(this);
1527-
CodeBuffer dst(nm_copy);
1528-
while (iter.next()) {
1529-
#ifdef USE_TRAMPOLINE_STUB_FIX_OWNER
1530-
// Direct calls may no longer be in range and the use of a trampoline may now be required.
1531-
// Instead, allow trampoline relocations to update their owners and perform the necessary checks.
1532-
if (iter.reloc()->is_call()) {
1533-
address trampoline = trampoline_stub_Relocation::get_trampoline_for(iter.reloc()->addr(), nm_copy);
1534-
if (trampoline != nullptr) {
1535-
continue;
1536-
}
1537-
}
1538-
#endif
1539-
1540-
iter.reloc()->fix_relocation_after_move(&src, &dst);
1541-
}
1542-
15431558
// To make dependency checking during class loading fast, record
15441559
// the nmethod dependencies in the classes it is dependent on.
15451560
// This allows the dependency checking code to simply walk the
@@ -1569,16 +1584,14 @@ nmethod* nmethod::relocate(CodeBlobType code_blob_type) {
15691584
if (!is_marked_for_deoptimization() && is_in_use()) {
15701585
assert(method() != nullptr && method()->code() == this, "should be if is in use");
15711586

1572-
nm_copy->clear_inline_caches();
1573-
15741587
// Attempt to start using the copy
15751588
if (nm_copy->make_in_use()) {
15761589
ICache::invalidate_range(nm_copy->code_begin(), nm_copy->code_size());
15771590

15781591
methodHandle mh(Thread::current(), nm_copy->method());
15791592
nm_copy->method()->set_code(mh, nm_copy);
15801593

1581-
make_not_used();
1594+
make_not_entrant(InvalidationReason::RELOCATED);
15821595

15831596
nm_copy->post_compiled_method_load_event();
15841597

src/hotspot/share/code/nmethod.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ class nmethod : public CodeBlob {
499499
UNCOMMON_TRAP,
500500
WHITEBOX_DEOPTIMIZATION,
501501
ZOMBIE,
502+
RELOCATED,
502503
INVALIDATION_REASONS_COUNT
503504
};
504505

@@ -543,6 +544,8 @@ class nmethod : public CodeBlob {
543544
return "whitebox deoptimization";
544545
case InvalidationReason::ZOMBIE:
545546
return "zombie";
547+
case InvalidationReason::RELOCATED:
548+
return "relocated";
546549
default: {
547550
assert(false, "Unhandled reason");
548551
return "Unknown";

src/hotspot/share/jvmci/vmStructs_jvmci.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,7 @@
586586
declare_constant(nmethod::InvalidationReason::UNCOMMON_TRAP) \
587587
declare_constant(nmethod::InvalidationReason::WHITEBOX_DEOPTIMIZATION) \
588588
declare_constant(nmethod::InvalidationReason::ZOMBIE) \
589+
declare_constant(nmethod::InvalidationReason::RELOCATED) \
589590
\
590591
declare_constant(CodeInstaller::VERIFIED_ENTRY) \
591592
declare_constant(CodeInstaller::UNVERIFIED_ENTRY) \

src/hotspot/share/prims/whitebox.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1678,7 +1678,7 @@ WB_ENTRY(void, WB_RelocateNMethodFromAddr(JNIEnv* env, jobject o, jlong addr, ji
16781678
CodeBlob* blob = CodeCache::find_blob(address);
16791679
if (blob != nullptr && blob->is_nmethod()) {
16801680
nmethod* code = blob->as_nmethod();
1681-
if (code->is_in_use()) {
1681+
if (code->is_in_use() && !code->is_unloading()) {
16821682
CompiledICLocker ic_locker(code);
16831683
code->relocate(static_cast<CodeBlobType>(blob_type));
16841684
}

0 commit comments

Comments
 (0)