Skip to content

Commit

Permalink
Merge branch 'upstream-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Datadog Syncup Service committed Nov 26, 2024
2 parents c90b4a2 + 86d527f commit 7c120da
Show file tree
Hide file tree
Showing 171 changed files with 9,431 additions and 3,338 deletions.
115 changes: 66 additions & 49 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3313,14 +3313,11 @@ void MacroAssembler::store_conditional(Register dst,
}


void MacroAssembler::cmpxchg_narrow_value_helper(Register addr, Register expected,
Register new_val,
void MacroAssembler::cmpxchg_narrow_value_helper(Register addr, Register expected, Register new_val,
enum operand_size size,
Register tmp1, Register tmp2, Register tmp3) {
Register shift, Register mask, Register aligned_addr) {
assert(size == int8 || size == int16, "unsupported operand size");

Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3;

andi(shift, addr, 3);
slli(shift, shift, 3);

Expand All @@ -3335,8 +3332,6 @@ void MacroAssembler::cmpxchg_narrow_value_helper(Register addr, Register expecte
}
sll(mask, mask, shift);

notr(not_mask, mask);

sll(expected, expected, shift);
andr(expected, expected, mask);

Expand All @@ -3353,35 +3348,46 @@ void MacroAssembler::cmpxchg_narrow_value(Register addr, Register expected,
Assembler::Aqrl acquire, Assembler::Aqrl release,
Register result, bool result_as_bool,
Register tmp1, Register tmp2, Register tmp3) {
Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3, old = result, tmp = t0;
assert_different_registers(addr, old, mask, not_mask, new_val, expected, shift, tmp);
cmpxchg_narrow_value_helper(addr, expected, new_val, size, tmp1, tmp2, tmp3);
assert_different_registers(addr, expected, new_val, result, tmp1, tmp2, tmp3, t0, t1);

Label retry, fail, done;
Register scratch0 = t0, aligned_addr = t1;
Register shift = tmp1, mask = tmp2, scratch1 = tmp3;

cmpxchg_narrow_value_helper(addr, expected, new_val, size, shift, mask, aligned_addr);

bind(retry);
Label retry, fail, done;

if (UseZacas) {
lw(old, aligned_addr);
lw(result, aligned_addr);

bind(retry); // amocas loads the current value into result
notr(scratch1, mask);

// if old & mask != expected
andr(tmp, old, mask);
bne(tmp, expected, fail);
andr(scratch0, result, scratch1); // scratch0 = word - cas bits
orr(scratch1, expected, scratch0); // scratch1 = non-cas bits + cas bits
bne(result, scratch1, fail); // cas bits differ, cas failed

andr(tmp, old, not_mask);
orr(tmp, tmp, new_val);
// result is the same as expected, use as expected value.

atomic_cas(old, tmp, aligned_addr, operand_size::int32, acquire, release);
bne(tmp, old, retry);
// scratch0 is still = word - cas bits
// Or in the new value to create complete new value.
orr(scratch0, scratch0, new_val);

mv(scratch1, result); // save our expected value
atomic_cas(result, scratch0, aligned_addr, operand_size::int32, acquire, release);
bne(scratch1, result, retry);
} else {
lr_w(old, aligned_addr, acquire);
andr(tmp, old, mask);
bne(tmp, expected, fail);
notr(scratch1, mask);
bind(retry);

lr_w(result, aligned_addr, acquire);
andr(scratch0, result, mask);
bne(scratch0, expected, fail);

andr(tmp, old, not_mask);
orr(tmp, tmp, new_val);
sc_w(tmp, tmp, aligned_addr, release);
bnez(tmp, retry);
andr(scratch0, result, scratch1); // scratch1 is ~mask
orr(scratch0, scratch0, new_val);
sc_w(scratch0, scratch0, aligned_addr, release);
bnez(scratch0, retry);
}

if (result_as_bool) {
Expand All @@ -3393,10 +3399,10 @@ void MacroAssembler::cmpxchg_narrow_value(Register addr, Register expected,

bind(done);
} else {
andr(tmp, old, mask);

bind(fail);
srl(result, tmp, shift);

andr(scratch0, result, mask);
srl(result, scratch0, shift);

if (size == int8) {
sign_extend(result, result, 8);
Expand All @@ -3416,33 +3422,44 @@ void MacroAssembler::weak_cmpxchg_narrow_value(Register addr, Register expected,
Assembler::Aqrl acquire, Assembler::Aqrl release,
Register result,
Register tmp1, Register tmp2, Register tmp3) {
Register aligned_addr = t1, shift = tmp1, mask = tmp2, not_mask = tmp3, old = result, tmp = t0;
assert_different_registers(addr, old, mask, not_mask, new_val, expected, shift, tmp);
cmpxchg_narrow_value_helper(addr, expected, new_val, size, tmp1, tmp2, tmp3);
assert_different_registers(addr, expected, new_val, result, tmp1, tmp2, tmp3, t0, t1);

Register scratch0 = t0, aligned_addr = t1;
Register shift = tmp1, mask = tmp2, scratch1 = tmp3;

cmpxchg_narrow_value_helper(addr, expected, new_val, size, shift, mask, aligned_addr);

Label fail, done;

if (UseZacas) {
lw(old, aligned_addr);
lw(result, aligned_addr);

// if old & mask != expected
andr(tmp, old, mask);
bne(tmp, expected, fail);
notr(scratch1, mask);

andr(tmp, old, not_mask);
orr(tmp, tmp, new_val);
andr(scratch0, result, scratch1); // scratch0 = word - cas bits
orr(scratch1, expected, scratch0); // scratch1 = non-cas bits + cas bits
bne(result, scratch1, fail); // cas bits differ, cas failed

atomic_cas(tmp, new_val, addr, operand_size::int32, acquire, release);
bne(tmp, old, fail);
// result is the same as expected, use as expected value.

// scratch0 is still = word - cas bits
// Or in the new value to create complete new value.
orr(scratch0, scratch0, new_val);

mv(scratch1, result); // save our expected value
atomic_cas(result, scratch0, aligned_addr, operand_size::int32, acquire, release);
bne(scratch1, result, fail); // This weak, so just bail-out.
} else {
lr_w(old, aligned_addr, acquire);
andr(tmp, old, mask);
bne(tmp, expected, fail);

andr(tmp, old, not_mask);
orr(tmp, tmp, new_val);
sc_w(tmp, tmp, aligned_addr, release);
bnez(tmp, fail);
notr(scratch1, mask);

lr_w(result, aligned_addr, acquire);
andr(scratch0, result, mask);
bne(scratch0, expected, fail);

andr(scratch0, result, scratch1); // scratch1 is ~mask
orr(scratch0, scratch0, new_val);
sc_w(scratch0, scratch0, aligned_addr, release);
bnez(scratch0, fail);
}

// Success
Expand Down
5 changes: 2 additions & 3 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1146,10 +1146,9 @@ class MacroAssembler: public Assembler {
enum operand_size size,
Assembler::Aqrl acquire, Assembler::Aqrl release,
Register result);
void cmpxchg_narrow_value_helper(Register addr, Register expected,
Register new_val,
void cmpxchg_narrow_value_helper(Register addr, Register expected, Register new_val,
enum operand_size size,
Register tmp1, Register tmp2, Register tmp3);
Register shift, Register mask, Register aligned_addr);
void cmpxchg_narrow_value(Register addr, Register expected,
Register new_val,
enum operand_size size,
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2112,7 +2112,7 @@ class StubGenerator: public StubCodeGenerator {

// Remaining count is less than 8 bytes. Fill it by a single store.
// Note that the total length is no less than 8 bytes.
if (t == T_BYTE || t == T_SHORT) {
if (!AvoidUnalignedAccesses && (t == T_BYTE || t == T_SHORT)) {
__ beqz(count, L_exit1);
__ shadd(to, count, to, tmp_reg, shift); // points to the end
__ sd(value, Address(to, -8)); // overwrite some elements
Expand Down
42 changes: 41 additions & 1 deletion src/hotspot/os/posix/os_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2111,7 +2111,7 @@ void os::shutdown() {
// easily trigger secondary faults in those threads. To reduce the likelihood
// of that we use _exit rather than exit, so that no atexit hooks get run.
// But note that os::shutdown() could also trigger secondary faults.
void os::abort(bool dump_core, void* siginfo, const void* context) {
void os::abort(bool dump_core, const void* siginfo, const void* context) {
os::shutdown();
if (dump_core) {
LINUX_ONLY(if (DumpPrivateMappingsInCore) ClassLoader::close_jrt_image();)
Expand Down Expand Up @@ -2186,3 +2186,43 @@ char* os::pd_map_memory(int fd, const char* unused,
bool os::pd_unmap_memory(char* addr, size_t bytes) {
return munmap(addr, bytes) == 0;
}

#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
static ucontext_t _saved_assert_context;
static bool _has_saved_context = false;
#endif // CAN_SHOW_REGISTERS_ON_ASSERT

void os::save_assert_context(const void* ucVoid) {
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
assert(ucVoid != nullptr, "invariant");
assert(!_has_saved_context, "invariant");
memcpy(&_saved_assert_context, ucVoid, sizeof(ucontext_t));
// on Linux ppc64, ucontext_t contains pointers into itself which have to be patched up
// after copying the context (see comment in sys/ucontext.h):
#if defined(PPC64)
*((void**)&_saved_assert_context.uc_mcontext.regs) = &(_saved_assert_context.uc_mcontext.gp_regs);
#elif defined(AMD64)
// In the copied version, fpregs should point to the copied contents.
// Sanity check: fpregs should point into the context.
if ((address)((const ucontext_t*)ucVoid)->uc_mcontext.fpregs > (address)ucVoid) {
size_t fpregs_offset = pointer_delta(((const ucontext_t*)ucVoid)->uc_mcontext.fpregs, ucVoid, 1);
if (fpregs_offset < sizeof(ucontext_t)) {
// Preserve the offset.
*((void**)&_saved_assert_context.uc_mcontext.fpregs) = (void*)((address)(void*)&_saved_assert_context + fpregs_offset);
}
}
#endif
_has_saved_context = true;
#endif // CAN_SHOW_REGISTERS_ON_ASSERT
}

const void* os::get_saved_assert_context(const void** sigInfo) {
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
assert(sigInfo != nullptr, "invariant");
*sigInfo = nullptr;
return _has_saved_context ? &_saved_assert_context : nullptr;
#endif
*sigInfo = nullptr;
return nullptr;
}

15 changes: 11 additions & 4 deletions src/hotspot/os/posix/signals_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,9 +578,8 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info,

// Handle assertion poison page accesses.
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if (!signal_was_handled &&
((sig == SIGSEGV || sig == SIGBUS) && info != nullptr && info->si_addr == g_assert_poison)) {
signal_was_handled = handle_assert_poison_fault(ucVoid, info->si_addr);
if (VMError::was_assert_poison_crash(info)) {
signal_was_handled = handle_assert_poison_fault(ucVoid);
}
#endif

Expand Down Expand Up @@ -1136,8 +1135,16 @@ static const char* get_signal_name(int sig, char* out, size_t outlen) {
}

void os::print_siginfo(outputStream* os, const void* si0) {
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
// If we are here because of an assert/guarantee, we suppress
// printing the siginfo, because it is only an implementation
// detail capturing the context for said assert/guarantee.
if (VMError::was_assert_poison_crash(si0)) {
return;
}
#endif

const siginfo_t* const si = (const siginfo_t*) si0;
const siginfo_t* const si = (const siginfo_t*)si0;

char buf[20];
os->print("siginfo:");
Expand Down
15 changes: 13 additions & 2 deletions src/hotspot/os/posix/vmError_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ static void crash_handler(int sig, siginfo_t* info, void* context) {

// Needed because asserts may happen in error handling too.
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if ((sig == SIGSEGV || sig == SIGBUS) && info != nullptr && info->si_addr == g_assert_poison) {
if (handle_assert_poison_fault(context, info->si_addr)) {
if (VMError::was_assert_poison_crash(info)) {
if (handle_assert_poison_fault(context)) {
return;
}
}
Expand Down Expand Up @@ -127,3 +127,14 @@ void VMError::check_failing_cds_access(outputStream* st, const void* siginfo) {
}
#endif
}

bool VMError::was_assert_poison_crash(const void* siginfo) {
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if (siginfo == nullptr) {
return false;
}
const siginfo_t* const si = (siginfo_t*)siginfo;
return (si->si_signo == SIGSEGV || si->si_signo == SIGBUS) && si->si_addr == g_assert_poison_read_only;
#endif
return false;
}
44 changes: 43 additions & 1 deletion src/hotspot/os/windows/os_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#include "services/runtimeService.hpp"
#include "symbolengine.hpp"
#include "utilities/align.hpp"
#include "utilities/debug.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"
Expand Down Expand Up @@ -1317,7 +1318,7 @@ void os::check_core_dump_prerequisites(char* buffer, size_t bufferSize, bool che
}
}

void os::abort(bool dump_core, void* siginfo, const void* context) {
void os::abort(bool dump_core, const void* siginfo, const void* context) {
EXCEPTION_POINTERS ep;
MINIDUMP_EXCEPTION_INFORMATION mei;
MINIDUMP_EXCEPTION_INFORMATION* pmei;
Expand Down Expand Up @@ -2112,7 +2113,17 @@ bool os::signal_sent_by_kill(const void* siginfo) {
}

void os::print_siginfo(outputStream *st, const void* siginfo) {
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
// If we are here because of an assert/guarantee, we suppress
// printing the siginfo, because it is only an implementation
// detail capturing the context for said assert/guarantee.
if (VMError::was_assert_poison_crash(siginfo)) {
return;
}
#endif

const EXCEPTION_RECORD* const er = (EXCEPTION_RECORD*)siginfo;

st->print("siginfo:");

char tmp[64];
Expand Down Expand Up @@ -2625,6 +2636,14 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
#endif
#endif

#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if (VMError::was_assert_poison_crash(exception_record)) {
if (handle_assert_poison_fault(exceptionInfo)) {
return EXCEPTION_CONTINUE_EXECUTION;
}
}
#endif

if (t != nullptr && t->is_Java_thread()) {
JavaThread* thread = JavaThread::cast(t);
bool in_java = thread->thread_state() == _thread_in_Java;
Expand Down Expand Up @@ -6165,3 +6184,26 @@ void os::print_user_info(outputStream* st) {
void os::print_active_locale(outputStream* st) {
// not implemented yet
}

static CONTEXT _saved_assert_context;
static EXCEPTION_RECORD _saved_exception_record;
static bool _has_saved_context = false;

void os::save_assert_context(const void* ucVoid) {
assert(ucVoid != nullptr, "invariant");
assert(!_has_saved_context, "invariant");
const EXCEPTION_POINTERS* ep = static_cast<const EXCEPTION_POINTERS*>(ucVoid);
memcpy(&_saved_assert_context, ep->ContextRecord, sizeof(CONTEXT));
memcpy(&_saved_exception_record, ep->ExceptionRecord, sizeof(EXCEPTION_RECORD));
_has_saved_context = true;
}

const void* os::get_saved_assert_context(const void** sigInfo) {
assert(sigInfo != nullptr, "invariant");
if (_has_saved_context) {
*sigInfo = &_saved_exception_record;
return &_saved_assert_context;
}
*sigInfo = nullptr;
return nullptr;
}
Loading

0 comments on commit 7c120da

Please sign in to comment.