diff --git a/core/iwasm/common/gc/gc_object.c b/core/iwasm/common/gc/gc_object.c index cf16852d9..0a235c29e 100644 --- a/core/iwasm/common/gc/gc_object.c +++ b/core/iwasm/common/gc/gc_object.c @@ -290,15 +290,24 @@ 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_bound, uint32 param_count_bound) + const WASMFuncType *func_type_bound, uint32 func_idx_bound, + uint32 param_count_bound) { WASMFuncObjectRef func_obj; uint64 total_size; + uint32 ref_param_count = 0, offset = 0, i; + uint16 *reference_table; bh_assert(rtt_obj->type_flag == WASM_TYPE_FUNC); + for (i = 0; i < param_count_bound; i++) { + if (wasm_is_type_reftype(func_type_bound->types[i])) + ref_param_count++; + } + total_size = offsetof(WASMFuncObject, params_bound) - + (uint64)sizeof(WASMValue) * param_count_bound; + + (uint64)sizeof(WASMValue) * param_count_bound + + (uint64)sizeof(uint16) * (ref_param_count + 1); if (!(func_obj = gc_obj_malloc(heap_handle, total_size))) { return NULL; } @@ -306,6 +315,18 @@ wasm_func_obj_new(void *heap_handle, WASMRttObjectRef rtt_obj, func_obj->header = (WASMObjectHeader)rtt_obj; func_obj->func_idx_bound = func_idx_bound; func_obj->param_count_bound = param_count_bound; + func_obj->reference_table = reference_table = + (uint16 *)((uint8 *)func_obj + offsetof(WASMFuncObject, params_bound) + + sizeof(WASMValue) * param_count_bound); + + *reference_table++ = (uint16)ref_param_count; + offset = (uint16)offsetof(WASMFuncObject, params_bound); + for (i = 0; i < param_count_bound; i++) { + if (wasm_is_type_reftype(func_type_bound->types[i])) { + *reference_table++ = (uint16)offset; + offset += (uint16)sizeof(WASMValue); + } + } return func_obj; } @@ -399,8 +420,12 @@ wasm_object_get_ref_list(WASMObjectRef obj, bool *p_is_compact_mode, return true; } else if (rtt_obj->defined_type->type_flag == WASM_TYPE_FUNC) { - /* TODO */ - return false; + /* function object */ + WASMFuncObjectRef func_obj = (WASMFuncObjectRef)obj; + *p_is_compact_mode = false; + *p_ref_num = *func_obj->reference_table; + *p_ref_list = func_obj->reference_table + 1; + return true; } else if (rtt_obj->defined_type->type_flag == WASM_TYPE_STRUCT) { /* struct object */ diff --git a/core/iwasm/common/gc/gc_object.h b/core/iwasm/common/gc/gc_object.h index c0e767c23..14c7b4064 100644 --- a/core/iwasm/common/gc/gc_object.h +++ b/core/iwasm/common/gc/gc_object.h @@ -97,6 +97,10 @@ typedef struct WASMFuncObject { WASMObjectHeader header; uint32 func_idx_bound; uint32 param_count_bound; + /* Offsets of reference params that need to be traced + during GC. The first element of the table is the + number of such offsets. */ + uint16 *reference_table; WASMValue params_bound[1]; } WASMFuncObject, *WASMFuncObjectRef; @@ -225,7 +229,8 @@ 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_bound, uint32 param_count_bound); + const WASMFuncType *func_type_bound, uint32 func_idx_bound, + uint32 param_count_bound); void wasm_func_obj_set_param_bound(WASMFuncObjectRef func_obj, uint32 param_idx, diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index b4ca66916..5798f8595 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -1773,7 +1773,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, func_type_dst = (WASMFuncType *)module->module->types[type_index]; - func_obj_old = POP_REF(); + SYNC_ALL_TO_FRAME(); + + /* Don't POP_REF() here to let the object be tracable + during GC when creating func object below */ + func_obj_old = GET_REF_FROM_ADDR(frame_sp - REF_CELL_NUM); if (!func_obj_old) { wasm_set_exception(module, "null function object"); goto got_exception; @@ -1794,6 +1798,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto got_exception; } + /* Pop object after the func object is created */ + (void)POP_REF(); + param_count_bound = wasm_func_obj_get_param_count_bound(func_obj_old); for (j = 0; j < (int32)param_count_bound; j++) { diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index ff7a8856f..57c8319fe 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -393,14 +393,24 @@ init_frame_refs(uint8 *frame_ref, uint32 cell_num, WASMFunctionInstance *func) (opnd_off = GET_OFFSET(), CLEAR_FRAME_REF(opnd_off), \ GET_REF_FROM_ADDR(frame_lp + opnd_off)) +#if WASM_ENABLE_GC != 0 +#define SYNC_FRAME_REF() frame->frame_ref = frame_ref +#define UPDATE_FRAME_REF() frame_ref = frame->frame_ref +#else +#define SYNC_FRAME_REF() (void)0 +#define UPDATE_FRAME_REF() (void)0 +#endif + #define SYNC_ALL_TO_FRAME() \ do { \ frame->ip = frame_ip; \ + SYNC_FRAME_REF(); \ } while (0) #define UPDATE_ALL_FROM_FRAME() \ do { \ frame_ip = frame->ip; \ + UPDATE_FRAME_REF(); \ } while (0) #if WASM_ENABLE_LABELS_AS_VALUES != 0 @@ -1103,12 +1113,12 @@ wasm_interp_dump_op_count() for (i = 0; i < WASM_OP_IMPDEP; i++) total_count += opcode_table[i].count; - printf("total opcode count: %ld\n", total_count); + os_printf("total opcode count: %ld\n", total_count); for (i = 0; i < WASM_OP_IMPDEP; i++) if (opcode_table[i].count > 0) - printf("\t\t%s count:\t\t%ld,\t\t%.2f%%\n", opcode_table[i].name, - opcode_table[i].count, - opcode_table[i].count * 100.0f / total_count); + os_printf("\t\t%s count:\t\t%ld,\t\t%.2f%%\n", opcode_table[i].name, + opcode_table[i].count, + opcode_table[i].count * 100.0f / total_count); } #endif @@ -1601,6 +1611,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if WASM_ENABLE_GC == 0 PUSH_I32(func_idx); #else + SYNC_ALL_TO_FRAME(); if (!(gc_obj = wasm_create_func_obj(module, func_idx, true, NULL, true, NULL, 0))) { goto got_exception; @@ -1654,7 +1665,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, type_idx = read_uint32(frame_ip); func_type_dst = (WASMFuncType *)module->module->types[type_idx]; - func_obj_old = POP_REF(); + SYNC_ALL_TO_FRAME(); + + opnd_off = GET_OFFSET(); + func_obj_old = GET_REF_FROM_ADDR(frame_lp + opnd_off); + if (!func_obj_old) { wasm_set_exception(module, "null function object"); goto got_exception; @@ -1779,6 +1794,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, struct_type = (WASMStructType *)module->module->types[type_idx]; + SYNC_ALL_TO_FRAME(); + rtt_obj = POP_REF(); struct_obj = wasm_struct_obj_new(module->gc_heap_handle, rtt_obj); @@ -1936,6 +1953,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, } } + SYNC_ALL_TO_FRAME(); + array_obj = wasm_array_obj_new(module->gc_heap_handle, rtt_obj, array_len, &array_elem); @@ -3975,6 +3994,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, + s, (uint32)(n * sizeof(uint32))); #else + SYNC_ALL_TO_FRAME(); + table_elems = (table_elem_type_t *)tbl_inst->base_addr + d; func_indexes = module->module->table_segments[elem_idx] diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 9ba8eff38..a34c1469b 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1207,8 +1207,9 @@ wasm_create_func_obj(WASMModuleInstance *module_inst, uint32 func_idx, return NULL; } - if (!(func_obj = wasm_func_obj_new(module_inst->gc_heap_handle, rtt_obj, - func_idx, param_count_bound))) { + if (!(func_obj = + wasm_func_obj_new(module_inst->gc_heap_handle, rtt_obj, func_type, + func_idx, param_count_bound))) { set_error_buf(error_buf, error_buf_size, "create func object failed"); return NULL; }