* configure.ac: check for pthread_jit_write_protect_np. * libguile/jit.c: add support for Apple Silicon JIT compilation.
Fixes https://debbugs.gnu.org/cgi/bugreport.cgi?bug=44505 --- configure.ac | 3 +++ libguile/jit.c | 25 ++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b3879df1f..f8c12f0d7 100644 --- a/configure.ac +++ b/configure.ac @@ -1187,6 +1187,9 @@ case "$with_threads" in pthread_get_stackaddr_np pthread_attr_get_np pthread_sigmask \ pthread_cancel]) + # Apple Silicon JIT code arena needs to be unprotected before writing. + AC_CHECK_FUNCS([pthread_jit_write_protect_np]) + # On past versions of Solaris, believe 8 through 10 at least, you # had to write "pthread_once_t foo = { PTHREAD_ONCE_INIT };". # This is contrary to POSIX: diff --git a/libguile/jit.c b/libguile/jit.c index 8420829b4..5cef8fae3 100644 --- a/libguile/jit.c +++ b/libguile/jit.c @@ -47,6 +47,10 @@ #include <sys/mman.h> #endif +#if defined __APPLE__ && HAVE_PTHREAD_JIT_WRITE_PROTECT_NP +#include <libkern/OSCacheControl.h> +#endif + #include "jit.h" @@ -1349,9 +1353,13 @@ allocate_code_arena (size_t size, struct code_arena *prev) ret->size = size; ret->prev = prev; #ifndef __MINGW32__ + int flags = MAP_PRIVATE | MAP_ANONYMOUS; +#if defined __APPLE__ && HAVE_PTHREAD_JIT_WRITE_PROTECT_NP + flags |= MAP_JIT; +#endif ret->base = mmap (NULL, ret->size, PROT_EXEC | PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + flags, -1, 0); if (ret->base == MAP_FAILED) { perror ("allocating JIT code buffer failed"); @@ -1406,11 +1414,21 @@ emit_code (scm_jit_state *j, void (*emit) (scm_jit_state *)) uint8_t *ret = jit_address (j->jit); +#if defined __APPLE__ && HAVE_PTHREAD_JIT_WRITE_PROTECT_NP + pthread_jit_write_protect_np(0); +#endif + emit (j); size_t size; if (!jit_has_overflow (j->jit) && jit_end (j->jit, &size)) { +#if defined __APPLE__ && HAVE_PTHREAD_JIT_WRITE_PROTECT_NP + /* protect previous code arena. leave unprotected after emit() + since jit_end() also writes to code arena. */ + pthread_jit_write_protect_np(1); + sys_icache_invalidate(arena->base, arena->size); +#endif ASSERT (size <= (arena->size - arena->used)); DEBUG ("mcode: %p,+%zu\n", ret, size); arena->used += size; @@ -1424,6 +1442,11 @@ emit_code (scm_jit_state *j, void (*emit) (scm_jit_state *)) } else { +#if defined __APPLE__ && HAVE_PTHREAD_JIT_WRITE_PROTECT_NP + /* protect previous code arena */ + pthread_jit_write_protect_np(1); + sys_icache_invalidate(arena->base, arena->size); +#endif jit_reset (j->jit); if (arena->used == 0) { -- 2.37.1 (Apple Git-137.1)