mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-15 16:58:34 +00:00
Implement GC opcode fund.bind
This commit is contained in:
parent
85dfa9b906
commit
e521d9991d
|
@ -289,36 +289,41 @@ wasm_array_obj_get_elem(WASMArrayObjectRef array_obj, uint32 elem_idx,
|
|||
}
|
||||
|
||||
WASMFuncObjectRef
|
||||
wasm_func_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj, uint32 func_idx)
|
||||
wasm_func_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj,
|
||||
uint32 func_idx_bound, uint32 param_count_bound)
|
||||
{
|
||||
WASMFuncObjectRef func_obj;
|
||||
WASMFuncType *func_type;
|
||||
uint64 total_size;
|
||||
|
||||
bh_assert(rtt_obj->type_flag == WASM_TYPE_FUNC);
|
||||
|
||||
func_type = (WASMFuncType *)rtt_obj->defined_type;
|
||||
|
||||
total_size =
|
||||
offsetof(WASMFuncObject, param_data) + func_type->total_param_size;
|
||||
total_size = offsetof(WASMFuncObject, params_bound)
|
||||
+ (uint64)sizeof(WASMValue) * param_count_bound;
|
||||
if (!(func_obj = gc_obj_malloc(heap_handle, total_size))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
func_obj->header = (WASMObjectHeader)rtt_obj;
|
||||
func_obj->func_idx = func_idx;
|
||||
func_obj->func_idx_bound = func_idx_bound;
|
||||
func_obj->param_count_bound = param_count_bound;
|
||||
return func_obj;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_func_obj_set_param(WASMFuncObjectRef func_obj, uint32 param_idx,
|
||||
WASMValue *value)
|
||||
{}
|
||||
wasm_func_obj_set_param_bound(WASMFuncObjectRef func_obj, uint32 param_idx,
|
||||
WASMValue *value)
|
||||
{
|
||||
bh_assert(param_idx < func_obj->param_count_bound);
|
||||
bh_memcpy_s(func_obj->params_bound + param_idx, sizeof(WASMValue), value,
|
||||
sizeof(WASMValue));
|
||||
}
|
||||
|
||||
WASMValue *
|
||||
wasm_func_obj_get_param(const WASMFuncObjectRef func_obj, uint32 param_idx)
|
||||
wasm_func_obj_get_param_bound(const WASMFuncObjectRef func_obj,
|
||||
uint32 param_idx)
|
||||
{
|
||||
return NULL;
|
||||
bh_assert(param_idx < func_obj->param_count_bound);
|
||||
return func_obj->params_bound + param_idx;
|
||||
}
|
||||
|
||||
WASMExternrefObjectRef
|
||||
|
@ -386,14 +391,17 @@ wasm_object_get_ref_list(WASMObjectRef obj, bool *p_is_compact_mode,
|
|||
|
||||
rtt_obj = (WASMRttObjectRef)wasm_object_header(obj);
|
||||
|
||||
if ((obj->header & WASM_OBJ_EXTERNREF_OBJ_FLAG)
|
||||
|| rtt_obj->defined_type->type_flag == WASM_TYPE_FUNC) {
|
||||
if (obj->header & WASM_OBJ_EXTERNREF_OBJ_FLAG) {
|
||||
/* externref object or function object */
|
||||
*p_is_compact_mode = false;
|
||||
*p_ref_num = 0;
|
||||
*p_ref_list = NULL;
|
||||
return true;
|
||||
}
|
||||
else if (rtt_obj->defined_type->type_flag == WASM_TYPE_FUNC) {
|
||||
/* TODO */
|
||||
return false;
|
||||
}
|
||||
else if (rtt_obj->defined_type->type_flag == WASM_TYPE_STRUCT) {
|
||||
/* struct object */
|
||||
WASMStructType *type = (WASMStructType *)rtt_obj->defined_type;
|
||||
|
|
|
@ -93,10 +93,11 @@ typedef struct WASMArrayObject {
|
|||
|
||||
/* Representation of WASM function objects */
|
||||
typedef struct WASMFuncObject {
|
||||
/* must be pointer of WASMRttObject of array type */
|
||||
/* must be pointer of WASMRttObject of func type */
|
||||
WASMObjectHeader header;
|
||||
uint32 func_idx;
|
||||
uint8 *param_data[1];
|
||||
uint32 func_idx_bound;
|
||||
uint32 param_count_bound;
|
||||
WASMValue params_bound[1];
|
||||
} WASMFuncObject, *WASMFuncObjectRef;
|
||||
|
||||
inline static WASMObjectHeader
|
||||
|
@ -223,14 +224,37 @@ wasm_array_obj_elem_addr(const WASMArrayObjectRef array_obj, uint32 elem_idx)
|
|||
}
|
||||
|
||||
WASMFuncObjectRef
|
||||
wasm_func_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj, uint32 func_idx);
|
||||
wasm_func_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj,
|
||||
uint32 func_idx_bound, uint32 param_count_bound);
|
||||
|
||||
void
|
||||
wasm_func_obj_set_param(WASMFuncObjectRef func_obj, uint32 param_idx,
|
||||
WASMValue *value);
|
||||
wasm_func_obj_set_param_bound(WASMFuncObjectRef func_obj, uint32 param_idx,
|
||||
WASMValue *value);
|
||||
|
||||
WASMValue *
|
||||
wasm_func_obj_get_param(const WASMFuncObjectRef func_obj, uint32 param_idx);
|
||||
wasm_func_obj_get_param_bound(const WASMFuncObjectRef func_obj,
|
||||
uint32 param_idx);
|
||||
|
||||
inline static uint32
|
||||
wasm_func_obj_get_func_idx_bound(const WASMFuncObjectRef func_obj)
|
||||
{
|
||||
return func_obj->func_idx_bound;
|
||||
}
|
||||
|
||||
inline static uint32
|
||||
wasm_func_obj_get_param_count_bound(const WASMFuncObjectRef func_obj)
|
||||
{
|
||||
return func_obj->param_count_bound;
|
||||
}
|
||||
|
||||
inline static WASMFuncType *
|
||||
wasm_func_obj_get_func_type(const WASMFuncObjectRef func_obj)
|
||||
{
|
||||
WASMRttObjectRef rtt_obj =
|
||||
(WASMRttObjectRef)wasm_object_header((WASMObjectRef)func_obj);
|
||||
bh_assert(rtt_obj->type_flag == WASM_TYPE_FUNC);
|
||||
return (WASMFuncType *)rtt_obj->defined_type;
|
||||
}
|
||||
|
||||
WASMExternrefObjectRef
|
||||
wasm_externref_obj_new(void *heap_handle, void *foreign_obj);
|
||||
|
|
|
@ -189,6 +189,35 @@ wasm_dump_array_type(const WASMArrayType *type)
|
|||
os_printf("\n");
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_value_types_is_subtype_of(const uint8 *types1,
|
||||
const WASMRefTypeMap *ref_type_maps1,
|
||||
const uint8 *types2,
|
||||
const WASMRefTypeMap *ref_type_maps2,
|
||||
uint32 value_type_count,
|
||||
const WASMTypePtr *types, uint32 type_count)
|
||||
{
|
||||
uint32 i;
|
||||
WASMRefType *ref_type1, *ref_type2;
|
||||
|
||||
for (i = 0; i < value_type_count; i++) {
|
||||
ref_type1 = ref_type2 = NULL;
|
||||
if (wasm_is_type_multi_byte_type(types1[i])) {
|
||||
ref_type1 = ref_type_maps1->ref_type;
|
||||
ref_type_maps1++;
|
||||
}
|
||||
if (wasm_is_type_multi_byte_type(types2[i])) {
|
||||
ref_type2 = ref_type_maps2->ref_type;
|
||||
ref_type_maps2++;
|
||||
}
|
||||
if (!wasm_reftype_is_subtype_of(types1[i], ref_type1, types2[i],
|
||||
ref_type2, types, type_count)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct TypeIdxNode {
|
||||
uint32 type_idx1;
|
||||
uint32 type_idx2;
|
||||
|
|
|
@ -26,6 +26,16 @@ wasm_dump_array_type(const WASMArrayType *type);
|
|||
|
||||
/* Operations of function type */
|
||||
|
||||
/* Whether a group of value types is subtype of
|
||||
another group of value types */
|
||||
bool
|
||||
wasm_value_types_is_subtype_of(const uint8 *types1,
|
||||
const WASMRefTypeMap *ref_type_maps1,
|
||||
const uint8 *types2,
|
||||
const WASMRefTypeMap *ref_type_maps2,
|
||||
uint32 value_type_count,
|
||||
const WASMTypePtr *types, uint32 type_count);
|
||||
|
||||
/* Whether two function types are equal */
|
||||
bool
|
||||
wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2,
|
||||
|
|
|
@ -338,8 +338,6 @@ typedef struct WASMFuncType {
|
|||
uint16 ret_cell_num;
|
||||
|
||||
#if WASM_ENABLE_GC != 0
|
||||
uint16 *param_offsets;
|
||||
uint16 total_param_size;
|
||||
uint16 ref_type_map_count;
|
||||
WASMRefTypeMap *ref_type_maps;
|
||||
WASMRefTypeMap *result_ref_type_maps;
|
||||
|
|
|
@ -1154,6 +1154,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#if WASM_ENABLE_GC != 0
|
||||
register uint8 *frame_ref = NULL; /* cache of frame->ref */
|
||||
uint8 *frame_ref_tmp;
|
||||
bool is_return_call_ref = false;
|
||||
#endif
|
||||
WASMBranchBlock *frame_csp = NULL;
|
||||
BlockAddr *cache_items;
|
||||
|
@ -1518,7 +1519,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
wasm_set_exception(module, "uninitialized element");
|
||||
goto got_exception;
|
||||
}
|
||||
fidx = func_obj->func_idx;
|
||||
fidx = wasm_func_obj_get_func_idx_bound(func_obj);
|
||||
#endif
|
||||
/* clang-format on */
|
||||
|
||||
|
@ -1535,21 +1536,40 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
/* always call module own functions */
|
||||
cur_func = module->functions + fidx;
|
||||
|
||||
/* clang-format off */
|
||||
#if WASM_ENABLE_GC == 0
|
||||
if (cur_func->is_import_func)
|
||||
cur_func_type = cur_func->u.func_import->func_type;
|
||||
else
|
||||
cur_func_type = cur_func->u.func->func_type;
|
||||
#else
|
||||
cur_func_type = wasm_func_obj_get_func_type(func_obj);
|
||||
#endif
|
||||
/* clang-format on */
|
||||
|
||||
if (!wasm_type_equal(
|
||||
(WASMType *)cur_type, (WASMType *)cur_func_type,
|
||||
module->module->types, module->module->type_count)) {
|
||||
wasm_set_exception(module, "indirect call type mismatch");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#if WASM_ENABLE_GC == 0
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
if (opcode == WASM_OP_RETURN_CALL_INDIRECT)
|
||||
goto call_func_from_return_call;
|
||||
#endif
|
||||
goto call_func_from_interp;
|
||||
#else
|
||||
is_return_call_ref = false;
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
if (opcode == WASM_OP_RETURN_CALL_INDIRECT)
|
||||
is_return_call_ref = true;
|
||||
#endif
|
||||
goto call_func_from_call_ref;
|
||||
#endif
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
/* parametric instructions */
|
||||
|
@ -1700,7 +1720,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#else
|
||||
SYNC_ALL_TO_FRAME();
|
||||
if (!(gc_obj = wasm_create_func_obj(module, func_idx, true,
|
||||
NULL, 0))) {
|
||||
NULL, true, NULL, 0))) {
|
||||
goto got_exception;
|
||||
}
|
||||
PUSH_REF(gc_obj);
|
||||
|
@ -1721,8 +1741,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
goto got_exception;
|
||||
}
|
||||
|
||||
cur_func = module->functions + func_obj->func_idx;
|
||||
goto call_func_from_interp;
|
||||
is_return_call_ref = false;
|
||||
goto call_func_from_call_ref;
|
||||
}
|
||||
|
||||
HANDLE_OP(WASM_OP_RETURN_CALL_REF)
|
||||
|
@ -1736,11 +1756,71 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
goto got_exception;
|
||||
}
|
||||
|
||||
cur_func = module->functions + func_obj->func_idx;
|
||||
goto call_func_from_return_call;
|
||||
is_return_call_ref = true;
|
||||
goto call_func_from_call_ref;
|
||||
}
|
||||
|
||||
HANDLE_OP(WASM_OP_FUNC_BIND)
|
||||
{
|
||||
WASMFuncObjectRef func_obj_old;
|
||||
WASMFuncType *func_type_src, *func_type_dst;
|
||||
WASMFunctionInstance *func_inst;
|
||||
WASMValue *value_bound, value;
|
||||
int32 param_count_bound, param_count_to_bind, func_idx_bound;
|
||||
int32 j;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
||||
func_type_dst =
|
||||
(WASMFuncType *)module->module->types[type_index];
|
||||
|
||||
func_obj_old = POP_REF();
|
||||
if (!func_obj_old) {
|
||||
wasm_set_exception(module, "null function object");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
func_idx_bound = wasm_func_obj_get_func_idx_bound(func_obj_old);
|
||||
func_inst = &module->functions[func_idx_bound];
|
||||
func_type_src = func_inst->is_import_func
|
||||
? func_inst->u.func_import->func_type
|
||||
: func_inst->u.func->func_type;
|
||||
|
||||
/* create func object */
|
||||
param_count_to_bind =
|
||||
func_type_src->param_count - func_type_dst->param_count;
|
||||
if (!(func_obj =
|
||||
wasm_create_func_obj(module, func_idx_bound, false,
|
||||
func_type_dst, true, NULL, 0))) {
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
param_count_bound =
|
||||
wasm_func_obj_get_param_count_bound(func_obj_old);
|
||||
for (j = 0; j < (int32)param_count_bound; j++) {
|
||||
value_bound =
|
||||
wasm_func_obj_get_param_bound(func_obj_old, j);
|
||||
wasm_func_obj_set_param_bound(func_obj, j, value_bound);
|
||||
}
|
||||
|
||||
/* pop bound arguments */
|
||||
for (j = param_count_to_bind - 1; j >= param_count_bound; j--) {
|
||||
if (wasm_is_type_multi_byte_type(func_type_src->types[j])) {
|
||||
value.gc_obj = POP_REF();
|
||||
}
|
||||
else if (func_type_src->types[j] == VALUE_TYPE_I32
|
||||
|| func_type_src->types[j] == VALUE_TYPE_F32) {
|
||||
value.i32 = POP_I32();
|
||||
}
|
||||
else {
|
||||
value.i64 = POP_I64();
|
||||
}
|
||||
wasm_func_obj_set_param_bound(func_obj, j, &value);
|
||||
}
|
||||
|
||||
PUSH_REF(func_obj);
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
HANDLE_OP(WASM_OP_LET)
|
||||
{
|
||||
wasm_set_exception(module, "unsupported opcode");
|
||||
|
@ -4018,7 +4098,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (func_indexes[i] != UINT32_MAX) {
|
||||
if (!(func_obj = wasm_create_func_obj(
|
||||
module, func_indexes[i], true, NULL,
|
||||
0))) {
|
||||
true, NULL, 0))) {
|
||||
goto got_exception;
|
||||
}
|
||||
table_elems[i] = func_obj;
|
||||
|
@ -4592,7 +4672,56 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
FETCH_OPCODE_AND_DISPATCH();
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
|
||||
#if WASM_ENABLE_GC != 0
|
||||
call_func_from_call_ref:
|
||||
{
|
||||
WASMInterpFrame *outs_area;
|
||||
WASMFuncType *func_type, *cur_func_type;
|
||||
WASMValue *value;
|
||||
uint32 *outs_area_lp;
|
||||
uint32 param_count_bound, j;
|
||||
|
||||
cur_func =
|
||||
module->functions + wasm_func_obj_get_func_idx_bound(func_obj);
|
||||
cur_func_type = (cur_func->is_import_func)
|
||||
? cur_func->u.func_import->func_type
|
||||
: cur_func->u.func->func_type;
|
||||
|
||||
if (!is_return_call_ref) {
|
||||
outs_area = wasm_exec_env_wasm_stack_top(exec_env);
|
||||
outs_area_lp = outs_area->lp;
|
||||
}
|
||||
else {
|
||||
outs_area_lp = frame->lp;
|
||||
}
|
||||
|
||||
param_count_bound = wasm_func_obj_get_param_count_bound(func_obj);
|
||||
for (j = 0; j < param_count_bound; j++) {
|
||||
value = wasm_func_obj_get_param_bound(func_obj, j);
|
||||
cell_num = wasm_value_type_cell_num(cur_func_type->types[j]);
|
||||
bh_memcpy_s(outs_area_lp, cell_num * 4, value, cell_num * 4);
|
||||
outs_area_lp += cell_num;
|
||||
}
|
||||
|
||||
func_type = wasm_func_obj_get_func_type(func_obj);
|
||||
if (func_type->param_cell_num > 0) {
|
||||
POP(func_type->param_cell_num);
|
||||
word_copy(outs_area_lp, frame_sp, func_type->param_cell_num);
|
||||
}
|
||||
|
||||
if (!is_return_call_ref) {
|
||||
SYNC_ALL_TO_FRAME();
|
||||
prev_frame = frame;
|
||||
}
|
||||
else {
|
||||
FREE_FRAME(exec_env, frame);
|
||||
wasm_exec_env_set_cur_frame(exec_env,
|
||||
(WASMRuntimeFrame *)prev_frame);
|
||||
}
|
||||
goto call_func_from_entry;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
call_func_from_return_call:
|
||||
{
|
||||
POP(cur_func->param_cell_num);
|
||||
|
@ -4608,11 +4737,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
{
|
||||
/* Only do the copy when it's called from interpreter. */
|
||||
WASMInterpFrame *outs_area = wasm_exec_env_wasm_stack_top(exec_env);
|
||||
POP(cur_func->param_cell_num);
|
||||
SYNC_ALL_TO_FRAME();
|
||||
if (cur_func->param_cell_num > 0) {
|
||||
POP(cur_func->param_cell_num);
|
||||
word_copy(outs_area->lp, frame_sp, cur_func->param_cell_num);
|
||||
}
|
||||
SYNC_ALL_TO_FRAME();
|
||||
prev_frame = frame;
|
||||
}
|
||||
|
||||
|
|
|
@ -1188,6 +1188,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#if WASM_ENABLE_GC != 0
|
||||
register uint8 *frame_ref = NULL; /* cache of frame->ref */
|
||||
int16 opnd_off;
|
||||
bool is_return_call_ref = false;
|
||||
#endif
|
||||
uint8 *frame_ip_end = frame_ip + 1;
|
||||
uint32 cond, count, fidx, tidx, frame_size = 0;
|
||||
|
@ -1403,7 +1404,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
wasm_set_exception(module, "uninitialized element");
|
||||
goto got_exception;
|
||||
}
|
||||
fidx = func_obj->func_idx;
|
||||
fidx = wasm_func_obj_get_func_idx_bound(func_obj);
|
||||
#endif
|
||||
/* clang-format on */
|
||||
|
||||
|
@ -1420,21 +1421,40 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
/* always call module own functions */
|
||||
cur_func = module->functions + fidx;
|
||||
|
||||
/* clang-format off */
|
||||
#if WASM_ENABLE_GC == 0
|
||||
if (cur_func->is_import_func)
|
||||
cur_func_type = cur_func->u.func_import->func_type;
|
||||
else
|
||||
cur_func_type = cur_func->u.func->func_type;
|
||||
#else
|
||||
cur_func_type = wasm_func_obj_get_func_type(func_obj);
|
||||
#endif
|
||||
/* clang-format on */
|
||||
|
||||
if (!wasm_type_equal(
|
||||
(WASMType *)cur_type, (WASMType *)cur_func_type,
|
||||
module->module->types, module->module->type_count)) {
|
||||
wasm_set_exception(module, "indirect call type mismatch");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#if WASM_ENABLE_GC == 0
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
if (opcode == WASM_OP_RETURN_CALL_INDIRECT)
|
||||
goto call_func_from_return_call;
|
||||
#endif
|
||||
goto call_func_from_interp;
|
||||
#else
|
||||
is_return_call_ref = false;
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
if (opcode == WASM_OP_RETURN_CALL_INDIRECT)
|
||||
is_return_call_ref = true;
|
||||
#endif
|
||||
goto call_func_from_call_ref;
|
||||
#endif
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
/* parametric instructions */
|
||||
|
@ -1582,7 +1602,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
PUSH_I32(func_idx);
|
||||
#else
|
||||
if (!(gc_obj = wasm_create_func_obj(module, func_idx, true,
|
||||
NULL, 0))) {
|
||||
NULL, true, NULL, 0))) {
|
||||
goto got_exception;
|
||||
}
|
||||
PUSH_REF(gc_obj);
|
||||
|
@ -1603,8 +1623,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
goto got_exception;
|
||||
}
|
||||
|
||||
cur_func = module->functions + func_obj->func_idx;
|
||||
goto call_func_from_interp;
|
||||
is_return_call_ref = false;
|
||||
goto call_func_from_call_ref;
|
||||
}
|
||||
|
||||
HANDLE_OP(WASM_OP_RETURN_CALL_REF)
|
||||
|
@ -1618,11 +1638,70 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
goto got_exception;
|
||||
}
|
||||
|
||||
cur_func = module->functions + func_obj->func_idx;
|
||||
goto call_func_from_return_call;
|
||||
is_return_call_ref = true;
|
||||
goto call_func_from_call_ref;
|
||||
}
|
||||
|
||||
HANDLE_OP(WASM_OP_FUNC_BIND)
|
||||
{
|
||||
WASMFuncObjectRef func_obj_old;
|
||||
WASMFuncType *func_type_src, *func_type_dst;
|
||||
WASMFunctionInstance *func_inst;
|
||||
WASMValue *value_bound, value;
|
||||
int32 param_count_bound, param_count_to_bind, func_idx_bound;
|
||||
int32 j;
|
||||
|
||||
type_idx = read_uint32(frame_ip);
|
||||
func_type_dst = (WASMFuncType *)module->module->types[type_idx];
|
||||
|
||||
func_obj_old = POP_REF();
|
||||
if (!func_obj_old) {
|
||||
wasm_set_exception(module, "null function object");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
func_idx_bound = wasm_func_obj_get_func_idx_bound(func_obj_old);
|
||||
func_inst = &module->functions[func_idx_bound];
|
||||
func_type_src = func_inst->is_import_func
|
||||
? func_inst->u.func_import->func_type
|
||||
: func_inst->u.func->func_type;
|
||||
|
||||
/* create func object */
|
||||
param_count_to_bind =
|
||||
func_type_src->param_count - func_type_dst->param_count;
|
||||
if (!(func_obj =
|
||||
wasm_create_func_obj(module, func_idx_bound, false,
|
||||
func_type_dst, true, NULL, 0))) {
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
param_count_bound =
|
||||
wasm_func_obj_get_param_count_bound(func_obj_old);
|
||||
for (j = 0; j < (int32)param_count_bound; j++) {
|
||||
value_bound =
|
||||
wasm_func_obj_get_param_bound(func_obj_old, j);
|
||||
wasm_func_obj_set_param_bound(func_obj, j, value_bound);
|
||||
}
|
||||
|
||||
/* pop bound arguments */
|
||||
for (j = param_count_to_bind - 1; j >= param_count_bound; j--) {
|
||||
if (wasm_is_type_multi_byte_type(func_type_src->types[j])) {
|
||||
value.gc_obj = POP_REF();
|
||||
}
|
||||
else if (func_type_src->types[j] == VALUE_TYPE_I32
|
||||
|| func_type_src->types[j] == VALUE_TYPE_F32) {
|
||||
value.i32 = POP_I32();
|
||||
}
|
||||
else {
|
||||
value.i64 = POP_I64();
|
||||
}
|
||||
wasm_func_obj_set_param_bound(func_obj, j, &value);
|
||||
}
|
||||
|
||||
PUSH_REF(func_obj);
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
HANDLE_OP(WASM_OP_LET)
|
||||
{
|
||||
wasm_set_exception(module, "unsupported opcode");
|
||||
|
@ -2352,7 +2431,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
*(int32 *)global_addr = frame_lp[addr1];
|
||||
else
|
||||
PUT_REF_TO_ADDR((uint32 *)global_addr,
|
||||
GET_REF_FROM_ADDR(frame_lp + addr_ret));
|
||||
GET_REF_FROM_ADDR(frame_lp + addr1));
|
||||
#endif
|
||||
/* clang-format on */
|
||||
HANDLE_OP_END();
|
||||
|
@ -3906,7 +3985,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (func_indexes[i] != UINT32_MAX) {
|
||||
if (!(func_obj = wasm_create_func_obj(
|
||||
module, func_indexes[i], true, NULL,
|
||||
0))) {
|
||||
true, NULL, 0))) {
|
||||
goto got_exception;
|
||||
}
|
||||
table_elems[i] = func_obj;
|
||||
|
@ -4503,7 +4582,95 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
FETCH_OPCODE_AND_DISPATCH();
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
|
||||
#if WASM_ENABLE_GC != 0
|
||||
call_func_from_call_ref:
|
||||
{
|
||||
WASMInterpFrame *outs_area;
|
||||
WASMValue *value;
|
||||
uint32 *lp_base = NULL, *lp = NULL;
|
||||
uint32 *outs_area_lp;
|
||||
uint32 param_count_bound, i;
|
||||
|
||||
cur_func =
|
||||
module->functions + wasm_func_obj_get_func_idx_bound(func_obj);
|
||||
|
||||
/* Allocate temporary memory for local variables */
|
||||
if (cur_func->param_cell_num > 0
|
||||
&& !(lp_base = lp = wasm_runtime_malloc(
|
||||
cur_func->param_cell_num * (uint32)sizeof(uint32)))) {
|
||||
wasm_set_exception(module, "allocate memory failed");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
/* Copy bound parameters from function object */
|
||||
param_count_bound = wasm_func_obj_get_param_count_bound(func_obj);
|
||||
for (i = 0; i < param_count_bound; i++) {
|
||||
value = wasm_func_obj_get_param_bound(func_obj, i);
|
||||
if (cur_func->param_types[i] == VALUE_TYPE_I64
|
||||
|| cur_func->param_types[i] == VALUE_TYPE_F64) {
|
||||
PUT_I64_TO_ADDR(lp, value->i64);
|
||||
lp += 2;
|
||||
}
|
||||
else {
|
||||
*lp++ = value->i32;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy left parameters from stack */
|
||||
for (; i < cur_func->param_count; i++) {
|
||||
if (cur_func->param_types[i] == VALUE_TYPE_I64
|
||||
|| cur_func->param_types[i] == VALUE_TYPE_F64) {
|
||||
PUT_I64_TO_ADDR(
|
||||
lp, GET_OPERAND(uint64, I64,
|
||||
2 * (cur_func->param_count - i - 1)));
|
||||
lp += 2;
|
||||
}
|
||||
else {
|
||||
*lp++ = GET_OPERAND(uint32, I32,
|
||||
(2 * (cur_func->param_count - i - 1)));
|
||||
}
|
||||
}
|
||||
frame_ip += (cur_func->param_count - param_count_bound) * 2;
|
||||
|
||||
if (!is_return_call_ref)
|
||||
outs_area = wasm_exec_env_wasm_stack_top(exec_env);
|
||||
else
|
||||
outs_area = frame;
|
||||
outs_area_lp = outs_area->operand + cur_func->const_cell_num;
|
||||
|
||||
/* Copy local variables from temporary memory */
|
||||
if (lp - lp_base > 0)
|
||||
word_copy(outs_area_lp, lp_base, lp - lp_base);
|
||||
|
||||
if (lp_base)
|
||||
wasm_runtime_free(lp_base);
|
||||
|
||||
if (!is_return_call_ref) {
|
||||
if (cur_func->ret_cell_num != 0) {
|
||||
/* Get the first return value's offset. Since loader emit
|
||||
* all return values' offset so we must skip remain return
|
||||
* values' offsets.
|
||||
*/
|
||||
WASMFuncType *func_type;
|
||||
if (cur_func->is_import_func)
|
||||
func_type = cur_func->u.func_import->func_type;
|
||||
else
|
||||
func_type = cur_func->u.func->func_type;
|
||||
frame->ret_offset = GET_OFFSET();
|
||||
frame_ip += 2 * (func_type->result_count - 1);
|
||||
}
|
||||
SYNC_ALL_TO_FRAME();
|
||||
prev_frame = frame;
|
||||
}
|
||||
else {
|
||||
FREE_FRAME(exec_env, frame);
|
||||
wasm_exec_env_set_cur_frame(exec_env,
|
||||
(WASMRuntimeFrame *)prev_frame);
|
||||
}
|
||||
goto call_func_from_entry;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
call_func_from_return_call:
|
||||
{
|
||||
uint32 *lp_base = NULL, *lp = NULL;
|
||||
|
|
|
@ -1053,8 +1053,7 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|||
uint32 param_count, result_count, i, j = 0;
|
||||
uint32 param_cell_num, ret_cell_num;
|
||||
uint32 ref_type_map_count = 0, result_ref_type_map_count = 0;
|
||||
uint64 total_size, param_offset;
|
||||
uint16 offset;
|
||||
uint64 total_size;
|
||||
bool need_ref_type_map;
|
||||
WASMRefType ref_type;
|
||||
WASMFuncType *type = NULL;
|
||||
|
@ -1094,8 +1093,6 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|||
|
||||
total_size = offsetof(WASMFuncType, types)
|
||||
+ sizeof(uint8) * (uint64)(param_count + result_count);
|
||||
total_size = param_offset = align_uint(total_size, 4);
|
||||
total_size += sizeof(uint16) * param_count;
|
||||
if (!(type = loader_malloc(total_size, error_buf, error_buf_size))) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1111,13 +1108,11 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|||
type->type_idx = type_idx;
|
||||
type->param_count = param_count;
|
||||
type->result_count = result_count;
|
||||
type->param_offsets = (uint16 *)((uint8 *)type + (uint32)param_offset);
|
||||
type->ref_type_map_count = ref_type_map_count;
|
||||
type->result_ref_type_maps =
|
||||
type->ref_type_maps + ref_type_map_count - result_ref_type_map_count;
|
||||
type->ref_count = 1;
|
||||
|
||||
offset = offsetof(WASMFuncObject, param_data);
|
||||
for (i = 0; i < param_count; i++) {
|
||||
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
||||
&ref_type, false, error_buf, error_buf_size)) {
|
||||
|
@ -1132,10 +1127,7 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
|||
goto fail;
|
||||
}
|
||||
}
|
||||
type->param_offsets[i] = offset;
|
||||
offset += wasm_value_type_size(ref_type.ref_type);
|
||||
}
|
||||
type->total_param_size = offset;
|
||||
|
||||
read_leb_uint32(p, p_end, result_count);
|
||||
for (i = 0; i < result_count; i++) {
|
||||
|
@ -5271,7 +5263,11 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
|
|||
case WASM_OP_BR_ON_NULL:
|
||||
case WASM_OP_BR_ON_NON_NULL:
|
||||
break;
|
||||
|
||||
case WASM_OP_FUNC_BIND:
|
||||
skip_leb_uint32(p, p_end); /* type index */
|
||||
break;
|
||||
|
||||
case WASM_OP_LET:
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
"unsupported opcode %02x", opcode);
|
||||
|
@ -6076,16 +6072,19 @@ check_stack_push(WASMLoaderContext *ctx, uint8 type, char *error_buf,
|
|||
&& ctx->frame_reftype_map >= ctx->frame_reftype_map_boundary) {
|
||||
/* Increase the frame reftype map stack */
|
||||
bh_assert(
|
||||
(uint32)(ctx->frame_reftype_map - ctx->frame_reftype_map_bottom)
|
||||
(uint32)((ctx->frame_reftype_map - ctx->frame_reftype_map_bottom)
|
||||
* sizeof(WASMRefTypeMap))
|
||||
== ctx->frame_reftype_map_size);
|
||||
MEM_REALLOC(ctx->frame_reftype_map_bottom, ctx->frame_reftype_map_size,
|
||||
ctx->frame_reftype_map_size
|
||||
+ (uint32)sizeof(WASMRefTypeMap) * 8);
|
||||
ctx->frame_reftype_map =
|
||||
ctx->frame_reftype_map_bottom + ctx->frame_reftype_map_size;
|
||||
ctx->frame_reftype_map_bottom
|
||||
+ ctx->frame_reftype_map_size / ((uint32)sizeof(WASMRefTypeMap));
|
||||
ctx->frame_reftype_map_size += (uint32)sizeof(WASMRefTypeMap) * 8;
|
||||
ctx->frame_reftype_map_boundary =
|
||||
ctx->frame_reftype_map_bottom + ctx->frame_reftype_map_size;
|
||||
ctx->frame_reftype_map_bottom
|
||||
+ ctx->frame_reftype_map_size / ((uint32)sizeof(WASMRefTypeMap));
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
|
@ -6113,18 +6112,22 @@ wasm_loader_push_frame_ref(WASMLoaderContext *ctx, uint8 type, char *error_buf,
|
|||
|
||||
if (ctx->frame_reftype_map >= ctx->frame_reftype_map_boundary) {
|
||||
/* Increase the frame reftype map stack */
|
||||
bh_assert(
|
||||
(uint32)(ctx->frame_reftype_map - ctx->frame_reftype_map_bottom)
|
||||
== ctx->frame_reftype_map_size);
|
||||
bh_assert((uint32)((ctx->frame_reftype_map
|
||||
- ctx->frame_reftype_map_bottom)
|
||||
* sizeof(WASMRefTypeMap))
|
||||
== ctx->frame_reftype_map_size);
|
||||
MEM_REALLOC(ctx->frame_reftype_map_bottom,
|
||||
ctx->frame_reftype_map_size,
|
||||
ctx->frame_reftype_map_size
|
||||
+ (uint32)sizeof(WASMRefTypeMap) * 8);
|
||||
ctx->frame_reftype_map =
|
||||
ctx->frame_reftype_map_bottom + ctx->frame_reftype_map_size;
|
||||
ctx->frame_reftype_map = ctx->frame_reftype_map_bottom
|
||||
+ ctx->frame_reftype_map_size
|
||||
/ ((uint32)sizeof(WASMRefTypeMap));
|
||||
ctx->frame_reftype_map_size += (uint32)sizeof(WASMRefTypeMap) * 8;
|
||||
ctx->frame_reftype_map_boundary =
|
||||
ctx->frame_reftype_map_bottom + ctx->frame_reftype_map_size;
|
||||
ctx->frame_reftype_map_bottom
|
||||
+ ctx->frame_reftype_map_size
|
||||
/ ((uint32)sizeof(WASMRefTypeMap));
|
||||
}
|
||||
|
||||
ctx->frame_reftype_map->index = ctx->stack_cell_num;
|
||||
|
@ -10000,6 +10003,111 @@ re_scan:
|
|||
break;
|
||||
|
||||
case WASM_OP_FUNC_BIND:
|
||||
{
|
||||
WASMFuncType *func_type_src, *func_type_dst;
|
||||
WASMRefTypeMap *ref_type_map_src;
|
||||
WASMRefType *ref_type_src;
|
||||
uint32 type_idx_src, type_idx_dst, pop_count;
|
||||
int32 j, idx;
|
||||
uint8 type_src;
|
||||
|
||||
/* Get the dest function type */
|
||||
read_leb_uint32(p, p_end, type_idx_dst);
|
||||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
emit_uint32(loader_ctx, type_idx_dst);
|
||||
#endif
|
||||
if (!check_type_index(module, type_idx_dst, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
if (module->types[type_idx_dst]->type_flag != WASM_TYPE_FUNC) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"unkown function type");
|
||||
goto fail;
|
||||
}
|
||||
func_type_dst = (WASMFuncType *)module->types[type_idx_dst];
|
||||
|
||||
/* Get the src function type */
|
||||
if (!wasm_loader_pop_nullable_typeidx(loader_ctx, &type_src,
|
||||
&type_idx_src, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
if (!check_type_index(module, type_idx_src, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
if (module->types[type_idx_src]->type_flag != WASM_TYPE_FUNC) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"unkown function type");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
func_type_src = (WASMFuncType *)module->types[type_idx_src];
|
||||
|
||||
/* Check function types */
|
||||
if (func_type_src->param_count < func_type_dst->param_count
|
||||
|| func_type_src->result_count
|
||||
!= func_type_dst->result_count) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"function type mismatch");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Calculate the begin ref_type_map of the non-pop arguments */
|
||||
ref_type_map_src = func_type_src->ref_type_maps;
|
||||
pop_count =
|
||||
func_type_src->param_count - func_type_dst->param_count;
|
||||
for (i = 0; i < pop_count; i++) {
|
||||
if (wasm_is_type_multi_byte_type(func_type_src->types[i])) {
|
||||
ref_type_map_src++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the subtype relationship of parameter types
|
||||
(contravariance) and the subtype relationship of
|
||||
result types (covariance) */
|
||||
if (!wasm_value_types_is_subtype_of(
|
||||
func_type_dst->types, func_type_dst->ref_type_maps,
|
||||
func_type_src->types + pop_count, ref_type_map_src,
|
||||
func_type_dst->param_count, module->types,
|
||||
module->type_count)
|
||||
|| !wasm_value_types_is_subtype_of(
|
||||
func_type_src->types + func_type_src->param_count,
|
||||
func_type_src->result_ref_type_maps,
|
||||
func_type_dst->types + func_type_dst->param_count,
|
||||
func_type_dst->result_ref_type_maps,
|
||||
func_type_dst->result_count, module->types,
|
||||
module->type_count)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"function type mismatch");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Pop arguments */
|
||||
j = ref_type_map_src - func_type_src->ref_type_maps - 1;
|
||||
for (idx = (int32)(pop_count - 1); idx >= 0; idx--) {
|
||||
if (wasm_is_type_multi_byte_type(
|
||||
func_type_src->types[idx])) {
|
||||
ref_type_src = func_type_src->ref_type_maps[j].ref_type;
|
||||
bh_memcpy_s(&wasm_ref_type, sizeof(WASMRefType),
|
||||
ref_type_src,
|
||||
wasm_reftype_struct_size(ref_type_src));
|
||||
j--;
|
||||
}
|
||||
POP_TYPE(func_type_src->types[idx]);
|
||||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
POP_OFFSET_TYPE(func_type_src->types[idx]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* PUSH (ref type_idx_dst) */
|
||||
wasm_set_refheaptype_typeidx(&wasm_ref_type.ref_ht_typeidx,
|
||||
false, type_idx_dst);
|
||||
PUSH_REF(wasm_ref_type.ref_type);
|
||||
break;
|
||||
}
|
||||
|
||||
case WASM_OP_LET:
|
||||
/* TODO */
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
|
|
|
@ -1166,12 +1166,15 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
|
|||
#if WASM_ENABLE_GC != 0
|
||||
void *
|
||||
wasm_create_func_obj(WASMModuleInstance *module_inst, uint32 func_idx,
|
||||
bool throw_exce, char *error_buf, uint32 error_buf_size)
|
||||
bool use_same_func_type,
|
||||
const WASMFuncType *func_type_to_bind, bool throw_exce,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
WASMRttObjectRef rtt_obj;
|
||||
WASMFuncObjectRef func_obj;
|
||||
WASMFunctionInstance *func_inst;
|
||||
WASMType *func_type;
|
||||
WASMFuncType *func_type;
|
||||
uint32 param_count_bound = 0;
|
||||
|
||||
if (throw_exce) {
|
||||
error_buf = module_inst->cur_exception;
|
||||
|
@ -1185,18 +1188,27 @@ wasm_create_func_obj(WASMModuleInstance *module_inst, uint32 func_idx,
|
|||
}
|
||||
|
||||
func_inst = &module_inst->functions[func_idx];
|
||||
func_type = (WASMType *)(func_inst->is_import_func
|
||||
? func_inst->u.func_import->func_type
|
||||
: func_inst->u.func->func_type);
|
||||
func_type = func_inst->is_import_func ? func_inst->u.func_import->func_type
|
||||
: func_inst->u.func->func_type;
|
||||
|
||||
if (use_same_func_type) {
|
||||
func_type_to_bind = func_type;
|
||||
}
|
||||
else {
|
||||
bh_assert(func_type->param_count >= func_type_to_bind->param_count);
|
||||
param_count_bound =
|
||||
func_type->param_count - func_type_to_bind->param_count;
|
||||
}
|
||||
|
||||
if (!(rtt_obj = wasm_rtt_obj_new(module_inst->module->rtt_obj_set, NULL,
|
||||
func_type, func_type->type_idx))) {
|
||||
(WASMType *)func_type_to_bind,
|
||||
func_type->type_idx))) {
|
||||
set_error_buf(error_buf, error_buf_size, "create rtt object failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(func_obj = wasm_func_obj_new(module_inst->gc_heap_handle, rtt_obj,
|
||||
func_idx))) {
|
||||
func_idx, param_count_bound))) {
|
||||
set_error_buf(error_buf, error_buf_size, "create func object failed");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1472,7 +1484,8 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
|
|||
if ((uint32)global->initial_value.i32 != UINT32_MAX) {
|
||||
if (!(func_obj = wasm_create_func_obj(
|
||||
module_inst, global->initial_value.i32,
|
||||
false, error_buf, error_buf_size)))
|
||||
true, NULL, false, error_buf,
|
||||
error_buf_size)))
|
||||
goto fail;
|
||||
}
|
||||
STORE_PTR((void **)global_data, func_obj);
|
||||
|
@ -1711,9 +1724,9 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
|
|||
uint32 func_idx = table_seg->func_indexes[j];
|
||||
/* UINT32_MAX indicates that it is an null reference */
|
||||
if (func_idx != UINT32_MAX) {
|
||||
if (!(func_obj =
|
||||
wasm_create_func_obj(module_inst, func_idx, false,
|
||||
error_buf, error_buf_size))) {
|
||||
if (!(func_obj = wasm_create_func_obj(
|
||||
module_inst, func_idx, true, NULL, false, error_buf,
|
||||
error_buf_size))) {
|
||||
goto fail;
|
||||
}
|
||||
*((void **)table_data + table_seg->base_offset.u.i32 + j) =
|
||||
|
@ -2533,7 +2546,8 @@ wasm_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 tbl_elem_idx,
|
|||
#if WASM_ENABLE_GC == 0
|
||||
func_idx = tbl_elem_val;
|
||||
#else
|
||||
func_idx = ((WASMFuncObjectRef)tbl_elem_val)->func_idx;
|
||||
func_idx =
|
||||
wasm_func_obj_get_func_idx_bound((WASMFuncObjectRef)tbl_elem_val);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -433,7 +433,9 @@ wasm_enlarge_table(WASMModuleInstance *module_inst, uint32 table_idx,
|
|||
#if WASM_ENABLE_GC != 0
|
||||
void *
|
||||
wasm_create_func_obj(WASMModuleInstance *module_inst, uint32 func_idx,
|
||||
bool throw_exce, char *error_buf, uint32 error_buf_size);
|
||||
bool use_same_func_type,
|
||||
const WASMFuncType *func_type_to_bind, bool throw_exce,
|
||||
char *error_buf, uint32 error_buf_size);
|
||||
|
||||
bool
|
||||
wasm_traverse_gc_rootset(WASMExecEnv *exec_env, void *heap);
|
||||
|
|
Loading…
Reference in New Issue
Block a user