Skip to content

8359463: AArch64: MacOS lazy JIT "write xor execute" switching #25806

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

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions src/hotspot/cpu/aarch64/assembler_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4286,6 +4286,7 @@ template<typename R, typename... Rx>
#undef INSN

Assembler(CodeBuffer* code) : AbstractAssembler(code) {
MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
}

// Stack overflow checking
Expand Down
4 changes: 3 additions & 1 deletion src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,9 @@ class Patcher : public RelocActions {
virtual reloc_insn adrpMovk() { return &Patcher::adrpMovk_impl; }

public:
Patcher(address insn_addr) : RelocActions(insn_addr) {}
Patcher(address insn_addr) : RelocActions(insn_addr) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
}

virtual int unconditionalBranch(address insn_addr, address &target) {
intptr_t offset = (target - insn_addr) >> 2;
Expand Down
6 changes: 6 additions & 0 deletions src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ address NativeCall::destination() const {
//
// Used in the runtime linkage of calls; see class CompiledIC.
void NativeCall::set_destination_mt_safe(address dest) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
assert((CodeCache_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) ||
CompiledICLocker::is_safe(addr_at(0)),
"concurrent code patching");
Expand Down Expand Up @@ -143,6 +144,7 @@ intptr_t NativeMovConstReg::data() const {
}

void NativeMovConstReg::set_data(intptr_t x) {
////MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
if (maybe_cpool_ref(instruction_address())) {
address addr = MacroAssembler::target_addr_for_insn(instruction_address());
*(intptr_t*)addr = x;
Expand Down Expand Up @@ -239,6 +241,7 @@ void NativeJump::set_jump_destination(address dest) {
if (dest == (address) -1)
dest = instruction_address();

//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
MacroAssembler::pd_patch_instruction(instruction_address(), dest);
ICache::invalidate_range(instruction_address(), instruction_size);
};
Expand All @@ -262,6 +265,7 @@ address NativeGeneralJump::jump_destination() const {
}

void NativeGeneralJump::set_jump_destination(address dest) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
NativeMovConstReg* move = nativeMovConstReg_at(instruction_address());

// We use jump to self as the unresolved address which the inline
Expand Down Expand Up @@ -369,6 +373,7 @@ void NativeJump::patch_verified_entry(address entry, address verified_entry, add
|| nativeInstruction_at(verified_entry)->is_sigill_not_entrant(),
"Aarch64 cannot replace non-jump with jump");

//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
// Patch this nmethod atomically.
if (Assembler::reachable_from_branch_at(verified_entry, dest)) {
ptrdiff_t disp = dest - verified_entry;
Expand Down Expand Up @@ -418,6 +423,7 @@ void NativeCallTrampolineStub::set_destination(address new_destination) {
void NativeCall::trampoline_jump(CodeBuffer &cbuf, address dest, JVMCI_TRAPS) {
MacroAssembler a(&cbuf);

//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
if (!a.far_branches()) {
// If not using far branches, patch this call directly to dest.
set_destination(dest);
Expand Down
22 changes: 12 additions & 10 deletions src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,18 @@ class NativeInstruction {

s_char sbyte_at(int offset) const { return *(s_char*)addr_at(offset); }
u_char ubyte_at(int offset) const { return *(u_char*)addr_at(offset); }
jint int_at(int offset) const { return *(jint*)addr_at(offset); }
juint uint_at(int offset) const { return *(juint*)addr_at(offset); }
address ptr_at(int offset) const { return *(address*)addr_at(offset); }
oop oop_at(int offset) const { return *(oop*)addr_at(offset); }

void set_char_at(int offset, char c) { *addr_at(offset) = (u_char)c; }
void set_int_at(int offset, jint i) { *(jint*)addr_at(offset) = i; }
void set_uint_at(int offset, jint i) { *(juint*)addr_at(offset) = i; }
void set_ptr_at(int offset, address ptr) { *(address*)addr_at(offset) = ptr; }
void set_oop_at(int offset, oop o) { *(oop*)addr_at(offset) = o; }
jint int_at(int offset) const { return *(jint*)addr_at(offset); }
juint uint_at(int offset) const { return *(juint*)addr_at(offset); }
address ptr_at(int offset) const { return *(address*)addr_at(offset); }
oop oop_at(int offset) const { return *(oop*)addr_at(offset); }

#define APPLE_WX_WRITE MACOS_AARCH64_ONLY(os::thread_wx_enable_write())
void set_char_at(int offset, char c) { APPLE_WX_WRITE; *addr_at(offset) = (u_char)c; }
void set_int_at(int offset, jint i) { APPLE_WX_WRITE; *(jint*)addr_at(offset) = i; }
void set_uint_at(int offset, jint i) { APPLE_WX_WRITE; *(juint*)addr_at(offset) = i; }
void set_ptr_at(int offset, address ptr) { APPLE_WX_WRITE; *(address*)addr_at(offset) = ptr; }
void set_oop_at(int offset, oop o) { APPLE_WX_WRITE; *(oop*)addr_at(offset) = o; }
#undef APPLE_WX_WRITE

void wrote(int offset);

Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int
#endif

VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());

// Read "A word on VtableStub sizing" in share/code/vtableStubs.hpp for details on stub sizing.
const int stub_code_length = code_size_limit(true);
VtableStub* s = new(stub_code_length) VtableStub(true, vtable_index);
Expand Down Expand Up @@ -137,6 +139,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {


VtableStub* VtableStubs::create_itable_stub(int itable_index) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
// Read "A word on VtableStub sizing" in share/code/vtableStubs.hpp for details on stub sizing.
const int stub_code_length = code_size_limit(false);
VtableStub* s = new(stub_code_length) VtableStub(false, itable_index);
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/os/bsd/os_bsd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2214,7 +2214,7 @@ uint os::processor_id() {
}

void os::set_native_thread_name(const char *name) {
#if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
#if true || defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
// This is only supported in Snow Leopard and beyond
if (name != nullptr) {
// Add a "Java: " prefix to the name
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/os_cpu/bsd_aarch64/globals_bsd_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ define_pd_global(uintx,JVMInvokeMethodSlack, 8192);
// Used on 64 bit platforms for UseCompressedOops base address
define_pd_global(uintx,HeapBaseMinAddress, 2*G);

define_pd_global(bool, TraceWXHealing, false);

#endif // OS_CPU_BSD_AARCH64_GLOBALS_BSD_AARCH64_HPP
92 changes: 85 additions & 7 deletions src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,19 +199,33 @@ NOINLINE frame os::current_frame() {

bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) {
// Enable WXWrite: this function is called by the signal handler at arbitrary
// point of execution.
ThreadWXEnable wx(WXWrite, thread);

// decide if this trap can be handled by a stub
address stub = nullptr;

address pc = nullptr;
address pc = nullptr;

//%note os_trap_1
if (info != nullptr && uc != nullptr && thread != nullptr) {
pc = (address) os::Posix::ucontext_get_pc(uc);

#ifdef __APPLE__
// If we got a SIGBUS because we tried to write into the code
// cache, try enabling WXWrite mode.
if (sig == SIGBUS && pc != info->si_addr && CodeCache::contains(info->si_addr)) {
if (thread->_cur_wx_mode) {
if (TraceWXHealing) {
fprintf(stderr, "Healing pointer at %p to WXWrite\n", thread->_cur_wx_mode);
}
*(thread->_cur_wx_mode) = WXWrite;
}
return thread->wx_enable_write();
}
#endif

// Enable WXWrite for the duration of this handler: this function
// is called by the signal handler at arbitrary point of
// execution.
ThreadWXEnable wx(WXWrite, thread);

// Handle ALL stack overflow variations here
if (sig == SIGSEGV || sig == SIGBUS) {
address addr = (address) info->si_addr;
Expand Down Expand Up @@ -488,10 +502,74 @@ int os::extra_bang_size_in_bytes() {
return 0;
}

// DEBUG CODE: REMOVE BEFORE SHIPPING
#if defined(__APPLE__) && defined(AARCH64)

#ifndef PRODUCT

long pthread_jit_write_protect_np_counter;
long pthread_jit_write_protect_not_counter;

bool aph_do_trace;
FILE *aph_do_trace_file;

void poo() __attribute__((constructor));
void poo() {
atexit([]() {
fclose(aph_do_trace_file);
if (getenv("JDK_PRINT_WX_COUNTER")) {
printf("pthread_jit_write_protect_np_counter == %ld\n", pthread_jit_write_protect_np_counter);
printf("pthread_jit_write_protect_not_counter == %ld\n", pthread_jit_write_protect_not_counter);
}
});
aph_do_trace = getenv("APH_DO_TRACE");
if (aph_do_trace) {
errno = 0;
aph_do_trace_file = fopen("/Users/aph/aph_trace", "w+");
if (errno) {
perror("fopen failed\n");
}
}
}

#endif // ! PRODUCT

static THREAD_LOCAL bool os_bsd_jit_exec_enabled;
// This is a wrapper around the standard library function
// pthread_jit_write_protect_np(3). We keep track of the state of
// per-thread write protection on the MAP_JIT region in the
// thread-local variable os_bsd_jit_exec_enabled.
void os::current_thread_enable_wx(WXMode mode) {
pthread_jit_write_protect_np(mode == WXExec);
bool exec_enabled = mode != WXWrite;
if (exec_enabled != os_bsd_jit_exec_enabled) {
permit_forbidden_function::pthread_jit_write_protect_np(exec_enabled);
os_bsd_jit_exec_enabled = exec_enabled;
NOT_PRODUCT(pthread_jit_write_protect_np_counter++);
} else {
NOT_PRODUCT(pthread_jit_write_protect_not_counter++);
}
}

// If the current thread is in the WX state WXArmedForWrite, change
// the state to WXWrite.
bool Thread::wx_enable_write() {
if (_wx_state == WXArmedForWrite) {
_wx_state = WXWrite;
os::current_thread_enable_wx(WXWrite);
return true;
} else {
return false;
}
}

// A wrapper around wx_enable_write() for when the current thread is
// not known.
void os::thread_wx_enable_write() {
Thread::current()->wx_enable_write();
}

#endif // defined(__APPLE__) && defined(AARCH64)

static inline void atomic_copy64(const volatile void *src, volatile void *dst) {
*(jlong *) dst = *(const jlong *) src;
}
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/asm/codeBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ CodeBuffer::CodeBuffer(CodeBlob* blob) DEBUG_ONLY(: Scrubber(this, sizeof(*this)
}

void CodeBuffer::initialize(csize_t code_size, csize_t locs_size) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());

// Always allow for empty slop around each section.
int slop = (int) CodeSection::end_slop();

Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/c1/c1_Runtime1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c
// Reset method handle flag.
current->set_is_method_handle_return(false);

MACOS_AARCH64_ONLY(current->wx_enable_write());
Handle exception(current, ex);

// This function is called when we are about to throw an exception. Therefore,
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/code/codeBlob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ BufferBlob::BufferBlob(const char* name, CodeBlobKind kind, int size)
{}

BufferBlob* BufferBlob::create(const char* name, uint buffer_size) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock

BufferBlob* blob = nullptr;
Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/share/code/nmethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1931,6 +1931,7 @@ void nmethod::verify_clean_inline_caches() {
}

void nmethod::mark_as_maybe_on_stack() {
MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
Atomic::store(&_gc_epoch, CodeCache::gc_epoch());
}

Expand Down Expand Up @@ -2397,6 +2398,8 @@ class IsUnloadingState: public AllStatic {
};

bool nmethod::is_unloading() {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());

uint8_t state = Atomic::load(&_is_unloading_state);
bool state_is_unloading = IsUnloadingState::is_unloading(state);
if (state_is_unloading) {
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/gc/shared/barrierSetNMethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ void BarrierSetNMethod::arm_all_nmethods() {
int BarrierSetNMethod::nmethod_stub_entry_barrier(address* return_address_ptr) {
// Enable WXWrite: the function is called directly from nmethod_entry_barrier
// stub.
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, Thread::current()));
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXArmedForWrite, Thread::current()));

address return_address = *return_address_ptr;
AARCH64_PORT_ONLY(return_address = pauth_strip_pointer(return_address));
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/interpreter/interpreterRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ JRT_ENTRY(void, InterpreterRuntime::create_exception(JavaThread* current, char*
JRT_END



JRT_ENTRY(void, InterpreterRuntime::create_klass_exception(JavaThread* current, char* name, oopDesc* obj))
// Produce the error message first because note_trap can safepoint
ResourceMark rm(current);
Expand Down
6 changes: 6 additions & 0 deletions src/hotspot/share/memory/heap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ void CodeHeap::mark_segmap_as_used(size_t beg, size_t end, bool is_FreeBlock_joi

void CodeHeap::invalidate(size_t beg, size_t end, size_t hdr_size) {
#ifndef PRODUCT
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
// Fill the given range with some bad value.
// length is expected to be in segment_size units.
// This prevents inadvertent execution of code leftover from previous use.
Expand All @@ -172,11 +173,13 @@ void CodeHeap::invalidate(size_t beg, size_t end, size_t hdr_size) {
}

void CodeHeap::clear(size_t beg, size_t end) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
mark_segmap_as_free(beg, end);
invalidate(beg, end, 0);
}

void CodeHeap::clear() {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
_next_segment = 0;
clear(_next_segment, _number_of_committed_segments);
}
Expand All @@ -198,6 +201,7 @@ void CodeHeap::on_code_mapping(char* base, size_t size) {


bool CodeHeap::reserve(ReservedSpace rs, size_t committed_size, size_t segment_size) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
assert(rs.size() >= committed_size, "reserved < committed");
assert(is_aligned(committed_size, rs.page_size()), "must be page aligned");
assert(segment_size >= sizeof(FreeBlock), "segment size is too small");
Expand Down Expand Up @@ -239,6 +243,7 @@ bool CodeHeap::reserve(ReservedSpace rs, size_t committed_size, size_t segment_s


bool CodeHeap::expand_by(size_t size) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
assert_locked_or_safepoint(CodeCache_lock);

// expand _memory space
Expand Down Expand Up @@ -269,6 +274,7 @@ bool CodeHeap::expand_by(size_t size) {


void* CodeHeap::allocate(size_t instance_size) {
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
size_t number_of_segments = size_to_segments(instance_size + header_size());
assert(segments_to_size(number_of_segments) >= sizeof(FreeBlock), "not enough room for FreeList");
assert_locked_or_safepoint(CodeCache_lock);
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/opto/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,8 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* c
// has updated oops.
StackWatermarkSet::after_unwind(current);

//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());

// Do not confuse exception_oop with pending_exception. The exception_oop
// is only used to pass arguments into the method. Not for general
// exception handling. DO NOT CHANGE IT to use pending_exception, since
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/prims/upcallStubs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "runtime/interfaceSupport.inline.hpp"

JVM_ENTRY(static jboolean, UH_FreeUpcallStub0(JNIEnv *env, jobject _unused, jlong addr))
//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
// safe to call 'find_blob' without code cache lock, because stub is always alive
CodeBlob* cb = CodeCache::find_blob((char*)addr);
if (cb == nullptr) {
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/runtime/deoptimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ void DeoptimizationScope::mark(nmethod* nm, bool inc_recompile_counts) {
return;
}

//MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
nmethod::DeoptimizationStatus status =
inc_recompile_counts ? nmethod::deoptimize : nmethod::deoptimize_noupdate;
Atomic::store(&nm->_deoptimization_status, status);
Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/share/runtime/globals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,10 @@ const int ObjectAlignmentInBytes = 8;
product(bool, UseThreadsLockThrottleLock, true, DIAGNOSTIC, \
"Use an extra lock during Thread start and exit to alleviate" \
"contention on Threads_lock.") \
\
develop_pd(bool, TraceWXHealing, \
"track occurrences of W^X mode healing") \


// end of RUNTIME_FLAGS

Expand Down
Loading