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

@ -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);

View File

@ -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
@ -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);

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

View File

@ -1235,9 +1235,8 @@ wasm_exporttype_type(const wasm_exporttype_t *export_type)
void
wasm_val_delete(wasm_val_t *v)
{
if (v) {
if (v)
wasm_runtime_free(v);
}
}
void
@ -1562,19 +1561,13 @@ wasm_trap_new_internal(WASMModuleInstanceCommon *inst_comm_rt,
#if WASM_ENABLE_INTERP != 0
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
if (!(error_info =
wasm_get_exception((WASMModuleInstance *)inst_comm_rt))) {
return NULL;
}
error_info = wasm_get_exception((WASMModuleInstance *)inst_comm_rt);
}
#endif
#if WASM_ENABLE_AOT != 0
if (inst_comm_rt->module_type == Wasm_Module_AoT) {
if (!(error_info =
aot_get_exception((AOTModuleInstance *)inst_comm_rt))) {
return NULL;
}
error_info = aot_get_exception((AOTModuleInstance *)inst_comm_rt);
}
#endif
@ -2160,7 +2153,7 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
- import_memory_count);
module_name_rt = import->module_name;
field_name_rt = import->table_name;
elem_type_rt = VALUE_TYPE_FUNCREF;
elem_type_rt = import->elem_type;
min_size = import->table_init_size;
max_size = import->table_max_size;
}
@ -2563,151 +2556,127 @@ wasm_func_type(const wasm_func_t *func)
return wasm_functype_copy(func->type);
}
static uint32
params_to_argv(WASMModuleInstanceCommon *inst_comm_rt, const wasm_val_t *params,
const wasm_valtype_vec_t *param_defs, size_t param_arity,
uint32 *out)
static bool
params_to_argv(const wasm_val_vec_t *params,
const wasm_valtype_vec_t *param_defs, uint32 *argv,
uint32 *ptr_argc)
{
size_t i = 0;
uint32 argc = 0;
const wasm_val_t *param = NULL;
if (!param_arity) {
return 0;
if (!param_defs->num_elems) {
return true;
}
bh_assert(params && param_defs && out);
bh_assert(param_defs->num_elems == param_arity);
if (!params || !params->num_elems || !params->size || !params->data) {
return false;
}
for (i = 0; out && i < param_arity; ++i) {
param = params + i;
*ptr_argc = 0;
for (i = 0; i < param_defs->num_elems; ++i) {
const wasm_val_t *param = params->data + i;
bh_assert((*(param_defs->data + i))->kind == param->kind);
switch (param->kind) {
case WASM_I32:
*(int32 *)out = param->of.i32;
out += 1;
argc += 1;
*(int32 *)argv = param->of.i32;
argv += 1;
*ptr_argc += 1;
break;
case WASM_I64:
*(int64 *)out = param->of.i64;
out += 2;
argc += 2;
*(int64 *)argv = param->of.i64;
argv += 2;
*ptr_argc += 2;
break;
case WASM_F32:
*(float32 *)out = param->of.f32;
out += 1;
argc += 1;
*(float32 *)argv = param->of.f32;
argv += 1;
*ptr_argc += 1;
break;
case WASM_F64:
*(float64 *)out = param->of.f64;
out += 2;
argc += 2;
*(float64 *)argv = param->of.f64;
argv += 2;
*ptr_argc += 2;
break;
#if WASM_ENABLE_REF_TYPES != 0
case WASM_ANYREF:
if (!wasm_externref_obj2ref(inst_comm_rt, param->of.ref, out)) {
goto failed;
}
out += 1;
argc += 1;
*(uintptr_t *)argv = (uintptr_t)param->of.ref;
argv += sizeof(uintptr_t) / sizeof(uint32);
*ptr_argc += 1;
break;
#endif
default:
LOG_WARNING("unexpected parameter val type %d", param->kind);
goto failed;
return false;
}
}
return argc;
failed:
LOG_DEBUG("%s failed", __FUNCTION__);
return 0;
return true;
}
static uint32
argv_to_results(const uint32 *results, const wasm_valtype_vec_t *result_defs,
size_t result_arity, wasm_val_t *out)
static bool
argv_to_results(const uint32 *argv, const wasm_valtype_vec_t *result_defs,
wasm_val_vec_t *results)
{
size_t i = 0;
uint32 argc = 0;
const uint32 *result = results;
const wasm_valtype_t *def = NULL;
size_t i = 0, argv_i = 0;
wasm_val_t *result;
if (!result_arity) {
return 0;
if (!result_defs->num_elems) {
return true;
}
bh_assert(results && result_defs && out);
bh_assert(result_arity == result_defs->num_elems);
if (!results || !results->num_elems || !results->size || !results->data) {
return false;
}
for (i = 0; out && i < result_arity; i++) {
def = *(result_defs->data + i);
switch (def->kind) {
for (i = 0, result = results->data, argv_i = 0; i < result_defs->num_elems;
i++, result++) {
switch (result_defs->data[i]->kind) {
case WASM_I32:
{
out->kind = WASM_I32;
out->of.i32 = *(int32 *)result;
result += 1;
result->kind = WASM_I32;
result->of.i32 = *(int32 *)(argv + argv_i);
argv_i += 1;
break;
}
case WASM_I64:
{
out->kind = WASM_I64;
out->of.i64 = *(int64 *)result;
result += 2;
result->kind = WASM_I64;
result->of.i64 = *(int64 *)(argv + argv_i);
argv_i += 2;
break;
}
case WASM_F32:
{
out->kind = WASM_F32;
out->of.f32 = *(float32 *)result;
result += 1;
result->kind = WASM_F32;
result->of.f32 = *(float32 *)(argv + argv_i);
argv_i += 1;
break;
}
case WASM_F64:
{
out->kind = WASM_F64;
out->of.f64 = *(float64 *)result;
result += 2;
result->kind = WASM_F64;
result->of.f64 = *(float64 *)(argv + argv_i);
argv_i += 2;
break;
}
#if WASM_ENABLE_REF_TYPES != 0
case WASM_ANYREF:
{
out->kind = WASM_ANYREF;
if (NULL_REF == *(uint32 *)result) {
out->of.ref = NULL;
}
else {
if (!wasm_externref_ref2obj(*(uint32 *)result,
(void **)&out->of.ref)) {
goto failed;
}
}
result += 1;
result->kind = WASM_ANYREF;
result->of.ref =
(struct wasm_ref_t *)(*(uintptr_t *)(argv + argv_i));
argv_i += sizeof(uintptr_t) / sizeof(uint32);
break;
}
#endif
default:
LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__,
def->kind);
goto failed;
result_defs->data[i]->kind);
return false;
}
out++;
argc++;
}
return argc;
failed:
LOG_DEBUG("%s failed", __FUNCTION__);
return 0;
return true;
}
wasm_trap_t *
@ -2718,7 +2687,7 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
/* a int64 or float64 parameter means 2 */
uint32 argc = 0;
/* a parameter list and a return value list */
uint32 argv_buf[32], *argv = argv_buf;
uint32 argv_buf[32] = { 0 }, *argv = argv_buf;
WASMFunctionInstanceCommon *func_comm_rt = NULL;
WASMExecEnv *exec_env = NULL;
size_t param_count, result_count, alloc_count;
@ -2776,10 +2745,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
/* copy parametes */
if (param_count
&& (!params
|| !(argc = params_to_argv(func->inst_comm_rt, params->data,
wasm_functype_params(func->type),
param_count, argv)))) {
&& !params_to_argv(params, wasm_functype_params(func->type), argv,
&argc)) {
goto failed;
}
@ -2798,9 +2765,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
/* copy results */
if (result_count) {
if (!results
|| !(argc = argv_to_results(argv, wasm_functype_results(func->type),
result_count, results->data))) {
if (!argv_to_results(argv, wasm_functype_results(func->type),
results)) {
goto failed;
}
results->num_elems = result_count;
@ -3265,7 +3231,7 @@ wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
if (table_idx_rt < module_aot->import_table_count) {
AOTImportTable *table_aot =
module_aot->import_tables + table_idx_rt;
val_type_rt = VALUE_TYPE_FUNCREF;
val_type_rt = table_aot->elem_type;
init_size = table_aot->table_init_size;
max_size = table_aot->table_max_size;
}
@ -3273,7 +3239,7 @@ wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
AOTTable *table_aot =
module_aot->tables
+ (table_idx_rt - module_aot->import_table_count);
val_type_rt = VALUE_TYPE_FUNCREF;
val_type_rt = table_aot->elem_type;
init_size = table_aot->table_init_size;
max_size = table_aot->table_max_size;
}
@ -3360,13 +3326,12 @@ wasm_table_type(const wasm_table_t *table)
own wasm_ref_t *
wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
{
uint32 func_idx_rt = NULL_REF;
uint32 ref_idx = NULL_REF;
if (!table) {
return NULL;
}
/* index -> func_idx_rt */
#if WASM_ENABLE_INTERP != 0
if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
WASMTableInstance *table_interp =
@ -3375,7 +3340,7 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
if (index >= table_interp->cur_size) {
return NULL;
}
func_idx_rt = ((uint32 *)table_interp->base_addr)[index];
ref_idx = ((uint32 *)table_interp->base_addr)[index];
}
#endif
@ -3387,7 +3352,7 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
if (index >= table_aot->cur_size) {
return NULL;
}
func_idx_rt = table_aot->data[index];
ref_idx = table_aot->data[index];
}
#endif
@ -3395,35 +3360,48 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
* a wrong combination of module filetype and compilation flags
* also leads to below branch
*/
if (func_idx_rt == NULL_REF) {
if (ref_idx == NULL_REF) {
return NULL;
}
return wasm_ref_new_internal(table->store, WASM_REF_func, func_idx_rt,
table->inst_comm_rt);
#if WASM_ENABLE_REF_TYPES != 0
if (table->type->val_type->kind == WASM_ANYREF) {
void *externref_obj;
if (!wasm_externref_ref2obj(ref_idx, &externref_obj)) {
return NULL;
}
return externref_obj;
}
else
#endif
{
return wasm_ref_new_internal(table->store, WASM_REF_func, ref_idx,
table->inst_comm_rt);
}
}
bool
wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
own wasm_ref_t *func_ref)
own wasm_ref_t *ref)
{
uint32 *p_func_idx_rt = NULL;
uint32 function_count = 0, ref_idx_rt = NULL_REF;
uint32 *p_ref_idx = NULL;
uint32 function_count = 0;
if (!table) {
return false;
}
if (func_ref && func_ref->kind != WASM_REF_func) {
if (ref
#if WASM_ENABLE_REF_TYPES != 0
&& !(WASM_REF_foreign == ref->kind
&& WASM_ANYREF == table->type->val_type->kind)
#endif
&& !(WASM_REF_func == ref->kind
&& WASM_FUNCREF == table->type->val_type->kind)) {
return false;
}
if (func_ref) {
ref_idx_rt = func_ref->ref_idx_rt;
wasm_ref_delete(func_ref);
}
/* index -> *p_func_idx_rt */
#if WASM_ENABLE_INTERP != 0
if (table->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
WASMTableInstance *table_interp =
@ -3434,7 +3412,7 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
return false;
}
p_func_idx_rt = ((uint32 *)table_interp->base_addr) + index;
p_ref_idx = ((uint32 *)table_interp->base_addr) + index;
function_count =
((WASMModuleInstance *)table->inst_comm_rt)->function_count;
}
@ -3451,7 +3429,7 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
return false;
}
p_func_idx_rt = table_aot->data + index;
p_ref_idx = table_aot->data + index;
function_count = module_aot->func_count;
}
#endif
@ -3460,17 +3438,31 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
* a wrong combination of module filetype and compilation flags
* leads to below branch
*/
if (!p_func_idx_rt) {
if (!p_ref_idx) {
return false;
}
if (NULL_REF != ref_idx_rt) {
if (ref_idx_rt >= function_count) {
return false;
#if WASM_ENABLE_REF_TYPES != 0
if (table->type->val_type->kind == WASM_ANYREF) {
return wasm_externref_obj2ref(table->inst_comm_rt, ref, p_ref_idx);
}
else
#endif
{
if (ref) {
if (NULL_REF != ref->ref_idx_rt) {
if (ref->ref_idx_rt >= function_count) {
return false;
}
}
*p_ref_idx = ref->ref_idx_rt;
wasm_ref_delete(ref);
}
else {
*p_ref_idx = NULL_REF;
}
}
*p_func_idx_rt = ref_idx_rt;
return true;
}

View File

@ -56,7 +56,6 @@ struct wasm_globaltype_t {
struct wasm_tabletype_t {
uint32 extern_kind;
/* always be WASM_FUNCREF */
wasm_valtype_t *val_type;
wasm_limits_t limits;
};

View File

@ -125,10 +125,6 @@ typedef struct WASMExecEnv {
WASMJmpBuf *jmpbuf_stack_top;
#endif
#if WASM_ENABLE_REF_TYPES != 0
uint16 nested_calling_depth;
#endif
#if WASM_ENABLE_MEMORY_PROFILING != 0
uint32 max_wasm_stack_used;
#endif

View File

@ -53,11 +53,30 @@ get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
uint32
get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis);
static bool
compare_type_with_signautre(uint8 type, const char signature)
{
const char num_sig_map[] = { 'F', 'f', 'I', 'i' };
if (VALUE_TYPE_F64 <= type && type <= VALUE_TYPE_I32
&& signature == num_sig_map[type - VALUE_TYPE_F64]) {
return true;
}
#if WASM_ENABLE_REF_TYPES != 0
if ('r' == signature && type == VALUE_TYPE_EXTERNREF)
return true;
#endif
/* TODO: a v128 parameter */
return false;
}
static bool
check_symbol_signature(const WASMType *type, const char *signature)
{
const char *p = signature, *p_end;
char sig_map[] = { 'F', 'f', 'I', 'i' }, sig;
char sig;
uint32 i = 0;
if (!p || strlen(p) < 2)
@ -74,16 +93,12 @@ check_symbol_signature(const WASMType *type, const char *signature)
for (i = 0; i < type->param_count; i++) {
sig = *p++;
if ((type->types[i] >= VALUE_TYPE_F64
&& type->types[i] <= VALUE_TYPE_I32
&& sig == sig_map[type->types[i] - VALUE_TYPE_F64])
#if WASM_ENABLE_REF_TYPES != 0
|| (sig == 'i' && type->types[i] == VALUE_TYPE_EXTERNREF)
#endif
)
/* normal parameter */
/* a f64/f32/i64/i32/externref parameter */
if (compare_type_with_signautre(type->types[i], sig))
continue;
/* a pointer/string paramter */
if (type->types[i] != VALUE_TYPE_I32)
/* pointer and string must be i32 type */
return false;
@ -112,8 +127,12 @@ check_symbol_signature(const WASMType *type, const char *signature)
if (type->result_count) {
if (p >= p_end)
return false;
if (*p++ != sig_map[type->types[i] - VALUE_TYPE_F64])
/* result types includes: f64,f32,i64,i32,externref */
if (!compare_type_with_signautre(type->types[i], *p))
return false;
p++;
}
if (*p != '\0')

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;

View File

@ -525,11 +525,6 @@ bool
wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices,
uint32 argc, uint32 argv[]);
bool
wasm_runtime_create_exec_env_and_call_wasm(
WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function,
uint32 argc, uint32 argv[]);
bool
wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
@ -813,16 +808,6 @@ wasm_runtime_dump_module_inst_mem_consumption(
void
wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env);
#if WASM_ENABLE_REF_TYPES != 0
void
wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function);
void
wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function,
bool ret, uint32 *argv);
#endif
bool
wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
const WASMExport *export_, WASMType **out);

View File

@ -96,6 +96,7 @@ typedef struct AOTMemInitData {
typedef struct AOTImportTable {
char *module_name;
char *table_name;
uint32 elem_type;
uint32 table_flags;
uint32 table_init_size;
uint32 table_max_size;

View File

@ -1398,6 +1398,7 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
* EMIT_STR(comp_data->import_tables[i].module_name );
* EMIT_STR(comp_data->import_tables[i].table_name);
*/
EMIT_U32(comp_data->import_tables[i].elem_type);
EMIT_U32(comp_data->import_tables[i].table_init_size);
EMIT_U32(comp_data->import_tables[i].table_max_size);
EMIT_U32(comp_data->import_tables[i].possible_grow & 0x000000FF);

View File

@ -155,16 +155,17 @@ enum wasm_valkind_enum {
#ifndef WASM_VAL_T_DEFINED
#define WASM_VAL_T_DEFINED
struct wasm_ref_t;
typedef struct wasm_val_t {
wasm_valkind_t kind;
union {
/* also represent a function index */
int32_t i32;
int64_t i64;
float f32;
double f64;
struct wasm_ref_t *ref;
/* represent a foreign object, aka externref in .wat */
uintptr_t foreign;
} of;
} wasm_val_t;
#endif
@ -790,6 +791,7 @@ wasm_runtime_get_native_addr_range(wasm_module_inst_t module_inst,
* 'I': the parameter is i64 type
* 'f': the parameter is f32 type
* 'F': the parameter is f64 type
* 'r': the parameter is externref type, it should be a uintptr_t in host
* '*': the parameter is a pointer (i32 in WASM), and runtime will
* auto check its boundary before calling the native function.
* If it is followed by '~', the checked length of the pointer

View File

@ -544,6 +544,19 @@ wasm_get_cell_num(const uint8 *types, uint32 type_count)
return cell_num;
}
#if WASM_ENABLE_REF_TYPES != 0
inline static uint16
wasm_value_type_cell_num_outside(uint8 value_type)
{
if (VALUE_TYPE_EXTERNREF == value_type) {
return sizeof(uintptr_t) / sizeof(uint32);
}
else {
return wasm_value_type_cell_num(value_type);
}
}
#endif
inline static bool
wasm_type_equal(const WASMType *type1, const WASMType *type2)
{

View File

@ -1748,16 +1748,8 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
}
#endif
#if WASM_ENABLE_REF_TYPES != 0
wasm_runtime_prepare_call_function(exec_env, func);
#endif
ret = wasm_call_function(exec_env, func, argc, argv);
#if WASM_ENABLE_REF_TYPES != 0
wasm_runtime_finalize_call_function(exec_env, func, ret, argv);
#endif
#if WASM_ENABLE_THREAD_MGR != 0
/* don't destroy the exec_env if it's searched from the cluster */
if (!existing_exec_env)
@ -1770,9 +1762,14 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
bool
wasm_create_exec_env_singleton(WASMModuleInstance *module_inst)
{
WASMExecEnv *exec_env =
wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
module_inst->default_wasm_stack_size);
WASMExecEnv *exec_env = NULL;
if (module_inst->exec_env_singleton) {
return true;
}
exec_env = wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
module_inst->default_wasm_stack_size);
if (exec_env)
module_inst->exec_env_singleton = exec_env;

View File

@ -74,6 +74,9 @@ os_mem_decommit(void *ptr, size_t size);
#define os_thread_local_attribute __declspec(thread)
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#if WASM_DISABLE_HW_BOUND_CHECK == 0
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)