Refactor externref related APIs of reference types feature (#971)

Currently when calling wasm_runtime_call_wasm() to invoke wasm function
with externref type argument from runtime embedder, developer needs to
use wasm_externref_obj2ref() to convert externref obj into an internal ref
index firstly, which is not convenient to developer.
To align with GC feature in which all the references passed to
wasm_runtime_call_wasm() can be object pointers directly, we change the
interface of wasm_runtime_call_wasm() to allow to pass object pointer
directly for the externref argument, and refactor the related codes, update
the related samples and the document.
This commit is contained in:
Wenyong Huang
2022-01-19 11:25:08 +08:00
committed by GitHub
parent 2c743dbd51
commit 260d36a62d
30 changed files with 1148 additions and 595 deletions

View File

@ -82,6 +82,7 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
{
WASMFunctionInstanceCommon *func;
WASMType *func_type = NULL;
WASMExecEnv *exec_env = NULL;
uint32 argc1 = 0, argv1[2] = { 0 };
uint32 total_argv_size = 0;
uint64 total_size;
@ -91,14 +92,20 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
uint32 *argv_offsets, module_type;
bool ret, is_import_func = true;
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (!exec_env) {
wasm_runtime_set_exception(module_inst,
"create singleton exec_env failed");
return false;
}
#if WASM_ENABLE_LIBC_WASI != 0
/* In wasi mode, we should call the function named "_start"
which initializes the wasi envrionment and then calls
the actual main function. Directly calling main function
may cause exception thrown. */
if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) {
return wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, 0,
NULL);
return wasm_runtime_call_wasm(exec_env, func, 0, NULL);
}
#endif /* end of WASM_ENABLE_LIBC_WASI */
@ -179,8 +186,7 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
(uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets);
}
ret = wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, argc1,
argv1);
ret = wasm_runtime_call_wasm(exec_env, func, argc1, argv1);
if (ret && func_type->result_count > 0 && argc > 0 && argv)
/* copy the return value */
*(int *)argv = (int)argv1[0];
@ -345,7 +351,11 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
WASMFunctionInstanceCommon *target_func;
WASMModuleInstanceCommon *target_inst;
WASMType *type = NULL;
WASMExecEnv *exec_env = NULL;
uint32 argc1, *argv1 = NULL, cell_num = 0, j, k = 0;
#if WASM_ENABLE_REF_TYPES != 0
uint32 param_size_in_double_world = 0, result_size_in_double_world = 0;
#endif
int32 i, p, module_type;
uint64 total_size;
const char *exception;
@ -373,8 +383,23 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
goto fail;
}
#if WASM_ENABLE_REF_TYPES != 0
for (i = 0; i < type->param_count; i++) {
param_size_in_double_world +=
wasm_value_type_cell_num_outside(type->types[i]);
}
for (i = 0; i < type->result_count; i++) {
result_size_in_double_world += wasm_value_type_cell_num_outside(
type->types[type->param_count + i]);
}
argc1 = param_size_in_double_world;
cell_num = (param_size_in_double_world >= result_size_in_double_world)
? param_size_in_double_world
: result_size_in_double_world;
#else
argc1 = type->param_cell_num;
cell_num = (argc1 > type->ret_cell_num) ? argc1 : type->ret_cell_num;
#endif
total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2);
if ((!(argv1 = runtime_malloc((uint32)total_size, target_inst, NULL, 0)))) {
@ -487,9 +512,8 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
{
if (strncmp(argv[i], "null", 4) == 0
|| strncmp(argv[i], "NULL", 4) == 0) {
argv1[p++] = NULL_REF;
if (strncasecmp(argv[i], "null", 4) == 0) {
argv1[p++] = (uint32)-1;
}
else {
argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
@ -498,23 +522,27 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
}
case VALUE_TYPE_EXTERNREF:
{
if (strncmp(argv[i], "null", 4) == 0
|| strncmp(argv[i], "NULL", 4) == 0) {
argv1[p++] = NULL_REF;
#if UINTPTR_MAX == UINT32_MAX
if (strncasecmp(argv[i], "null", 4) == 0) {
argv1[p++] = (uint32)-1;
}
else {
uint64 val = strtoull(argv[i], &endptr, 0);
void *extern_obj = (void *)(uintptr_t)val;
uint32 externref_idx;
if (!wasm_externref_obj2ref(target_inst, extern_obj,
&externref_idx)) {
wasm_runtime_set_exception(
module_inst, "map extern object to ref failed");
goto fail;
}
argv1[p++] = externref_idx;
argv1[p++] = strtoul(argv[i], &endptr, 0);
}
#else
union {
uintptr_t val;
uint32 parts[2];
} u;
if (strncasecmp(argv[i], "null", 4) == 0) {
u.val = (uintptr_t)-1LL;
}
else {
u.val = strtoull(argv[i], &endptr, 0);
}
argv1[p++] = u.parts[0];
argv1[p++] = u.parts[1];
#endif
break;
}
#endif /* WASM_ENABLE_REF_TYPES */
@ -529,11 +557,20 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
goto fail;
}
}
bh_assert(p == (int32)argc1);
wasm_runtime_set_exception(module_inst, NULL);
if (!wasm_runtime_create_exec_env_and_call_wasm(target_inst, target_func,
argc1, argv1)) {
#if WASM_ENABLE_REF_TYPES == 0
bh_assert(p == (int32)argc1);
#endif
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (!exec_env) {
wasm_runtime_set_exception(module_inst,
"create singleton exec_env failed");
goto fail;
}
if (!wasm_runtime_call_wasm(exec_env, target_func, argc1, argv1)) {
goto fail;
}
@ -576,7 +613,7 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
os_printf("%.7g:f64", u.val);
break;
}
#if WASM_ENABLE_REF_TYPES
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
{
if (argv1[k] != NULL_REF)
@ -588,16 +625,25 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
}
case VALUE_TYPE_EXTERNREF:
{
if (argv1[k] != NULL_REF) {
void *extern_obj = NULL;
bool ret = wasm_externref_ref2obj(argv1[k], &extern_obj);
bh_assert(ret);
(void)ret;
os_printf("%p:ref.extern", extern_obj);
}
#if UINTPTR_MAX == UINT32_MAX
if (argv1[k] != 0 && argv1[k] != (uint32)-1)
os_printf("%p:ref.extern", (void *)argv1[k]);
else
os_printf("extern:ref.null");
k++;
#else
union {
uintptr_t val;
uint32 parts[2];
} u;
u.parts[0] = argv1[k];
u.parts[1] = argv1[k + 1];
k += 2;
if (u.val && u.val != (uintptr_t)-1LL)
os_printf("%p:ref.extern", (void *)u.val);
else
os_printf("extern:ref.null");
#endif
break;
}
#endif