Add support for multi-memory proposal in classic interpreter (#3742)
Implement multi-memory for classic-interpreter. Support core spec (and bulk memory) opcodes now, and will support atomic opcodes, and add multi-memory export APIs in the future. PS: Multi-memory spec test patched a lot for linking test to adapt for multi-module implementation.
This commit is contained in:
@ -94,6 +94,14 @@ extern "C" {
|
||||
#define SHARED_MEMORY_FLAG 0x02
|
||||
#define MEMORY64_FLAG 0x04
|
||||
|
||||
/**
|
||||
* In the multi-memory proposal, the memarg in loads and stores are
|
||||
* reinterpreted as a bitfield, bit 6 serves as a flag indicating the presence
|
||||
* of the optional memory index, if it is set, then an i32 memory index follows
|
||||
* after the alignment bitfield
|
||||
*/
|
||||
#define OPT_MEMIDX_FLAG 0x40
|
||||
|
||||
#define DEFAULT_NUM_BYTES_PER_PAGE 65536
|
||||
#define DEFAULT_MAX_PAGES 65536
|
||||
#define DEFAULT_MEM64_MAX_PAGES UINT32_MAX
|
||||
|
||||
@ -697,6 +697,44 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
|
||||
#define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res)
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
/* If the current memidx differs than the last cached one,
|
||||
* update memory related information */
|
||||
#define read_leb_memidx(p, p_end, res) \
|
||||
do { \
|
||||
read_leb_uint32(p, p_end, res); \
|
||||
if (res != memidx_cached) { \
|
||||
memory = wasm_get_memory_with_idx(module, res); \
|
||||
linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory); \
|
||||
memidx_cached = res; \
|
||||
} \
|
||||
} while (0)
|
||||
/* First read the alignment, then if it has flag indicating following memidx,
|
||||
* read and update memory related information, if it differs than the
|
||||
* last(cached) one. If it doesn't have flag reset the
|
||||
* memory instance to the default memories[0] */
|
||||
#define read_leb_memarg(p, p_end, res) \
|
||||
do { \
|
||||
read_leb_uint32(p, p_end, res); \
|
||||
if (!(res & OPT_MEMIDX_FLAG)) \
|
||||
memidx = 0; \
|
||||
else \
|
||||
read_leb_uint32(p, p_end, memidx); \
|
||||
if (memidx != memidx_cached) { \
|
||||
memory = wasm_get_memory_with_idx(module, memidx); \
|
||||
linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory); \
|
||||
memidx_cached = memidx; \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define read_leb_memarg(p, p_end, res) \
|
||||
do { \
|
||||
read_leb_uint32(p, p_end, res); \
|
||||
(void)res; \
|
||||
} while (0)
|
||||
#define read_leb_memidx(p, p_end, res) read_leb_memarg(p, p_end, res)
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LABELS_AS_VALUES == 0
|
||||
#define RECOVER_FRAME_IP_END() frame_ip_end = wasm_get_func_code_end(cur_func)
|
||||
#else
|
||||
@ -1567,6 +1605,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
if (memory)
|
||||
is_memory64 = memory->is_memory64;
|
||||
#endif
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
uint32 memidx = 0;
|
||||
uint32 memidx_cached = (uint32)-1;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
uint8 *frame_ip_orig = NULL;
|
||||
@ -4292,13 +4334,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(4);
|
||||
PUSH_I32(LOAD_I32(maddr));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4308,13 +4349,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(8);
|
||||
PUSH_I64(LOAD_I64(maddr));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4323,13 +4363,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(1);
|
||||
PUSH_I32(sign_ext_8_32(*(int8 *)maddr));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4338,13 +4377,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(1);
|
||||
PUSH_I32((uint32)(*(uint8 *)maddr));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4353,13 +4391,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(2);
|
||||
PUSH_I32(sign_ext_16_32(LOAD_I16(maddr)));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4368,13 +4405,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(2);
|
||||
PUSH_I32((uint32)(LOAD_U16(maddr)));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4383,13 +4419,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(1);
|
||||
PUSH_I64(sign_ext_8_64(*(int8 *)maddr));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4398,13 +4433,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(1);
|
||||
PUSH_I64((uint64)(*(uint8 *)maddr));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4413,13 +4447,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(2);
|
||||
PUSH_I64(sign_ext_16_64(LOAD_I16(maddr)));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4428,13 +4461,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(2);
|
||||
PUSH_I64((uint64)(LOAD_U16(maddr)));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4443,14 +4475,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
opcode = *(frame_ip - 1);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(4);
|
||||
PUSH_I64(sign_ext_32_64(LOAD_I32(maddr)));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4459,13 +4489,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
addr = POP_MEM_OFFSET();
|
||||
CHECK_MEMORY_OVERFLOW(4);
|
||||
PUSH_I64((uint64)(LOAD_U32(maddr)));
|
||||
CHECK_READ_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4476,7 +4505,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
frame_sp--;
|
||||
addr = POP_MEM_OFFSET();
|
||||
@ -4491,7 +4520,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
STORE_U32(maddr, frame_sp[1]);
|
||||
}
|
||||
CHECK_WRITE_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4501,7 +4529,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 flags;
|
||||
mem_offset_t offset, addr;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
frame_sp -= 2;
|
||||
addr = POP_MEM_OFFSET();
|
||||
@ -4519,7 +4547,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
GET_I64_FROM_ADDR(frame_sp + 1));
|
||||
}
|
||||
CHECK_WRITE_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4531,7 +4558,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint32 sval;
|
||||
|
||||
opcode = *(frame_ip - 1);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
sval = (uint32)POP_I32();
|
||||
addr = POP_MEM_OFFSET();
|
||||
@ -4545,7 +4572,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
}
|
||||
CHECK_WRITE_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -4558,7 +4584,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint64 sval;
|
||||
|
||||
opcode = *(frame_ip - 1);
|
||||
read_leb_uint32(frame_ip, frame_ip_end, flags);
|
||||
read_leb_memarg(frame_ip, frame_ip_end, flags);
|
||||
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
|
||||
sval = (uint64)POP_I64();
|
||||
addr = POP_MEM_OFFSET();
|
||||
@ -4576,29 +4602,27 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
STORE_U32(maddr, (uint32)sval);
|
||||
}
|
||||
CHECK_WRITE_WATCHPOINT(addr, offset);
|
||||
(void)flags;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
/* memory size and memory grow instructions */
|
||||
HANDLE_OP(WASM_OP_MEMORY_SIZE)
|
||||
{
|
||||
uint32 reserved;
|
||||
read_leb_uint32(frame_ip, frame_ip_end, reserved);
|
||||
uint32 mem_idx;
|
||||
read_leb_memidx(frame_ip, frame_ip_end, mem_idx);
|
||||
PUSH_PAGE_COUNT(memory->cur_page_count);
|
||||
(void)reserved;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
HANDLE_OP(WASM_OP_MEMORY_GROW)
|
||||
{
|
||||
uint32 reserved, delta,
|
||||
prev_page_count = memory->cur_page_count;
|
||||
uint32 mem_idx, delta, prev_page_count;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, reserved);
|
||||
read_leb_memidx(frame_ip, frame_ip_end, mem_idx);
|
||||
prev_page_count = memory->cur_page_count;
|
||||
delta = (uint32)POP_PAGE_COUNT();
|
||||
|
||||
if (!wasm_enlarge_memory(module, delta)) {
|
||||
if (!wasm_enlarge_memory_with_idx(module, delta, mem_idx)) {
|
||||
/* failed to memory.grow, return -1 */
|
||||
PUSH_PAGE_COUNT(-1);
|
||||
}
|
||||
@ -4614,7 +4638,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
#endif
|
||||
}
|
||||
|
||||
(void)reserved;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
@ -5610,8 +5633,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint8 *data;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, segment);
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
read_leb_memidx(frame_ip, frame_ip_end, memidx);
|
||||
#else
|
||||
/* skip memory index */
|
||||
frame_ip++;
|
||||
#endif
|
||||
|
||||
bytes = (uint64)(uint32)POP_I32();
|
||||
offset = (uint64)(uint32)POP_I32();
|
||||
@ -5660,33 +5687,54 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
{
|
||||
mem_offset_t dst, src, len;
|
||||
uint8 *mdst, *msrc;
|
||||
uint64 dlen;
|
||||
|
||||
frame_ip += 2;
|
||||
len = POP_MEM_OFFSET();
|
||||
src = POP_MEM_OFFSET();
|
||||
dst = POP_MEM_OFFSET();
|
||||
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
/* dst memidx */
|
||||
read_leb_memidx(frame_ip, frame_ip_end, memidx);
|
||||
#else
|
||||
/* skip dst memidx */
|
||||
frame_ip += 1;
|
||||
#endif
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
linear_mem_size = get_linear_mem_size();
|
||||
#endif
|
||||
|
||||
/* dst boundary check */
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc);
|
||||
CHECK_BULK_MEMORY_OVERFLOW(dst, len, mdst);
|
||||
#else
|
||||
if ((uint64)(uint32)src + len > linear_mem_size)
|
||||
if ((uint64)dst + len > linear_mem_size)
|
||||
goto out_of_bounds;
|
||||
msrc = memory->memory_data + (uint32)src;
|
||||
mdst = memory->memory_data + dst;
|
||||
#endif
|
||||
dlen = linear_mem_size - dst;
|
||||
|
||||
if ((uint64)(uint32)dst + len > linear_mem_size)
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
/* src memidx */
|
||||
read_leb_memidx(frame_ip, frame_ip_end, memidx);
|
||||
#else
|
||||
/* skip src memidx */
|
||||
frame_ip += 1;
|
||||
#endif
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
linear_mem_size = get_linear_mem_size();
|
||||
#endif
|
||||
/* src boundary check */
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
CHECK_BULK_MEMORY_OVERFLOW(src, len, msrc);
|
||||
#else
|
||||
if ((uint64)src + len > linear_mem_size)
|
||||
goto out_of_bounds;
|
||||
mdst = memory->memory_data + (uint32)dst;
|
||||
msrc = memory->memory_data + src;
|
||||
#endif
|
||||
|
||||
/* allowing the destination and source to overlap */
|
||||
#if WASM_ENABLE_MEMORY64 == 0
|
||||
bh_memmove_s(mdst, (uint32)(linear_mem_size - dst),
|
||||
msrc, (uint32)len);
|
||||
/* allowing the destination and source to overlap */
|
||||
bh_memmove_s(mdst, (uint32)dlen, msrc, (uint32)len);
|
||||
#else
|
||||
/* use memmove when memory64 is enabled since len
|
||||
may be larger than UINT32_MAX */
|
||||
@ -5698,7 +5746,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
{
|
||||
mem_offset_t dst, len;
|
||||
uint8 fill_val, *mdst;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
read_leb_memidx(frame_ip, frame_ip_end, memidx);
|
||||
#else
|
||||
/* skip memory index */
|
||||
frame_ip++;
|
||||
#endif
|
||||
|
||||
len = POP_MEM_OFFSET();
|
||||
fill_val = POP_I32();
|
||||
|
||||
@ -3837,6 +3837,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
addr_ret = GET_OFFSET();
|
||||
delta = (uint32)frame_lp[addr1];
|
||||
|
||||
/* TODO: multi-memory wasm_enlarge_memory_with_idx() */
|
||||
if (!wasm_enlarge_memory(module, delta)) {
|
||||
/* failed to memory.grow, return -1 */
|
||||
frame_lp[addr_ret] = -1;
|
||||
|
||||
@ -127,6 +127,17 @@ check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length,
|
||||
#define skip_leb_uint32(p, p_end) skip_leb(p)
|
||||
#define skip_leb_int32(p, p_end) skip_leb(p)
|
||||
#define skip_leb_mem_offset(p, p_end) skip_leb(p)
|
||||
#define skip_leb_memidx(p, p_end) skip_leb(p)
|
||||
#if WASM_ENABLE_MULTI_MEMORY == 0
|
||||
#define skip_leb_align(p, p_end) skip_leb(p)
|
||||
#else
|
||||
/* Skip the following memidx if applicable */
|
||||
#define skip_leb_align(p, p_end) \
|
||||
do { \
|
||||
if (*p++ & OPT_MEMIDX_FLAG) \
|
||||
skip_leb_uint32(p, p_end); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define read_uint8(p) TEMPLATE_READ_VALUE(uint8, p)
|
||||
#define read_uint32(p) TEMPLATE_READ_VALUE(uint32, p)
|
||||
@ -173,6 +184,40 @@ check_buf1(const uint8 *buf, const uint8 *buf_end, uint32 length,
|
||||
res = (int32)res64; \
|
||||
} while (0)
|
||||
|
||||
#define read_leb_memidx(p, p_end, res) read_leb_uint32(p, p_end, res)
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
#define check_memidx(module, memidx) \
|
||||
do { \
|
||||
if (memidx >= module->import_memory_count + module->memory_count) { \
|
||||
set_error_buf_v(error_buf, error_buf_size, "unknown memory %d", \
|
||||
memidx); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
/* Bit 6(0x40) indicating the optional memidx, and reset bit 6 for
|
||||
* alignment check */
|
||||
#define read_leb_memarg(p, p_end, res) \
|
||||
do { \
|
||||
read_leb_uint32(p, p_end, res); \
|
||||
if (res & OPT_MEMIDX_FLAG) { \
|
||||
res &= ~OPT_MEMIDX_FLAG; \
|
||||
read_leb_uint32(p, p_end, memidx); /* memidx */ \
|
||||
check_memidx(module, memidx); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
/* reserved byte 0x00 */
|
||||
#define check_memidx(module, memidx) \
|
||||
do { \
|
||||
(void)module; \
|
||||
if (memidx != 0) { \
|
||||
set_error_buf(error_buf, error_buf_size, "zero byte expected"); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
#define read_leb_memarg(p, p_end, res) read_leb_uint32(p, p_end, res)
|
||||
#endif
|
||||
|
||||
static char *
|
||||
type2str(uint8 type)
|
||||
{
|
||||
@ -3288,11 +3333,13 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
if (flags & 1)
|
||||
read_leb_uint32(p, p_end, u32);
|
||||
module->import_memory_count++;
|
||||
#if WASM_ENABLE_MULTI_MEMORY == 0
|
||||
if (module->import_memory_count > 1) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"multiple memories");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if WASM_ENABLE_TAGS != 0
|
||||
@ -3903,11 +3950,14 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
WASMMemory *memory;
|
||||
|
||||
read_leb_uint32(p, p_end, memory_count);
|
||||
|
||||
#if WASM_ENABLE_MULTI_MEMORY == 0
|
||||
/* a total of one memory is allowed */
|
||||
if (module->import_memory_count + memory_count > 1) {
|
||||
set_error_buf(error_buf, error_buf_size, "multiple memories");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (memory_count) {
|
||||
module->memory_count = memory_count;
|
||||
@ -7258,13 +7308,13 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
|
||||
case WASM_OP_I64_STORE8:
|
||||
case WASM_OP_I64_STORE16:
|
||||
case WASM_OP_I64_STORE32:
|
||||
skip_leb_uint32(p, p_end); /* align */
|
||||
skip_leb_align(p, p_end); /* align */
|
||||
skip_leb_mem_offset(p, p_end); /* offset */
|
||||
break;
|
||||
|
||||
case WASM_OP_MEMORY_SIZE:
|
||||
case WASM_OP_MEMORY_GROW:
|
||||
skip_leb_uint32(p, p_end); /* 0x00 */
|
||||
skip_leb_memidx(p, p_end); /* memidx */
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_CONST:
|
||||
@ -7562,19 +7612,17 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
case WASM_OP_MEMORY_INIT:
|
||||
skip_leb_uint32(p, p_end);
|
||||
/* skip memory idx */
|
||||
p++;
|
||||
skip_leb_memidx(p, p_end);
|
||||
break;
|
||||
case WASM_OP_DATA_DROP:
|
||||
skip_leb_uint32(p, p_end);
|
||||
break;
|
||||
case WASM_OP_MEMORY_COPY:
|
||||
/* skip two memory idx */
|
||||
p += 2;
|
||||
skip_leb_memidx(p, p_end);
|
||||
skip_leb_memidx(p, p_end);
|
||||
break;
|
||||
case WASM_OP_MEMORY_FILL:
|
||||
/* skip memory idx */
|
||||
p++;
|
||||
skip_leb_memidx(p, p_end);
|
||||
break;
|
||||
#endif /* WASM_ENABLE_BULK_MEMORY */
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
@ -7701,7 +7749,6 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
case WASM_OP_ATOMIC_PREFIX:
|
||||
{
|
||||
/* TODO: memory64 offset type changes */
|
||||
uint32 opcode1;
|
||||
|
||||
/* atomic_op (u32_leb) + memarg (2 u32_leb) */
|
||||
@ -10876,6 +10923,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
||||
#else
|
||||
mem_offset_type = VALUE_TYPE_I32;
|
||||
#endif
|
||||
uint32 memidx;
|
||||
|
||||
global_count = module->import_global_count + module->global_count;
|
||||
|
||||
@ -13155,7 +13203,7 @@ re_scan:
|
||||
}
|
||||
#endif
|
||||
CHECK_MEMORY();
|
||||
read_leb_uint32(p, p_end, align); /* align */
|
||||
read_leb_memarg(p, p_end, align); /* align */
|
||||
read_leb_mem_offset(p, p_end, mem_offset); /* offset */
|
||||
if (!check_memory_access_align(opcode, align, error_buf,
|
||||
error_buf_size)) {
|
||||
@ -13221,12 +13269,8 @@ re_scan:
|
||||
|
||||
case WASM_OP_MEMORY_SIZE:
|
||||
CHECK_MEMORY();
|
||||
/* reserved byte 0x00 */
|
||||
if (*p++ != 0x00) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"zero byte expected");
|
||||
goto fail;
|
||||
}
|
||||
read_leb_uint32(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
PUSH_PAGE_COUNT();
|
||||
|
||||
module->possible_memory_grow = true;
|
||||
@ -13237,12 +13281,8 @@ re_scan:
|
||||
|
||||
case WASM_OP_MEMORY_GROW:
|
||||
CHECK_MEMORY();
|
||||
/* reserved byte 0x00 */
|
||||
if (*p++ != 0x00) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"zero byte expected");
|
||||
goto fail;
|
||||
}
|
||||
read_leb_uint32(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
POP_AND_PUSH(mem_offset_type, mem_offset_type);
|
||||
|
||||
module->possible_memory_grow = true;
|
||||
@ -14594,8 +14634,8 @@ re_scan:
|
||||
&& module->memory_count == 0)
|
||||
goto fail_unknown_memory;
|
||||
|
||||
if (*p++ != 0x00)
|
||||
goto fail_zero_byte_expected;
|
||||
read_leb_uint32(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
|
||||
if (data_seg_idx >= module->data_seg_count) {
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
@ -14644,10 +14684,11 @@ re_scan:
|
||||
case WASM_OP_MEMORY_COPY:
|
||||
{
|
||||
CHECK_BUF(p, p_end, sizeof(int16));
|
||||
/* both src and dst memory index should be 0 */
|
||||
if (*(int16 *)p != 0x0000)
|
||||
goto fail_zero_byte_expected;
|
||||
p += 2;
|
||||
/* check both src and dst memory index */
|
||||
read_leb_uint32(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
read_leb_uint32(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
|
||||
if (module->import_memory_count == 0
|
||||
&& module->memory_count == 0)
|
||||
@ -14666,9 +14707,8 @@ re_scan:
|
||||
}
|
||||
case WASM_OP_MEMORY_FILL:
|
||||
{
|
||||
if (*p++ != 0x00) {
|
||||
goto fail_zero_byte_expected;
|
||||
}
|
||||
read_leb_uint32(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
if (module->import_memory_count == 0
|
||||
&& module->memory_count == 0) {
|
||||
goto fail_unknown_memory;
|
||||
@ -14684,10 +14724,6 @@ re_scan:
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
fail_zero_byte_expected:
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"zero byte expected");
|
||||
goto fail;
|
||||
|
||||
fail_unknown_memory:
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
@ -14921,7 +14957,6 @@ re_scan:
|
||||
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
|
||||
case WASM_OP_SIMD_PREFIX:
|
||||
{
|
||||
/* TODO: memory64 offset type changes */
|
||||
uint32 opcode1;
|
||||
|
||||
#if WASM_ENABLE_WAMR_COMPILER != 0
|
||||
|
||||
@ -62,6 +62,17 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
||||
#define skip_leb_uint32(p, p_end) skip_leb(p)
|
||||
#define skip_leb_int32(p, p_end) skip_leb(p)
|
||||
#define skip_leb_mem_offset(p, p_end) skip_leb(p)
|
||||
#define skip_leb_memidx(p, p_end) skip_leb(p)
|
||||
#if WASM_ENABLE_MULTI_MEMORY == 0
|
||||
#define skip_leb_align(p, p_end) skip_leb(p)
|
||||
#else
|
||||
/* Skip the following memidx if applicable */
|
||||
#define skip_leb_align(p, p_end) \
|
||||
do { \
|
||||
if (*p++ & OPT_MEMIDX_FLAG) \
|
||||
skip_leb_uint32(p, p_end); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
static bool
|
||||
is_32bit_type(uint8 type)
|
||||
@ -132,6 +143,35 @@ is_byte_a_type(uint8 type)
|
||||
#else
|
||||
#define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res)
|
||||
#endif
|
||||
#define read_leb_memidx(p, p_end, res) read_leb_uint32(p, p_end, res)
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
#define check_memidx(module, memidx) \
|
||||
do { \
|
||||
bh_assert(memidx \
|
||||
< module->import_memory_count + module->memory_count); \
|
||||
(void)memidx; \
|
||||
} while (0)
|
||||
/* Bit 6 indicating the optional memidx, and reset bit 6 for
|
||||
* alignment check */
|
||||
#define read_leb_memarg(p, p_end, res) \
|
||||
do { \
|
||||
read_leb_uint32(p, p_end, res); \
|
||||
if (res & OPT_MEMIDX_FLAG) { \
|
||||
res &= ~OPT_MEMIDX_FLAG; \
|
||||
read_leb_uint32(p, p_end, memidx); /* memidx */ \
|
||||
check_memidx(module, memidx); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
/* reserved byte 0x00 */
|
||||
#define check_memidx(module, memidx) \
|
||||
do { \
|
||||
(void)module; \
|
||||
bh_assert(memidx == 0); \
|
||||
(void)memidx; \
|
||||
} while (0)
|
||||
#define read_leb_memarg(p, p_end, res) read_leb_uint32(p, p_end, res)
|
||||
#endif
|
||||
|
||||
static void *
|
||||
loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
|
||||
@ -882,7 +922,9 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
if (flags & 1)
|
||||
read_leb_uint32(p, p_end, u32);
|
||||
module->import_memory_count++;
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
bh_assert(module->import_memory_count <= 1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case IMPORT_KIND_GLOBAL: /* import global */
|
||||
@ -1223,7 +1265,9 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
||||
WASMMemory *memory;
|
||||
|
||||
read_leb_uint32(p, p_end, memory_count);
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
bh_assert(module->import_memory_count + memory_count <= 1);
|
||||
#endif
|
||||
|
||||
if (memory_count) {
|
||||
module->memory_count = memory_count;
|
||||
@ -3585,13 +3629,13 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
|
||||
case WASM_OP_I64_STORE8:
|
||||
case WASM_OP_I64_STORE16:
|
||||
case WASM_OP_I64_STORE32:
|
||||
skip_leb_uint32(p, p_end); /* align */
|
||||
skip_leb_align(p, p_end); /* align */
|
||||
skip_leb_mem_offset(p, p_end); /* offset */
|
||||
break;
|
||||
|
||||
case WASM_OP_MEMORY_SIZE:
|
||||
case WASM_OP_MEMORY_GROW:
|
||||
skip_leb_uint32(p, p_end); /* 0x00 */
|
||||
skip_leb_memidx(p, p_end); /* memidx */
|
||||
break;
|
||||
|
||||
case WASM_OP_I32_CONST:
|
||||
@ -3758,19 +3802,17 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
case WASM_OP_MEMORY_INIT:
|
||||
skip_leb_uint32(p, p_end);
|
||||
/* skip memory idx */
|
||||
p++;
|
||||
skip_leb_memidx(p, p_end);
|
||||
break;
|
||||
case WASM_OP_DATA_DROP:
|
||||
skip_leb_uint32(p, p_end);
|
||||
break;
|
||||
case WASM_OP_MEMORY_COPY:
|
||||
/* skip two memory idx */
|
||||
p += 2;
|
||||
skip_leb_memidx(p, p_end);
|
||||
skip_leb_memidx(p, p_end);
|
||||
break;
|
||||
case WASM_OP_MEMORY_FILL:
|
||||
/* skip memory idx */
|
||||
p++;
|
||||
skip_leb_memidx(p, p_end);
|
||||
break;
|
||||
#endif
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
@ -5905,7 +5947,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
||||
uint8 *param_types, *local_types, local_type, global_type, mem_offset_type;
|
||||
BlockType func_block_type;
|
||||
uint16 *local_offsets, local_offset;
|
||||
uint32 count, local_idx, global_idx, u32, align, i;
|
||||
uint32 count, local_idx, global_idx, u32, align, i, memidx;
|
||||
mem_offset_t mem_offset;
|
||||
int32 i32, i32_const = 0;
|
||||
int64 i64_const;
|
||||
@ -7267,7 +7309,7 @@ re_scan:
|
||||
}
|
||||
#endif
|
||||
CHECK_MEMORY();
|
||||
read_leb_uint32(p, p_end, align); /* align */
|
||||
read_leb_memarg(p, p_end, align); /* align */
|
||||
read_leb_mem_offset(p, p_end, mem_offset); /* offset */
|
||||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
emit_uint32(loader_ctx, mem_offset);
|
||||
@ -7329,9 +7371,8 @@ re_scan:
|
||||
|
||||
case WASM_OP_MEMORY_SIZE:
|
||||
CHECK_MEMORY();
|
||||
/* reserved byte 0x00 */
|
||||
bh_assert(*p == 0x00);
|
||||
p++;
|
||||
read_leb_memidx(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
PUSH_PAGE_COUNT();
|
||||
|
||||
module->possible_memory_grow = true;
|
||||
@ -7342,9 +7383,8 @@ re_scan:
|
||||
|
||||
case WASM_OP_MEMORY_GROW:
|
||||
CHECK_MEMORY();
|
||||
/* reserved byte 0x00 */
|
||||
bh_assert(*p == 0x00);
|
||||
p++;
|
||||
read_leb_memidx(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
POP_AND_PUSH(mem_offset_type, mem_offset_type);
|
||||
|
||||
module->possible_memory_grow = true;
|
||||
@ -7682,16 +7722,13 @@ re_scan:
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
case WASM_OP_MEMORY_INIT:
|
||||
{
|
||||
CHECK_MEMORY();
|
||||
read_leb_uint32(p, p_end, segment_index);
|
||||
#if WASM_ENABLE_FAST_INTERP != 0
|
||||
emit_uint32(loader_ctx, segment_index);
|
||||
#endif
|
||||
bh_assert(module->import_memory_count
|
||||
+ module->memory_count
|
||||
> 0);
|
||||
|
||||
bh_assert(*p == 0x00);
|
||||
p++;
|
||||
read_leb_memidx(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
|
||||
bh_assert(segment_index < module->data_seg_count);
|
||||
bh_assert(module->data_seg_count1 > 0);
|
||||
@ -7719,14 +7756,13 @@ re_scan:
|
||||
}
|
||||
case WASM_OP_MEMORY_COPY:
|
||||
{
|
||||
CHECK_MEMORY();
|
||||
CHECK_BUF(p, p_end, sizeof(int16));
|
||||
/* both src and dst memory index should be 0 */
|
||||
bh_assert(*(int16 *)p == 0x0000);
|
||||
p += 2;
|
||||
|
||||
bh_assert(module->import_memory_count
|
||||
+ module->memory_count
|
||||
> 0);
|
||||
/* check both src and dst memory index */
|
||||
read_leb_memidx(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
read_leb_memidx(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
|
||||
POP_MEM_OFFSET();
|
||||
POP_MEM_OFFSET();
|
||||
@ -7738,12 +7774,9 @@ re_scan:
|
||||
}
|
||||
case WASM_OP_MEMORY_FILL:
|
||||
{
|
||||
bh_assert(*p == 0);
|
||||
p++;
|
||||
|
||||
bh_assert(module->import_memory_count
|
||||
+ module->memory_count
|
||||
> 0);
|
||||
CHECK_MEMORY();
|
||||
read_leb_memidx(p, p_end, memidx);
|
||||
check_memidx(module, memidx);
|
||||
|
||||
POP_MEM_OFFSET();
|
||||
POP_I32();
|
||||
|
||||
@ -194,114 +194,119 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
|
||||
default_max_page =
|
||||
memory->is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
|
||||
|
||||
if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1
|
||||
&& module_inst->module->free_function != (uint32)-1) {
|
||||
/* Disable app heap, use malloc/free function exported
|
||||
by wasm app to allocate/free memory instead */
|
||||
heap_size = 0;
|
||||
}
|
||||
/* The app heap should be in the default memory */
|
||||
if (memory_idx == 0) {
|
||||
if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1
|
||||
&& module_inst->module->free_function != (uint32)-1) {
|
||||
/* Disable app heap, use malloc/free function exported
|
||||
by wasm app to allocate/free memory instead */
|
||||
heap_size = 0;
|
||||
}
|
||||
|
||||
/* If initial memory is the largest size allowed, disallowing insert host
|
||||
* managed heap */
|
||||
if (heap_size > 0
|
||||
&& heap_offset == GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"failed to insert app heap into linear memory, "
|
||||
"try using `--heap-size=0` option");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (init_page_count == max_page_count && init_page_count == 1) {
|
||||
/* If only one page and at most one page, we just append
|
||||
the app heap to the end of linear memory, enlarge the
|
||||
num_bytes_per_page, and don't change the page count */
|
||||
heap_offset = num_bytes_per_page;
|
||||
num_bytes_per_page += heap_size;
|
||||
if (num_bytes_per_page < heap_size) {
|
||||
/* If initial memory is the largest size allowed, disallowing insert
|
||||
* host managed heap */
|
||||
if (heap_size > 0
|
||||
&& heap_offset == GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"failed to insert app heap into linear memory, "
|
||||
"try using `--heap-size=0` option");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (heap_size > 0) {
|
||||
if (init_page_count == max_page_count && init_page_count == 0) {
|
||||
/* If the memory data size is always 0, we resize it to
|
||||
one page for app heap */
|
||||
num_bytes_per_page = heap_size;
|
||||
heap_offset = 0;
|
||||
inc_page_count = 1;
|
||||
}
|
||||
else if (module->aux_heap_base_global_index != (uint32)-1
|
||||
&& module->aux_heap_base
|
||||
< (uint64)num_bytes_per_page * init_page_count) {
|
||||
/* Insert app heap before __heap_base */
|
||||
aux_heap_base = module->aux_heap_base;
|
||||
bytes_of_last_page = aux_heap_base % num_bytes_per_page;
|
||||
if (bytes_of_last_page == 0)
|
||||
bytes_of_last_page = num_bytes_per_page;
|
||||
bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
|
||||
inc_page_count =
|
||||
(heap_size - bytes_to_page_end + num_bytes_per_page - 1)
|
||||
/ num_bytes_per_page;
|
||||
heap_offset = aux_heap_base;
|
||||
aux_heap_base += heap_size;
|
||||
|
||||
bytes_of_last_page = aux_heap_base % num_bytes_per_page;
|
||||
if (bytes_of_last_page == 0)
|
||||
bytes_of_last_page = num_bytes_per_page;
|
||||
bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
|
||||
if (bytes_to_page_end < 1 * BH_KB) {
|
||||
aux_heap_base += 1 * BH_KB;
|
||||
inc_page_count++;
|
||||
if (init_page_count == max_page_count && init_page_count == 1) {
|
||||
/* If only one page and at most one page, we just append
|
||||
the app heap to the end of linear memory, enlarge the
|
||||
num_bytes_per_page, and don't change the page count */
|
||||
heap_offset = num_bytes_per_page;
|
||||
num_bytes_per_page += heap_size;
|
||||
if (num_bytes_per_page < heap_size) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"failed to insert app heap into linear memory, "
|
||||
"try using `--heap-size=0` option");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (heap_size > 0) {
|
||||
if (init_page_count == max_page_count && init_page_count == 0) {
|
||||
/* If the memory data size is always 0, we resize it to
|
||||
one page for app heap */
|
||||
num_bytes_per_page = heap_size;
|
||||
heap_offset = 0;
|
||||
inc_page_count = 1;
|
||||
}
|
||||
else if (module->aux_heap_base_global_index != (uint32)-1
|
||||
&& module->aux_heap_base
|
||||
< (uint64)num_bytes_per_page * init_page_count) {
|
||||
/* Insert app heap before __heap_base */
|
||||
aux_heap_base = module->aux_heap_base;
|
||||
bytes_of_last_page = aux_heap_base % num_bytes_per_page;
|
||||
if (bytes_of_last_page == 0)
|
||||
bytes_of_last_page = num_bytes_per_page;
|
||||
bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
|
||||
inc_page_count =
|
||||
(heap_size - bytes_to_page_end + num_bytes_per_page - 1)
|
||||
/ num_bytes_per_page;
|
||||
heap_offset = aux_heap_base;
|
||||
aux_heap_base += heap_size;
|
||||
|
||||
/* Adjust __heap_base global value */
|
||||
global_idx = module->aux_heap_base_global_index;
|
||||
bh_assert(module_inst->e->globals
|
||||
&& global_idx < module_inst->e->global_count);
|
||||
global_addr = module_inst->global_data
|
||||
+ module_inst->e->globals[global_idx].data_offset;
|
||||
bytes_of_last_page = aux_heap_base % num_bytes_per_page;
|
||||
if (bytes_of_last_page == 0)
|
||||
bytes_of_last_page = num_bytes_per_page;
|
||||
bytes_to_page_end = num_bytes_per_page - bytes_of_last_page;
|
||||
if (bytes_to_page_end < 1 * BH_KB) {
|
||||
aux_heap_base += 1 * BH_KB;
|
||||
inc_page_count++;
|
||||
}
|
||||
|
||||
/* Adjust __heap_base global value */
|
||||
global_idx = module->aux_heap_base_global_index;
|
||||
bh_assert(module_inst->e->globals
|
||||
&& global_idx < module_inst->e->global_count);
|
||||
global_addr = module_inst->global_data
|
||||
+ module_inst->e->globals[global_idx].data_offset;
|
||||
#if WASM_ENABLE_MEMORY64 != 0
|
||||
if (memory->is_memory64) {
|
||||
/* For memory64, the global value should be i64 */
|
||||
*(uint64 *)global_addr = aux_heap_base;
|
||||
}
|
||||
else
|
||||
if (memory->is_memory64) {
|
||||
/* For memory64, the global value should be i64 */
|
||||
*(uint64 *)global_addr = aux_heap_base;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* For memory32, the global value should be i32 */
|
||||
*(uint32 *)global_addr = (uint32)aux_heap_base;
|
||||
{
|
||||
/* For memory32, the global value should be i32 */
|
||||
*(uint32 *)global_addr = (uint32)aux_heap_base;
|
||||
}
|
||||
LOG_VERBOSE("Reset __heap_base global to %" PRIu64,
|
||||
aux_heap_base);
|
||||
}
|
||||
else {
|
||||
/* Insert app heap before new page */
|
||||
inc_page_count =
|
||||
(heap_size + num_bytes_per_page - 1) / num_bytes_per_page;
|
||||
heap_offset = (uint64)num_bytes_per_page * init_page_count;
|
||||
heap_size = (uint64)num_bytes_per_page * inc_page_count;
|
||||
if (heap_size > 0)
|
||||
heap_size -= 1 * BH_KB;
|
||||
}
|
||||
init_page_count += inc_page_count;
|
||||
max_page_count += inc_page_count;
|
||||
if (init_page_count > default_max_page) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"failed to insert app heap into linear memory, "
|
||||
"try using `--heap-size=0` option");
|
||||
return NULL;
|
||||
}
|
||||
LOG_VERBOSE("Reset __heap_base global to %" PRIu64, aux_heap_base);
|
||||
}
|
||||
else {
|
||||
/* Insert app heap before new page */
|
||||
inc_page_count =
|
||||
(heap_size + num_bytes_per_page - 1) / num_bytes_per_page;
|
||||
heap_offset = (uint64)num_bytes_per_page * init_page_count;
|
||||
heap_size = (uint64)num_bytes_per_page * inc_page_count;
|
||||
if (heap_size > 0)
|
||||
heap_size -= 1 * BH_KB;
|
||||
}
|
||||
init_page_count += inc_page_count;
|
||||
max_page_count += inc_page_count;
|
||||
if (init_page_count > default_max_page) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"failed to insert app heap into linear memory, "
|
||||
"try using `--heap-size=0` option");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (max_page_count > default_max_page)
|
||||
max_page_count = default_max_page;
|
||||
if (max_page_count > default_max_page)
|
||||
max_page_count = default_max_page;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_VERBOSE("Memory instantiate:");
|
||||
LOG_VERBOSE(" page bytes: %u, init pages: %u, max pages: %u",
|
||||
num_bytes_per_page, init_page_count, max_page_count);
|
||||
LOG_VERBOSE(" heap offset: %" PRIu64 ", heap size: %u\n", heap_offset,
|
||||
heap_size);
|
||||
if (memory_idx == 0)
|
||||
LOG_VERBOSE(" heap offset: %" PRIu64 ", heap size: %u\n", heap_offset,
|
||||
heap_size);
|
||||
|
||||
max_memory_data_size = (uint64)num_bytes_per_page * max_page_count;
|
||||
bh_assert(max_memory_data_size
|
||||
@ -326,12 +331,14 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
|
||||
memory->max_page_count = max_page_count;
|
||||
memory->memory_data_size = memory_data_size;
|
||||
|
||||
memory->heap_data = memory->memory_data + heap_offset;
|
||||
memory->heap_data_end = memory->heap_data + heap_size;
|
||||
memory->memory_data_end = memory->memory_data + memory_data_size;
|
||||
if (memory_idx == 0) {
|
||||
memory->heap_data = memory->memory_data + heap_offset;
|
||||
memory->heap_data_end = memory->heap_data + heap_size;
|
||||
memory->memory_data_end = memory->memory_data + memory_data_size;
|
||||
}
|
||||
|
||||
/* Initialize heap */
|
||||
if (heap_size > 0) {
|
||||
if (memory_idx == 0 && heap_size > 0) {
|
||||
uint32 heap_struct_size = mem_allocator_get_heap_struct_size();
|
||||
|
||||
if (!(memory->heap_handle = runtime_malloc(
|
||||
@ -361,7 +368,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
|
||||
return memory;
|
||||
|
||||
fail2:
|
||||
if (heap_size > 0)
|
||||
if (memory_idx == 0 && heap_size > 0)
|
||||
wasm_runtime_free(memory->heap_handle);
|
||||
fail1:
|
||||
if (memory->memory_data)
|
||||
@ -1351,7 +1358,45 @@ export_globals_instantiate(const WASMModule *module,
|
||||
bh_assert((uint32)(export_global - export_globals) == export_glob_count);
|
||||
return export_globals;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
static void
|
||||
export_memories_deinstantiate(WASMExportMemInstance *memories)
|
||||
{
|
||||
if (memories)
|
||||
wasm_runtime_free(memories);
|
||||
}
|
||||
|
||||
static WASMExportMemInstance *
|
||||
export_memories_instantiate(const WASMModule *module,
|
||||
WASMModuleInstance *module_inst,
|
||||
uint32 export_mem_count, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
WASMExportMemInstance *export_memories, *export_memory;
|
||||
WASMExport *export = module->exports;
|
||||
uint32 i;
|
||||
uint64 total_size =
|
||||
sizeof(WASMExportMemInstance) * (uint64)export_mem_count;
|
||||
|
||||
if (!(export_memory = export_memories =
|
||||
runtime_malloc(total_size, error_buf, error_buf_size))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < module->export_count; i++, export ++)
|
||||
if (export->kind == EXPORT_KIND_MEMORY) {
|
||||
export_memory->name = export->name;
|
||||
export_memory->memory = module_inst->memories[export->index];
|
||||
export_memory++;
|
||||
}
|
||||
|
||||
bh_assert((uint32)(export_memory - export_memories) == export_mem_count);
|
||||
return export_memories;
|
||||
}
|
||||
#endif /* end of if WASM_ENABLE_MULTI_MEMORY != 0 */
|
||||
|
||||
#endif /* end of if WASM_ENABLE_MULTI_MODULE != 0 */
|
||||
|
||||
static WASMFunctionInstance *
|
||||
lookup_post_instantiate_func(WASMModuleInstance *module_inst,
|
||||
@ -2387,6 +2432,12 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||
module, module_inst, module_inst->export_global_count,
|
||||
error_buf, error_buf_size)))
|
||||
#endif
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0 && WASM_ENABLE_MULTI_MEMORY != 0
|
||||
|| (module_inst->export_memory_count > 0
|
||||
&& !(module_inst->export_memories = export_memories_instantiate(
|
||||
module, module_inst, module_inst->export_memory_count,
|
||||
error_buf, error_buf_size)))
|
||||
#endif
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
|| (module_inst->e->function_count > 0
|
||||
&& !init_func_ptrs(module_inst, module, error_buf, error_buf_size))
|
||||
@ -3189,6 +3240,10 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
||||
export_globals_deinstantiate(module_inst->export_globals);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0 && WASM_ENABLE_MULTI_MEMORY != 0
|
||||
export_memories_deinstantiate(module_inst->export_memories);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
|
||||
wasm_externref_cleanup((WASMModuleInstanceCommon *)module_inst);
|
||||
#endif
|
||||
@ -3251,12 +3306,16 @@ wasm_lookup_global(const WASMModuleInstance *module_inst, const char *name)
|
||||
WASMMemoryInstance *
|
||||
wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name)
|
||||
{
|
||||
/**
|
||||
* using a strong assumption that one module instance only has
|
||||
* one memory instance
|
||||
*/
|
||||
#if WASM_ENABLE_MULTI_MEMORY != 0
|
||||
uint32 i;
|
||||
for (i = 0; i < module_inst->export_memory_count; i++)
|
||||
if (!strcmp(module_inst->export_memories[i].name, name))
|
||||
return module_inst->export_memories[i].memory;
|
||||
return NULL;
|
||||
#else
|
||||
(void)module_inst->export_memories;
|
||||
return module_inst->memories[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
WASMTableInstance *
|
||||
|
||||
@ -620,9 +620,16 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
||||
WASMMemoryInstance *
|
||||
wasm_get_default_memory(WASMModuleInstance *module_inst);
|
||||
|
||||
WASMMemoryInstance *
|
||||
wasm_get_memory_with_idx(WASMModuleInstance *module_inst, uint32 index);
|
||||
|
||||
bool
|
||||
wasm_enlarge_memory(WASMModuleInstance *module_inst, uint32 inc_page_count);
|
||||
|
||||
bool
|
||||
wasm_enlarge_memory_with_idx(WASMModuleInstance *module_inst,
|
||||
uint32 inc_page_count, uint32 memidx);
|
||||
|
||||
bool
|
||||
wasm_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
|
||||
uint32 argc, uint32 argv[]);
|
||||
|
||||
Reference in New Issue
Block a user