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:
@ -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, ¶m_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 **)¶m->of.ref)) {
|
||||
return false;
|
||||
}
|
||||
if (!wasm_externref_ref2obj(*argv,
|
||||
(void **)¶m->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;
|
||||
|
||||
Reference in New Issue
Block a user