|
|
@@ -4681,6 +4681,8 @@ typedef struct ExternRefMapNode {
|
|
|
bool retained;
|
|
|
/* Whether it is marked by runtime */
|
|
|
bool marked;
|
|
|
+ /* cleanup function called when the externref is freed */
|
|
|
+ void (*cleanup)(void *);
|
|
|
} ExternRefMapNode;
|
|
|
|
|
|
static uint32
|
|
|
@@ -4743,6 +4745,81 @@ lookup_extobj_callback(void *key, void *value, void *user_data)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+delete_externref(void *key, ExternRefMapNode *node)
|
|
|
+{
|
|
|
+ bh_hash_map_remove(externref_map, key, NULL, NULL);
|
|
|
+ if (node->cleanup) {
|
|
|
+ (*node->cleanup)(node->extern_obj);
|
|
|
+ }
|
|
|
+ wasm_runtime_free(node);
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+delete_extobj_callback(void *key, void *value, void *user_data)
|
|
|
+{
|
|
|
+ ExternRefMapNode *node = (ExternRefMapNode *)value;
|
|
|
+ LookupExtObj_UserData *lookup_user_data =
|
|
|
+ (LookupExtObj_UserData *)user_data;
|
|
|
+
|
|
|
+ if (node->extern_obj == lookup_user_data->node.extern_obj
|
|
|
+ && node->module_inst == lookup_user_data->node.module_inst) {
|
|
|
+ lookup_user_data->found = true;
|
|
|
+ delete_externref(key, node);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool
|
|
|
+wasm_externref_objdel(WASMModuleInstanceCommon *module_inst, void *extern_obj)
|
|
|
+{
|
|
|
+ LookupExtObj_UserData lookup_user_data = { 0 };
|
|
|
+ bool ok = false;
|
|
|
+
|
|
|
+ /* in a wrapper, extern_obj could be any value */
|
|
|
+ lookup_user_data.node.extern_obj = extern_obj;
|
|
|
+ lookup_user_data.node.module_inst = module_inst;
|
|
|
+ lookup_user_data.found = false;
|
|
|
+
|
|
|
+ os_mutex_lock(&externref_lock);
|
|
|
+ /* Lookup hashmap firstly */
|
|
|
+ bh_hash_map_traverse(externref_map, delete_extobj_callback,
|
|
|
+ (void *)&lookup_user_data);
|
|
|
+ if (lookup_user_data.found) {
|
|
|
+ ok = true;
|
|
|
+ }
|
|
|
+ os_mutex_unlock(&externref_lock);
|
|
|
+
|
|
|
+ return ok;
|
|
|
+}
|
|
|
+
|
|
|
+bool
|
|
|
+wasm_externref_set_cleanup(WASMModuleInstanceCommon *module_inst,
|
|
|
+ void *extern_obj, void (*extern_obj_cleanup)(void *))
|
|
|
+{
|
|
|
+
|
|
|
+ LookupExtObj_UserData lookup_user_data = { 0 };
|
|
|
+ bool ok = false;
|
|
|
+
|
|
|
+ /* in a wrapper, extern_obj could be any value */
|
|
|
+ lookup_user_data.node.extern_obj = extern_obj;
|
|
|
+ lookup_user_data.node.module_inst = module_inst;
|
|
|
+ lookup_user_data.found = false;
|
|
|
+
|
|
|
+ os_mutex_lock(&externref_lock);
|
|
|
+ /* Lookup hashmap firstly */
|
|
|
+ bh_hash_map_traverse(externref_map, lookup_extobj_callback,
|
|
|
+ (void *)&lookup_user_data);
|
|
|
+ if (lookup_user_data.found) {
|
|
|
+ void *key = (void *)(uintptr_t)lookup_user_data.externref_idx;
|
|
|
+ ExternRefMapNode *node = bh_hash_map_find(externref_map, key);
|
|
|
+ node->cleanup = extern_obj_cleanup;
|
|
|
+ ok = true;
|
|
|
+ }
|
|
|
+ os_mutex_unlock(&externref_lock);
|
|
|
+
|
|
|
+ return ok;
|
|
|
+}
|
|
|
+
|
|
|
bool
|
|
|
wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
|
|
|
uint32 *p_externref_idx)
|
|
|
@@ -4792,6 +4869,7 @@ wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
|
|
|
memset(node, 0, sizeof(ExternRefMapNode));
|
|
|
node->extern_obj = extern_obj;
|
|
|
node->module_inst = module_inst;
|
|
|
+ node->cleanup = NULL;
|
|
|
|
|
|
externref_idx = externref_global_id;
|
|
|
|
|
|
@@ -4842,8 +4920,7 @@ reclaim_extobj_callback(void *key, void *value, void *user_data)
|
|
|
|
|
|
if (node->module_inst == module_inst) {
|
|
|
if (!node->marked && !node->retained) {
|
|
|
- bh_hash_map_remove(externref_map, key, NULL, NULL);
|
|
|
- wasm_runtime_free(value);
|
|
|
+ delete_externref(key, node);
|
|
|
}
|
|
|
else {
|
|
|
node->marked = false;
|
|
|
@@ -4958,8 +5035,7 @@ cleanup_extobj_callback(void *key, void *value, void *user_data)
|
|
|
(WASMModuleInstanceCommon *)user_data;
|
|
|
|
|
|
if (node->module_inst == module_inst) {
|
|
|
- bh_hash_map_remove(externref_map, key, NULL, NULL);
|
|
|
- wasm_runtime_free(value);
|
|
|
+ delete_externref(key, node);
|
|
|
}
|
|
|
}
|
|
|
|