8283326: Implement SafeFetch statically

Reviewed-by: dholmes, mdoerr, akozlov, lucy
This commit is contained in:
Thomas Stuefe 2022-04-15 10:39:19 +00:00
parent bb7c97bddf
commit bdf8a2a205
37 changed files with 1044 additions and 636 deletions

View File

@ -3986,46 +3986,6 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry,
address* fault_pc, address* continuation_pc) {
// safefetch signatures:
// int SafeFetch32(int* adr, int errValue);
// intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue);
//
// arguments:
// c_rarg0 = adr
// c_rarg1 = errValue
//
// result:
// PPC_RET = *adr or errValue
StubCodeMark mark(this, "StubRoutines", name);
// Entry point, pc or function descriptor.
*entry = __ pc();
// Load *adr into c_rarg1, may fault.
*fault_pc = __ pc();
switch (size) {
case 4:
// int32_t
__ ldrw(c_rarg1, Address(c_rarg0, 0));
break;
case 8:
// int64_t
__ ldr(c_rarg1, Address(c_rarg0, 0));
break;
default:
ShouldNotReachHere();
}
// return errValue or *adr
*continuation_pc = __ pc();
__ mov(r0, c_rarg1);
__ ret(lr);
}
/**
* Arguments:
*
@ -7488,14 +7448,6 @@ class StubGenerator: public StubCodeGenerator {
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dcos)) {
StubRoutines::_dcos = generate_dsin_dcos(/* isCos = */ true);
}
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
&StubRoutines::_safefetch32_continuation_pc);
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
&StubRoutines::_safefetchN_fault_pc,
&StubRoutines::_safefetchN_continuation_pc);
}
void generate_all() {

View File

@ -2837,46 +2837,6 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry, address* fault_pc, address* continuation_pc) {
// safefetch signatures:
// int SafeFetch32(int* adr, int errValue);
// intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue);
//
// arguments:
// R0 = adr
// R1 = errValue
//
// result:
// R0 = *adr or errValue
StubCodeMark mark(this, "StubRoutines", name);
// Entry point, pc or function descriptor.
*entry = __ pc();
// Load *adr into c_rarg2, may fault.
*fault_pc = __ pc();
switch (size) {
case 4: // int32_t
__ ldr_s32(R1, Address(R0));
break;
case 8: // int64_t
Unimplemented();
break;
default:
ShouldNotReachHere();
}
// return errValue or *adr
*continuation_pc = __ pc();
__ mov(R0, R1);
__ ret();
}
void generate_arraycopy_stubs() {
// Note: the disjoint stubs must be generated first, some of
@ -3029,16 +2989,9 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_atomic_load_long_entry = generate_atomic_load_long();
StubRoutines::_atomic_store_long_entry = generate_atomic_store_long();
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
&StubRoutines::_safefetch32_continuation_pc);
assert (sizeof(int) == wordSize, "32-bit architecture");
StubRoutines::_safefetchN_entry = StubRoutines::_safefetch32_entry;
StubRoutines::_safefetchN_fault_pc = StubRoutines::_safefetch32_fault_pc;
StubRoutines::_safefetchN_continuation_pc = StubRoutines::_safefetch32_continuation_pc;
}
void generate_all() {
// Generates all stubs and initializes the entry points

View File

@ -3159,45 +3159,6 @@ class StubGenerator: public StubCodeGenerator {
#endif
}
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry, address* fault_pc, address* continuation_pc) {
// safefetch signatures:
// int SafeFetch32(int* adr, int errValue);
// intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue);
//
// arguments:
// R3_ARG1 = adr
// R4_ARG2 = errValue
//
// result:
// R3_RET = *adr or errValue
StubCodeMark mark(this, "StubRoutines", name);
// Entry point, pc or function descriptor.
*entry = __ function_entry();
// Load *adr into R4_ARG2, may fault.
*fault_pc = __ pc();
switch (size) {
case 4:
// int32_t, signed extended
__ lwa(R4_ARG2, 0, R3_ARG1);
break;
case 8:
// int64_t
__ ld(R4_ARG2, 0, R3_ARG1);
break;
default:
ShouldNotReachHere();
}
// return errValue or *adr
*continuation_pc = __ pc();
__ mr(R3_RET, R4_ARG2);
__ blr();
}
// Stub for BigInteger::multiplyToLen()
//
// Arguments:
@ -4573,14 +4534,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_crc32c_table_addr = StubRoutines::ppc::generate_crc_constants(REVERSE_CRC32C_POLY);
StubRoutines::_updateBytesCRC32C = generate_CRC32_updateBytes(true);
}
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
&StubRoutines::_safefetch32_continuation_pc);
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
&StubRoutines::_safefetchN_fault_pc,
&StubRoutines::_safefetchN_continuation_pc);
}
void generate_all() {

View File

@ -2196,46 +2196,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill");
}
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry,
address* fault_pc, address* continuation_pc) {
// safefetch signatures:
// int SafeFetch32(int* adr, int errValue)
// intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue)
//
// arguments:
// c_rarg0 = adr
// c_rarg1 = errValue
//
// result:
// PPC_RET = *adr or errValue
assert_cond(entry != NULL && fault_pc != NULL && continuation_pc != NULL);
StubCodeMark mark(this, "StubRoutines", name);
// Entry point, pc or function descriptor.
*entry = __ pc();
// Load *adr into c_rarg1, may fault.
*fault_pc = __ pc();
switch (size) {
case 4:
// int32_t
__ lw(c_rarg1, Address(c_rarg0, 0));
break;
case 8:
// int64_t
__ ld(c_rarg1, Address(c_rarg0, 0));
break;
default:
ShouldNotReachHere();
}
// return errValue or *adr
*continuation_pc = __ pc();
__ mv(x10, c_rarg1);
__ ret();
}
// code for comparing 16 bytes of strings with same encoding
void compare_string_16_bytes_same(Label &DIFF1, Label &DIFF2) {
const Register result = x10, str1 = x11, cnt1 = x12, str2 = x13, tmp1 = x28, tmp2 = x29, tmp4 = x7, tmp5 = x31;
@ -3767,13 +3727,6 @@ class StubGenerator: public StubCodeGenerator {
generate_throw_exception("delayed StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address,
SharedRuntime::throw_delayed_StackOverflowError));
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
&StubRoutines::_safefetch32_continuation_pc);
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
&StubRoutines::_safefetchN_fault_pc,
&StubRoutines::_safefetchN_continuation_pc);
}
void generate_all() {

View File

@ -1458,44 +1458,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy (true, "arrayof_oop_arraycopy_uninit", true);
}
void generate_safefetch(const char* name, int size, address* entry, address* fault_pc, address* continuation_pc) {
// safefetch signatures:
// int SafeFetch32(int* adr, int errValue);
// intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue);
//
// arguments:
// Z_ARG1 = adr
// Z_ARG2 = errValue
//
// result:
// Z_RET = *adr or errValue
StubCodeMark mark(this, "StubRoutines", name);
// entry point
// Load *adr into Z_ARG2, may fault.
*entry = *fault_pc = __ pc();
switch (size) {
case 4:
// Sign extended int32_t.
__ z_lgf(Z_ARG2, 0, Z_ARG1);
break;
case 8:
// int64_t
__ z_lg(Z_ARG2, 0, Z_ARG1);
break;
default:
ShouldNotReachHere();
}
// Return errValue or *adr.
*continuation_pc = __ pc();
__ z_lgr(Z_RET, Z_ARG2);
__ z_br(Z_R14);
}
// Call interface for AES_encryptBlock, AES_decryptBlock stubs.
//
// Z_ARG1 - source data block. Ptr to leftmost byte to be processed.
@ -2338,10 +2300,6 @@ class StubGenerator: public StubCodeGenerator {
// Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction.
StubRoutines::zarch::_trot_table_addr = (address)StubRoutines::zarch::_trot_table;
// safefetch stubs
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry, &StubRoutines::_safefetch32_fault_pc, &StubRoutines::_safefetch32_continuation_pc);
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry, &StubRoutines::_safefetchN_fault_pc, &StubRoutines::_safefetchN_continuation_pc);
}

View File

@ -3653,40 +3653,6 @@ class StubGenerator: public StubCodeGenerator {
}
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry,
address* fault_pc, address* continuation_pc) {
// safefetch signatures:
// int SafeFetch32(int* adr, int errValue);
// intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue);
StubCodeMark mark(this, "StubRoutines", name);
// Entry point, pc or function descriptor.
*entry = __ pc();
__ movl(rax, Address(rsp, 0x8));
__ movl(rcx, Address(rsp, 0x4));
// Load *adr into eax, may fault.
*fault_pc = __ pc();
switch (size) {
case 4:
// int32_t
__ movl(rax, Address(rcx, 0));
break;
case 8:
// int64_t
Unimplemented();
break;
default:
ShouldNotReachHere();
}
// Return errValue or *adr.
*continuation_pc = __ pc();
__ ret(0);
}
address generate_method_entry_barrier() {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "nmethod_entry_barrier");
@ -3985,14 +3951,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_dtan = generate_libmTan();
}
}
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
&StubRoutines::_safefetch32_continuation_pc);
StubRoutines::_safefetchN_entry = StubRoutines::_safefetch32_entry;
StubRoutines::_safefetchN_fault_pc = StubRoutines::_safefetch32_fault_pc;
StubRoutines::_safefetchN_continuation_pc = StubRoutines::_safefetch32_continuation_pc;
}
void generate_all() {

View File

@ -3836,46 +3836,6 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry,
address* fault_pc, address* continuation_pc) {
// safefetch signatures:
// int SafeFetch32(int* adr, int errValue);
// intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue);
//
// arguments:
// c_rarg0 = adr
// c_rarg1 = errValue
//
// result:
// PPC_RET = *adr or errValue
StubCodeMark mark(this, "StubRoutines", name);
// Entry point, pc or function descriptor.
*entry = __ pc();
// Load *adr into c_rarg1, may fault.
*fault_pc = __ pc();
switch (size) {
case 4:
// int32_t
__ movl(c_rarg1, Address(c_rarg0, 0));
break;
case 8:
// int64_t
__ movq(c_rarg1, Address(c_rarg0, 0));
break;
default:
ShouldNotReachHere();
}
// return errValue or *adr
*continuation_pc = __ pc();
__ movq(rax, c_rarg1);
__ ret(0);
}
// This is a version of CBC/AES Decrypt which does 4 blocks in a loop at a time
// to hide instruction latency
//
@ -7672,14 +7632,6 @@ address generate_avx_ghash_processBlocks() {
StubRoutines::_dtan = generate_libmTan();
}
}
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
&StubRoutines::_safefetch32_continuation_pc);
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
&StubRoutines::_safefetchN_fault_pc,
&StubRoutines::_safefetchN_continuation_pc);
}
void generate_all() {

View File

@ -43,18 +43,6 @@
#include "opto/runtime.hpp"
#endif
// For SafeFetch we need POSIX tls and setjmp
#include <setjmp.h>
#include <pthread.h>
static pthread_key_t g_jmpbuf_key;
// return the currently active jump buffer for this thread
// - if there is any, NULL otherwise. Called from
// zero signal handlers.
extern sigjmp_buf* get_jmp_buf_for_continuation() {
return (sigjmp_buf*) pthread_getspecific(g_jmpbuf_key);
}
// Declaration and definition of StubGenerator (no .hpp file).
// For a more detailed description of the stub routine structure
// see the comment in stubRoutines.hpp
@ -188,57 +176,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_oop_arraycopy;
}
static int SafeFetch32(int *adr, int errValue) {
// set up a jump buffer; anchor the pointer to the jump buffer in tls; then
// do the pointer access. If pointer is invalid, we crash; in signal
// handler, we retrieve pointer to jmp buffer from tls, and jump back.
//
// Note: the jump buffer itself - which can get pretty large depending on
// the architecture - lives on the stack and that is fine, because we will
// not rewind the stack: either we crash, in which case signal handler
// frame is below us, or we don't crash, in which case it does not matter.
sigjmp_buf jb;
if (sigsetjmp(jb, 1)) {
// we crashed. clean up tls and return default value.
pthread_setspecific(g_jmpbuf_key, NULL);
return errValue;
} else {
// preparation phase
pthread_setspecific(g_jmpbuf_key, &jb);
}
int value = errValue;
value = *adr;
// all went well. clean tls.
pthread_setspecific(g_jmpbuf_key, NULL);
return value;
}
static intptr_t SafeFetchN(intptr_t *adr, intptr_t errValue) {
sigjmp_buf jb;
if (sigsetjmp(jb, 1)) {
// we crashed. clean up tls and return default value.
pthread_setspecific(g_jmpbuf_key, NULL);
return errValue;
} else {
// preparation phase
pthread_setspecific(g_jmpbuf_key, &jb);
}
intptr_t value = errValue;
value = *adr;
// all went well. clean tls.
pthread_setspecific(g_jmpbuf_key, NULL);
return value;
}
void generate_initial() {
// Generates all stubs and initializes the entry points
@ -285,15 +222,6 @@ class StubGenerator: public StubCodeGenerator {
// arraycopy stubs used by compilers
generate_arraycopy_stubs();
// Safefetch stubs.
pthread_key_create(&g_jmpbuf_key, NULL);
StubRoutines::_safefetch32_entry = CAST_FROM_FN_PTR(address, StubGenerator::SafeFetch32);
StubRoutines::_safefetch32_fault_pc = NULL;
StubRoutines::_safefetch32_continuation_pc = NULL;
StubRoutines::_safefetchN_entry = CAST_FROM_FN_PTR(address, StubGenerator::SafeFetchN);
StubRoutines::_safefetchN_fault_pc = NULL;
StubRoutines::_safefetchN_continuation_pc = NULL;
}
public:

View File

@ -61,7 +61,7 @@
#include "runtime/os.hpp"
#include "runtime/osThread.hpp"
#include "runtime/perfMemory.hpp"
#include "runtime/safefetch.inline.hpp"
#include "runtime/safefetch.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/statSampler.hpp"
#include "runtime/thread.inline.hpp"
@ -2005,36 +2005,33 @@ static bool checked_mprotect(char* addr, size_t size, int prot) {
//
if (!os::Aix::xpg_sus_mode()) {
if (CanUseSafeFetch32()) {
const bool read_protected =
(SafeFetch32((int*)addr, 0x12345678) == 0x12345678 &&
SafeFetch32((int*)addr, 0x76543210) == 0x76543210) ? true : false;
const bool read_protected =
(SafeFetch32((int*)addr, 0x12345678) == 0x12345678 &&
SafeFetch32((int*)addr, 0x76543210) == 0x76543210) ? true : false;
if (prot & PROT_READ) {
rc = !read_protected;
} else {
rc = read_protected;
}
if (prot & PROT_READ) {
rc = !read_protected;
} else {
rc = read_protected;
}
if (!rc) {
if (os::Aix::on_pase()) {
// There is an issue on older PASE systems where mprotect() will return success but the
// memory will not be protected.
// This has nothing to do with the problem of using mproect() on SPEC1170 incompatible
// machines; we only see it rarely, when using mprotect() to protect the guard page of
// a stack. It is an OS error.
//
// A valid strategy is just to try again. This usually works. :-/
if (!rc) {
if (os::Aix::on_pase()) {
// There is an issue on older PASE systems where mprotect() will return success but the
// memory will not be protected.
// This has nothing to do with the problem of using mproect() on SPEC1170 incompatible
// machines; we only see it rarely, when using mprotect() to protect the guard page of
// a stack. It is an OS error.
//
// A valid strategy is just to try again. This usually works. :-/
::usleep(1000);
Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot);
if (::mprotect(addr, size, prot) == 0) {
const bool read_protected_2 =
(SafeFetch32((int*)addr, 0x12345678) == 0x12345678 &&
SafeFetch32((int*)addr, 0x76543210) == 0x76543210) ? true : false;
rc = true;
}
::usleep(1000);
Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot);
if (::mprotect(addr, size, prot) == 0) {
const bool read_protected_2 =
(SafeFetch32((int*)addr, 0x12345678) == 0x12345678 &&
SafeFetch32((int*)addr, 0x76543210) == 0x76543210) ? true : false;
rc = true;
}
}
}

View File

@ -34,7 +34,7 @@
#include "logging/log.hpp"
#include "runtime/init.hpp"
#include "runtime/os.hpp"
#include "runtime/safefetch.inline.hpp"
#include "runtime/safefetch.hpp"
#include "utilities/align.hpp"
#include "utilities/debug.hpp"
#include "utilities/growableArray.hpp"

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "runtime/safefetch.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#ifdef SAFEFETCH_METHOD_SIGSETJMP
// For SafeFetch we need POSIX TLS and sigsetjmp/longjmp.
#include <setjmp.h>
#include <pthread.h>
static pthread_key_t g_jmpbuf_key;
struct InitTLSKey { InitTLSKey() { pthread_key_create(&g_jmpbuf_key, NULL); } };
static InitTLSKey g_init_tly_key;
// Handle safefetch, sigsetjmp style:
//
// If a safefetch jump had been established and the sig qualifies, we
// jump back to the established jump point (and hence out of signal handling).
//
// Note that this function will never return for safefetch faults. We just
// keep the prototype the same as other handle_safefetch() versions to keep
// caller sites simple.
bool handle_safefetch(int sig, address ignored1, void* ignored2) {
if (sig == SIGSEGV || sig == SIGBUS) {
// Retrieve jump buffer pointer from TLS. If not NULL, it means we set the
// jump buffer and this is indeed a SafeFetch fault.
// Note signal safety: pthread_getspecific is not safe for signal handler
// usage, but in practice it works and we have done this in the JVM for many
// years (via Thread::current_or_null_safe()).
sigjmp_buf* const jb = (sigjmp_buf*) pthread_getspecific(g_jmpbuf_key);
if (jb) {
siglongjmp(*jb, 1);
}
}
return false;
}
template <class T>
static bool _SafeFetchXX_internal(const T *adr, T* result) {
T n = 0;
// Set up a jump buffer. Anchor its pointer in TLS. Then read from the unsafe address.
// If that address was invalid, we fault, and in the signal handler we will jump back
// to the jump point.
sigjmp_buf jb;
if (sigsetjmp(jb, 1) != 0) {
// We faulted. Reset TLS slot, then return.
pthread_setspecific(g_jmpbuf_key, NULL);
*result = 0;
return false;
}
// Anchor jump buffer in TLS
pthread_setspecific(g_jmpbuf_key, &jb);
// unsafe access
n = *adr;
// Still here... All went well, adr was valid.
// Reset TLS slot, then return result.
pthread_setspecific(g_jmpbuf_key, NULL);
*result = n;
return true;
}
int SafeFetch32_impl(int *adr, int errValue) {
int result;
return _SafeFetchXX_internal<int>(adr, &result) ? result : errValue;
}
intptr_t SafeFetchN_impl(intptr_t *adr, intptr_t errValue) {
intptr_t result;
return _SafeFetchXX_internal<intptr_t>(adr, &result) ? result : errValue;
}
#endif // SAFEFETCH_METHOD_SIGSETJMP

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef OS_POSIX_SAFEFETCH_SIGJMP_HPP
#define OS_POSIX_SAFEFETCH_SIGJMP_HPP
#include "utilities/globalDefinitions.hpp"
// On Posix platforms that don't do anything better - or cannot, like Zero -
// SafeFetch is implemented using setjmp/longjmp. That is reliable and portable,
// but slower than other methods, and needs more thread stack (the sigjmp buffer
// lives on the thread stack).
int SafeFetch32_impl(int* adr, int errValue);
intptr_t SafeFetchN_impl(intptr_t* adr, intptr_t errValue);
// Handle safefetch, sigsetjmp style. Only call from signal handler.
// If a safefetch jump had been established and the sig qualifies, we
// jump back to the established jump point (and hence out of signal handling).
bool handle_safefetch(int sig, address pc, void* context);
#endif // OS_POSIX_SAFEFETCH_SIGJMP_HPP

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "runtime/os.hpp"
#include "runtime/safefetch.hpp"
#include "utilities/globalDefinitions.hpp"
#ifdef SAFEFETCH_METHOD_STATIC_ASSEMBLY
// SafeFetch handling, static assembly style:
//
// SafeFetch32 and SafeFetchN are implemented via static assembly
// and live in os_cpu/xx_xx/safefetch_xx_xx.S
extern "C" char _SafeFetch32_continuation[] __attribute__ ((visibility ("hidden")));
extern "C" char _SafeFetch32_fault[] __attribute__ ((visibility ("hidden")));
#ifdef _LP64
extern "C" char _SafeFetchN_continuation[] __attribute__ ((visibility ("hidden")));
extern "C" char _SafeFetchN_fault[] __attribute__ ((visibility ("hidden")));
#endif // _LP64
bool handle_safefetch(int sig, address pc, void* context) {
ucontext_t* uc = (ucontext_t*)context;
if ((sig == SIGSEGV || sig == SIGBUS) && uc != NULL) {
address pc = os::Posix::ucontext_get_pc(uc);
if (pc == (address)_SafeFetch32_fault) {
os::Posix::ucontext_set_pc(uc, (address)_SafeFetch32_continuation);
return true;
}
#ifdef _LP64
if (pc == (address)_SafeFetchN_fault) {
os::Posix::ucontext_set_pc(uc, (address)_SafeFetchN_continuation);
return true;
}
#endif
}
return false;
}
#endif // SAFEFETCH_METHOD_STATIC_ASSEMBLY

View File

@ -32,20 +32,14 @@
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "runtime/osThread.hpp"
#include "runtime/safefetch.hpp"
#include "runtime/semaphore.inline.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.hpp"
#include "signals_posix.hpp"
#include "utilities/events.hpp"
#include "utilities/ostream.hpp"
#include "utilities/vmError.hpp"
#ifdef ZERO
// See stubGenerator_zero.cpp
#include <setjmp.h>
extern sigjmp_buf* get_jmp_buf_for_continuation();
#endif
#include <signal.h>
@ -599,25 +593,26 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info,
}
#endif
// Extract pc from context. Note that for certain signals and certain
// architectures the pc in ucontext_t will point *after* the offending
// instruction. In those cases, use siginfo si_addr instead.
address pc = NULL;
if (uc != NULL) {
if (S390_ONLY(sig == SIGILL || sig == SIGFPE) NOT_S390(false)) {
pc = (address)info->si_addr;
} else if (ZERO_ONLY(true) NOT_ZERO(false)) {
// Non-arch-specific Zero code does not really know the pc.
// This can be alleviated by making arch-specific os::Posix::ucontext_get_pc
// available for Zero for known architectures. But for generic Zero
// code, it would still remain unknown.
pc = NULL;
} else {
pc = os::Posix::ucontext_get_pc(uc);
}
}
if (!signal_was_handled) {
// Handle SafeFetch access.
#ifndef ZERO
if (uc != NULL) {
address pc = os::Posix::ucontext_get_pc(uc);
if (StubRoutines::is_safefetch_fault(pc)) {
os::Posix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
signal_was_handled = true;
}
}
#else
// See JDK-8076185
if (sig == SIGSEGV || sig == SIGBUS) {
sigjmp_buf* const pjb = get_jmp_buf_for_continuation();
if (pjb) {
siglongjmp(*pjb, 1);
}
}
#endif // ZERO
signal_was_handled = handle_safefetch(sig, pc, uc);
}
// Ignore SIGPIPE and SIGXFSZ (4229104, 6499219).
@ -642,22 +637,6 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info,
// Invoke fatal error handling.
if (!signal_was_handled && abort_if_unrecognized) {
// Extract pc from context for the error handler to display.
address pc = NULL;
if (uc != NULL) {
// prepare fault pc address for error reporting.
if (S390_ONLY(sig == SIGILL || sig == SIGFPE) NOT_S390(false)) {
pc = (address)info->si_addr;
} else if (ZERO_ONLY(true) NOT_ZERO(false)) {
// Non-arch-specific Zero code does not really know the pc.
// This can be alleviated by making arch-specific os::Posix::ucontext_get_pc
// available for Zero for known architectures. But for generic Zero
// code, it would still remain unknown.
pc = NULL;
} else {
pc = os::Posix::ucontext_get_pc(uc);
}
}
// For Zero, we ignore the crash context, because:
// a) The crash would be in C++ interpreter code, so context is not really relevant;
// b) Generic Zero code would not be able to parse it, so when generic error

View File

@ -26,7 +26,7 @@
#include "precompiled.hpp"
#include "cds/metaspaceShared.hpp"
#include "runtime/os.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/safefetch.hpp"
#include "runtime/thread.hpp"
#include "signals_posix.hpp"
#include "utilities/debug.hpp"
@ -67,7 +67,6 @@ static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
PosixSignals::unblock_error_signals();
// support safefetch faults in error handling
ucontext_t* const uc = (ucontext_t*) ucVoid;
address pc = (uc != NULL) ? os::Posix::ucontext_get_pc(uc) : NULL;
@ -76,9 +75,8 @@ static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
pc = (address) info->si_addr;
}
// Needed to make it possible to call SafeFetch.. APIs in error handling.
if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
os::Posix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
// Handle safefetch here too, to be able to use SafeFetch() inside the error handler
if (handle_safefetch(sig, pc, uc)) {
return;
}

View File

@ -56,11 +56,12 @@
#include "runtime/orderAccess.hpp"
#include "runtime/osThread.hpp"
#include "runtime/perfMemory.hpp"
#include "runtime/safefetch.inline.hpp"
#include "runtime/safefetch.hpp"
#include "runtime/safepointMechanism.hpp"
#include "runtime/semaphore.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/statSampler.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp"
@ -2494,11 +2495,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
#endif
Thread* t = Thread::current_or_null_safe();
// Handle SafeFetch32 and SafeFetchN exceptions.
if (StubRoutines::is_safefetch_fault(pc)) {
return Handle_Exception(exceptionInfo, StubRoutines::continuation_for_safefetch_fault(pc));
}
#ifndef _WIN64
// Execution protection violation - win32 running on AMD64 only
// Handled first to avoid misdiagnosis as a "normal" access violation;

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef OS_WINDOWS_SAFEFETCH_WINDOWS_HPP
#define OS_WINDOWS_SAFEFETCH_WINDOWS_HPP
#include "utilities/globalDefinitions.hpp"
// On windows, we use structured exception handling to implement SafeFetch
template <class T>
inline T SafeFetchXX(const T* adr, T errValue) {
T v = 0;
__try {
v = *adr;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
v = errValue;
}
return v;
}
inline int SafeFetch32_impl(const int* adr, int errValue) {
return SafeFetchXX<int>(adr, errValue);
}
inline intptr_t SafeFetchN_impl(const intptr_t* adr, intptr_t errValue) {
return SafeFetchXX<intptr_t>(adr, errValue);
}
#endif

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifdef __APPLE__
# Darwin uses _ prefixed global symbols
#define SYMBOL(s) _ ## s
#define ELF_TYPE(name, description)
#else
#define SYMBOL(s) s
#define ELF_TYPE(name, description) .type name,description
#endif
.global SYMBOL(SafeFetchN_impl)
.global SYMBOL(_SafeFetchN_fault)
.global SYMBOL(_SafeFetchN_continuation)
.global SYMBOL(SafeFetch32_impl)
.global SYMBOL(_SafeFetch32_fault)
.global SYMBOL(_SafeFetch32_continuation)
# Support for int SafeFetch32(int* address, int defaultval);
#
# x0 : address
# w1 : defaultval
# needed to align function start to 4 byte
.align 6
ELF_TYPE(SafeFetch32_impl,@function)
SYMBOL(SafeFetch32_impl):
SYMBOL(_SafeFetch32_fault):
ldr w0, [x0]
ret
SYMBOL(_SafeFetch32_continuation):
mov x0, x1
ret
# Support for intptr_t SafeFetchN(intptr_t* address, intptr_t defaultval);
#
# x1 : address
# x0 : defaultval
.align 6
ELF_TYPE(SafeFetchN_impl,@function)
SYMBOL(SafeFetchN_impl):
SYMBOL(_SafeFetchN_fault):
ldr x0, [x0]
ret
SYMBOL(_SafeFetchN_continuation):
mov x0, x1
ret

View File

@ -0,0 +1,67 @@
#
# Copyright (c) 2022 SAP SE. All rights reserved.
# Copyright (c) 2022, 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
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#ifdef __APPLE__
# Darwin uses _ prefixed global symbols
#define SYMBOL(s) _ ## s
#define ELF_TYPE(name, description)
#else
#define SYMBOL(s) s
#define ELF_TYPE(name, description) .type name,description
#endif
.globl SYMBOL(SafeFetch32_impl)
.globl SYMBOL(SafeFetchN_impl)
.globl SYMBOL(_SafeFetch32_fault)
.globl SYMBOL(_SafeFetchN_fault)
.globl SYMBOL(_SafeFetch32_continuation)
.globl SYMBOL(_SafeFetchN_continuation)
.text
# Support for int SafeFetch32(int* address, int defaultval);
#
# %rdi : address
# %esi : defaultval
ELF_TYPE(SafeFetch32_impl,@function)
SYMBOL(SafeFetch32_impl:)
SYMBOL(_SafeFetch32_fault:)
movl (%rdi), %eax
ret
SYMBOL(_SafeFetch32_continuation:)
movl %esi, %eax
ret
# Support for intptr_t SafeFetchN(intptr_t* address, intptr_t defaultval);
#
# %rdi : address
# %rsi : defaultval
ELF_TYPE(SafeFetchN_impl,@function)
SYMBOL(SafeFetchN_impl:)
SYMBOL(_SafeFetchN_fault:)
movq (%rdi), %rax
ret
SYMBOL(_SafeFetchN_continuation:)
movq %rsi, %rax
ret

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
.globl SafeFetchN_impl
.globl _SafeFetchN_fault
.globl _SafeFetchN_continuation
.globl SafeFetch32_impl
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
# Support for int SafeFetch32(int* address, int defaultval);
#
# x0 : address
# x1 : defaultval
SafeFetch32_impl:
_SafeFetch32_fault:
ldr w0, [x0]
ret
_SafeFetch32_continuation:
mov x0, x1
ret
# Support for intptr_t SafeFetchN(intptr_t* address, intptr_t defaultval);
#
# x1 : address
# x0 : defaultval
SafeFetchN_impl:
_SafeFetchN_fault:
ldr x0, [x0]
ret
_SafeFetchN_continuation:
mov x0, x1
ret

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
.globl SafeFetch32_impl
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
# Support for int SafeFetch32(int* address, int defaultval);
#
# r0 : address
# r1 : defaultval
SafeFetch32_impl:
_SafeFetch32_fault:
ldr r0, [r0]
bx lr
_SafeFetch32_continuation:
mov r0, r1
bx lr

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
.globl SafeFetchN_impl
.globl _SafeFetchN_fault
.globl _SafeFetchN_continuation
.globl SafeFetch32_impl
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
# Support for int SafeFetch32(int* address, int defaultval);
#
# r3 : address
# r4 : defaultval
# r3 : retval
SafeFetch32_impl:
_SafeFetch32_fault:
lwa %r3, 0(%r3)
blr
_SafeFetch32_continuation:
mr %r3, %r4
blr
# Support for intptr_t SafeFetchN(intptr_t* address, intptr_t defaultval);
#
# r3 : address
# r4 : defaultval
# r3 : retval
SafeFetchN_impl:
_SafeFetchN_fault:
ld %r3, 0(%r3)
blr
_SafeFetchN_continuation:
mr %r3, %r4
blr

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
.globl SafeFetchN_impl
.globl _SafeFetchN_fault
.globl _SafeFetchN_continuation
.globl SafeFetch32_impl
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
# Support for int SafeFetch32(int* address, int defaultval);
#
# x10 (a0) : address
# x11 (a1) : defaultval
# x10 (a0) : retval
SafeFetch32_impl:
_SafeFetch32_fault:
lw a0, 0(a0)
ret
_SafeFetch32_continuation:
mv a0, a1
ret
# Support for intptr_t SafeFetchN(intptr_t* address, intptr_t defaultval);
#
# x10 (a0) : address
# x11 (a1) : defaultval
# x10 (a0) : retval
SafeFetchN_impl:
_SafeFetchN_fault:
ld a0, 0(a0)
ret
_SafeFetchN_continuation:
mv a0, a1
ret

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
.globl SafeFetchN_impl
.globl _SafeFetchN_fault
.globl _SafeFetchN_continuation
.globl SafeFetch32_impl
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
# Support for int SafeFetch32(int* address, int defaultval);
#
# r2 : address
# r3 : defaultval
# r2 : retval
SafeFetch32_impl:
_SafeFetch32_fault:
lgf %r2, 0(%r2)
br %r14
_SafeFetch32_continuation:
lgr %r2, %r3
br %r14
# Support for intptr_t SafeFetchN(intptr_t* address, intptr_t defaultval);
#
# r2 : address
# r3 : defaultval
# r2 : retval
SafeFetchN_impl:
_SafeFetchN_fault:
lg %r2, 0(%r2)
br %r14
_SafeFetchN_continuation:
lgr %r2, %r3
br %r14

View File

@ -0,0 +1,43 @@
#
# Copyright (c) 2022 SAP SE. All rights reserved.
# Copyright (c) 2022, 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
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
.globl SafeFetch32_impl
.globl _SafeFetch32_fault
.globl _SafeFetch32_continuation
.text
# Support for int SafeFetch32(int* address, int defaultval);
#
# 8(%esp) : default value
# 4(%esp) : crash address
# 0(%esp) : return pc
.type _SafeFetch32_impl,@function
SafeFetch32_impl:
movl 4(%esp),%ecx # load address from stack
_SafeFetch32_fault:
movl (%ecx), %eax # load target value, may fault
ret
_SafeFetch32_continuation:
movl 8(%esp),%eax # load default value from stack
ret

View File

@ -0,0 +1,58 @@
#
# Copyright (c) 2022 SAP SE. All rights reserved.
# Copyright (c) 2022, 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
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
.globl SafeFetch32_impl
.globl SafeFetchN_impl
.globl _SafeFetch32_fault
.globl _SafeFetchN_fault
.globl _SafeFetch32_continuation
.globl _SafeFetchN_continuation
.text
# Support for int SafeFetch32(int* address, int defaultval);
#
# %rdi : address
# %esi : defaultval
.type SafeFetch32_impl,@function
SafeFetch32_impl:
_SafeFetch32_fault:
movl (%rdi), %eax # load target value, may fault
ret
_SafeFetch32_continuation:
movl %esi, %eax # return default
ret
# Support for intptr_t SafeFetchN(intptr_t* address, intptr_t defaultval);
#
# %rdi : address
# %rsi : defaultval
.type SafeFetchN_impl,@function
SafeFetchN_impl:
_SafeFetchN_fault:
movq (%rdi), %rax # load target value, may fault
ret
_SafeFetchN_continuation:
movq %rsi, %rax # return default
ret

View File

@ -36,7 +36,7 @@
#include "runtime/mutexLocker.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/os.hpp"
#include "runtime/safefetch.inline.hpp"
#include "runtime/safefetch.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.hpp"
#include "services/memTracker.hpp"
@ -300,7 +300,6 @@ void OopStorage::Block::set_active_index(size_t index) {
size_t OopStorage::Block::active_index_safe(const Block* block) {
STATIC_ASSERT(sizeof(intptr_t) == sizeof(block->_active_index));
assert(CanUseSafeFetchN(), "precondition");
return SafeFetchN((intptr_t*)&block->_active_index, 0);
}
@ -366,7 +365,6 @@ void OopStorage::Block::delete_block(const Block& block) {
// require additional validation of the result.
OopStorage::Block*
OopStorage::Block::block_for_ptr(const OopStorage* owner, const oop* ptr) {
assert(CanUseSafeFetchN(), "precondition");
STATIC_ASSERT(_data_pos == 0);
// Const-ness of ptr is not related to const-ness of containing block.
// Blocks are allocated section-aligned, so get the containing section.

View File

@ -47,7 +47,7 @@
#include "runtime/orderAccess.hpp"
#include "runtime/osThread.hpp"
#include "runtime/perfData.hpp"
#include "runtime/safefetch.inline.hpp"
#include "runtime/safefetch.hpp"
#include "runtime/safepointMechanism.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/thread.inline.hpp"

View File

@ -54,7 +54,7 @@
#include "runtime/mutexLocker.hpp"
#include "runtime/os.inline.hpp"
#include "runtime/osThread.hpp"
#include "runtime/safefetch.inline.hpp"
#include "runtime/safefetch.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/threadSMR.hpp"
@ -1045,11 +1045,7 @@ void os::print_date_and_time(outputStream *st, char* buf, size_t buflen) {
// Check if pointer can be read from (4-byte read access).
// Helps to prove validity of a not-NULL pointer.
// Returns true in very early stages of VM life when stub is not yet generated.
#define SAFEFETCH_DEFAULT true
bool os::is_readable_pointer(const void* p) {
if (!CanUseSafeFetch32()) {
return SAFEFETCH_DEFAULT;
}
int* const aligned = (int*) align_down((intptr_t)p, 4);
int cafebabe = 0xcafebabe; // tester value 1
int deadbeef = 0xdeadbeef; // tester value 2

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_RUNTIME_SAFEFETCH_HPP
#define SHARE_RUNTIME_SAFEFETCH_HPP
#include "utilities/macros.hpp"
// Safefetch allows to load a value from a location that's not known
// to be valid. If the load causes a fault, the error value is returned.
#ifdef _WIN32
// Windows uses Structured Exception Handling
#include "safefetch_windows.hpp"
#elif defined(ZERO) || defined (_AIX)
// These platforms implement safefetch via Posix sigsetjmp/longjmp.
// This is slower than the other methods and uses more thread stack,
// but its safe and portable.
#include "safefetch_sigjmp.hpp"
#define SAFEFETCH_METHOD_SIGSETJMP
#else
// All other platforms use static assembly
#include "safefetch_static.hpp"
#define SAFEFETCH_METHOD_STATIC_ASSEMBLY
#endif
inline int SafeFetch32(int* adr, int errValue) {
return SafeFetch32_impl(adr, errValue);
}
inline intptr_t SafeFetchN(intptr_t* adr, intptr_t errValue) {
return SafeFetchN_impl(adr, errValue);
}
#endif // SHARE_RUNTIME_SAFEFETCH_HPP

View File

@ -1,74 +0,0 @@
/*
* Copyright (c) 1997, 2021, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_RUNTIME_SAFEFETCH_INLINE_HPP
#define SHARE_RUNTIME_SAFEFETCH_INLINE_HPP
// No safefetch.hpp
#include "runtime/stubRoutines.hpp"
#include "runtime/threadWXSetters.inline.hpp"
// Safefetch allows to load a value from a location that's not known
// to be valid. If the load causes a fault, the error value is returned.
inline int SafeFetch32(int* adr, int errValue) {
assert(StubRoutines::SafeFetch32_stub(), "stub not yet generated");
#if defined(__APPLE__) && defined(AARCH64)
Thread* thread = Thread::current_or_null_safe();
assert(thread != NULL, "required for W^X management");
ThreadWXEnable wx(WXExec, thread);
#endif // __APPLE__ && AARCH64
return StubRoutines::SafeFetch32_stub()(adr, errValue);
}
inline intptr_t SafeFetchN(intptr_t* adr, intptr_t errValue) {
assert(StubRoutines::SafeFetchN_stub(), "stub not yet generated");
#if defined(__APPLE__) && defined(AARCH64)
Thread* thread = Thread::current_or_null_safe();
assert(thread != NULL, "required for W^X management");
ThreadWXEnable wx(WXExec, thread);
#endif // __APPLE__ && AARCH64
return StubRoutines::SafeFetchN_stub()(adr, errValue);
}
// returns true if SafeFetch32 and SafeFetchN can be used safely (stubroutines are already generated)
inline bool CanUseSafeFetch32() {
#if defined (__APPLE__) && defined(AARCH64)
if (Thread::current_or_null_safe() == NULL) { // workaround for JDK-8282475
return false;
}
#endif // __APPLE__ && AARCH64
return StubRoutines::SafeFetch32_stub() ? true : false;
}
inline bool CanUseSafeFetchN() {
#if defined (__APPLE__) && defined(AARCH64)
if (Thread::current_or_null_safe() == NULL) {
return false;
}
#endif // __APPLE__ && AARCH64
return StubRoutines::SafeFetchN_stub() ? true : false;
}
#endif // SHARE_RUNTIME_SAFEFETCH_INLINE_HPP

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_RUNTIME_SAFEFETCH_STATIC_HPP
#define SHARE_RUNTIME_SAFEFETCH_STATIC_HPP
#include "utilities/globalDefinitions.hpp"
extern "C" int SafeFetch32_impl(int* adr, int errValue);
#ifdef _LP64
extern "C" intptr_t SafeFetchN_impl(intptr_t* adr, intptr_t errValue);
#else
inline intptr_t SafeFetchN_impl(intptr_t* adr, intptr_t errValue) {
return SafeFetch32_impl(adr, errValue);
}
#endif // _LP64
bool handle_safefetch(int sig, address pc, void* context);
#endif // SHARE_RUNTIME_SAFEFETCH_STATIC_HPP

View File

@ -31,8 +31,8 @@
#include "prims/vectorSupport.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/safefetch.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/align.hpp"
#include "utilities/copy.hpp"
#ifdef COMPILER2
@ -168,13 +168,6 @@ address StubRoutines::_dlibm_reduce_pi04l = NULL;
address StubRoutines::_dlibm_tan_cot_huge = NULL;
address StubRoutines::_dtan = NULL;
address StubRoutines::_safefetch32_entry = NULL;
address StubRoutines::_safefetch32_fault_pc = NULL;
address StubRoutines::_safefetch32_continuation_pc = NULL;
address StubRoutines::_safefetchN_entry = NULL;
address StubRoutines::_safefetchN_fault_pc = NULL;
address StubRoutines::_safefetchN_continuation_pc = NULL;
address StubRoutines::_vector_f_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_SVML_OP] = {{NULL}, {NULL}};
address StubRoutines::_vector_d_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_SVML_OP] = {{NULL}, {NULL}};

View File

@ -250,14 +250,6 @@ class StubRoutines: AllStatic {
static address _dlibm_tan_cot_huge;
static address _dtan;
// Safefetch stubs.
static address _safefetch32_entry;
static address _safefetch32_fault_pc;
static address _safefetch32_continuation_pc;
static address _safefetchN_entry;
static address _safefetchN_fault_pc;
static address _safefetchN_continuation_pc;
// Vector Math Routines
static address _vector_f_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_SVML_OP];
static address _vector_d_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_SVML_OP];
@ -428,34 +420,6 @@ class StubRoutines: AllStatic {
static address select_fill_function(BasicType t, bool aligned, const char* &name);
//
// Safefetch stub support
//
typedef int (*SafeFetch32Stub)(int* adr, int errValue);
typedef intptr_t (*SafeFetchNStub) (intptr_t* adr, intptr_t errValue);
static SafeFetch32Stub SafeFetch32_stub() { return CAST_TO_FN_PTR(SafeFetch32Stub, _safefetch32_entry); }
static SafeFetchNStub SafeFetchN_stub() { return CAST_TO_FN_PTR(SafeFetchNStub, _safefetchN_entry); }
static bool is_safefetch_fault(address pc) {
return pc != NULL &&
(pc == _safefetch32_fault_pc ||
pc == _safefetchN_fault_pc);
}
static address continuation_for_safefetch_fault(address pc) {
assert(_safefetch32_continuation_pc != NULL &&
_safefetchN_continuation_pc != NULL,
"not initialized");
if (pc == _safefetch32_fault_pc) return _safefetch32_continuation_pc;
if (pc == _safefetchN_fault_pc) return _safefetchN_continuation_pc;
ShouldNotReachHere();
return NULL;
}
//
// Default versions of the above arraycopy functions for platforms which do
// not have specialized versions

View File

@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "runtime/os.hpp"
#include "runtime/safefetch.inline.hpp"
#include "runtime/safefetch.hpp"
#include "services/mallocSiteTable.hpp"
#include "services/mallocTracker.hpp"
#include "services/memTracker.hpp"
@ -293,7 +293,7 @@ void* MallocTracker::record_free(void* memblock) {
// signals popping up, e.g. when writing an hs_err file.
bool MallocTracker::print_pointer_information(const void* p, outputStream* st) {
assert(MemTracker::enabled(), "NMT must be enabled");
if (CanUseSafeFetch32() && os::is_readable_pointer(p)) {
if (os::is_readable_pointer(p)) {
const NMT_TrackingLevel tracking_level = MemTracker::tracking_level();
const MallocHeader* mhdr = malloc_header(p);
char msg[256];

View File

@ -44,7 +44,7 @@
#include "runtime/init.hpp"
#include "runtime/os.hpp"
#include "runtime/osThread.hpp"
#include "runtime/safefetch.inline.hpp"
#include "runtime/safefetch.hpp"
#include "runtime/safepointMechanism.hpp"
#include "runtime/stackFrameStream.inline.hpp"
#include "runtime/thread.inline.hpp"
@ -597,18 +597,14 @@ void VMError::report(outputStream* st, bool _verbose) {
// to test that resetting the signal handler works correctly.
if (_verbose && TestSafeFetchInErrorHandler) {
st->print_cr("Will test SafeFetch...");
if (CanUseSafeFetch32()) {
int* const invalid_pointer = (int*)segfault_address;
const int x = 0x76543210;
int i1 = SafeFetch32(invalid_pointer, x);
int i2 = SafeFetch32(invalid_pointer, x);
if (i1 == x && i2 == x) {
st->print_cr("SafeFetch OK."); // Correctly deflected and returned default pattern
} else {
st->print_cr("??");
}
int* const invalid_pointer = (int*)segfault_address;
const int x = 0x76543210;
int i1 = SafeFetch32(invalid_pointer, x);
int i2 = SafeFetch32(invalid_pointer, x);
if (i1 == x && i2 == x) {
st->print_cr("SafeFetch OK."); // Correctly deflected and returned default pattern
} else {
st->print_cr("not possible; skipped.");
st->print_cr("??");
}
}
#endif // ASSERT

View File

@ -24,33 +24,120 @@
#include "precompiled.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/safefetch.inline.hpp"
#include "runtime/safefetch.hpp"
#include "runtime/vmOperations.hpp"
#include "runtime/vmThread.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/vmError.hpp"
#include "unittest.hpp"
#include "testutils.hpp"
static const intptr_t pattern = LP64_ONLY(0xABCDABCDABCDABCDULL) NOT_LP64(0xABCDABCD);
static intptr_t* invalid_address = (intptr_t*)VMError::segfault_address;
// Note: beyond these tests, there exist additional tests testing that safefetch in error handling
// (in the context of signal handling) works, see runtime/ErrorHandling
TEST_VM(os, safefetch_can_use) {
// Once VM initialization is through,
// safefetch should work on every platform.
ASSERT_TRUE(CanUseSafeFetch32());
static const intptr_t patternN = LP64_ONLY(0xABCDABCDABCDABCDULL) NOT_LP64(0xABCDABCD);
static const int pattern32 = 0xABCDABCD;
static intptr_t* const bad_addressN = (intptr_t*) VMError::segfault_address;
static int* const bad_address32 = (int*) VMError::segfault_address;
static intptr_t dataN[3] = { 0, patternN, 0 };
static int data32[3] = { 0, pattern32, 0 };
static intptr_t* const good_addressN = dataN + 1;
static int* const good_address32 = data32 + 1;
void test_safefetchN_positive() {
intptr_t a = SafeFetchN(good_addressN, 1);
ASSERT_EQ(patternN, a);
}
TEST_VM(os, safefetch_positive) {
intptr_t v = pattern;
intptr_t a = SafeFetchN(&v, 1);
ASSERT_EQ(v, a);
static void test_safefetch32_positive() {
uint64_t a = SafeFetch32(good_address32, 1);
ASSERT_EQ((uint64_t)pattern32, a);
}
TEST_VM(os, safefetch_negative) {
intptr_t a = SafeFetchN(invalid_address, pattern);
ASSERT_EQ(pattern, a);
a = SafeFetchN(invalid_address, ~pattern);
ASSERT_EQ(~pattern, a);
static void test_safefetchN_negative() {
intptr_t a = SafeFetchN(bad_addressN, 0);
ASSERT_EQ(0, a);
a = SafeFetchN(bad_addressN, -1);
ASSERT_EQ(-1, a);
a = SafeFetchN(bad_addressN, ~patternN);
ASSERT_EQ(~patternN, a);
// Also test NULL, but not on AIX, where NULL is readable
#ifndef AIX
a = SafeFetchN(NULL, 0);
ASSERT_EQ(0, a);
a = SafeFetchN(NULL, ~patternN);
ASSERT_EQ(~patternN, a);
#endif
}
static void test_safefetch32_negative() {
int a = SafeFetch32(bad_address32, 0);
ASSERT_EQ(0, a);
a = SafeFetch32(bad_address32, -1);
ASSERT_EQ(-1, a);
a = SafeFetch32(bad_address32, ~pattern32);
ASSERT_EQ(~pattern32, a);
// Also test NULL, but not on AIX, where NULL is readable
#ifndef AIX
a = SafeFetch32(NULL, 0);
ASSERT_EQ(0, a);
a = SafeFetch32(NULL, ~pattern32);
ASSERT_EQ(~pattern32, a);
#endif
}
TEST_VM(os, safefetchN_positive) {
test_safefetchN_positive();
}
TEST_VM(os, safefetch32_positive) {
test_safefetch32_positive();
}
TEST_VM(os, safefetchN_negative) {
test_safefetchN_negative();
}
TEST_VM(os, safefetch32_negative) {
test_safefetch32_negative();
}
// Try with Thread::current being NULL. SafeFetch should work then too.
// See JDK-8282475
class ThreadCurrentNullMark : public StackObj {
Thread* _saved;
public:
ThreadCurrentNullMark() {
_saved = Thread::current();
Thread::clear_thread_current();
}
~ThreadCurrentNullMark() {
_saved->initialize_thread_current();
}
};
TEST_VM(os, safefetchN_positive_current_null) {
ThreadCurrentNullMark tcnmark;
test_safefetchN_positive();
}
TEST_VM(os, safefetch32_positive_current_null) {
ThreadCurrentNullMark tcnmark;
test_safefetch32_positive();
}
TEST_VM(os, safefetchN_negative_current_null) {
ThreadCurrentNullMark tcnmark;
test_safefetchN_negative();
}
TEST_VM(os, safefetch32_negative_current_null) {
ThreadCurrentNullMark tcnmark;
test_safefetch32_negative();
}
class VM_TestSafeFetchAtSafePoint : public VM_GTestExecuteAtSafepoint {
@ -58,10 +145,7 @@ public:
void doit() {
// Regression test for JDK-8257828
// Should not crash.
intptr_t a = SafeFetchN(invalid_address, pattern);
ASSERT_EQ(pattern, a);
a = SafeFetchN(invalid_address, ~pattern);
ASSERT_EQ(~pattern, a);
test_safefetchN_negative();
}
};