diff options
author | Damien George <damien@micropython.org> | 2025-09-01 14:48:17 +1000 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2025-09-26 14:03:31 +1000 |
commit | 9eddbb32f338a51b475b56891b334084633fbd0e (patch) | |
tree | 23f514a4196c7dbded1c8abc2d7e82fa6918607f | |
parent | 24f395b5dbb2149bf505873e32f7899c6dd57558 (diff) |
webassembly: Do GC in return path rather than entry path.
Doing GC calls in the entry path (when JavaScript calls into MicroPython at
the top/outer level) can lead to freeing of objects which are still in use.
This is because the (JavaScript) objects are referenced in the input
arguments to the C functions and they are not yet converted to full proxy
objects and not yet tracked properly by the live-object tracker.
Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r-- | ports/webassembly/main.c | 16 | ||||
-rw-r--r-- | ports/webassembly/proxy_c.c | 17 |
2 files changed, 14 insertions, 19 deletions
diff --git a/ports/webassembly/main.c b/ports/webassembly/main.c index e0e2d59ae..a7df7969c 100644 --- a/ports/webassembly/main.c +++ b/ports/webassembly/main.c @@ -58,15 +58,15 @@ static void gc_collect_top_level(void); void external_call_depth_inc(void) { ++external_call_depth; - #if MICROPY_GC_SPLIT_HEAP_AUTO - if (external_call_depth == 1) { - gc_collect_top_level(); - } - #endif } void external_call_depth_dec(void) { --external_call_depth; + #if MICROPY_GC_SPLIT_HEAP_AUTO + if (external_call_depth == 0) { + gc_collect_top_level(); + } + #endif } void mp_js_init(int pystack_size, int heap_size) { @@ -133,13 +133,12 @@ void mp_js_do_import(const char *name, uint32_t *out) { } } nlr_pop(); - external_call_depth_dec(); proxy_convert_mp_to_js_obj_cside(ret, out); } else { // uncaught exception - external_call_depth_dec(); proxy_convert_mp_to_js_exc_cside(nlr.ret_val, out); } + external_call_depth_dec(); } void mp_js_do_exec(const char *src, size_t len, uint32_t *out) { @@ -153,13 +152,12 @@ void mp_js_do_exec(const char *src, size_t len, uint32_t *out) { mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false); mp_obj_t ret = mp_call_function_0(module_fun); nlr_pop(); - external_call_depth_dec(); proxy_convert_mp_to_js_obj_cside(ret, out); } else { // uncaught exception - external_call_depth_dec(); proxy_convert_mp_to_js_exc_cside(nlr.ret_val, out); } + external_call_depth_dec(); } void mp_js_do_exec_async(const char *src, size_t len, uint32_t *out) { diff --git a/ports/webassembly/proxy_c.c b/ports/webassembly/proxy_c.c index b7bc87b76..459f6a6da 100644 --- a/ports/webassembly/proxy_c.c +++ b/ports/webassembly/proxy_c.c @@ -257,13 +257,12 @@ void proxy_c_to_js_call(uint32_t c_ref, uint32_t n_args, uint32_t *args_value, u mp_obj_t obj = proxy_c_get_obj(c_ref); mp_obj_t member = mp_call_function_n_kw(obj, n_args, 0, args); nlr_pop(); - external_call_depth_dec(); proxy_convert_mp_to_js_obj_cside(member, out); } else { // uncaught exception - external_call_depth_dec(); proxy_convert_mp_to_js_exc_cside(nlr.ret_val, out); } + external_call_depth_dec(); } void proxy_c_to_js_dir(uint32_t c_ref, uint32_t *out) { @@ -285,13 +284,12 @@ void proxy_c_to_js_dir(uint32_t c_ref, uint32_t *out) { dir = mp_builtin_dir_obj.fun.var(1, args); } nlr_pop(); - external_call_depth_dec(); proxy_convert_mp_to_js_obj_cside(dir, out); } else { // uncaught exception - external_call_depth_dec(); proxy_convert_mp_to_js_exc_cside(nlr.ret_val, out); } + external_call_depth_dec(); } bool proxy_c_to_js_has_attr(uint32_t c_ref, const char *attr_in) { @@ -333,13 +331,12 @@ void proxy_c_to_js_lookup_attr(uint32_t c_ref, const char *attr_in, uint32_t *ou member = mp_load_attr(obj, attr); } nlr_pop(); - external_call_depth_dec(); proxy_convert_mp_to_js_obj_cside(member, out); } else { // uncaught exception - external_call_depth_dec(); proxy_convert_mp_to_js_exc_cside(nlr.ret_val, out); } + external_call_depth_dec(); } static bool proxy_c_to_js_store_helper(uint32_t c_ref, const char *attr_in, uint32_t *value_in) { @@ -450,16 +447,17 @@ bool proxy_c_to_js_iternext(uint32_t c_ref, uint32_t *out) { return false; } nlr_pop(); - external_call_depth_dec(); proxy_convert_mp_to_js_obj_cside(iter, out); + external_call_depth_dec(); return true; } else { - external_call_depth_dec(); if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { + external_call_depth_dec(); return false; } else { // uncaught exception proxy_convert_mp_to_js_exc_cside(nlr.ret_val, out); + external_call_depth_dec(); return true; } } @@ -605,11 +603,10 @@ void proxy_c_to_js_resume(uint32_t c_ref, uint32_t *args) { mp_obj_t reject = proxy_convert_js_to_mp_obj_cside(args + 2 * 3); mp_obj_t ret = proxy_resume_execute(obj, mp_const_none, mp_const_none, resolve, reject); nlr_pop(); - external_call_depth_dec(); proxy_convert_mp_to_js_obj_cside(ret, args); } else { // uncaught exception - external_call_depth_dec(); proxy_convert_mp_to_js_exc_cside(nlr.ret_val, args); } + external_call_depth_dec(); } |