Skip to content

Commit

Permalink
Refactor externref related APIs of reference types feature (bytecodea…
Browse files Browse the repository at this point in the history
…lliance#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.
  • Loading branch information
wenyongh authored Jan 19, 2022
1 parent 2c743db commit 260d36a
Show file tree
Hide file tree
Showing 30 changed files with 1,142 additions and 589 deletions.
1 change: 1 addition & 0 deletions core/iwasm/aot/aot_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@ load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,

/* keep sync with aot_emit_table_info() aot_emit_aot_file */
for (i = 0; i < module->import_table_count; i++, import_table++) {
read_uint32(buf, buf_end, import_table->elem_type);
read_uint32(buf, buf_end, import_table->table_init_size);
read_uint32(buf, buf_end, import_table->table_max_size);
read_uint32(buf, buf_end, possible_grow);
Expand Down
10 changes: 1 addition & 9 deletions core/iwasm/aot/aot_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ init_global_data(uint8 *global_data, uint8 type, WASMValue *initial_value)
switch (type) {
case VALUE_TYPE_I32:
case VALUE_TYPE_F32:
#if WASM_ENABLE_REF_TYPES
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
Expand Down Expand Up @@ -1572,16 +1572,8 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
}
}

#if WASM_ENABLE_REF_TYPES != 0
wasm_runtime_prepare_call_function(exec_env, func);
#endif

ret = aot_call_function(exec_env, func, argc, argv);

#if WASM_ENABLE_REF_TYPES != 0
wasm_runtime_finalize_call_function(exec_env, func, ret, argv);
#endif

/* don't destroy the exec_env if it's searched from the cluster */
if (!existing_exec_env)
wasm_exec_env_destroy(exec_env);
Expand Down
110 changes: 78 additions & 32 deletions core/iwasm/common/wasm_application.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 */

Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)))) {
Expand Down Expand Up @@ -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);
Expand All @@ -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 */
Expand All @@ -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;
}

Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down
Loading

0 comments on commit 260d36a

Please sign in to comment.