[wasm] Implement GC support. Embedder must provide main loop pumping function request...
authorRodrigo Kumpera <kumpera@gmail.com>
Thu, 28 Sep 2017 00:30:49 +0000 (17:30 -0700)
committerRodrigo Kumpera <kumpera@gmail.com>
Thu, 28 Sep 2017 00:30:49 +0000 (17:30 -0700)
mono/metadata/sgen-mono.c
mono/metadata/sgen-stw.c
mono/sgen/sgen-conf.h
mono/sgen/sgen-gc.c

index 4cd30493fff80524e3b60b368623d7e2d35563c7..df39ea5c5676d099098001fde4f2b65e9abf026d 100644 (file)
@@ -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;
index 48ce7f963ed23cfab6cc0eb68b6b42aa4f37eebf..a8a1b9bf32c9f8437d6772e3031ddf03ea1e3625 100644 (file)
@@ -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
index 5e8866ffff869d2123ece47d39040009b0a95118..47173bc29c959a8bd3ed8f1fc52c2d256959092f 100644 (file)
@@ -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)
index d5416f0df3630ee6a6bc5b4781bc0e9c5442873c..4c3454823fdd42c2f5e0073a87f650601d6b84bf 100644 (file)
@@ -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.h>
+
+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