summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/webassembly/Makefile1
-rw-r--r--ports/webassembly/proxy_c.c32
-rw-r--r--ports/webassembly/proxy_js.js6
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;
}