Skip to content

8334247: [PPC64] Consider trap based nmethod entry barriers #24135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/hotspot/cpu/ppc/assembler_ppc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2058,12 +2058,12 @@ class Assembler : public AbstractAssembler {
protected:
inline void tdi_unchecked(int tobits, Register a, int si16);
inline void twi_unchecked(int tobits, Register a, int si16);
public:
inline void tdi( int tobits, Register a, int si16); // asserts UseSIGTRAP
inline void twi( int tobits, Register a, int si16); // asserts UseSIGTRAP
inline void td( int tobits, Register a, Register b); // asserts UseSIGTRAP
inline void tw( int tobits, Register a, Register b); // asserts UseSIGTRAP

public:
static bool is_tdi(int x, int tobits, int ra, int si16) {
return (TDI_OPCODE == (x & TDI_OPCODE_MASK))
&& (tobits == inv_to_field(x))
Expand Down
18 changes: 12 additions & 6 deletions src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,20 +185,26 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register t

__ block_comment("nmethod_entry_barrier (nmethod_entry_barrier) {");

// Load stub address using toc (fixed instruction size, unlike load_const_optimized)
__ calculate_address_from_global_toc(tmp, StubRoutines::method_entry_barrier(),
true, true, false); // 2 instructions
__ mtctr(tmp);
if (!TrapBasedNMethodEntryBarriers) {
// Load stub address using toc (fixed instruction size, unlike load_const_optimized)
__ calculate_address_from_global_toc(tmp, StubRoutines::method_entry_barrier(),
true, true, false); // 2 instructions
__ mtctr(tmp);
}

// This is a compound instruction. Patching support is provided by NativeMovRegMem.
// Actual patching is done in (platform-specific part of) BarrierSetNMethod.
__ load_const32(tmp, 0 /* Value is patched */); // 2 instructions

// Low order half of 64 bit value is currently used.
__ ld(R0, in_bytes(bs_nm->thread_disarmed_guard_value_offset()), R16_thread);
__ cmpw(CR0, R0, tmp);

__ bnectrl(CR0);
if (TrapBasedNMethodEntryBarriers) {
__ tw(Assembler::traptoLessThanUnsigned | Assembler::traptoGreaterThanUnsigned, R0, tmp);
} else {
__ cmpw(CR0, R0, tmp);
__ bnectrl(CR0);
}

// Oops may have been changed. Make those updates observable.
// "isync" can serve both, data and instruction patching.
Expand Down
30 changes: 19 additions & 11 deletions src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class NativeNMethodBarrier: public NativeInstruction {

NativeMovRegMem* get_patchable_instruction_handle() const {
// Endianness is handled by NativeMovRegMem
return reinterpret_cast<NativeMovRegMem*>(get_barrier_start_address() + 3 * 4);
return reinterpret_cast<NativeMovRegMem*>(get_barrier_start_address() +
(TrapBasedNMethodEntryBarriers ? 0 : 3) * BytesPerInstWord);
}

public:
Expand Down Expand Up @@ -66,22 +67,28 @@ class NativeNMethodBarrier: public NativeInstruction {

uint* current_instruction = reinterpret_cast<uint*>(get_barrier_start_address());

// calculate_address_from_global_toc (compound instruction)
verify_op_code_manually(current_instruction, MacroAssembler::is_addis(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_addi(*current_instruction));
if (!TrapBasedNMethodEntryBarriers) {
// calculate_address_from_global_toc (compound instruction)
verify_op_code_manually(current_instruction, MacroAssembler::is_addis(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_addi(*current_instruction));

verify_op_code_manually(current_instruction, MacroAssembler::is_mtctr(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_mtctr(*current_instruction));
}

get_patchable_instruction_handle()->verify();
current_instruction += 2;

verify_op_code(current_instruction, Assembler::LD_OPCODE);

// cmpw (mnemonic)
verify_op_code(current_instruction, Assembler::CMP_OPCODE);
if (TrapBasedNMethodEntryBarriers) {
verify_op_code(current_instruction, Assembler::TW_OPCODE);
} else {
// cmpw (mnemonic)
verify_op_code(current_instruction, Assembler::CMP_OPCODE);

// bnectrl (mnemonic) (weak check; not checking the exact type)
verify_op_code(current_instruction, Assembler::BCCTR_OPCODE);
// bnectrl (mnemonic) (weak check; not checking the exact type)
verify_op_code(current_instruction, Assembler::BCCTR_OPCODE);
}

// isync is optional
}
Expand All @@ -102,9 +109,10 @@ class NativeNMethodBarrier: public NativeInstruction {

static NativeNMethodBarrier* get_nmethod_barrier(nmethod* nm) {
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
address barrier_address = nm->code_begin() + nm->frame_complete_offset() + (-8 * 4);
address barrier_address = nm->code_begin() + nm->frame_complete_offset() -
(TrapBasedNMethodEntryBarriers ? 4 : 8) * BytesPerInstWord;
if (bs_asm->nmethod_patching_type() != NMethodPatchingType::stw_instruction_and_data_patch) {
barrier_address -= 4; // isync (see nmethod_entry_barrier)
barrier_address -= BytesPerInstWord; // isync (see nmethod_entry_barrier)
}

auto barrier = reinterpret_cast<NativeNMethodBarrier*>(barrier_address);
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/cpu/ppc/globals_ppc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong);
"switch off all optimizations requiring SIGTRAP.") \
product(bool, TrapBasedICMissChecks, true, DIAGNOSTIC, \
"Raise and handle SIGTRAP if inline cache miss detected.") \
product(bool, TrapBasedNMethodEntryBarriers, true, DIAGNOSTIC, \
"Raise and handle SIGTRAP if nmethod entry barrier armed.") \
\
product(bool, TraceTraps, false, DIAGNOSTIC, \
"Trace all traps the signal handler handles.") \
Expand Down
6 changes: 6 additions & 0 deletions src/hotspot/cpu/ppc/nativeInst_ppc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ class NativeInstruction {
}
#endif

bool is_sigtrap_nmethod_entry_barrier() {
assert(UseSIGTRAP && TrapBasedNMethodEntryBarriers, "precondition");
return Assembler::is_tw(long_at(0), Assembler::traptoLessThanUnsigned | Assembler::traptoGreaterThanUnsigned,
0, -1);
}

bool is_safepoint_poll() {
// The current arguments of the instruction are not checked!
if (USE_POLL_BIT_ONLY) {
Expand Down
6 changes: 4 additions & 2 deletions src/hotspot/cpu/ppc/vm_version_ppc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ void VM_Version::initialize() {
if (!UseSIGTRAP) {
MSG(TrapBasedICMissChecks);
MSG(TrapBasedNullChecks);
FLAG_SET_ERGO(TrapBasedNullChecks, false);
FLAG_SET_ERGO(TrapBasedICMissChecks, false);
MSG(TrapBasedNMethodEntryBarriers);
FLAG_SET_ERGO(TrapBasedNullChecks, false);
FLAG_SET_ERGO(TrapBasedICMissChecks, false);
FLAG_SET_ERGO(TrapBasedNMethodEntryBarriers, false);
}

#ifdef COMPILER2
Expand Down
15 changes: 14 additions & 1 deletion src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
* Copyright (c) 2012, 2025 SAP SE. 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 @@ -254,6 +254,18 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
goto run_stub;
}

// SIGTRAP-based nmethod entry barriers.
else if (sig == SIGTRAP && TrapBasedNMethodEntryBarriers &&
nativeInstruction_at(pc)->is_sigtrap_nmethod_entry_barrier() &&
CodeCache::contains((void*) pc)) {
if (TraceTraps) {
tty->print_cr("trap: nmethod entry barrier at " INTPTR_FORMAT " (SIGTRAP)", p2i(pc));
}
stub = StubRoutines::method_entry_barrier();
uc->uc_mcontext.jmp_context.lr = (uintptr_t)(pc + BytesPerInstWord); // emulate call by setting LR
goto run_stub;
}

// SIGTRAP-based ic miss check in compiled code.
else if (sig == SIGTRAP && TrapBasedICMissChecks &&
nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) {
Expand Down Expand Up @@ -282,6 +294,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", p2i(pc));
}
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
goto run_stub;
}

#ifdef COMPILER2
Expand Down
13 changes: 12 additions & 1 deletion src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
* Copyright (c) 2012, 2025 SAP SE. 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 @@ -286,6 +286,17 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
stub = SharedRuntime::polling_page_return_handler_blob()->entry_point();
}

// SIGTRAP-based nmethod entry barriers.
else if (sig == SIGTRAP && TrapBasedNMethodEntryBarriers &&
nativeInstruction_at(pc)->is_sigtrap_nmethod_entry_barrier() &&
CodeCache::contains((void*) pc)) {
if (TraceTraps) {
tty->print_cr("trap: nmethod entry barrier at " INTPTR_FORMAT " (SIGTRAP)", p2i(pc));
}
stub = StubRoutines::method_entry_barrier();
uc->uc_mcontext.regs->link = (uintptr_t)(pc + BytesPerInstWord); // emulate call by setting LR
}

// SIGTRAP-based ic miss check in compiled code.
else if (sig == SIGTRAP && TrapBasedICMissChecks &&
nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) {
Expand Down