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

@ -1199,46 +1199,163 @@ wasm_runtime_lookup_function(WASMModuleInstanceCommon *const module_inst,
}
#if WASM_ENABLE_REF_TYPES != 0
static void
wasm_runtime_reclaim_externref(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function,
uint32 *argv)
/* (uintptr_t)externref -> (uint32_t)index */
/* argv -> *ret_argv */
static bool
wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function,
uint32 *argv, uint32 argc, uint32 **ret_argv,
uint32 *ret_argc_param,
uint32 *ret_argc_result)
{
uint32 i = 0, cell_num = 0;
uint32 *new_argv = NULL, argv_i = 0, new_argv_i = 0, param_i = 0,
result_i = 0;
bool need_param_transform = false, need_result_transform = false;
uint64 size = 0;
WASMType *func_type = wasm_runtime_get_function_type(
function, exec_env->module_inst->module_type);
bh_assert(func_type);
*ret_argc_param = func_type->param_cell_num;
*ret_argc_result = func_type->ret_cell_num;
for (param_i = 0; param_i < func_type->param_count; param_i++) {
if (VALUE_TYPE_EXTERNREF == func_type->types[param_i]) {
need_param_transform = true;
}
}
for (result_i = 0; result_i < func_type->result_count; result_i++) {
if (VALUE_TYPE_EXTERNREF
== func_type->types[func_type->param_count + result_i]) {
need_result_transform = true;
}
}
if (!need_param_transform && !need_result_transform) {
*ret_argv = argv;
return true;
}
if (func_type->param_cell_num >= func_type->ret_cell_num) {
size = sizeof(uint32) * func_type->param_cell_num;
}
else {
size = sizeof(uint32) * func_type->ret_cell_num;
}
if (!(new_argv = runtime_malloc(size, exec_env->module_inst, NULL, 0))) {
return false;
}
if (!need_param_transform) {
bh_memcpy_s(new_argv, size, argv, size);
}
else {
for (param_i = 0; param_i < func_type->param_count && argv_i < argc
&& new_argv_i < func_type->param_cell_num;
param_i++) {
uint8 param_type = func_type->types[param_i];
if (VALUE_TYPE_EXTERNREF == param_type) {
void *externref_obj;
uint32 externref_index;
#if UINTPTR_MAX == UINT32_MAX
externref_obj = (void *)argv[argv_i];
#else
union {
uintptr_t val;
uint32 parts[2];
} u;
u.parts[0] = argv[argv_i];
u.parts[1] = argv[argv_i + 1];
externref_obj = (void *)u.val;
#endif
if (!wasm_externref_obj2ref(exec_env->module_inst,
externref_obj, &externref_index)) {
wasm_runtime_free(new_argv);
return false;
}
new_argv[new_argv_i] = externref_index;
argv_i += sizeof(uintptr_t) / sizeof(uint32);
new_argv_i++;
}
else {
uint16 param_cell_num = wasm_value_type_cell_num(param_type);
uint32 param_size = sizeof(uint32) * param_cell_num;
bh_memcpy_s(new_argv + new_argv_i, param_size, argv + argv_i,
param_size);
argv_i += param_cell_num;
new_argv_i += param_cell_num;
}
}
}
*ret_argv = new_argv;
return true;
}
/* (uintptr_t)externref <- (uint32_t)index */
/* argv <- new_argv */
static bool
wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function,
uint32 *argv, uint32 argc, uint32 *ret_argv)
{
uint32 argv_i = 0, result_i = 0, ret_argv_i = 0;
WASMType *func_type;
bh_assert(argv && ret_argv);
if (argv == ret_argv) {
return true;
}
func_type = wasm_runtime_get_function_type(
function, exec_env->module_inst->module_type);
bh_assert(func_type);
while (i < func_type->result_count) {
uint8 result_type = func_type->types[func_type->param_count + i];
if (result_type == VALUE_TYPE_EXTERNREF && argv[i] != NULL_REF) {
/* Retain the externref returned to runtime embedder */
(void)wasm_externref_retain(argv[i]);
for (result_i = 0; result_i < func_type->result_count && argv_i < argc;
result_i++) {
uint8 result_type = func_type->types[func_type->param_count + result_i];
if (result_type == VALUE_TYPE_EXTERNREF) {
void *externref_obj;
#if UINTPTR_MAX != UINT32_MAX
union {
uintptr_t val;
uint32 parts[2];
} u;
#endif
if (!wasm_externref_ref2obj(argv[argv_i], &externref_obj)) {
wasm_runtime_free(argv);
return false;
}
#if UINTPTR_MAX == UINT32_MAX
ret_argv[ret_argv_i] = (uintptr_t)externref_obj;
#else
u.val = (uintptr_t)externref_obj;
ret_argv[ret_argv_i] = u.parts[0];
ret_argv[ret_argv_i + 1] = u.parts[1];
#endif
argv_i += 1;
ret_argv_i += sizeof(uintptr_t) / sizeof(uint32);
}
else {
uint16 result_cell_num = wasm_value_type_cell_num(result_type);
uint32 result_size = sizeof(uint32) * result_cell_num;
bh_memcpy_s(ret_argv + ret_argv_i, result_size, argv + argv_i,
result_size);
argv_i += result_cell_num;
ret_argv_i += result_cell_num;
}
cell_num += wasm_value_type_cell_num(result_type);
i++;
}
wasm_externref_reclaim(exec_env->module_inst);
}
void
wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function)
{
exec_env->nested_calling_depth++;
}
void
wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function,
bool ret, uint32 *argv)
{
exec_env->nested_calling_depth--;
if (!exec_env->nested_calling_depth && ret) {
wasm_runtime_reclaim_externref(exec_env, function, argv);
}
wasm_runtime_free(argv);
return true;
}
#endif
@ -1248,6 +1365,10 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
uint32 argv[])
{
bool ret = false;
uint32 *new_argv = NULL, param_argc;
#if WASM_ENABLE_REF_TYPES != 0
uint32 result_argc = 0;
#endif
if (!wasm_runtime_exec_env_check(exec_env)) {
LOG_ERROR("Invalid exec env stack info.");
@ -1255,34 +1376,53 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
}
#if WASM_ENABLE_REF_TYPES != 0
wasm_runtime_prepare_call_function(exec_env, function);
if (!wasm_runtime_prepare_call_function(exec_env, function, argv, argc,
&new_argv, &param_argc,
&result_argc)) {
wasm_runtime_set_exception(exec_env->module_inst,
"the arguments conversion is failed");
return false;
}
#else
new_argv = argv;
param_argc = argc;
#endif
#if WASM_ENABLE_INTERP != 0
if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
ret = wasm_call_function(exec_env, (WASMFunctionInstance *)function,
argc, argv);
param_argc, new_argv);
#endif
#if WASM_ENABLE_AOT != 0
if (exec_env->module_inst->module_type == Wasm_Module_AoT)
ret = aot_call_function(exec_env, (AOTFunctionInstance *)function, argc,
argv);
ret = aot_call_function(exec_env, (AOTFunctionInstance *)function,
param_argc, new_argv);
#endif
if (!ret) {
if (new_argv != argv) {
wasm_runtime_free(new_argv);
}
return false;
}
#if WASM_ENABLE_REF_TYPES != 0
wasm_runtime_finalize_call_function(exec_env, function, ret, argv);
if (!wasm_runtime_finalize_call_function(exec_env, function, new_argv,
result_argc, argv)) {
wasm_runtime_set_exception(exec_env->module_inst,
"the result conversion is failed");
return false;
}
#endif
return ret;
}
static uint32
parse_args_to_uint32_array(WASMType *type, uint32 num_args, wasm_val_t *args,
uint32 *out_argv)
static void
parse_args_to_uint32_array(WASMType *type, wasm_val_t *args, uint32 *out_argv)
{
uint32 i, p;
for (i = 0, p = 0; i < num_args; i++) {
for (i = 0, p = 0; i < type->param_count; i++) {
switch (args[i].kind) {
case WASM_I32:
out_argv[p++] = args[i].of.i32;
@ -1319,16 +1459,38 @@ parse_args_to_uint32_array(WASMType *type, uint32 num_args, wasm_val_t *args,
out_argv[p++] = u.parts[1];
break;
}
#if WASM_ENABLE_REF_TYPES != 0
case WASM_FUNCREF:
{
out_argv[p++] = args[i].of.i32;
break;
}
case WASM_ANYREF:
{
#if UINTPTR_MAX == UINT32_MAX
out_argv[p++] = args[i].of.foreign;
#else
union {
uintptr_t val;
uint32 parts[2];
} u;
u.val = (uintptr_t)args[i].of.foreign;
out_argv[p++] = u.parts[0];
out_argv[p++] = u.parts[1];
#endif
break;
}
#endif
default:
bh_assert(0);
break;
}
}
return p;
}
static uint32
parse_uint32_array_to_results(WASMType *type, uint32 argc, uint32 *argv,
static void
parse_uint32_array_to_results(WASMType *type, uint32 *argv,
wasm_val_t *out_results)
{
uint32 i, p;
@ -1374,13 +1536,36 @@ parse_uint32_array_to_results(WASMType *type, uint32 argc, uint32 *argv,
out_results[i].of.f64 = u.val;
break;
}
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
{
out_results[i].kind = WASM_I32;
out_results[i].of.i32 = (int32)argv[p++];
break;
}
case VALUE_TYPE_EXTERNREF:
{
#if UINTPTR_MAX == UINT32_MAX
out_results[i].kind = WASM_ANYREF;
out_results[i].of.foreign = (uintptr_t)argv[p++];
#else
union {
uintptr_t val;
uint32 parts[2];
} u;
u.parts[0] = argv[p++];
u.parts[1] = argv[p++];
out_results[i].kind = WASM_ANYREF;
out_results[i].of.foreign = u.val;
#endif
break;
}
#endif
default:
bh_assert(0);
break;
}
}
bh_assert(argc == p);
return type->result_count;
}
bool
@ -1389,7 +1574,10 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
uint32 num_results, wasm_val_t results[],
uint32 num_args, wasm_val_t args[])
{
uint32 argc, *argv, ret_num, cell_num, total_size, module_type;
uint32 argc, *argv, cell_num, total_size, module_type;
#if WASM_ENABLE_REF_TYPES != 0
uint32 i, param_size_in_double_world = 0, result_size_in_double_world = 0;
#endif
WASMType *type;
bool ret = false;
@ -1402,8 +1590,23 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
goto fail1;
}
#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]);
}
argc = param_size_in_double_world;
cell_num = (argc >= result_size_in_double_world)
? argc
: result_size_in_double_world;
#else
argc = type->param_cell_num;
cell_num = (argc > type->ret_cell_num) ? argc : type->ret_cell_num;
#endif
if (num_results != type->result_count) {
LOG_ERROR(
@ -1425,14 +1628,11 @@ wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
goto fail1;
}
argc = parse_args_to_uint32_array(type, num_args, args, argv);
if (!(ret = wasm_runtime_call_wasm(exec_env, function, argc, argv)))
parse_args_to_uint32_array(type, args, argv);
if (!(ret = wasm_runtime_call_wasm(exec_env, function, num_args, argv)))
goto fail2;
ret_num =
parse_uint32_array_to_results(type, type->ret_cell_num, argv, results);
bh_assert(ret_num == num_results);
(void)ret_num;
parse_uint32_array_to_results(type, argv, results);
fail2:
wasm_runtime_free(argv);
@ -1492,6 +1692,20 @@ wasm_runtime_call_wasm_v(WASMExecEnv *exec_env,
args[i].kind = WASM_F64;
args[i].of.f64 = va_arg(vargs, float64);
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
{
args[i].kind = WASM_FUNCREF;
args[i].of.i32 = va_arg(vargs, uint32);
break;
}
case VALUE_TYPE_EXTERNREF:
{
args[i].kind = WASM_ANYREF;
args[i].of.foreign = va_arg(vargs, uintptr_t);
break;
}
#endif
default:
bh_assert(0);
break;
@ -1547,13 +1761,21 @@ WASMExecEnv *
wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst)
{
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode)
if (module_inst->module_type == Wasm_Module_Bytecode) {
if (!((WASMModuleInstance *)module_inst)->exec_env_singleton) {
wasm_create_exec_env_singleton((WASMModuleInstance *)module_inst);
}
return ((WASMModuleInstance *)module_inst)->exec_env_singleton;
}
#endif
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT)
if (module_inst->module_type == Wasm_Module_AoT) {
if (!((AOTModuleInstance *)module_inst)->exec_env_singleton.ptr) {
aot_create_exec_env_singleton((AOTModuleInstance *)module_inst);
}
return (WASMExecEnv *)((AOTModuleInstance *)module_inst)
->exec_env_singleton.ptr;
}
#endif
return NULL;
}
@ -2497,6 +2719,9 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
for (i = 0; i < func_type->param_count; i++, argv_dst++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
*(uint32 *)argv_dst = arg_i32 = *argv_src++;
if (signature) {
@ -2540,10 +2765,19 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
*(float32 *)argv_dst = *(float32 *)argv_src++;
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
*(uint32 *)argv_dst = *argv_src++;
{
uint32 externref_idx = *argv_src++;
void *externref_obj;
if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
goto fail;
bh_memcpy_s(argv_dst, sizeof(uintptr_t), argv_src,
sizeof(uintptr_t));
break;
}
#endif
default:
bh_assert(0);
@ -2560,7 +2794,6 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
argv_ret[0] = *(uint32 *)argv1;
break;
@ -2572,6 +2805,23 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
bh_memcpy_s(argv_ret, sizeof(uint32) * 2, argv1,
sizeof(uint64));
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
uint32 externref_idx;
uint64 externref_obj;
bh_memcpy_s(&externref_obj, sizeof(uint64), argv1,
sizeof(uint64));
if (!wasm_externref_obj2ref(exec_env->module_inst,
(void *)(uintptr_t)externref_obj,
&externref_idx))
goto fail;
argv_ret[0] = externref_idx;
break;
}
#endif
default:
bh_assert(0);
break;
@ -2634,6 +2884,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
uint32 result_count = func_type->result_count;
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
bool ret = false;
#if WASM_ENABLE_REF_TYPES != 0
bool is_aot_func = (NULL == signature);
#endif
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC)
uint32 *fps;
int n_fps = 0;
@ -2792,6 +3045,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
arg_i32 = *argv_src++;
@ -2829,17 +3085,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
stacks[n_stacks++] = arg_i32;
break;
}
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
{
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *argv_src++;
else
stacks[n_stacks++] = *argv_src++;
break;
}
#endif
case VALUE_TYPE_I64:
{
if (n_ints < MAX_REG_INTS - 1) {
@ -2959,6 +3204,31 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break;
}
#endif /* BUILD_TARGET_RISCV32_ILP32D */
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
uint32 externref_idx = *argv_src++;
if (is_aot_func) {
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = externref_idx;
else
stacks[n_stacks++] = externref_idx;
}
else {
void *externref_obj;
if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
goto fail;
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = (uintptr_t)externref_obj;
else
stacks[n_stacks++] = (uintptr_t)externref_obj;
}
break;
}
#endif
default:
bh_assert(0);
break;
@ -2982,7 +3252,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
argv_ret[0] =
(uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
@ -2999,6 +3268,30 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
PUT_F64_TO_ADDR(
argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
if (is_aot_func) {
uint32 externref_idx =
(uint32)invokeNative_Int32(func_ptr, argv1, argc1);
argv_ret[0] = externref_idx;
}
else {
uint32 externref_idx;
void *externref_obj;
externref_obj = (void *)(uintptr_t)invokeNative_Int32(
func_ptr, argv1, argc1);
if (!wasm_externref_obj2ref(exec_env->module_inst,
externref_obj, &externref_idx))
goto fail;
argv_ret[0] = externref_idx;
}
break;
}
#endif
default:
bh_assert(0);
break;
@ -3060,6 +3353,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
uint64 size;
bool ret = false;
#if WASM_ENABLE_REF_TYPES != 0
bool is_aot_func = (NULL == signature);
#endif
#if defined(BUILD_TARGET_X86_32)
argc1 = argc + ext_ret_count + 2;
@ -3083,6 +3379,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
arg_i32 = *argv++;
@ -3129,12 +3428,26 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
argv1[j++] = *argv++;
break;
case VALUE_TYPE_F32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
argv1[j++] = *argv++;
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
uint32 externref_idx = *argv++;
if (is_aot_func) {
argv1[j++] = externref_idx;
}
else {
void *externref_obj;
if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
goto fail;
argv1[j++] = (uintptr_t)externref_obj;
}
break;
}
#endif
default:
bh_assert(0);
break;
@ -3154,7 +3467,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
argv_ret[0] =
(uint32)invokeNative_Int32(func_ptr, argv1, argc1);
@ -3171,6 +3483,26 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
PUT_F64_TO_ADDR(argv_ret,
invokeNative_Float64(func_ptr, argv1, argc1));
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
if (is_aot_func) {
uint32 externref_idx =
(uint32)invokeNative_Int32(func_ptr, argv1, argc1);
argv_ret[0] = externref_idx;
}
else {
void *externref_obj = (void *)(uintptr_t)invokeNative_Int32(
func_ptr, argv1, argc1);
uint32 externref_idx;
if (!wasm_externref_obj2ref(exec_env->module_inst,
externref_obj, &externref_idx))
goto fail;
argv_ret[0] = externref_idx;
}
break;
}
#endif
default:
bh_assert(0);
break;
@ -3281,12 +3613,16 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
uint32 *argv_ret)
{
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
uint64 argv_buf[32], *argv1 = argv_buf, *ints, *stacks, size, arg_i64;
uint64 argv_buf[32] = { 0 }, *argv1 = argv_buf, *ints, *stacks, size,
arg_i64;
uint32 *argv_src = argv, i, argc1, n_ints = 0, n_stacks = 0;
uint32 arg_i32, ptr_len;
uint32 result_count = func_type->result_count;
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
bool ret = false;
#if WASM_ENABLE_REF_TYPES != 0
bool is_aot_func = (NULL == signature);
#endif
#ifndef BUILD_TARGET_RISCV64_LP64
#if WASM_ENABLE_SIMD == 0
uint64 *fps;
@ -3336,6 +3672,9 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
for (i = 0; i < func_type->param_count; i++) {
switch (func_type->types[i]) {
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
#endif
{
arg_i32 = *argv_src++;
arg_i64 = arg_i32;
@ -3397,13 +3736,28 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
argv_src += 2;
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = *argv_src++;
else
stacks[n_stacks++] = *argv_src++;
{
uint32 externref_idx = *argv_src++;
if (is_aot_func) {
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = externref_idx;
else
stacks[n_stacks++] = externref_idx;
}
else {
void *externref_obj;
if (!wasm_externref_ref2obj(externref_idx, &externref_obj))
goto fail;
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = (uintptr_t)externref_obj;
else
stacks[n_stacks++] = (uintptr_t)externref_obj;
}
break;
}
#endif
#if WASM_ENABLE_SIMD != 0
case VALUE_TYPE_V128:
@ -3442,7 +3796,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_I32:
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_FUNCREF:
case VALUE_TYPE_EXTERNREF:
#endif
argv_ret[0] =
(uint32)invokeNative_Int32(func_ptr, argv1, n_stacks);
@ -3459,6 +3812,26 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
PUT_F64_TO_ADDR(
argv_ret, invokeNative_Float64(func_ptr, argv1, n_stacks));
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
{
if (is_aot_func) {
argv_ret[0] = invokeNative_Int32(func_ptr, argv1, n_stacks);
}
else {
uint32 externref_idx;
void *externref_obj = (void *)(uintptr_t)invokeNative_Int64(
func_ptr, argv1, n_stacks);
if (!wasm_externref_obj2ref(exec_env->module_inst,
externref_obj, &externref_idx))
goto fail;
argv_ret[0] = externref_idx;
}
break;
}
#endif
#if WASM_ENABLE_SIMD != 0
case VALUE_TYPE_V128:
*(v128 *)argv_ret =
@ -3709,10 +4082,24 @@ bool
wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst, void *extern_obj,
uint32 *p_externref_idx)
{
LookupExtObj_UserData lookup_user_data;
LookupExtObj_UserData lookup_user_data = { 0 };
ExternRefMapNode *node;
uint32 externref_idx;
/*
* to catch a parameter from `wasm_application_execute_func`,
* which represents a string 'null'
*/
#if UINTPTR_MAX == UINT32_MAX
if ((uint32)-1 == (uintptr_t)extern_obj) {
#else
if ((uint64)-1LL == (uintptr_t)extern_obj) {
#endif
*p_externref_idx = NULL_REF;
return true;
}
/* 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;
@ -3764,8 +4151,10 @@ wasm_externref_ref2obj(uint32 externref_idx, void **p_extern_obj)
{
ExternRefMapNode *node;
/* catch a `ref.null` vairable */
if (externref_idx == NULL_REF) {
return false;
*p_extern_obj = NULL;
return true;
}
os_mutex_lock(&externref_lock);
@ -4170,14 +4559,9 @@ argv_to_params(wasm_val_t *out_params, const uint32 *argv, WASMType *func_type)
case VALUE_TYPE_EXTERNREF:
param->kind = WASM_ANYREF;
if (NULL_REF == *argv) {
param->of.ref = NULL;
}
else {
if (!wasm_externref_ref2obj(*argv,
(void **)&param->of.ref)) {
return false;
}
if (!wasm_externref_ref2obj(*argv,
(void **)&param->of.foreign)) {
return false;
}
argv++;
@ -4213,8 +4597,8 @@ results_to_argv(WASMModuleInstanceCommon *module_inst, uint32 *out_argv,
break;
#if WASM_ENABLE_REF_TYPES != 0
case VALUE_TYPE_EXTERNREF:
if (!wasm_externref_obj2ref(module_inst, result->of.ref,
argv)) {
if (!wasm_externref_obj2ref(module_inst,
(void *)result->of.foreign, argv)) {
return false;
}
argv++;
@ -4234,17 +4618,19 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
uint32 argc, uint32 *argv, bool with_env,
void *wasm_c_api_env)
{
wasm_val_t params_buf[16], results_buf[4];
wasm_val_t params_buf[16] = { 0 }, results_buf[4] = { 0 };
wasm_val_t *params = params_buf, *results = results_buf;
wasm_trap_t *trap = NULL;
bool ret = false;
wasm_val_vec_t params_vec, results_vec;
if (func_type->param_count > 16
&& !(params = wasm_runtime_malloc(sizeof(wasm_val_t)
* func_type->param_count))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed");
return false;
if (func_type->param_count > 16) {
if (!(params =
runtime_malloc(sizeof(wasm_val_t) * func_type->param_count,
module_inst, NULL, 0))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed");
return false;
}
}
if (!argv_to_params(params, argv, func_type)) {
@ -4252,11 +4638,13 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
goto fail;
}
if (func_type->result_count > 4
&& !(results = wasm_runtime_malloc(sizeof(wasm_val_t)
* func_type->result_count))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed");
goto fail;
if (func_type->result_count > 4) {
if (!(results =
runtime_malloc(sizeof(wasm_val_t) * func_type->result_count,
module_inst, NULL, 0))) {
wasm_runtime_set_exception(module_inst, "allocate memory failed");
goto fail;
}
}
params_vec.data = params;