From a7c9e39f0f58a1dcd41475f5623f301f14e31da7 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Wed, 27 Sep 2017 17:30:49 -0700 Subject: [PATCH] [wasm] Implement GC support. Embedder must provide main loop pumping function request_gc_cycle. --- mono/metadata/sgen-mono.c | 4 ++++ mono/metadata/sgen-stw.c | 2 ++ mono/sgen/sgen-conf.h | 2 +- mono/sgen/sgen-gc.c | 48 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index 4cd30493fff..df39ea5c567 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -2361,6 +2361,10 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p { scan_area_arg_start = start_nursery; scan_area_arg_end = end_nursery; +#ifdef HOST_WASM + //Under WASM we don't scan thread stacks and we can't trust the values we find there either. + return; +#endif FOREACH_THREAD (info) { int skip_reason = 0; diff --git a/mono/metadata/sgen-stw.c b/mono/metadata/sgen-stw.c index 48ce7f963ed..a8a1b9bf32c 100644 --- a/mono/metadata/sgen-stw.c +++ b/mono/metadata/sgen-stw.c @@ -70,6 +70,8 @@ update_current_thread_stack (void *start) #if !defined(MONO_CROSS_COMPILE) && MONO_ARCH_HAS_MONO_CONTEXT MONO_CONTEXT_GET_CURRENT (info->client_info.ctx); +#elif defined (HOST_WASM) + //nothing #else g_error ("Sgen STW requires a working mono-context"); #endif diff --git a/mono/sgen/sgen-conf.h b/mono/sgen/sgen-conf.h index 5e8866ffff8..47173bc29c9 100644 --- a/mono/sgen/sgen-conf.h +++ b/mono/sgen/sgen-conf.h @@ -104,7 +104,7 @@ typedef mword SgenDescriptor; #endif #endif -#if defined (TARGET_WASM) +#if defined (HOST_WASM) #define DEFAULT_MAJOR SGEN_MAJOR_SERIAL #define DEFAULT_SWEEP_MODE SGEN_SWEEP_SERIAL #elif defined(HAVE_CONC_GC_AS_DEFAULT) diff --git a/mono/sgen/sgen-gc.c b/mono/sgen/sgen-gc.c index d5416f0df36..4c3454823fd 100644 --- a/mono/sgen/sgen-gc.c +++ b/mono/sgen/sgen-gc.c @@ -2503,7 +2503,7 @@ sgen_ensure_free_space (size_t size, int generation) * LOCKING: Assumes the GC lock is held. */ void -sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish, gboolean stw) +sgen_perform_collection_inner (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish, gboolean stw) { TV_DECLARE (gc_total_start); TV_DECLARE (gc_total_end); @@ -2582,6 +2582,52 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const sgen_restart_world (oldest_generation_collected); } +#ifdef HOST_WASM + +typedef struct { + size_t requested_size; + int generation_to_collect; + const char *reason; +} SgenGcRequest; + +static SgenGcRequest gc_request; +static gboolean pending_request; + +extern void request_gc_cycle (void); + +#include + +EMSCRIPTEN_KEEPALIVE void +mono_gc_pump_callback (void) +{ + if (!pending_request) + return; + pending_request = FALSE; + sgen_perform_collection_inner (gc_request.requested_size, gc_request.generation_to_collect, gc_request.reason, TRUE, TRUE); +} +#endif + +void +sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish, gboolean stw) +{ +#ifdef HOST_WASM + g_assert (stw); //can't handle non-stw mode (IE, domain unload) + //we ignore wait_to_finish + if (!pending_request || gc_request.generation_to_collect <= generation_to_collect) { //no active request or request was for a smaller part of the heap + gc_request.requested_size = requested_size; + gc_request.generation_to_collect = generation_to_collect; + gc_request.reason = reason; + if (!pending_request) { + request_gc_cycle (); + pending_request = TRUE; + } + } + + degraded_mode = 1; //enable degraded mode so allocation can continue +#else + sgen_perform_collection_inner (requested_size, generation_to_collect, reason, wait_to_finish, stw); +#endif +} /* * ###################################################################### * ######## Memory allocation from the OS -- 2.25.1