mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-15 16:58:34 +00:00
Merge pull request #908 from bytecodealliance/main
Merge bytecodealliance:main into wenyongh:update_release_notes
This commit is contained in:
commit
b4ae0cfb8a
|
@ -134,7 +134,9 @@ endif ()
|
||||||
|
|
||||||
# Sanitizers
|
# Sanitizers
|
||||||
|
|
||||||
set(WAMR_BUILD_SANITIZER $ENV{WAMR_BUILD_SANITIZER})
|
if (NOT DEFINED WAMR_BUILD_SANITIZER)
|
||||||
|
set(WAMR_BUILD_SANITIZER $ENV{WAMR_BUILD_SANITIZER})
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (NOT DEFINED WAMR_BUILD_SANITIZER)
|
if (NOT DEFINED WAMR_BUILD_SANITIZER)
|
||||||
set(WAMR_BUILD_SANITIZER "")
|
set(WAMR_BUILD_SANITIZER "")
|
||||||
|
@ -554,3 +556,9 @@ else ()
|
||||||
# Disable aot intrinsics for interp, fast-jit and llvm-jit
|
# Disable aot intrinsics for interp, fast-jit and llvm-jit
|
||||||
add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=0)
|
add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=0)
|
||||||
endif ()
|
endif ()
|
||||||
|
if (WAMR_BUILD_ALLOC_WITH_USAGE EQUAL 1)
|
||||||
|
add_definitions(-DWASM_MEM_ALLOC_WITH_USAGE=1)
|
||||||
|
endif()
|
||||||
|
if (NOT WAMR_BUILD_SANITIZER STREQUAL "")
|
||||||
|
message (" Sanitizer ${WAMR_BUILD_SANITIZER} enabled")
|
||||||
|
endif ()
|
||||||
|
|
|
@ -445,7 +445,29 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Reserved bytes to the native thread stack boundary, throw native
|
/* Reserved bytes to the native thread stack boundary, throw native
|
||||||
stack overflow exception if the guard boudary is reached */
|
* stack overflow exception if the guard boudary is reached
|
||||||
|
*
|
||||||
|
* WASM_STACK_GUARD_SIZE needs to be large enough for:
|
||||||
|
*
|
||||||
|
* - native functions
|
||||||
|
* w/o hw bound check, the overhead (aot_call_function etc) + the native
|
||||||
|
* function itself. as of writing this, the former is about 1000 bytes
|
||||||
|
* on macOS amd64.
|
||||||
|
* with hw bound check, theoretically, only needs to cover the logic to
|
||||||
|
* set up the jmp_buf stack.
|
||||||
|
*
|
||||||
|
* - aot runtime functions
|
||||||
|
* eg. aot_enlarge_memory.
|
||||||
|
*
|
||||||
|
* - w/o hw bound check, the intepreter loop
|
||||||
|
*
|
||||||
|
* - stack check wrapper functions generated by the aot compiler
|
||||||
|
* (--stack-bounds-checks=1)
|
||||||
|
*
|
||||||
|
* Note: on platforms with lazy function binding, don't forget to consider
|
||||||
|
* the symbol resolution overhead on the first call. For example,
|
||||||
|
* on Ubuntu amd64 20.04, it seems to consume about 1500 bytes.
|
||||||
|
*/
|
||||||
#ifndef WASM_STACK_GUARD_SIZE
|
#ifndef WASM_STACK_GUARD_SIZE
|
||||||
#if WASM_ENABLE_UVWASI != 0
|
#if WASM_ENABLE_UVWASI != 0
|
||||||
/* UVWASI requires larger native stack */
|
/* UVWASI requires larger native stack */
|
||||||
|
@ -587,4 +609,8 @@
|
||||||
#define WASM_TABLE_MAX_SIZE 1024
|
#define WASM_TABLE_MAX_SIZE 1024
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef WASM_MEM_ALLOC_WITH_USAGE
|
||||||
|
#define WASM_MEM_ALLOC_WITH_USAGE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* end of _CONFIG_H_ */
|
#endif /* end of _CONFIG_H_ */
|
||||||
|
|
|
@ -1525,30 +1525,42 @@ fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_type(AOTType *type)
|
||||||
|
{
|
||||||
|
#if WASM_ENABLE_GC != 0
|
||||||
|
if (type->ref_count > 1) {
|
||||||
|
/* The type is referenced by other types
|
||||||
|
of current aot module */
|
||||||
|
type->ref_count--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type->type_flag == WASM_TYPE_FUNC) {
|
||||||
|
AOTFuncType *func_type = (AOTFuncType *)type;
|
||||||
|
if (func_type->ref_type_maps != NULL) {
|
||||||
|
bh_assert(func_type->ref_type_map_count > 0);
|
||||||
|
wasm_runtime_free(func_type->ref_type_maps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type->type_flag == WASM_TYPE_STRUCT) {
|
||||||
|
AOTStructType *struct_type = (AOTStructType *)type;
|
||||||
|
if (struct_type->ref_type_maps != NULL) {
|
||||||
|
bh_assert(struct_type->ref_type_map_count > 0);
|
||||||
|
wasm_runtime_free(struct_type->ref_type_maps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
wasm_runtime_free(type);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_types(AOTType **types, uint32 count)
|
destroy_types(AOTType **types, uint32 count)
|
||||||
{
|
{
|
||||||
uint32 i;
|
uint32 i;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
|
|
||||||
if (types[i]) {
|
if (types[i]) {
|
||||||
#if WASM_ENABLE_GC != 0
|
destroy_type(types[i]);
|
||||||
if (types[i]->type_flag == WASM_TYPE_FUNC) {
|
|
||||||
AOTFuncType *func_type = (AOTFuncType *)types[i];
|
|
||||||
if (func_type->ref_type_maps != NULL) {
|
|
||||||
bh_assert(func_type->ref_type_map_count > 0);
|
|
||||||
wasm_runtime_free(func_type->ref_type_maps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (types[i]->type_flag == WASM_TYPE_STRUCT) {
|
|
||||||
AOTStructType *struct_type = (AOTStructType *)types[i];
|
|
||||||
if (struct_type->ref_type_maps != NULL) {
|
|
||||||
bh_assert(struct_type->ref_type_map_count > 0);
|
|
||||||
wasm_runtime_free(struct_type->ref_type_maps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
wasm_runtime_free(types[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wasm_runtime_free(types);
|
wasm_runtime_free(types);
|
||||||
|
@ -1556,14 +1568,17 @@ destroy_types(AOTType **types, uint32 count)
|
||||||
|
|
||||||
#if WASM_ENABLE_GC != 0
|
#if WASM_ENABLE_GC != 0
|
||||||
static void
|
static void
|
||||||
init_base_type(AOTType *base_type, uint16 type_flag, bool is_sub_final,
|
init_base_type(AOTType *base_type, uint32 type_idx, uint16 type_flag,
|
||||||
uint32 parent_type_idx, uint16 rec_count, uint16 rec_idx)
|
bool is_sub_final, uint32 parent_type_idx, uint16 rec_count,
|
||||||
|
uint16 rec_idx)
|
||||||
{
|
{
|
||||||
base_type->type_flag = type_flag;
|
base_type->type_flag = type_flag;
|
||||||
|
base_type->ref_count = 1;
|
||||||
base_type->is_sub_final = is_sub_final;
|
base_type->is_sub_final = is_sub_final;
|
||||||
base_type->parent_type_idx = parent_type_idx;
|
base_type->parent_type_idx = parent_type_idx;
|
||||||
base_type->rec_count = rec_count;
|
base_type->rec_count = rec_count;
|
||||||
base_type->rec_idx = rec_idx;
|
base_type->rec_idx = rec_idx;
|
||||||
|
base_type->rec_begin_type_idx = type_idx - rec_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -1576,7 +1591,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
||||||
uint32 i, j;
|
uint32 i, j;
|
||||||
uint32 type_flag, param_cell_num, ret_cell_num;
|
uint32 type_flag, param_cell_num, ret_cell_num;
|
||||||
uint16 param_count, result_count, ref_type_map_count, rec_count, rec_idx;
|
uint16 param_count, result_count, ref_type_map_count, rec_count, rec_idx;
|
||||||
bool is_sub_final;
|
bool is_equivalence_type, is_sub_final;
|
||||||
uint32 parent_type_idx;
|
uint32 parent_type_idx;
|
||||||
WASMRefType ref_type;
|
WASMRefType ref_type;
|
||||||
|
|
||||||
|
@ -1590,12 +1605,31 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
||||||
|
|
||||||
/* Create each type */
|
/* Create each type */
|
||||||
for (i = 0; i < module->type_count; i++) {
|
for (i = 0; i < module->type_count; i++) {
|
||||||
|
|
||||||
buf = align_ptr(buf, 4);
|
buf = align_ptr(buf, 4);
|
||||||
|
|
||||||
/* Read base type info */
|
/* Read base type info */
|
||||||
read_uint16(buf, buf_end, type_flag);
|
read_uint16(buf, buf_end, type_flag);
|
||||||
read_uint16(buf, buf_end, is_sub_final);
|
|
||||||
|
read_uint8(buf, buf_end, is_equivalence_type);
|
||||||
|
/* If there is an equivalence type, re-use it */
|
||||||
|
if (is_equivalence_type) {
|
||||||
|
uint8 u8;
|
||||||
|
/* padding */
|
||||||
|
read_uint8(buf, buf_end, u8);
|
||||||
|
(void)u8;
|
||||||
|
|
||||||
|
read_uint32(buf, buf_end, j);
|
||||||
|
if (module->types[j]->ref_count == UINT16_MAX) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"wasm type's ref count too large");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
module->types[j]->ref_count++;
|
||||||
|
module->types[i] = module->types[j];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_uint8(buf, buf_end, is_sub_final);
|
||||||
read_uint32(buf, buf_end, parent_type_idx);
|
read_uint32(buf, buf_end, parent_type_idx);
|
||||||
read_uint16(buf, buf_end, rec_count);
|
read_uint16(buf, buf_end, rec_count);
|
||||||
read_uint16(buf, buf_end, rec_idx);
|
read_uint16(buf, buf_end, rec_idx);
|
||||||
|
@ -1620,7 +1654,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
||||||
|
|
||||||
types[i] = (AOTType *)func_type;
|
types[i] = (AOTType *)func_type;
|
||||||
|
|
||||||
init_base_type((AOTType *)func_type, type_flag, is_sub_final,
|
init_base_type((AOTType *)func_type, i, type_flag, is_sub_final,
|
||||||
parent_type_idx, rec_count, rec_idx);
|
parent_type_idx, rec_count, rec_idx);
|
||||||
func_type->param_count = param_count;
|
func_type->param_count = param_count;
|
||||||
func_type->result_count = result_count;
|
func_type->result_count = result_count;
|
||||||
|
@ -1726,7 +1760,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
||||||
offset = (uint32)offsetof(WASMStructObject, field_data);
|
offset = (uint32)offsetof(WASMStructObject, field_data);
|
||||||
types[i] = (AOTType *)struct_type;
|
types[i] = (AOTType *)struct_type;
|
||||||
|
|
||||||
init_base_type((AOTType *)struct_type, type_flag, is_sub_final,
|
init_base_type((AOTType *)struct_type, i, type_flag, is_sub_final,
|
||||||
parent_type_idx, rec_count, rec_idx);
|
parent_type_idx, rec_count, rec_idx);
|
||||||
struct_type->field_count = field_count;
|
struct_type->field_count = field_count;
|
||||||
struct_type->ref_type_map_count = ref_type_map_count;
|
struct_type->ref_type_map_count = ref_type_map_count;
|
||||||
|
@ -1812,7 +1846,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
||||||
|
|
||||||
types[i] = (AOTType *)array_type;
|
types[i] = (AOTType *)array_type;
|
||||||
|
|
||||||
init_base_type((AOTType *)array_type, type_flag, is_sub_final,
|
init_base_type((AOTType *)array_type, i, type_flag, is_sub_final,
|
||||||
parent_type_idx, rec_count, rec_idx);
|
parent_type_idx, rec_count, rec_idx);
|
||||||
read_uint16(buf, buf_end, array_type->elem_flags);
|
read_uint16(buf, buf_end, array_type->elem_flags);
|
||||||
read_uint8(buf, buf_end, array_type->elem_type);
|
read_uint8(buf, buf_end, array_type->elem_type);
|
||||||
|
@ -1841,7 +1875,6 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
||||||
if (rec_count == 0) {
|
if (rec_count == 0) {
|
||||||
bh_assert(rec_idx == 0);
|
bh_assert(rec_idx == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = i - rec_idx; j <= i; j++) {
|
for (j = i - rec_idx; j <= i; j++) {
|
||||||
AOTType *cur_type = module->types[j];
|
AOTType *cur_type = module->types[j];
|
||||||
parent_type_idx = cur_type->parent_type_idx;
|
parent_type_idx = cur_type->parent_type_idx;
|
||||||
|
@ -1850,6 +1883,11 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
||||||
|
|
||||||
module->types[j]->parent_type = parent_type;
|
module->types[j]->parent_type = parent_type;
|
||||||
module->types[j]->root_type = parent_type->root_type;
|
module->types[j]->root_type = parent_type->root_type;
|
||||||
|
if (parent_type->inherit_depth == UINT16_MAX) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"parent type's inherit depth too large");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
module->types[j]->inherit_depth =
|
module->types[j]->inherit_depth =
|
||||||
parent_type->inherit_depth + 1;
|
parent_type->inherit_depth + 1;
|
||||||
}
|
}
|
||||||
|
@ -1867,7 +1905,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
|
||||||
AOTType *parent_type = module->types[parent_type_idx];
|
AOTType *parent_type = module->types[parent_type_idx];
|
||||||
/* subtyping has been checked during compilation */
|
/* subtyping has been checked during compilation */
|
||||||
bh_assert(wasm_type_is_subtype_of(
|
bh_assert(wasm_type_is_subtype_of(
|
||||||
module->types[j], parent_type, module->types, i));
|
module->types[j], parent_type, module->types, i + 1));
|
||||||
(void)parent_type;
|
(void)parent_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3257,37 +3295,26 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end,
|
||||||
bh_memcpy_s(symbol_name_buf, (uint32)sizeof(symbol_name_buf),
|
bh_memcpy_s(symbol_name_buf, (uint32)sizeof(symbol_name_buf),
|
||||||
symbol_name, symbol_name_len);
|
symbol_name, symbol_name_len);
|
||||||
|
|
||||||
if ((group_name_len == strlen(".text")
|
/* aot compiler emits string with '\0' since 2.0.0 */
|
||||||
|| (module->is_indirect_mode
|
if (group_name_len == strlen(".text") + 1
|
||||||
&& group_name_len == strlen(".text") + 1))
|
|
||||||
&& !strncmp(group_name, ".text", strlen(".text"))) {
|
&& !strncmp(group_name, ".text", strlen(".text"))) {
|
||||||
if ((symbol_name_len == strlen(YMM_PLT_PREFIX) + 64
|
/* aot compiler emits string with '\0' since 2.0.0 */
|
||||||
|| (module->is_indirect_mode
|
if (symbol_name_len == strlen(YMM_PLT_PREFIX) + 64 + 1
|
||||||
&& symbol_name_len == strlen(YMM_PLT_PREFIX) + 64 + 1))
|
|
||||||
&& !strncmp(symbol_name, YMM_PLT_PREFIX,
|
&& !strncmp(symbol_name, YMM_PLT_PREFIX,
|
||||||
strlen(YMM_PLT_PREFIX))) {
|
strlen(YMM_PLT_PREFIX))) {
|
||||||
module->ymm_plt_count++;
|
module->ymm_plt_count++;
|
||||||
}
|
}
|
||||||
else if ((symbol_name_len == strlen(XMM_PLT_PREFIX) + 32
|
else if (symbol_name_len == strlen(XMM_PLT_PREFIX) + 32 + 1
|
||||||
|| (module->is_indirect_mode
|
|
||||||
&& symbol_name_len
|
|
||||||
== strlen(XMM_PLT_PREFIX) + 32 + 1))
|
|
||||||
&& !strncmp(symbol_name, XMM_PLT_PREFIX,
|
&& !strncmp(symbol_name, XMM_PLT_PREFIX,
|
||||||
strlen(XMM_PLT_PREFIX))) {
|
strlen(XMM_PLT_PREFIX))) {
|
||||||
module->xmm_plt_count++;
|
module->xmm_plt_count++;
|
||||||
}
|
}
|
||||||
else if ((symbol_name_len == strlen(REAL_PLT_PREFIX) + 16
|
else if (symbol_name_len == strlen(REAL_PLT_PREFIX) + 16 + 1
|
||||||
|| (module->is_indirect_mode
|
|
||||||
&& symbol_name_len
|
|
||||||
== strlen(REAL_PLT_PREFIX) + 16 + 1))
|
|
||||||
&& !strncmp(symbol_name, REAL_PLT_PREFIX,
|
&& !strncmp(symbol_name, REAL_PLT_PREFIX,
|
||||||
strlen(REAL_PLT_PREFIX))) {
|
strlen(REAL_PLT_PREFIX))) {
|
||||||
module->real_plt_count++;
|
module->real_plt_count++;
|
||||||
}
|
}
|
||||||
else if ((symbol_name_len >= strlen(REAL_PLT_PREFIX) + 8
|
else if (symbol_name_len >= strlen(REAL_PLT_PREFIX) + 8 + 1
|
||||||
|| (module->is_indirect_mode
|
|
||||||
&& symbol_name_len
|
|
||||||
== strlen(REAL_PLT_PREFIX) + 8 + 1))
|
|
||||||
&& !strncmp(symbol_name, REAL_PLT_PREFIX,
|
&& !strncmp(symbol_name, REAL_PLT_PREFIX,
|
||||||
strlen(REAL_PLT_PREFIX))) {
|
strlen(REAL_PLT_PREFIX))) {
|
||||||
module->float_plt_count++;
|
module->float_plt_count++;
|
||||||
|
|
|
@ -143,6 +143,7 @@ typedef struct {
|
||||||
REG_SYM(aot_array_init_with_data), \
|
REG_SYM(aot_array_init_with_data), \
|
||||||
REG_SYM(aot_create_func_obj), \
|
REG_SYM(aot_create_func_obj), \
|
||||||
REG_SYM(aot_obj_is_instance_of), \
|
REG_SYM(aot_obj_is_instance_of), \
|
||||||
|
REG_SYM(aot_func_type_is_super_of), \
|
||||||
REG_SYM(aot_rtt_type_new), \
|
REG_SYM(aot_rtt_type_new), \
|
||||||
REG_SYM(wasm_array_obj_copy), \
|
REG_SYM(wasm_array_obj_copy), \
|
||||||
REG_SYM(wasm_array_obj_new), \
|
REG_SYM(wasm_array_obj_new), \
|
||||||
|
|
|
@ -1721,6 +1721,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
|
||||||
|
|
||||||
bh_assert(table_init_data);
|
bh_assert(table_init_data);
|
||||||
|
|
||||||
|
bh_assert(table_init_data->table_index < module_inst->table_count);
|
||||||
table = module_inst->tables[table_init_data->table_index];
|
table = module_inst->tables[table_init_data->table_index];
|
||||||
bh_assert(table);
|
bh_assert(table);
|
||||||
|
|
||||||
|
@ -1728,8 +1729,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
|
||||||
bh_assert(table_data);
|
bh_assert(table_data);
|
||||||
|
|
||||||
wasm_runtime_get_table_inst_elem_type(
|
wasm_runtime_get_table_inst_elem_type(
|
||||||
(WASMModuleInstanceCommon *)module_inst, i, &tbl_elem_type,
|
(WASMModuleInstanceCommon *)module_inst,
|
||||||
&tbl_elem_ref_type, &tbl_init_size, &tbl_max_size);
|
table_init_data->table_index, &tbl_elem_type, &tbl_elem_ref_type,
|
||||||
|
&tbl_init_size, &tbl_max_size);
|
||||||
|
|
||||||
if (!wasm_elem_is_declarative(table_init_data->mode)
|
if (!wasm_elem_is_declarative(table_init_data->mode)
|
||||||
&& !wasm_reftype_is_subtype_of(
|
&& !wasm_reftype_is_subtype_of(
|
||||||
|
@ -4487,6 +4489,22 @@ aot_obj_is_instance_of(AOTModuleInstance *module_inst, WASMObjectRef gc_obj,
|
||||||
return wasm_obj_is_instance_of(gc_obj, type_index, types, type_count);
|
return wasm_obj_is_instance_of(gc_obj, type_index, types, type_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
aot_func_type_is_super_of(AOTModuleInstance *module_inst, uint32 type_idx1,
|
||||||
|
uint32 type_idx2)
|
||||||
|
{
|
||||||
|
AOTModule *aot_module = (AOTModule *)module_inst->module;
|
||||||
|
AOTType **types = aot_module->types;
|
||||||
|
|
||||||
|
if (type_idx1 == type_idx2)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bh_assert(types[type_idx1]->type_flag == WASM_TYPE_FUNC);
|
||||||
|
bh_assert(types[type_idx2]->type_flag == WASM_TYPE_FUNC);
|
||||||
|
return wasm_func_type_is_super_of((WASMFuncType *)types[type_idx1],
|
||||||
|
(WASMFuncType *)types[type_idx2]);
|
||||||
|
}
|
||||||
|
|
||||||
WASMRttTypeRef
|
WASMRttTypeRef
|
||||||
aot_rtt_type_new(AOTModuleInstance *module_inst, uint32 type_index)
|
aot_rtt_type_new(AOTModuleInstance *module_inst, uint32 type_index)
|
||||||
{
|
{
|
||||||
|
|
|
@ -752,6 +752,11 @@ bool
|
||||||
aot_obj_is_instance_of(AOTModuleInstance *module_inst, WASMObjectRef gc_obj,
|
aot_obj_is_instance_of(AOTModuleInstance *module_inst, WASMObjectRef gc_obj,
|
||||||
uint32 type_index);
|
uint32 type_index);
|
||||||
|
|
||||||
|
/* Whether func type1 is one of super types of func type2 */
|
||||||
|
bool
|
||||||
|
aot_func_type_is_super_of(AOTModuleInstance *module_inst, uint32 type_idx1,
|
||||||
|
uint32 type_idx2);
|
||||||
|
|
||||||
WASMRttTypeRef
|
WASMRttTypeRef
|
||||||
aot_rtt_type_new(AOTModuleInstance *module_inst, uint32 type_index);
|
aot_rtt_type_new(AOTModuleInstance *module_inst, uint32 type_index);
|
||||||
|
|
||||||
|
|
|
@ -304,7 +304,12 @@ wasm_defined_type_equal(WASMType *const def_type1, WASMType *const def_type2,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_AOT != 0
|
#if WASM_ENABLE_AOT != 0
|
||||||
/* TODO */
|
if (module->module_type == Wasm_Module_AoT) {
|
||||||
|
AOTModule *aot_module = (AOTModule *)module;
|
||||||
|
|
||||||
|
types = aot_module->types;
|
||||||
|
type_count = aot_module->type_count;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bh_assert(types);
|
bh_assert(types);
|
||||||
|
|
|
@ -250,6 +250,51 @@ wasm_value_types_is_subtype_of(const uint8 *types1,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
rec_ref_type_equal(const WASMRefType *ref_type1, const WASMRefType *ref_type2,
|
||||||
|
uint32 rec_begin_type_idx1, uint32 rec_begin_type_idx2,
|
||||||
|
uint32 rec_count, const WASMTypePtr *types,
|
||||||
|
uint32 type_count)
|
||||||
|
{
|
||||||
|
uint32 type_idx1, type_idx2;
|
||||||
|
|
||||||
|
if (!wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)
|
||||||
|
|| !wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common))
|
||||||
|
return ref_type1->ref_ht_common.heap_type
|
||||||
|
== ref_type2->ref_ht_common.heap_type
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
|
||||||
|
/* Now both ref types are type of (ref type_idx) */
|
||||||
|
type_idx1 = ref_type1->ref_ht_typeidx.type_idx;
|
||||||
|
type_idx2 = ref_type2->ref_ht_typeidx.type_idx;
|
||||||
|
|
||||||
|
if (type_idx1 >= rec_begin_type_idx1
|
||||||
|
&& type_idx1 < rec_begin_type_idx1 + rec_count) {
|
||||||
|
/* The converted iso-recursive types should be the same */
|
||||||
|
bool ret = (type_idx2 >= rec_begin_type_idx2
|
||||||
|
&& type_idx2 < rec_begin_type_idx2 + rec_count
|
||||||
|
&& type_idx1 - rec_begin_type_idx1
|
||||||
|
== type_idx2 - rec_begin_type_idx2)
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else if (type_idx2 >= rec_begin_type_idx2
|
||||||
|
&& type_idx2 < rec_begin_type_idx2 + rec_count) {
|
||||||
|
/* The converted iso-recursive types should be the same */
|
||||||
|
bool ret = (type_idx1 >= rec_begin_type_idx1
|
||||||
|
&& type_idx1 < rec_begin_type_idx1 + rec_count
|
||||||
|
&& type_idx1 - rec_begin_type_idx1
|
||||||
|
== type_idx2 - rec_begin_type_idx2)
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return types[type_idx1] == types[type_idx2] ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2,
|
wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2,
|
||||||
const WASMTypePtr *types, uint32 type_count)
|
const WASMTypePtr *types, uint32 type_count)
|
||||||
|
@ -277,9 +322,11 @@ wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2,
|
||||||
|
|
||||||
ref_type1 = type1->ref_type_maps[j].ref_type;
|
ref_type1 = type1->ref_type_maps[j].ref_type;
|
||||||
ref_type2 = type2->ref_type_maps[j].ref_type;
|
ref_type2 = type2->ref_type_maps[j].ref_type;
|
||||||
if (!wasm_reftype_equal(ref_type1->ref_type, ref_type1,
|
|
||||||
ref_type2->ref_type, ref_type2, types,
|
if (!rec_ref_type_equal(
|
||||||
type_count))
|
ref_type1, ref_type2, type1->base_type.rec_begin_type_idx,
|
||||||
|
type2->base_type.rec_begin_type_idx,
|
||||||
|
type1->base_type.rec_count, types, type_count))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
j++;
|
j++;
|
||||||
|
@ -316,9 +363,11 @@ wasm_struct_type_equal(const WASMStructType *type1, const WASMStructType *type2,
|
||||||
|
|
||||||
ref_type1 = type1->ref_type_maps[j].ref_type;
|
ref_type1 = type1->ref_type_maps[j].ref_type;
|
||||||
ref_type2 = type2->ref_type_maps[j].ref_type;
|
ref_type2 = type2->ref_type_maps[j].ref_type;
|
||||||
if (!wasm_reftype_equal(ref_type1->ref_type, ref_type1,
|
|
||||||
ref_type2->ref_type, ref_type2, types,
|
if (!rec_ref_type_equal(
|
||||||
type_count))
|
ref_type1, ref_type2, type1->base_type.rec_begin_type_idx,
|
||||||
|
type2->base_type.rec_begin_type_idx,
|
||||||
|
type1->base_type.rec_count, types, type_count))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
j++;
|
j++;
|
||||||
|
@ -338,21 +387,67 @@ wasm_array_type_equal(const WASMArrayType *type1, const WASMArrayType *type2,
|
||||||
if (type1->elem_flags != type2->elem_flags)
|
if (type1->elem_flags != type2->elem_flags)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return wasm_reftype_equal(type1->elem_type, type1->elem_ref_type,
|
if (type1->elem_type != type2->elem_type)
|
||||||
type2->elem_type, type2->elem_ref_type, types,
|
return false;
|
||||||
type_count);
|
|
||||||
|
if (!wasm_is_type_multi_byte_type(type1->elem_type))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return rec_ref_type_equal(type1->elem_ref_type, type2->elem_ref_type,
|
||||||
|
type1->base_type.rec_begin_type_idx,
|
||||||
|
type2->base_type.rec_begin_type_idx,
|
||||||
|
type1->base_type.rec_count, types, type_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm_type_equal(const WASMType *type1, const WASMType *type2,
|
wasm_type_equal(const WASMType *type1, const WASMType *type2,
|
||||||
const WASMTypePtr *types, uint32 type_count)
|
const WASMTypePtr *types, uint32 type_count)
|
||||||
{
|
{
|
||||||
|
uint32 rec_begin_type_idx1 = type1->rec_begin_type_idx;
|
||||||
|
uint32 rec_begin_type_idx2 = type2->rec_begin_type_idx;
|
||||||
|
uint32 parent_type_idx1, parent_type_idx2, rec_count;
|
||||||
|
|
||||||
if (type1 == type2)
|
if (type1 == type2)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (type1->type_flag != type2->type_flag)
|
if (!(type1->type_flag == type2->type_flag
|
||||||
|
&& type1->is_sub_final == type2->is_sub_final
|
||||||
|
&& type1->rec_count == type2->rec_count
|
||||||
|
&& type1->rec_idx == type2->rec_idx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
rec_count = type1->rec_count;
|
||||||
|
|
||||||
|
parent_type_idx1 = type1->parent_type_idx;
|
||||||
|
parent_type_idx2 = type2->parent_type_idx;
|
||||||
|
|
||||||
|
if (parent_type_idx1 >= rec_begin_type_idx1
|
||||||
|
&& parent_type_idx1 < rec_begin_type_idx1 + rec_count) {
|
||||||
|
/* The converted iso-recursive types should be the same */
|
||||||
|
if (!(parent_type_idx2 >= rec_begin_type_idx2
|
||||||
|
&& parent_type_idx2 < rec_begin_type_idx2 + rec_count
|
||||||
|
&& parent_type_idx1 - rec_begin_type_idx1
|
||||||
|
== parent_type_idx2 - rec_begin_type_idx2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (parent_type_idx2 >= rec_begin_type_idx2
|
||||||
|
&& parent_type_idx2 < rec_begin_type_idx2 + rec_count) {
|
||||||
|
/* The converted iso-recursive types should be the same */
|
||||||
|
if (!(parent_type_idx1 >= rec_begin_type_idx1
|
||||||
|
&& parent_type_idx1 < rec_begin_type_idx1 + rec_count
|
||||||
|
&& parent_type_idx1 - rec_begin_type_idx1
|
||||||
|
== parent_type_idx2 - rec_begin_type_idx2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type1->parent_type != type2->parent_type) {
|
||||||
|
/* The parent types should be same since they have been
|
||||||
|
normalized and equivalence types with different type
|
||||||
|
indexes are referring to a same WASMType */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (wasm_type_is_func_type(type1))
|
if (wasm_type_is_func_type(type1))
|
||||||
return wasm_func_type_equal((WASMFuncType *)type1,
|
return wasm_func_type_equal((WASMFuncType *)type1,
|
||||||
(WASMFuncType *)type2, types, type_count);
|
(WASMFuncType *)type2, types, type_count);
|
||||||
|
@ -653,12 +748,6 @@ wasm_reftype_struct_size(const WASMRefType *ref_type)
|
||||||
return (uint32)sizeof(RefHeapType_Common);
|
return (uint32)sizeof(RefHeapType_Common);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
type_idx_equal(uint32 type_idx1, uint32 type_idx2)
|
|
||||||
{
|
|
||||||
return (type_idx1 == type_idx2) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm_refheaptype_equal(const RefHeapType_Common *ref_heap_type1,
|
wasm_refheaptype_equal(const RefHeapType_Common *ref_heap_type1,
|
||||||
const RefHeapType_Common *ref_heap_type2,
|
const RefHeapType_Common *ref_heap_type2,
|
||||||
|
@ -673,8 +762,16 @@ wasm_refheaptype_equal(const RefHeapType_Common *ref_heap_type1,
|
||||||
if (ref_heap_type1->heap_type != ref_heap_type2->heap_type) {
|
if (ref_heap_type1->heap_type != ref_heap_type2->heap_type) {
|
||||||
if (wasm_is_refheaptype_typeidx(ref_heap_type1)
|
if (wasm_is_refheaptype_typeidx(ref_heap_type1)
|
||||||
&& wasm_is_refheaptype_typeidx(ref_heap_type2)) {
|
&& wasm_is_refheaptype_typeidx(ref_heap_type2)) {
|
||||||
return type_idx_equal(ref_heap_type1->heap_type,
|
if (ref_heap_type1->heap_type == ref_heap_type2->heap_type)
|
||||||
ref_heap_type2->heap_type);
|
return true;
|
||||||
|
else
|
||||||
|
/* the type_count may be 0 when called from reftype_equal */
|
||||||
|
return ((uint32)ref_heap_type1->heap_type < type_count
|
||||||
|
&& (uint32)ref_heap_type2->heap_type < type_count
|
||||||
|
&& types[ref_heap_type1->heap_type]
|
||||||
|
== types[ref_heap_type2->heap_type])
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -835,6 +932,13 @@ wasm_type_is_supers_of(const WASMType *type1, const WASMType *type2)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
wasm_func_type_is_super_of(const WASMFuncType *type1, const WASMFuncType *type2)
|
||||||
|
{
|
||||||
|
return wasm_type_is_supers_of((const WASMType *)type1,
|
||||||
|
(const WASMType *)type2);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
|
wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
|
||||||
uint8 type2, const WASMRefType *ref_type2,
|
uint8 type2, const WASMRefType *ref_type2,
|
||||||
|
@ -914,14 +1018,15 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
|
||||||
#endif
|
#endif
|
||||||
else if (type1 == REF_TYPE_HT_NULLABLE) {
|
else if (type1 == REF_TYPE_HT_NULLABLE) {
|
||||||
if (wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)) {
|
if (wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)) {
|
||||||
|
bh_assert((uint32)ref_type1->ref_ht_typeidx.type_idx < type_count);
|
||||||
/* reftype1 is (ref null $t) */
|
/* reftype1 is (ref null $t) */
|
||||||
if (type2 == REF_TYPE_HT_NULLABLE && ref_type2 != NULL
|
if (type2 == REF_TYPE_HT_NULLABLE && ref_type2 != NULL
|
||||||
&& wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common)) {
|
&& wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common)) {
|
||||||
return type_idx_equal(ref_type1->ref_ht_typeidx.type_idx,
|
bh_assert((uint32)ref_type2->ref_ht_typeidx.type_idx
|
||||||
ref_type2->ref_ht_typeidx.type_idx)
|
< type_count);
|
||||||
|| wasm_type_is_supers_of(
|
return wasm_type_is_supers_of(
|
||||||
types[ref_type2->ref_ht_typeidx.type_idx],
|
types[ref_type2->ref_ht_typeidx.type_idx],
|
||||||
types[ref_type1->ref_ht_typeidx.type_idx]);
|
types[ref_type1->ref_ht_typeidx.type_idx]);
|
||||||
}
|
}
|
||||||
else if (types[ref_type1->ref_ht_typeidx.type_idx]->type_flag
|
else if (types[ref_type1->ref_ht_typeidx.type_idx]->type_flag
|
||||||
== WASM_TYPE_STRUCT)
|
== WASM_TYPE_STRUCT)
|
||||||
|
@ -963,16 +1068,17 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
|
||||||
else if (type1 == REF_TYPE_HT_NON_NULLABLE) {
|
else if (type1 == REF_TYPE_HT_NON_NULLABLE) {
|
||||||
bh_assert(ref_type1);
|
bh_assert(ref_type1);
|
||||||
if (wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)) {
|
if (wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)) {
|
||||||
|
bh_assert((uint32)ref_type1->ref_ht_typeidx.type_idx < type_count);
|
||||||
/* reftype1 is (ref $t) */
|
/* reftype1 is (ref $t) */
|
||||||
if ((type2 == REF_TYPE_HT_NULLABLE
|
if ((type2 == REF_TYPE_HT_NULLABLE
|
||||||
|| type2 == REF_TYPE_HT_NON_NULLABLE)
|
|| type2 == REF_TYPE_HT_NON_NULLABLE)
|
||||||
&& ref_type2 != NULL
|
&& ref_type2 != NULL
|
||||||
&& wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common)) {
|
&& wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common)) {
|
||||||
return type_idx_equal(ref_type1->ref_ht_typeidx.type_idx,
|
bh_assert((uint32)ref_type2->ref_ht_typeidx.type_idx
|
||||||
ref_type2->ref_ht_typeidx.type_idx)
|
< type_count);
|
||||||
|| wasm_type_is_supers_of(
|
return wasm_type_is_supers_of(
|
||||||
types[ref_type2->ref_ht_typeidx.type_idx],
|
types[ref_type2->ref_ht_typeidx.type_idx],
|
||||||
types[ref_type1->ref_ht_typeidx.type_idx]);
|
types[ref_type1->ref_ht_typeidx.type_idx]);
|
||||||
}
|
}
|
||||||
else if (types[ref_type1->ref_ht_typeidx.type_idx]->type_flag
|
else if (types[ref_type1->ref_ht_typeidx.type_idx]->type_flag
|
||||||
== WASM_TYPE_STRUCT) {
|
== WASM_TYPE_STRUCT) {
|
||||||
|
|
|
@ -47,6 +47,12 @@ wasm_func_type_is_subtype_of(const WASMFuncType *type1,
|
||||||
const WASMFuncType *type2,
|
const WASMFuncType *type2,
|
||||||
const WASMTypePtr *types, uint32 type_count);
|
const WASMTypePtr *types, uint32 type_count);
|
||||||
|
|
||||||
|
/* Whether func type1 is one of super types of func type2,
|
||||||
|
used for the func type check in call_indirect/call_ref opcodes */
|
||||||
|
bool
|
||||||
|
wasm_func_type_is_super_of(const WASMFuncType *type1,
|
||||||
|
const WASMFuncType *type2);
|
||||||
|
|
||||||
/* Whether func type1's result types are subtype of
|
/* Whether func type1's result types are subtype of
|
||||||
func type2's result types */
|
func type2's result types */
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -578,8 +578,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
|
||||||
is_anyref = true;
|
is_anyref = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wasm_is_type_multi_byte_type(
|
if (wasm_is_type_multi_byte_type(type->types[i])) {
|
||||||
type->types[type->param_count + i])) {
|
|
||||||
WASMRefType *ref_type = ref_type_map->ref_type;
|
WASMRefType *ref_type = ref_type_map->ref_type;
|
||||||
if (wasm_is_refheaptype_common(
|
if (wasm_is_refheaptype_common(
|
||||||
&ref_type->ref_ht_common)) {
|
&ref_type->ref_ht_common)) {
|
||||||
|
|
|
@ -29,16 +29,35 @@ static void *enlarge_memory_error_user_data;
|
||||||
|
|
||||||
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
static void *allocator_user_data = NULL;
|
static void *allocator_user_data = NULL;
|
||||||
static void *(*malloc_func)(void *user_data, unsigned int size) = NULL;
|
|
||||||
static void *(*realloc_func)(void *user_data, void *ptr,
|
|
||||||
unsigned int size) = NULL;
|
|
||||||
static void (*free_func)(void *user_data, void *ptr) = NULL;
|
|
||||||
#else
|
|
||||||
static void *(*malloc_func)(unsigned int size) = NULL;
|
|
||||||
static void *(*realloc_func)(void *ptr, unsigned int size) = NULL;
|
|
||||||
static void (*free_func)(void *ptr) = NULL;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void *(*malloc_func)(
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
|
mem_alloc_usage_t usage,
|
||||||
|
#endif
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
|
void *user_data,
|
||||||
|
#endif
|
||||||
|
unsigned int size) = NULL;
|
||||||
|
|
||||||
|
static void *(*realloc_func)(
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
|
mem_alloc_usage_t usage, bool full_size_mmaped,
|
||||||
|
#endif
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
|
void *user_data,
|
||||||
|
#endif
|
||||||
|
void *ptr, unsigned int size) = NULL;
|
||||||
|
|
||||||
|
static void (*free_func)(
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
|
mem_alloc_usage_t usage,
|
||||||
|
#endif
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
|
void *user_data,
|
||||||
|
#endif
|
||||||
|
void *ptr) = NULL;
|
||||||
|
|
||||||
static unsigned int global_pool_size;
|
static unsigned int global_pool_size;
|
||||||
|
|
||||||
static uint64
|
static uint64
|
||||||
|
@ -177,11 +196,14 @@ wasm_runtime_malloc_internal(unsigned int size)
|
||||||
return mem_allocator_malloc(pool_allocator, size);
|
return mem_allocator_malloc(pool_allocator, size);
|
||||||
}
|
}
|
||||||
else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
|
else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
|
||||||
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
return malloc_func(
|
||||||
return malloc_func(allocator_user_data, size);
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
#else
|
Alloc_For_Runtime,
|
||||||
return malloc_func(size);
|
|
||||||
#endif
|
#endif
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
|
allocator_user_data,
|
||||||
|
#endif
|
||||||
|
size);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return os_malloc(size);
|
return os_malloc(size);
|
||||||
|
@ -201,11 +223,14 @@ wasm_runtime_realloc_internal(void *ptr, unsigned int size)
|
||||||
}
|
}
|
||||||
else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
|
else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
|
||||||
if (realloc_func)
|
if (realloc_func)
|
||||||
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
return realloc_func(
|
||||||
return realloc_func(allocator_user_data, ptr, size);
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
#else
|
Alloc_For_Runtime, false,
|
||||||
return realloc_func(ptr, size);
|
|
||||||
#endif
|
#endif
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
|
allocator_user_data,
|
||||||
|
#endif
|
||||||
|
ptr, size);
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -233,11 +258,14 @@ wasm_runtime_free_internal(void *ptr)
|
||||||
mem_allocator_free(pool_allocator, ptr);
|
mem_allocator_free(pool_allocator, ptr);
|
||||||
}
|
}
|
||||||
else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
|
else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
|
||||||
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
free_func(
|
||||||
free_func(allocator_user_data, ptr);
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
#else
|
Alloc_For_Runtime,
|
||||||
free_func(ptr);
|
|
||||||
#endif
|
#endif
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
|
allocator_user_data,
|
||||||
|
#endif
|
||||||
|
ptr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
os_free(ptr);
|
os_free(ptr);
|
||||||
|
@ -765,6 +793,29 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
|
||||||
bh_assert(total_size_new
|
bh_assert(total_size_new
|
||||||
<= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64));
|
<= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64));
|
||||||
|
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
|
if (!(memory_data_new =
|
||||||
|
realloc_func(Alloc_For_LinearMemory, full_size_mmaped,
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
|
NULL,
|
||||||
|
#endif
|
||||||
|
memory_data_old, total_size_new))) {
|
||||||
|
ret = false;
|
||||||
|
goto return_func;
|
||||||
|
}
|
||||||
|
if (heap_size > 0) {
|
||||||
|
if (mem_allocator_migrate(memory->heap_handle,
|
||||||
|
(char *)heap_data_old
|
||||||
|
+ (memory_data_new - memory_data_old),
|
||||||
|
heap_size)
|
||||||
|
!= 0) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memory->heap_data = memory_data_new + (heap_data_old - memory_data_old);
|
||||||
|
memory->heap_data_end = memory->heap_data + heap_size;
|
||||||
|
memory->memory_data = memory_data_new;
|
||||||
|
#else
|
||||||
if (full_size_mmaped) {
|
if (full_size_mmaped) {
|
||||||
#ifdef BH_PLATFORM_WINDOWS
|
#ifdef BH_PLATFORM_WINDOWS
|
||||||
if (!os_mem_commit(memory->memory_data_end,
|
if (!os_mem_commit(memory->memory_data_end,
|
||||||
|
@ -823,6 +874,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
|
||||||
os_writegsbase(memory_data_new);
|
os_writegsbase(memory_data_new);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif /* end of WASM_MEM_ALLOC_WITH_USAGE */
|
||||||
|
|
||||||
memory->num_bytes_per_page = num_bytes_per_page;
|
memory->num_bytes_per_page = num_bytes_per_page;
|
||||||
memory->cur_page_count = total_page_count;
|
memory->cur_page_count = total_page_count;
|
||||||
|
@ -903,8 +955,19 @@ wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst)
|
||||||
#else
|
#else
|
||||||
map_size = 8 * (uint64)BH_GB;
|
map_size = 8 * (uint64)BH_GB;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
|
(void)map_size;
|
||||||
|
free_func(Alloc_For_LinearMemory,
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
|
NULL,
|
||||||
|
#endif
|
||||||
|
memory_inst->memory_data);
|
||||||
|
#else
|
||||||
wasm_munmap_linear_memory(memory_inst->memory_data,
|
wasm_munmap_linear_memory(memory_inst->memory_data,
|
||||||
memory_inst->memory_data_size, map_size);
|
memory_inst->memory_data_size, map_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
memory_inst->memory_data = NULL;
|
memory_inst->memory_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -954,9 +1017,20 @@ wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory,
|
||||||
*memory_data_size = align_as_and_cast(*memory_data_size, page_size);
|
*memory_data_size = align_as_and_cast(*memory_data_size, page_size);
|
||||||
|
|
||||||
if (map_size > 0) {
|
if (map_size > 0) {
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
|
(void)wasm_mmap_linear_memory;
|
||||||
|
if (!(*data = malloc_func(Alloc_For_LinearMemory,
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
|
NULL,
|
||||||
|
#endif
|
||||||
|
*memory_data_size))) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!(*data = wasm_mmap_linear_memory(map_size, *memory_data_size))) {
|
if (!(*data = wasm_mmap_linear_memory(map_size, *memory_data_size))) {
|
||||||
return BHT_ERROR;
|
return BHT_ERROR;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return BHT_OK;
|
return BHT_OK;
|
||||||
|
|
|
@ -84,9 +84,9 @@ compare_type_with_signautre(uint8 type, const char signature)
|
||||||
if ('r' == signature
|
if ('r' == signature
|
||||||
#if WASM_ENABLE_GC != 0
|
#if WASM_ENABLE_GC != 0
|
||||||
#if WASM_ENABLE_STRINGREF != 0
|
#if WASM_ENABLE_STRINGREF != 0
|
||||||
&& (type >= REF_TYPE_STRINGVIEWITER && type <= REF_TYPE_FUNCREF)
|
&& (type >= REF_TYPE_STRINGVIEWITER && type <= REF_TYPE_NULLFUNCREF)
|
||||||
#else
|
#else
|
||||||
&& (type >= REF_TYPE_NULLREF && type <= REF_TYPE_FUNCREF)
|
&& (type >= REF_TYPE_HT_NULLABLE && type <= REF_TYPE_NULLFUNCREF)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
&& type == VALUE_TYPE_EXTERNREF
|
&& type == VALUE_TYPE_EXTERNREF
|
||||||
|
|
|
@ -3727,6 +3727,213 @@ static union {
|
||||||
|
|
||||||
#define is_little_endian() (__ue.b == 1) /* NOLINT */
|
#define is_little_endian() (__ue.b == 1) /* NOLINT */
|
||||||
|
|
||||||
|
int32
|
||||||
|
wasm_runtime_get_import_count(WASMModuleCommon *const module)
|
||||||
|
{
|
||||||
|
if (!module) {
|
||||||
|
bh_assert(0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_AOT != 0
|
||||||
|
if (module->module_type == Wasm_Module_AoT) {
|
||||||
|
const AOTModule *aot_module = (const AOTModule *)module;
|
||||||
|
return (int32)(aot_module->import_func_count
|
||||||
|
+ aot_module->import_global_count
|
||||||
|
+ aot_module->import_table_count
|
||||||
|
+ aot_module->import_memory_count);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_INTERP != 0
|
||||||
|
if (module->module_type == Wasm_Module_Bytecode) {
|
||||||
|
const WASMModule *wasm_module = (const WASMModule *)module;
|
||||||
|
return (int32)wasm_module->import_count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
|
||||||
|
wasm_import_type *import_type)
|
||||||
|
{
|
||||||
|
if (!import_type) {
|
||||||
|
bh_assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(import_type, 0, sizeof(wasm_import_type));
|
||||||
|
|
||||||
|
if (!module) {
|
||||||
|
bh_assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_AOT != 0
|
||||||
|
if (module->module_type == Wasm_Module_AoT) {
|
||||||
|
const AOTModule *aot_module = (const AOTModule *)module;
|
||||||
|
|
||||||
|
uint32 func_index = (uint32)import_index;
|
||||||
|
if (func_index < aot_module->import_func_count) {
|
||||||
|
const AOTImportFunc *aot_import_func =
|
||||||
|
&aot_module->import_funcs[func_index];
|
||||||
|
import_type->module_name = aot_import_func->module_name;
|
||||||
|
import_type->name = aot_import_func->func_name;
|
||||||
|
import_type->kind = WASM_IMPORT_EXPORT_KIND_FUNC;
|
||||||
|
import_type->linked =
|
||||||
|
aot_import_func->func_ptr_linked ? true : false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 global_index = func_index - aot_module->import_func_count;
|
||||||
|
if (global_index < aot_module->import_global_count) {
|
||||||
|
const AOTImportGlobal *aot_import_global =
|
||||||
|
&aot_module->import_globals[global_index];
|
||||||
|
import_type->module_name = aot_import_global->module_name;
|
||||||
|
import_type->name = aot_import_global->global_name;
|
||||||
|
import_type->kind = WASM_IMPORT_EXPORT_KIND_GLOBAL;
|
||||||
|
import_type->linked = aot_import_global->is_linked;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 table_index = global_index - aot_module->import_global_count;
|
||||||
|
if (table_index < aot_module->import_table_count) {
|
||||||
|
const AOTImportTable *aot_import_table =
|
||||||
|
&aot_module->import_tables[table_index];
|
||||||
|
import_type->module_name = aot_import_table->module_name;
|
||||||
|
import_type->name = aot_import_table->table_name;
|
||||||
|
import_type->kind = WASM_IMPORT_EXPORT_KIND_TABLE;
|
||||||
|
import_type->linked = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 memory_index = table_index - aot_module->import_table_count;
|
||||||
|
if (memory_index < aot_module->import_memory_count) {
|
||||||
|
const AOTImportMemory *aot_import_memory =
|
||||||
|
&aot_module->import_memories[memory_index];
|
||||||
|
import_type->module_name = aot_import_memory->module_name;
|
||||||
|
import_type->name = aot_import_memory->memory_name;
|
||||||
|
import_type->kind = WASM_IMPORT_EXPORT_KIND_MEMORY;
|
||||||
|
import_type->linked = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bh_assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_INTERP != 0
|
||||||
|
if (module->module_type == Wasm_Module_Bytecode) {
|
||||||
|
const WASMModule *wasm_module = (const WASMModule *)module;
|
||||||
|
|
||||||
|
if ((uint32)import_index >= wasm_module->import_count) {
|
||||||
|
bh_assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WASMImport *wasm_import = &wasm_module->imports[import_index];
|
||||||
|
|
||||||
|
import_type->module_name = wasm_import->u.names.module_name;
|
||||||
|
import_type->name = wasm_import->u.names.field_name;
|
||||||
|
import_type->kind = wasm_import->kind;
|
||||||
|
switch (import_type->kind) {
|
||||||
|
case WASM_IMPORT_EXPORT_KIND_FUNC:
|
||||||
|
import_type->linked = wasm_import->u.function.func_ptr_linked;
|
||||||
|
break;
|
||||||
|
case WASM_IMPORT_EXPORT_KIND_GLOBAL:
|
||||||
|
import_type->linked = wasm_import->u.global.is_linked;
|
||||||
|
break;
|
||||||
|
case WASM_IMPORT_EXPORT_KIND_TABLE:
|
||||||
|
/* not supported */
|
||||||
|
import_type->linked = false;
|
||||||
|
break;
|
||||||
|
case WASM_IMPORT_EXPORT_KIND_MEMORY:
|
||||||
|
/* not supported */
|
||||||
|
import_type->linked = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bh_assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
wasm_runtime_get_export_count(WASMModuleCommon *const module)
|
||||||
|
{
|
||||||
|
if (!module) {
|
||||||
|
bh_assert(0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_AOT != 0
|
||||||
|
if (module->module_type == Wasm_Module_AoT) {
|
||||||
|
const AOTModule *aot_module = (const AOTModule *)module;
|
||||||
|
return (int32)aot_module->export_count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_INTERP != 0
|
||||||
|
if (module->module_type == Wasm_Module_Bytecode) {
|
||||||
|
const WASMModule *wasm_module = (const WASMModule *)module;
|
||||||
|
return (int32)wasm_module->export_count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index,
|
||||||
|
wasm_export_type *export_type)
|
||||||
|
{
|
||||||
|
if (!export_type) {
|
||||||
|
bh_assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(export_type, 0, sizeof(wasm_export_type));
|
||||||
|
|
||||||
|
if (!module) {
|
||||||
|
bh_assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_AOT != 0
|
||||||
|
if (module->module_type == Wasm_Module_AoT) {
|
||||||
|
const AOTModule *aot_module = (const AOTModule *)module;
|
||||||
|
|
||||||
|
if ((uint32)export_index >= aot_module->export_count) {
|
||||||
|
bh_assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AOTExport *aot_export = &aot_module->exports[export_index];
|
||||||
|
export_type->name = aot_export->name;
|
||||||
|
export_type->kind = aot_export->kind;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if WASM_ENABLE_INTERP != 0
|
||||||
|
if (module->module_type == Wasm_Module_Bytecode) {
|
||||||
|
const WASMModule *wasm_module = (const WASMModule *)module;
|
||||||
|
|
||||||
|
if ((uint32)export_index >= wasm_module->export_count) {
|
||||||
|
bh_assert(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WASMExport *wasm_export = &wasm_module->exports[export_index];
|
||||||
|
export_type->name = wasm_export->name;
|
||||||
|
export_type->kind = wasm_export->kind;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm_runtime_register_natives(const char *module_name,
|
wasm_runtime_register_natives(const char *module_name,
|
||||||
NativeSymbol *native_symbols,
|
NativeSymbol *native_symbols,
|
||||||
|
|
|
@ -484,15 +484,15 @@ static uint32
|
||||||
get_func_type_size(AOTCompContext *comp_ctx, AOTFuncType *func_type)
|
get_func_type_size(AOTCompContext *comp_ctx, AOTFuncType *func_type)
|
||||||
{
|
{
|
||||||
#if WASM_ENABLE_GC != 0
|
#if WASM_ENABLE_GC != 0
|
||||||
/* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx + param
|
/* type flag + equivalence type flag + is_sub_final + parent_type_idx
|
||||||
* count + result count
|
+ rec_count + rec_idx + param count + result count
|
||||||
* + ref_type_map_count + types + context of ref_type_map */
|
+ ref_type_map_count + types + context of ref_type_map */
|
||||||
if (comp_ctx->enable_gc) {
|
if (comp_ctx->enable_gc) {
|
||||||
uint32 size = 0;
|
uint32 size = 0;
|
||||||
|
|
||||||
/* type flag */
|
/* type flag */
|
||||||
size += sizeof(func_type->base_type.type_flag);
|
size += sizeof(func_type->base_type.type_flag);
|
||||||
/* is_sub_final */
|
/* equivalence type flag + is_sub_final */
|
||||||
size += sizeof(uint16);
|
size += sizeof(uint16);
|
||||||
/* parent_type_idx */
|
/* parent_type_idx */
|
||||||
size += sizeof(func_type->base_type.parent_type_idx);
|
size += sizeof(func_type->base_type.parent_type_idx);
|
||||||
|
@ -529,12 +529,12 @@ static uint32
|
||||||
get_struct_type_size(AOTCompContext *comp_ctx, AOTStructType *struct_type)
|
get_struct_type_size(AOTCompContext *comp_ctx, AOTStructType *struct_type)
|
||||||
{
|
{
|
||||||
uint32 size = 0;
|
uint32 size = 0;
|
||||||
/* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx + field
|
/* type flag + equivalence type flag + is_sub_final + parent_type_idx
|
||||||
* count + fields */
|
+ rec_count + rec_idx + field count + fields */
|
||||||
|
|
||||||
/* type flag */
|
/* type flag */
|
||||||
size += sizeof(struct_type->base_type.type_flag);
|
size += sizeof(struct_type->base_type.type_flag);
|
||||||
/* is_sub_final */
|
/* equivalence type flag + is_sub_final */
|
||||||
size += sizeof(uint16);
|
size += sizeof(uint16);
|
||||||
/* parent_type_idx */
|
/* parent_type_idx */
|
||||||
size += sizeof(struct_type->base_type.parent_type_idx);
|
size += sizeof(struct_type->base_type.parent_type_idx);
|
||||||
|
@ -558,12 +558,12 @@ static uint32
|
||||||
get_array_type_size(AOTCompContext *comp_ctx, AOTArrayType *array_type)
|
get_array_type_size(AOTCompContext *comp_ctx, AOTArrayType *array_type)
|
||||||
{
|
{
|
||||||
uint32 size = 0;
|
uint32 size = 0;
|
||||||
/* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx +
|
/* type flag + equivalence type flag + is_sub_final + parent_type_idx
|
||||||
elem_flags + elem_type + elem_ref_type */
|
+ rec_count + rec_idx + elem_flags + elem_type + elem_ref_type */
|
||||||
|
|
||||||
/* type flag */
|
/* type flag */
|
||||||
size += sizeof(array_type->base_type.type_flag);
|
size += sizeof(array_type->base_type.type_flag);
|
||||||
/* is_sub_final */
|
/* equivalence type flag + is_sub_final */
|
||||||
size += sizeof(uint16);
|
size += sizeof(uint16);
|
||||||
/* parent_type_idx (u32) */
|
/* parent_type_idx (u32) */
|
||||||
size += sizeof(array_type->base_type.parent_type_idx);
|
size += sizeof(array_type->base_type.parent_type_idx);
|
||||||
|
@ -597,7 +597,22 @@ get_type_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
|
||||||
#if WASM_ENABLE_GC != 0
|
#if WASM_ENABLE_GC != 0
|
||||||
if (comp_ctx->enable_gc) {
|
if (comp_ctx->enable_gc) {
|
||||||
for (i = 0; i < comp_data->type_count; i++) {
|
for (i = 0; i < comp_data->type_count; i++) {
|
||||||
|
uint32 j;
|
||||||
|
|
||||||
size = align_uint(size, 4);
|
size = align_uint(size, 4);
|
||||||
|
|
||||||
|
/* Emit simple info if there is an equivalence type */
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
if (comp_data->types[j] == comp_data->types[i]) {
|
||||||
|
/* type_flag (2 bytes) + equivalence type flag (1 byte)
|
||||||
|
+ padding (1 byte) + equivalence type index */
|
||||||
|
size += 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j < i)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (comp_data->types[i]->type_flag == WASM_TYPE_FUNC)
|
if (comp_data->types[i]->type_flag == WASM_TYPE_FUNC)
|
||||||
size += get_func_type_size(comp_ctx,
|
size += get_func_type_size(comp_ctx,
|
||||||
(AOTFuncType *)comp_data->types[i]);
|
(AOTFuncType *)comp_data->types[i]);
|
||||||
|
@ -2093,13 +2108,32 @@ aot_emit_type_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||||
|
|
||||||
#if WASM_ENABLE_GC != 0
|
#if WASM_ENABLE_GC != 0
|
||||||
if (comp_ctx->enable_gc) {
|
if (comp_ctx->enable_gc) {
|
||||||
int32 idx;
|
|
||||||
AOTType **types = comp_data->types;
|
AOTType **types = comp_data->types;
|
||||||
|
int32 idx;
|
||||||
|
uint32 j;
|
||||||
|
|
||||||
for (i = 0; i < comp_data->type_count; i++) {
|
for (i = 0; i < comp_data->type_count; i++) {
|
||||||
offset = align_uint(offset, 4);
|
offset = align_uint(offset, 4);
|
||||||
|
|
||||||
|
/* Emit simple info if there is an equivalence type */
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
if (types[j] == types[i]) {
|
||||||
|
EMIT_U16(types[i]->type_flag);
|
||||||
|
/* equivalence type flag is true */
|
||||||
|
EMIT_U8(1);
|
||||||
|
EMIT_U8(0);
|
||||||
|
/* equivalence type index */
|
||||||
|
EMIT_U32(j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j < i)
|
||||||
|
continue;
|
||||||
|
|
||||||
EMIT_U16(types[i]->type_flag);
|
EMIT_U16(types[i]->type_flag);
|
||||||
EMIT_U16(types[i]->is_sub_final);
|
/* equivalence type flag is false */
|
||||||
|
EMIT_U8(0);
|
||||||
|
EMIT_U8(types[i]->is_sub_final);
|
||||||
EMIT_U32(types[i]->parent_type_idx);
|
EMIT_U32(types[i]->parent_type_idx);
|
||||||
|
|
||||||
EMIT_U16(types[i]->rec_count);
|
EMIT_U16(types[i]->rec_count);
|
||||||
|
@ -2593,7 +2627,7 @@ aot_emit_func_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||||
if (comp_ctx->enable_gc) {
|
if (comp_ctx->enable_gc) {
|
||||||
/* emit func_local_ref_flag arrays for both import and AOTed funcs */
|
/* emit func_local_ref_flag arrays for both import and AOTed funcs */
|
||||||
AOTFuncType *func_type;
|
AOTFuncType *func_type;
|
||||||
uint32 j, local_ref_flags_cell_num;
|
uint32 j, local_ref_flags_cell_num, paddings;
|
||||||
|
|
||||||
for (i = 0; i < comp_data->import_func_count; i++) {
|
for (i = 0; i < comp_data->import_func_count; i++) {
|
||||||
func_type = comp_data->import_funcs[i].func_type;
|
func_type = comp_data->import_funcs[i].func_type;
|
||||||
|
@ -2603,6 +2637,8 @@ aot_emit_func_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||||
local_ref_flags_cell_num += wasm_value_type_cell_num_internal(
|
local_ref_flags_cell_num += wasm_value_type_cell_num_internal(
|
||||||
func_type->types[j], comp_ctx->pointer_size);
|
func_type->types[j], comp_ctx->pointer_size);
|
||||||
}
|
}
|
||||||
|
paddings =
|
||||||
|
local_ref_flags_cell_num < 2 ? 2 - local_ref_flags_cell_num : 0;
|
||||||
local_ref_flags_cell_num =
|
local_ref_flags_cell_num =
|
||||||
local_ref_flags_cell_num > 2 ? local_ref_flags_cell_num : 2;
|
local_ref_flags_cell_num > 2 ? local_ref_flags_cell_num : 2;
|
||||||
|
|
||||||
|
@ -2614,7 +2650,7 @@ aot_emit_func_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
|
||||||
func_type->types[j]))
|
func_type->types[j]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (; j < 2; j++)
|
for (j = 0; j < paddings; j++)
|
||||||
EMIT_U8(0);
|
EMIT_U8(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1826,6 +1826,52 @@ fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_GC != 0
|
||||||
|
static LLVMValueRef
|
||||||
|
call_aot_func_type_is_super_of_func(AOTCompContext *comp_ctx,
|
||||||
|
AOTFuncContext *func_ctx,
|
||||||
|
LLVMValueRef type_idx1,
|
||||||
|
LLVMValueRef type_idx2)
|
||||||
|
{
|
||||||
|
LLVMValueRef param_values[3], ret_value, value, func;
|
||||||
|
LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
|
||||||
|
|
||||||
|
param_types[0] = comp_ctx->aot_inst_type;
|
||||||
|
param_types[1] = I32_TYPE;
|
||||||
|
param_types[2] = I32_TYPE;
|
||||||
|
ret_type = INT8_TYPE;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_JIT != 0
|
||||||
|
if (comp_ctx->is_jit_mode)
|
||||||
|
GET_AOT_FUNCTION(llvm_jit_func_type_is_super_of, 3);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
GET_AOT_FUNCTION(aot_func_type_is_super_of, 3);
|
||||||
|
|
||||||
|
param_values[0] = func_ctx->aot_inst;
|
||||||
|
param_values[1] = type_idx1;
|
||||||
|
param_values[2] = type_idx2;
|
||||||
|
|
||||||
|
if (!(ret_value =
|
||||||
|
LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values,
|
||||||
|
3, "call_aot_func_type_is_super_of"))) {
|
||||||
|
aot_set_last_error("llvm build call failed.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ret_value = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, ret_value,
|
||||||
|
I8_ZERO, "check_fail"))) {
|
||||||
|
aot_set_last_error("llvm build icmp failed.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_value;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
AOTFuncType *aot_func_type,
|
AOTFuncType *aot_func_type,
|
||||||
|
@ -2018,15 +2064,23 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the equivalent function type whose type index is the smallest:
|
if (!comp_ctx->enable_gc) {
|
||||||
the callee function's type index is also converted to the smallest
|
/* Find the equivalent function type whose type index is the smallest:
|
||||||
one in wasm loader, so we can just check whether the two type indexes
|
the callee function's type index is also converted to the smallest
|
||||||
are equal (the type index of call_indirect opcode and callee func),
|
one in wasm loader, so we can just check whether the two type indexes
|
||||||
we don't need to check whether the whole function types are equal,
|
are equal (the type index of call_indirect opcode and callee func),
|
||||||
including param types and result types. */
|
we don't need to check whether the whole function types are equal,
|
||||||
type_idx =
|
including param types and result types. */
|
||||||
wasm_get_smallest_type_idx((WASMTypePtr *)comp_ctx->comp_data->types,
|
type_idx = wasm_get_smallest_type_idx(
|
||||||
comp_ctx->comp_data->type_count, type_idx);
|
(WASMTypePtr *)comp_ctx->comp_data->types,
|
||||||
|
comp_ctx->comp_data->type_count, type_idx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Call aot_func_type_is_super_of to check whether the func type
|
||||||
|
provided in the bytecode is a super type of the func type of
|
||||||
|
the function to call */
|
||||||
|
}
|
||||||
|
|
||||||
ftype_idx_const = I32_CONST(type_idx);
|
ftype_idx_const = I32_CONST(type_idx);
|
||||||
CHECK_LLVM_CONST(ftype_idx_const);
|
CHECK_LLVM_CONST(ftype_idx_const);
|
||||||
|
|
||||||
|
@ -2254,11 +2308,23 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if function type index not equal */
|
#if WASM_ENABLE_GC != 0
|
||||||
if (!(cmp_ftype_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, ftype_idx,
|
if (comp_ctx->enable_gc) {
|
||||||
ftype_idx_const, "cmp_ftype_idx"))) {
|
if (!(cmp_ftype_idx = call_aot_func_type_is_super_of_func(
|
||||||
aot_set_last_error("llvm build icmp failed.");
|
comp_ctx, func_ctx, ftype_idx_const, ftype_idx))) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Check if function type index not equal */
|
||||||
|
if (!(cmp_ftype_idx =
|
||||||
|
LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, ftype_idx,
|
||||||
|
ftype_idx_const, "cmp_ftype_idx"))) {
|
||||||
|
aot_set_last_error("llvm build icmp failed.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Throw exception if ftype_idx != ftype_idx_const */
|
/* Throw exception if ftype_idx != ftype_idx_const */
|
||||||
|
|
|
@ -69,6 +69,25 @@ struct WASMModuleCommon;
|
||||||
typedef struct WASMModuleCommon *wasm_module_t;
|
typedef struct WASMModuleCommon *wasm_module_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WASM_IMPORT_EXPORT_KIND_FUNC,
|
||||||
|
WASM_IMPORT_EXPORT_KIND_TABLE,
|
||||||
|
WASM_IMPORT_EXPORT_KIND_MEMORY,
|
||||||
|
WASM_IMPORT_EXPORT_KIND_GLOBAL
|
||||||
|
} wasm_import_export_kind_t;
|
||||||
|
|
||||||
|
typedef struct wasm_import_type {
|
||||||
|
const char *module_name;
|
||||||
|
const char *name;
|
||||||
|
wasm_import_export_kind_t kind;
|
||||||
|
bool linked;
|
||||||
|
} wasm_import_type;
|
||||||
|
|
||||||
|
typedef struct wasm_export_type {
|
||||||
|
const char *name;
|
||||||
|
wasm_import_export_kind_t kind;
|
||||||
|
} wasm_export_type;
|
||||||
|
|
||||||
/* Instantiated WASM module */
|
/* Instantiated WASM module */
|
||||||
struct WASMModuleInstanceCommon;
|
struct WASMModuleInstanceCommon;
|
||||||
typedef struct WASMModuleInstanceCommon *wasm_module_inst_t;
|
typedef struct WASMModuleInstanceCommon *wasm_module_inst_t;
|
||||||
|
@ -113,6 +132,11 @@ typedef enum {
|
||||||
Alloc_With_System_Allocator,
|
Alloc_With_System_Allocator,
|
||||||
} mem_alloc_type_t;
|
} mem_alloc_type_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Alloc_For_Runtime,
|
||||||
|
Alloc_For_LinearMemory
|
||||||
|
} mem_alloc_usage_t;
|
||||||
|
|
||||||
/* Memory allocator option */
|
/* Memory allocator option */
|
||||||
typedef union MemAllocOption {
|
typedef union MemAllocOption {
|
||||||
struct {
|
struct {
|
||||||
|
@ -120,6 +144,9 @@ typedef union MemAllocOption {
|
||||||
uint32_t heap_size;
|
uint32_t heap_size;
|
||||||
} pool;
|
} pool;
|
||||||
struct {
|
struct {
|
||||||
|
/* the function signature is varied when
|
||||||
|
WASM_MEM_ALLOC_WITH_USER_DATA and
|
||||||
|
WASM_MEM_ALLOC_WITH_USAGE are defined */
|
||||||
void *malloc_func;
|
void *malloc_func;
|
||||||
void *realloc_func;
|
void *realloc_func;
|
||||||
void *free_func;
|
void *free_func;
|
||||||
|
@ -1197,6 +1224,48 @@ wasm_runtime_get_native_addr_range(wasm_module_inst_t module_inst,
|
||||||
uint8_t **p_native_start_addr,
|
uint8_t **p_native_start_addr,
|
||||||
uint8_t **p_native_end_addr);
|
uint8_t **p_native_end_addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of import items for a WASM module
|
||||||
|
*
|
||||||
|
* @param module the WASM module
|
||||||
|
*
|
||||||
|
* @return the number of imports (zero for none), or -1 for failure
|
||||||
|
*/
|
||||||
|
WASM_RUNTIME_API_EXTERN int32_t
|
||||||
|
wasm_runtime_get_import_count(const wasm_module_t module);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information about a specific WASM module import
|
||||||
|
*
|
||||||
|
* @param module the WASM module
|
||||||
|
* @param import_index the desired import index
|
||||||
|
* @param import_type the location to store information about the import
|
||||||
|
*/
|
||||||
|
WASM_RUNTIME_API_EXTERN void
|
||||||
|
wasm_runtime_get_import_type(const wasm_module_t module, int32_t import_index,
|
||||||
|
wasm_import_type *import_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of export items for a WASM module
|
||||||
|
*
|
||||||
|
* @param module the WASM module
|
||||||
|
*
|
||||||
|
* @return the number of exports (zero for none), or -1 for failure
|
||||||
|
*/
|
||||||
|
WASM_RUNTIME_API_EXTERN int32_t
|
||||||
|
wasm_runtime_get_export_count(const wasm_module_t module);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information about a specific WASM module export
|
||||||
|
*
|
||||||
|
* @param module the WASM module
|
||||||
|
* @param export_index the desired export index
|
||||||
|
* @param export_type the location to store information about the export
|
||||||
|
*/
|
||||||
|
WASM_RUNTIME_API_EXTERN void
|
||||||
|
wasm_runtime_get_export_type(const wasm_module_t module, int32_t export_index,
|
||||||
|
wasm_export_type *export_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register native functions with same module name
|
* Register native functions with same module name
|
||||||
*
|
*
|
||||||
|
|
|
@ -274,7 +274,7 @@ typedef struct InitializerExpression {
|
||||||
*/
|
*/
|
||||||
typedef struct RefHeapType_TypeIdx {
|
typedef struct RefHeapType_TypeIdx {
|
||||||
/* ref_type is REF_TYPE_HT_NULLABLE or
|
/* ref_type is REF_TYPE_HT_NULLABLE or
|
||||||
REF_TYPE_HT_NON_NULLABLE, (0x6C or 0x6B) */
|
REF_TYPE_HT_NON_NULLABLE, (0x63 or 0x64) */
|
||||||
uint8 ref_type;
|
uint8 ref_type;
|
||||||
/* true if ref_type is REF_TYPE_HT_NULLABLE */
|
/* true if ref_type is REF_TYPE_HT_NULLABLE */
|
||||||
bool nullable;
|
bool nullable;
|
||||||
|
@ -288,7 +288,7 @@ typedef struct RefHeapType_TypeIdx {
|
||||||
*/
|
*/
|
||||||
typedef struct RefHeapType_Common {
|
typedef struct RefHeapType_Common {
|
||||||
/* ref_type is REF_TYPE_HT_NULLABLE or
|
/* ref_type is REF_TYPE_HT_NULLABLE or
|
||||||
REF_TYPE_HT_NON_NULLABLE (0x6C or 0x6B) */
|
REF_TYPE_HT_NON_NULLABLE (0x63 or 0x64) */
|
||||||
uint8 ref_type;
|
uint8 ref_type;
|
||||||
/* true if ref_type is REF_TYPE_HT_NULLABLE */
|
/* true if ref_type is REF_TYPE_HT_NULLABLE */
|
||||||
bool nullable;
|
bool nullable;
|
||||||
|
@ -338,18 +338,24 @@ typedef struct WASMType {
|
||||||
uint16 type_flag;
|
uint16 type_flag;
|
||||||
|
|
||||||
bool is_sub_final;
|
bool is_sub_final;
|
||||||
|
/* How many types are referring to this type */
|
||||||
|
uint16 ref_count;
|
||||||
/* The inheritance depth */
|
/* The inheritance depth */
|
||||||
uint32 inherit_depth;
|
uint16 inherit_depth;
|
||||||
/* The root type */
|
/* The root type */
|
||||||
struct WASMType *root_type;
|
struct WASMType *root_type;
|
||||||
/* The parent type */
|
/* The parent type */
|
||||||
struct WASMType *parent_type;
|
struct WASMType *parent_type;
|
||||||
uint32 parent_type_idx;
|
uint32 parent_type_idx;
|
||||||
|
|
||||||
/* number of internal types in the current rec group, if the type is not in
|
/* The number of internal types in the current rec group, and if
|
||||||
* a recursive group, rec_count = 0 */
|
the type is not in a recursive group, rec_count is 1 since a
|
||||||
|
single type definition is reinterpreted as a short-hand for a
|
||||||
|
recursive group containing just one type */
|
||||||
uint16 rec_count;
|
uint16 rec_count;
|
||||||
uint16 rec_idx;
|
uint16 rec_idx;
|
||||||
|
/* The index of the begin type of this group */
|
||||||
|
uint32 rec_begin_type_idx;
|
||||||
} WASMType, *WASMTypePtr;
|
} WASMType, *WASMTypePtr;
|
||||||
#endif /* end of WASM_ENABLE_GC */
|
#endif /* end of WASM_ENABLE_GC */
|
||||||
|
|
||||||
|
@ -375,9 +381,6 @@ typedef struct WASMFuncType {
|
||||||
uint16 ref_type_map_count;
|
uint16 ref_type_map_count;
|
||||||
WASMRefTypeMap *ref_type_maps;
|
WASMRefTypeMap *ref_type_maps;
|
||||||
WASMRefTypeMap *result_ref_type_maps;
|
WASMRefTypeMap *result_ref_type_maps;
|
||||||
/* minimal type index of the type equal to this type,
|
|
||||||
used in type equal check in call_indirect opcode */
|
|
||||||
uint32 min_type_idx_normalized;
|
|
||||||
#else
|
#else
|
||||||
uint16 ref_count;
|
uint16 ref_count;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2212,6 +2212,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
WASMFuncType *cur_type, *cur_func_type;
|
WASMFuncType *cur_type, *cur_func_type;
|
||||||
WASMTableInstance *tbl_inst;
|
WASMTableInstance *tbl_inst;
|
||||||
uint32 tbl_idx;
|
uint32 tbl_idx;
|
||||||
|
|
||||||
#if WASM_ENABLE_TAIL_CALL != 0
|
#if WASM_ENABLE_TAIL_CALL != 0
|
||||||
opcode = *(frame_ip - 1);
|
opcode = *(frame_ip - 1);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2282,8 +2283,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (cur_type->min_type_idx_normalized
|
if (!wasm_func_type_is_super_of(cur_type, cur_func_type)) {
|
||||||
!= cur_func_type->min_type_idx_normalized) {
|
|
||||||
wasm_set_exception(module, "indirect call type mismatch");
|
wasm_set_exception(module, "indirect call type mismatch");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
|
@ -4202,7 +4202,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
*(uint32 *)global_addr = aux_stack_top;
|
*(uint32 *)global_addr = (uint32)aux_stack_top;
|
||||||
frame_sp--;
|
frame_sp--;
|
||||||
}
|
}
|
||||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||||
|
|
|
@ -1736,8 +1736,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (cur_type->min_type_idx_normalized
|
if (!wasm_func_type_is_super_of(cur_type, cur_func_type)) {
|
||||||
!= cur_func_type->min_type_idx_normalized) {
|
|
||||||
wasm_set_exception(module, "indirect call type mismatch");
|
wasm_set_exception(module, "indirect call type mismatch");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,21 @@
|
||||||
#define TEMPLATE_READ_VALUE(Type, p) \
|
#define TEMPLATE_READ_VALUE(Type, p) \
|
||||||
(p += sizeof(Type), *(Type *)(p - sizeof(Type)))
|
(p += sizeof(Type), *(Type *)(p - sizeof(Type)))
|
||||||
|
|
||||||
|
#if WASM_ENABLE_MEMORY64 != 0
|
||||||
|
static bool
|
||||||
|
has_module_memory64(WASMModule *module)
|
||||||
|
{
|
||||||
|
/* TODO: multi-memories for now assuming the memory idx type is consistent
|
||||||
|
* across multi-memories */
|
||||||
|
if (module->import_memory_count > 0)
|
||||||
|
return !!(module->import_memories[0].u.memory.flags & MEMORY64_FLAG);
|
||||||
|
else if (module->memory_count > 0)
|
||||||
|
return !!(module->memories[0].flags & MEMORY64_FLAG);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
||||||
{
|
{
|
||||||
|
@ -394,10 +409,10 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
|
||||||
|
|
||||||
#if WASM_ENABLE_GC != 0
|
#if WASM_ENABLE_GC != 0
|
||||||
static bool
|
static bool
|
||||||
check_type_index(const WASMModule *module, uint32 type_index, char *error_buf,
|
check_type_index(const WASMModule *module, uint32 type_count, uint32 type_index,
|
||||||
uint32 error_buf_size)
|
char *error_buf, uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
if (type_index >= module->type_count) {
|
if (type_index >= type_count) {
|
||||||
set_error_buf_v(error_buf, error_buf_size, "unknown type %d",
|
set_error_buf_v(error_buf, error_buf_size, "unknown type %d",
|
||||||
type_index);
|
type_index);
|
||||||
return false;
|
return false;
|
||||||
|
@ -409,7 +424,8 @@ static bool
|
||||||
check_array_type(const WASMModule *module, uint32 type_index, char *error_buf,
|
check_array_type(const WASMModule *module, uint32 type_index, char *error_buf,
|
||||||
uint32 error_buf_size)
|
uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
if (!check_type_index(module, type_index, error_buf, error_buf_size)) {
|
if (!check_type_index(module, module->type_count, type_index, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (module->types[type_index]->type_flag != WASM_TYPE_ARRAY) {
|
if (module->types[type_index]->type_flag != WASM_TYPE_ARRAY) {
|
||||||
|
@ -775,8 +791,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
||||||
if (!is_byte_a_type(type1)) {
|
if (!is_byte_a_type(type1)) {
|
||||||
p--;
|
p--;
|
||||||
read_leb_uint32(p, p_end, type_idx);
|
read_leb_uint32(p, p_end, type_idx);
|
||||||
if (!check_type_index(module, type_idx, error_buf,
|
if (!check_type_index(module, module->type_count, type_idx,
|
||||||
error_buf_size))
|
error_buf, error_buf_size))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
wasm_set_refheaptype_typeidx(&cur_ref_type.ref_ht_typeidx,
|
wasm_set_refheaptype_typeidx(&cur_ref_type.ref_ht_typeidx,
|
||||||
|
@ -902,7 +918,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
||||||
uint32 field_count;
|
uint32 field_count;
|
||||||
read_leb_uint32(p, p_end, type_idx);
|
read_leb_uint32(p, p_end, type_idx);
|
||||||
|
|
||||||
if (!check_type_index(module, type_idx, error_buf,
|
if (!check_type_index(module, module->type_count,
|
||||||
|
type_idx, error_buf,
|
||||||
error_buf_size)) {
|
error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -966,7 +983,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
||||||
read_leb_uint32(p, p_end, cur_value.type_index);
|
read_leb_uint32(p, p_end, cur_value.type_index);
|
||||||
type_idx = cur_value.type_index;
|
type_idx = cur_value.type_index;
|
||||||
|
|
||||||
if (!check_type_index(module, type_idx, error_buf,
|
if (!check_type_index(module, module->type_count,
|
||||||
|
type_idx, error_buf,
|
||||||
error_buf_size)) {
|
error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -1001,7 +1019,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
||||||
read_leb_uint32(p, p_end, cur_value.type_index);
|
read_leb_uint32(p, p_end, cur_value.type_index);
|
||||||
type_idx = cur_value.type_index;
|
type_idx = cur_value.type_index;
|
||||||
|
|
||||||
if (!check_type_index(module, type_idx, error_buf,
|
if (!check_type_index(module, module->type_count,
|
||||||
|
type_idx, error_buf,
|
||||||
error_buf_size)) {
|
error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -1275,6 +1294,13 @@ destroy_array_type(WASMArrayType *type)
|
||||||
static void
|
static void
|
||||||
destroy_wasm_type(WASMType *type)
|
destroy_wasm_type(WASMType *type)
|
||||||
{
|
{
|
||||||
|
if (type->ref_count > 1) {
|
||||||
|
/* The type is referenced by other types
|
||||||
|
of current wasm module */
|
||||||
|
type->ref_count--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (type->type_flag == WASM_TYPE_FUNC)
|
if (type->type_flag == WASM_TYPE_FUNC)
|
||||||
destroy_func_type((WASMFuncType *)type);
|
destroy_func_type((WASMFuncType *)type);
|
||||||
else if (type->type_flag == WASM_TYPE_STRUCT)
|
else if (type->type_flag == WASM_TYPE_STRUCT)
|
||||||
|
@ -1289,8 +1315,9 @@ destroy_wasm_type(WASMType *type)
|
||||||
/* Resolve (ref null ht) or (ref ht) */
|
/* Resolve (ref null ht) or (ref ht) */
|
||||||
static bool
|
static bool
|
||||||
resolve_reftype_htref(const uint8 **p_buf, const uint8 *buf_end,
|
resolve_reftype_htref(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
WASMModule *module, bool nullable, WASMRefType *ref_type,
|
WASMModule *module, uint32 type_count, bool nullable,
|
||||||
char *error_buf, uint32 error_buf_size)
|
WASMRefType *ref_type, char *error_buf,
|
||||||
|
uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
const uint8 *p = *p_buf, *p_end = buf_end;
|
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||||
|
|
||||||
|
@ -1301,8 +1328,9 @@ resolve_reftype_htref(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
|
|
||||||
if (wasm_is_refheaptype_typeidx(&ref_type->ref_ht_common)) {
|
if (wasm_is_refheaptype_typeidx(&ref_type->ref_ht_common)) {
|
||||||
/* heap type is (type i), i : typeidx, >= 0 */
|
/* heap type is (type i), i : typeidx, >= 0 */
|
||||||
if (!check_type_index(module, ref_type->ref_ht_typeidx.type_idx,
|
if (!check_type_index(module, type_count,
|
||||||
error_buf, error_buf_size)) {
|
ref_type->ref_ht_typeidx.type_idx, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1320,9 +1348,10 @@ fail:
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
|
resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
WASMModule *module, bool *p_need_ref_type_map,
|
WASMModule *module, uint32 type_count,
|
||||||
WASMRefType *ref_type, bool allow_packed_type,
|
bool *p_need_ref_type_map, WASMRefType *ref_type,
|
||||||
char *error_buf, uint32 error_buf_size)
|
bool allow_packed_type, char *error_buf,
|
||||||
|
uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
const uint8 *p = *p_buf, *p_end = buf_end;
|
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||||
uint8 type;
|
uint8 type;
|
||||||
|
@ -1334,8 +1363,8 @@ resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
|
|
||||||
if (wasm_is_reftype_htref_nullable(type)) {
|
if (wasm_is_reftype_htref_nullable(type)) {
|
||||||
/* (ref null ht) */
|
/* (ref null ht) */
|
||||||
if (!resolve_reftype_htref(&p, p_end, module, true, ref_type, error_buf,
|
if (!resolve_reftype_htref(&p, p_end, module, type_count, true,
|
||||||
error_buf_size))
|
ref_type, error_buf, error_buf_size))
|
||||||
return false;
|
return false;
|
||||||
if (!wasm_is_refheaptype_common(&ref_type->ref_ht_common))
|
if (!wasm_is_refheaptype_common(&ref_type->ref_ht_common))
|
||||||
*p_need_ref_type_map = true;
|
*p_need_ref_type_map = true;
|
||||||
|
@ -1351,8 +1380,8 @@ resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
}
|
}
|
||||||
else if (wasm_is_reftype_htref_non_nullable(type)) {
|
else if (wasm_is_reftype_htref_non_nullable(type)) {
|
||||||
/* (ref ht) */
|
/* (ref ht) */
|
||||||
if (!resolve_reftype_htref(&p, p_end, module, false, ref_type,
|
if (!resolve_reftype_htref(&p, p_end, module, type_count, false,
|
||||||
error_buf, error_buf_size))
|
ref_type, error_buf, error_buf_size))
|
||||||
return false;
|
return false;
|
||||||
*p_need_ref_type_map = true;
|
*p_need_ref_type_map = true;
|
||||||
#if WASM_ENABLE_STRINGREF != 0
|
#if WASM_ENABLE_STRINGREF != 0
|
||||||
|
@ -1401,7 +1430,8 @@ reftype_set_insert(HashMap *ref_type_set, const WASMRefType *ref_type,
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
||||||
uint32 type_idx, char *error_buf, uint32 error_buf_size)
|
uint32 type_count, uint32 type_idx, char *error_buf,
|
||||||
|
uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
|
const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
|
||||||
uint32 param_count, result_count, i, j = 0;
|
uint32 param_count, result_count, i, j = 0;
|
||||||
|
@ -1417,8 +1447,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
||||||
read_leb_uint32(p, p_end, param_count);
|
read_leb_uint32(p, p_end, param_count);
|
||||||
p_org = p;
|
p_org = p;
|
||||||
for (i = 0; i < param_count; i++) {
|
for (i = 0; i < param_count; i++) {
|
||||||
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
if (!resolve_value_type(&p, p_end, module, type_count,
|
||||||
&ref_type, false, error_buf, error_buf_size)) {
|
&need_ref_type_map, &ref_type, false, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (need_ref_type_map)
|
if (need_ref_type_map)
|
||||||
|
@ -1427,8 +1458,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
||||||
|
|
||||||
read_leb_uint32(p, p_end, result_count);
|
read_leb_uint32(p, p_end, result_count);
|
||||||
for (i = 0; i < result_count; i++) {
|
for (i = 0; i < result_count; i++) {
|
||||||
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
if (!resolve_value_type(&p, p_end, module, type_count,
|
||||||
&ref_type, false, error_buf, error_buf_size)) {
|
&need_ref_type_map, &ref_type, false, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (need_ref_type_map) {
|
if (need_ref_type_map) {
|
||||||
|
@ -1468,8 +1500,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < param_count; i++) {
|
for (i = 0; i < param_count; i++) {
|
||||||
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
if (!resolve_value_type(&p, p_end, module, type_count,
|
||||||
&ref_type, false, error_buf, error_buf_size)) {
|
&need_ref_type_map, &ref_type, false, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
type->types[i] = ref_type.ref_type;
|
type->types[i] = ref_type.ref_type;
|
||||||
|
@ -1485,8 +1518,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
||||||
|
|
||||||
read_leb_uint32(p, p_end, result_count);
|
read_leb_uint32(p, p_end, result_count);
|
||||||
for (i = 0; i < result_count; i++) {
|
for (i = 0; i < result_count; i++) {
|
||||||
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
if (!resolve_value_type(&p, p_end, module, type_count,
|
||||||
&ref_type, false, error_buf, error_buf_size)) {
|
&need_ref_type_map, &ref_type, false, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
type->types[param_count + i] = ref_type.ref_type;
|
type->types[param_count + i] = ref_type.ref_type;
|
||||||
|
@ -1527,18 +1561,6 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Calculate the minimal type index of the type equal to this type */
|
|
||||||
type->min_type_idx_normalized = type_idx;
|
|
||||||
for (i = 0; i < type_idx; i++) {
|
|
||||||
WASMFuncType *func_type = (WASMFuncType *)module->types[i];
|
|
||||||
if (func_type->base_type.type_flag == WASM_TYPE_FUNC
|
|
||||||
&& wasm_func_type_equal(type, func_type, module->types,
|
|
||||||
type_idx + 1)) {
|
|
||||||
type->min_type_idx_normalized = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*p_buf = p;
|
*p_buf = p;
|
||||||
|
|
||||||
module->types[type_idx] = (WASMType *)type;
|
module->types[type_idx] = (WASMType *)type;
|
||||||
|
@ -1552,8 +1574,8 @@ fail:
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end,
|
resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
WASMModule *module, uint32 type_idx, char *error_buf,
|
WASMModule *module, uint32 type_count, uint32 type_idx,
|
||||||
uint32 error_buf_size)
|
char *error_buf, uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
|
const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
|
||||||
uint32 field_count, ref_type_map_count = 0, ref_field_count = 0;
|
uint32 field_count, ref_type_map_count = 0, ref_field_count = 0;
|
||||||
|
@ -1569,8 +1591,9 @@ resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
read_leb_uint32(p, p_end, field_count);
|
read_leb_uint32(p, p_end, field_count);
|
||||||
p_org = p;
|
p_org = p;
|
||||||
for (i = 0; i < field_count; i++) {
|
for (i = 0; i < field_count; i++) {
|
||||||
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
if (!resolve_value_type(&p, p_end, module, type_count,
|
||||||
&ref_type, true, error_buf, error_buf_size)) {
|
&need_ref_type_map, &ref_type, true, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (need_ref_type_map)
|
if (need_ref_type_map)
|
||||||
|
@ -1617,8 +1640,9 @@ resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
|
|
||||||
offset = (uint32)offsetof(WASMStructObject, field_data);
|
offset = (uint32)offsetof(WASMStructObject, field_data);
|
||||||
for (i = 0; i < field_count; i++) {
|
for (i = 0; i < field_count; i++) {
|
||||||
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
if (!resolve_value_type(&p, p_end, module, type_count,
|
||||||
&ref_type, true, error_buf, error_buf_size)) {
|
&need_ref_type_map, &ref_type, true, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
type->fields[i].field_type = ref_type.ref_type;
|
type->fields[i].field_type = ref_type.ref_type;
|
||||||
|
@ -1671,8 +1695,8 @@ fail:
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
resolve_array_type(const uint8 **p_buf, const uint8 *buf_end,
|
resolve_array_type(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
WASMModule *module, uint32 type_idx, char *error_buf,
|
WASMModule *module, uint32 type_count, uint32 type_idx,
|
||||||
uint32 error_buf_size)
|
char *error_buf, uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
const uint8 *p = *p_buf, *p_end = buf_end;
|
const uint8 *p = *p_buf, *p_end = buf_end;
|
||||||
uint8 mutable;
|
uint8 mutable;
|
||||||
|
@ -1680,8 +1704,8 @@ resolve_array_type(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
WASMRefType ref_type;
|
WASMRefType ref_type;
|
||||||
WASMArrayType *type = NULL;
|
WASMArrayType *type = NULL;
|
||||||
|
|
||||||
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, &ref_type,
|
if (!resolve_value_type(&p, p_end, module, type_count, &need_ref_type_map,
|
||||||
true, error_buf, error_buf_size)) {
|
&ref_type, true, error_buf, error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1730,7 +1754,8 @@ init_ref_type(WASMModule *module, WASMRefType *ref_type, bool nullable,
|
||||||
int32 heap_type, char *error_buf, uint32 error_buf_size)
|
int32 heap_type, char *error_buf, uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
if (heap_type >= 0) {
|
if (heap_type >= 0) {
|
||||||
if (!check_type_index(module, heap_type, error_buf, error_buf_size)) {
|
if (!check_type_index(module, module->type_count, heap_type, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
wasm_set_refheaptype_typeidx(&ref_type->ref_ht_typeidx, nullable,
|
wasm_set_refheaptype_typeidx(&ref_type->ref_ht_typeidx, nullable,
|
||||||
|
@ -2010,6 +2035,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
|
|
||||||
if (flag == DEFINED_TYPE_FUNC) {
|
if (flag == DEFINED_TYPE_FUNC) {
|
||||||
if (!resolve_func_type(&p, buf_end, module,
|
if (!resolve_func_type(&p, buf_end, module,
|
||||||
|
processed_type_count + rec_count,
|
||||||
processed_type_count + j, error_buf,
|
processed_type_count + j, error_buf,
|
||||||
error_buf_size)) {
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2017,6 +2043,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
}
|
}
|
||||||
else if (flag == DEFINED_TYPE_STRUCT) {
|
else if (flag == DEFINED_TYPE_STRUCT) {
|
||||||
if (!resolve_struct_type(&p, buf_end, module,
|
if (!resolve_struct_type(&p, buf_end, module,
|
||||||
|
processed_type_count + rec_count,
|
||||||
processed_type_count + j,
|
processed_type_count + j,
|
||||||
error_buf, error_buf_size)) {
|
error_buf, error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2024,6 +2051,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
}
|
}
|
||||||
else if (flag == DEFINED_TYPE_ARRAY) {
|
else if (flag == DEFINED_TYPE_ARRAY) {
|
||||||
if (!resolve_array_type(&p, buf_end, module,
|
if (!resolve_array_type(&p, buf_end, module,
|
||||||
|
processed_type_count + rec_count,
|
||||||
processed_type_count + j, error_buf,
|
processed_type_count + j, error_buf,
|
||||||
error_buf_size)) {
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2037,13 +2065,13 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
|
|
||||||
cur_type = module->types[processed_type_count + j];
|
cur_type = module->types[processed_type_count + j];
|
||||||
|
|
||||||
|
cur_type->ref_count = 1;
|
||||||
cur_type->parent_type_idx = parent_type_idx;
|
cur_type->parent_type_idx = parent_type_idx;
|
||||||
cur_type->is_sub_final = is_sub_final;
|
cur_type->is_sub_final = is_sub_final;
|
||||||
|
|
||||||
if (rec_count > 1) {
|
cur_type->rec_count = rec_count;
|
||||||
cur_type->rec_count = rec_count;
|
cur_type->rec_idx = j;
|
||||||
cur_type->rec_idx = j;
|
cur_type->rec_begin_type_idx = processed_type_count;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* resolve subtyping relationship in current rec group */
|
/* resolve subtyping relationship in current rec group */
|
||||||
|
@ -2055,6 +2083,11 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
module->types[cur_type->parent_type_idx];
|
module->types[cur_type->parent_type_idx];
|
||||||
cur_type->parent_type = parent_type;
|
cur_type->parent_type = parent_type;
|
||||||
cur_type->root_type = parent_type->root_type;
|
cur_type->root_type = parent_type->root_type;
|
||||||
|
if (parent_type->inherit_depth == UINT16_MAX) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"parent type's inherit depth too large");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
cur_type->inherit_depth = parent_type->inherit_depth + 1;
|
cur_type->inherit_depth = parent_type->inherit_depth + 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2080,6 +2113,49 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If there is already an equivalence type or a group of equivalence
|
||||||
|
recursive types created, use it or them instead */
|
||||||
|
for (j = 0; j < processed_type_count;) {
|
||||||
|
WASMType *src_type = module->types[j];
|
||||||
|
WASMType *cur_type = module->types[processed_type_count];
|
||||||
|
uint32 k, src_rec_count;
|
||||||
|
|
||||||
|
src_rec_count = src_type->rec_count;
|
||||||
|
if (src_rec_count != rec_count) {
|
||||||
|
/* no type equivalence */
|
||||||
|
j += src_rec_count;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 0; k < rec_count; k++) {
|
||||||
|
src_type = module->types[j + k];
|
||||||
|
cur_type = module->types[processed_type_count + k];
|
||||||
|
if (!wasm_type_equal(src_type, cur_type, module->types,
|
||||||
|
module->type_count)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (k < rec_count) {
|
||||||
|
/* no type equivalence */
|
||||||
|
j += src_rec_count;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* type equivalence */
|
||||||
|
for (k = 0; k < rec_count; k++) {
|
||||||
|
if (module->types[j + k]->ref_count == UINT16_MAX) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"wasm type's ref count too large");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
destroy_wasm_type(module->types[processed_type_count + k]);
|
||||||
|
module->types[processed_type_count + k] =
|
||||||
|
module->types[j + k];
|
||||||
|
module->types[j + k]->ref_count++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (rec_count > 1) {
|
if (rec_count > 1) {
|
||||||
LOG_VERBOSE("Finished processing rec group [%d-%d]",
|
LOG_VERBOSE("Finished processing rec group [%d-%d]",
|
||||||
processed_type_count,
|
processed_type_count,
|
||||||
|
@ -2511,8 +2587,9 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else /* else of WASM_ENABLE_GC == 0 */
|
#else /* else of WASM_ENABLE_GC == 0 */
|
||||||
if (!resolve_value_type(&p, p_end, parent_module, &need_ref_type_map,
|
if (!resolve_value_type(&p, p_end, parent_module, parent_module->type_count,
|
||||||
&ref_type, false, error_buf, error_buf_size)) {
|
&need_ref_type_map, &ref_type, false, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (wasm_is_reftype_htref_non_nullable(ref_type.ref_type)) {
|
if (wasm_is_reftype_htref_non_nullable(ref_type.ref_type)) {
|
||||||
|
@ -2947,8 +3024,9 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
|
||||||
declare_type = read_uint8(p);
|
declare_type = read_uint8(p);
|
||||||
declare_mutable = read_uint8(p);
|
declare_mutable = read_uint8(p);
|
||||||
#else
|
#else
|
||||||
if (!resolve_value_type(&p, p_end, parent_module, &need_ref_type_map,
|
if (!resolve_value_type(&p, p_end, parent_module, parent_module->type_count,
|
||||||
&ref_type, false, error_buf, error_buf_size)) {
|
&need_ref_type_map, &ref_type, false, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
declare_type = ref_type.ref_type;
|
declare_type = ref_type.ref_type;
|
||||||
|
@ -3050,8 +3128,9 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else /* else of WASM_ENABLE_GC == 0 */
|
#else /* else of WASM_ENABLE_GC == 0 */
|
||||||
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, &ref_type,
|
if (!resolve_value_type(&p, p_end, module, module->type_count,
|
||||||
false, error_buf, error_buf_size)) {
|
&need_ref_type_map, &ref_type, false, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
table->elem_type = ref_type.ref_type;
|
table->elem_type = ref_type.ref_type;
|
||||||
|
@ -3536,7 +3615,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
||||||
type_index_org = type_index;
|
type_index_org = type_index;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
|
#if (WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0) \
|
||||||
|
&& WASM_ENABLE_GC == 0
|
||||||
type_index = wasm_get_smallest_type_idx(
|
type_index = wasm_get_smallest_type_idx(
|
||||||
module->types, module->type_count, type_index);
|
module->types, module->type_count, type_index);
|
||||||
#endif
|
#endif
|
||||||
|
@ -3577,8 +3657,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
if (!resolve_value_type(&p_code, buf_code_end, module,
|
if (!resolve_value_type(&p_code, buf_code_end, module,
|
||||||
&need_ref_type_map, &ref_type, false,
|
module->type_count, &need_ref_type_map,
|
||||||
error_buf, error_buf_size)) {
|
&ref_type, false, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
local_count += sub_local_count;
|
local_count += sub_local_count;
|
||||||
|
@ -3664,8 +3745,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (!resolve_value_type(&p_code, buf_code_end, module,
|
if (!resolve_value_type(&p_code, buf_code_end, module,
|
||||||
&need_ref_type_map, &ref_type, false,
|
module->type_count, &need_ref_type_map,
|
||||||
error_buf, error_buf_size)) {
|
&ref_type, false, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (need_ref_type_map) {
|
if (need_ref_type_map) {
|
||||||
|
@ -3923,9 +4005,9 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
global->type = read_uint8(p);
|
global->type = read_uint8(p);
|
||||||
mutable = read_uint8(p);
|
mutable = read_uint8(p);
|
||||||
#else
|
#else
|
||||||
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map,
|
if (!resolve_value_type(&p, p_end, module, module->type_count,
|
||||||
&ref_type, false, error_buf,
|
&need_ref_type_map, &ref_type, false,
|
||||||
error_buf_size)) {
|
error_buf, error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
global->type = ref_type.ref_type;
|
global->type = ref_type.ref_type;
|
||||||
|
@ -4231,8 +4313,8 @@ load_elem_type(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
|
||||||
#else
|
#else
|
||||||
p--;
|
p--;
|
||||||
if (!resolve_value_type((const uint8 **)&p, p_end, module,
|
if (!resolve_value_type((const uint8 **)&p, p_end, module,
|
||||||
&need_ref_type_map, &elem_ref_type, false,
|
module->type_count, &need_ref_type_map,
|
||||||
error_buf, error_buf_size)) {
|
&elem_ref_type, false, error_buf, error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!wasm_is_type_reftype(elem_ref_type.ref_type)) {
|
if (!wasm_is_type_reftype(elem_ref_type.ref_type)) {
|
||||||
|
@ -5592,6 +5674,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
uint32 aux_data_end_global_index = (uint32)-1;
|
uint32 aux_data_end_global_index = (uint32)-1;
|
||||||
uint32 aux_heap_base_global_index = (uint32)-1;
|
uint32 aux_heap_base_global_index = (uint32)-1;
|
||||||
WASMFuncType *func_type;
|
WASMFuncType *func_type;
|
||||||
|
uint8 malloc_free_io_type = VALUE_TYPE_I32;
|
||||||
|
|
||||||
/* Find code and function sections if have */
|
/* Find code and function sections if have */
|
||||||
while (section) {
|
while (section) {
|
||||||
|
@ -5820,6 +5903,10 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
module->retain_function = (uint32)-1;
|
module->retain_function = (uint32)-1;
|
||||||
|
|
||||||
/* Resolve malloc/free function exported by wasm module */
|
/* Resolve malloc/free function exported by wasm module */
|
||||||
|
#if WASM_ENABLE_MEMORY64 != 0
|
||||||
|
if (has_module_memory64(module))
|
||||||
|
malloc_free_io_type = VALUE_TYPE_I64;
|
||||||
|
#endif
|
||||||
export = module->exports;
|
export = module->exports;
|
||||||
for (i = 0; i < module->export_count; i++, export ++) {
|
for (i = 0; i < module->export_count; i++, export ++) {
|
||||||
if (export->kind == EXPORT_KIND_FUNC) {
|
if (export->kind == EXPORT_KIND_FUNC) {
|
||||||
|
@ -5828,8 +5915,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
func_index = export->index - module->import_function_count;
|
func_index = export->index - module->import_function_count;
|
||||||
func_type = module->functions[func_index]->func_type;
|
func_type = module->functions[func_index]->func_type;
|
||||||
if (func_type->param_count == 1 && func_type->result_count == 1
|
if (func_type->param_count == 1 && func_type->result_count == 1
|
||||||
&& func_type->types[0] == VALUE_TYPE_I32
|
&& func_type->types[0] == malloc_free_io_type
|
||||||
&& func_type->types[1] == VALUE_TYPE_I32) {
|
&& func_type->types[1] == malloc_free_io_type) {
|
||||||
bh_assert(module->malloc_function == (uint32)-1);
|
bh_assert(module->malloc_function == (uint32)-1);
|
||||||
module->malloc_function = export->index;
|
module->malloc_function = export->index;
|
||||||
LOG_VERBOSE("Found malloc function, name: %s, index: %u",
|
LOG_VERBOSE("Found malloc function, name: %s, index: %u",
|
||||||
|
@ -5842,9 +5929,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
func_index = export->index - module->import_function_count;
|
func_index = export->index - module->import_function_count;
|
||||||
func_type = module->functions[func_index]->func_type;
|
func_type = module->functions[func_index]->func_type;
|
||||||
if (func_type->param_count == 2 && func_type->result_count == 1
|
if (func_type->param_count == 2 && func_type->result_count == 1
|
||||||
&& func_type->types[0] == VALUE_TYPE_I32
|
&& func_type->types[0] == malloc_free_io_type
|
||||||
&& func_type->types[1] == VALUE_TYPE_I32
|
&& func_type->types[1] == VALUE_TYPE_I32
|
||||||
&& func_type->types[2] == VALUE_TYPE_I32) {
|
&& func_type->types[2] == malloc_free_io_type) {
|
||||||
uint32 j;
|
uint32 j;
|
||||||
WASMExport *export_tmp;
|
WASMExport *export_tmp;
|
||||||
|
|
||||||
|
@ -5868,8 +5955,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
module->functions[func_index]->func_type;
|
module->functions[func_index]->func_type;
|
||||||
if (func_type->param_count == 1
|
if (func_type->param_count == 1
|
||||||
&& func_type->result_count == 1
|
&& func_type->result_count == 1
|
||||||
&& func_type->types[0] == VALUE_TYPE_I32
|
&& func_type->types[0] == malloc_free_io_type
|
||||||
&& func_type->types[1] == VALUE_TYPE_I32) {
|
&& func_type->types[1] == malloc_free_io_type) {
|
||||||
bh_assert(module->retain_function
|
bh_assert(module->retain_function
|
||||||
== (uint32)-1);
|
== (uint32)-1);
|
||||||
module->retain_function = export_tmp->index;
|
module->retain_function = export_tmp->index;
|
||||||
|
@ -5895,7 +5982,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
func_index = export->index - module->import_function_count;
|
func_index = export->index - module->import_function_count;
|
||||||
func_type = module->functions[func_index]->func_type;
|
func_type = module->functions[func_index]->func_type;
|
||||||
if (func_type->param_count == 1 && func_type->result_count == 0
|
if (func_type->param_count == 1 && func_type->result_count == 0
|
||||||
&& func_type->types[0] == VALUE_TYPE_I32) {
|
&& func_type->types[0] == malloc_free_io_type) {
|
||||||
bh_assert(module->free_function == (uint32)-1);
|
bh_assert(module->free_function == (uint32)-1);
|
||||||
module->free_function = export->index;
|
module->free_function = export->index;
|
||||||
LOG_VERBOSE("Found free function, name: %s, index: %u",
|
LOG_VERBOSE("Found free function, name: %s, index: %u",
|
||||||
|
@ -10670,14 +10757,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
||||||
func->param_cell_num, func->local_cell_num, func->ret_cell_num);
|
func->param_cell_num, func->local_cell_num, func->ret_cell_num);
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_MEMORY64 != 0
|
#if WASM_ENABLE_MEMORY64 != 0
|
||||||
bool is_memory64 = false;
|
bool is_memory64 = has_module_memory64(module);
|
||||||
/* TODO: multi-memories for now assuming the memory idx type is consistent
|
|
||||||
* across multi-memories */
|
|
||||||
if (module->import_memory_count > 0)
|
|
||||||
is_memory64 = module->import_memories[0].u.memory.flags & MEMORY64_FLAG;
|
|
||||||
else if (module->memory_count > 0)
|
|
||||||
is_memory64 = module->memories[0].flags & MEMORY64_FLAG;
|
|
||||||
|
|
||||||
mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
|
mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
|
||||||
#else
|
#else
|
||||||
mem_offset_type = VALUE_TYPE_I32;
|
mem_offset_type = VALUE_TYPE_I32;
|
||||||
|
@ -10827,7 +10907,8 @@ re_scan:
|
||||||
p_org = p;
|
p_org = p;
|
||||||
p--;
|
p--;
|
||||||
if (!resolve_value_type((const uint8 **)&p, p_end,
|
if (!resolve_value_type((const uint8 **)&p, p_end,
|
||||||
module, &need_ref_type_map,
|
module, module->type_count,
|
||||||
|
&need_ref_type_map,
|
||||||
&wasm_ref_type, false,
|
&wasm_ref_type, false,
|
||||||
error_buf, error_buf_size)) {
|
error_buf, error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -11303,8 +11384,8 @@ re_scan:
|
||||||
bh_memcpy_s(loader_ctx->frame_offset, size,
|
bh_memcpy_s(loader_ctx->frame_offset, size,
|
||||||
block->param_frame_offsets, size);
|
block->param_frame_offsets, size);
|
||||||
loader_ctx->frame_offset += (size / sizeof(int16));
|
loader_ctx->frame_offset += (size / sizeof(int16));
|
||||||
loader_ctx->dynamic_offset = block->start_dynamic_offset;
|
|
||||||
}
|
}
|
||||||
|
loader_ctx->dynamic_offset = block->start_dynamic_offset;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -11598,6 +11679,15 @@ re_scan:
|
||||||
if (opcode == WASM_OP_CALL_REF
|
if (opcode == WASM_OP_CALL_REF
|
||||||
|| opcode == WASM_OP_RETURN_CALL_REF) {
|
|| opcode == WASM_OP_RETURN_CALL_REF) {
|
||||||
read_leb_uint32(p, p_end, type_idx1);
|
read_leb_uint32(p, p_end, type_idx1);
|
||||||
|
if (!check_type_index(module, module->type_count, type_idx1,
|
||||||
|
error_buf, error_buf_size)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (module->types[type_idx1]->type_flag != WASM_TYPE_FUNC) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"unkown function type");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
if (!wasm_loader_pop_nullable_typeidx(loader_ctx, &type,
|
if (!wasm_loader_pop_nullable_typeidx(loader_ctx, &type,
|
||||||
&type_idx, error_buf,
|
&type_idx, error_buf,
|
||||||
error_buf_size)) {
|
error_buf_size)) {
|
||||||
|
@ -11606,8 +11696,8 @@ re_scan:
|
||||||
if (type == VALUE_TYPE_ANY) {
|
if (type == VALUE_TYPE_ANY) {
|
||||||
type_idx = type_idx1;
|
type_idx = type_idx1;
|
||||||
}
|
}
|
||||||
if (!check_type_index(module, type_idx, error_buf,
|
if (!check_type_index(module, module->type_count, type_idx,
|
||||||
error_buf_size)) {
|
error_buf, error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (module->types[type_idx]->type_flag != WASM_TYPE_FUNC) {
|
if (module->types[type_idx]->type_flag != WASM_TYPE_FUNC) {
|
||||||
|
@ -11615,7 +11705,9 @@ re_scan:
|
||||||
"unkown function type");
|
"unkown function type");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (type_idx != type_idx1) {
|
if (!wasm_func_type_is_super_of(
|
||||||
|
(WASMFuncType *)module->types[type_idx1],
|
||||||
|
(WASMFuncType *)module->types[type_idx])) {
|
||||||
set_error_buf(error_buf, error_buf_size,
|
set_error_buf(error_buf, error_buf_size,
|
||||||
"function type mismatch");
|
"function type mismatch");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -12055,8 +12147,9 @@ re_scan:
|
||||||
#else
|
#else
|
||||||
p_org = p + 1;
|
p_org = p + 1;
|
||||||
if (!resolve_value_type((const uint8 **)&p, p_end, module,
|
if (!resolve_value_type((const uint8 **)&p, p_end, module,
|
||||||
&need_ref_type_map, &wasm_ref_type,
|
module->type_count, &need_ref_type_map,
|
||||||
false, error_buf, error_buf_size)) {
|
&wasm_ref_type, false, error_buf,
|
||||||
|
error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
type = wasm_ref_type.ref_type;
|
type = wasm_ref_type.ref_type;
|
||||||
|
@ -12223,8 +12316,8 @@ re_scan:
|
||||||
#else
|
#else
|
||||||
read_leb_int32(p, p_end, heap_type);
|
read_leb_int32(p, p_end, heap_type);
|
||||||
if (heap_type >= 0) {
|
if (heap_type >= 0) {
|
||||||
if (!check_type_index(module, heap_type, error_buf,
|
if (!check_type_index(module, module->type_count, heap_type,
|
||||||
error_buf_size)) {
|
error_buf, error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
wasm_set_refheaptype_typeidx(&wasm_ref_type.ref_ht_typeidx,
|
wasm_set_refheaptype_typeidx(&wasm_ref_type.ref_ht_typeidx,
|
||||||
|
@ -13288,7 +13381,8 @@ re_scan:
|
||||||
#if WASM_ENABLE_FAST_INTERP != 0
|
#if WASM_ENABLE_FAST_INTERP != 0
|
||||||
emit_uint32(loader_ctx, type_idx);
|
emit_uint32(loader_ctx, type_idx);
|
||||||
#endif
|
#endif
|
||||||
if (!check_type_index(module, type_idx, error_buf,
|
if (!check_type_index(module, module->type_count,
|
||||||
|
type_idx, error_buf,
|
||||||
error_buf_size)) {
|
error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -13374,7 +13468,8 @@ re_scan:
|
||||||
#if WASM_ENABLE_FAST_INTERP != 0
|
#if WASM_ENABLE_FAST_INTERP != 0
|
||||||
emit_uint32(loader_ctx, type_idx);
|
emit_uint32(loader_ctx, type_idx);
|
||||||
#endif
|
#endif
|
||||||
if (!check_type_index(module, type_idx, error_buf,
|
if (!check_type_index(module, module->type_count,
|
||||||
|
type_idx, error_buf,
|
||||||
error_buf_size)) {
|
error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -13787,7 +13882,8 @@ re_scan:
|
||||||
emit_uint32(loader_ctx, (uint32)heap_type);
|
emit_uint32(loader_ctx, (uint32)heap_type);
|
||||||
#endif
|
#endif
|
||||||
if (heap_type >= 0) {
|
if (heap_type >= 0) {
|
||||||
if (!check_type_index(module, heap_type, error_buf,
|
if (!check_type_index(module, module->type_count,
|
||||||
|
heap_type, error_buf,
|
||||||
error_buf_size)) {
|
error_buf_size)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,21 @@
|
||||||
#define TEMPLATE_READ_VALUE(Type, p) \
|
#define TEMPLATE_READ_VALUE(Type, p) \
|
||||||
(p += sizeof(Type), *(Type *)(p - sizeof(Type)))
|
(p += sizeof(Type), *(Type *)(p - sizeof(Type)))
|
||||||
|
|
||||||
|
#if WASM_ENABLE_MEMORY64 != 0
|
||||||
|
static bool
|
||||||
|
has_module_memory64(WASMModule *module)
|
||||||
|
{
|
||||||
|
/* TODO: multi-memories for now assuming the memory idx type is consistent
|
||||||
|
* across multi-memories */
|
||||||
|
if (module->import_memory_count > 0)
|
||||||
|
return !!(module->import_memories[0].u.memory.flags & MEMORY64_FLAG);
|
||||||
|
else if (module->memory_count > 0)
|
||||||
|
return !!(module->memories[0].flags & MEMORY64_FLAG);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
||||||
{
|
{
|
||||||
|
@ -2573,6 +2588,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
uint32 aux_data_end_global_index = (uint32)-1;
|
uint32 aux_data_end_global_index = (uint32)-1;
|
||||||
uint32 aux_heap_base_global_index = (uint32)-1;
|
uint32 aux_heap_base_global_index = (uint32)-1;
|
||||||
WASMFuncType *func_type;
|
WASMFuncType *func_type;
|
||||||
|
uint8 malloc_free_io_type = VALUE_TYPE_I32;
|
||||||
|
|
||||||
/* Find code and function sections if have */
|
/* Find code and function sections if have */
|
||||||
while (section) {
|
while (section) {
|
||||||
|
@ -2781,6 +2797,10 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
module->retain_function = (uint32)-1;
|
module->retain_function = (uint32)-1;
|
||||||
|
|
||||||
/* Resolve malloc/free function exported by wasm module */
|
/* Resolve malloc/free function exported by wasm module */
|
||||||
|
#if WASM_ENABLE_MEMORY64 != 0
|
||||||
|
if (has_module_memory64(module))
|
||||||
|
malloc_free_io_type = VALUE_TYPE_I64;
|
||||||
|
#endif
|
||||||
export = module->exports;
|
export = module->exports;
|
||||||
for (i = 0; i < module->export_count; i++, export ++) {
|
for (i = 0; i < module->export_count; i++, export ++) {
|
||||||
if (export->kind == EXPORT_KIND_FUNC) {
|
if (export->kind == EXPORT_KIND_FUNC) {
|
||||||
|
@ -2789,8 +2809,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
func_index = export->index - module->import_function_count;
|
func_index = export->index - module->import_function_count;
|
||||||
func_type = module->functions[func_index]->func_type;
|
func_type = module->functions[func_index]->func_type;
|
||||||
if (func_type->param_count == 1 && func_type->result_count == 1
|
if (func_type->param_count == 1 && func_type->result_count == 1
|
||||||
&& func_type->types[0] == VALUE_TYPE_I32
|
&& func_type->types[0] == malloc_free_io_type
|
||||||
&& func_type->types[1] == VALUE_TYPE_I32) {
|
&& func_type->types[1] == malloc_free_io_type) {
|
||||||
bh_assert(module->malloc_function == (uint32)-1);
|
bh_assert(module->malloc_function == (uint32)-1);
|
||||||
module->malloc_function = export->index;
|
module->malloc_function = export->index;
|
||||||
LOG_VERBOSE("Found malloc function, name: %s, index: %u",
|
LOG_VERBOSE("Found malloc function, name: %s, index: %u",
|
||||||
|
@ -2803,9 +2823,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
func_index = export->index - module->import_function_count;
|
func_index = export->index - module->import_function_count;
|
||||||
func_type = module->functions[func_index]->func_type;
|
func_type = module->functions[func_index]->func_type;
|
||||||
if (func_type->param_count == 2 && func_type->result_count == 1
|
if (func_type->param_count == 2 && func_type->result_count == 1
|
||||||
&& func_type->types[0] == VALUE_TYPE_I32
|
&& func_type->types[0] == malloc_free_io_type
|
||||||
&& func_type->types[1] == VALUE_TYPE_I32
|
&& func_type->types[1] == VALUE_TYPE_I32
|
||||||
&& func_type->types[2] == VALUE_TYPE_I32) {
|
&& func_type->types[2] == malloc_free_io_type) {
|
||||||
uint32 j;
|
uint32 j;
|
||||||
WASMExport *export_tmp;
|
WASMExport *export_tmp;
|
||||||
|
|
||||||
|
@ -2829,8 +2849,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
module->functions[func_index]->func_type;
|
module->functions[func_index]->func_type;
|
||||||
if (func_type->param_count == 1
|
if (func_type->param_count == 1
|
||||||
&& func_type->result_count == 1
|
&& func_type->result_count == 1
|
||||||
&& func_type->types[0] == VALUE_TYPE_I32
|
&& func_type->types[0] == malloc_free_io_type
|
||||||
&& func_type->types[1] == VALUE_TYPE_I32) {
|
&& func_type->types[1] == malloc_free_io_type) {
|
||||||
bh_assert(module->retain_function
|
bh_assert(module->retain_function
|
||||||
== (uint32)-1);
|
== (uint32)-1);
|
||||||
module->retain_function = export_tmp->index;
|
module->retain_function = export_tmp->index;
|
||||||
|
@ -2856,7 +2876,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
func_index = export->index - module->import_function_count;
|
func_index = export->index - module->import_function_count;
|
||||||
func_type = module->functions[func_index]->func_type;
|
func_type = module->functions[func_index]->func_type;
|
||||||
if (func_type->param_count == 1 && func_type->result_count == 0
|
if (func_type->param_count == 1 && func_type->result_count == 0
|
||||||
&& func_type->types[0] == VALUE_TYPE_I32) {
|
&& func_type->types[0] == malloc_free_io_type) {
|
||||||
bh_assert(module->free_function == (uint32)-1);
|
bh_assert(module->free_function == (uint32)-1);
|
||||||
module->free_function = export->index;
|
module->free_function = export->index;
|
||||||
LOG_VERBOSE("Found free function, name: %s, index: %u",
|
LOG_VERBOSE("Found free function, name: %s, index: %u",
|
||||||
|
@ -5906,14 +5926,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
||||||
func->param_cell_num, func->local_cell_num, func->ret_cell_num);
|
func->param_cell_num, func->local_cell_num, func->ret_cell_num);
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_MEMORY64 != 0
|
#if WASM_ENABLE_MEMORY64 != 0
|
||||||
bool is_memory64 = false;
|
bool is_memory64 = has_module_memory64(module);
|
||||||
/* TODO: multi-memories for now assuming the memory idx type is consistent
|
|
||||||
* across multi-memories */
|
|
||||||
if (module->import_memory_count > 0)
|
|
||||||
is_memory64 = module->import_memories[0].u.memory.flags & MEMORY64_FLAG;
|
|
||||||
else if (module->memory_count > 0)
|
|
||||||
is_memory64 = module->memories[0].flags & MEMORY64_FLAG;
|
|
||||||
|
|
||||||
mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
|
mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
|
||||||
#else
|
#else
|
||||||
mem_offset_type = VALUE_TYPE_I32;
|
mem_offset_type = VALUE_TYPE_I32;
|
||||||
|
@ -6226,8 +6239,8 @@ re_scan:
|
||||||
bh_memcpy_s(loader_ctx->frame_offset, size,
|
bh_memcpy_s(loader_ctx->frame_offset, size,
|
||||||
block->param_frame_offsets, size);
|
block->param_frame_offsets, size);
|
||||||
loader_ctx->frame_offset += (size / sizeof(int16));
|
loader_ctx->frame_offset += (size / sizeof(int16));
|
||||||
loader_ctx->dynamic_offset = block->start_dynamic_offset;
|
|
||||||
}
|
}
|
||||||
|
loader_ctx->dynamic_offset = block->start_dynamic_offset;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1400,30 +1400,39 @@ fail:
|
||||||
static bool
|
static bool
|
||||||
execute_malloc_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
execute_malloc_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||||
WASMFunctionInstance *malloc_func,
|
WASMFunctionInstance *malloc_func,
|
||||||
WASMFunctionInstance *retain_func, uint32 size,
|
WASMFunctionInstance *retain_func, uint64 size,
|
||||||
uint32 *p_result)
|
uint64 *p_result)
|
||||||
{
|
{
|
||||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||||
WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
|
WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
|
||||||
#endif
|
#endif
|
||||||
WASMExecEnv *exec_env_created = NULL;
|
WASMExecEnv *exec_env_created = NULL;
|
||||||
WASMModuleInstanceCommon *module_inst_old = NULL;
|
WASMModuleInstanceCommon *module_inst_old = NULL;
|
||||||
uint32 argv[2], argc;
|
uint32 argv[3], argc;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
#if WASM_ENABLE_MEMORY64 != 0
|
||||||
argv[0] = size;
|
bool is_memory64 = module_inst->memories[0]->is_memory64;
|
||||||
argc = 1;
|
if (is_memory64) {
|
||||||
|
argc = 2;
|
||||||
|
PUT_I64_TO_ADDR(&argv[0], size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
argc = 1;
|
||||||
|
argv[0] = size;
|
||||||
|
}
|
||||||
|
|
||||||
/* if __retain is exported, then this module is compiled by
|
/* if __retain is exported, then this module is compiled by
|
||||||
assemblyscript, the memory should be managed by as's runtime,
|
assemblyscript, the memory should be managed by as's runtime,
|
||||||
in this case we need to call the retain function after malloc
|
in this case we need to call the retain function after malloc
|
||||||
the memory */
|
the memory */
|
||||||
if (retain_func) {
|
if (retain_func) {
|
||||||
/* the malloc functino from assemblyscript is:
|
/* the malloc function from assemblyscript is:
|
||||||
function __new(size: usize, id: u32)
|
function __new(size: usize, id: u32)
|
||||||
id = 0 means this is an ArrayBuffer object */
|
id = 0 means this is an ArrayBuffer object */
|
||||||
argv[1] = 0;
|
argv[argc] = 0;
|
||||||
argc = 2;
|
argc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exec_env) {
|
if (exec_env) {
|
||||||
|
@ -1475,24 +1484,42 @@ execute_malloc_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||||
if (exec_env_created)
|
if (exec_env_created)
|
||||||
wasm_exec_env_destroy(exec_env_created);
|
wasm_exec_env_destroy(exec_env_created);
|
||||||
|
|
||||||
if (ret)
|
if (ret) {
|
||||||
*p_result = argv[0];
|
#if WASM_ENABLE_MEMORY64 != 0
|
||||||
|
if (is_memory64)
|
||||||
|
*p_result = GET_I64_FROM_ADDR(&argv[0]);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
*p_result = argv[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||||
WASMFunctionInstance *free_func, uint32 offset)
|
WASMFunctionInstance *free_func, uint64 offset)
|
||||||
{
|
{
|
||||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||||
WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
|
WASMExecEnv *exec_env_tls = wasm_runtime_get_exec_env_tls();
|
||||||
#endif
|
#endif
|
||||||
WASMExecEnv *exec_env_created = NULL;
|
WASMExecEnv *exec_env_created = NULL;
|
||||||
WASMModuleInstanceCommon *module_inst_old = NULL;
|
WASMModuleInstanceCommon *module_inst_old = NULL;
|
||||||
uint32 argv[2];
|
uint32 argv[2], argc;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
argv[0] = offset;
|
#if WASM_ENABLE_MEMORY64 != 0
|
||||||
|
if (module_inst->memories[0]->is_memory64) {
|
||||||
|
PUT_I64_TO_ADDR(&argv[0], offset);
|
||||||
|
argc = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
argv[0] = (uint32)offset;
|
||||||
|
argc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (exec_env) {
|
if (exec_env) {
|
||||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||||
|
@ -1531,7 +1558,7 @@ execute_free_function(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = wasm_call_function(exec_env, free_func, 1, argv);
|
ret = wasm_call_function(exec_env, free_func, argc, argv);
|
||||||
|
|
||||||
if (module_inst_old)
|
if (module_inst_old)
|
||||||
/* Restore the existing exec_env's module inst */
|
/* Restore the existing exec_env's module inst */
|
||||||
|
@ -3336,7 +3363,7 @@ wasm_module_malloc_internal(WASMModuleInstance *module_inst,
|
||||||
{
|
{
|
||||||
WASMMemoryInstance *memory = wasm_get_default_memory(module_inst);
|
WASMMemoryInstance *memory = wasm_get_default_memory(module_inst);
|
||||||
uint8 *addr = NULL;
|
uint8 *addr = NULL;
|
||||||
uint32 offset = 0;
|
uint64 offset = 0;
|
||||||
|
|
||||||
/* TODO: Memory64 size check based on memory idx type */
|
/* TODO: Memory64 size check based on memory idx type */
|
||||||
bh_assert(size <= UINT32_MAX);
|
bh_assert(size <= UINT32_MAX);
|
||||||
|
@ -3352,7 +3379,7 @@ wasm_module_malloc_internal(WASMModuleInstance *module_inst,
|
||||||
else if (module_inst->e->malloc_function && module_inst->e->free_function) {
|
else if (module_inst->e->malloc_function && module_inst->e->free_function) {
|
||||||
if (!execute_malloc_function(
|
if (!execute_malloc_function(
|
||||||
module_inst, exec_env, module_inst->e->malloc_function,
|
module_inst, exec_env, module_inst->e->malloc_function,
|
||||||
module_inst->e->retain_function, (uint32)size, &offset)) {
|
module_inst->e->retain_function, size, &offset)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* If we use app's malloc function,
|
/* If we use app's malloc function,
|
||||||
|
@ -3452,7 +3479,7 @@ wasm_module_free_internal(WASMModuleInstance *module_inst,
|
||||||
&& module_inst->e->free_function && memory->memory_data <= addr
|
&& module_inst->e->free_function && memory->memory_data <= addr
|
||||||
&& addr < memory_data_end) {
|
&& addr < memory_data_end) {
|
||||||
execute_free_function(module_inst, exec_env,
|
execute_free_function(module_inst, exec_env,
|
||||||
module_inst->e->free_function, (uint32)ptr);
|
module_inst->e->free_function, ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4404,6 +4431,22 @@ llvm_jit_obj_is_instance_of(WASMModuleInstance *module_inst,
|
||||||
return wasm_obj_is_instance_of(gc_obj, type_index, types, type_count);
|
return wasm_obj_is_instance_of(gc_obj, type_index, types, type_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
llvm_jit_func_type_is_super_of(WASMModuleInstance *module_inst,
|
||||||
|
uint32 type_idx1, uint32 type_idx2)
|
||||||
|
{
|
||||||
|
WASMModule *module = module_inst->module;
|
||||||
|
WASMType **types = module->types;
|
||||||
|
|
||||||
|
if (type_idx1 == type_idx2)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bh_assert(types[type_idx1]->type_flag == WASM_TYPE_FUNC);
|
||||||
|
bh_assert(types[type_idx2]->type_flag == WASM_TYPE_FUNC);
|
||||||
|
return wasm_func_type_is_super_of((WASMFuncType *)types[type_idx1],
|
||||||
|
(WASMFuncType *)types[type_idx2]);
|
||||||
|
}
|
||||||
|
|
||||||
WASMRttTypeRef
|
WASMRttTypeRef
|
||||||
llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index)
|
llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index)
|
||||||
{
|
{
|
||||||
|
|
|
@ -811,6 +811,11 @@ bool
|
||||||
llvm_jit_obj_is_instance_of(WASMModuleInstance *module_inst,
|
llvm_jit_obj_is_instance_of(WASMModuleInstance *module_inst,
|
||||||
WASMObjectRef gc_obj, uint32 type_index);
|
WASMObjectRef gc_obj, uint32 type_index);
|
||||||
|
|
||||||
|
/* Whether func type1 is one of super types of func type2 */
|
||||||
|
bool
|
||||||
|
llvm_jit_func_type_is_super_of(WASMModuleInstance *module_inst,
|
||||||
|
uint32 type_idx1, uint32 type_idx2);
|
||||||
|
|
||||||
WASMRttTypeRef
|
WASMRttTypeRef
|
||||||
llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index);
|
llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index);
|
||||||
|
|
||||||
|
|
|
@ -254,6 +254,10 @@ Currently we only profile the memory consumption of module, module_instance and
|
||||||
|
|
||||||
> See [Enable segue optimization for wamrc when generating the aot file](./perf_tune.md#3-enable-segue-optimization-for-wamrc-when-generating-the-aot-file) for more details.
|
> See [Enable segue optimization for wamrc when generating the aot file](./perf_tune.md#3-enable-segue-optimization-for-wamrc-when-generating-the-aot-file) for more details.
|
||||||
|
|
||||||
|
#### **User defined linear memory allocator**
|
||||||
|
- **WAMR_BUILD_ALLOC_WITH_USAGE**=1/0, default to disable if not set
|
||||||
|
> Notes: by default, the linear memory is allocated by system. when it's set to 1 and Alloc_With_Allocator is selected, it will be allocated by customer.
|
||||||
|
|
||||||
#### **Enable running PGO(Profile-Guided Optimization) instrumented AOT file**
|
#### **Enable running PGO(Profile-Guided Optimization) instrumented AOT file**
|
||||||
- **WAMR_BUILD_STATIC_PGO**=1/0, default to disable if not set
|
- **WAMR_BUILD_STATIC_PGO**=1/0, default to disable if not set
|
||||||
> Note: See [Use the AOT static PGO method](./perf_tune.md#5-use-the-aot-static-pgo-method) for more details.
|
> Note: See [Use the AOT static PGO method](./perf_tune.md#5-use-the-aot-static-pgo-method) for more details.
|
||||||
|
|
|
@ -129,6 +129,10 @@ if(CONFIG_INTERPRETERS_WAMR_GLOBAL_HEAP_POOL)
|
||||||
set(WAMR_BUILD_GLOBAL_HEAP_SIZE ${_HEAP_SIZE_})
|
set(WAMR_BUILD_GLOBAL_HEAP_SIZE ${_HEAP_SIZE_})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (CONFIG_INTERPRETERS_WAMR_MEM_ALLOC_WITH_USAGE)
|
||||||
|
set(WAMR_BUILD_MEM_ALLOC_WITH_USAGE 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_INTERPRETERS_WAMR_ENABLE_SPEC_TEST)
|
if(CONFIG_INTERPRETERS_WAMR_ENABLE_SPEC_TEST)
|
||||||
set(WAMR_BUILD_SPEC_TEST 1)
|
set(WAMR_BUILD_SPEC_TEST 1)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -373,6 +373,11 @@ CFLAGS += -DWASM_ENABLE_GLOBAL_HEAP_POOL=1
|
||||||
CFLAGS += -DWASM_GLOBAL_HEAP_SIZE="$(CONFIG_INTERPRETERS_WAMR_GLOBAL_HEAP_POOL_SIZE) * 1024"
|
CFLAGS += -DWASM_GLOBAL_HEAP_SIZE="$(CONFIG_INTERPRETERS_WAMR_GLOBAL_HEAP_POOL_SIZE) * 1024"
|
||||||
else
|
else
|
||||||
CFLAGS += -DWASM_ENABLE_GLOBAL_HEAP_POOL=0
|
CFLAGS += -DWASM_ENABLE_GLOBAL_HEAP_POOL=0
|
||||||
|
ifeq ($(CONFIG_INTERPRETERS_WAMR_MEM_ALLOC_WITH_USAGE),y)
|
||||||
|
CFLAGS += -DWASM_MEM_ALLOC_WITH_USAGE=1
|
||||||
|
else
|
||||||
|
CFLAGS += -DWASM_MEM_ALLOC_WITH_USAGE=0
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_ENABLE_SPEC_TEST),y)
|
ifeq ($(CONFIG_INTERPRETERS_WAMR_ENABLE_SPEC_TEST),y)
|
||||||
|
|
|
@ -445,6 +445,9 @@ static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE] = { 0 };
|
||||||
#else
|
#else
|
||||||
static void *
|
static void *
|
||||||
malloc_func(
|
malloc_func(
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
|
mem_alloc_usage_t usage,
|
||||||
|
#endif
|
||||||
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
void *user_data,
|
void *user_data,
|
||||||
#endif
|
#endif
|
||||||
|
@ -455,6 +458,9 @@ malloc_func(
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
realloc_func(
|
realloc_func(
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
|
mem_alloc_usage_t usage, bool full_size_mmaped,
|
||||||
|
#endif
|
||||||
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
void *user_data,
|
void *user_data,
|
||||||
#endif
|
#endif
|
||||||
|
@ -465,6 +471,9 @@ realloc_func(
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_func(
|
free_func(
|
||||||
|
#if WASM_MEM_ALLOC_WITH_USAGE != 0
|
||||||
|
mem_alloc_usage_t usage,
|
||||||
|
#endif
|
||||||
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
|
||||||
void *user_data,
|
void *user_data,
|
||||||
#endif
|
#endif
|
||||||
|
|
1
samples/native-stack-overflow/.gitignore
vendored
Normal file
1
samples/native-stack-overflow/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/out/
|
87
samples/native-stack-overflow/CMakeLists.txt
Normal file
87
samples/native-stack-overflow/CMakeLists.txt
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
|
||||||
|
cmake_minimum_required (VERSION 3.14)
|
||||||
|
|
||||||
|
include(CheckPIESupported)
|
||||||
|
|
||||||
|
if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||||
|
project (native-stack-overflow)
|
||||||
|
else()
|
||||||
|
project (native-stack-overflow C ASM)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
################ runtime settings ################
|
||||||
|
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
|
||||||
|
if (APPLE)
|
||||||
|
add_definitions(-DBH_PLATFORM_DARWIN)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Reset default linker flags
|
||||||
|
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||||
|
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
||||||
|
|
||||||
|
# WAMR features switch
|
||||||
|
|
||||||
|
# Set WAMR_BUILD_TARGET, currently values supported:
|
||||||
|
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
|
||||||
|
# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
|
||||||
|
if (NOT DEFINED WAMR_BUILD_TARGET)
|
||||||
|
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)")
|
||||||
|
set (WAMR_BUILD_TARGET "AARCH64")
|
||||||
|
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
|
||||||
|
set (WAMR_BUILD_TARGET "RISCV64")
|
||||||
|
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
# Build as X86_64 by default in 64-bit platform
|
||||||
|
set (WAMR_BUILD_TARGET "X86_64")
|
||||||
|
elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
|
# Build as X86_32 by default in 32-bit platform
|
||||||
|
set (WAMR_BUILD_TARGET "X86_32")
|
||||||
|
else ()
|
||||||
|
message(SEND_ERROR "Unsupported build target platform!")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (NOT CMAKE_BUILD_TYPE)
|
||||||
|
set (CMAKE_BUILD_TYPE Debug)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set (WAMR_BUILD_INTERP 1)
|
||||||
|
set (WAMR_BUILD_AOT 1)
|
||||||
|
set (WAMR_BUILD_JIT 0)
|
||||||
|
set (WAMR_BUILD_LIBC_BUILTIN 0)
|
||||||
|
set (WAMR_BUILD_LIBC_WASI 1)
|
||||||
|
|
||||||
|
if (NOT MSVC)
|
||||||
|
# linker flags
|
||||||
|
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||||
|
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||||
|
endif ()
|
||||||
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security")
|
||||||
|
if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
|
||||||
|
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||||
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# build out vmlib
|
||||||
|
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
|
||||||
|
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||||
|
|
||||||
|
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||||
|
|
||||||
|
################ application related ################
|
||||||
|
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||||
|
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
||||||
|
|
||||||
|
add_executable (native-stack-overflow src/main.c src/native_impl.c ${UNCOMMON_SHARED_SOURCE})
|
||||||
|
|
||||||
|
check_pie_supported()
|
||||||
|
set_target_properties (native-stack-overflow PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
target_link_libraries (native-stack-overflow vmlib -lm -ldl -lpthread)
|
||||||
|
else ()
|
||||||
|
target_link_libraries (native-stack-overflow vmlib -lm -ldl -lpthread -lrt)
|
||||||
|
endif ()
|
4
samples/native-stack-overflow/README.md
Normal file
4
samples/native-stack-overflow/README.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
The "native-stack-overflow" sample project
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
This sample examines native stack overflow detection mechanisms.
|
75
samples/native-stack-overflow/build.sh
Executable file
75
samples/native-stack-overflow/build.sh
Executable file
|
@ -0,0 +1,75 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
#
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CURR_DIR=$PWD
|
||||||
|
WAMR_DIR=${PWD}/../..
|
||||||
|
OUT_DIR=${PWD}/out
|
||||||
|
|
||||||
|
WASM_APPS=${PWD}/wasm-apps
|
||||||
|
|
||||||
|
|
||||||
|
rm -rf ${OUT_DIR}
|
||||||
|
mkdir ${OUT_DIR}
|
||||||
|
mkdir ${OUT_DIR}/wasm-apps
|
||||||
|
|
||||||
|
|
||||||
|
echo "##################### build (default)"
|
||||||
|
cd ${CURR_DIR}
|
||||||
|
mkdir -p cmake_build
|
||||||
|
cd cmake_build
|
||||||
|
cmake ..
|
||||||
|
make -j 4
|
||||||
|
if [ $? != 0 ];then
|
||||||
|
echo "BUILD_FAIL native-stack-overflow exit as $?\n"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
cp -a native-stack-overflow ${OUT_DIR}
|
||||||
|
|
||||||
|
echo "##################### build (WAMR_DISABLE_HW_BOUND_CHECK=1)"
|
||||||
|
cd ${CURR_DIR}
|
||||||
|
mkdir -p cmake_build_disable_hw_bound
|
||||||
|
cd cmake_build_disable_hw_bound
|
||||||
|
cmake -D WAMR_DISABLE_HW_BOUND_CHECK=1 ..
|
||||||
|
make -j 4
|
||||||
|
if [ $? != 0 ];then
|
||||||
|
echo "BUILD_FAIL native-stack-overflow exit as $?\n"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
cp -a native-stack-overflow ${OUT_DIR}/native-stack-overflow.WAMR_DISABLE_HW_BOUND_CHECK
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "##################### build wasm apps"
|
||||||
|
|
||||||
|
cd ${WASM_APPS}
|
||||||
|
|
||||||
|
for i in `ls *.c`
|
||||||
|
do
|
||||||
|
APP_SRC="$i"
|
||||||
|
OUT_FILE=${i%.*}.wasm
|
||||||
|
|
||||||
|
# use WAMR SDK to build out the .wasm binary
|
||||||
|
/opt/wasi-sdk/bin/clang \
|
||||||
|
-mexec-model=reactor \
|
||||||
|
-Os -z stack-size=4096 -Wl,--initial-memory=65536 \
|
||||||
|
-Wl,--allow-undefined \
|
||||||
|
-o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC}
|
||||||
|
|
||||||
|
if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then
|
||||||
|
echo "build ${OUT_FILE} success"
|
||||||
|
else
|
||||||
|
echo "build ${OUT_FILE} fail"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "#################### build wasm apps done"
|
||||||
|
|
||||||
|
echo "#################### aot-compile"
|
||||||
|
WAMRC=${WAMR_DIR}/wamr-compiler/build/wamrc
|
||||||
|
${WAMRC} -o ${OUT_DIR}/wasm-apps/${OUT_FILE}.aot ${OUT_DIR}/wasm-apps/${OUT_FILE}
|
||||||
|
|
||||||
|
echo "#################### aot-compile (--bounds-checks=1)"
|
||||||
|
${WAMRC} -o ${OUT_DIR}/wasm-apps/${OUT_FILE}.aot.bounds-checks --bounds-checks=1 ${OUT_DIR}/wasm-apps/${OUT_FILE}
|
1
samples/native-stack-overflow/clean.sh
Executable file
1
samples/native-stack-overflow/clean.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
rm -r cmake_build cmake_build_disable_hw_bound out
|
12
samples/native-stack-overflow/run.sh
Executable file
12
samples/native-stack-overflow/run.sh
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "====== Interpreter"
|
||||||
|
out/native-stack-overflow out/wasm-apps/testapp.wasm
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "====== AOT"
|
||||||
|
out/native-stack-overflow out/wasm-apps/testapp.wasm.aot
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "====== AOT WAMR_DISABLE_HW_BOUND_CHECK=1"
|
||||||
|
out/native-stack-overflow.WAMR_DISABLE_HW_BOUND_CHECK out/wasm-apps/testapp.wasm.aot.bounds-checks
|
178
samples/native-stack-overflow/src/main.c
Normal file
178
samples/native-stack-overflow/src/main.c
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Midokura Japan KK. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wasm_export.h"
|
||||||
|
#include "bh_read_file.h"
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
host_consume_stack_and_call_indirect(wasm_exec_env_t exec_env, uint32_t funcidx,
|
||||||
|
uint32_t x, uint32_t stack);
|
||||||
|
uint32_t
|
||||||
|
host_consume_stack(wasm_exec_env_t exec_env, uint32_t stack);
|
||||||
|
|
||||||
|
extern unsigned int nest;
|
||||||
|
|
||||||
|
static NativeSymbol native_symbols[] = {
|
||||||
|
{ "host_consume_stack_and_call_indirect",
|
||||||
|
host_consume_stack_and_call_indirect, "(iii)i", NULL },
|
||||||
|
{ "host_consume_stack", host_consume_stack, "(i)i", NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct record {
|
||||||
|
bool failed;
|
||||||
|
bool leaked;
|
||||||
|
char exception[128]; /* EXCEPTION_BUF_LEN */
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
print_record(unsigned int start, unsigned int end, const struct record *rec)
|
||||||
|
{
|
||||||
|
printf("%5u - %5u | %6s | %6s | %s\n", start, end,
|
||||||
|
rec->failed ? "failed" : "ok", rec->leaked ? "leaked" : "ok",
|
||||||
|
rec->exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *buffer;
|
||||||
|
char error_buf[128];
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
char *module_path = argv[1];
|
||||||
|
|
||||||
|
wasm_module_t module = NULL;
|
||||||
|
uint32 buf_size;
|
||||||
|
uint32 stack_size = 4096;
|
||||||
|
/*
|
||||||
|
* disable app heap.
|
||||||
|
* - we use wasi
|
||||||
|
* - https://github.com/bytecodealliance/wasm-micro-runtime/issues/2275
|
||||||
|
*/
|
||||||
|
uint32 heap_size = 0;
|
||||||
|
|
||||||
|
RuntimeInitArgs init_args;
|
||||||
|
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
||||||
|
init_args.mem_alloc_type = Alloc_With_System_Allocator;
|
||||||
|
init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||||
|
init_args.native_module_name = "env";
|
||||||
|
init_args.native_symbols = native_symbols;
|
||||||
|
if (!wasm_runtime_full_init(&init_args)) {
|
||||||
|
printf("wasm_runtime_full_init failed.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = bh_read_file_to_buffer(module_path, &buf_size);
|
||||||
|
if (!buffer) {
|
||||||
|
printf("bh_read_file_to_buffer failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf,
|
||||||
|
sizeof(error_buf));
|
||||||
|
if (!module) {
|
||||||
|
printf("wasm_runtime_load failed: %s\n", error_buf);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* header */
|
||||||
|
printf(" stack size | fail? | leak? | exception\n");
|
||||||
|
printf("-------------------------------------------------------------------"
|
||||||
|
"--------\n");
|
||||||
|
|
||||||
|
unsigned int stack;
|
||||||
|
unsigned int prevstack;
|
||||||
|
unsigned int stack_range_start = 0;
|
||||||
|
unsigned int stack_range_end = 4096 * 6;
|
||||||
|
unsigned int step = 16;
|
||||||
|
struct record rec0;
|
||||||
|
struct record rec1;
|
||||||
|
struct record *rec = &rec0;
|
||||||
|
struct record *prevrec = &rec1;
|
||||||
|
bool have_prevrec = false;
|
||||||
|
for (stack = stack_range_start; stack < stack_range_end; stack += step) {
|
||||||
|
wasm_module_inst_t module_inst = NULL;
|
||||||
|
wasm_exec_env_t exec_env = NULL;
|
||||||
|
bool failed = true;
|
||||||
|
const char *exception = NULL;
|
||||||
|
nest = 0;
|
||||||
|
|
||||||
|
module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
|
||||||
|
error_buf, sizeof(error_buf));
|
||||||
|
if (!module_inst) {
|
||||||
|
printf("wasm_runtime_instantiate failed: %s\n", error_buf);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
|
||||||
|
if (!exec_env) {
|
||||||
|
printf("wasm_runtime_create_exec_env failed\n");
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *funcname = "test";
|
||||||
|
wasm_function_inst_t func =
|
||||||
|
wasm_runtime_lookup_function(module_inst, funcname);
|
||||||
|
if (!func) {
|
||||||
|
printf("wasm_runtime_lookup_function failed for %s\n", funcname);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* note: the function type is (ii)i */
|
||||||
|
uint32_t wasm_argv[] = {
|
||||||
|
stack,
|
||||||
|
30,
|
||||||
|
};
|
||||||
|
uint32_t wasm_argc = 2;
|
||||||
|
if (!wasm_runtime_call_wasm(exec_env, func, wasm_argc, wasm_argv)) {
|
||||||
|
exception = wasm_runtime_get_exception(module_inst);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
failed = false;
|
||||||
|
fail2:
|
||||||
|
/*
|
||||||
|
* note: non-zero "nest" here demonstrates resource leak on longjmp
|
||||||
|
* from signal handler.
|
||||||
|
* cf.
|
||||||
|
* https://github.com/bytecodealliance/wasm-micro-runtime/issues/3320
|
||||||
|
*/
|
||||||
|
memset(rec, 0, sizeof(*rec));
|
||||||
|
rec->failed = failed;
|
||||||
|
rec->leaked = nest != 0;
|
||||||
|
strncpy(rec->exception, exception ? exception : "",
|
||||||
|
sizeof(rec->exception));
|
||||||
|
if (have_prevrec && memcmp(prevrec, rec, sizeof(*rec))) {
|
||||||
|
print_record(prevstack, stack, prevrec);
|
||||||
|
have_prevrec = false;
|
||||||
|
}
|
||||||
|
if (!have_prevrec) {
|
||||||
|
prevstack = stack;
|
||||||
|
struct record *tmp = prevrec;
|
||||||
|
prevrec = rec;
|
||||||
|
rec = tmp;
|
||||||
|
have_prevrec = true;
|
||||||
|
}
|
||||||
|
if (exec_env) {
|
||||||
|
wasm_runtime_destroy_exec_env(exec_env);
|
||||||
|
}
|
||||||
|
if (module_inst) {
|
||||||
|
wasm_runtime_deinstantiate(module_inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (have_prevrec) {
|
||||||
|
print_record(prevstack, stack, prevrec);
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (module) {
|
||||||
|
wasm_runtime_unload(module);
|
||||||
|
}
|
||||||
|
if (buffer) {
|
||||||
|
BH_FREE(buffer);
|
||||||
|
}
|
||||||
|
wasm_runtime_destroy();
|
||||||
|
}
|
71
samples/native-stack-overflow/src/native_impl.c
Normal file
71
samples/native-stack-overflow/src/native_impl.c
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Midokura Japan KK. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "wasm_export.h"
|
||||||
|
#include "bh_platform.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this "nest" var has two purposes:
|
||||||
|
* - prevent tail-call optimization
|
||||||
|
* - detect possible resource leak
|
||||||
|
*/
|
||||||
|
unsigned int nest = 0;
|
||||||
|
ptrdiff_t prev_diff = 0;
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
call_indirect(wasm_exec_env_t exec_env, uint32_t funcidx, uint32_t x)
|
||||||
|
{
|
||||||
|
uint32_t argv[1] = {
|
||||||
|
x,
|
||||||
|
};
|
||||||
|
uint32_t argc = 1;
|
||||||
|
if (!wasm_runtime_call_indirect(exec_env, funcidx, argc, argv)) {
|
||||||
|
/* failed */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return argv[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
host_consume_stack_and_call_indirect(wasm_exec_env_t exec_env, uint32_t funcidx,
|
||||||
|
uint32_t x, uint32_t stack)
|
||||||
|
{
|
||||||
|
void *boundary = os_thread_get_stack_boundary();
|
||||||
|
void *fp = __builtin_frame_address(0);
|
||||||
|
ptrdiff_t diff = fp - boundary;
|
||||||
|
if (diff > stack) {
|
||||||
|
prev_diff = diff;
|
||||||
|
nest++;
|
||||||
|
uint32_t ret =
|
||||||
|
host_consume_stack_and_call_indirect(exec_env, funcidx, x, stack);
|
||||||
|
nest--;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return call_indirect(exec_env, funcidx, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
consume_stack1(wasm_exec_env_t exec_env, void *base, uint32_t stack)
|
||||||
|
{
|
||||||
|
void *fp = __builtin_frame_address(0);
|
||||||
|
ptrdiff_t diff = (unsigned char *)base - (unsigned char *)fp;
|
||||||
|
assert(diff > 0);
|
||||||
|
char buf[16];
|
||||||
|
memset_s(buf, sizeof(buf), 0, sizeof(buf));
|
||||||
|
if (diff > stack) {
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
return consume_stack1(exec_env, base, stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
host_consume_stack(wasm_exec_env_t exec_env, uint32_t stack)
|
||||||
|
{
|
||||||
|
void *base = __builtin_frame_address(0);
|
||||||
|
return consume_stack1(exec_env, base, stack);
|
||||||
|
}
|
54
samples/native-stack-overflow/wasm-apps/testapp.c
Normal file
54
samples/native-stack-overflow/wasm-apps/testapp.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Midokura Japan KK. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
host_consume_stack_and_call_indirect(int (*)(int), uint32_t, uint32_t);
|
||||||
|
uint32_t host_consume_stack(uint32_t);
|
||||||
|
|
||||||
|
int
|
||||||
|
cb(int x)
|
||||||
|
{
|
||||||
|
return x * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
consume_stack_cb(int x)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* intentions:
|
||||||
|
*
|
||||||
|
* - consume native stack by making recursive calls
|
||||||
|
*
|
||||||
|
* - avoid tail-call optimization (either by the C compiler or
|
||||||
|
* aot-compiler)
|
||||||
|
*/
|
||||||
|
if (x == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return consume_stack_cb(x - 1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
host_consume_stack_cb(int x)
|
||||||
|
{
|
||||||
|
return host_consume_stack(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((export_name("test"))) uint32_t
|
||||||
|
test(uint32_t native_stack, uint32_t recurse_count)
|
||||||
|
{
|
||||||
|
uint32_t ret;
|
||||||
|
ret = host_consume_stack_and_call_indirect(cb, 321, native_stack);
|
||||||
|
ret = host_consume_stack_and_call_indirect(consume_stack_cb, recurse_count,
|
||||||
|
native_stack);
|
||||||
|
#if 0 /* notyet */
|
||||||
|
ret = host_consume_stack_and_call_indirect(host_consume_stack_cb, 1000000,
|
||||||
|
native_stack);
|
||||||
|
#endif
|
||||||
|
return 42;
|
||||||
|
}
|
|
@ -95,7 +95,7 @@ def ignore_the_case(
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if gc_flag:
|
if gc_flag:
|
||||||
if case_name in ["type-equivalence", "type-rec", "array_init_elem", "array_init_data"]:
|
if case_name in ["array_init_elem", "array_init_data"]:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if sgx_flag:
|
if sgx_flag:
|
||||||
|
|
|
@ -9,78 +9,6 @@ index 335496f0..5b975028 100644
|
||||||
- "integer representation too long"
|
- "integer representation too long"
|
||||||
+ "invalid type flag" ;; In GC extension, the first byte in rectype define is just one byte, not LEB128 encoded.
|
+ "invalid type flag" ;; In GC extension, the first byte in rectype define is just one byte, not LEB128 encoded.
|
||||||
)
|
)
|
||||||
diff --git a/test/core/binary.wast b/test/core/binary.wast
|
|
||||||
index 1661a1c6..84c716b9 100644
|
|
||||||
--- a/test/core/binary.wast
|
|
||||||
+++ b/test/core/binary.wast
|
|
||||||
@@ -1082,7 +1082,7 @@
|
|
||||||
)
|
|
||||||
|
|
||||||
;; 1 br_table target declared, 2 given
|
|
||||||
-(assert_malformed
|
|
||||||
+(;assert_malformed
|
|
||||||
(module binary
|
|
||||||
"\00asm" "\01\00\00\00"
|
|
||||||
"\01\04\01" ;; type section
|
|
||||||
@@ -1132,3 +1132,4 @@
|
|
||||||
)
|
|
||||||
"unexpected content after last section"
|
|
||||||
)
|
|
||||||
+;)
|
|
||||||
diff --git a/test/core/data.wast b/test/core/data.wast
|
|
||||||
index a5c87fbb..6f948bae 100644
|
|
||||||
--- a/test/core/data.wast
|
|
||||||
+++ b/test/core/data.wast
|
|
||||||
@@ -306,9 +306,10 @@
|
|
||||||
"\02\01\41\00\0b" ;; active data segment 0 for memory 1
|
|
||||||
"\00" ;; empty vec(byte)
|
|
||||||
)
|
|
||||||
- "unknown memory 1"
|
|
||||||
+ "unknown memory"
|
|
||||||
)
|
|
||||||
|
|
||||||
+(; not supported by wat2wasm
|
|
||||||
;; Data segment with memory index 0 (no memory section)
|
|
||||||
(assert_invalid
|
|
||||||
(module binary
|
|
||||||
@@ -317,7 +318,7 @@
|
|
||||||
"\00\41\00\0b" ;; active data segment 0 for memory 0
|
|
||||||
"\00" ;; empty vec(byte)
|
|
||||||
)
|
|
||||||
- "unknown memory 0"
|
|
||||||
+ "unknown memory"
|
|
||||||
)
|
|
||||||
|
|
||||||
;; Data segment with memory index 1 (no memory section)
|
|
||||||
@@ -328,7 +329,7 @@
|
|
||||||
"\02\01\41\00\0b" ;; active data segment 0 for memory 1
|
|
||||||
"\00" ;; empty vec(byte)
|
|
||||||
)
|
|
||||||
- "unknown memory 1"
|
|
||||||
+ "unknown memory"
|
|
||||||
)
|
|
||||||
|
|
||||||
;; Data segment with memory index 1 and vec(byte) as above,
|
|
||||||
@@ -348,7 +349,7 @@
|
|
||||||
"\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f"
|
|
||||||
"\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d"
|
|
||||||
)
|
|
||||||
- "unknown memory 1"
|
|
||||||
+ "unknown memory"
|
|
||||||
)
|
|
||||||
|
|
||||||
;; Data segment with memory index 1 and specially crafted vec(byte) after.
|
|
||||||
@@ -368,8 +369,9 @@
|
|
||||||
"\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f"
|
|
||||||
"\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d"
|
|
||||||
)
|
|
||||||
- "unknown memory 1"
|
|
||||||
+ "unknown memory"
|
|
||||||
)
|
|
||||||
+;)
|
|
||||||
|
|
||||||
|
|
||||||
;; Invalid offsets
|
|
||||||
diff --git a/test/core/elem.wast b/test/core/elem.wast
|
diff --git a/test/core/elem.wast b/test/core/elem.wast
|
||||||
index df1610f6..32c1d8b3 100644
|
index df1610f6..32c1d8b3 100644
|
||||||
--- a/test/core/elem.wast
|
--- a/test/core/elem.wast
|
||||||
|
@ -268,196 +196,11 @@ index 00000000..32650644
|
||||||
+ )
|
+ )
|
||||||
+ "unsupported initializer expression for table"
|
+ "unsupported initializer expression for table"
|
||||||
+)
|
+)
|
||||||
diff --git a/test/core/gc/ref_test.wast b/test/core/gc/ref_test.wast
|
|
||||||
index 590b81b8..e0aa49ed 100644
|
|
||||||
--- a/test/core/gc/ref_test.wast
|
|
||||||
+++ b/test/core/gc/ref_test.wast
|
|
||||||
@@ -310,15 +310,16 @@
|
|
||||||
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 11)))))
|
|
||||||
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 12)))))
|
|
||||||
|
|
||||||
- (br_if $l (i32.eqz (ref.test (ref $t1') (table.get (i32.const 1)))))
|
|
||||||
- (br_if $l (i32.eqz (ref.test (ref $t1') (table.get (i32.const 2)))))
|
|
||||||
+ ;; Must have explicit sub relationship
|
|
||||||
+ ;; (br_if $l (i32.eqz (ref.test (ref $t1') (table.get (i32.const 1)))))
|
|
||||||
+ ;; (br_if $l (i32.eqz (ref.test (ref $t1') (table.get (i32.const 2)))))
|
|
||||||
|
|
||||||
- (br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 11)))))
|
|
||||||
- (br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 12)))))
|
|
||||||
+ ;; (br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 11)))))
|
|
||||||
+ ;; (br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 12)))))
|
|
||||||
|
|
||||||
- (br_if $l (i32.eqz (ref.test (ref $t2') (table.get (i32.const 2)))))
|
|
||||||
+ ;; (br_if $l (i32.eqz (ref.test (ref $t2') (table.get (i32.const 2)))))
|
|
||||||
|
|
||||||
- (br_if $l (i32.eqz (ref.test (ref $t2) (table.get (i32.const 12)))))
|
|
||||||
+ ;; (br_if $l (i32.eqz (ref.test (ref $t2) (table.get (i32.const 12)))))
|
|
||||||
|
|
||||||
(return)
|
|
||||||
)
|
|
||||||
diff --git a/test/core/gc/type-subtyping.wast b/test/core/gc/type-subtyping.wast
|
diff --git a/test/core/gc/type-subtyping.wast b/test/core/gc/type-subtyping.wast
|
||||||
index a9022fc3..4e22e91b 100644
|
index a9022fc3..4aa36e2a 100644
|
||||||
--- a/test/core/gc/type-subtyping.wast
|
--- a/test/core/gc/type-subtyping.wast
|
||||||
+++ b/test/core/gc/type-subtyping.wast
|
+++ b/test/core/gc/type-subtyping.wast
|
||||||
@@ -112,6 +112,8 @@
|
@@ -740,7 +740,7 @@
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
+;; don't support recursive type equality and subtype check
|
|
||||||
+(;
|
|
||||||
(module
|
|
||||||
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
|
|
||||||
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
|
|
||||||
@@ -135,6 +137,7 @@
|
|
||||||
(func $g (type $g2))
|
|
||||||
(global (ref $g1) (ref.func $g))
|
|
||||||
)
|
|
||||||
+;)
|
|
||||||
|
|
||||||
(assert_invalid
|
|
||||||
(module
|
|
||||||
@@ -156,6 +159,8 @@
|
|
||||||
(global (ref $f1) (ref.func $g))
|
|
||||||
)
|
|
||||||
|
|
||||||
+;; don't support recursive type equality and subtype check
|
|
||||||
+(;
|
|
||||||
(module
|
|
||||||
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
|
|
||||||
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
|
|
||||||
@@ -201,6 +206,7 @@
|
|
||||||
(global (ref $g12) (ref.func $g12))
|
|
||||||
(global (ref $g22) (ref.func $g12))
|
|
||||||
)
|
|
||||||
+;)
|
|
||||||
|
|
||||||
(assert_invalid
|
|
||||||
(module
|
|
||||||
@@ -226,6 +232,8 @@
|
|
||||||
|
|
||||||
;; Runtime types
|
|
||||||
|
|
||||||
+;; don't support recursive type equality and subtype check
|
|
||||||
+(;
|
|
||||||
(module
|
|
||||||
(type $t0 (sub (func (result (ref null func)))))
|
|
||||||
(rec (type $t1 (sub $t0 (func (result (ref null $t1))))))
|
|
||||||
@@ -286,6 +294,7 @@
|
|
||||||
(assert_trap (invoke "fail4") "cast")
|
|
||||||
(assert_trap (invoke "fail5") "cast")
|
|
||||||
(assert_trap (invoke "fail6") "cast")
|
|
||||||
+;)
|
|
||||||
|
|
||||||
(module
|
|
||||||
(type $t1 (sub (func)))
|
|
||||||
@@ -316,7 +325,8 @@
|
|
||||||
(assert_trap (invoke "fail3") "cast")
|
|
||||||
(assert_trap (invoke "fail4") "cast")
|
|
||||||
|
|
||||||
-
|
|
||||||
+;; don't support recursive type equality and subtype check
|
|
||||||
+(;
|
|
||||||
(module
|
|
||||||
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
|
|
||||||
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
|
|
||||||
@@ -346,6 +356,7 @@
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(assert_return (invoke "run") (i32.const 1))
|
|
||||||
+;)
|
|
||||||
|
|
||||||
(module
|
|
||||||
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
|
|
||||||
@@ -370,6 +381,8 @@
|
|
||||||
)
|
|
||||||
(assert_return (invoke "run") (i32.const 1))
|
|
||||||
|
|
||||||
+;; don't support recursive type equality and subtype check
|
|
||||||
+(;
|
|
||||||
(module
|
|
||||||
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
|
|
||||||
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
|
|
||||||
@@ -390,7 +403,6 @@
|
|
||||||
)
|
|
||||||
(assert_return (invoke "run") (i32.const 1) (i32.const 1))
|
|
||||||
|
|
||||||
-
|
|
||||||
(module
|
|
||||||
(rec (type $f11 (sub (func (result (ref func))))) (type $f12 (sub $f11 (func (result (ref $f11))))))
|
|
||||||
(rec (type $f21 (sub (func (result (ref func))))) (type $f22 (sub $f21 (func (result (ref $f21))))))
|
|
||||||
@@ -429,7 +441,9 @@
|
|
||||||
(i32.const 1) (i32.const 1) (i32.const 1) (i32.const 1)
|
|
||||||
(i32.const 1) (i32.const 1) (i32.const 1) (i32.const 1)
|
|
||||||
)
|
|
||||||
+;)
|
|
||||||
|
|
||||||
+(; we use normalized function type index
|
|
||||||
(module
|
|
||||||
(rec (type $f11 (sub (func))) (type $f12 (sub $f11 (func))))
|
|
||||||
(rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func))))
|
|
||||||
@@ -439,6 +453,7 @@
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(assert_return (invoke "run") (i32.const 0))
|
|
||||||
+;)
|
|
||||||
|
|
||||||
(module
|
|
||||||
(rec (type $f01 (sub (func))) (type $f02 (sub $f01 (func))))
|
|
||||||
@@ -547,15 +562,15 @@
|
|
||||||
(func (import "M3" "g") (type $g1))
|
|
||||||
)
|
|
||||||
|
|
||||||
-(module
|
|
||||||
- (rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
|
|
||||||
- (rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
|
|
||||||
- (rec
|
|
||||||
- (type $g2 (sub $f2 (func)))
|
|
||||||
- (type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
|
|
||||||
- )
|
|
||||||
- (func (export "g") (type $g2))
|
|
||||||
-)
|
|
||||||
+;; (module
|
|
||||||
+;; (rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
|
|
||||||
+;; (rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
|
|
||||||
+;; (rec
|
|
||||||
+;; (type $g2 (sub $f2 (func)))
|
|
||||||
+;; (type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
|
|
||||||
+;; )
|
|
||||||
+;; (func (export "g") (type $g2))
|
|
||||||
+;; )
|
|
||||||
(register "M4")
|
|
||||||
(module
|
|
||||||
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
|
|
||||||
@@ -597,17 +612,17 @@
|
|
||||||
(func (import "M6" "g") (type $f1))
|
|
||||||
)
|
|
||||||
|
|
||||||
-(module
|
|
||||||
- (rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
|
|
||||||
- (rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
|
|
||||||
- (rec
|
|
||||||
- (type $g2 (sub $f2 (func)))
|
|
||||||
- (type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
|
|
||||||
- )
|
|
||||||
- (rec (type $h (sub $g2 (func))) (type (struct)))
|
|
||||||
- (func (export "h") (type $h))
|
|
||||||
-)
|
|
||||||
-(register "M7")
|
|
||||||
+;; (module
|
|
||||||
+;; (rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
|
|
||||||
+;; (rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
|
|
||||||
+;; (rec
|
|
||||||
+;; (type $g2 (sub $f2 (func)))
|
|
||||||
+;; (type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
|
|
||||||
+;; )
|
|
||||||
+;; (rec (type $h (sub $g2 (func))) (type (struct)))
|
|
||||||
+;; (func (export "h") (type $h))
|
|
||||||
+;; )
|
|
||||||
+;; (register "M7")
|
|
||||||
(module
|
|
||||||
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
|
|
||||||
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
|
|
||||||
@@ -740,7 +755,7 @@
|
|
||||||
"sub type"
|
"sub type"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -466,7 +209,7 @@ index a9022fc3..4e22e91b 100644
|
||||||
(module
|
(module
|
||||||
(type $f0 (sub (func (param i32) (result i32))))
|
(type $f0 (sub (func (param i32) (result i32))))
|
||||||
(type $s0 (sub $f0 (struct)))
|
(type $s0 (sub $f0 (struct)))
|
||||||
@@ -764,7 +779,7 @@
|
@@ -764,7 +764,7 @@
|
||||||
"sub type"
|
"sub type"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -475,7 +218,7 @@ index a9022fc3..4e22e91b 100644
|
||||||
(module
|
(module
|
||||||
(type $s0 (sub (struct)))
|
(type $s0 (sub (struct)))
|
||||||
(type $f0 (sub $s0 (func (param i32) (result i32))))
|
(type $f0 (sub $s0 (func (param i32) (result i32))))
|
||||||
@@ -772,7 +787,7 @@
|
@@ -772,7 +772,7 @@
|
||||||
"sub type"
|
"sub type"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1262,29 +1005,3 @@ index 0b2d26f7..bdab6a01 100644
|
||||||
(table $t0 30 30 funcref)
|
(table $t0 30 30 funcref)
|
||||||
(table $t1 30 30 funcref)
|
(table $t1 30 30 funcref)
|
||||||
(elem (table $t1) (i32.const 2) func 3 1 4 1)
|
(elem (table $t1) (i32.const 2) func 3 1 4 1)
|
||||||
diff --git a/test/core/unreached-valid.wast b/test/core/unreached-valid.wast
|
|
||||||
index f3feb0f3..d8ef8743 100644
|
|
||||||
--- a/test/core/unreached-valid.wast
|
|
||||||
+++ b/test/core/unreached-valid.wast
|
|
||||||
@@ -60,7 +60,7 @@
|
|
||||||
|
|
||||||
;; Validation after unreachable
|
|
||||||
|
|
||||||
-(module
|
|
||||||
+(;module
|
|
||||||
(func (export "meet-bottom")
|
|
||||||
(block (result f64)
|
|
||||||
(block (result f32)
|
|
||||||
@@ -76,7 +76,6 @@
|
|
||||||
|
|
||||||
(assert_trap (invoke "meet-bottom") "unreachable")
|
|
||||||
|
|
||||||
-
|
|
||||||
;; Bottom heap type
|
|
||||||
|
|
||||||
(module
|
|
||||||
@@ -106,3 +105,4 @@
|
|
||||||
(unreachable)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
+;)
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user