Merge branch main into dev/wasi_threads
This commit is contained in:
@ -16,9 +16,14 @@ _invokeNative:
|
||||
push %ebp
|
||||
movl %esp, %ebp
|
||||
movl 16(%ebp), %ecx /* ecx = argc */
|
||||
movl 12(%ebp), %edx /* edx = argv */
|
||||
leal 2(%ecx), %edx /* edx = ecx + 2 (count return address and saved ebp) */
|
||||
andl $3, %edx /* edx = edx % 4 */
|
||||
jz stack_aligned /* if edx == 0, stack is already 16 bytes aligned */
|
||||
leal -16(%esp, %edx, 4), %esp /* esp = esp - 16 + edx * 4 */
|
||||
stack_aligned:
|
||||
test %ecx, %ecx
|
||||
jz skip_push_args /* if ecx == 0, skip pushing arguments */
|
||||
movl 12(%ebp), %edx /* edx = argv */
|
||||
leal -4(%edx,%ecx,4), %edx /* edx = edx + ecx * 4 - 4 */
|
||||
subl %esp, %edx /* edx = edx - esp */
|
||||
1:
|
||||
|
||||
@ -276,7 +276,7 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
|
||||
WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
|
||||
|
||||
#ifndef NDEBUG
|
||||
#if WAMR_BUILD_MEMORY_PROFILING != 0
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
#define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM()
|
||||
#else
|
||||
#define WASM_C_DUMP_PROC_MEM() (void)0
|
||||
@ -398,7 +398,7 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
|
||||
}
|
||||
|
||||
/* global engine instance */
|
||||
static wasm_engine_t *singleton_engine = NULL;
|
||||
static wasm_engine_t *singleton_engine;
|
||||
#ifdef os_thread_local_attribute
|
||||
/* categorize wasm_store_t as threads*/
|
||||
static os_thread_local_attribute unsigned thread_local_stores_num = 0;
|
||||
@ -1458,6 +1458,30 @@ wasm_importtype_type(const wasm_importtype_t *import_type)
|
||||
return import_type->extern_type;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_importtype_is_linked(const wasm_importtype_t *import_type)
|
||||
{
|
||||
if (!import_type)
|
||||
return false;
|
||||
|
||||
const wasm_name_t *module_name = wasm_importtype_module(import_type);
|
||||
const wasm_name_t *field_name = wasm_importtype_name(import_type);
|
||||
|
||||
switch (wasm_externtype_kind(wasm_importtype_type(import_type))) {
|
||||
case WASM_EXTERN_FUNC:
|
||||
return wasm_runtime_is_import_func_linked(module_name->data,
|
||||
field_name->data);
|
||||
case WASM_EXTERN_GLOBAL:
|
||||
return wasm_runtime_is_import_global_linked(module_name->data,
|
||||
field_name->data);
|
||||
case WASM_EXTERN_MEMORY:
|
||||
case WASM_EXTERN_TABLE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
own wasm_exporttype_t *
|
||||
wasm_exporttype_new(own wasm_byte_vec_t *name,
|
||||
own wasm_externtype_t *extern_type)
|
||||
@ -2537,12 +2561,12 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
|
||||
|
||||
bh_assert(extern_type);
|
||||
|
||||
wasm_name_new_from_string(&module_name, module_name_rt);
|
||||
wasm_name_new_from_string_nt(&module_name, module_name_rt);
|
||||
if (strlen(module_name_rt) && !module_name.data) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
wasm_name_new_from_string(&name, field_name_rt);
|
||||
wasm_name_new_from_string_nt(&name, field_name_rt);
|
||||
if (strlen(field_name_rt) && !name.data) {
|
||||
goto failed;
|
||||
}
|
||||
@ -2622,7 +2646,7 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
|
||||
}
|
||||
|
||||
/* byte* -> wasm_byte_vec_t */
|
||||
wasm_name_new_from_string(&name, export->name);
|
||||
wasm_name_new_from_string_nt(&name, export->name);
|
||||
if (strlen(export->name) && !name.data) {
|
||||
goto failed;
|
||||
}
|
||||
@ -3008,6 +3032,20 @@ failed:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static wasm_func_t *
|
||||
wasm_func_new_empty(wasm_store_t *store)
|
||||
{
|
||||
wasm_func_t *func = NULL;
|
||||
|
||||
if (!(func = malloc_internal(sizeof(wasm_func_t))))
|
||||
goto failed;
|
||||
|
||||
func->store = store;
|
||||
func->kind = WASM_EXTERN_FUNC;
|
||||
|
||||
RETURN_OBJ(func, wasm_func_delete)
|
||||
}
|
||||
|
||||
void
|
||||
wasm_func_delete(wasm_func_t *func)
|
||||
{
|
||||
@ -3211,7 +3249,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
|
||||
wasm_name_t message = { 0 };
|
||||
wasm_trap_t *trap;
|
||||
|
||||
wasm_name_new_from_string(&message, "failed to call unlinked function");
|
||||
wasm_name_new_from_string_nt(&message,
|
||||
"failed to call unlinked function");
|
||||
trap = wasm_trap_new(func->store, &message);
|
||||
wasm_byte_vec_delete(&message);
|
||||
|
||||
@ -3371,6 +3410,25 @@ failed:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static wasm_global_t *
|
||||
wasm_global_new_empty(wasm_store_t *store)
|
||||
{
|
||||
wasm_global_t *global = NULL;
|
||||
|
||||
global = malloc_internal(sizeof(wasm_global_t));
|
||||
if (!global)
|
||||
goto failed;
|
||||
|
||||
global->store = store;
|
||||
global->kind = WASM_EXTERN_GLOBAL;
|
||||
|
||||
return global;
|
||||
failed:
|
||||
LOG_DEBUG("%s failed", __FUNCTION__);
|
||||
wasm_global_delete(global);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* almost same with wasm_global_new */
|
||||
wasm_global_t *
|
||||
wasm_global_copy(const wasm_global_t *src)
|
||||
@ -4205,7 +4263,8 @@ wasm_memory_data_size(const wasm_memory_t *memory)
|
||||
(WASMModuleInstance *)module_inst_comm;
|
||||
WASMMemoryInstance *memory_inst =
|
||||
module_inst->memories[memory->memory_idx_rt];
|
||||
return memory_inst->cur_page_count * memory_inst->num_bytes_per_page;
|
||||
return (size_t)memory_inst->cur_page_count
|
||||
* memory_inst->num_bytes_per_page;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4215,7 +4274,8 @@ wasm_memory_data_size(const wasm_memory_t *memory)
|
||||
AOTMemoryInstance *memory_inst =
|
||||
((AOTMemoryInstance **)
|
||||
module_inst->memories)[memory->memory_idx_rt];
|
||||
return memory_inst->cur_page_count * memory_inst->num_bytes_per_page;
|
||||
return (size_t)memory_inst->cur_page_count
|
||||
* memory_inst->num_bytes_per_page;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4286,6 +4346,11 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp,
|
||||
|
||||
imported_func_interp = module_interp->import_functions + func_idx_rt;
|
||||
bh_assert(imported_func_interp);
|
||||
bh_assert(imported_func_interp->kind == IMPORT_KIND_FUNC);
|
||||
|
||||
/* it is a placeholder and let's skip it*/
|
||||
if (!import->type)
|
||||
return true;
|
||||
|
||||
/* type comparison */
|
||||
if (!wasm_functype_same_internal(
|
||||
@ -4300,6 +4365,8 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp,
|
||||
imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb;
|
||||
else
|
||||
imported_func_interp->u.function.func_ptr_linked = import->u.cb;
|
||||
bh_assert(imported_func_interp->u.function.func_ptr_linked);
|
||||
|
||||
import->func_idx_rt = func_idx_rt;
|
||||
|
||||
(void)inst;
|
||||
@ -4318,12 +4385,19 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt,
|
||||
|
||||
imported_global_interp = module_interp->import_globals + global_idx_rt;
|
||||
bh_assert(imported_global_interp);
|
||||
bh_assert(imported_global_interp->kind == IMPORT_KIND_GLOBAL);
|
||||
|
||||
/* it is a placeholder and let's skip it*/
|
||||
if (!import->type)
|
||||
return true;
|
||||
|
||||
/* type comparison */
|
||||
if (!cmp_val_kind_with_val_type(wasm_valtype_kind(import->type->val_type),
|
||||
imported_global_interp->u.global.type))
|
||||
return false;
|
||||
|
||||
/* set init value */
|
||||
bh_assert(import->init);
|
||||
switch (wasm_valtype_kind(import->type->val_type)) {
|
||||
case WASM_I32:
|
||||
imported_global_interp->u.global.global_data_linked.i32 =
|
||||
@ -4350,58 +4424,6 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
interp_link(const wasm_instance_t *inst, const WASMModule *module_interp,
|
||||
wasm_extern_t *imports[])
|
||||
{
|
||||
uint32 i = 0;
|
||||
uint32 import_func_i = 0;
|
||||
uint32 import_global_i = 0;
|
||||
|
||||
bh_assert(inst && module_interp && imports);
|
||||
|
||||
for (i = 0; i < module_interp->import_count; ++i) {
|
||||
wasm_extern_t *import = imports[i];
|
||||
WASMImport *import_rt = module_interp->imports + i;
|
||||
|
||||
switch (import_rt->kind) {
|
||||
case IMPORT_KIND_FUNC:
|
||||
{
|
||||
if (!interp_link_func(inst, module_interp, import_func_i,
|
||||
wasm_extern_as_func(import))) {
|
||||
LOG_WARNING("link #%d function failed", import_func_i);
|
||||
goto failed;
|
||||
}
|
||||
import_func_i++;
|
||||
break;
|
||||
}
|
||||
case IMPORT_KIND_GLOBAL:
|
||||
{
|
||||
if (!interp_link_global(module_interp, import_global_i,
|
||||
wasm_extern_as_global(import))) {
|
||||
LOG_WARNING("link #%d global failed", import_global_i);
|
||||
goto failed;
|
||||
}
|
||||
import_global_i++;
|
||||
break;
|
||||
}
|
||||
case IMPORT_KIND_MEMORY:
|
||||
case IMPORT_KIND_TABLE:
|
||||
default:
|
||||
ASSERT_NOT_IMPLEMENTED();
|
||||
LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
|
||||
import_rt->kind);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
failed:
|
||||
LOG_DEBUG("%s failed", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
interp_process_export(wasm_store_t *store,
|
||||
const WASMModuleInstance *inst_interp,
|
||||
@ -4501,6 +4523,10 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot,
|
||||
import_aot_func = module_aot->import_funcs + import_func_idx_rt;
|
||||
bh_assert(import_aot_func);
|
||||
|
||||
/* it is a placeholder and let's skip it*/
|
||||
if (!import->type)
|
||||
return true;
|
||||
|
||||
/* type comparison */
|
||||
if (!wasm_functype_same_internal(import->type, import_aot_func->func_type))
|
||||
return false;
|
||||
@ -4513,6 +4539,8 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot,
|
||||
import_aot_func->func_ptr_linked = import->u.cb_env.cb;
|
||||
else
|
||||
import_aot_func->func_ptr_linked = import->u.cb;
|
||||
bh_assert(import_aot_func->func_ptr_linked);
|
||||
|
||||
import->func_idx_rt = import_func_idx_rt;
|
||||
|
||||
return true;
|
||||
@ -4530,6 +4558,10 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
|
||||
import_aot_global = module_aot->import_globals + global_idx_rt;
|
||||
bh_assert(import_aot_global);
|
||||
|
||||
/* it is a placeholder and let's skip it*/
|
||||
if (!import->type)
|
||||
return true;
|
||||
|
||||
val_type = wasm_globaltype_content(import->type);
|
||||
bh_assert(val_type);
|
||||
|
||||
@ -4537,6 +4569,7 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
|
||||
import_aot_global->type))
|
||||
return false;
|
||||
|
||||
bh_assert(import->init);
|
||||
switch (wasm_valtype_kind(val_type)) {
|
||||
case WASM_I32:
|
||||
import_aot_global->global_data_linked.i32 = import->init->of.i32;
|
||||
@ -4557,62 +4590,6 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
|
||||
import->global_idx_rt = global_idx_rt;
|
||||
import_aot_global->is_linked = true;
|
||||
return true;
|
||||
|
||||
failed:
|
||||
LOG_DEBUG("%s failed", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
aot_link(const wasm_instance_t *inst, const AOTModule *module_aot,
|
||||
wasm_extern_t *imports[])
|
||||
{
|
||||
uint32 i = 0;
|
||||
uint32 import_func_i = 0;
|
||||
uint32 import_global_i = 0;
|
||||
wasm_extern_t *import = NULL;
|
||||
wasm_func_t *func = NULL;
|
||||
wasm_global_t *global = NULL;
|
||||
|
||||
bh_assert(inst && module_aot && imports);
|
||||
|
||||
while (import_func_i < module_aot->import_func_count
|
||||
|| import_global_i < module_aot->import_global_count) {
|
||||
import = imports[i++];
|
||||
|
||||
bh_assert(import);
|
||||
|
||||
switch (wasm_extern_kind(import)) {
|
||||
case WASM_EXTERN_FUNC:
|
||||
bh_assert(import_func_i < module_aot->import_func_count);
|
||||
func = wasm_extern_as_func((wasm_extern_t *)import);
|
||||
if (!aot_link_func(inst, module_aot, import_func_i, func)) {
|
||||
LOG_WARNING("link #%d function failed", import_func_i);
|
||||
goto failed;
|
||||
}
|
||||
import_func_i++;
|
||||
|
||||
break;
|
||||
case WASM_EXTERN_GLOBAL:
|
||||
bh_assert(import_global_i < module_aot->import_global_count);
|
||||
global = wasm_extern_as_global((wasm_extern_t *)import);
|
||||
if (!aot_link_global(module_aot, import_global_i, global)) {
|
||||
LOG_WARNING("link #%d global failed", import_global_i);
|
||||
goto failed;
|
||||
}
|
||||
import_global_i++;
|
||||
|
||||
break;
|
||||
case WASM_EXTERN_MEMORY:
|
||||
case WASM_EXTERN_TABLE:
|
||||
default:
|
||||
ASSERT_NOT_IMPLEMENTED();
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
failed:
|
||||
LOG_DEBUG("%s failed", __FUNCTION__);
|
||||
return false;
|
||||
@ -4693,7 +4670,7 @@ aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot,
|
||||
goto failed;
|
||||
}
|
||||
|
||||
wasm_name_new_from_string(external->name, export->name);
|
||||
wasm_name_new_from_string_nt(external->name, export->name);
|
||||
if (strlen(export->name) && !external->name->data) {
|
||||
goto failed;
|
||||
}
|
||||
@ -4711,6 +4688,95 @@ failed:
|
||||
}
|
||||
#endif /* WASM_ENABLE_AOT */
|
||||
|
||||
static bool
|
||||
do_link(const wasm_instance_t *inst, const wasm_module_t *module,
|
||||
const wasm_extern_vec_t *imports)
|
||||
{
|
||||
uint32 i, import_func_i, import_global_i;
|
||||
|
||||
bh_assert(inst && module);
|
||||
|
||||
/* we have run a module_type check before. */
|
||||
|
||||
for (i = 0, import_func_i = 0, import_global_i = 0; i < imports->num_elems;
|
||||
i++) {
|
||||
wasm_extern_t *import = imports->data[i];
|
||||
|
||||
if (!import) {
|
||||
LOG_ERROR("imports[%d] is NULL and it is fatal\n", i);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
switch (wasm_extern_kind(import)) {
|
||||
case WASM_EXTERN_FUNC:
|
||||
{
|
||||
bool ret = false;
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if ((*module)->module_type == Wasm_Module_Bytecode) {
|
||||
ret = interp_link_func(inst, MODULE_INTERP(module),
|
||||
import_func_i,
|
||||
wasm_extern_as_func(import));
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if ((*module)->module_type == Wasm_Module_AoT) {
|
||||
ret = aot_link_func(inst, MODULE_AOT(module), import_func_i,
|
||||
wasm_extern_as_func(import));
|
||||
}
|
||||
#endif
|
||||
if (!ret) {
|
||||
LOG_WARNING("link function #%d failed", import_func_i);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
import_func_i++;
|
||||
break;
|
||||
}
|
||||
case WASM_EXTERN_GLOBAL:
|
||||
{
|
||||
bool ret = false;
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if ((*module)->module_type == Wasm_Module_Bytecode) {
|
||||
ret = interp_link_global(MODULE_INTERP(module),
|
||||
import_global_i,
|
||||
wasm_extern_as_global(import));
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if ((*module)->module_type == Wasm_Module_AoT) {
|
||||
ret = aot_link_global(MODULE_AOT(module), import_global_i,
|
||||
wasm_extern_as_global(import));
|
||||
}
|
||||
#endif
|
||||
if (!ret) {
|
||||
LOG_WARNING("link global #%d failed", import_global_i);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
import_global_i++;
|
||||
break;
|
||||
}
|
||||
case WASM_EXTERN_MEMORY:
|
||||
case WASM_EXTERN_TABLE:
|
||||
{
|
||||
LOG_WARNING("doesn't support import memories and tables for "
|
||||
"now, ignore them");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
failed:
|
||||
LOG_DEBUG("%s failed", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
wasm_instance_t *
|
||||
wasm_instance_new(wasm_store_t *store, const wasm_module_t *module,
|
||||
const wasm_extern_vec_t *imports, own wasm_trap_t **trap)
|
||||
@ -4719,57 +4785,6 @@ wasm_instance_new(wasm_store_t *store, const wasm_module_t *module,
|
||||
KILOBYTE(32), KILOBYTE(32));
|
||||
}
|
||||
|
||||
static bool
|
||||
compare_imports(const wasm_module_t *module, const wasm_extern_vec_t *imports)
|
||||
{
|
||||
unsigned import_func_count = 0;
|
||||
unsigned import_global_count = 0;
|
||||
unsigned import_memory_count = 0;
|
||||
unsigned import_table_count = 0;
|
||||
unsigned i = 0;
|
||||
|
||||
for (i = 0; imports && i < imports->num_elems; i++) {
|
||||
wasm_extern_t *import = imports->data[i];
|
||||
switch (wasm_extern_kind(import)) {
|
||||
case WASM_EXTERN_FUNC:
|
||||
import_func_count++;
|
||||
break;
|
||||
case WASM_EXTERN_GLOBAL:
|
||||
import_global_count++;
|
||||
break;
|
||||
case WASM_EXTERN_MEMORY:
|
||||
import_memory_count++;
|
||||
break;
|
||||
case WASM_EXTERN_TABLE:
|
||||
import_table_count++;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if ((*module)->module_type == Wasm_Module_Bytecode)
|
||||
return import_func_count == MODULE_INTERP(module)->import_function_count
|
||||
&& import_global_count
|
||||
== MODULE_INTERP(module)->import_global_count
|
||||
&& import_memory_count
|
||||
== MODULE_INTERP(module)->import_memory_count
|
||||
&& import_table_count
|
||||
== MODULE_INTERP(module)->import_table_count;
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if ((*module)->module_type == Wasm_Module_AoT)
|
||||
return import_func_count == MODULE_AOT(module)->import_func_count
|
||||
&& import_global_count == MODULE_AOT(module)->import_global_count
|
||||
&& import_memory_count == MODULE_AOT(module)->import_memory_count
|
||||
&& import_table_count == MODULE_AOT(module)->import_table_count;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
wasm_instance_t *
|
||||
wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||
const wasm_extern_vec_t *imports,
|
||||
@ -4779,7 +4794,6 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||
char sub_error_buf[128] = { 0 };
|
||||
char error_buf[256] = { 0 };
|
||||
wasm_instance_t *instance = NULL;
|
||||
WASMModuleInstance *inst_rt;
|
||||
CApiFuncImport *func_import = NULL, **p_func_imports = NULL;
|
||||
uint32 i = 0, import_func_count = 0;
|
||||
uint64 total_size;
|
||||
@ -4790,11 +4804,9 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||
if (!module)
|
||||
return NULL;
|
||||
|
||||
if (!compare_imports(module, imports)) {
|
||||
snprintf(sub_error_buf, sizeof(sub_error_buf),
|
||||
"Failed to match imports");
|
||||
goto failed;
|
||||
}
|
||||
/*
|
||||
* will do the check at the end of wasm_runtime_instantiate
|
||||
*/
|
||||
|
||||
WASM_C_DUMP_PROC_MEM();
|
||||
|
||||
@ -4805,43 +4817,17 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* link module and imports */
|
||||
if (imports && imports->num_elems) {
|
||||
bool link = false;
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if ((*module)->module_type == Wasm_Module_Bytecode) {
|
||||
if (!interp_link(instance, MODULE_INTERP(module),
|
||||
(wasm_extern_t **)imports->data)) {
|
||||
snprintf(sub_error_buf, sizeof(sub_error_buf),
|
||||
"Failed to validate imports");
|
||||
goto failed;
|
||||
}
|
||||
link = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if ((*module)->module_type == Wasm_Module_AoT) {
|
||||
if (!aot_link(instance, MODULE_AOT(module),
|
||||
(wasm_extern_t **)imports->data)) {
|
||||
snprintf(sub_error_buf, sizeof(sub_error_buf),
|
||||
"Failed to validate imports");
|
||||
goto failed;
|
||||
}
|
||||
link = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* a wrong combination of module filetype and compilation flags
|
||||
* also leads to below branch
|
||||
*/
|
||||
if (!link) {
|
||||
/* executes the instantiate-time linking if provided */
|
||||
if (imports) {
|
||||
if (!do_link(instance, module, imports)) {
|
||||
snprintf(sub_error_buf, sizeof(sub_error_buf),
|
||||
"Failed to verify import count");
|
||||
"Failed to validate imports");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* will do the linking result check at the end of wasm_runtime_instantiate
|
||||
*/
|
||||
|
||||
instance->inst_comm_rt = wasm_runtime_instantiate(
|
||||
*module, stack_size, heap_size, sub_error_buf, sizeof(sub_error_buf));
|
||||
@ -4856,18 +4842,22 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||
}
|
||||
|
||||
/* create the c-api func import list */
|
||||
inst_rt = (WASMModuleInstance *)instance->inst_comm_rt;
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||
p_func_imports = &inst_rt->e->c_api_func_imports;
|
||||
import_func_count = inst_rt->module->import_function_count;
|
||||
WASMModuleInstanceExtra *e =
|
||||
((WASMModuleInstance *)instance->inst_comm_rt)->e;
|
||||
p_func_imports = &(e->c_api_func_imports);
|
||||
import_func_count = MODULE_INTERP(module)->import_function_count;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||
p_func_imports =
|
||||
&((AOTModuleInstanceExtra *)inst_rt->e)->c_api_func_imports;
|
||||
import_func_count = ((AOTModule *)inst_rt->module)->import_func_count;
|
||||
AOTModuleInstanceExtra *e =
|
||||
(AOTModuleInstanceExtra *)((AOTModuleInstance *)
|
||||
instance->inst_comm_rt)
|
||||
->e;
|
||||
p_func_imports = &(e->c_api_func_imports);
|
||||
import_func_count = MODULE_AOT(module)->import_func_count;
|
||||
}
|
||||
#endif
|
||||
bh_assert(p_func_imports);
|
||||
@ -4880,16 +4870,21 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* fill in c-api func import list */
|
||||
/* fill in module_inst->e->c_api_func_imports */
|
||||
for (i = 0; imports && i < imports->num_elems; i++) {
|
||||
wasm_func_t *func_host;
|
||||
wasm_extern_t *in;
|
||||
wasm_func_t *func_host = NULL;
|
||||
wasm_extern_t *in = imports->data[i];
|
||||
bh_assert(in);
|
||||
|
||||
in = imports->data[i];
|
||||
if (wasm_extern_kind(in) != WASM_EXTERN_FUNC)
|
||||
continue;
|
||||
|
||||
func_host = wasm_extern_as_func(in);
|
||||
/* it is a placeholder and let's skip it*/
|
||||
if (!func_host->type) {
|
||||
func_import++;
|
||||
continue;
|
||||
}
|
||||
|
||||
func_import->with_env_arg = func_host->with_env;
|
||||
if (func_host->with_env) {
|
||||
@ -4900,6 +4895,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||
func_import->func_ptr_linked = func_host->u.cb;
|
||||
func_import->env_arg = NULL;
|
||||
}
|
||||
bh_assert(func_import->func_ptr_linked);
|
||||
|
||||
func_import++;
|
||||
}
|
||||
@ -4907,6 +4903,8 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||
/* fill with inst */
|
||||
for (i = 0; imports && imports->data && i < imports->num_elems; ++i) {
|
||||
wasm_extern_t *import = imports->data[i];
|
||||
bh_assert(import);
|
||||
|
||||
switch (import->kind) {
|
||||
case WASM_EXTERN_FUNC:
|
||||
wasm_extern_as_func(import)->inst_comm_rt =
|
||||
@ -5002,7 +5000,7 @@ failed:
|
||||
sub_error_buf);
|
||||
if (trap != NULL) {
|
||||
wasm_message_t message = { 0 };
|
||||
wasm_name_new_from_string(&message, error_buf);
|
||||
wasm_name_new_from_string_nt(&message, error_buf);
|
||||
*trap = wasm_trap_new(store, &message);
|
||||
wasm_byte_vec_delete(&message);
|
||||
}
|
||||
@ -5202,3 +5200,16 @@ BASIC_FOUR_LIST(WASM_EXTERN_AS_OTHER_CONST)
|
||||
|
||||
BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN_CONST)
|
||||
#undef WASM_OTHER_AS_EXTERN_CONST
|
||||
|
||||
wasm_extern_t *
|
||||
wasm_extern_new_empty(wasm_store_t *store, wasm_externkind_t extern_kind)
|
||||
{
|
||||
if (extern_kind == WASM_EXTERN_FUNC)
|
||||
return wasm_func_as_extern(wasm_func_new_empty(store));
|
||||
|
||||
if (extern_kind == WASM_EXTERN_GLOBAL)
|
||||
return wasm_global_as_extern(wasm_global_new_empty(store));
|
||||
|
||||
LOG_ERROR("Don't support linking table and memory for now");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -211,6 +211,7 @@ wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
|
||||
exec_env->handle = os_self_thread();
|
||||
exec_env->native_stack_boundary =
|
||||
stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL;
|
||||
exec_env->native_stack_top_min = (void *)UINTPTR_MAX;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
|
||||
@ -84,6 +84,12 @@ typedef struct WASMExecEnv {
|
||||
void **native_symbol;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The lowest stack pointer value observed.
|
||||
* Assumption: native stack grows to the lower address.
|
||||
*/
|
||||
uint8 *native_stack_top_min;
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
/**
|
||||
* Cache for
|
||||
@ -165,6 +171,17 @@ typedef struct WASMExecEnv {
|
||||
} wasm_stack;
|
||||
} WASMExecEnv;
|
||||
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
#define RECORD_STACK_USAGE(e, p) \
|
||||
do { \
|
||||
if ((e)->native_stack_top_min > (p)) { \
|
||||
(e)->native_stack_top_min = (p); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define RECORD_STACK_USAGE(e, p) (void)0
|
||||
#endif
|
||||
|
||||
WASMExecEnv *
|
||||
wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size);
|
||||
|
||||
@ -250,6 +250,10 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* allow func_type and all outputs, like p_signature, p_attachment and
|
||||
* p_call_conv_raw to be NULL
|
||||
*/
|
||||
void *
|
||||
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
||||
const WASMType *func_type, const char **p_signature,
|
||||
@ -275,10 +279,13 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
||||
node = node_next;
|
||||
}
|
||||
|
||||
if (!p_signature || !p_attachment || !p_call_conv_raw)
|
||||
return func_ptr;
|
||||
|
||||
if (func_ptr) {
|
||||
if (signature && signature[0] != '\0') {
|
||||
/* signature is not empty, check its format */
|
||||
if (!check_symbol_signature(func_type, signature)) {
|
||||
if (!func_type || !check_symbol_signature(func_type, signature)) {
|
||||
#if WASM_ENABLE_WAMR_COMPILER == 0
|
||||
/* Output warning except running aot compiler */
|
||||
LOG_WARNING("failed to check signature '%s' and resolve "
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "bh_common.h"
|
||||
#include "bh_assert.h"
|
||||
#include "bh_log.h"
|
||||
#include "wasm_native.h"
|
||||
#include "wasm_runtime_common.h"
|
||||
#include "wasm_memory.h"
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
@ -128,6 +129,12 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
|
||||
static JitCompOptions jit_options = { 0 };
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
static LLVMJITOptions llvm_jit_options = { 3, 3 };
|
||||
#endif
|
||||
|
||||
static RunningMode runtime_running_mode = Mode_Default;
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
/* The exec_env of thread local storage, set before calling function
|
||||
and used in signal handler, as we cannot get it from the argument
|
||||
@ -514,6 +521,20 @@ wasm_runtime_destroy()
|
||||
wasm_runtime_memory_destroy();
|
||||
}
|
||||
|
||||
RunningMode
|
||||
wasm_runtime_get_default_running_mode(void)
|
||||
{
|
||||
return runtime_running_mode;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
LLVMJITOptions
|
||||
wasm_runtime_get_llvm_jit_options(void)
|
||||
{
|
||||
return llvm_jit_options;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
wasm_runtime_full_init(RuntimeInitArgs *init_args)
|
||||
{
|
||||
@ -521,10 +542,20 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
|
||||
&init_args->mem_alloc_option))
|
||||
return false;
|
||||
|
||||
if (!wasm_runtime_set_default_running_mode(init_args->running_mode)) {
|
||||
wasm_runtime_memory_destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
jit_options.code_cache_size = init_args->fast_jit_code_cache_size;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
llvm_jit_options.size_level = init_args->llvm_jit_size_level;
|
||||
llvm_jit_options.opt_level = init_args->llvm_jit_opt_level;
|
||||
#endif
|
||||
|
||||
if (!wasm_runtime_env_init()) {
|
||||
wasm_runtime_memory_destroy();
|
||||
return false;
|
||||
@ -554,6 +585,47 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_is_running_mode_supported(RunningMode running_mode)
|
||||
{
|
||||
if (running_mode == Mode_Default) {
|
||||
return true;
|
||||
}
|
||||
else if (running_mode == Mode_Interp) {
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
else if (running_mode == Mode_Fast_JIT) {
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
else if (running_mode == Mode_LLVM_JIT) {
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
else if (running_mode == Mode_Multi_Tier_JIT) {
|
||||
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
|
||||
&& WASM_ENABLE_LAZY_JIT != 0
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_set_default_running_mode(RunningMode running_mode)
|
||||
{
|
||||
if (wasm_runtime_is_running_mode_supported(running_mode)) {
|
||||
runtime_running_mode = running_mode;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PackageType
|
||||
get_package_type(const uint8 *buf, uint32 size)
|
||||
{
|
||||
@ -1171,6 +1243,41 @@ wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
|
||||
RunningMode running_mode)
|
||||
{
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstance *module_inst_interp =
|
||||
(WASMModuleInstance *)module_inst;
|
||||
|
||||
return wasm_set_running_mode(module_inst_interp, running_mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
RunningMode
|
||||
wasm_runtime_get_running_mode(wasm_module_inst_t module_inst)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstance *module_inst_interp =
|
||||
(WASMModuleInstance *)module_inst;
|
||||
return module_inst_interp->e->running_mode;
|
||||
}
|
||||
#endif
|
||||
|
||||
return Mode_Default;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
@ -1399,6 +1506,22 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env)
|
||||
else
|
||||
os_printf("Total aux stack used: no enough info to profile\n");
|
||||
|
||||
/*
|
||||
* Report the native stack usage estimation.
|
||||
*
|
||||
* Unlike the aux stack above, we report the amount unused
|
||||
* because we don't know the stack "bottom".
|
||||
*
|
||||
* Note that this is just about what the runtime itself observed.
|
||||
* It doesn't cover host func implementations, signal handlers, etc.
|
||||
*/
|
||||
if (exec_env->native_stack_top_min != (void *)UINTPTR_MAX)
|
||||
os_printf("Native stack left: %zd\n",
|
||||
exec_env->native_stack_top_min
|
||||
- exec_env->native_stack_boundary);
|
||||
else
|
||||
os_printf("Native stack left: no enough info to profile\n");
|
||||
|
||||
os_printf("Total app heap used: %u\n", app_heap_peak_size);
|
||||
}
|
||||
#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
|
||||
@ -2195,6 +2318,12 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
|
||||
if (exec_env) {
|
||||
wasm_cluster_spread_exception(exec_env, exception ? false : true);
|
||||
}
|
||||
#if WASM_ENABLE_SHARED_MEMORY
|
||||
if (exception) {
|
||||
notify_stale_threads_on_exception(
|
||||
(WASMModuleInstanceCommon *)module_inst);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
(void)exec_env;
|
||||
#endif
|
||||
@ -2219,9 +2348,7 @@ static const char *exception_msgs[] = {
|
||||
"wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
|
||||
"out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
|
||||
"wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
"failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
|
||||
#endif
|
||||
"", /* EXCE_ALREADY_THROWN */
|
||||
};
|
||||
/* clang-format on */
|
||||
@ -5205,3 +5332,24 @@ wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
|
||||
*minor = WAMR_VERSION_MINOR;
|
||||
*patch = WAMR_VERSION_PATCH;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_is_import_func_linked(const char *module_name,
|
||||
const char *func_name)
|
||||
{
|
||||
return wasm_native_resolve_symbol(module_name, func_name, NULL, NULL, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_is_import_global_linked(const char *module_name,
|
||||
const char *global_name)
|
||||
{
|
||||
#if WASM_ENABLE_LIBC_BUILTIN != 0
|
||||
WASMGlobalImport global = { 0 };
|
||||
return wasm_native_lookup_libc_builtin_global(module_name, global_name,
|
||||
&global);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -25,6 +25,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Internal use for setting default running mode */
|
||||
#define Mode_Default 0
|
||||
|
||||
#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
|
||||
|
||||
#define PUT_I64_TO_ADDR(addr, value) \
|
||||
@ -413,6 +416,13 @@ typedef struct wasm_frame_t {
|
||||
const char *func_name_wp;
|
||||
} WASMCApiFrame;
|
||||
|
||||
#ifdef WASM_ENABLE_JIT
|
||||
typedef struct LLVMJITOptions {
|
||||
uint32 opt_level;
|
||||
uint32 size_level;
|
||||
} LLVMJITOptions;
|
||||
#endif
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
/* Signal info passing to interp/aot signal handler */
|
||||
typedef struct WASMSignalInfo {
|
||||
@ -437,10 +447,28 @@ wasm_runtime_get_exec_env_tls(void);
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_init(void);
|
||||
|
||||
/* Internal API */
|
||||
RunningMode
|
||||
wasm_runtime_get_default_running_mode(void);
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
/* Internal API */
|
||||
LLVMJITOptions
|
||||
wasm_runtime_get_llvm_jit_options(void);
|
||||
#endif
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_full_init(RuntimeInitArgs *init_args);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_is_running_mode_supported(RunningMode running_mode);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_set_default_running_mode(RunningMode running_mode);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_destroy(void);
|
||||
@ -484,6 +512,15 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size,
|
||||
uint32 heap_size, char *error_buf,
|
||||
uint32 error_buf_size);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
|
||||
RunningMode running_mode);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN RunningMode
|
||||
wasm_runtime_get_running_mode(wasm_module_inst_t module_inst);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst);
|
||||
@ -956,6 +993,14 @@ void
|
||||
wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list);
|
||||
#endif
|
||||
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_is_import_func_linked(const char *module_name,
|
||||
const char *func_name);
|
||||
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_is_import_global_linked(const char *module_name,
|
||||
const char *global_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -30,6 +30,11 @@ typedef struct AtomicWaitNode {
|
||||
korp_cond wait_cond;
|
||||
} AtomicWaitNode;
|
||||
|
||||
typedef struct AtomicWaitAddressArgs {
|
||||
uint32 index;
|
||||
void **addr;
|
||||
} AtomicWaitAddressArgs;
|
||||
|
||||
/* Atomic wait map */
|
||||
static HashMap *wait_map;
|
||||
|
||||
@ -87,6 +92,61 @@ search_module(WASMModuleCommon *module)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
wait_map_address_count_callback(void *key, void *value,
|
||||
void *p_total_elem_count)
|
||||
{
|
||||
*(uint32 *)p_total_elem_count = *(uint32 *)p_total_elem_count + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
create_list_of_waiter_addresses(void *key, void *value, void *user_data)
|
||||
{
|
||||
AtomicWaitAddressArgs *data = (AtomicWaitAddressArgs *)user_data;
|
||||
data->addr[data->index++] = key;
|
||||
}
|
||||
|
||||
void
|
||||
notify_stale_threads_on_exception(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
AtomicWaitAddressArgs args = { 0 };
|
||||
uint32 i = 0, total_elem_count = 0;
|
||||
uint64 total_elem_count_size = 0;
|
||||
|
||||
os_mutex_lock(&shared_memory_list_lock);
|
||||
|
||||
/* count number of addresses in wait_map */
|
||||
bh_hash_map_traverse(wait_map, wait_map_address_count_callback,
|
||||
(void *)&total_elem_count);
|
||||
|
||||
if (!total_elem_count) {
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate memory */
|
||||
total_elem_count_size = (uint64)sizeof(void *) * total_elem_count;
|
||||
if (total_elem_count_size >= UINT32_MAX
|
||||
|| !(args.addr = wasm_runtime_malloc((uint32)total_elem_count_size))) {
|
||||
LOG_ERROR(
|
||||
"failed to allocate memory for list of atomic wait addresses");
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* set values in list of addresses */
|
||||
bh_hash_map_traverse(wait_map, create_list_of_waiter_addresses, &args);
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
|
||||
/* notify */
|
||||
for (i = 0; i < args.index; i++) {
|
||||
wasm_runtime_atomic_notify(module_inst, args.addr[i], UINT32_MAX);
|
||||
}
|
||||
|
||||
/* free memory allocated to args data */
|
||||
wasm_runtime_free(args.addr);
|
||||
}
|
||||
|
||||
WASMSharedMemNode *
|
||||
wasm_module_get_shared_memory(WASMModuleCommon *module)
|
||||
{
|
||||
@ -120,6 +180,7 @@ shared_memory_dec_reference(WASMModuleCommon *module)
|
||||
bh_list_remove(shared_memory_list, node);
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
|
||||
os_mutex_destroy(&node->shared_mem_lock);
|
||||
os_mutex_destroy(&node->lock);
|
||||
wasm_runtime_free(node);
|
||||
}
|
||||
@ -148,7 +209,14 @@ shared_memory_set_memory_inst(WASMModuleCommon *module,
|
||||
node->module = module;
|
||||
node->memory_inst = memory;
|
||||
node->ref_count = 1;
|
||||
|
||||
if (os_mutex_init(&node->shared_mem_lock) != 0) {
|
||||
wasm_runtime_free(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (os_mutex_init(&node->lock) != 0) {
|
||||
os_mutex_destroy(&node->shared_mem_lock);
|
||||
wasm_runtime_free(node);
|
||||
return NULL;
|
||||
}
|
||||
@ -322,6 +390,10 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
bh_assert(module->module_type == Wasm_Module_Bytecode
|
||||
|| module->module_type == Wasm_Module_AoT);
|
||||
|
||||
if (wasm_get_exception(module_inst)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Currently we have only one memory instance */
|
||||
if (!module_inst->memories[0]->is_shared) {
|
||||
wasm_runtime_set_exception(module, "expected shared memory");
|
||||
|
||||
@ -26,6 +26,8 @@ typedef struct WASMSharedMemNode {
|
||||
WASMModuleCommon *module;
|
||||
/* The memory information */
|
||||
WASMMemoryInstanceCommon *memory_inst;
|
||||
/* Lock used for atomic operations */
|
||||
korp_mutex shared_mem_lock;
|
||||
|
||||
/* reference count */
|
||||
uint32 ref_count;
|
||||
@ -37,6 +39,9 @@ wasm_shared_memory_init();
|
||||
void
|
||||
wasm_shared_memory_destroy();
|
||||
|
||||
void
|
||||
notify_stale_threads_on_exception(WASMModuleInstanceCommon *module);
|
||||
|
||||
WASMSharedMemNode *
|
||||
wasm_module_get_shared_memory(WASMModuleCommon *module);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user