mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-11 15:03:33 +00:00
Compare commits
2 Commits
1394b8a7a7
...
969072567a
Author | SHA1 | Date | |
---|---|---|---|
![]() |
969072567a | ||
![]() |
ccdc8369d6 |
|
@ -185,6 +185,13 @@ typedef struct {
|
||||||
#define REG_STRINGREF_SYM()
|
#define REG_STRINGREF_SYM()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
|
#define REG_SHARED_HEAP_SYM() \
|
||||||
|
REG_SYM(wasm_runtime_check_and_update_last_used_shared_heap),
|
||||||
|
#else
|
||||||
|
#define REG_SHARED_HEAP_SYM()
|
||||||
|
#endif
|
||||||
|
|
||||||
#define REG_COMMON_SYMBOLS \
|
#define REG_COMMON_SYMBOLS \
|
||||||
REG_SYM(aot_set_exception_with_id), \
|
REG_SYM(aot_set_exception_with_id), \
|
||||||
REG_SYM(aot_invoke_native), \
|
REG_SYM(aot_invoke_native), \
|
||||||
|
@ -218,6 +225,7 @@ typedef struct {
|
||||||
REG_LLVM_PGO_SYM() \
|
REG_LLVM_PGO_SYM() \
|
||||||
REG_GC_SYM() \
|
REG_GC_SYM() \
|
||||||
REG_STRINGREF_SYM() \
|
REG_STRINGREF_SYM() \
|
||||||
|
REG_SHARED_HEAP_SYM() \
|
||||||
|
|
||||||
#define CHECK_RELOC_OFFSET(data_size) do { \
|
#define CHECK_RELOC_OFFSET(data_size) do { \
|
||||||
if (!check_reloc_offset(target_section_size, \
|
if (!check_reloc_offset(target_section_size, \
|
||||||
|
|
|
@ -63,6 +63,14 @@ bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_start_off) == 16);
|
||||||
bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_end_off) == 24);
|
bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_end_off) == 24);
|
||||||
bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap) == 32);
|
bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap) == 32);
|
||||||
|
|
||||||
|
bh_static_assert(offsetof(WASMSharedHeap, next) == 0);
|
||||||
|
bh_static_assert(offsetof(WASMSharedHeap, chain_next) == 8);
|
||||||
|
bh_static_assert(offsetof(WASMSharedHeap, heap_handle) == 16);
|
||||||
|
bh_static_assert(offsetof(WASMSharedHeap, base_addr) == 24);
|
||||||
|
bh_static_assert(offsetof(WASMSharedHeap, size) == 32);
|
||||||
|
bh_static_assert(offsetof(WASMSharedHeap, start_off_mem64) == 40);
|
||||||
|
bh_static_assert(offsetof(WASMSharedHeap, start_off_mem32) == 48);
|
||||||
|
|
||||||
bh_static_assert(sizeof(CApiFuncImport) == sizeof(uintptr_t) * 3);
|
bh_static_assert(sizeof(CApiFuncImport) == sizeof(uintptr_t) * 3);
|
||||||
|
|
||||||
bh_static_assert(sizeof(wasm_val_t) == 16);
|
bh_static_assert(sizeof(wasm_val_t) == 16);
|
||||||
|
@ -1991,6 +1999,8 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
|
||||||
#else
|
#else
|
||||||
extra->shared_heap_start_off.u32[0] = UINT32_MAX;
|
extra->shared_heap_start_off.u32[0] = UINT32_MAX;
|
||||||
#endif
|
#endif
|
||||||
|
/* After shared heap chain, will early stop if shared heap is NULL */
|
||||||
|
extra->shared_heap = NULL;
|
||||||
|
|
||||||
#if WASM_ENABLE_PERF_PROFILING != 0
|
#if WASM_ENABLE_PERF_PROFILING != 0
|
||||||
total_size = sizeof(AOTFuncPerfProfInfo)
|
total_size = sizeof(AOTFuncPerfProfInfo)
|
||||||
|
|
|
@ -178,16 +178,16 @@ wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args)
|
||||||
}
|
}
|
||||||
|
|
||||||
size = align_uint(size, os_getpagesize());
|
size = align_uint(size, os_getpagesize());
|
||||||
heap->size = size;
|
|
||||||
heap->start_off_mem64 = UINT64_MAX - heap->size + 1;
|
|
||||||
heap->start_off_mem32 = UINT32_MAX - heap->size + 1;
|
|
||||||
heap->attached_count = 0;
|
|
||||||
|
|
||||||
if (size > APP_HEAP_SIZE_MAX || size < APP_HEAP_SIZE_MIN) {
|
if (size > APP_HEAP_SIZE_MAX || size < APP_HEAP_SIZE_MIN) {
|
||||||
LOG_WARNING("Invalid size of shared heap");
|
LOG_WARNING("Invalid size of shared heap");
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
heap->size = size;
|
||||||
|
heap->start_off_mem64 = UINT64_MAX - heap->size + 1;
|
||||||
|
heap->start_off_mem32 = UINT32_MAX - heap->size + 1;
|
||||||
|
heap->attached_count = 0;
|
||||||
|
|
||||||
if (init_args->pre_allocated_addr != NULL) {
|
if (init_args->pre_allocated_addr != NULL) {
|
||||||
/* Create shared heap from a pre allocated buffer, its size need to
|
/* Create shared heap from a pre allocated buffer, its size need to
|
||||||
* align with system page */
|
* align with system page */
|
||||||
|
@ -275,6 +275,13 @@ wasm_runtime_chain_shared_heaps(WASMSharedHeap *head, WASMSharedHeap *body)
|
||||||
os_mutex_unlock(&shared_heap_list_lock);
|
os_mutex_unlock(&shared_heap_list_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (cur == head && cur->chain_next) {
|
||||||
|
LOG_WARNING(
|
||||||
|
"To create shared heap chain, the 'head' shared heap can't "
|
||||||
|
"already be the 'head' in another a chain");
|
||||||
|
os_mutex_unlock(&shared_heap_list_lock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (cur = body; cur; cur = cur->chain_next) {
|
for (cur = body; cur; cur = cur->chain_next) {
|
||||||
if (cur->heap_handle && heap_handle_exist) {
|
if (cur->heap_handle && heap_handle_exist) {
|
||||||
|
@ -519,6 +526,10 @@ wasm_runtime_attach_shared_heap(WASMModuleInstanceCommon *module_inst,
|
||||||
void
|
void
|
||||||
wasm_runtime_detach_shared_heap_internal(WASMModuleInstanceCommon *module_inst)
|
wasm_runtime_detach_shared_heap_internal(WASMModuleInstanceCommon *module_inst)
|
||||||
{
|
{
|
||||||
|
/* Reset shared_heap_end_off = UINT64/32_MAX - 1 to handling a corner case,
|
||||||
|
app_offset >= shared_heap_start && app_offset <= shared_heap_end-bytes+1
|
||||||
|
when bytes=1 and both e->shared_heap_start_off and e->shared_heap_end_off
|
||||||
|
is 0xffffffff */
|
||||||
#if WASM_ENABLE_INTERP != 0
|
#if WASM_ENABLE_INTERP != 0
|
||||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||||
WASMModuleInstanceExtra *e =
|
WASMModuleInstanceExtra *e =
|
||||||
|
@ -614,7 +625,7 @@ is_app_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
|
||||||
shared_heap_start =
|
shared_heap_start =
|
||||||
(uint64)get_last_used_shared_heap_start_offset(module_inst);
|
(uint64)get_last_used_shared_heap_start_offset(module_inst);
|
||||||
shared_heap_end = (uint64)get_last_used_shared_heap_end_offset(module_inst);
|
shared_heap_end = (uint64)get_last_used_shared_heap_end_offset(module_inst);
|
||||||
if (app_offset >= shared_heap_start
|
if (bytes - 1 <= shared_heap_end && app_offset >= shared_heap_start
|
||||||
&& app_offset <= shared_heap_end - bytes + 1) {
|
&& app_offset <= shared_heap_end - bytes + 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -623,7 +634,7 @@ is_app_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
|
||||||
shared_heap_start =
|
shared_heap_start =
|
||||||
is_memory64 ? heap->start_off_mem64 : heap->start_off_mem32;
|
is_memory64 ? heap->start_off_mem64 : heap->start_off_mem32;
|
||||||
shared_heap_end = is_memory64 ? UINT64_MAX : UINT32_MAX;
|
shared_heap_end = is_memory64 ? UINT64_MAX : UINT32_MAX;
|
||||||
if (app_offset < shared_heap_start
|
if (bytes - 1 > shared_heap_end || app_offset < shared_heap_start
|
||||||
|| app_offset > shared_heap_end - bytes + 1) {
|
|| app_offset > shared_heap_end - bytes + 1) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -634,7 +645,7 @@ is_app_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
|
||||||
shared_heap_start =
|
shared_heap_start =
|
||||||
is_memory64 ? cur->start_off_mem64 : cur->start_off_mem32;
|
is_memory64 ? cur->start_off_mem64 : cur->start_off_mem32;
|
||||||
shared_heap_end = shared_heap_start - 1 + cur->size;
|
shared_heap_end = shared_heap_start - 1 + cur->size;
|
||||||
if (app_offset >= shared_heap_start
|
if (bytes - 1 <= shared_heap_end && app_offset >= shared_heap_start
|
||||||
&& app_offset <= shared_heap_end - bytes + 1) {
|
&& app_offset <= shared_heap_end - bytes + 1) {
|
||||||
update_last_used_shared_heap(module_inst, cur, is_memory64);
|
update_last_used_shared_heap(module_inst, cur, is_memory64);
|
||||||
return true;
|
return true;
|
||||||
|
@ -1072,7 +1083,7 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
|
||||||
shared_heap_base_addr_adj =
|
shared_heap_base_addr_adj =
|
||||||
(char *)get_last_used_shared_heap_base_addr_adj(module_inst_comm);
|
(char *)get_last_used_shared_heap_base_addr_adj(module_inst_comm);
|
||||||
str = shared_heap_base_addr_adj + app_str_offset;
|
str = shared_heap_base_addr_adj + app_str_offset;
|
||||||
str_end = shared_heap_base_addr_adj + shared_heap_end_off;
|
str_end = shared_heap_base_addr_adj + shared_heap_end_off + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
@ -1227,7 +1238,9 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
|
||||||
#if WASM_ENABLE_SHARED_HEAP != 0
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
if (is_native_addr_in_shared_heap(module_inst_comm,
|
if (is_native_addr_in_shared_heap(module_inst_comm,
|
||||||
memory_inst->is_memory64, addr, 1)) {
|
memory_inst->is_memory64, addr, 1)) {
|
||||||
return addr - get_last_used_shared_heap_base_addr_adj(module_inst_comm);
|
return (uint64)(uintptr_t)(addr
|
||||||
|
- get_last_used_shared_heap_base_addr_adj(
|
||||||
|
module_inst_comm));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1349,11 +1362,12 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
||||||
(WASMModuleInstanceCommon *)module_inst);
|
(WASMModuleInstanceCommon *)module_inst);
|
||||||
shared_heap_end_off = get_last_used_shared_heap_end_offset(
|
shared_heap_end_off = get_last_used_shared_heap_end_offset(
|
||||||
(WASMModuleInstanceCommon *)module_inst);
|
(WASMModuleInstanceCommon *)module_inst);
|
||||||
native_addr = shared_heap_base_addr_adj + app_buf_addr;
|
native_addr = shared_heap_base_addr_adj + (uintptr_t)app_buf_addr;
|
||||||
|
|
||||||
/* The whole string must be in the shared heap */
|
/* The whole string must be in the shared heap */
|
||||||
str = (const char *)native_addr;
|
str = (const char *)native_addr;
|
||||||
str_end = (const char *)shared_heap_base_addr_adj + shared_heap_end_off;
|
str_end =
|
||||||
|
(const char *)shared_heap_base_addr_adj + shared_heap_end_off + 1;
|
||||||
while (str < str_end && *str != '\0')
|
while (str < str_end && *str != '\0')
|
||||||
str++;
|
str++;
|
||||||
if (str == str_end) {
|
if (str == str_end) {
|
||||||
|
|
|
@ -7883,3 +7883,37 @@ wasm_runtime_is_underlying_binary_freeable(WASMModuleCommon *const module)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
|
bool
|
||||||
|
wasm_runtime_check_and_update_last_used_shared_heap(
|
||||||
|
WASMModuleInstanceCommon *module_inst, uintptr_t app_offset, size_t bytes,
|
||||||
|
uintptr_t *shared_heap_start_off_p, uintptr_t *shared_heap_end_off_p,
|
||||||
|
uint8 **shared_heap_base_addr_adj_p, bool is_memory64)
|
||||||
|
{
|
||||||
|
WASMSharedHeap *heap = wasm_runtime_get_shared_heap(module_inst), *cur;
|
||||||
|
uint64 shared_heap_start, shared_heap_end;
|
||||||
|
|
||||||
|
if (bytes == 0) {
|
||||||
|
bytes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the exact shared heap that app addr is in, and update last used
|
||||||
|
* shared heap info in func context */
|
||||||
|
for (cur = heap; cur; cur = cur->chain_next) {
|
||||||
|
shared_heap_start =
|
||||||
|
is_memory64 ? cur->start_off_mem64 : cur->start_off_mem32;
|
||||||
|
shared_heap_end = shared_heap_start - 1 + cur->size;
|
||||||
|
if (bytes - 1 <= shared_heap_end && app_offset >= shared_heap_start
|
||||||
|
&& app_offset <= shared_heap_end - bytes + 1) {
|
||||||
|
*shared_heap_start_off_p = (uintptr_t)shared_heap_start;
|
||||||
|
*shared_heap_end_off_p = (uintptr_t)shared_heap_end;
|
||||||
|
*shared_heap_base_addr_adj_p =
|
||||||
|
cur->base_addr - (uintptr_t)shared_heap_start;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1336,6 +1336,14 @@ void
|
||||||
wasm_runtime_set_linux_perf(bool flag);
|
wasm_runtime_set_linux_perf(bool flag);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
|
bool
|
||||||
|
wasm_runtime_check_and_update_last_used_shared_heap(
|
||||||
|
WASMModuleInstanceCommon *module_inst, uintptr_t app_offset, size_t bytes,
|
||||||
|
uintptr_t *shared_heap_start_off_p, uintptr_t *shared_heap_end_off_p,
|
||||||
|
uint8 **shared_heap_base_addr_adj_p, bool is_memory64);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,6 +10,40 @@
|
||||||
#include "aot_intrinsic.h"
|
#include "aot_intrinsic.h"
|
||||||
#include "aot_emit_control.h"
|
#include "aot_emit_control.h"
|
||||||
|
|
||||||
|
#define BUILD_IS_NOT_NULL(value, res, name) \
|
||||||
|
do { \
|
||||||
|
if (!(res = LLVMBuildIsNotNull(comp_ctx->builder, value, name))) { \
|
||||||
|
aot_set_last_error("llvm build is not null failed."); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define BUILD_BR(llvm_block) \
|
||||||
|
do { \
|
||||||
|
if (!LLVMBuildBr(comp_ctx->builder, llvm_block)) { \
|
||||||
|
aot_set_last_error("llvm build br failed."); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define BUILD_COND_BR(value_if, block_then, block_else) \
|
||||||
|
do { \
|
||||||
|
if (!LLVMBuildCondBr(comp_ctx->builder, value_if, block_then, \
|
||||||
|
block_else)) { \
|
||||||
|
aot_set_last_error("llvm build cond br failed."); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define BUILD_TRUNC(value, data_type) \
|
||||||
|
do { \
|
||||||
|
if (!(value = LLVMBuildTrunc(comp_ctx->builder, value, data_type, \
|
||||||
|
"val_trunc"))) { \
|
||||||
|
aot_set_last_error("llvm build trunc failed."); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define BUILD_ICMP(op, left, right, res, name) \
|
#define BUILD_ICMP(op, left, right, res, name) \
|
||||||
do { \
|
do { \
|
||||||
if (!(res = \
|
if (!(res = \
|
||||||
|
@ -111,6 +145,418 @@ ffs(int n)
|
||||||
static LLVMValueRef
|
static LLVMValueRef
|
||||||
get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||||
|
|
||||||
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
|
uint32
|
||||||
|
get_module_inst_extra_offset(AOTCompContext *comp_ctx);
|
||||||
|
|
||||||
|
#define BUILD_LOAD_PTR(ptr, data_type, res) \
|
||||||
|
do { \
|
||||||
|
if (!(res = LLVMBuildLoad2(comp_ctx->builder, data_type, ptr, \
|
||||||
|
"load_value"))) { \
|
||||||
|
aot_set_last_error("llvm build load failed"); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Update last used shared heap info(alloc ptr) in function ctx:
|
||||||
|
* 1. shared_heap_start_off 2. shared_heap_end_off 3. shared_heap_base_addr_adj
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
aot_check_shared_heap_chain_and_update(AOTCompContext *comp_ctx,
|
||||||
|
AOTFuncContext *func_ctx,
|
||||||
|
LLVMBasicBlockRef check_succ,
|
||||||
|
LLVMValueRef start_offset,
|
||||||
|
LLVMValueRef bytes, bool is_memory64)
|
||||||
|
{
|
||||||
|
LLVMValueRef param_values[7], ret_value, func, value, cmp;
|
||||||
|
LLVMTypeRef param_types[7], ret_type, func_type, func_ptr_type;
|
||||||
|
|
||||||
|
param_types[0] = INT8_PTR_TYPE;
|
||||||
|
param_types[1] = INTPTR_T_TYPE;
|
||||||
|
param_types[2] = SIZE_T_TYPE;
|
||||||
|
param_types[3] = INTPTR_T_PTR_TYPE;
|
||||||
|
param_types[4] = INTPTR_T_PTR_TYPE;
|
||||||
|
param_types[5] = INT8_PTR_TYPE;
|
||||||
|
param_types[6] = INT8_TYPE;
|
||||||
|
ret_type = INT8_TYPE;
|
||||||
|
|
||||||
|
GET_AOT_FUNCTION(wasm_runtime_check_and_update_last_used_shared_heap, 7);
|
||||||
|
|
||||||
|
/* Call function */
|
||||||
|
param_values[0] = func_ctx->aot_inst;
|
||||||
|
param_values[1] = start_offset;
|
||||||
|
param_values[2] = bytes;
|
||||||
|
/* pass alloc ptr */
|
||||||
|
param_values[3] = func_ctx->shared_heap_start_off;
|
||||||
|
param_values[4] = func_ctx->shared_heap_end_off;
|
||||||
|
param_values[5] = func_ctx->shared_heap_base_addr_adj;
|
||||||
|
param_values[6] = is_memory64 ? I8_ONE : I8_ZERO;
|
||||||
|
|
||||||
|
if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
|
||||||
|
param_values, 7, "call"))) {
|
||||||
|
aot_set_last_error("llvm build call failed.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
BUILD_ICMP(LLVMIntEQ, ret_value, I8_ZERO, cmp, "shared_heap_oob");
|
||||||
|
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||||
|
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp,
|
||||||
|
check_succ)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the basic blocks for shared heap and shared chain memory checks.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* block_curr: The current basic block.
|
||||||
|
* app_addr_in_cache_shared_heap: Output, block for cache shared heap.
|
||||||
|
* app_addr_in_linear_mem: Output, block for linear memory.
|
||||||
|
* app_addr_in_shared_heap_chain: Output, block for shared heap chain
|
||||||
|
* (only for shared heap chain).
|
||||||
|
* check_shared_heap_chain: Output, block for checking shared heap chain
|
||||||
|
* (only for shared heap chain).
|
||||||
|
*
|
||||||
|
* Topology:
|
||||||
|
* If enable_shared_heap:
|
||||||
|
* block_curr -> app_addr_in_cache_shared_heap
|
||||||
|
* -> app_addr_in_linear_mem
|
||||||
|
* If enable_shared_chain:
|
||||||
|
* block_curr -> app_addr_in_shared_heap_chain
|
||||||
|
* -> app_addr_in_cache_shared_heap
|
||||||
|
* -> check_shared_heap_chain
|
||||||
|
* -> app_addr_in_linear_mem
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
setup_shared_heap_blocks(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
|
LLVMBasicBlockRef block_curr,
|
||||||
|
LLVMBasicBlockRef *app_addr_in_cache_shared_heap,
|
||||||
|
LLVMBasicBlockRef *app_addr_in_linear_mem,
|
||||||
|
LLVMBasicBlockRef *app_addr_in_shared_heap_chain,
|
||||||
|
LLVMBasicBlockRef *check_shared_heap_chain)
|
||||||
|
{
|
||||||
|
ADD_BASIC_BLOCK(*app_addr_in_cache_shared_heap,
|
||||||
|
"app_addr_in_cache_shared_heap");
|
||||||
|
ADD_BASIC_BLOCK(*app_addr_in_linear_mem, "app_addr_in_linear_mem");
|
||||||
|
|
||||||
|
if (comp_ctx->enable_shared_heap) {
|
||||||
|
LLVMMoveBasicBlockAfter(*app_addr_in_cache_shared_heap, block_curr);
|
||||||
|
LLVMMoveBasicBlockAfter(*app_addr_in_linear_mem,
|
||||||
|
*app_addr_in_cache_shared_heap);
|
||||||
|
}
|
||||||
|
else if (comp_ctx->enable_shared_chain) {
|
||||||
|
ADD_BASIC_BLOCK(*app_addr_in_shared_heap_chain,
|
||||||
|
"app_addr_in_shared_heap_chain");
|
||||||
|
ADD_BASIC_BLOCK(*check_shared_heap_chain, "check_shared_heap_chain");
|
||||||
|
LLVMMoveBasicBlockAfter(*app_addr_in_shared_heap_chain, block_curr);
|
||||||
|
LLVMMoveBasicBlockAfter(*app_addr_in_cache_shared_heap,
|
||||||
|
*app_addr_in_shared_heap_chain);
|
||||||
|
LLVMMoveBasicBlockAfter(*check_shared_heap_chain,
|
||||||
|
*app_addr_in_cache_shared_heap);
|
||||||
|
LLVMMoveBasicBlockAfter(*app_addr_in_linear_mem,
|
||||||
|
*app_addr_in_cache_shared_heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build a branch to check if start_offset is in the shared heap chain region.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* start_offset: The offset to check.
|
||||||
|
* app_addr_in_shared_heap_chain: Block to branch if in shared heap chain.
|
||||||
|
* app_addr_in_linear_mem: Block to branch if not in shared heap chain.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
build_check_app_addr_in_shared_heap_chain(
|
||||||
|
AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
|
LLVMValueRef start_offset, LLVMBasicBlockRef app_addr_in_shared_heap_chain,
|
||||||
|
LLVMBasicBlockRef app_addr_in_linear_mem)
|
||||||
|
{
|
||||||
|
LLVMValueRef is_in_shared_heap = NULL;
|
||||||
|
|
||||||
|
/* Use start_offset > func_ctx->shared_heap_head_start_off to test
|
||||||
|
* start_off falls in shared heap chain memory region. The shared heap
|
||||||
|
* chain oob will be detected in app_addr_in_shared_heap block or
|
||||||
|
* aot_check_shared_heap_chain_and_update function
|
||||||
|
*/
|
||||||
|
BUILD_ICMP(LLVMIntUGT, start_offset, func_ctx->shared_heap_head_start_off,
|
||||||
|
is_in_shared_heap, "shared_heap_lb_cmp");
|
||||||
|
BUILD_COND_BR(is_in_shared_heap, app_addr_in_shared_heap_chain,
|
||||||
|
app_addr_in_linear_mem);
|
||||||
|
|
||||||
|
SET_BUILD_POS(app_addr_in_shared_heap_chain);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build the conditional branch for cache shared heap or shared heap chain.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* cmp: The condition for being in cache shared heap.
|
||||||
|
* app_addr_in_cache_shared_heap: Block for cache shared heap.
|
||||||
|
* app_addr_in_linear_mem: Block for linear memory.
|
||||||
|
* check_shared_heap_chain: Block for checking shared heap chain.
|
||||||
|
* bytes: The access size in bytes.
|
||||||
|
* start_offset: The offset to check.
|
||||||
|
* is_memory64: Whether memory is 64-bit.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
build_shared_heap_conditional_branching(
|
||||||
|
AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef cmp,
|
||||||
|
LLVMBasicBlockRef app_addr_in_cache_shared_heap,
|
||||||
|
LLVMBasicBlockRef app_addr_in_linear_mem,
|
||||||
|
LLVMBasicBlockRef check_shared_heap_chain, LLVMValueRef bytes,
|
||||||
|
LLVMValueRef start_offset, bool is_memory64)
|
||||||
|
{
|
||||||
|
if (comp_ctx->enable_shared_heap) {
|
||||||
|
BUILD_COND_BR(cmp, app_addr_in_cache_shared_heap,
|
||||||
|
app_addr_in_linear_mem);
|
||||||
|
}
|
||||||
|
else if (comp_ctx->enable_shared_chain) {
|
||||||
|
BUILD_COND_BR(cmp, app_addr_in_cache_shared_heap,
|
||||||
|
check_shared_heap_chain);
|
||||||
|
SET_BUILD_POS(check_shared_heap_chain);
|
||||||
|
if (!aot_check_shared_heap_chain_and_update(
|
||||||
|
comp_ctx, func_ctx, app_addr_in_cache_shared_heap, start_offset,
|
||||||
|
bytes, is_memory64))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the native address in the cache shared heap.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* start_offset: The offset to use for address calculation.
|
||||||
|
* maddr: Output, the native address that in the cache shared heap.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
build_get_maddr_in_cache_shared_heap(AOTCompContext *comp_ctx,
|
||||||
|
AOTFuncContext *func_ctx,
|
||||||
|
LLVMValueRef start_offset,
|
||||||
|
LLVMValueRef *maddr)
|
||||||
|
{
|
||||||
|
LLVMValueRef shared_heap_base_addr_adj;
|
||||||
|
/* load the local variable */
|
||||||
|
BUILD_LOAD_PTR(func_ctx->shared_heap_base_addr_adj, INT8_PTR_TYPE,
|
||||||
|
shared_heap_base_addr_adj);
|
||||||
|
if (!(*maddr = LLVMBuildInBoundsGEP2(
|
||||||
|
comp_ctx->builder, INT8_TYPE, shared_heap_base_addr_adj,
|
||||||
|
&start_offset, 1, "maddr_cache_shared_heap"))) {
|
||||||
|
aot_set_last_error("llvm build inbounds gep failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for memory overflow in shared heap for normal memory access.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* block_curr: The current basic block.
|
||||||
|
* block_maddr_phi: The phi block for memory address.
|
||||||
|
* maddr_phi: The phi node for memory address.
|
||||||
|
* start_offset: The first offset to check.
|
||||||
|
* mem_base_addr: The base address of memory. Only used with segue.
|
||||||
|
* bytes_u32: The access size in bytes.
|
||||||
|
* is_memory64: Whether memory is wasm64 memory.
|
||||||
|
* is_target_64bit: Whether target is 64-bit.
|
||||||
|
* enable_segue: Whether to use segment register addressing.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
aot_check_shared_heap_memory_overflow(
|
||||||
|
AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
|
LLVMBasicBlockRef block_curr, LLVMBasicBlockRef block_maddr_phi,
|
||||||
|
LLVMValueRef maddr_phi, LLVMValueRef start_offset,
|
||||||
|
LLVMValueRef mem_base_addr, uint32 bytes_u32, bool is_memory64,
|
||||||
|
bool is_target_64bit, bool enable_segue)
|
||||||
|
{
|
||||||
|
LLVMBasicBlockRef app_addr_in_cache_shared_heap, app_addr_in_linear_mem;
|
||||||
|
LLVMBasicBlockRef app_addr_in_shared_heap_chain = NULL,
|
||||||
|
check_shared_heap_chain = NULL;
|
||||||
|
LLVMValueRef cmp, cmp1, cmp2, shared_heap_start_off, shared_heap_end_off,
|
||||||
|
shared_heap_check_bound, maddr = NULL;
|
||||||
|
/* On 64/32-bit target, the offset is 64/32-bit */
|
||||||
|
LLVMTypeRef offset_type = is_target_64bit ? I64_TYPE : I32_TYPE;
|
||||||
|
LLVMValueRef length, bytes;
|
||||||
|
|
||||||
|
if (!setup_shared_heap_blocks(
|
||||||
|
comp_ctx, func_ctx, block_curr, &app_addr_in_cache_shared_heap,
|
||||||
|
&app_addr_in_linear_mem, &app_addr_in_shared_heap_chain,
|
||||||
|
&check_shared_heap_chain))
|
||||||
|
goto fail;
|
||||||
|
LLVMMoveBasicBlockAfter(block_maddr_phi, app_addr_in_linear_mem);
|
||||||
|
|
||||||
|
/* Early branching when it's not in shared heap chain at all */
|
||||||
|
if (comp_ctx->enable_shared_chain
|
||||||
|
&& !build_check_app_addr_in_shared_heap_chain(
|
||||||
|
comp_ctx, func_ctx, start_offset, app_addr_in_shared_heap_chain,
|
||||||
|
app_addr_in_linear_mem))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Load the local variable of the function */
|
||||||
|
BUILD_LOAD_PTR(func_ctx->shared_heap_start_off, offset_type,
|
||||||
|
shared_heap_start_off);
|
||||||
|
BUILD_LOAD_PTR(func_ctx->shared_heap_end_off, offset_type,
|
||||||
|
shared_heap_end_off);
|
||||||
|
/* Check if the app address is in the cache shared heap range.
|
||||||
|
* If yes, branch to the cache branch; if not, check the shared heap chain
|
||||||
|
*/
|
||||||
|
BUILD_ICMP(LLVMIntUGE, start_offset, shared_heap_start_off, cmp,
|
||||||
|
"cmp_cache_shared_heap_start");
|
||||||
|
length =
|
||||||
|
is_target_64bit ? I64_CONST(bytes_u32 - 1) : I32_CONST(bytes_u32 - 1);
|
||||||
|
CHECK_LLVM_CONST(length);
|
||||||
|
BUILD_OP(Sub, shared_heap_end_off, length, shared_heap_check_bound,
|
||||||
|
"cache_shared_heap_end_bound");
|
||||||
|
BUILD_ICMP(LLVMIntULE, start_offset, shared_heap_check_bound, cmp1,
|
||||||
|
"cmp_cache_shared_heap_end");
|
||||||
|
BUILD_OP(And, cmp, cmp1, cmp2, "is_in_cache_shared_heap");
|
||||||
|
/* Conditional branching based on whether in cached shared heap */
|
||||||
|
bytes = is_target_64bit ? I64_CONST(bytes_u32) : I32_CONST(bytes_u32);
|
||||||
|
if (!build_shared_heap_conditional_branching(
|
||||||
|
comp_ctx, func_ctx, cmp2, app_addr_in_cache_shared_heap,
|
||||||
|
app_addr_in_linear_mem, check_shared_heap_chain, bytes,
|
||||||
|
start_offset, is_memory64))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
SET_BUILD_POS(app_addr_in_cache_shared_heap);
|
||||||
|
if (!build_get_maddr_in_cache_shared_heap(comp_ctx, func_ctx, start_offset,
|
||||||
|
&maddr))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (enable_segue) {
|
||||||
|
LLVMValueRef mem_base_addr_u64, maddr_u64, offset_to_mem_base;
|
||||||
|
if (!(maddr_u64 = LLVMBuildPtrToInt(comp_ctx->builder, maddr, I64_TYPE,
|
||||||
|
"maddr_u64"))
|
||||||
|
|| !(mem_base_addr_u64 =
|
||||||
|
LLVMBuildPtrToInt(comp_ctx->builder, mem_base_addr,
|
||||||
|
I64_TYPE, "mem_base_addr_u64"))) {
|
||||||
|
aot_set_last_error("llvm build ptr to int failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!(offset_to_mem_base =
|
||||||
|
LLVMBuildSub(comp_ctx->builder, maddr_u64, mem_base_addr_u64,
|
||||||
|
"offset_to_mem_base"))) {
|
||||||
|
aot_set_last_error("llvm build sub failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!(maddr = LLVMBuildIntToPtr(comp_ctx->builder, offset_to_mem_base,
|
||||||
|
INT8_PTR_TYPE_GS,
|
||||||
|
"maddr_shared_heap_segue"))) {
|
||||||
|
aot_set_last_error("llvm build int to ptr failed.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMAddIncoming(maddr_phi, &maddr, &app_addr_in_cache_shared_heap, 1);
|
||||||
|
BUILD_BR(block_maddr_phi);
|
||||||
|
SET_BUILD_POS(app_addr_in_linear_mem);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for memory overflow in shared heap for bulk memory access.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* block_curr: The current basic block.
|
||||||
|
* block_maddr_phi: The phi block for memory address.
|
||||||
|
* check_succ: The block to branch to on success.
|
||||||
|
* maddr_phi: The phi node for memory address.
|
||||||
|
* start_offset: The offset to check.
|
||||||
|
* max_addr: The maximum address to check.
|
||||||
|
* bytes: The access size in bytes (LLVMValueRef).
|
||||||
|
* is_memory64: Whether memory is wasm64 memory.
|
||||||
|
* is_target_64bit: Whether target is 64-bit.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
aot_check_bulk_memory_shared_heap_memory_overflow(
|
||||||
|
AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
|
LLVMBasicBlockRef block_curr, LLVMBasicBlockRef block_maddr_phi,
|
||||||
|
LLVMBasicBlockRef check_succ, LLVMValueRef maddr_phi,
|
||||||
|
LLVMValueRef start_offset, LLVMValueRef max_addr, LLVMValueRef bytes,
|
||||||
|
bool is_memory64, bool is_target_64bit)
|
||||||
|
{
|
||||||
|
LLVMBasicBlockRef app_addr_in_cache_shared_heap, app_addr_in_linear_mem;
|
||||||
|
LLVMBasicBlockRef app_addr_in_shared_heap_chain = NULL,
|
||||||
|
check_shared_heap_chain = NULL;
|
||||||
|
LLVMValueRef cmp, cmp1, cmp2, shared_heap_start_off, shared_heap_end_off,
|
||||||
|
maddr = NULL, max_offset;
|
||||||
|
/* On 64/32-bit target, the offset is 64/32-bit */
|
||||||
|
LLVMTypeRef offset_type = is_target_64bit ? I64_TYPE : I32_TYPE;
|
||||||
|
|
||||||
|
if (!setup_shared_heap_blocks(
|
||||||
|
comp_ctx, func_ctx, block_curr, &app_addr_in_cache_shared_heap,
|
||||||
|
&app_addr_in_linear_mem, &app_addr_in_shared_heap_chain,
|
||||||
|
&check_shared_heap_chain))
|
||||||
|
goto fail;
|
||||||
|
LLVMMoveBasicBlockAfter(block_maddr_phi, check_succ);
|
||||||
|
|
||||||
|
/* Early branching when it's not in shared heap chain at all */
|
||||||
|
if (comp_ctx->enable_shared_chain
|
||||||
|
&& !build_check_app_addr_in_shared_heap_chain(
|
||||||
|
comp_ctx, func_ctx, start_offset, app_addr_in_shared_heap_chain,
|
||||||
|
app_addr_in_linear_mem))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Load the local variable of the function */
|
||||||
|
BUILD_LOAD_PTR(func_ctx->shared_heap_start_off, offset_type,
|
||||||
|
shared_heap_start_off);
|
||||||
|
BUILD_LOAD_PTR(func_ctx->shared_heap_end_off, offset_type,
|
||||||
|
shared_heap_end_off);
|
||||||
|
/* Check if the app address is in the cache shared heap range.
|
||||||
|
* If yes, branch to the cache branch; if not, check the shared heap chain
|
||||||
|
*/
|
||||||
|
BUILD_ICMP(LLVMIntUGE, start_offset, shared_heap_start_off, cmp,
|
||||||
|
"cmp_cache_shared_heap_start");
|
||||||
|
BUILD_OP(Add, max_addr, is_target_64bit ? I64_NEG_ONE : I32_NEG_ONE,
|
||||||
|
max_offset, "max_offset");
|
||||||
|
BUILD_ICMP(LLVMIntULE, max_offset, shared_heap_end_off, cmp1,
|
||||||
|
"cmp_cache_shared_heap_end");
|
||||||
|
BUILD_OP(And, cmp, cmp1, cmp2, "is_in_cache_shared_heap");
|
||||||
|
/* Conditional branching based on whether in cached shared heap */
|
||||||
|
if (!build_shared_heap_conditional_branching(
|
||||||
|
comp_ctx, func_ctx, cmp2, app_addr_in_cache_shared_heap,
|
||||||
|
app_addr_in_linear_mem, check_shared_heap_chain, bytes,
|
||||||
|
start_offset, is_memory64))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
SET_BUILD_POS(app_addr_in_cache_shared_heap);
|
||||||
|
if (!build_get_maddr_in_cache_shared_heap(comp_ctx, func_ctx, start_offset,
|
||||||
|
&maddr))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
LLVMAddIncoming(maddr_phi, &maddr, &app_addr_in_cache_shared_heap, 1);
|
||||||
|
BUILD_BR(block_maddr_phi);
|
||||||
|
SET_BUILD_POS(app_addr_in_linear_mem);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
LLVMValueRef
|
LLVMValueRef
|
||||||
aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
mem_offset_t offset, uint32 bytes, bool enable_segue,
|
mem_offset_t offset, uint32 bytes, bool enable_segue,
|
||||||
|
@ -118,10 +564,10 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
{
|
{
|
||||||
LLVMValueRef offset_const =
|
LLVMValueRef offset_const =
|
||||||
MEMORY64_COND_VALUE(I64_CONST(offset), I32_CONST(offset));
|
MEMORY64_COND_VALUE(I64_CONST(offset), I32_CONST(offset));
|
||||||
LLVMValueRef addr, maddr, maddr_phi = NULL, offset1, cmp1, cmp2, cmp;
|
LLVMValueRef addr, maddr, offset1, cmp1, cmp;
|
||||||
LLVMValueRef mem_base_addr, mem_check_bound;
|
LLVMValueRef mem_base_addr, mem_check_bound;
|
||||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||||
LLVMBasicBlockRef check_succ, block_maddr_phi = NULL;
|
LLVMBasicBlockRef check_succ;
|
||||||
AOTValue *aot_value_top;
|
AOTValue *aot_value_top;
|
||||||
uint32 local_idx_of_aot_value = 0;
|
uint32 local_idx_of_aot_value = 0;
|
||||||
uint64 const_value;
|
uint64 const_value;
|
||||||
|
@ -136,6 +582,10 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
#else
|
#else
|
||||||
bool is_memory64 = IS_MEMORY64;
|
bool is_memory64 = IS_MEMORY64;
|
||||||
#endif
|
#endif
|
||||||
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
|
LLVMValueRef maddr_phi = NULL;
|
||||||
|
LLVMBasicBlockRef block_maddr_phi = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false;
|
is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false;
|
||||||
|
|
||||||
|
@ -262,6 +712,13 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
*alignp = 1;
|
*alignp = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The overflow check needs to be done under following conditions:
|
||||||
|
* 1. In 64-bit target, offset and addr will be extended to 64-bit
|
||||||
|
* 1.1 offset + addr can overflow when it's memory64
|
||||||
|
* 1.2 no overflow when it's memory32
|
||||||
|
* 2. In 32-bit target, offset and addr will be 32-bit
|
||||||
|
* 2.1 offset + addr can overflow when it's memory32
|
||||||
|
*/
|
||||||
if (is_target_64bit) {
|
if (is_target_64bit) {
|
||||||
if (!(offset_const = LLVMBuildZExt(comp_ctx->builder, offset_const,
|
if (!(offset_const = LLVMBuildZExt(comp_ctx->builder, offset_const,
|
||||||
I64_TYPE, "offset_i64"))
|
I64_TYPE, "offset_i64"))
|
||||||
|
@ -275,7 +732,9 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
/* offset1 = offset + addr; */
|
/* offset1 = offset + addr; */
|
||||||
BUILD_OP(Add, offset_const, addr, offset1, "offset1");
|
BUILD_OP(Add, offset_const, addr, offset1, "offset1");
|
||||||
|
|
||||||
if (is_memory64 && comp_ctx->enable_bound_check) {
|
/* 1.1 offset + addr can overflow when it's memory64
|
||||||
|
* 2.1 Or when it's on 32-bit platform */
|
||||||
|
if (is_memory64 || !is_target_64bit) {
|
||||||
/* Check whether integer overflow occurs in offset + addr */
|
/* Check whether integer overflow occurs in offset + addr */
|
||||||
LLVMBasicBlockRef check_integer_overflow_end;
|
LLVMBasicBlockRef check_integer_overflow_end;
|
||||||
ADD_BASIC_BLOCK(check_integer_overflow_end,
|
ADD_BASIC_BLOCK(check_integer_overflow_end,
|
||||||
|
@ -289,23 +748,14 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
SET_BUILD_POS(check_integer_overflow_end);
|
SET_BUILD_POS(check_integer_overflow_end);
|
||||||
|
block_curr = check_integer_overflow_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
LLVMBasicBlockRef app_addr_in_shared_heap, app_addr_in_linear_mem;
|
if (comp_ctx->enable_shared_heap
|
||||||
LLVMValueRef is_in_shared_heap, shared_heap_check_bound = NULL;
|
|| comp_ctx->enable_shared_chain /* TODO: && mem_idx == 0 */) {
|
||||||
|
|
||||||
/* Add basic blocks */
|
|
||||||
ADD_BASIC_BLOCK(app_addr_in_shared_heap, "app_addr_in_shared_heap");
|
|
||||||
ADD_BASIC_BLOCK(app_addr_in_linear_mem, "app_addr_in_linear_mem");
|
|
||||||
ADD_BASIC_BLOCK(block_maddr_phi, "maddr_phi");
|
ADD_BASIC_BLOCK(block_maddr_phi, "maddr_phi");
|
||||||
|
SET_BUILD_POS(block_maddr_phi);
|
||||||
LLVMMoveBasicBlockAfter(app_addr_in_shared_heap, block_curr);
|
|
||||||
LLVMMoveBasicBlockAfter(app_addr_in_linear_mem,
|
|
||||||
app_addr_in_shared_heap);
|
|
||||||
LLVMMoveBasicBlockAfter(block_maddr_phi, app_addr_in_linear_mem);
|
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_maddr_phi);
|
|
||||||
if (!(maddr_phi =
|
if (!(maddr_phi =
|
||||||
LLVMBuildPhi(comp_ctx->builder,
|
LLVMBuildPhi(comp_ctx->builder,
|
||||||
enable_segue ? INT8_PTR_TYPE_GS : INT8_PTR_TYPE,
|
enable_segue ? INT8_PTR_TYPE_GS : INT8_PTR_TYPE,
|
||||||
|
@ -313,110 +763,16 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
aot_set_last_error("llvm build phi failed");
|
aot_set_last_error("llvm build phi failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
SET_BUILD_POS(block_curr);
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
|
if (!aot_check_shared_heap_memory_overflow(
|
||||||
|
comp_ctx, func_ctx, block_curr, block_maddr_phi, maddr_phi,
|
||||||
if (!is_target_64bit) {
|
offset1, mem_base_addr, bytes, is_memory64, is_target_64bit,
|
||||||
/* Check whether integer overflow occurs in addr + offset */
|
enable_segue)) {
|
||||||
LLVMBasicBlockRef check_integer_overflow_end;
|
|
||||||
ADD_BASIC_BLOCK(check_integer_overflow_end,
|
|
||||||
"check_integer_overflow_end");
|
|
||||||
LLVMMoveBasicBlockAfter(check_integer_overflow_end, block_curr);
|
|
||||||
|
|
||||||
BUILD_ICMP(LLVMIntULT, offset1, addr, cmp1, "cmp1");
|
|
||||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
|
||||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true,
|
|
||||||
cmp1, check_integer_overflow_end)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
SET_BUILD_POS(check_integer_overflow_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_heap_check_bound =
|
|
||||||
is_memory64 ? I64_CONST(UINT64_MAX - bytes + 1)
|
|
||||||
: (comp_ctx->pointer_size == sizeof(uint64)
|
|
||||||
? I64_CONST(UINT32_MAX - bytes + 1)
|
|
||||||
: I32_CONST(UINT32_MAX - bytes + 1));
|
|
||||||
CHECK_LLVM_CONST(shared_heap_check_bound);
|
|
||||||
|
|
||||||
/* Check whether the bytes to access are in shared heap */
|
|
||||||
if (!comp_ctx->enable_bound_check) {
|
|
||||||
/* Use IntUGT but not IntUGE to compare, since (1) in the ems
|
|
||||||
memory allocator, the hmu node includes hmu header and hmu
|
|
||||||
memory, only the latter is returned to the caller as the
|
|
||||||
allocated memory, the hmu header isn't returned so the
|
|
||||||
first byte of the shared heap won't be accessed, (2) using
|
|
||||||
IntUGT gets better performance than IntUGE in some cases */
|
|
||||||
BUILD_ICMP(LLVMIntUGT, offset1, func_ctx->shared_heap_start_off,
|
|
||||||
is_in_shared_heap, "is_in_shared_heap");
|
|
||||||
/* We don't check the shared heap's upper boundary if boundary
|
|
||||||
check isn't enabled, the runtime may also use the guard pages
|
|
||||||
of shared heap to check the boundary if hardware boundary
|
|
||||||
check feature is enabled. */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Use IntUGT but not IntUGE to compare, same as above */
|
|
||||||
BUILD_ICMP(LLVMIntUGT, offset1, func_ctx->shared_heap_start_off,
|
|
||||||
cmp1, "cmp1");
|
|
||||||
/* Check the shared heap's upper boundary if boundary check is
|
|
||||||
enabled */
|
|
||||||
BUILD_ICMP(LLVMIntULE, offset1, shared_heap_check_bound, cmp2,
|
|
||||||
"cmp2");
|
|
||||||
BUILD_OP(And, cmp1, cmp2, is_in_shared_heap, "is_in_shared_heap");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!LLVMBuildCondBr(comp_ctx->builder, is_in_shared_heap,
|
|
||||||
app_addr_in_shared_heap, app_addr_in_linear_mem)) {
|
|
||||||
aot_set_last_error("llvm build cond br failed");
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, app_addr_in_shared_heap);
|
|
||||||
|
|
||||||
/* Get native address inside shared heap */
|
|
||||||
if (!(maddr =
|
|
||||||
LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
|
||||||
func_ctx->shared_heap_base_addr_adj,
|
|
||||||
&offset1, 1, "maddr_shared_heap"))) {
|
|
||||||
aot_set_last_error("llvm build inbounds gep failed");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable_segue) {
|
|
||||||
LLVMValueRef mem_base_addr_u64, maddr_u64, offset_to_mem_base;
|
|
||||||
|
|
||||||
if (!(maddr_u64 = LLVMBuildPtrToInt(comp_ctx->builder, maddr,
|
|
||||||
I64_TYPE, "maddr_u64"))
|
|
||||||
|| !(mem_base_addr_u64 =
|
|
||||||
LLVMBuildPtrToInt(comp_ctx->builder, mem_base_addr,
|
|
||||||
I64_TYPE, "mem_base_addr_u64"))) {
|
|
||||||
aot_set_last_error("llvm build ptr to int failed");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (!(offset_to_mem_base =
|
|
||||||
LLVMBuildSub(comp_ctx->builder, maddr_u64,
|
|
||||||
mem_base_addr_u64, "offset_to_mem_base"))) {
|
|
||||||
aot_set_last_error("llvm build sub failed");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (!(maddr = LLVMBuildIntToPtr(
|
|
||||||
comp_ctx->builder, offset_to_mem_base, INT8_PTR_TYPE_GS,
|
|
||||||
"maddr_shared_heap_segue"))) {
|
|
||||||
aot_set_last_error("llvm build int to ptr failed.");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMAddIncoming(maddr_phi, &maddr, &app_addr_in_shared_heap, 1);
|
|
||||||
|
|
||||||
if (!LLVMBuildBr(comp_ctx->builder, block_maddr_phi)) {
|
|
||||||
aot_set_last_error("llvm build br failed");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, app_addr_in_linear_mem);
|
|
||||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (comp_ctx->enable_bound_check
|
if (comp_ctx->enable_bound_check
|
||||||
&& !(is_local_of_aot_value
|
&& !(is_local_of_aot_value
|
||||||
|
@ -449,21 +805,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_target_64bit) {
|
BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp, "cmp");
|
||||||
BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp, "cmp");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
|
|
||||||
/* Check integer overflow has been checked above */
|
|
||||||
BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp, "cmp");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Check integer overflow */
|
|
||||||
BUILD_ICMP(LLVMIntULT, offset1, addr, cmp1, "cmp1");
|
|
||||||
BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp2, "cmp2");
|
|
||||||
BUILD_OP(Or, cmp1, cmp2, cmp, "cmp");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add basic blocks */
|
/* Add basic blocks */
|
||||||
ADD_BASIC_BLOCK(check_succ, "check_succ");
|
ADD_BASIC_BLOCK(check_succ, "check_succ");
|
||||||
|
@ -509,17 +851,20 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
|
if (comp_ctx->enable_shared_heap
|
||||||
|
|| comp_ctx->enable_shared_chain /* TODO: && mem_idx == 0 */) {
|
||||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||||
LLVMAddIncoming(maddr_phi, &maddr, &block_curr, 1);
|
LLVMAddIncoming(maddr_phi, &maddr, &block_curr, 1);
|
||||||
if (!LLVMBuildBr(comp_ctx->builder, block_maddr_phi)) {
|
if (!LLVMBuildBr(comp_ctx->builder, block_maddr_phi)) {
|
||||||
aot_set_last_error("llvm build br failed");
|
aot_set_last_error("llvm build br failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_maddr_phi);
|
SET_BUILD_POS(block_maddr_phi);
|
||||||
return maddr_phi;
|
return maddr_phi;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
return maddr;
|
return maddr;
|
||||||
fail:
|
fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -544,15 +889,6 @@ fail:
|
||||||
LLVMSetAlignment(value, known_align); \
|
LLVMSetAlignment(value, known_align); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define BUILD_TRUNC(value, data_type) \
|
|
||||||
do { \
|
|
||||||
if (!(value = LLVMBuildTrunc(comp_ctx->builder, value, data_type, \
|
|
||||||
"val_trunc"))) { \
|
|
||||||
aot_set_last_error("llvm build trunc failed."); \
|
|
||||||
goto fail; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define BUILD_STORE() \
|
#define BUILD_STORE() \
|
||||||
do { \
|
do { \
|
||||||
LLVMValueRef res; \
|
LLVMValueRef res; \
|
||||||
|
@ -1150,16 +1486,23 @@ LLVMValueRef
|
||||||
check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
LLVMValueRef offset, LLVMValueRef bytes)
|
LLVMValueRef offset, LLVMValueRef bytes)
|
||||||
{
|
{
|
||||||
LLVMValueRef maddr, max_addr, cmp;
|
LLVMValueRef maddr, max_addr, cmp, cmp1;
|
||||||
LLVMValueRef mem_base_addr, maddr_phi = NULL;
|
LLVMValueRef mem_base_addr;
|
||||||
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||||
LLVMBasicBlockRef check_succ, block_maddr_phi = NULL;
|
LLVMBasicBlockRef check_succ;
|
||||||
LLVMValueRef mem_size;
|
LLVMValueRef mem_size;
|
||||||
|
bool is_target_64bit;
|
||||||
#if WASM_ENABLE_MEMORY64 == 0
|
#if WASM_ENABLE_MEMORY64 == 0
|
||||||
bool is_memory64 = false;
|
bool is_memory64 = false;
|
||||||
#else
|
#else
|
||||||
bool is_memory64 = IS_MEMORY64;
|
bool is_memory64 = IS_MEMORY64;
|
||||||
#endif
|
#endif
|
||||||
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
|
LLVMValueRef maddr_phi = NULL;
|
||||||
|
LLVMBasicBlockRef block_maddr_phi = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false;
|
||||||
|
|
||||||
/* Get memory base address and memory data size */
|
/* Get memory base address and memory data size */
|
||||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||||
|
@ -1221,111 +1564,71 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
ADD_BASIC_BLOCK(check_succ, "check_succ");
|
ADD_BASIC_BLOCK(check_succ, "check_succ");
|
||||||
LLVMMoveBasicBlockAfter(check_succ, block_curr);
|
LLVMMoveBasicBlockAfter(check_succ, block_curr);
|
||||||
|
|
||||||
offset =
|
/* Same logic with aot_check_memory_overflow, offset and bytes are 32/64
|
||||||
LLVMBuildZExt(comp_ctx->builder, offset, I64_TYPE, "extend_offset");
|
* bits on 32/64 bits platform */
|
||||||
bytes = LLVMBuildZExt(comp_ctx->builder, bytes, I64_TYPE, "extend_len");
|
if (is_target_64bit) {
|
||||||
if (!offset || !bytes) {
|
offset =
|
||||||
aot_set_last_error("llvm build zext failed.");
|
LLVMBuildZExt(comp_ctx->builder, offset, I64_TYPE, "extend_offset");
|
||||||
goto fail;
|
bytes = LLVMBuildZExt(comp_ctx->builder, bytes, I64_TYPE, "extend_len");
|
||||||
|
if (!offset || !bytes) {
|
||||||
|
aot_set_last_error("llvm build zext failed.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILD_OP(Add, offset, bytes, max_addr, "max_addr");
|
BUILD_OP(Add, offset, bytes, max_addr, "max_addr");
|
||||||
|
|
||||||
if (is_memory64 && comp_ctx->enable_bound_check) {
|
/* Check overflow when it's memory64 or it's on 32 bits platform */
|
||||||
/* Check whether integer overflow occurs in offset + addr */
|
if (is_memory64 || !is_target_64bit) {
|
||||||
|
/* Check whether integer overflow occurs in offset + bytes */
|
||||||
LLVMBasicBlockRef check_integer_overflow_end;
|
LLVMBasicBlockRef check_integer_overflow_end;
|
||||||
ADD_BASIC_BLOCK(check_integer_overflow_end,
|
ADD_BASIC_BLOCK(check_integer_overflow_end,
|
||||||
"check_integer_overflow_end");
|
"check_integer_overflow_end");
|
||||||
LLVMMoveBasicBlockAfter(check_integer_overflow_end, block_curr);
|
LLVMMoveBasicBlockAfter(check_integer_overflow_end, block_curr);
|
||||||
|
|
||||||
|
/* offset + bytes can overflow yet is valid(for example, 0xffffffff, 1),
|
||||||
|
* allow it to be 0(either 0, 0 or overflow and valid) */
|
||||||
BUILD_ICMP(LLVMIntULT, max_addr, offset, cmp, "cmp");
|
BUILD_ICMP(LLVMIntULT, max_addr, offset, cmp, "cmp");
|
||||||
|
BUILD_ICMP(LLVMIntNE, max_addr, is_target_64bit ? I64_ZERO : I32_ZERO,
|
||||||
|
cmp1, "cmp1");
|
||||||
|
BUILD_OP(And, cmp, cmp1, cmp, "overflow");
|
||||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp,
|
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp,
|
||||||
check_integer_overflow_end)) {
|
check_integer_overflow_end)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
SET_BUILD_POS(check_integer_overflow_end);
|
SET_BUILD_POS(check_integer_overflow_end);
|
||||||
|
block_curr = check_integer_overflow_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
LLVMBasicBlockRef app_addr_in_shared_heap, app_addr_in_linear_mem;
|
if (comp_ctx->enable_shared_heap
|
||||||
LLVMValueRef shared_heap_start_off, shared_heap_check_bound;
|
|| comp_ctx->enable_shared_chain /* TODO: && mem_idx == 0 */) {
|
||||||
LLVMValueRef max_offset, cmp1, cmp2, is_in_shared_heap;
|
|
||||||
|
|
||||||
/* Add basic blocks */
|
|
||||||
ADD_BASIC_BLOCK(app_addr_in_shared_heap, "app_addr_in_shared_heap");
|
|
||||||
ADD_BASIC_BLOCK(app_addr_in_linear_mem, "app_addr_in_linear_mem");
|
|
||||||
ADD_BASIC_BLOCK(block_maddr_phi, "maddr_phi");
|
ADD_BASIC_BLOCK(block_maddr_phi, "maddr_phi");
|
||||||
|
SET_BUILD_POS(block_maddr_phi);
|
||||||
LLVMMoveBasicBlockAfter(app_addr_in_shared_heap, block_curr);
|
|
||||||
LLVMMoveBasicBlockAfter(app_addr_in_linear_mem,
|
|
||||||
app_addr_in_shared_heap);
|
|
||||||
LLVMMoveBasicBlockAfter(block_maddr_phi, check_succ);
|
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_maddr_phi);
|
|
||||||
if (!(maddr_phi = LLVMBuildPhi(comp_ctx->builder, INT8_PTR_TYPE,
|
if (!(maddr_phi = LLVMBuildPhi(comp_ctx->builder, INT8_PTR_TYPE,
|
||||||
"maddr_phi"))) {
|
"maddr_phi"))) {
|
||||||
aot_set_last_error("llvm build phi failed");
|
aot_set_last_error("llvm build phi failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
SET_BUILD_POS(block_curr);
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
|
if (!aot_check_bulk_memory_shared_heap_memory_overflow(
|
||||||
|
comp_ctx, func_ctx, block_curr, block_maddr_phi, check_succ,
|
||||||
shared_heap_start_off = func_ctx->shared_heap_start_off;
|
maddr_phi, offset, max_addr, bytes, is_memory64,
|
||||||
if (comp_ctx->pointer_size == sizeof(uint32)) {
|
is_target_64bit)) {
|
||||||
if (!(shared_heap_start_off =
|
|
||||||
LLVMBuildZExt(comp_ctx->builder, shared_heap_start_off,
|
|
||||||
I64_TYPE, "shared_heap_start_off_u64"))) {
|
|
||||||
aot_set_last_error("llvm build zext failed");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shared_heap_check_bound =
|
|
||||||
is_memory64 ? I64_CONST(UINT64_MAX) : I64_CONST(UINT32_MAX);
|
|
||||||
CHECK_LLVM_CONST(shared_heap_check_bound);
|
|
||||||
|
|
||||||
/* Check whether the bytes to access are in shared heap */
|
|
||||||
if (!comp_ctx->enable_bound_check) {
|
|
||||||
/* Use IntUGT but not IntUGE to compare, same as the check
|
|
||||||
in aot_check_memory_overflow */
|
|
||||||
BUILD_ICMP(LLVMIntUGT, offset, func_ctx->shared_heap_start_off,
|
|
||||||
is_in_shared_heap, "is_in_shared_heap");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
BUILD_ICMP(LLVMIntUGT, offset, func_ctx->shared_heap_start_off,
|
|
||||||
cmp1, "cmp1");
|
|
||||||
BUILD_OP(Add, max_addr, I64_NEG_ONE, max_offset, "max_offset");
|
|
||||||
BUILD_ICMP(LLVMIntULE, max_offset, shared_heap_check_bound, cmp2,
|
|
||||||
"cmp2");
|
|
||||||
BUILD_OP(And, cmp1, cmp2, is_in_shared_heap, "is_in_shared_heap");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!LLVMBuildCondBr(comp_ctx->builder, is_in_shared_heap,
|
|
||||||
app_addr_in_shared_heap, app_addr_in_linear_mem)) {
|
|
||||||
aot_set_last_error("llvm build cond br failed");
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, app_addr_in_shared_heap);
|
|
||||||
|
|
||||||
/* Get native address inside shared heap */
|
|
||||||
if (!(maddr = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
|
||||||
func_ctx->shared_heap_base_addr_adj,
|
|
||||||
&offset, 1, "maddr_shared_heap"))) {
|
|
||||||
aot_set_last_error("llvm build inbounds gep failed");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
LLVMAddIncoming(maddr_phi, &maddr, &app_addr_in_shared_heap, 1);
|
|
||||||
|
|
||||||
if (!LLVMBuildBr(comp_ctx->builder, block_maddr_phi)) {
|
|
||||||
aot_set_last_error("llvm build br failed");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, app_addr_in_linear_mem);
|
|
||||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* mem_size is always 64-bit, extend max_addr on 32 bits platform */
|
||||||
|
if (!is_target_64bit
|
||||||
|
&& !(max_addr = LLVMBuildZExt(comp_ctx->builder, max_addr, I64_TYPE,
|
||||||
|
"extend_max_addr"))) {
|
||||||
|
aot_set_last_error("llvm build zext failed.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
BUILD_ICMP(LLVMIntUGT, max_addr, mem_size, cmp, "cmp_max_mem_addr");
|
BUILD_ICMP(LLVMIntUGT, max_addr, mem_size, cmp, "cmp_max_mem_addr");
|
||||||
|
|
||||||
if (!aot_emit_exception(comp_ctx, func_ctx,
|
if (!aot_emit_exception(comp_ctx, func_ctx,
|
||||||
|
@ -1341,7 +1644,9 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
|
if (comp_ctx->enable_shared_heap
|
||||||
|
|| comp_ctx->enable_shared_chain /* TODO: && mem_idx == 0 */) {
|
||||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||||
LLVMAddIncoming(maddr_phi, &maddr, &block_curr, 1);
|
LLVMAddIncoming(maddr_phi, &maddr, &block_curr, 1);
|
||||||
if (!LLVMBuildBr(comp_ctx->builder, block_maddr_phi)) {
|
if (!LLVMBuildBr(comp_ctx->builder, block_maddr_phi)) {
|
||||||
|
@ -1352,6 +1657,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
return maddr_phi;
|
return maddr_phi;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
return maddr;
|
return maddr;
|
||||||
fail:
|
fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -1517,73 +1517,154 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BUILD_IS_NOT_NULL(value, res, name) \
|
||||||
|
do { \
|
||||||
|
if (!(res = LLVMBuildIsNotNull(comp_ctx->builder, value, name))) { \
|
||||||
|
aot_set_last_error("llvm build is not null failed."); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define get_module_extra_field_offset(field) \
|
||||||
|
do { \
|
||||||
|
offset_u32 = get_module_inst_extra_offset(comp_ctx); \
|
||||||
|
if (comp_ctx->is_jit_mode) \
|
||||||
|
offset_u32 += offsetof(WASMModuleInstanceExtra, field); \
|
||||||
|
else \
|
||||||
|
offset_u32 += offsetof(AOTModuleInstanceExtra, field); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LOAD_MODULE_EXTRA_FIELD_AND_ALLOCA(field, type) \
|
||||||
|
do { \
|
||||||
|
get_module_extra_field_offset(field); \
|
||||||
|
offset = I32_CONST(offset_u32); \
|
||||||
|
CHECK_LLVM_CONST(offset); \
|
||||||
|
if (!(field_p = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, \
|
||||||
|
func_ctx->aot_inst, &offset, 1, \
|
||||||
|
#field "_p"))) { \
|
||||||
|
aot_set_last_error("llvm build inbounds gep failed"); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
if (!(load_val = \
|
||||||
|
LLVMBuildLoad2(comp_ctx->builder, type, field_p, #field))) { \
|
||||||
|
aot_set_last_error("llvm build load failed"); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
if (!(func_ctx->field = \
|
||||||
|
LLVMBuildAlloca(comp_ctx->builder, type, #field))) { \
|
||||||
|
aot_set_last_error("llvm build alloca failed"); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
if (!LLVMBuildStore(comp_ctx->builder, load_val, func_ctx->field)) { \
|
||||||
|
aot_set_last_error("llvm build store failed"); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
create_shared_heap_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
create_shared_heap_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||||
{
|
{
|
||||||
LLVMValueRef offset, base_addr_p, start_off_p, cmp;
|
#if WASM_ENABLE_SHARED_HEAP != 0
|
||||||
|
LLVMValueRef offset, field_p, load_val, shared_heap_head_p,
|
||||||
|
shared_heap_head, cmp, field_p_or_default, shared_heap_head_start_off,
|
||||||
|
shared_heap_head_start_off_minus_one;
|
||||||
|
LLVMTypeRef shared_heap_offset_type;
|
||||||
uint32 offset_u32;
|
uint32 offset_u32;
|
||||||
|
#if WASM_ENABLE_MEMORY64 == 0
|
||||||
/* Load aot_inst->e->shared_heap_base_addr_adj */
|
bool is_memory64 = false;
|
||||||
offset_u32 = get_module_inst_extra_offset(comp_ctx);
|
#else
|
||||||
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_SHARED_HEAP != 0
|
bool is_memory64 = IS_MEMORY64;
|
||||||
if (comp_ctx->is_jit_mode)
|
|
||||||
offset_u32 +=
|
|
||||||
offsetof(WASMModuleInstanceExtra, shared_heap_base_addr_adj);
|
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
offset_u32 +=
|
|
||||||
offsetof(AOTModuleInstanceExtra, shared_heap_base_addr_adj);
|
shared_heap_offset_type =
|
||||||
|
comp_ctx->pointer_size == sizeof(uint64) ? I64_TYPE : I32_TYPE;
|
||||||
|
|
||||||
|
/* shared_heap_base_addr_adj, shared_heap_start_off, and
|
||||||
|
* shared_heap_end_off can be updated later, use local variable to
|
||||||
|
* represent them */
|
||||||
|
LOAD_MODULE_EXTRA_FIELD_AND_ALLOCA(shared_heap_base_addr_adj,
|
||||||
|
INT8_PTR_TYPE);
|
||||||
|
LOAD_MODULE_EXTRA_FIELD_AND_ALLOCA(shared_heap_start_off,
|
||||||
|
shared_heap_offset_type);
|
||||||
|
LOAD_MODULE_EXTRA_FIELD_AND_ALLOCA(shared_heap_end_off,
|
||||||
|
shared_heap_offset_type);
|
||||||
|
|
||||||
|
/* Shared Heap head start off won't be updated, no need to alloca */
|
||||||
|
get_module_extra_field_offset(shared_heap);
|
||||||
offset = I32_CONST(offset_u32);
|
offset = I32_CONST(offset_u32);
|
||||||
CHECK_LLVM_CONST(offset);
|
CHECK_LLVM_CONST(offset);
|
||||||
|
if (!(shared_heap_head_p = LLVMBuildInBoundsGEP2(
|
||||||
if (!(base_addr_p = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
|
||||||
func_ctx->aot_inst, &offset, 1,
|
"shared_heap_head_p"))) {
|
||||||
"shared_heap_base_addr_adj_p"))) {
|
|
||||||
aot_set_last_error("llvm build inbounds gep failed");
|
aot_set_last_error("llvm build inbounds gep failed");
|
||||||
return false;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (!(func_ctx->shared_heap_base_addr_adj =
|
if (!(shared_heap_head =
|
||||||
LLVMBuildLoad2(comp_ctx->builder, INT8_PTR_TYPE, base_addr_p,
|
LLVMBuildLoad2(comp_ctx->builder, INT8_PTR_TYPE,
|
||||||
"shared_heap_base_addr_adj"))) {
|
shared_heap_head_p, "shared_heap_head"))) {
|
||||||
aot_set_last_error("llvm build load failed");
|
aot_set_last_error("llvm build load failed");
|
||||||
return false;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
BUILD_IS_NOT_NULL(shared_heap_head, cmp, "has_shared_heap");
|
||||||
|
|
||||||
/* Load aot_inst->e->shared_heap_start_off */
|
if (is_memory64) {
|
||||||
offset_u32 = get_module_inst_extra_offset(comp_ctx);
|
offset_u32 = offsetof(WASMSharedHeap, start_off_mem64);
|
||||||
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_SHARED_HEAP != 0
|
}
|
||||||
if (comp_ctx->is_jit_mode)
|
else {
|
||||||
offset_u32 += offsetof(WASMModuleInstanceExtra, shared_heap_start_off);
|
offset_u32 = offsetof(WASMSharedHeap, start_off_mem32);
|
||||||
else
|
}
|
||||||
#endif
|
|
||||||
offset_u32 += offsetof(AOTModuleInstanceExtra, shared_heap_start_off);
|
|
||||||
offset = I32_CONST(offset_u32);
|
offset = I32_CONST(offset_u32);
|
||||||
CHECK_LLVM_CONST(offset);
|
CHECK_LLVM_CONST(offset);
|
||||||
|
if (!(field_p = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
||||||
if (!(start_off_p = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
shared_heap_head, &offset, 1,
|
||||||
func_ctx->aot_inst, &offset, 1,
|
"head_start_off_p"))) {
|
||||||
"shared_heap_start_off_p"))) {
|
|
||||||
aot_set_last_error("llvm build inbounds gep failed");
|
aot_set_last_error("llvm build inbounds gep failed");
|
||||||
return false;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (!(func_ctx->shared_heap_start_off = LLVMBuildLoad2(
|
|
||||||
comp_ctx->builder,
|
/* Select a valid shared heap head ptr or safe alloca ptr stores
|
||||||
comp_ctx->pointer_size == sizeof(uint64) ? I64_TYPE : I32_TYPE,
|
* shared_heap_start_off(UINT32_MAX/UINT64_MAX) */
|
||||||
start_off_p, "shared_heap_start_off"))) {
|
if (!(field_p_or_default = LLVMBuildSelect(comp_ctx->builder, cmp, field_p,
|
||||||
|
func_ctx->shared_heap_start_off,
|
||||||
|
"ptr_or_default"))) {
|
||||||
|
aot_set_last_error("llvm build select failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(shared_heap_head_start_off = LLVMBuildLoad2(
|
||||||
|
comp_ctx->builder, shared_heap_offset_type, field_p_or_default,
|
||||||
|
"shared_heap_head_start_off"))) {
|
||||||
aot_set_last_error("llvm build load failed");
|
aot_set_last_error("llvm build load failed");
|
||||||
return false;
|
goto fail;
|
||||||
|
}
|
||||||
|
if (!(shared_heap_head_start_off_minus_one = LLVMBuildAdd(
|
||||||
|
comp_ctx->builder, shared_heap_head_start_off,
|
||||||
|
comp_ctx->pointer_size == sizeof(uint64) ? I64_NEG_ONE
|
||||||
|
: I32_NEG_ONE,
|
||||||
|
"head_start_off_minus_one"))) {
|
||||||
|
aot_set_last_error("llvm build load failed");
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(cmp = LLVMBuildIsNotNull(comp_ctx->builder,
|
/* if there is attached shared heap(s), the value will be valid start_off-1,
|
||||||
func_ctx->shared_heap_base_addr_adj,
|
* otherwise it will be UINT32_MAX/UINT64_MAX, so during the bounds checks,
|
||||||
"has_shared_heap"))) {
|
* when has attached shared heap:
|
||||||
aot_set_last_error("llvm build is not null failed");
|
* offset > start_off - 1 => offset >= start_off
|
||||||
return false;
|
* when no attached shared heap:
|
||||||
|
* offset > UINT32_MAX/UINT64_MAX is always false
|
||||||
|
* */
|
||||||
|
if (!(func_ctx->shared_heap_head_start_off = LLVMBuildSelect(
|
||||||
|
comp_ctx->builder, cmp, shared_heap_head_start_off_minus_one,
|
||||||
|
shared_heap_head_start_off, "head_start_off"))) {
|
||||||
|
aot_set_last_error("llvm build select failed");
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
|
#else /* else of WASM_ENABLE_SHARED_HEAP != 0 */
|
||||||
|
return true;
|
||||||
|
#endif /* end of WASM_ENABLE_SHARED_HEAP != 0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -1877,7 +1958,7 @@ aot_create_func_context(const AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load shared heap, shared heap start off mem32 or mem64 */
|
/* Load shared heap, shared heap start off mem32 or mem64 */
|
||||||
if (comp_ctx->enable_shared_heap
|
if ((comp_ctx->enable_shared_heap || comp_ctx->enable_shared_chain)
|
||||||
&& !create_shared_heap_info(comp_ctx, func_ctx)) {
|
&& !create_shared_heap_info(comp_ctx, func_ctx)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -2703,6 +2784,9 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
|
||||||
if (option->enable_shared_heap)
|
if (option->enable_shared_heap)
|
||||||
comp_ctx->enable_shared_heap = true;
|
comp_ctx->enable_shared_heap = true;
|
||||||
|
|
||||||
|
if (option->enable_shared_chain)
|
||||||
|
comp_ctx->enable_shared_chain = true;
|
||||||
|
|
||||||
comp_ctx->opt_level = option->opt_level;
|
comp_ctx->opt_level = option->opt_level;
|
||||||
comp_ctx->size_level = option->size_level;
|
comp_ctx->size_level = option->size_level;
|
||||||
|
|
||||||
|
|
|
@ -254,8 +254,12 @@ typedef struct AOTFuncContext {
|
||||||
bool mem_space_unchanged;
|
bool mem_space_unchanged;
|
||||||
AOTCheckedAddrList checked_addr_list;
|
AOTCheckedAddrList checked_addr_list;
|
||||||
|
|
||||||
|
/* The last accessed shared heap info */
|
||||||
LLVMValueRef shared_heap_base_addr_adj;
|
LLVMValueRef shared_heap_base_addr_adj;
|
||||||
LLVMValueRef shared_heap_start_off;
|
LLVMValueRef shared_heap_start_off;
|
||||||
|
LLVMValueRef shared_heap_end_off;
|
||||||
|
/* The start offset of the head of shared heap chain */
|
||||||
|
LLVMValueRef shared_heap_head_start_off;
|
||||||
|
|
||||||
LLVMBasicBlockRef got_exception_block;
|
LLVMBasicBlockRef got_exception_block;
|
||||||
LLVMBasicBlockRef func_return_block;
|
LLVMBasicBlockRef func_return_block;
|
||||||
|
@ -486,6 +490,7 @@ typedef struct AOTCompContext {
|
||||||
bool enable_gc;
|
bool enable_gc;
|
||||||
|
|
||||||
bool enable_shared_heap;
|
bool enable_shared_heap;
|
||||||
|
bool enable_shared_chain;
|
||||||
|
|
||||||
uint32 opt_level;
|
uint32 opt_level;
|
||||||
uint32 size_level;
|
uint32 size_level;
|
||||||
|
|
|
@ -79,6 +79,7 @@ typedef struct AOTCompOption {
|
||||||
bool enable_stack_estimation;
|
bool enable_stack_estimation;
|
||||||
bool quick_invoke_c_api_import;
|
bool quick_invoke_c_api_import;
|
||||||
bool enable_shared_heap;
|
bool enable_shared_heap;
|
||||||
|
bool enable_shared_chain;
|
||||||
char *use_prof_file;
|
char *use_prof_file;
|
||||||
uint32_t opt_level;
|
uint32_t opt_level;
|
||||||
uint32_t size_level;
|
uint32_t size_level;
|
||||||
|
|
|
@ -2818,6 +2818,7 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
|
||||||
#else
|
#else
|
||||||
module_inst->e->shared_heap_start_off.u32[0] = UINT32_MAX;
|
module_inst->e->shared_heap_start_off.u32[0] = UINT32_MAX;
|
||||||
#endif
|
#endif
|
||||||
|
module_inst->e->shared_heap = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_GC != 0
|
#if WASM_ENABLE_GC != 0
|
||||||
|
|
|
@ -95,13 +95,13 @@ typedef union {
|
||||||
typedef struct WASMSharedHeap {
|
typedef struct WASMSharedHeap {
|
||||||
/* The global shared heap list maintained in runtime, used for runtime
|
/* The global shared heap list maintained in runtime, used for runtime
|
||||||
* destroy */
|
* destroy */
|
||||||
struct WASMSharedHeap *next;
|
DefPointer(struct WASMSharedHeap *, next);
|
||||||
/* The logical shared heap chain the shared heap in */
|
/* The logical shared heap chain the shared heap in */
|
||||||
struct WASMSharedHeap *chain_next;
|
DefPointer(struct WASMSharedHeap *, chain_next);
|
||||||
/* Will be null if shared heap is created from pre allocated memory chunk
|
/* Will be null if shared heap is created from pre allocated memory chunk
|
||||||
* and don't need to dynamic malloc and free */
|
* and don't need to dynamic malloc and free */
|
||||||
void *heap_handle;
|
DefPointer(void *, heap_handle);
|
||||||
uint8 *base_addr;
|
DefPointer(uint8 *, base_addr);
|
||||||
uint64 size;
|
uint64 size;
|
||||||
uint64 start_off_mem64;
|
uint64 start_off_mem64;
|
||||||
uint64 start_off_mem32;
|
uint64 start_off_mem32;
|
||||||
|
|
|
@ -111,21 +111,31 @@ if (WAMR_BUILD_AOT EQUAL 1)
|
||||||
)
|
)
|
||||||
if (WAMR_COMPILER)
|
if (WAMR_COMPILER)
|
||||||
message (CHECK_PASS "found")
|
message (CHECK_PASS "found")
|
||||||
else()
|
else ()
|
||||||
message (CHECK_FAIL "not found")
|
message (CHECK_FAIL "not found")
|
||||||
endif()
|
endif ()
|
||||||
if (NOT EXISTS ${WAMR_COMPILER})
|
if (NOT EXISTS ${WAMR_COMPILER})
|
||||||
message (FATAL_ERROR "Please build wamrc under ${WAMR_ROOT_DIR}/wamr-compiler")
|
message (FATAL_ERROR "Please build wamrc under ${WAMR_ROOT_DIR}/wamr-compiler")
|
||||||
else()
|
else ()
|
||||||
message (STATUS "WAMR_COMPILER is ${WAMR_COMPILER}")
|
message (STATUS "WAMR_COMPILER is ${WAMR_COMPILER}")
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
|
if (WAMR_BUILD_TARGET STREQUAL "X86_32")
|
||||||
|
set (WAMR_COMPILER_FLAGS --enable-shared-heap --target=i386)
|
||||||
|
set (WAMR_COMPILER_CHAIN_FLAGS --enable-shared-chain --target=i386)
|
||||||
|
else ()
|
||||||
|
set (WAMR_COMPILER_FLAGS --enable-shared-heap)
|
||||||
|
set (WAMR_COMPILER_CHAIN_FLAGS --enable-shared-chain)
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_custom_target(
|
add_custom_target(
|
||||||
wasm_to_aot
|
wasm_to_aot
|
||||||
ALL
|
ALL
|
||||||
DEPENDS wasm-apps/test1.wasm wasm-apps/test2.wasm ${WAMR_COMPILER}
|
DEPENDS wasm-apps/test1.wasm wasm-apps/test2.wasm ${WAMR_COMPILER}
|
||||||
COMMAND ${WAMR_COMPILER} --enable-shared-heap -o wasm-apps/test1.aot wasm-apps/test1.wasm
|
COMMAND ${WAMR_COMPILER} ${WAMR_COMPILER_FLAGS} -o wasm-apps/test1.aot wasm-apps/test1.wasm
|
||||||
COMMAND ${WAMR_COMPILER} --enable-shared-heap -o wasm-apps/test2.aot wasm-apps/test2.wasm
|
COMMAND ${WAMR_COMPILER} ${WAMR_COMPILER_FLAGS} -o wasm-apps/test2.aot wasm-apps/test2.wasm
|
||||||
|
COMMAND ${WAMR_COMPILER} ${WAMR_COMPILER_CHAIN_FLAGS} -o wasm-apps/test1_chain.aot wasm-apps/test1.wasm
|
||||||
|
COMMAND ${WAMR_COMPILER} ${WAMR_COMPILER_CHAIN_FLAGS} -o wasm-apps/test2_chain.aot wasm-apps/test2.wasm
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -24,7 +24,7 @@ produce_data(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
|
||||||
wasm_runtime_get_exception(module_inst));
|
wasm_runtime_get_exception(module_inst));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (free_on_fail && argv[0] == 0) {
|
if (argv[0] == 0) {
|
||||||
printf("Failed to allocate memory from shared heap\n");
|
printf("Failed to allocate memory from shared heap\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ produce_data(wasm_module_inst_t module_inst, wasm_exec_env_t exec_env,
|
||||||
|
|
||||||
/* Passes wasm address directly between wasm apps since memory in shared
|
/* Passes wasm address directly between wasm apps since memory in shared
|
||||||
* heap chain is viewed as single address space in wasm's perspective */
|
* heap chain is viewed as single address space in wasm's perspective */
|
||||||
buf = (uint8 *)(uint64)argv[0];
|
buf = (uint8 *)(uintptr_t)argv[0];
|
||||||
if (!bh_post_msg(queue, 1, buf, buf_size)) {
|
if (!bh_post_msg(queue, 1, buf, buf_size)) {
|
||||||
printf("Failed to post message to queue\n");
|
printf("Failed to post message to queue\n");
|
||||||
if (free_on_fail)
|
if (free_on_fail)
|
||||||
|
@ -130,7 +130,7 @@ wasm_consumer(wasm_module_inst_t module_inst, bh_queue *queue)
|
||||||
buf = bh_message_payload(msg);
|
buf = bh_message_payload(msg);
|
||||||
|
|
||||||
/* call wasm function */
|
/* call wasm function */
|
||||||
argv[0] = (uint32)(uint64)buf;
|
argv[0] = (uint32)(uintptr_t)buf;
|
||||||
if (i < 8)
|
if (i < 8)
|
||||||
wasm_runtime_call_wasm(exec_env, print_buf_func, 1, argv);
|
wasm_runtime_call_wasm(exec_env, print_buf_func, 1, argv);
|
||||||
else
|
else
|
||||||
|
@ -198,7 +198,7 @@ main(int argc, char **argv)
|
||||||
if (!aot_mode)
|
if (!aot_mode)
|
||||||
wasm_file1 = "./wasm-apps/test1.wasm";
|
wasm_file1 = "./wasm-apps/test1.wasm";
|
||||||
else
|
else
|
||||||
wasm_file1 = "./wasm-apps/test1.aot";
|
wasm_file1 = "./wasm-apps/test1_chain.aot";
|
||||||
if (!(wasm_file1_buf =
|
if (!(wasm_file1_buf =
|
||||||
bh_read_file_to_buffer(wasm_file1, &wasm_file1_size))) {
|
bh_read_file_to_buffer(wasm_file1, &wasm_file1_size))) {
|
||||||
printf("Open wasm file %s failed.\n", wasm_file1);
|
printf("Open wasm file %s failed.\n", wasm_file1);
|
||||||
|
@ -225,7 +225,7 @@ main(int argc, char **argv)
|
||||||
if (!aot_mode)
|
if (!aot_mode)
|
||||||
wasm_file2 = "./wasm-apps/test2.wasm";
|
wasm_file2 = "./wasm-apps/test2.wasm";
|
||||||
else
|
else
|
||||||
wasm_file2 = "./wasm-apps/test2.aot";
|
wasm_file2 = "./wasm-apps/test2_chain.aot";
|
||||||
if (!(wasm_file2_buf =
|
if (!(wasm_file2_buf =
|
||||||
bh_read_file_to_buffer(wasm_file2, &wasm_file2_size))) {
|
bh_read_file_to_buffer(wasm_file2, &wasm_file2_size))) {
|
||||||
printf("Open wasm file %s failed.\n", wasm_file1);
|
printf("Open wasm file %s failed.\n", wasm_file1);
|
||||||
|
|
|
@ -62,6 +62,10 @@ my_shared_heap_free(void *ptr)
|
||||||
void *
|
void *
|
||||||
produce_str(char *addr, uint32_t index)
|
produce_str(char *addr, uint32_t index)
|
||||||
{
|
{
|
||||||
|
char c;
|
||||||
snprintf(addr, 512, "Data: %u stores to pre-allocated shared heap", index);
|
snprintf(addr, 512, "Data: %u stores to pre-allocated shared heap", index);
|
||||||
|
/* Actually access it in wasm */
|
||||||
|
c = addr[0];
|
||||||
|
printf("In WASM: the first char is %c\n", c);
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,10 @@ print_buf(char *buf)
|
||||||
void
|
void
|
||||||
consume_str(char *buf)
|
consume_str(char *buf)
|
||||||
{
|
{
|
||||||
printf("wasm app2's wasm func received buf in pre-allocated shared buf: "
|
/* Actually access it in wasm */
|
||||||
"%s\n\n",
|
char c = buf[0];
|
||||||
buf);
|
printf("In WASM: wasm app2's wasm func received buf in pre-allocated "
|
||||||
|
"shared buf: "
|
||||||
|
"%s with its first char is %c\n\n",
|
||||||
|
buf, c);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,15 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
|
|
||||||
if(WAMR_BUILD_TARGET STREQUAL "X86_32")
|
if(WAMR_BUILD_TARGET STREQUAL "X86_32")
|
||||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
|
# 1) Force -m32
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32" CACHE STRING "" FORCE)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32" CACHE STRING "" FORCE)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32" CACHE STRING "" FORCE)
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32" CACHE STRING "" FORCE)
|
||||||
|
|
||||||
|
# 2) Make CMake prefer i386 libraries
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR i386 CACHE STRING "" FORCE)
|
||||||
|
set(CMAKE_LIBRARY_ARCHITECTURE "i386-linux-gnu" CACHE STRING "" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Prevent overriding the parent project's compiler/linker
|
# Prevent overriding the parent project's compiler/linker
|
||||||
|
@ -29,12 +36,21 @@ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
# Fetch Google test
|
# Fetch Google test
|
||||||
include (FetchContent)
|
include (FetchContent)
|
||||||
FetchContent_Declare (
|
|
||||||
|
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.24")
|
||||||
|
FetchContent_Declare (
|
||||||
googletest
|
googletest
|
||||||
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
DOWNLOAD_EXTRACT_TIMESTAMP ON
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable (googletest)
|
else()
|
||||||
|
FetchContent_Declare (
|
||||||
|
googletest
|
||||||
|
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(googletest)
|
||||||
|
|
||||||
SET(GOOGLETEST_INCLUDED 1)
|
SET(GOOGLETEST_INCLUDED 1)
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,20 @@ set(WAMR_BUILD_AOT 1)
|
||||||
set(WAMR_BUILD_INTERP 1)
|
set(WAMR_BUILD_INTERP 1)
|
||||||
set(WAMR_BUILD_FAST_INTERP 1)
|
set(WAMR_BUILD_FAST_INTERP 1)
|
||||||
set(WAMR_BUILD_JIT 0)
|
set(WAMR_BUILD_JIT 0)
|
||||||
set(WAMR_BUILD_MEMORY64 1)
|
if(WAMR_BUILD_TARGET STREQUAL "X86_32")
|
||||||
|
set(WAMR_BUILD_MEMORY64 0)
|
||||||
|
else()
|
||||||
|
set(WAMR_BUILD_MEMORY64 1)
|
||||||
|
endif()
|
||||||
set(WAMR_BUILD_SHARED_HEAP 1)
|
set(WAMR_BUILD_SHARED_HEAP 1)
|
||||||
|
|
||||||
# Compile wasm modules
|
# Compile wasm modules
|
||||||
add_subdirectory(wasm-apps)
|
add_subdirectory(wasm-apps)
|
||||||
|
|
||||||
|
if (WAMR_BUILD_MEMORY64 EQUAL 1)
|
||||||
|
add_subdirectory(wasm-apps/memory64)
|
||||||
|
endif ()
|
||||||
|
|
||||||
# if only load this CMake other than load it as subdirectory
|
# if only load this CMake other than load it as subdirectory
|
||||||
include(../unit_common.cmake)
|
include(../unit_common.cmake)
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ static bool
|
||||||
load_wasm(char *wasm_file_tested, unsigned int app_heap_size,
|
load_wasm(char *wasm_file_tested, unsigned int app_heap_size,
|
||||||
ret_env &ret_module_env)
|
ret_env &ret_module_env)
|
||||||
{
|
{
|
||||||
const char *wasm_file = strdup(wasm_file_tested);
|
char *wasm_file = strdup(wasm_file_tested);
|
||||||
unsigned int wasm_file_size = 0;
|
unsigned int wasm_file_size = 0;
|
||||||
unsigned int stack_size = 16 * 1024, heap_size = app_heap_size;
|
unsigned int stack_size = 16 * 1024, heap_size = app_heap_size;
|
||||||
char error_buf[128] = { 0 };
|
char error_buf[128] = { 0 };
|
||||||
|
@ -68,8 +68,10 @@ load_wasm(char *wasm_file_tested, unsigned int app_heap_size,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(wasm_file);
|
||||||
return true;
|
return true;
|
||||||
fail:
|
fail:
|
||||||
|
free(wasm_file);
|
||||||
destroy_module_env(ret_module_env);
|
destroy_module_env(ret_module_env);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +157,9 @@ TEST_F(shared_heap_test, test_shared_heap_basic)
|
||||||
|
|
||||||
test_shared_heap(shared_heap, "test.aot", "test", 0, argv);
|
test_shared_heap(shared_heap, "test.aot", "test", 0, argv);
|
||||||
EXPECT_EQ(10, argv[0]);
|
EXPECT_EQ(10, argv[0]);
|
||||||
|
|
||||||
|
test_shared_heap(shared_heap, "test_chain.aot", "test", 0, argv);
|
||||||
|
EXPECT_EQ(10, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(shared_heap_test, test_shared_heap_malloc_fail)
|
TEST_F(shared_heap_test, test_shared_heap_malloc_fail)
|
||||||
|
@ -175,6 +180,10 @@ TEST_F(shared_heap_test, test_shared_heap_malloc_fail)
|
||||||
|
|
||||||
test_shared_heap(shared_heap, "test.aot", "test_malloc_fail", 0, argv);
|
test_shared_heap(shared_heap, "test.aot", "test_malloc_fail", 0, argv);
|
||||||
EXPECT_EQ(1, argv[0]);
|
EXPECT_EQ(1, argv[0]);
|
||||||
|
|
||||||
|
test_shared_heap(shared_heap, "test_chain.aot", "test_malloc_fail", 0,
|
||||||
|
argv);
|
||||||
|
EXPECT_EQ(1, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(shared_heap_test, test_preallocated_shared_heap_malloc_fail)
|
TEST_F(shared_heap_test, test_preallocated_shared_heap_malloc_fail)
|
||||||
|
@ -201,20 +210,41 @@ TEST_F(shared_heap_test, test_preallocated_shared_heap_malloc_fail)
|
||||||
argv[0] = 1024;
|
argv[0] = 1024;
|
||||||
test_shared_heap(shared_heap, "test.aot", "my_shared_heap_malloc", 1, argv);
|
test_shared_heap(shared_heap, "test.aot", "my_shared_heap_malloc", 1, argv);
|
||||||
EXPECT_EQ(0, argv[0]);
|
EXPECT_EQ(0, argv[0]);
|
||||||
|
|
||||||
|
argv[0] = 1024;
|
||||||
|
test_shared_heap(shared_heap, "test_chain.aot", "my_shared_heap_malloc", 1,
|
||||||
|
argv);
|
||||||
|
EXPECT_EQ(0, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(shared_heap_test, test_shared_heap_chain_rmw)
|
static void
|
||||||
|
create_test_shared_heap(uint8 *preallocated_buf, size_t size,
|
||||||
|
WASMSharedHeap **shared_heap_res)
|
||||||
{
|
{
|
||||||
SharedHeapInitArgs args = { 0 };
|
SharedHeapInitArgs args = { 0 };
|
||||||
WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr,
|
WASMSharedHeap *shared_heap = nullptr;
|
||||||
*shared_heap_chain = nullptr;
|
|
||||||
uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize();
|
|
||||||
uint8 preallocated_buf[BUF_SIZE] = { 0 },
|
|
||||||
preallocated_buf2[BUF_SIZE] = { 0 };
|
|
||||||
uint32 start1, end1, start2, end2;
|
|
||||||
|
|
||||||
args.pre_allocated_addr = preallocated_buf;
|
args.pre_allocated_addr = preallocated_buf;
|
||||||
args.size = BUF_SIZE;
|
args.size = size;
|
||||||
|
shared_heap = wasm_runtime_create_shared_heap(&args);
|
||||||
|
if (!shared_heap) {
|
||||||
|
FAIL() << "Create preallocated shared heap failed.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
*shared_heap_res = shared_heap;
|
||||||
|
if (!*shared_heap_res) {
|
||||||
|
FAIL() << "Create shared heap chain failed.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_test_shared_heap_chain(uint8 *preallocated_buf, size_t size,
|
||||||
|
uint8 *preallocated_buf2, size_t size2,
|
||||||
|
WASMSharedHeap **shared_heap_chain)
|
||||||
|
{
|
||||||
|
SharedHeapInitArgs args = { 0 };
|
||||||
|
WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr;
|
||||||
|
args.pre_allocated_addr = preallocated_buf;
|
||||||
|
args.size = size;
|
||||||
shared_heap = wasm_runtime_create_shared_heap(&args);
|
shared_heap = wasm_runtime_create_shared_heap(&args);
|
||||||
if (!shared_heap) {
|
if (!shared_heap) {
|
||||||
FAIL() << "Create preallocated shared heap failed.\n";
|
FAIL() << "Create preallocated shared heap failed.\n";
|
||||||
|
@ -222,23 +252,74 @@ TEST_F(shared_heap_test, test_shared_heap_chain_rmw)
|
||||||
|
|
||||||
memset(&args, 0, sizeof(args));
|
memset(&args, 0, sizeof(args));
|
||||||
args.pre_allocated_addr = preallocated_buf2;
|
args.pre_allocated_addr = preallocated_buf2;
|
||||||
args.size = BUF_SIZE;
|
args.size = size2;
|
||||||
shared_heap2 = wasm_runtime_create_shared_heap(&args);
|
shared_heap2 = wasm_runtime_create_shared_heap(&args);
|
||||||
if (!shared_heap2) {
|
if (!shared_heap2) {
|
||||||
FAIL() << "Create preallocated shared heap failed.\n";
|
FAIL() << "Create preallocated shared heap failed.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_heap_chain =
|
*shared_heap_chain =
|
||||||
wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
|
wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
|
||||||
if (!shared_heap_chain) {
|
if (!*shared_heap_chain) {
|
||||||
FAIL() << "Create shared heap chain failed.\n";
|
FAIL() << "Create shared heap chain failed.\n";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(shared_heap_test, test_shared_heap_rmw)
|
||||||
|
{
|
||||||
|
WASMSharedHeap *shared_heap = nullptr;
|
||||||
|
uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize();
|
||||||
|
uint8 preallocated_buf[BUF_SIZE] = { 0 };
|
||||||
|
uint32 start1, end1;
|
||||||
|
|
||||||
|
create_test_shared_heap(preallocated_buf, BUF_SIZE, &shared_heap);
|
||||||
|
|
||||||
/* app addr for shared heap */
|
/* app addr for shared heap */
|
||||||
start1 = 0xFFFFFFFF - 2 * BUF_SIZE + 1;
|
start1 = UINT32_MAX - BUF_SIZE + 1;
|
||||||
end1 = 0xFFFFFFFF - BUF_SIZE;
|
end1 = UINT32_MAX;
|
||||||
start2 = 0xFFFFFFFF - BUF_SIZE + 1;
|
|
||||||
end2 = 0xFFFFFFFF;
|
argv[0] = end1;
|
||||||
|
argv[1] = 101;
|
||||||
|
test_shared_heap(shared_heap, "test.wasm", "read_modify_write_8", 2, argv);
|
||||||
|
EXPECT_EQ(0, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf[BUF_SIZE - 1], 101);
|
||||||
|
|
||||||
|
argv[0] = start1;
|
||||||
|
argv[1] = 37;
|
||||||
|
test_shared_heap(shared_heap, "test.wasm", "read_modify_write_8", 2, argv);
|
||||||
|
EXPECT_EQ(0, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf[0], 37);
|
||||||
|
|
||||||
|
argv[0] = end1;
|
||||||
|
argv[1] = 81;
|
||||||
|
test_shared_heap(shared_heap, "test.aot", "read_modify_write_8", 2, argv);
|
||||||
|
EXPECT_EQ(101, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf[BUF_SIZE - 1], 81);
|
||||||
|
|
||||||
|
argv[0] = start1;
|
||||||
|
argv[1] = 98;
|
||||||
|
test_shared_heap(shared_heap, "test.aot", "read_modify_write_8", 2, argv);
|
||||||
|
EXPECT_EQ(37, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf[0], 98);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(shared_heap_test, test_shared_heap_chain_rmw)
|
||||||
|
{
|
||||||
|
SharedHeapInitArgs args = { 0 };
|
||||||
|
WASMSharedHeap *shared_heap_chain = nullptr;
|
||||||
|
uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize();
|
||||||
|
uint8 preallocated_buf[BUF_SIZE] = { 0 },
|
||||||
|
preallocated_buf2[BUF_SIZE] = { 0 };
|
||||||
|
uint32 start1, end1, start2, end2;
|
||||||
|
|
||||||
|
create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
|
||||||
|
BUF_SIZE, &shared_heap_chain);
|
||||||
|
|
||||||
|
/* app addr for shared heap */
|
||||||
|
start1 = UINT32_MAX - 2 * BUF_SIZE + 1;
|
||||||
|
end1 = UINT32_MAX - BUF_SIZE;
|
||||||
|
start2 = UINT32_MAX - BUF_SIZE + 1;
|
||||||
|
end2 = UINT32_MAX;
|
||||||
|
|
||||||
/* shared heap 1 */
|
/* shared heap 1 */
|
||||||
argv[0] = end1;
|
argv[0] = end1;
|
||||||
|
@ -256,76 +337,309 @@ TEST_F(shared_heap_test, test_shared_heap_chain_rmw)
|
||||||
EXPECT_EQ(0, argv[0]);
|
EXPECT_EQ(0, argv[0]);
|
||||||
EXPECT_EQ(preallocated_buf2[0], 129);
|
EXPECT_EQ(preallocated_buf2[0], 129);
|
||||||
|
|
||||||
/* TODO: test aot when chain is supported in AOT */
|
|
||||||
/*
|
|
||||||
argv[0] = start1;
|
argv[0] = start1;
|
||||||
argv[1] = 98;
|
argv[1] = 98;
|
||||||
test_shared_heap(shared_heap_chain, "test.aot", "read_modify_write_8", 2,
|
test_shared_heap(shared_heap_chain, "test_chain.aot", "read_modify_write_8",
|
||||||
argv);
|
2, argv);
|
||||||
EXPECT_EQ(0, argv[0]);
|
EXPECT_EQ(0, argv[0]);
|
||||||
EXPECT_EQ(preallocated_buf[0], 98);
|
EXPECT_EQ(preallocated_buf[0], 98);
|
||||||
|
|
||||||
argv[0] = end2;
|
argv[0] = end2;
|
||||||
argv[1] = 81;
|
argv[1] = 81;
|
||||||
test_shared_heap(shared_heap_chain, "test.aot", "read_modify_write_8", 2,
|
test_shared_heap(shared_heap_chain, "test_chain.aot", "read_modify_write_8",
|
||||||
argv);
|
2, argv);
|
||||||
EXPECT_EQ(0, argv[0]);
|
EXPECT_EQ(0, argv[0]);
|
||||||
EXPECT_EQ(preallocated_buf2[BUF_SIZE - 1], 81);
|
EXPECT_EQ(preallocated_buf2[BUF_SIZE - 1], 81);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(shared_heap_test, test_shared_heap_chain_rmw_oob)
|
TEST_F(shared_heap_test, test_shared_heap_chain_rmw_bulk_memory)
|
||||||
{
|
{
|
||||||
SharedHeapInitArgs args = { 0 };
|
SharedHeapInitArgs args = { 0 };
|
||||||
WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr,
|
WASMSharedHeap *shared_heap_chain = nullptr;
|
||||||
*shared_heap_chain = nullptr;
|
uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize();
|
||||||
|
uint8 preallocated_buf[BUF_SIZE] = { 0 },
|
||||||
|
preallocated_buf2[BUF_SIZE] = { 0 };
|
||||||
|
uint32 start1, end1, start2, end2;
|
||||||
|
|
||||||
|
create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
|
||||||
|
BUF_SIZE, &shared_heap_chain);
|
||||||
|
|
||||||
|
/* app addr for shared heap */
|
||||||
|
start1 = UINT32_MAX - 2 * BUF_SIZE + 1;
|
||||||
|
end1 = UINT32_MAX - BUF_SIZE;
|
||||||
|
start2 = UINT32_MAX - BUF_SIZE + 1;
|
||||||
|
end2 = UINT32_MAX;
|
||||||
|
|
||||||
|
argv[0] = end1;
|
||||||
|
argv[1] = 101;
|
||||||
|
argv[2] = 1;
|
||||||
|
test_shared_heap(shared_heap_chain, "test_bulk_memory.wasm",
|
||||||
|
"memory_fill_test", 3, argv);
|
||||||
|
/* no modification since no return value */
|
||||||
|
EXPECT_EQ(end1, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf[BUF_SIZE - 1], 101);
|
||||||
|
|
||||||
|
argv[0] = start1;
|
||||||
|
argv[1] = 14;
|
||||||
|
argv[2] = 1;
|
||||||
|
test_shared_heap(shared_heap_chain, "test_bulk_memory_chain.aot",
|
||||||
|
"memory_fill_test", 3, argv);
|
||||||
|
/* no modification since no return value */
|
||||||
|
EXPECT_EQ(start1, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf[0], 14);
|
||||||
|
|
||||||
|
/* nothing happen when memory fill 0 byte */
|
||||||
|
argv[0] = start2;
|
||||||
|
argv[1] = 68;
|
||||||
|
argv[2] = 0;
|
||||||
|
test_shared_heap(shared_heap_chain, "test_bulk_memory_chain.aot",
|
||||||
|
"memory_fill_test", 3, argv);
|
||||||
|
/* no modification since no return value */
|
||||||
|
EXPECT_EQ(start2, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf2[0], 0);
|
||||||
|
|
||||||
|
argv[0] = end2;
|
||||||
|
argv[1] = 98;
|
||||||
|
argv[2] = 1;
|
||||||
|
test_shared_heap(shared_heap_chain, "test_bulk_memory_chain.aot",
|
||||||
|
"memory_fill_test", 3, argv);
|
||||||
|
/* no modification since no return value */
|
||||||
|
EXPECT_EQ(end2, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf2[BUF_SIZE - 1], 98);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(shared_heap_test, test_shared_heap_chain_rmw_bulk_memory_oob)
|
||||||
|
{
|
||||||
|
SharedHeapInitArgs args = { 0 };
|
||||||
|
WASMSharedHeap *shared_heap_chain = nullptr;
|
||||||
|
uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize();
|
||||||
|
uint8 preallocated_buf[BUF_SIZE] = { 0 },
|
||||||
|
preallocated_buf2[BUF_SIZE] = { 0 };
|
||||||
|
uint32 start1, end1, start2, end2;
|
||||||
|
|
||||||
|
create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
|
||||||
|
BUF_SIZE, &shared_heap_chain);
|
||||||
|
|
||||||
|
/* app addr for shared heap */
|
||||||
|
start1 = UINT32_MAX - 2 * BUF_SIZE + 1;
|
||||||
|
end1 = UINT32_MAX - BUF_SIZE;
|
||||||
|
start2 = UINT32_MAX - BUF_SIZE + 1;
|
||||||
|
end2 = UINT32_MAX;
|
||||||
|
|
||||||
|
/* shared heap 1 */
|
||||||
|
argv[0] = end1;
|
||||||
|
argv[1] = 101;
|
||||||
|
argv[2] = 2;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
|
"test_bulk_memory.wasm",
|
||||||
|
"memory_fill_test", 3, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
argv[0] = end2;
|
||||||
|
argv[1] = 98;
|
||||||
|
argv[2] = 2;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
|
"test_bulk_memory.wasm",
|
||||||
|
"memory_fill_test", 3, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
argv[0] = start1;
|
||||||
|
argv[1] = 98;
|
||||||
|
argv[2] = BUF_SIZE + 1;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
|
"test_bulk_memory.wasm",
|
||||||
|
"memory_fill_test", 3, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
argv[0] = start2;
|
||||||
|
argv[1] = 98;
|
||||||
|
argv[2] = BUF_SIZE + 1;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
|
"test_bulk_memory.wasm",
|
||||||
|
"memory_fill_test", 3, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
argv[0] = end1;
|
||||||
|
argv[1] = 101;
|
||||||
|
argv[2] = 2;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
|
"test_bulk_memory_chain.aot",
|
||||||
|
"memory_fill_test", 3, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
argv[0] = end2;
|
||||||
|
argv[1] = 98;
|
||||||
|
argv[2] = 2;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
|
"test_bulk_memory_chain.aot",
|
||||||
|
"memory_fill_test", 3, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
argv[0] = start1;
|
||||||
|
argv[1] = 98;
|
||||||
|
argv[2] = BUF_SIZE + 1;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
|
"test_bulk_memory_chain.aot",
|
||||||
|
"memory_fill_test", 3, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
argv[0] = start2;
|
||||||
|
argv[1] = 98;
|
||||||
|
argv[2] = BUF_SIZE + 1;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
|
"test_bulk_memory_chain.aot",
|
||||||
|
"memory_fill_test", 3, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(shared_heap_test, test_shared_heap_rmw_oob)
|
||||||
|
{
|
||||||
|
WASMSharedHeap *shared_heap = nullptr;
|
||||||
uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize();
|
uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize();
|
||||||
uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE];
|
uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE];
|
||||||
uint32 start1, end1, start2, end2;
|
uint32 start1, end1, start2, end2;
|
||||||
|
|
||||||
args.pre_allocated_addr = preallocated_buf;
|
create_test_shared_heap(preallocated_buf, BUF_SIZE, &shared_heap);
|
||||||
args.size = BUF_SIZE;
|
|
||||||
shared_heap = wasm_runtime_create_shared_heap(&args);
|
|
||||||
if (!shared_heap) {
|
|
||||||
FAIL() << "Create preallocated shared heap failed.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&args, 0, sizeof(args));
|
|
||||||
args.pre_allocated_addr = preallocated_buf2;
|
|
||||||
args.size = BUF_SIZE;
|
|
||||||
shared_heap2 = wasm_runtime_create_shared_heap(&args);
|
|
||||||
if (!shared_heap2) {
|
|
||||||
FAIL() << "Create preallocated shared heap failed.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_heap_chain =
|
|
||||||
wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
|
|
||||||
if (!shared_heap_chain) {
|
|
||||||
FAIL() << "Create shared heap chain failed.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* app addr for shared heap */
|
/* app addr for shared heap */
|
||||||
start1 = 0xFFFFFFFF - 2 * BUF_SIZE + 1;
|
start1 = UINT32_MAX - BUF_SIZE + 1;
|
||||||
end1 = 0xFFFFFFFF - BUF_SIZE;
|
end1 = UINT32_MAX;
|
||||||
start2 = 0xFFFFFFFF - BUF_SIZE + 1;
|
|
||||||
end2 = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
/* try to rmw an u16, first u8 is in the first shared heap and second u8 is
|
/* try to rmw an u16, first u8 is in the first shared heap and second u8 is
|
||||||
* in the second shared heap, will be seen as oob */
|
* in the second shared heap, will be seen as oob */
|
||||||
argv[0] = end1;
|
argv[0] = end1;
|
||||||
argv[1] = 12025;
|
argv[1] = 12025;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap, "test.wasm",
|
||||||
|
"read_modify_write_16", 2, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
argv[0] = start1 - 1;
|
||||||
|
argv[1] = 12025;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap, "test.aot",
|
||||||
|
"read_modify_write_16", 2, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
argv[0] = end1;
|
||||||
|
argv[1] = 12025;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap, "test.aot",
|
||||||
|
"read_modify_write_16", 2, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(shared_heap_test, test_shared_heap_chain_rmw_oob)
|
||||||
|
{
|
||||||
|
WASMSharedHeap *shared_heap_chain = nullptr;
|
||||||
|
uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize();
|
||||||
|
uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE];
|
||||||
|
uint32 start1, end1, start2, end2;
|
||||||
|
|
||||||
|
create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
|
||||||
|
BUF_SIZE, &shared_heap_chain);
|
||||||
|
|
||||||
|
/* app addr for shared heap */
|
||||||
|
start1 = UINT32_MAX - 2 * BUF_SIZE + 1;
|
||||||
|
end1 = UINT32_MAX - BUF_SIZE;
|
||||||
|
start2 = UINT32_MAX - BUF_SIZE + 1;
|
||||||
|
end2 = UINT32_MAX;
|
||||||
|
|
||||||
|
/* try to rmw an u16, first u8 is in the first shared heap and second u8 is
|
||||||
|
* in the second shared heap, will be seen as oob */
|
||||||
|
argv[0] = end2;
|
||||||
|
argv[1] = 12025;
|
||||||
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain, "test.wasm",
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain, "test.wasm",
|
||||||
"read_modify_write_16", 2, argv),
|
"read_modify_write_16", 2, argv),
|
||||||
"Exception: out of bounds memory access");
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
/* TODO: test aot when chain is supported in AOT */
|
argv[0] = end1;
|
||||||
/*argv[0] = end1;
|
|
||||||
argv[1] = 12025;
|
argv[1] = 12025;
|
||||||
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain, "test.wasm",
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
|
"test_chain.aot",
|
||||||
"read_modify_write_16", 2, argv),
|
"read_modify_write_16", 2, argv),
|
||||||
"Exception: out of bounds memory access");*/
|
"Exception: out of bounds memory access");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_MEMORY64 != 0
|
||||||
|
TEST_F(shared_heap_test, test_shared_heap_chain_memory64_rmw)
|
||||||
|
{
|
||||||
|
WASMSharedHeap *shared_heap_chain = nullptr;
|
||||||
|
uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize();
|
||||||
|
uint8 preallocated_buf[BUF_SIZE] = { 0 },
|
||||||
|
preallocated_buf2[BUF_SIZE] = { 0 };
|
||||||
|
uint64 start1, end1, start2, end2;
|
||||||
|
|
||||||
|
create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
|
||||||
|
BUF_SIZE, &shared_heap_chain);
|
||||||
|
|
||||||
|
/* app addr for shared heap */
|
||||||
|
start1 = UINT64_MAX - 2 * BUF_SIZE + 1;
|
||||||
|
end1 = UINT64_MAX - BUF_SIZE;
|
||||||
|
start2 = UINT64_MAX - BUF_SIZE + 1;
|
||||||
|
end2 = UINT64_MAX;
|
||||||
|
|
||||||
|
/* shared heap 1 */
|
||||||
|
PUT_I64_TO_ADDR(argv, end1);
|
||||||
|
argv[2] = 101;
|
||||||
|
test_shared_heap(shared_heap_chain, "test64.wasm", "read_modify_write_8", 3,
|
||||||
|
argv);
|
||||||
|
EXPECT_EQ(0, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf[BUF_SIZE - 1], 101);
|
||||||
|
|
||||||
|
/* shared heap 2 */
|
||||||
|
PUT_I64_TO_ADDR(argv, start2);
|
||||||
|
argv[2] = 129;
|
||||||
|
test_shared_heap(shared_heap_chain, "test64.wasm", "read_modify_write_8", 3,
|
||||||
|
argv);
|
||||||
|
EXPECT_EQ(0, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf2[0], 129);
|
||||||
|
|
||||||
|
PUT_I64_TO_ADDR(argv, start1);
|
||||||
|
argv[2] = 98;
|
||||||
|
test_shared_heap(shared_heap_chain, "test64_chain.aot",
|
||||||
|
"read_modify_write_8", 3, argv);
|
||||||
|
EXPECT_EQ(0, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf[0], 98);
|
||||||
|
|
||||||
|
PUT_I64_TO_ADDR(argv, end2);
|
||||||
|
argv[2] = 81;
|
||||||
|
test_shared_heap(shared_heap_chain, "test64_chain.aot",
|
||||||
|
"read_modify_write_8", 3, argv);
|
||||||
|
EXPECT_EQ(0, argv[0]);
|
||||||
|
EXPECT_EQ(preallocated_buf2[BUF_SIZE - 1], 81);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(shared_heap_test, test_shared_heap_chain_memory64_rmw_oob)
|
||||||
|
{
|
||||||
|
WASMSharedHeap *shared_heap_chain = nullptr;
|
||||||
|
uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize();
|
||||||
|
uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE];
|
||||||
|
uint64 start1, end1, start2, end2;
|
||||||
|
|
||||||
|
create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
|
||||||
|
BUF_SIZE, &shared_heap_chain);
|
||||||
|
|
||||||
|
/* app addr for shared heap */
|
||||||
|
start1 = UINT64_MAX - 2 * BUF_SIZE + 1;
|
||||||
|
end1 = UINT64_MAX - BUF_SIZE;
|
||||||
|
start2 = UINT64_MAX - BUF_SIZE + 1;
|
||||||
|
end2 = UINT64_MAX;
|
||||||
|
|
||||||
|
/* try to rmw an u16, first u8 is in the first shared heap and second u8 is
|
||||||
|
* in the second shared heap, will be seen as oob */
|
||||||
|
PUT_I64_TO_ADDR(argv, end1);
|
||||||
|
argv[2] = 12025;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain, "test64.wasm",
|
||||||
|
"read_modify_write_16", 3, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
PUT_I64_TO_ADDR(argv, end1);
|
||||||
|
argv[2] = 12025;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
|
"test64_chain.aot",
|
||||||
|
"read_modify_write_16", 3, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef native_function
|
#ifndef native_function
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
#define native_function(func_name, signature) \
|
#define native_function(func_name, signature) \
|
||||||
|
@ -378,6 +692,9 @@ TEST_F(shared_heap_test, test_addr_conv)
|
||||||
|
|
||||||
test_shared_heap(shared_heap, "test_addr_conv.aot", "test", 0, argv);
|
test_shared_heap(shared_heap, "test_addr_conv.aot", "test", 0, argv);
|
||||||
EXPECT_EQ(1, argv[0]);
|
EXPECT_EQ(1, argv[0]);
|
||||||
|
|
||||||
|
test_shared_heap(shared_heap, "test_addr_conv_chain.aot", "test", 0, argv);
|
||||||
|
EXPECT_EQ(1, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(shared_heap_test, test_addr_conv_pre_allocated_oob)
|
TEST_F(shared_heap_test, test_addr_conv_pre_allocated_oob)
|
||||||
|
@ -412,6 +729,12 @@ TEST_F(shared_heap_test, test_addr_conv_pre_allocated_oob)
|
||||||
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap, "test_addr_conv.aot",
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap, "test_addr_conv.aot",
|
||||||
"test_preallocated", 1, argv),
|
"test_preallocated", 1, argv),
|
||||||
"Exception: out of bounds memory access");
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
|
argv[0] = app_addr;
|
||||||
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap,
|
||||||
|
"test_addr_conv_chain.aot",
|
||||||
|
"test_preallocated", 1, argv),
|
||||||
|
"Exception: out of bounds memory access");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(shared_heap_test, test_shared_heap_chain)
|
TEST_F(shared_heap_test, test_shared_heap_chain)
|
||||||
|
@ -453,9 +776,8 @@ TEST_F(shared_heap_test, test_shared_heap_chain)
|
||||||
test_shared_heap(shared_heap_chain, "test_addr_conv.wasm", "test", 0, argv);
|
test_shared_heap(shared_heap_chain, "test_addr_conv.wasm", "test", 0, argv);
|
||||||
EXPECT_EQ(1, argv[0]);
|
EXPECT_EQ(1, argv[0]);
|
||||||
|
|
||||||
/* TODO: test aot when chain is supported in AOT */
|
test_shared_heap(shared_heap, "test_addr_conv.aot", "test", 0, argv);
|
||||||
/*test_shared_heap(shared_heap, "test_addr_conv.aot", "test", 1, argv);
|
EXPECT_EQ(1, argv[0]);
|
||||||
EXPECT_EQ(1, argv[0]);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(shared_heap_test, test_shared_heap_chain_create_fail)
|
TEST_F(shared_heap_test, test_shared_heap_chain_create_fail)
|
||||||
|
@ -666,14 +988,15 @@ TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv)
|
||||||
"test_preallocated", 1, argv);
|
"test_preallocated", 1, argv);
|
||||||
EXPECT_EQ(1, argv[0]);
|
EXPECT_EQ(1, argv[0]);
|
||||||
|
|
||||||
/* TODO: test aot when chain is supported in AOT */
|
argv[0] = 0xFFFFFFFF;
|
||||||
/*argv[0] = 0xFFFFFFFF;
|
test_shared_heap(shared_heap, "test_addr_conv_chain.aot",
|
||||||
test_shared_heap(shared_heap, "test_addr_conv.aot", "test", 1, argv);
|
"test_preallocated", 1, argv);
|
||||||
EXPECT_EQ(1, argv[0]);
|
EXPECT_EQ(1, argv[0]);
|
||||||
|
|
||||||
argv[0] = 0xFFFFF000;
|
argv[0] = 0xFFFFF000;
|
||||||
test_shared_heap(shared_heap, "test_addr_conv.aot", "test", 1, argv);
|
test_shared_heap(shared_heap, "test_addr_conv_chain.aot",
|
||||||
EXPECT_EQ(1, argv[0]); */
|
"test_preallocated", 1, argv);
|
||||||
|
EXPECT_EQ(1, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv_oob)
|
TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv_oob)
|
||||||
|
@ -719,10 +1042,10 @@ TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv_oob)
|
||||||
"test_preallocated", 1, argv),
|
"test_preallocated", 1, argv),
|
||||||
"Exception: out of bounds memory access");
|
"Exception: out of bounds memory access");
|
||||||
|
|
||||||
/* TODO: test aot when chain is supported in AOT */
|
/* test aot */
|
||||||
/*argv[0] = 0xFFFFFFFF - BUF_SIZE - 4096;
|
argv[0] = 0xFFFFFFFF - BUF_SIZE - 4096;
|
||||||
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
|
||||||
"test_addr_conv.aot",
|
"test_addr_conv_chain.aot",
|
||||||
"test_preallocated", 1, argv),
|
"test_preallocated", 1, argv),
|
||||||
"Exception: out of bounds memory access");*/
|
"Exception: out of bounds memory access");
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,44 +29,81 @@ set(CMAKE_EXE_LINKER_FLAGS
|
||||||
-Wl,--allow-undefined"
|
-Wl,--allow-undefined"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (WAMR_BUILD_TARGET STREQUAL "X86_32")
|
||||||
|
set (WAMR_COMPILER_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap --target=i386)
|
||||||
|
set (WAMR_COMPILER_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain --target=i386)
|
||||||
|
else ()
|
||||||
|
set (WAMR_COMPILER_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap)
|
||||||
|
set (WAMR_COMPILER_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
function(copy_wasm TARGET_NAME)
|
||||||
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||||
|
COMMENT "Copy ${TARGET_NAME} to the same directory of google test"
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(compile_and_copy_aot_from TARGET_NAME)
|
||||||
|
string(REPLACE ".wasm" ".aot" AOT_TARGET ${TARGET_NAME})
|
||||||
|
string(REPLACE ".wasm" "_chain.aot" AOT_CHAIN_TARGET ${TARGET_NAME})
|
||||||
|
|
||||||
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||||
|
COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_FLAGS}
|
||||||
|
-o ${AOT_TARGET}
|
||||||
|
${TARGET_NAME}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${AOT_TARGET}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||||
|
COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_CHAIN_FLAGS}
|
||||||
|
-o ${AOT_CHAIN_TARGET}
|
||||||
|
${TARGET_NAME}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${AOT_CHAIN_TARGET}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||||
|
COMMENT "Compile and copy ${AOT_TARGET} to the same directory of google test"
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
add_executable(test.wasm test.c)
|
add_executable(test.wasm test.c)
|
||||||
target_link_libraries(test.wasm)
|
target_link_libraries(test.wasm)
|
||||||
|
copy_wasm(test.wasm)
|
||||||
add_custom_command(TARGET test.wasm POST_BUILD
|
compile_and_copy_aot_from(test.wasm)
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/test.wasm
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
|
||||||
COMMENT "Copy test.wasm to the same directory of google test"
|
|
||||||
)
|
|
||||||
|
|
||||||
add_custom_command(TARGET test.wasm POST_BUILD
|
|
||||||
COMMAND ${WAMRC_ROOT_DIR}/wamrc --opt-level=0 --enable-shared-heap --bounds-checks=1
|
|
||||||
-o
|
|
||||||
test.aot
|
|
||||||
test.wasm
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/test.aot
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
|
||||||
COMMENT "Copy test.aot to the same directory of google test"
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(test_addr_conv.wasm test_addr_conv.c)
|
add_executable(test_addr_conv.wasm test_addr_conv.c)
|
||||||
target_link_libraries(test.wasm)
|
target_link_libraries(test_addr_conv.wasm)
|
||||||
|
copy_wasm(test_addr_conv.wasm)
|
||||||
|
compile_and_copy_aot_from(test_addr_conv.wasm)
|
||||||
|
|
||||||
add_custom_command(TARGET test_addr_conv.wasm POST_BUILD
|
# copy and compile aot for bulk memory test
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy
|
set(SOURCE_WASM ${CMAKE_CURRENT_SOURCE_DIR}/bulk-memory/test_bulk_memory.wasm)
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/test_addr_conv.wasm
|
set(BUILD_WASM ${CMAKE_CURRENT_BINARY_DIR}/../test_bulk_memory.wasm)
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
set(OUTPUT_AOT ${CMAKE_CURRENT_BINARY_DIR}/../test_bulk_memory.aot)
|
||||||
COMMENT "Copy test_addr_conv.wasm to the same directory of google test"
|
set(OUTPUT_CHAIN_AOT ${CMAKE_CURRENT_BINARY_DIR}/../test_bulk_memory_chain.aot)
|
||||||
)
|
|
||||||
|
|
||||||
add_custom_command(TARGET test_addr_conv.wasm POST_BUILD
|
add_custom_command(
|
||||||
COMMAND ${WAMRC_ROOT_DIR}/wamrc --opt-level=0 --enable-shared-heap --bounds-checks=1
|
OUTPUT ${BUILD_WASM}
|
||||||
-o
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
test_addr_conv.aot
|
${SOURCE_WASM}
|
||||||
test_addr_conv.wasm
|
${BUILD_WASM}
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy
|
DEPENDS ${SOURCE_WASM}
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/test_addr_conv.aot
|
COMMENT "Copying bulk memory WASM to build directory"
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
)
|
||||||
COMMENT "Copy test_addr_conv.aot to the same directory of google test"
|
|
||||||
)
|
add_custom_command(
|
||||||
|
OUTPUT ${OUTPUT_AOT}
|
||||||
|
COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_FLAGS}
|
||||||
|
-o ${OUTPUT_AOT}
|
||||||
|
${BUILD_WASM}
|
||||||
|
COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_CHAIN_FLAGS}
|
||||||
|
-o ${OUTPUT_CHAIN_AOT}
|
||||||
|
${BUILD_WASM}
|
||||||
|
DEPENDS ${BUILD_WASM}
|
||||||
|
COMMENT "Compiling bulk memory AOT from copied WASM"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(compile_bulk_memory_aot ALL
|
||||||
|
DEPENDS ${OUTPUT_AOT}
|
||||||
|
)
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
||||||
|
(module
|
||||||
|
(memory 1)
|
||||||
|
|
||||||
|
(func $memory_fill_test (param $dst i32) (param $val i32) (param $len i32)
|
||||||
|
local.get $dst
|
||||||
|
local.get $val
|
||||||
|
local.get $len
|
||||||
|
memory.fill
|
||||||
|
)
|
||||||
|
|
||||||
|
(export "memory_fill_test" (func $memory_fill_test))
|
||||||
|
)
|
68
tests/unit/shared-heap/wasm-apps/memory64/CMakeLists.txt
Normal file
68
tests/unit/shared-heap/wasm-apps/memory64/CMakeLists.txt
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
project(wasm-apps-wasm64)
|
||||||
|
|
||||||
|
set(WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../..)
|
||||||
|
set(WAMRC_ROOT_DIR ${WAMR_ROOT_DIR}/wamr-compiler/build)
|
||||||
|
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR wasm64)
|
||||||
|
set(CMAKE_SYSROOT ${WAMR_ROOT_DIR}/wamr-sdk/app/libc-builtin-sysroot)
|
||||||
|
|
||||||
|
if (NOT DEFINED WASI_SDK_DIR)
|
||||||
|
set(WASI_SDK_DIR "/opt/wasi-sdk")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS "-nostdlib -pthread -Qunused-arguments")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -z stack-size=8192 -nostdlib -O0 --target=wasm64")
|
||||||
|
set(CMAKE_C_COMPILER_TARGET "wasm64")
|
||||||
|
set(CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang")
|
||||||
|
|
||||||
|
set(DEFINED_SYMBOLS
|
||||||
|
"${WAMR_ROOT_DIR}/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt")
|
||||||
|
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS
|
||||||
|
"-Wl,--no-entry \
|
||||||
|
-Wl,--initial-memory=65536 \
|
||||||
|
-Wl,--export-all \
|
||||||
|
-Wl,--allow-undefined"
|
||||||
|
)
|
||||||
|
|
||||||
|
set (WAMR_COMPILER_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-heap)
|
||||||
|
set (WAMR_COMPILER_CHAIN_FLAGS --opt-level=3 --bounds-checks=1 --enable-shared-chain)
|
||||||
|
|
||||||
|
function(copy_wasm TARGET_NAME)
|
||||||
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/../../
|
||||||
|
COMMENT "Copy ${TARGET_NAME} to the same directory of google test"
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(compile_and_copy_aot_from TARGET_NAME)
|
||||||
|
string(REPLACE ".wasm" ".aot" AOT_TARGET ${TARGET_NAME})
|
||||||
|
string(REPLACE ".wasm" "_chain.aot" AOT_CHAIN_TARGET ${TARGET_NAME})
|
||||||
|
|
||||||
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||||
|
COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_FLAGS}
|
||||||
|
-o ${AOT_TARGET}
|
||||||
|
${TARGET_NAME}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${AOT_TARGET}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/../../
|
||||||
|
COMMAND ${WAMRC_ROOT_DIR}/wamrc ${WAMR_COMPILER_CHAIN_FLAGS}
|
||||||
|
-o ${AOT_CHAIN_TARGET}
|
||||||
|
${TARGET_NAME}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${AOT_CHAIN_TARGET}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/../../
|
||||||
|
COMMENT "Compile and copy ${AOT_TARGET} ${AOT_CHAIN_TARGET} to the same directory of google test"
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
add_executable(test64.wasm ../test.c)
|
||||||
|
target_link_libraries(test64.wasm)
|
||||||
|
copy_wasm(test64.wasm)
|
||||||
|
compile_and_copy_aot_from(test64.wasm)
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#define NULL 0
|
||||||
|
|
||||||
extern void *
|
extern void *
|
||||||
shared_heap_malloc(int size);
|
shared_heap_malloc(int size);
|
||||||
|
|
|
@ -284,6 +284,7 @@ include (${IWASM_DIR}/interpreter/iwasm_interp.cmake)
|
||||||
include (${IWASM_DIR}/aot/iwasm_aot.cmake)
|
include (${IWASM_DIR}/aot/iwasm_aot.cmake)
|
||||||
include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
|
include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
|
||||||
include (${PROJECT_SOURCE_DIR}/../build-scripts/version.cmake)
|
include (${PROJECT_SOURCE_DIR}/../build-scripts/version.cmake)
|
||||||
|
include (${IWASM_DIR}/libraries/shared-heap/shared_heap.cmake)
|
||||||
|
|
||||||
if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
|
if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
|
||||||
include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake)
|
include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake)
|
||||||
|
@ -366,6 +367,7 @@ add_library (vmlib
|
||||||
${LIBC_WASI_SOURCE}
|
${LIBC_WASI_SOURCE}
|
||||||
${LIB_PTHREAD_SOURCE}
|
${LIB_PTHREAD_SOURCE}
|
||||||
${LIB_WASI_THREADS_SOURCE}
|
${LIB_WASI_THREADS_SOURCE}
|
||||||
|
${LIB_SHARED_HEAP_SOURCE}
|
||||||
${IWASM_COMMON_SOURCE}
|
${IWASM_COMMON_SOURCE}
|
||||||
${IWASM_INTERP_SOURCE}
|
${IWASM_INTERP_SOURCE}
|
||||||
${IWASM_AOT_SOURCE}
|
${IWASM_AOT_SOURCE}
|
||||||
|
|
|
@ -210,7 +210,9 @@ print_help()
|
||||||
printf(" --enable-linux-perf Enable linux perf support\n");
|
printf(" --enable-linux-perf Enable linux perf support\n");
|
||||||
#endif
|
#endif
|
||||||
printf(" --mllvm=<option> Add the LLVM command line option\n");
|
printf(" --mllvm=<option> Add the LLVM command line option\n");
|
||||||
printf(" --enable-shared-heap Enable shared heap feature\n");
|
printf(" --enable-shared-heap Enable shared heap feature, assuming only one shared heap will be attached\n");
|
||||||
|
printf(" --enable-shared-chain Enable shared heap chain feature, works for more than one shared heap\n");
|
||||||
|
printf(" WARNING: enable this feature will largely increase code size\n");
|
||||||
printf(" -v=n Set log verbose level (0 to 5, default is 2), larger with more log\n");
|
printf(" -v=n Set log verbose level (0 to 5, default is 2), larger with more log\n");
|
||||||
printf(" --version Show version information\n");
|
printf(" --version Show version information\n");
|
||||||
printf("Examples: wamrc -o test.aot test.wasm\n");
|
printf("Examples: wamrc -o test.aot test.wasm\n");
|
||||||
|
@ -658,6 +660,9 @@ main(int argc, char *argv[])
|
||||||
else if (!strcmp(argv[0], "--enable-shared-heap")) {
|
else if (!strcmp(argv[0], "--enable-shared-heap")) {
|
||||||
option.enable_shared_heap = true;
|
option.enable_shared_heap = true;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(argv[0], "--enable-shared-chain")) {
|
||||||
|
option.enable_shared_chain = true;
|
||||||
|
}
|
||||||
else if (!strcmp(argv[0], "--version")) {
|
else if (!strcmp(argv[0], "--version")) {
|
||||||
uint32 major, minor, patch;
|
uint32 major, minor, patch;
|
||||||
wasm_runtime_get_version(&major, &minor, &patch);
|
wasm_runtime_get_version(&major, &minor, &patch);
|
||||||
|
@ -720,6 +725,13 @@ main(int argc, char *argv[])
|
||||||
option.enable_ref_types = false;
|
option.enable_ref_types = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (option.enable_shared_chain) {
|
||||||
|
LOG_VERBOSE("Enable shared chain will overwrite shared heap and sw "
|
||||||
|
"bounds control");
|
||||||
|
option.enable_shared_heap = false;
|
||||||
|
option.bounds_checks = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!use_dummy_wasm) {
|
if (!use_dummy_wasm) {
|
||||||
wasm_file_name = argv[0];
|
wasm_file_name = argv[0];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user