diff --git a/src/racket/include/mzwin.def b/src/racket/include/mzwin.def index 4064ca015c..007b1aadb5 100644 --- a/src/racket/include/mzwin.def +++ b/src/racket/include/mzwin.def @@ -185,6 +185,7 @@ EXPORTS scheme_eval_compiled_sized_string_with_magic scheme_detach_multple_array scheme_malloc_code + scheme_malloc_permanent_code scheme_free_code scheme_malloc_gcable_code scheme_malloc_eternal diff --git a/src/racket/include/mzwin3m.def b/src/racket/include/mzwin3m.def index 4cdbe20d4b..eba516240e 100644 --- a/src/racket/include/mzwin3m.def +++ b/src/racket/include/mzwin3m.def @@ -194,6 +194,7 @@ EXPORTS GC_malloc_atomic_allow_interior GC_malloc_tagged_allow_interior scheme_malloc_code + scheme_malloc_permanent_code scheme_free_code scheme_malloc_gcable_code scheme_malloc_eternal diff --git a/src/racket/include/racket.exp b/src/racket/include/racket.exp index 0a8dd3a8e1..07ca3c6666 100644 --- a/src/racket/include/racket.exp +++ b/src/racket/include/racket.exp @@ -197,6 +197,7 @@ GC_malloc_atomic GC_malloc_stubborn GC_malloc_uncollectable scheme_malloc_code +scheme_malloc_permanent_code scheme_free_code scheme_malloc_gcable_code scheme_malloc_eternal diff --git a/src/racket/include/racket3m.exp b/src/racket/include/racket3m.exp index 79adea4d10..fe920d3ce1 100644 --- a/src/racket/include/racket3m.exp +++ b/src/racket/include/racket3m.exp @@ -202,6 +202,7 @@ GC_malloc_allow_interior GC_malloc_atomic_allow_interior GC_malloc_tagged_allow_interior scheme_malloc_code +scheme_malloc_permanent_code scheme_free_code scheme_malloc_gcable_code scheme_malloc_eternal diff --git a/src/racket/src/jitstate.c b/src/racket/src/jitstate.c index 5d07da058c..6c61c1a6bb 100644 --- a/src/racket/src/jitstate.c +++ b/src/racket/src/jitstate.c @@ -136,7 +136,7 @@ void *scheme_generate_one(mz_jit_state *old_jitter, buffer = scheme_malloc_gcable_code(size); #endif } else { - buffer = scheme_malloc_code(size); + buffer = scheme_malloc_permanent_code(size); } RECORD_CODE_SIZE(size); } else if (old_jitter) { diff --git a/src/racket/src/salloc.c b/src/racket/src/salloc.c index 77b5361e97..25a8c9de64 100644 --- a/src/racket/src/salloc.c +++ b/src/racket/src/salloc.c @@ -839,6 +839,12 @@ struct free_list_entry { THREAD_LOCAL_DECL(static struct free_list_entry *free_list;) THREAD_LOCAL_DECL(static int free_list_bucket_count;) +#ifdef MZ_USE_PLACES +static mzrt_mutex *permanent_code_mutex = NULL; +static void *permanent_code_page = NULL; +static intptr_t available_code_page_amount = 0; +#endif + static intptr_t get_page_size() { # ifdef PAGESIZE @@ -1095,6 +1101,47 @@ void *scheme_malloc_code(intptr_t size) #endif } +void *scheme_malloc_permanent_code(intptr_t size) +/* allocate code that will never be freed and that can be used + in multiple places */ +{ +#if defined(MZ_USE_PLACES) && (defined(MZ_JIT_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC)) + void *p; + intptr_t page_size; + + if (!permanent_code_mutex) { + /* This function will be called at least once before any other place + is created, so it's ok to create the mutex here. */ + mzrt_mutex_create(&permanent_code_mutex); + } + + /* 16-byte alignment: */ + if (size & 0xF) size += 16 - (size & 0xF); + + mzrt_mutex_lock(permanent_code_mutex); + + if (available_code_page_amount < size) { + page_size = get_page_size(); + page_size *= 4; + while (page_size < size) page_size *= 2; + + permanent_code_page = malloc_page(page_size); + + available_code_page_amount = page_size; + } + + p = permanent_code_page; + permanent_code_page = ((char *)permanent_code_page) + size; + available_code_page_amount -= size; + + mzrt_mutex_unlock(permanent_code_mutex); + + return p; +#else + return scheme_malloc_code(size); +#endif +} + void scheme_free_code(void *p) { #if defined(MZ_JIT_USE_MPROTECT) || defined(MZ_JIT_USE_WINDOWS_VIRTUAL_ALLOC) diff --git a/src/racket/src/schemef.h b/src/racket/src/schemef.h index 66aa634730..fe05e3bff0 100644 --- a/src/racket/src/schemef.h +++ b/src/racket/src/schemef.h @@ -399,6 +399,7 @@ MZ_EXTERN void *GC_malloc_uncollectable(size_t size_in_bytes); #endif MZ_EXTERN void *scheme_malloc_code(intptr_t size); +MZ_EXTERN void *scheme_malloc_permanent_code(intptr_t size); MZ_EXTERN void scheme_free_code(void *p); #ifndef MZ_PRECISE_GC MZ_EXTERN void *scheme_malloc_gcable_code(intptr_t size); diff --git a/src/racket/src/schemex.h b/src/racket/src/schemex.h index c7760e7aad..45031faf8c 100644 --- a/src/racket/src/schemex.h +++ b/src/racket/src/schemex.h @@ -308,6 +308,7 @@ void *(*GC_malloc_uncollectable)(size_t size_in_bytes); # endif #endif void *(*scheme_malloc_code)(intptr_t size); +void *(*scheme_malloc_permanent_code)(intptr_t size); void (*scheme_free_code)(void *p); #ifndef MZ_PRECISE_GC void *(*scheme_malloc_gcable_code)(intptr_t size); diff --git a/src/racket/src/schemex.inc b/src/racket/src/schemex.inc index bcb847cff3..3d669fbe97 100644 --- a/src/racket/src/schemex.inc +++ b/src/racket/src/schemex.inc @@ -219,6 +219,7 @@ # endif #endif scheme_extension_table->scheme_malloc_code = scheme_malloc_code; + scheme_extension_table->scheme_malloc_permanent_code = scheme_malloc_permanent_code; scheme_extension_table->scheme_free_code = scheme_free_code; #ifndef MZ_PRECISE_GC scheme_extension_table->scheme_malloc_gcable_code = scheme_malloc_gcable_code; diff --git a/src/racket/src/schemexm.h b/src/racket/src/schemexm.h index 505e2e2085..40feea2bfb 100644 --- a/src/racket/src/schemexm.h +++ b/src/racket/src/schemexm.h @@ -219,6 +219,7 @@ # endif #endif #define scheme_malloc_code (scheme_extension_table->scheme_malloc_code) +#define scheme_malloc_permanent_code (scheme_extension_table->scheme_malloc_permanent_code) #define scheme_free_code (scheme_extension_table->scheme_free_code) #ifndef MZ_PRECISE_GC #define scheme_malloc_gcable_code (scheme_extension_table->scheme_malloc_gcable_code)