diff options
| -rw-r--r-- | ports/webassembly/Makefile | 1 | ||||
| -rw-r--r-- | ports/webassembly/proxy_c.c | 32 | ||||
| -rw-r--r-- | ports/webassembly/proxy_js.js | 6 |
3 files changed, 38 insertions, 1 deletions
diff --git a/ports/webassembly/Makefile b/ports/webassembly/Makefile index fddfb5094..435636531 100644 --- a/ports/webassembly/Makefile +++ b/ports/webassembly/Makefile @@ -54,6 +54,7 @@ EXPORTED_FUNCTIONS_EXTRA += ,\ _mp_js_do_exec_async,\ _mp_js_do_import,\ _mp_js_register_js_module,\ + _proxy_c_free_obj,\ _proxy_c_init,\ _proxy_c_to_js_call,\ _proxy_c_to_js_delete_attr,\ diff --git a/ports/webassembly/proxy_c.c b/ports/webassembly/proxy_c.c index 22f879177..6e6f928a2 100644 --- a/ports/webassembly/proxy_c.c +++ b/ports/webassembly/proxy_c.c @@ -32,6 +32,9 @@ #include "py/runtime.h" #include "proxy_c.h" +// Number of static entries at the start of proxy_c_ref. +#define PROXY_C_REF_NUM_STATIC (1) + // These constants should match the constants in proxy_js.js. enum { @@ -71,16 +74,36 @@ static const mp_obj_base_t mp_const_undefined_obj = {&mp_type_undefined}; MP_DEFINE_EXCEPTION(JsException, Exception) +// Index to start searching for the next available slot in proxy_c_ref. +static size_t proxy_c_ref_next; + void proxy_c_init(void) { MP_STATE_PORT(proxy_c_ref) = mp_obj_new_list(0, NULL); mp_obj_list_append(MP_STATE_PORT(proxy_c_ref), MP_OBJ_NULL); + proxy_c_ref_next = PROXY_C_REF_NUM_STATIC; } MP_REGISTER_ROOT_POINTER(mp_obj_t proxy_c_ref); +// obj cannot be MP_OBJ_NULL. static inline size_t proxy_c_add_obj(mp_obj_t obj) { - size_t id = ((mp_obj_list_t *)MP_OBJ_TO_PTR(MP_STATE_PORT(proxy_c_ref)))->len; + // Search for the first free slot in proxy_c_ref. + mp_obj_list_t *l = (mp_obj_list_t *)MP_OBJ_TO_PTR(MP_STATE_PORT(proxy_c_ref)); + while (proxy_c_ref_next < l->len) { + if (l->items[proxy_c_ref_next] == MP_OBJ_NULL) { + // Free slot found, reuse it. + size_t id = proxy_c_ref_next; + ++proxy_c_ref_next; + l->items[id] = obj; + return id; + } + ++proxy_c_ref_next; + } + + // No free slots, so grow proxy_c_ref by one (append at the end of the list). + size_t id = l->len; mp_obj_list_append(MP_STATE_PORT(proxy_c_ref), obj); + proxy_c_ref_next = l->len; return id; } @@ -88,6 +111,13 @@ static inline mp_obj_t proxy_c_get_obj(uint32_t c_ref) { return ((mp_obj_list_t *)MP_OBJ_TO_PTR(MP_STATE_PORT(proxy_c_ref)))->items[c_ref]; } +void proxy_c_free_obj(uint32_t c_ref) { + if (c_ref >= PROXY_C_REF_NUM_STATIC) { + ((mp_obj_list_t *)MP_OBJ_TO_PTR(MP_STATE_PORT(proxy_c_ref)))->items[c_ref] = MP_OBJ_NULL; + proxy_c_ref_next = MIN(proxy_c_ref_next, c_ref); + } +} + mp_obj_t proxy_convert_js_to_mp_obj_cside(uint32_t *value) { if (value[0] == PROXY_KIND_JS_UNDEFINED) { return mp_const_undefined; diff --git a/ports/webassembly/proxy_js.js b/ports/webassembly/proxy_js.js index 20f13f1d7..fe92b5725 100644 --- a/ports/webassembly/proxy_js.js +++ b/ports/webassembly/proxy_js.js @@ -61,6 +61,11 @@ class PythonError extends Error { function proxy_js_init() { globalThis.proxy_js_ref = [globalThis, undefined]; globalThis.proxy_js_ref_next = PROXY_JS_REF_NUM_STATIC; + globalThis.pyProxyFinalizationRegistry = new FinalizationRegistry( + (cRef) => { + Module.ccall("proxy_c_free_obj", "null", ["number"], [cRef]); + }, + ); } // js_obj cannot be undefined @@ -251,6 +256,7 @@ function proxy_convert_mp_to_js_obj_jsside(value) { const target = new PyProxy(id); obj = new Proxy(target, py_proxy_handler); } + globalThis.pyProxyFinalizationRegistry.register(obj, id); } return obj; } |
