mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-09 13:16:26 +00:00
Merge branch 'main' into godjan/iterate_callstack
This commit is contained in:
commit
b9039f986e
3
.github/workflows/spec_test_on_nuttx.yml
vendored
3
.github/workflows/spec_test_on_nuttx.yml
vendored
|
@ -127,7 +127,8 @@ jobs:
|
||||||
wamr_feature_option:
|
wamr_feature_option:
|
||||||
# Empty option for default
|
# Empty option for default
|
||||||
- { option: "", mode: "" }
|
- { option: "", mode: "" }
|
||||||
- { option: "CONFIG_INTERPRETERS_WAMR_GC CONFIG_INTERPRETERS_WAMR_AOT_STACK_FRAME", mode: "-G" }
|
# need to install menhir
|
||||||
|
# - { option: "CONFIG_INTERPRETERS_WAMR_GC CONFIG_INTERPRETERS_WAMR_AOT_STACK_FRAME", mode: "-G" }
|
||||||
|
|
||||||
exclude:
|
exclude:
|
||||||
# XIP is not fully supported yet on RISCV64, some relocations can not be resolved
|
# XIP is not fully supported yet on RISCV64, some relocations can not be resolved
|
||||||
|
|
|
@ -3047,9 +3047,9 @@ static const char *exception_msgs[] = {
|
||||||
"wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */
|
"wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */
|
||||||
"failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
|
"failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
|
||||||
/* GC related exceptions */
|
/* GC related exceptions */
|
||||||
"null function object", /* EXCE_NULL_FUNC_OBJ */
|
"null function reference", /* EXCE_NULL_FUNC_OBJ */
|
||||||
"null structure object", /* EXCE_NULL_STRUCT_OBJ */
|
"null structure reference", /* EXCE_NULL_STRUCT_OBJ */
|
||||||
"null array reference", /* EXCE_NULL_ARRAY_OBJ */
|
"null array reference", /* EXCE_NULL_ARRAY_OBJ */
|
||||||
"null i31 reference", /* EXCE_NULL_I31_OBJ */
|
"null i31 reference", /* EXCE_NULL_I31_OBJ */
|
||||||
"null reference", /* EXCE_NULL_REFERENCE */
|
"null reference", /* EXCE_NULL_REFERENCE */
|
||||||
"create rtt type failed", /* EXCE_FAILED_TO_CREATE_RTT_TYPE */
|
"create rtt type failed", /* EXCE_FAILED_TO_CREATE_RTT_TYPE */
|
||||||
|
@ -3057,7 +3057,7 @@ static const char *exception_msgs[] = {
|
||||||
"create array object failed", /* EXCE_FAILED_TO_CREATE_ARRAY_OBJ */
|
"create array object failed", /* EXCE_FAILED_TO_CREATE_ARRAY_OBJ */
|
||||||
"create externref object failed", /* EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ */
|
"create externref object failed", /* EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ */
|
||||||
"cast failure", /* EXCE_CAST_FAILURE */
|
"cast failure", /* EXCE_CAST_FAILURE */
|
||||||
"out of bounds array access", /* EXCE_ARRAY_IDX_OOB */
|
"out of bounds array access", /* EXCE_ARRAY_IDX_OOB */
|
||||||
/* stringref related exceptions */
|
/* stringref related exceptions */
|
||||||
"create string object failed", /* EXCE_FAILED_TO_CREATE_STRING */
|
"create string object failed", /* EXCE_FAILED_TO_CREATE_STRING */
|
||||||
"create stringref failed", /* EXCE_FAILED_TO_CREATE_STRINGREF */
|
"create stringref failed", /* EXCE_FAILED_TO_CREATE_STRINGREF */
|
||||||
|
|
|
@ -2649,7 +2649,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
||||||
func_obj = POP_REF();
|
func_obj = POP_REF();
|
||||||
if (!func_obj) {
|
if (!func_obj) {
|
||||||
wasm_set_exception(module, "null function object");
|
wasm_set_exception(module, "null function reference");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2666,7 +2666,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
||||||
func_obj = POP_REF();
|
func_obj = POP_REF();
|
||||||
if (!func_obj) {
|
if (!func_obj) {
|
||||||
wasm_set_exception(module, "null function object");
|
wasm_set_exception(module, "null function reference");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2813,7 +2813,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
struct_obj = POP_REF();
|
struct_obj = POP_REF();
|
||||||
|
|
||||||
if (!struct_obj) {
|
if (!struct_obj) {
|
||||||
wasm_set_exception(module, "null structure object");
|
wasm_set_exception(module,
|
||||||
|
"null structure reference");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2869,7 +2870,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
|
|
||||||
struct_obj = POP_REF();
|
struct_obj = POP_REF();
|
||||||
if (!struct_obj) {
|
if (!struct_obj) {
|
||||||
wasm_set_exception(module, "null structure object");
|
wasm_set_exception(module,
|
||||||
|
"null structure reference");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1992,7 +1992,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
#endif
|
#endif
|
||||||
func_obj = POP_REF();
|
func_obj = POP_REF();
|
||||||
if (!func_obj) {
|
if (!func_obj) {
|
||||||
wasm_set_exception(module, "null function object");
|
wasm_set_exception(module, "null function reference");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2007,7 +2007,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
#endif
|
#endif
|
||||||
func_obj = POP_REF();
|
func_obj = POP_REF();
|
||||||
if (!func_obj) {
|
if (!func_obj) {
|
||||||
wasm_set_exception(module, "null function object");
|
wasm_set_exception(module, "null function reference");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2148,7 +2148,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
struct_obj = POP_REF();
|
struct_obj = POP_REF();
|
||||||
|
|
||||||
if (!struct_obj) {
|
if (!struct_obj) {
|
||||||
wasm_set_exception(module, "null structure object");
|
wasm_set_exception(module,
|
||||||
|
"null structure reference");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2204,7 +2205,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||||
|
|
||||||
struct_obj = POP_REF();
|
struct_obj = POP_REF();
|
||||||
if (!struct_obj) {
|
if (!struct_obj) {
|
||||||
wasm_set_exception(module, "null structure object");
|
wasm_set_exception(module,
|
||||||
|
"null structure reference");
|
||||||
goto got_exception;
|
goto got_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -355,9 +355,14 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
|
||||||
{
|
{
|
||||||
uint8 *mem_new;
|
uint8 *mem_new;
|
||||||
bh_assert(size_new > size_old);
|
bh_assert(size_new > size_old);
|
||||||
|
|
||||||
|
if ((mem_new = wasm_runtime_realloc(mem_old, size_new))) {
|
||||||
|
memset(mem_new + size_old, 0, size_new - size_old);
|
||||||
|
return mem_new;
|
||||||
|
}
|
||||||
|
|
||||||
if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) {
|
if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) {
|
||||||
bh_memcpy_s(mem_new, size_new, mem_old, size_old);
|
bh_memcpy_s(mem_new, size_new, mem_old, size_old);
|
||||||
memset(mem_new + size_old, 0, size_new - size_old);
|
|
||||||
wasm_runtime_free(mem_old);
|
wasm_runtime_free(mem_old);
|
||||||
}
|
}
|
||||||
return mem_new;
|
return mem_new;
|
||||||
|
@ -2134,8 +2139,9 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||||
if (!wasm_type_is_subtype_of(cur_type, parent_type,
|
if (!wasm_type_is_subtype_of(cur_type, parent_type,
|
||||||
module->types,
|
module->types,
|
||||||
module->type_count)) {
|
module->type_count)) {
|
||||||
set_error_buf(error_buf, error_buf_size,
|
set_error_buf_v(error_buf, error_buf_size,
|
||||||
"sub type does not match super type");
|
"sub type %u does not match super type",
|
||||||
|
processed_type_count + j);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4707,6 +4713,21 @@ fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
|
static bool
|
||||||
|
check_data_count_consistency(bool has_datacount_section, int datacount_len,
|
||||||
|
int data_seg_len, char *error_buf,
|
||||||
|
uint32 error_buf_size)
|
||||||
|
{
|
||||||
|
if (has_datacount_section && datacount_len != data_seg_len) {
|
||||||
|
set_error_buf(error_buf, error_buf_size,
|
||||||
|
"data count and data section have inconsistent lengths");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
|
load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
|
||||||
WASMModule *module,
|
WASMModule *module,
|
||||||
|
@ -4730,9 +4751,9 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
|
||||||
read_leb_uint32(p, p_end, data_seg_count);
|
read_leb_uint32(p, p_end, data_seg_count);
|
||||||
|
|
||||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
if (has_datacount_section && data_seg_count != module->data_seg_count1) {
|
if (!check_data_count_consistency(has_datacount_section,
|
||||||
set_error_buf(error_buf, error_buf_size,
|
module->data_seg_count1, data_seg_count,
|
||||||
"data count and data section have inconsistent lengths");
|
error_buf, error_buf_size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -5920,6 +5941,14 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
section = section->next;
|
section = section->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
|
if (!check_data_count_consistency(
|
||||||
|
has_datacount_section, module->data_seg_count1,
|
||||||
|
module->data_seg_count, error_buf, error_buf_size)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
module->aux_data_end_global_index = (uint32)-1;
|
module->aux_data_end_global_index = (uint32)-1;
|
||||||
module->aux_heap_base_global_index = (uint32)-1;
|
module->aux_heap_base_global_index = (uint32)-1;
|
||||||
module->aux_stack_top_global_index = (uint32)-1;
|
module->aux_stack_top_global_index = (uint32)-1;
|
||||||
|
@ -7949,11 +7978,16 @@ typedef struct WASMLoaderContext {
|
||||||
/* preserved local offset */
|
/* preserved local offset */
|
||||||
int16 preserved_local_offset;
|
int16 preserved_local_offset;
|
||||||
|
|
||||||
/* const buffer */
|
/* const buffer for i64 and f64 consts, note that the raw bytes
|
||||||
uint8 *const_buf;
|
* of i64 and f64 are the same, so we read an i64 value from an
|
||||||
uint16 num_const;
|
* f64 const with its raw bytes, something like `*(int64 *)&f64 */
|
||||||
uint16 const_cell_num;
|
int64 *i64_consts;
|
||||||
uint32 const_buf_size;
|
uint32 i64_const_max_num;
|
||||||
|
uint32 i64_const_num;
|
||||||
|
/* const buffer for i32 and f32 consts */
|
||||||
|
int32 *i32_consts;
|
||||||
|
uint32 i32_const_max_num;
|
||||||
|
uint32 i32_const_num;
|
||||||
|
|
||||||
/* processed code */
|
/* processed code */
|
||||||
uint8 *p_code_compiled;
|
uint8 *p_code_compiled;
|
||||||
|
@ -7966,12 +8000,6 @@ typedef struct WASMLoaderContext {
|
||||||
#endif
|
#endif
|
||||||
} WASMLoaderContext;
|
} WASMLoaderContext;
|
||||||
|
|
||||||
typedef struct Const {
|
|
||||||
WASMValue value;
|
|
||||||
uint16 slot_index;
|
|
||||||
uint8 value_type;
|
|
||||||
} Const;
|
|
||||||
|
|
||||||
#define CHECK_CSP_PUSH() \
|
#define CHECK_CSP_PUSH() \
|
||||||
do { \
|
do { \
|
||||||
if (ctx->frame_csp >= ctx->frame_csp_boundary) { \
|
if (ctx->frame_csp >= ctx->frame_csp_boundary) { \
|
||||||
|
@ -8189,8 +8217,10 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx)
|
||||||
#if WASM_ENABLE_FAST_INTERP != 0
|
#if WASM_ENABLE_FAST_INTERP != 0
|
||||||
if (ctx->frame_offset_bottom)
|
if (ctx->frame_offset_bottom)
|
||||||
wasm_runtime_free(ctx->frame_offset_bottom);
|
wasm_runtime_free(ctx->frame_offset_bottom);
|
||||||
if (ctx->const_buf)
|
if (ctx->i64_consts)
|
||||||
wasm_runtime_free(ctx->const_buf);
|
wasm_runtime_free(ctx->i64_consts);
|
||||||
|
if (ctx->i32_consts)
|
||||||
|
wasm_runtime_free(ctx->i32_consts);
|
||||||
#endif
|
#endif
|
||||||
wasm_runtime_free(ctx);
|
wasm_runtime_free(ctx);
|
||||||
}
|
}
|
||||||
|
@ -8238,10 +8268,15 @@ wasm_loader_ctx_init(WASMFunction *func, char *error_buf, uint32 error_buf_size)
|
||||||
goto fail;
|
goto fail;
|
||||||
loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32;
|
loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32;
|
||||||
|
|
||||||
loader_ctx->num_const = 0;
|
loader_ctx->i64_const_max_num = 8;
|
||||||
loader_ctx->const_buf_size = sizeof(Const) * 8;
|
if (!(loader_ctx->i64_consts =
|
||||||
if (!(loader_ctx->const_buf = loader_malloc(loader_ctx->const_buf_size,
|
loader_malloc(sizeof(int64) * loader_ctx->i64_const_max_num,
|
||||||
error_buf, error_buf_size)))
|
error_buf, error_buf_size)))
|
||||||
|
goto fail;
|
||||||
|
loader_ctx->i32_const_max_num = 8;
|
||||||
|
if (!(loader_ctx->i32_consts =
|
||||||
|
loader_malloc(sizeof(int32) * loader_ctx->i32_const_max_num,
|
||||||
|
error_buf, error_buf_size)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (func->param_cell_num >= (int32)INT16_MAX - func->local_cell_num) {
|
if (func->param_cell_num >= (int32)INT16_MAX - func->local_cell_num) {
|
||||||
|
@ -9489,108 +9524,116 @@ wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmp_i64_const(const void *p_i64_const1, const void *p_i64_const2)
|
||||||
|
{
|
||||||
|
int64 i64_const1 = *(int64 *)p_i64_const1;
|
||||||
|
int64 i64_const2 = *(int64 *)p_i64_const2;
|
||||||
|
|
||||||
|
return (i64_const1 < i64_const2) ? -1 : (i64_const1 > i64_const2) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmp_i32_const(const void *p_i32_const1, const void *p_i32_const2)
|
||||||
|
{
|
||||||
|
int32 i32_const1 = *(int32 *)p_i32_const1;
|
||||||
|
int32 i32_const2 = *(int32 *)p_i32_const2;
|
||||||
|
|
||||||
|
return (i32_const1 < i32_const2) ? -1 : (i32_const1 > i32_const2) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value,
|
wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value,
|
||||||
int16 *offset, char *error_buf,
|
int16 *offset, char *error_buf,
|
||||||
uint32 error_buf_size)
|
uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
int8 bytes_to_increase;
|
if (!ctx->p_code_compiled) {
|
||||||
int16 operand_offset = 0;
|
/* Treat i64 and f64 as the same by reading i64 value from
|
||||||
Const *c;
|
the raw bytes */
|
||||||
|
if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) {
|
||||||
|
/* No slot left, emit const instead */
|
||||||
|
if (ctx->i64_const_num * 2 + ctx->i32_const_num > INT16_MAX - 2) {
|
||||||
|
*offset = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Search existing constant */
|
/* Traverse the list if the const num is small */
|
||||||
for (c = (Const *)ctx->const_buf;
|
if (ctx->i64_const_num < 10) {
|
||||||
(uint8 *)c < ctx->const_buf + ctx->num_const * sizeof(Const); c++) {
|
for (uint32 i = 0; i < ctx->i64_const_num; i++) {
|
||||||
/* TODO: handle v128 type? */
|
if (ctx->i64_consts[i] == *(int64 *)value) {
|
||||||
if ((type == c->value_type)
|
*offset = -1;
|
||||||
&& ((type == VALUE_TYPE_I64 && *(int64 *)value == c->value.i64)
|
return true;
|
||||||
|| (type == VALUE_TYPE_I32 && *(int32 *)value == c->value.i32)
|
}
|
||||||
#if WASM_ENABLE_REF_TYPES != 0 && WASM_ENABLE_GC == 0
|
}
|
||||||
|| (type == VALUE_TYPE_FUNCREF
|
}
|
||||||
&& *(int32 *)value == c->value.i32)
|
|
||||||
|| (type == VALUE_TYPE_EXTERNREF
|
|
||||||
&& *(int32 *)value == c->value.i32)
|
|
||||||
#endif
|
|
||||||
|| (type == VALUE_TYPE_F64
|
|
||||||
&& (0 == memcmp(value, &(c->value.f64), sizeof(float64))))
|
|
||||||
|| (type == VALUE_TYPE_F32
|
|
||||||
&& (0
|
|
||||||
== memcmp(value, &(c->value.f32), sizeof(float32)))))) {
|
|
||||||
operand_offset = c->slot_index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (is_32bit_type(c->value_type))
|
|
||||||
operand_offset += 1;
|
|
||||||
else
|
|
||||||
operand_offset += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((uint8 *)c == ctx->const_buf + ctx->num_const * sizeof(Const)) {
|
if (ctx->i64_const_num >= ctx->i64_const_max_num) {
|
||||||
/* New constant, append to the const buffer */
|
MEM_REALLOC(ctx->i64_consts,
|
||||||
if ((type == VALUE_TYPE_F64) || (type == VALUE_TYPE_I64)) {
|
sizeof(int64) * ctx->i64_const_max_num,
|
||||||
bytes_to_increase = 2;
|
sizeof(int64) * (ctx->i64_const_max_num * 2));
|
||||||
|
ctx->i64_const_max_num *= 2;
|
||||||
|
}
|
||||||
|
ctx->i64_consts[ctx->i64_const_num++] = *(int64 *)value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bytes_to_increase = 1;
|
/* Treat i32 and f32 as the same by reading i32 value from
|
||||||
|
the raw bytes */
|
||||||
|
bh_assert(type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32);
|
||||||
|
|
||||||
|
/* No slot left, emit const instead */
|
||||||
|
if (ctx->i64_const_num * 2 + ctx->i32_const_num > INT16_MAX - 1) {
|
||||||
|
*offset = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Traverse the list if the const num is small */
|
||||||
|
if (ctx->i32_const_num < 10) {
|
||||||
|
for (uint32 i = 0; i < ctx->i32_const_num; i++) {
|
||||||
|
if (ctx->i32_consts[i] == *(int32 *)value) {
|
||||||
|
*offset = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->i32_const_num >= ctx->i32_const_max_num) {
|
||||||
|
MEM_REALLOC(ctx->i32_consts,
|
||||||
|
sizeof(int32) * ctx->i32_const_max_num,
|
||||||
|
sizeof(int32) * (ctx->i32_const_max_num * 2));
|
||||||
|
ctx->i32_const_max_num *= 2;
|
||||||
|
}
|
||||||
|
ctx->i32_consts[ctx->i32_const_num++] = *(int32 *)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The max cell num of const buffer is 32768 since the valid index range
|
*offset = -1;
|
||||||
* is -32768 ~ -1. Return an invalid index 0 to indicate the buffer is
|
return true;
|
||||||
* full */
|
}
|
||||||
if (ctx->const_cell_num > INT16_MAX - bytes_to_increase + 1) {
|
else {
|
||||||
*offset = 0;
|
if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) {
|
||||||
return true;
|
int64 key = *(int64 *)value, *i64_const;
|
||||||
}
|
i64_const = bsearch(&key, ctx->i64_consts, ctx->i64_const_num,
|
||||||
|
sizeof(int64), cmp_i64_const);
|
||||||
if ((uint8 *)c == ctx->const_buf + ctx->const_buf_size) {
|
if (!i64_const) { /* not found, emit const instead */
|
||||||
MEM_REALLOC(ctx->const_buf, ctx->const_buf_size,
|
*offset = 0;
|
||||||
ctx->const_buf_size + 4 * sizeof(Const));
|
return true;
|
||||||
ctx->const_buf_size += 4 * sizeof(Const);
|
}
|
||||||
c = (Const *)(ctx->const_buf + ctx->num_const * sizeof(Const));
|
*offset = -(uint32)(ctx->i64_const_num * 2 + ctx->i32_const_num)
|
||||||
}
|
+ (uint32)(i64_const - ctx->i64_consts) * 2;
|
||||||
c->value_type = type;
|
}
|
||||||
switch (type) {
|
else {
|
||||||
case VALUE_TYPE_F64:
|
int32 key = *(int32 *)value, *i32_const;
|
||||||
bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value,
|
i32_const = bsearch(&key, ctx->i32_consts, ctx->i32_const_num,
|
||||||
sizeof(float64));
|
sizeof(int32), cmp_i32_const);
|
||||||
ctx->const_cell_num += 2;
|
if (!i32_const) { /* not found, emit const instead */
|
||||||
/* The const buf will be reversed, we use the second cell */
|
*offset = 0;
|
||||||
/* of the i64/f64 const so the final offset is correct */
|
return true;
|
||||||
operand_offset++;
|
}
|
||||||
break;
|
*offset = -(uint32)(ctx->i32_const_num)
|
||||||
case VALUE_TYPE_I64:
|
+ (uint32)(i32_const - ctx->i32_consts);
|
||||||
c->value.i64 = *(int64 *)value;
|
}
|
||||||
ctx->const_cell_num += 2;
|
|
||||||
operand_offset++;
|
return true;
|
||||||
break;
|
|
||||||
case VALUE_TYPE_F32:
|
|
||||||
bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value,
|
|
||||||
sizeof(float32));
|
|
||||||
ctx->const_cell_num++;
|
|
||||||
break;
|
|
||||||
case VALUE_TYPE_I32:
|
|
||||||
c->value.i32 = *(int32 *)value;
|
|
||||||
ctx->const_cell_num++;
|
|
||||||
break;
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0 && WASM_ENABLE_GC == 0
|
|
||||||
case VALUE_TYPE_EXTERNREF:
|
|
||||||
case VALUE_TYPE_FUNCREF:
|
|
||||||
c->value.i32 = *(int32 *)value;
|
|
||||||
ctx->const_cell_num++;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
c->slot_index = operand_offset;
|
|
||||||
ctx->num_const++;
|
|
||||||
LOG_OP("#### new const [%d]: %ld\n", ctx->num_const,
|
|
||||||
(int64)c->value.i64);
|
|
||||||
}
|
}
|
||||||
/* use negative index for const */
|
|
||||||
operand_offset = -(operand_offset + 1);
|
|
||||||
*offset = operand_offset;
|
|
||||||
return true;
|
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -11028,7 +11071,6 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
||||||
bool need_ref_type_map;
|
bool need_ref_type_map;
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_FAST_INTERP != 0
|
#if WASM_ENABLE_FAST_INTERP != 0
|
||||||
uint8 *func_const_end, *func_const = NULL;
|
|
||||||
int16 operand_offset = 0;
|
int16 operand_offset = 0;
|
||||||
uint8 last_op = 0;
|
uint8 last_op = 0;
|
||||||
bool disable_emit, preserve_local = false, if_condition_available = true;
|
bool disable_emit, preserve_local = false, if_condition_available = true;
|
||||||
|
@ -11095,6 +11137,68 @@ re_scan:
|
||||||
p = func->code;
|
p = func->code;
|
||||||
func->code_compiled = loader_ctx->p_code_compiled;
|
func->code_compiled = loader_ctx->p_code_compiled;
|
||||||
func->code_compiled_size = loader_ctx->code_compiled_size;
|
func->code_compiled_size = loader_ctx->code_compiled_size;
|
||||||
|
|
||||||
|
if (loader_ctx->i64_const_num > 0) {
|
||||||
|
int64 *i64_consts_old = loader_ctx->i64_consts;
|
||||||
|
|
||||||
|
/* Sort the i64 consts */
|
||||||
|
qsort(i64_consts_old, loader_ctx->i64_const_num, sizeof(int64),
|
||||||
|
cmp_i64_const);
|
||||||
|
|
||||||
|
/* Remove the duplicated i64 consts */
|
||||||
|
uint32 k = 1;
|
||||||
|
for (i = 1; i < loader_ctx->i64_const_num; i++) {
|
||||||
|
if (i64_consts_old[i] != i64_consts_old[i - 1]) {
|
||||||
|
i64_consts_old[k++] = i64_consts_old[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k < loader_ctx->i64_const_num) {
|
||||||
|
int64 *i64_consts_new;
|
||||||
|
/* Try to reallocate memory with a smaller size */
|
||||||
|
if ((i64_consts_new =
|
||||||
|
wasm_runtime_malloc((uint32)sizeof(int64) * k))) {
|
||||||
|
bh_memcpy_s(i64_consts_new, (uint32)sizeof(int64) * k,
|
||||||
|
i64_consts_old, (uint32)sizeof(int64) * k);
|
||||||
|
/* Free the old memory */
|
||||||
|
wasm_runtime_free(i64_consts_old);
|
||||||
|
loader_ctx->i64_consts = i64_consts_new;
|
||||||
|
loader_ctx->i64_const_max_num = k;
|
||||||
|
}
|
||||||
|
loader_ctx->i64_const_num = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loader_ctx->i32_const_num > 0) {
|
||||||
|
int32 *i32_consts_old = loader_ctx->i32_consts;
|
||||||
|
|
||||||
|
/* Sort the i32 consts */
|
||||||
|
qsort(i32_consts_old, loader_ctx->i32_const_num, sizeof(int32),
|
||||||
|
cmp_i32_const);
|
||||||
|
|
||||||
|
/* Remove the duplicated i32 consts */
|
||||||
|
uint32 k = 1;
|
||||||
|
for (i = 1; i < loader_ctx->i32_const_num; i++) {
|
||||||
|
if (i32_consts_old[i] != i32_consts_old[i - 1]) {
|
||||||
|
i32_consts_old[k++] = i32_consts_old[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k < loader_ctx->i32_const_num) {
|
||||||
|
int32 *i32_consts_new;
|
||||||
|
/* Try to reallocate memory with a smaller size */
|
||||||
|
if ((i32_consts_new =
|
||||||
|
wasm_runtime_malloc((uint32)sizeof(int32) * k))) {
|
||||||
|
bh_memcpy_s(i32_consts_new, (uint32)sizeof(int32) * k,
|
||||||
|
i32_consts_old, (uint32)sizeof(int32) * k);
|
||||||
|
/* Free the old memory */
|
||||||
|
wasm_runtime_free(i32_consts_old);
|
||||||
|
loader_ctx->i32_consts = i32_consts_new;
|
||||||
|
loader_ctx->i32_const_max_num = k;
|
||||||
|
}
|
||||||
|
loader_ctx->i32_const_num = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -16016,29 +16120,25 @@ re_scan:
|
||||||
if (loader_ctx->p_code_compiled == NULL)
|
if (loader_ctx->p_code_compiled == NULL)
|
||||||
goto re_scan;
|
goto re_scan;
|
||||||
|
|
||||||
func->const_cell_num = loader_ctx->const_cell_num;
|
func->const_cell_num =
|
||||||
|
loader_ctx->i64_const_num * 2 + loader_ctx->i32_const_num;
|
||||||
if (func->const_cell_num > 0) {
|
if (func->const_cell_num > 0) {
|
||||||
int32 j;
|
if (!(func->consts =
|
||||||
|
loader_malloc((uint64)sizeof(uint32) * func->const_cell_num,
|
||||||
if (!(func->consts = func_const = loader_malloc(
|
error_buf, error_buf_size)))
|
||||||
func->const_cell_num * 4, error_buf, error_buf_size)))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
if (loader_ctx->i64_const_num > 0) {
|
||||||
func_const_end = func->consts + func->const_cell_num * 4;
|
bh_memcpy_s(func->consts,
|
||||||
/* reverse the const buf */
|
(uint32)sizeof(int64) * loader_ctx->i64_const_num,
|
||||||
for (j = loader_ctx->num_const - 1; j >= 0; j--) {
|
loader_ctx->i64_consts,
|
||||||
Const *c = (Const *)(loader_ctx->const_buf + j * sizeof(Const));
|
(uint32)sizeof(int64) * loader_ctx->i64_const_num);
|
||||||
if (c->value_type == VALUE_TYPE_F64
|
}
|
||||||
|| c->value_type == VALUE_TYPE_I64) {
|
if (loader_ctx->i32_const_num > 0) {
|
||||||
bh_memcpy_s(func_const, (uint32)(func_const_end - func_const),
|
bh_memcpy_s(func->consts
|
||||||
&(c->value.f64), (uint32)sizeof(int64));
|
+ sizeof(int64) * loader_ctx->i64_const_num,
|
||||||
func_const += sizeof(int64);
|
(uint32)sizeof(int32) * loader_ctx->i32_const_num,
|
||||||
}
|
loader_ctx->i32_consts,
|
||||||
else {
|
(uint32)sizeof(int32) * loader_ctx->i32_const_num);
|
||||||
bh_memcpy_s(func_const, (uint32)(func_const_end - func_const),
|
|
||||||
&(c->value.f32), (uint32)sizeof(int32));
|
|
||||||
func_const += sizeof(int32);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,9 +208,14 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
|
||||||
{
|
{
|
||||||
uint8 *mem_new;
|
uint8 *mem_new;
|
||||||
bh_assert(size_new > size_old);
|
bh_assert(size_new > size_old);
|
||||||
|
|
||||||
|
if ((mem_new = wasm_runtime_realloc(mem_old, size_new))) {
|
||||||
|
memset(mem_new + size_old, 0, size_new - size_old);
|
||||||
|
return mem_new;
|
||||||
|
}
|
||||||
|
|
||||||
if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) {
|
if ((mem_new = loader_malloc(size_new, error_buf, error_buf_size))) {
|
||||||
bh_memcpy_s(mem_new, size_new, mem_old, size_old);
|
bh_memcpy_s(mem_new, size_new, mem_old, size_old);
|
||||||
memset(mem_new + size_old, 0, size_new - size_old);
|
|
||||||
wasm_runtime_free(mem_old);
|
wasm_runtime_free(mem_old);
|
||||||
}
|
}
|
||||||
return mem_new;
|
return mem_new;
|
||||||
|
@ -2729,6 +2734,11 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
||||||
section = section->next;
|
section = section->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||||
|
bh_assert(!has_datacount_section
|
||||||
|
|| module->data_seg_count == module->data_seg_count1);
|
||||||
|
#endif
|
||||||
|
|
||||||
module->aux_data_end_global_index = (uint32)-1;
|
module->aux_data_end_global_index = (uint32)-1;
|
||||||
module->aux_heap_base_global_index = (uint32)-1;
|
module->aux_heap_base_global_index = (uint32)-1;
|
||||||
module->aux_stack_top_global_index = (uint32)-1;
|
module->aux_stack_top_global_index = (uint32)-1;
|
||||||
|
@ -4047,11 +4057,16 @@ typedef struct WASMLoaderContext {
|
||||||
/* preserved local offset */
|
/* preserved local offset */
|
||||||
int16 preserved_local_offset;
|
int16 preserved_local_offset;
|
||||||
|
|
||||||
/* const buffer */
|
/* const buffer for i64 and f64 consts, note that the raw bytes
|
||||||
uint8 *const_buf;
|
* of i64 and f64 are the same, so we read an i64 value from an
|
||||||
uint16 num_const;
|
* f64 const with its raw bytes, something like `*(int64 *)&f64 */
|
||||||
uint16 const_cell_num;
|
int64 *i64_consts;
|
||||||
uint32 const_buf_size;
|
uint32 i64_const_max_num;
|
||||||
|
uint32 i64_const_num;
|
||||||
|
/* const buffer for i32 and f32 consts */
|
||||||
|
int32 *i32_consts;
|
||||||
|
uint32 i32_const_max_num;
|
||||||
|
uint32 i32_const_num;
|
||||||
|
|
||||||
/* processed code */
|
/* processed code */
|
||||||
uint8 *p_code_compiled;
|
uint8 *p_code_compiled;
|
||||||
|
@ -4064,12 +4079,6 @@ typedef struct WASMLoaderContext {
|
||||||
#endif
|
#endif
|
||||||
} WASMLoaderContext;
|
} WASMLoaderContext;
|
||||||
|
|
||||||
typedef struct Const {
|
|
||||||
WASMValue value;
|
|
||||||
uint16 slot_index;
|
|
||||||
uint8 value_type;
|
|
||||||
} Const;
|
|
||||||
|
|
||||||
#define CHECK_CSP_PUSH() \
|
#define CHECK_CSP_PUSH() \
|
||||||
do { \
|
do { \
|
||||||
if (ctx->frame_csp >= ctx->frame_csp_boundary) { \
|
if (ctx->frame_csp >= ctx->frame_csp_boundary) { \
|
||||||
|
@ -4224,8 +4233,10 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx)
|
||||||
#if WASM_ENABLE_FAST_INTERP != 0
|
#if WASM_ENABLE_FAST_INTERP != 0
|
||||||
if (ctx->frame_offset_bottom)
|
if (ctx->frame_offset_bottom)
|
||||||
wasm_runtime_free(ctx->frame_offset_bottom);
|
wasm_runtime_free(ctx->frame_offset_bottom);
|
||||||
if (ctx->const_buf)
|
if (ctx->i64_consts)
|
||||||
wasm_runtime_free(ctx->const_buf);
|
wasm_runtime_free(ctx->i64_consts);
|
||||||
|
if (ctx->i32_consts)
|
||||||
|
wasm_runtime_free(ctx->i32_consts);
|
||||||
#endif
|
#endif
|
||||||
wasm_runtime_free(ctx);
|
wasm_runtime_free(ctx);
|
||||||
}
|
}
|
||||||
|
@ -4259,10 +4270,15 @@ wasm_loader_ctx_init(WASMFunction *func, char *error_buf, uint32 error_buf_size)
|
||||||
goto fail;
|
goto fail;
|
||||||
loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32;
|
loader_ctx->frame_offset_boundary = loader_ctx->frame_offset_bottom + 32;
|
||||||
|
|
||||||
loader_ctx->num_const = 0;
|
loader_ctx->i64_const_max_num = 8;
|
||||||
loader_ctx->const_buf_size = sizeof(Const) * 8;
|
if (!(loader_ctx->i64_consts =
|
||||||
if (!(loader_ctx->const_buf = loader_malloc(loader_ctx->const_buf_size,
|
loader_malloc(sizeof(int64) * loader_ctx->i64_const_max_num,
|
||||||
error_buf, error_buf_size)))
|
error_buf, error_buf_size)))
|
||||||
|
goto fail;
|
||||||
|
loader_ctx->i32_const_max_num = 8;
|
||||||
|
if (!(loader_ctx->i32_consts =
|
||||||
|
loader_malloc(sizeof(int32) * loader_ctx->i32_const_max_num,
|
||||||
|
error_buf, error_buf_size)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (func->param_cell_num >= (int32)INT16_MAX - func->local_cell_num) {
|
if (func->param_cell_num >= (int32)INT16_MAX - func->local_cell_num) {
|
||||||
|
@ -5085,107 +5101,116 @@ wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmp_i64_const(const void *p_i64_const1, const void *p_i64_const2)
|
||||||
|
{
|
||||||
|
int64 i64_const1 = *(int64 *)p_i64_const1;
|
||||||
|
int64 i64_const2 = *(int64 *)p_i64_const2;
|
||||||
|
|
||||||
|
return (i64_const1 < i64_const2) ? -1 : (i64_const1 > i64_const2) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmp_i32_const(const void *p_i32_const1, const void *p_i32_const2)
|
||||||
|
{
|
||||||
|
int32 i32_const1 = *(int32 *)p_i32_const1;
|
||||||
|
int32 i32_const2 = *(int32 *)p_i32_const2;
|
||||||
|
|
||||||
|
return (i32_const1 < i32_const2) ? -1 : (i32_const1 > i32_const2) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value,
|
wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type, void *value,
|
||||||
int16 *offset, char *error_buf,
|
int16 *offset, char *error_buf,
|
||||||
uint32 error_buf_size)
|
uint32 error_buf_size)
|
||||||
{
|
{
|
||||||
int8 bytes_to_increase;
|
if (!ctx->p_code_compiled) {
|
||||||
int16 operand_offset = 0;
|
/* Treat i64 and f64 as the same by reading i64 value from
|
||||||
Const *c;
|
the raw bytes */
|
||||||
|
if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) {
|
||||||
|
/* No slot left, emit const instead */
|
||||||
|
if (ctx->i64_const_num * 2 + ctx->i32_const_num > INT16_MAX - 2) {
|
||||||
|
*offset = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Search existing constant */
|
/* Traverse the list if the const num is small */
|
||||||
for (c = (Const *)ctx->const_buf;
|
if (ctx->i64_const_num < 10) {
|
||||||
(uint8 *)c < ctx->const_buf + ctx->num_const * sizeof(Const); c++) {
|
for (uint32 i = 0; i < ctx->i64_const_num; i++) {
|
||||||
if ((type == c->value_type)
|
if (ctx->i64_consts[i] == *(int64 *)value) {
|
||||||
&& ((type == VALUE_TYPE_I64 && *(int64 *)value == c->value.i64)
|
*offset = -1;
|
||||||
|| (type == VALUE_TYPE_I32 && *(int32 *)value == c->value.i32)
|
return true;
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
}
|
||||||
|| (type == VALUE_TYPE_FUNCREF
|
}
|
||||||
&& *(int32 *)value == c->value.i32)
|
}
|
||||||
|| (type == VALUE_TYPE_EXTERNREF
|
|
||||||
&& *(int32 *)value == c->value.i32)
|
|
||||||
#endif
|
|
||||||
|| (type == VALUE_TYPE_F64
|
|
||||||
&& (0 == memcmp(value, &(c->value.f64), sizeof(float64))))
|
|
||||||
|| (type == VALUE_TYPE_F32
|
|
||||||
&& (0
|
|
||||||
== memcmp(value, &(c->value.f32), sizeof(float32)))))) {
|
|
||||||
operand_offset = c->slot_index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (c->value_type == VALUE_TYPE_I64 || c->value_type == VALUE_TYPE_F64)
|
|
||||||
operand_offset += 2;
|
|
||||||
else
|
|
||||||
operand_offset += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((uint8 *)c == ctx->const_buf + ctx->num_const * sizeof(Const)) {
|
if (ctx->i64_const_num >= ctx->i64_const_max_num) {
|
||||||
/* New constant, append to the const buffer */
|
MEM_REALLOC(ctx->i64_consts,
|
||||||
if ((type == VALUE_TYPE_F64) || (type == VALUE_TYPE_I64)) {
|
sizeof(int64) * ctx->i64_const_max_num,
|
||||||
bytes_to_increase = 2;
|
sizeof(int64) * (ctx->i64_const_max_num * 2));
|
||||||
|
ctx->i64_const_max_num *= 2;
|
||||||
|
}
|
||||||
|
ctx->i64_consts[ctx->i64_const_num++] = *(int64 *)value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bytes_to_increase = 1;
|
/* Treat i32 and f32 as the same by reading i32 value from
|
||||||
|
the raw bytes */
|
||||||
|
bh_assert(type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32);
|
||||||
|
|
||||||
|
/* No slot left, emit const instead */
|
||||||
|
if (ctx->i64_const_num * 2 + ctx->i32_const_num > INT16_MAX - 1) {
|
||||||
|
*offset = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Traverse the list if the const num is small */
|
||||||
|
if (ctx->i32_const_num < 10) {
|
||||||
|
for (uint32 i = 0; i < ctx->i32_const_num; i++) {
|
||||||
|
if (ctx->i32_consts[i] == *(int32 *)value) {
|
||||||
|
*offset = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->i32_const_num >= ctx->i32_const_max_num) {
|
||||||
|
MEM_REALLOC(ctx->i32_consts,
|
||||||
|
sizeof(int32) * ctx->i32_const_max_num,
|
||||||
|
sizeof(int32) * (ctx->i32_const_max_num * 2));
|
||||||
|
ctx->i32_const_max_num *= 2;
|
||||||
|
}
|
||||||
|
ctx->i32_consts[ctx->i32_const_num++] = *(int32 *)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The max cell num of const buffer is 32768 since the valid index range
|
*offset = -1;
|
||||||
* is -32768 ~ -1. Return an invalid index 0 to indicate the buffer is
|
return true;
|
||||||
* full */
|
}
|
||||||
if (ctx->const_cell_num > INT16_MAX - bytes_to_increase + 1) {
|
else {
|
||||||
*offset = 0;
|
if (type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64) {
|
||||||
return true;
|
int64 key = *(int64 *)value, *i64_const;
|
||||||
}
|
i64_const = bsearch(&key, ctx->i64_consts, ctx->i64_const_num,
|
||||||
|
sizeof(int64), cmp_i64_const);
|
||||||
if ((uint8 *)c == ctx->const_buf + ctx->const_buf_size) {
|
if (!i64_const) { /* not found, emit const instead */
|
||||||
MEM_REALLOC(ctx->const_buf, ctx->const_buf_size,
|
*offset = 0;
|
||||||
ctx->const_buf_size + 4 * sizeof(Const));
|
return true;
|
||||||
ctx->const_buf_size += 4 * sizeof(Const);
|
}
|
||||||
c = (Const *)(ctx->const_buf + ctx->num_const * sizeof(Const));
|
*offset = -(uint32)(ctx->i64_const_num * 2 + ctx->i32_const_num)
|
||||||
}
|
+ (uint32)(i64_const - ctx->i64_consts) * 2;
|
||||||
c->value_type = type;
|
}
|
||||||
switch (type) {
|
else {
|
||||||
case VALUE_TYPE_F64:
|
int32 key = *(int32 *)value, *i32_const;
|
||||||
bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value,
|
i32_const = bsearch(&key, ctx->i32_consts, ctx->i32_const_num,
|
||||||
sizeof(float64));
|
sizeof(int32), cmp_i32_const);
|
||||||
ctx->const_cell_num += 2;
|
if (!i32_const) { /* not found, emit const instead */
|
||||||
/* The const buf will be reversed, we use the second cell */
|
*offset = 0;
|
||||||
/* of the i64/f64 const so the finnal offset is corrent */
|
return true;
|
||||||
operand_offset++;
|
}
|
||||||
break;
|
*offset = -(uint32)(ctx->i32_const_num)
|
||||||
case VALUE_TYPE_I64:
|
+ (uint32)(i32_const - ctx->i32_consts);
|
||||||
c->value.i64 = *(int64 *)value;
|
}
|
||||||
ctx->const_cell_num += 2;
|
|
||||||
operand_offset++;
|
return true;
|
||||||
break;
|
|
||||||
case VALUE_TYPE_F32:
|
|
||||||
bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value,
|
|
||||||
sizeof(float32));
|
|
||||||
ctx->const_cell_num++;
|
|
||||||
break;
|
|
||||||
case VALUE_TYPE_I32:
|
|
||||||
c->value.i32 = *(int32 *)value;
|
|
||||||
ctx->const_cell_num++;
|
|
||||||
break;
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
case VALUE_TYPE_EXTERNREF:
|
|
||||||
case VALUE_TYPE_FUNCREF:
|
|
||||||
c->value.i32 = *(int32 *)value;
|
|
||||||
ctx->const_cell_num++;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
c->slot_index = operand_offset;
|
|
||||||
ctx->num_const++;
|
|
||||||
LOG_OP("#### new const [%d]: %ld\n", ctx->num_const,
|
|
||||||
(int64)c->value.i64);
|
|
||||||
}
|
}
|
||||||
/* use negetive index for const */
|
|
||||||
operand_offset = -(operand_offset + 1);
|
|
||||||
*offset = operand_offset;
|
|
||||||
return true;
|
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -6151,11 +6176,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
||||||
uint32 segment_index;
|
uint32 segment_index;
|
||||||
#endif
|
#endif
|
||||||
#if WASM_ENABLE_FAST_INTERP != 0
|
#if WASM_ENABLE_FAST_INTERP != 0
|
||||||
uint8 *func_const_end, *func_const = NULL;
|
|
||||||
int16 operand_offset = 0;
|
int16 operand_offset = 0;
|
||||||
uint8 last_op = 0;
|
uint8 last_op = 0;
|
||||||
bool disable_emit, preserve_local = false, if_condition_available = true;
|
bool disable_emit, preserve_local = false, if_condition_available = true;
|
||||||
;
|
|
||||||
float32 f32_const;
|
float32 f32_const;
|
||||||
float64 f64_const;
|
float64 f64_const;
|
||||||
|
|
||||||
|
@ -6206,6 +6229,68 @@ re_scan:
|
||||||
p = func->code;
|
p = func->code;
|
||||||
func->code_compiled = loader_ctx->p_code_compiled;
|
func->code_compiled = loader_ctx->p_code_compiled;
|
||||||
func->code_compiled_size = loader_ctx->code_compiled_size;
|
func->code_compiled_size = loader_ctx->code_compiled_size;
|
||||||
|
|
||||||
|
if (loader_ctx->i64_const_num > 0) {
|
||||||
|
int64 *i64_consts_old = loader_ctx->i64_consts;
|
||||||
|
|
||||||
|
/* Sort the i64 consts */
|
||||||
|
qsort(i64_consts_old, loader_ctx->i64_const_num, sizeof(int64),
|
||||||
|
cmp_i64_const);
|
||||||
|
|
||||||
|
/* Remove the duplicated i64 consts */
|
||||||
|
uint32 k = 1;
|
||||||
|
for (i = 1; i < loader_ctx->i64_const_num; i++) {
|
||||||
|
if (i64_consts_old[i] != i64_consts_old[i - 1]) {
|
||||||
|
i64_consts_old[k++] = i64_consts_old[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k < loader_ctx->i64_const_num) {
|
||||||
|
int64 *i64_consts_new;
|
||||||
|
/* Try to reallocate memory with a smaller size */
|
||||||
|
if ((i64_consts_new =
|
||||||
|
wasm_runtime_malloc((uint32)sizeof(int64) * k))) {
|
||||||
|
bh_memcpy_s(i64_consts_new, (uint32)sizeof(int64) * k,
|
||||||
|
i64_consts_old, (uint32)sizeof(int64) * k);
|
||||||
|
/* Free the old memory */
|
||||||
|
wasm_runtime_free(i64_consts_old);
|
||||||
|
loader_ctx->i64_consts = i64_consts_new;
|
||||||
|
loader_ctx->i64_const_max_num = k;
|
||||||
|
}
|
||||||
|
loader_ctx->i64_const_num = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loader_ctx->i32_const_num > 0) {
|
||||||
|
int32 *i32_consts_old = loader_ctx->i32_consts;
|
||||||
|
|
||||||
|
/* Sort the i32 consts */
|
||||||
|
qsort(i32_consts_old, loader_ctx->i32_const_num, sizeof(int32),
|
||||||
|
cmp_i32_const);
|
||||||
|
|
||||||
|
/* Remove the duplicated i32 consts */
|
||||||
|
uint32 k = 1;
|
||||||
|
for (i = 1; i < loader_ctx->i32_const_num; i++) {
|
||||||
|
if (i32_consts_old[i] != i32_consts_old[i - 1]) {
|
||||||
|
i32_consts_old[k++] = i32_consts_old[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k < loader_ctx->i32_const_num) {
|
||||||
|
int32 *i32_consts_new;
|
||||||
|
/* Try to reallocate memory with a smaller size */
|
||||||
|
if ((i32_consts_new =
|
||||||
|
wasm_runtime_malloc((uint32)sizeof(int32) * k))) {
|
||||||
|
bh_memcpy_s(i32_consts_new, (uint32)sizeof(int32) * k,
|
||||||
|
i32_consts_old, (uint32)sizeof(int32) * k);
|
||||||
|
/* Free the old memory */
|
||||||
|
wasm_runtime_free(i32_consts_old);
|
||||||
|
loader_ctx->i32_consts = i32_consts_new;
|
||||||
|
loader_ctx->i32_const_max_num = k;
|
||||||
|
}
|
||||||
|
loader_ctx->i32_const_num = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -8352,29 +8437,25 @@ re_scan:
|
||||||
if (loader_ctx->p_code_compiled == NULL)
|
if (loader_ctx->p_code_compiled == NULL)
|
||||||
goto re_scan;
|
goto re_scan;
|
||||||
|
|
||||||
func->const_cell_num = loader_ctx->const_cell_num;
|
func->const_cell_num =
|
||||||
|
loader_ctx->i64_const_num * 2 + loader_ctx->i32_const_num;
|
||||||
if (func->const_cell_num > 0) {
|
if (func->const_cell_num > 0) {
|
||||||
int32 j;
|
if (!(func->consts =
|
||||||
|
loader_malloc((uint64)sizeof(uint32) * func->const_cell_num,
|
||||||
if (!(func->consts = func_const = loader_malloc(
|
error_buf, error_buf_size)))
|
||||||
func->const_cell_num * 4, error_buf, error_buf_size)))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
if (loader_ctx->i64_const_num > 0) {
|
||||||
func_const_end = func->consts + func->const_cell_num * 4;
|
bh_memcpy_s(func->consts,
|
||||||
/* reverse the const buf */
|
(uint32)sizeof(int64) * loader_ctx->i64_const_num,
|
||||||
for (j = loader_ctx->num_const - 1; j >= 0; j--) {
|
loader_ctx->i64_consts,
|
||||||
Const *c = (Const *)(loader_ctx->const_buf + j * sizeof(Const));
|
(uint32)sizeof(int64) * loader_ctx->i64_const_num);
|
||||||
if (c->value_type == VALUE_TYPE_F64
|
}
|
||||||
|| c->value_type == VALUE_TYPE_I64) {
|
if (loader_ctx->i32_const_num > 0) {
|
||||||
bh_memcpy_s(func_const, (uint32)(func_const_end - func_const),
|
bh_memcpy_s(func->consts
|
||||||
&(c->value.f64), (uint32)sizeof(int64));
|
+ sizeof(int64) * loader_ctx->i64_const_num,
|
||||||
func_const += sizeof(int64);
|
(uint32)sizeof(int32) * loader_ctx->i32_const_num,
|
||||||
}
|
loader_ctx->i32_consts,
|
||||||
else {
|
(uint32)sizeof(int32) * loader_ctx->i32_const_num);
|
||||||
bh_memcpy_s(func_const, (uint32)(func_const_end - func_const),
|
|
||||||
&(c->value.f32), (uint32)sizeof(int32));
|
|
||||||
func_const += sizeof(int32);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4701,7 +4701,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
||||||
if (!(func_obj = wasm_create_func_obj(module_inst,
|
if (!(func_obj = wasm_create_func_obj(module_inst,
|
||||||
init_values[i].u.ref_index,
|
init_values[i].u.ref_index,
|
||||||
true, NULL, 0))) {
|
true, NULL, 0))) {
|
||||||
wasm_set_exception(module_inst, "null function object");
|
wasm_set_exception(module_inst, "null function reference");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
table_elems[i] = func_obj;
|
table_elems[i] = func_obj;
|
||||||
|
|
|
@ -100,7 +100,12 @@ def ignore_the_case(
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if gc_flag:
|
if gc_flag:
|
||||||
if case_name in ["array_init_elem", "array_init_data"]:
|
if case_name in [
|
||||||
|
"array_init_elem",
|
||||||
|
"array_init_data",
|
||||||
|
"array_new_data",
|
||||||
|
"array_new_elem"
|
||||||
|
]:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if sgx_flag:
|
if sgx_flag:
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,53 +1,56 @@
|
||||||
diff --git a/test/core/return_call.wast b/test/core/return_call.wast
|
diff --git a/test/core/return_call.wast b/test/core/return_call.wast
|
||||||
index ad66acca..b27af19b 100644
|
index 8a3d7512..5a4eba68 100644
|
||||||
--- a/test/core/return_call.wast
|
--- a/test/core/return_call.wast
|
||||||
+++ b/test/core/return_call.wast
|
+++ b/test/core/return_call.wast
|
||||||
@@ -102,20 +102,20 @@
|
@@ -103,22 +103,22 @@
|
||||||
|
|
||||||
(assert_return (invoke "count" (i64.const 0)) (i64.const 0))
|
(assert_return (invoke "count" (i64.const 0)) (i64.const 0))
|
||||||
(assert_return (invoke "count" (i64.const 1000)) (i64.const 0))
|
(assert_return (invoke "count" (i64.const 1000)) (i64.const 0))
|
||||||
|
(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;)
|
||||||
-(assert_return (invoke "count" (i64.const 100_000)) (i64.const 0))
|
-(assert_return (invoke "count" (i64.const 100_000)) (i64.const 0))
|
||||||
+(assert_return (invoke "count" (i64.const 1001)) (i64.const 0))
|
+(assert_return (invoke "count" (i64.const 1_001)) (i64.const 0))
|
||||||
|
|
||||||
(assert_return (invoke "even" (i64.const 0)) (i32.const 44))
|
(assert_return (invoke "even" (i64.const 0)) (i32.const 44))
|
||||||
(assert_return (invoke "even" (i64.const 1)) (i32.const 99))
|
(assert_return (invoke "even" (i64.const 1)) (i32.const 99))
|
||||||
(assert_return (invoke "even" (i64.const 100)) (i32.const 44))
|
(assert_return (invoke "even" (i64.const 100)) (i32.const 44))
|
||||||
(assert_return (invoke "even" (i64.const 77)) (i32.const 99))
|
(assert_return (invoke "even" (i64.const 77)) (i32.const 99))
|
||||||
|
(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;)
|
||||||
-(assert_return (invoke "even" (i64.const 100_000)) (i32.const 44))
|
-(assert_return (invoke "even" (i64.const 100_000)) (i32.const 44))
|
||||||
-(assert_return (invoke "even" (i64.const 100_001)) (i32.const 99))
|
-(assert_return (invoke "even" (i64.const 100_001)) (i32.const 99))
|
||||||
+(assert_return (invoke "even" (i64.const 1000)) (i32.const 44))
|
+(assert_return (invoke "even" (i64.const 1_000)) (i32.const 44))
|
||||||
+(assert_return (invoke "even" (i64.const 1001)) (i32.const 99))
|
+(assert_return (invoke "even" (i64.const 1_001)) (i32.const 99))
|
||||||
(assert_return (invoke "odd" (i64.const 0)) (i32.const 99))
|
(assert_return (invoke "odd" (i64.const 0)) (i32.const 99))
|
||||||
(assert_return (invoke "odd" (i64.const 1)) (i32.const 44))
|
(assert_return (invoke "odd" (i64.const 1)) (i32.const 44))
|
||||||
(assert_return (invoke "odd" (i64.const 200)) (i32.const 99))
|
(assert_return (invoke "odd" (i64.const 200)) (i32.const 99))
|
||||||
(assert_return (invoke "odd" (i64.const 77)) (i32.const 44))
|
(assert_return (invoke "odd" (i64.const 77)) (i32.const 44))
|
||||||
|
(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;)
|
||||||
-(assert_return (invoke "odd" (i64.const 100_000)) (i32.const 99))
|
-(assert_return (invoke "odd" (i64.const 100_000)) (i32.const 99))
|
||||||
-(assert_return (invoke "odd" (i64.const 99_999)) (i32.const 44))
|
-(assert_return (invoke "odd" (i64.const 99_999)) (i32.const 44))
|
||||||
+(assert_return (invoke "odd" (i64.const 1000)) (i32.const 99))
|
+(assert_return (invoke "odd" (i64.const 1_000)) (i32.const 99))
|
||||||
+(assert_return (invoke "odd" (i64.const 999)) (i32.const 44))
|
+(assert_return (invoke "odd" (i64.const 999)) (i32.const 44))
|
||||||
|
|
||||||
|
|
||||||
;; Invalid typing
|
;; Invalid typing
|
||||||
diff --git a/test/core/return_call_indirect.wast b/test/core/return_call_indirect.wast
|
diff --git a/test/core/return_call_indirect.wast b/test/core/return_call_indirect.wast
|
||||||
index 6b95c24b..a9e86d42 100644
|
index 7f68b4a5..08a31417 100644
|
||||||
--- a/test/core/return_call_indirect.wast
|
--- a/test/core/return_call_indirect.wast
|
||||||
+++ b/test/core/return_call_indirect.wast
|
+++ b/test/core/return_call_indirect.wast
|
||||||
@@ -257,14 +257,14 @@
|
@@ -257,15 +257,15 @@
|
||||||
(assert_return (invoke "even" (i32.const 1)) (i32.const 99))
|
(assert_return (invoke "even" (i32.const 1)) (i32.const 99))
|
||||||
(assert_return (invoke "even" (i32.const 100)) (i32.const 44))
|
(assert_return (invoke "even" (i32.const 100)) (i32.const 44))
|
||||||
(assert_return (invoke "even" (i32.const 77)) (i32.const 99))
|
(assert_return (invoke "even" (i32.const 77)) (i32.const 99))
|
||||||
-(assert_return (invoke "even" (i32.const 100_000)) (i32.const 44))
|
-(assert_return (invoke "even" (i32.const 100_000)) (i32.const 44))
|
||||||
-(assert_return (invoke "even" (i32.const 111_111)) (i32.const 99))
|
-(assert_return (invoke "even" (i32.const 111_111)) (i32.const 99))
|
||||||
+(assert_return (invoke "even" (i32.const 1000)) (i32.const 44))
|
+(assert_return (invoke "even" (i32.const 1_000)) (i32.const 44))
|
||||||
+(assert_return (invoke "even" (i32.const 1111)) (i32.const 99))
|
+(assert_return (invoke "even" (i32.const 1_001)) (i32.const 99))
|
||||||
(assert_return (invoke "odd" (i32.const 0)) (i32.const 99))
|
(assert_return (invoke "odd" (i32.const 0)) (i32.const 99))
|
||||||
(assert_return (invoke "odd" (i32.const 1)) (i32.const 44))
|
(assert_return (invoke "odd" (i32.const 1)) (i32.const 44))
|
||||||
(assert_return (invoke "odd" (i32.const 200)) (i32.const 99))
|
(assert_return (invoke "odd" (i32.const 200)) (i32.const 99))
|
||||||
(assert_return (invoke "odd" (i32.const 77)) (i32.const 44))
|
(assert_return (invoke "odd" (i32.const 77)) (i32.const 44))
|
||||||
|
(;Return to the original configuration after we have corrected the error in the AOT/JIT tail-call implementation.;)
|
||||||
-(assert_return (invoke "odd" (i32.const 100_002)) (i32.const 99))
|
-(assert_return (invoke "odd" (i32.const 100_002)) (i32.const 99))
|
||||||
-(assert_return (invoke "odd" (i32.const 100_003)) (i32.const 44))
|
-(assert_return (invoke "odd" (i32.const 100_003)) (i32.const 44))
|
||||||
+(assert_return (invoke "odd" (i32.const 1002)) (i32.const 99))
|
+(assert_return (invoke "odd" (i32.const 1_002)) (i32.const 99))
|
||||||
+(assert_return (invoke "odd" (i32.const 1003)) (i32.const 44))
|
+(assert_return (invoke "odd" (i32.const 1_003)) (i32.const 44))
|
||||||
|
|
||||||
|
|
||||||
;; Invalid syntax
|
;; Invalid syntax
|
||||||
|
|
|
@ -467,8 +467,8 @@ function spec_test()
|
||||||
git clone -b main --single-branch https://github.com/WebAssembly/gc.git spec
|
git clone -b main --single-branch https://github.com/WebAssembly/gc.git spec
|
||||||
pushd spec
|
pushd spec
|
||||||
|
|
||||||
# Reset to commit: "[test] Unify the error message."
|
# Dec 9, 2024. Merge branch 'funcref'
|
||||||
git reset --hard 0caaadc65b5e1910512d8ae228502edcf9d60390
|
git reset --hard 756060f5816c7e2159f4817fbdee76cf52f9c923
|
||||||
git apply ../../spec-test-script/gc_ignore_cases.patch || exit 1
|
git apply ../../spec-test-script/gc_ignore_cases.patch || exit 1
|
||||||
|
|
||||||
if [[ ${ENABLE_QEMU} == 1 ]]; then
|
if [[ ${ENABLE_QEMU} == 1 ]]; then
|
||||||
|
@ -477,6 +477,13 @@ function spec_test()
|
||||||
git apply ../../spec-test-script/gc_nuttx_tail_call.patch || exit 1
|
git apply ../../spec-test-script/gc_nuttx_tail_call.patch || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# As of version 1.0.36, wabt is still unable to correctly handle the GC proposal.
|
||||||
|
#
|
||||||
|
# $ $ /opt/wabt-1.0.36/bin/wast2json --enable-all ../spec/test/core/br_if.wast
|
||||||
|
#
|
||||||
|
# ../spec/test/core/br_if.wast:670:26: error: unexpected token "null", expected a numeric index or a name (e.g. 12 or $foo).
|
||||||
|
# (func $f (param (ref null $t)) (result funcref) (local.get 0))
|
||||||
|
#
|
||||||
compile_reference_interpreter
|
compile_reference_interpreter
|
||||||
elif [[ ${ENABLE_MEMORY64} == 1 ]]; then
|
elif [[ ${ENABLE_MEMORY64} == 1 ]]; then
|
||||||
echo "checkout spec for memory64 proposal"
|
echo "checkout spec for memory64 proposal"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user