From 504268b297ab88f2e17e34ab8958c6869a283aeb Mon Sep 17 00:00:00 2001 From: wenyongh Date: Fri, 31 May 2019 01:21:39 -0500 Subject: [PATCH] Implement memory.grow and limit heap space base offset to 1G (#36) * Implement memory profiler, optimize memory usage, modify code indent * Implement memory.grow and limit heap space base offset to 1G; modify iwasm build type to Release and 64 bit by default --- README.md | 2 +- core/iwasm/products/linux/CMakeLists.txt | 9 +- core/iwasm/products/linux/main.c | 41 ++-- core/iwasm/runtime/vmcore-wasm/wasm_interp.c | 65 +++--- core/iwasm/runtime/vmcore-wasm/wasm_loader.c | 24 ++- core/iwasm/runtime/vmcore-wasm/wasm_runtime.c | 186 +++++++++++------- core/iwasm/runtime/vmcore-wasm/wasm_runtime.h | 18 +- core/shared-lib/include/bh_memory.h | 6 + core/shared-lib/include/config.h | 9 + core/shared-lib/mem-alloc/bh_memory.c | 15 +- core/shared-lib/platform/linux/bh_thread.c | 2 +- 11 files changed, 237 insertions(+), 140 deletions(-) diff --git a/README.md b/README.md index 1fe9e8bf..2e855452 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,7 @@ cd iwasm/products/linux/bin You will get the following output: ``` Hello world! -buf ptr: 0x000101ac +buf ptr: 0x400002b0 buf: 1234 ``` If you would like to run the test app on Zephyr, we have embedded a test sample into its OS image. You will need to execute: diff --git a/core/iwasm/products/linux/CMakeLists.txt b/core/iwasm/products/linux/CMakeLists.txt index 72926661..a2510790 100644 --- a/core/iwasm/products/linux/CMakeLists.txt +++ b/core/iwasm/products/linux/CMakeLists.txt @@ -29,8 +29,8 @@ if (NOT ("$ENV{VALGRIND}" STREQUAL "YES")) add_definitions(-DNVALGRIND) endif () -# Currently build as 32-bit by default. -set (BUILD_AS_64BIT_SUPPORT "NO") +# Currently build as 64-bit by default. +set (BUILD_AS_64BIT_SUPPORT "YES") if (CMAKE_SIZEOF_VOID_P EQUAL 8) if (${BUILD_AS_64BIT_SUPPORT} STREQUAL "YES") @@ -44,6 +44,11 @@ else () endif () endif () +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif (NOT CMAKE_BUILD_TYPE) +message ("CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic") diff --git a/core/iwasm/products/linux/main.c b/core/iwasm/products/linux/main.c index 7a87d8b0..22fe692c 100644 --- a/core/iwasm/products/linux/main.c +++ b/core/iwasm/products/linux/main.c @@ -35,15 +35,14 @@ static int print_help() { wasm_printf("Usage: iwasm [-options] wasm_file [args...]\n"); wasm_printf("options:\n"); - wasm_printf(" -f|--function name Specify function name to run " - "in module rather than main\n"); + wasm_printf(" -f|--function name Specify function name to run in module\n" + " rather than main\n"); #if WASM_ENABLE_LOG != 0 - wasm_printf( - " -v=X Set log verbose level (0 to 2, default is 1), larger level with more log\n"); + wasm_printf(" -v=X Set log verbose level (0 to 2, default is 1),\n" + " larger level with more log\n"); #endif - wasm_printf( - " --repl Start a very simple REPL (read-eval-print-loop) mode \n" - " that runs commands in the form of `FUNC ARG...`\n"); + wasm_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" + " that runs commands in the form of `FUNC ARG...`\n"); return 1; } @@ -64,7 +63,7 @@ app_instance_func(wasm_module_inst_t module_inst, const char *func_name) const char *exception; wasm_application_execute_func(module_inst, func_name, app_argc - 1, - app_argv + 1); + app_argv + 1); if ((exception = wasm_runtime_get_exception(module_inst))) wasm_printf("%s\n", exception); return NULL; @@ -122,7 +121,7 @@ app_instance_repl(wasm_module_inst_t module_inst) } if (app_argc != 0) { wasm_application_execute_func(module_inst, app_argv[0], - app_argc - 1, app_argv + 1); + app_argc - 1, app_argv + 1); } free(app_argv); } @@ -177,7 +176,7 @@ int main(int argc, char *argv[]) app_argv = argv; if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { + != 0) { wasm_printf("Init global heap failed.\n"); return -1; } @@ -190,19 +189,22 @@ int main(int argc, char *argv[]) /* load WASM byte buffer from WASM bin file */ if (!(wasm_file_buf = (uint8*) wasm_read_file_to_buffer(wasm_file, - &wasm_file_size))) + &wasm_file_size))) goto fail2; /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, - error_buf, sizeof(error_buf)))) { + error_buf, sizeof(error_buf)))) { wasm_printf("%s\n", error_buf); goto fail3; } /* instantiate the module */ - if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, 8 * 1024, - 8 * 1024, error_buf, sizeof(error_buf)))) { + if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, + 16 * 1024, /* stack size */ + 8 * 1024, /* heap size */ + error_buf, + sizeof(error_buf)))) { wasm_printf("%s\n", error_buf); goto fail4; } @@ -217,21 +219,20 @@ int main(int argc, char *argv[]) /* destroy the module instance */ wasm_runtime_deinstantiate(wasm_module_inst); - fail4: +fail4: /* unload the module */ wasm_runtime_unload(wasm_module); - fail3: +fail3: /* free the file buffer */ wasm_free(wasm_file_buf); - fail2: +fail2: /* destroy runtime environment */ wasm_runtime_destroy(); - fail1: bh_memory_destroy(); - - (void) func_name; +fail1: + bh_memory_destroy(); return 0; } diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c b/core/iwasm/runtime/vmcore-wasm/wasm_interp.c index ab715a47..73163f32 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_interp.c @@ -74,26 +74,28 @@ GET_F64_FROM_ADDR (uint32 *addr) } #endif /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */ -#define is_valid_addr(memory, heap, addr) \ - (memory->base_addr <= addr && addr <= memory->end_addr) \ - #define CHECK_MEMORY_OVERFLOW() do { \ + uint32 offset1 = offset + addr; \ uint8 *maddr1; \ if (flags != 2) \ LOG_VERBOSE("unaligned load/store in wasm interp, flag is: %d.\n", flags);\ - if (offset + addr < addr) { \ - wasm_runtime_set_exception(module, "out of bounds memory access"); \ - goto got_exception; \ + if (offset1 < offset) \ + goto out_of_bounds; \ + if (offset1 < heap_base_offset) { \ + maddr = memory->memory_data + offset1; \ + if (maddr < memory->base_addr) \ + goto out_of_bounds; \ + maddr1 = maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD]; \ + if (maddr1 > memory->end_addr) \ + goto out_of_bounds; \ } \ - maddr = memory->memory_data + (offset + addr); \ - if (!is_valid_addr(memory, NULL, maddr)) { \ - wasm_runtime_set_exception(module, "out of bounds memory access"); \ - goto got_exception; \ - } \ - maddr1 = maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD]; \ - if (!is_valid_addr(memory, NULL, maddr1)) { \ - wasm_runtime_set_exception(module, "out of bounds memory access"); \ - goto got_exception; \ + else { \ + maddr = memory->heap_data + offset1 - memory->heap_base_offset; \ + if (maddr < memory->heap_data) \ + goto out_of_bounds; \ + maddr1 = maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD]; \ + if (maddr1 > memory->heap_data_end) \ + goto out_of_bounds; \ } \ } while (0) @@ -712,6 +714,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, { WASMModuleInstance *module = self->module_inst; WASMMemoryInstance *memory = module->default_memory; + int32 heap_base_offset = memory ? memory->heap_base_offset : 0; WASMTableInstance *table = module->default_table; uint8 opcode_IMPDEP2 = WASM_OP_IMPDEP2; WASMInterpFrame *frame = NULL; @@ -1247,26 +1250,25 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP (WASM_OP_MEMORY_GROW): { - uint32 reserved, prev_page_count, delta, tmp; + uint32 reserved, delta, prev_page_count = memory->cur_page_count; read_leb_uint32(frame_ip, frame_ip_end, reserved); - prev_page_count = memory->cur_page_count; delta = POP_I32(); - PUSH_I32(prev_page_count); - if (delta == 0) - HANDLE_OP_END (); - else if (delta + prev_page_count > memory->max_page_count || - delta + prev_page_count < prev_page_count) { - tmp = POP_I32(); + + if (!wasm_runtime_enlarge_memory(module, delta)) { + /* fail to memory.grow, return -1 */ PUSH_I32(-1); - (void)tmp; - HANDLE_OP_END (); + if (wasm_runtime_get_exception(module)) { + printf("%s\n", wasm_runtime_get_exception(module)); + wasm_runtime_set_exception(module, NULL); + } + } + else { + /* success, return previous page count */ + PUSH_I32(prev_page_count); + /* update the memory instance ptr */ + memory = module->default_memory; } - - if (!wasm_runtime_enlarge_memory(module, delta)) - goto got_exception; - - memory = module->default_memory; (void)reserved; HANDLE_OP_END (); @@ -2093,6 +2095,9 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP_END (); } + out_of_bounds: + wasm_runtime_set_exception(module, "out of bounds memory access"); + got_exception: if (depths && depths != depth_buf) { wasm_free(depths); diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_loader.c b/core/iwasm/runtime/vmcore-wasm/wasm_loader.c index 1af9278e..c03ddc3a 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_loader.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_loader.c @@ -314,14 +314,20 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; + uint32 pool_size = bh_memory_pool_size(); + uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT + / NumBytesPerPage; read_leb_uint32(p, p_end, memory->flags); read_leb_uint32(p, p_end, memory->init_page_count); - if (memory->flags & 1) + if (memory->flags & 1) { read_leb_uint32(p, p_end, memory->max_page_count); + if (memory->max_page_count > max_page_count) + memory->max_page_count = max_page_count; + } else - /* Limit the maximum memory size to 4GB */ - memory->max_page_count = 0x10000; + /* Limit the maximum memory size to max_page_count */ + memory->max_page_count = max_page_count; *p_buf = p; return true; @@ -351,14 +357,20 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory, char *error_buf, uint32 error_buf_size) { const uint8 *p = *p_buf, *p_end = buf_end; + uint32 pool_size = bh_memory_pool_size(); + uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT + / NumBytesPerPage; read_leb_uint32(p, p_end, memory->flags); read_leb_uint32(p, p_end, memory->init_page_count); - if (memory->flags & 1) + if (memory->flags & 1) { read_leb_uint32(p, p_end, memory->max_page_count); + if (memory->max_page_count > max_page_count) + memory->max_page_count = max_page_count; + } else - /* Limit the maximum memory size to 4GB */ - memory->max_page_count = 0x10000; + /* Limit the maximum memory size to max_page_count */ + memory->max_page_count = max_page_count; *p_buf = p; return true; diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c index b12256d3..ebfe14b5 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c @@ -163,6 +163,7 @@ memories_deinstantiate(WASMMemoryInstance **memories, uint32 count) if (memories[i]) { if (memories[i]->heap_handle) mem_allocator_destroy(memories[i]->heap_handle); + wasm_free(memories[i]->heap_data); wasm_free(memories[i]); } wasm_free(memories); @@ -177,10 +178,10 @@ memory_instantiate(uint32 init_page_count, uint32 max_page_count, { WASMMemoryInstance *memory; uint32 total_size = offsetof(WASMMemoryInstance, base_addr) + - NumBytesPerPage * init_page_count + - addr_data_size + global_data_size + - heap_size; + NumBytesPerPage * init_page_count + + addr_data_size + global_data_size; + /* Allocate memory space, addr data and global data */ if (!(memory = wasm_malloc(total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate memory failed: allocate memory failed."); @@ -190,28 +191,46 @@ memory_instantiate(uint32 init_page_count, uint32 max_page_count, memset(memory, 0, total_size); memory->cur_page_count = init_page_count; memory->max_page_count = max_page_count; + memory->addr_data = memory->base_addr; memory->addr_data_size = addr_data_size; memory->memory_data = memory->addr_data + addr_data_size; - memory->heap_data = memory->memory_data + - NumBytesPerPage * memory->cur_page_count;; - memory->heap_data_size = heap_size; - - memory->global_data = memory->heap_data + memory->heap_data_size; + memory->global_data = memory->memory_data + + NumBytesPerPage * memory->cur_page_count;; memory->global_data_size = global_data_size; memory->end_addr = memory->global_data + global_data_size; + /* Allocate heap space */ + if (!(memory->heap_data = wasm_malloc(heap_size))) { + set_error_buf(error_buf, error_buf_size, + "Instantiate memory failed: allocate memory failed."); + goto fail1; + } + memory->heap_data_end = memory->heap_data + heap_size; + /* Initialize heap */ if (!(memory->heap_handle = mem_allocator_create - (memory->heap_data, memory->heap_data_size))) { - wasm_free(memory); - return NULL; + (memory->heap_data, heap_size))) { + goto fail2; } +#if WASM_ENABLE_MEMORY_GROW != 0 + memory->heap_base_offset = DEFAULT_APP_HEAP_BASE_OFFSET; +#else + memory->heap_base_offset = memory->end_addr - memory->memory_data; +#endif + return memory; + +fail2: + wasm_free(memory->heap_data); + +fail1: + wasm_free(memory); + return NULL; } /** @@ -975,58 +994,65 @@ wasm_runtime_deinstantiate(WASMModuleInstance *module_inst) bool wasm_runtime_enlarge_memory(WASMModuleInstance *module, int inc_page_count) { -#if 1 - wasm_runtime_set_exception(module, "unsupported operation: enlarge memory."); - return false; -#else +#if WASM_ENABLE_MEMORY_GROW != 0 WASMMemoryInstance *memory = module->default_memory; WASMMemoryInstance *new_memory; uint32 total_page_count = inc_page_count + memory->cur_page_count; uint32 total_size = offsetof(WASMMemoryInstance, base_addr) + memory->addr_data_size + NumBytesPerPage * total_page_count + - memory->global_data_size + - memory->thunk_argv_data_size + - sizeof(uint32) * memory->thunk_argc; + memory->global_data_size; + + if (inc_page_count <= 0) + /* No need to enlarge memory */ + return true; + + if (total_page_count < memory->cur_page_count /* integer overflow */ + || total_page_count > memory->max_page_count) { + wasm_runtime_set_exception(module, "fail to enlarge memory."); + return false; + } if (!(new_memory = wasm_malloc(total_size))) { - wasm_runtime_set_exception(module, "alloc memory for enlarge memory failed."); + wasm_runtime_set_exception(module, "fail to enlarge memory."); return false; } new_memory->cur_page_count = total_page_count; - new_memory->max_page_count = memory->max_page_count > total_page_count - ? memory->max_page_count : total_page_count; + new_memory->max_page_count = memory->max_page_count; + new_memory->addr_data = new_memory->base_addr; new_memory->addr_data_size = memory->addr_data_size; - new_memory->thunk_argv_data = new_memory->addr_data + memory->addr_data_size; - new_memory->thunk_argv_data_size = memory->thunk_argv_data_size; - new_memory->thunk_argc = memory->thunk_argc; - new_memory->thunk_argv_offsets = new_memory->thunk_argv_data + - memory->thunk_argv_data_size; + new_memory->memory_data = new_memory->addr_data + new_memory->addr_data_size; - new_memory->memory_data = new_memory->thunk_argv_offsets + - sizeof(uint32) * memory->thunk_argc; new_memory->global_data = new_memory->memory_data + - NumBytesPerPage * new_memory->cur_page_count; + NumBytesPerPage * total_page_count; new_memory->global_data_size = memory->global_data_size; new_memory->end_addr = new_memory->global_data + memory->global_data_size; - /* Copy addr data, thunk argv data, thunk argv offsets and memory data */ + /* Copy addr data and memory data */ memcpy(new_memory->addr_data, memory->addr_data, memory->global_data - memory->addr_data); /* Copy global data */ memcpy(new_memory->global_data, memory->global_data, - memory->end_addr - memory->global_data); + memory->global_data_size); /* Init free space of new memory */ memset(new_memory->memory_data + NumBytesPerPage * memory->cur_page_count, - 0, NumBytesPerPage * (total_page_count - memory->cur_page_count)); + 0, NumBytesPerPage * (total_page_count - memory->cur_page_count)); + + new_memory->heap_data = memory->heap_data; + new_memory->heap_data_end = memory->heap_data_end; + new_memory->heap_handle = memory->heap_handle; + new_memory->heap_base_offset = memory->heap_base_offset; - wasm_free(memory); module->memories[0] = module->default_memory = new_memory; + wasm_free(memory); return true; +#else + wasm_runtime_set_exception(module, "unsupported operation: enlarge memory."); + return false; #endif } @@ -1098,29 +1124,29 @@ wasm_runtime_get_current_module_inst() int32 wasm_runtime_module_malloc(WASMModuleInstance *module_inst, uint32 size) { - uint8 *memory_base = module_inst->default_memory->memory_data; - void *heap = module_inst->default_memory->heap_handle; - uint8 *addr = mem_allocator_malloc(heap, size); - if (!addr) + WASMMemoryInstance *memory = module_inst->default_memory; + uint8 *addr = mem_allocator_malloc(memory->heap_handle, size); + if (!addr) { wasm_runtime_set_exception(module_inst, "out of memory"); - return addr ? addr - memory_base : 0; + return 0; + } + return memory->heap_base_offset + (addr - memory->heap_data); } void wasm_runtime_module_free(WASMModuleInstance *module_inst, int32 ptr) { - uint8 *memory_base = module_inst->default_memory->memory_data; - uint8 *heap_base = module_inst->default_memory->heap_data; - uint32 heap_size = module_inst->default_memory->heap_data_size; - void *heap = module_inst->default_memory->heap_handle; - uint8 *addr = ptr ? memory_base + ptr : NULL; - if (addr && (heap_base < addr && addr < heap_base + heap_size)) - mem_allocator_free(heap, addr); + if (ptr) { + WASMMemoryInstance *memory = module_inst->default_memory; + uint8 *addr = memory->heap_data + (ptr - memory->heap_base_offset); + if (memory->heap_data < addr && addr < memory->heap_data_end) + mem_allocator_free(memory->heap_handle, addr); + } } - int32 +int32 wasm_runtime_module_dup_data(WASMModuleInstance *module_inst, - const char *src, uint32 size) + const char *src, uint32 size) { int32 buffer_offset = wasm_runtime_module_malloc(module_inst, size); if (buffer_offset != 0) { @@ -1135,22 +1161,32 @@ bool wasm_runtime_validate_app_addr(WASMModuleInstance *module_inst, int32 app_offset, uint32 size) { + WASMMemoryInstance *memory; + uint8 *addr; + /* integer overflow check */ if(app_offset < 0 || - app_offset + size < size) { - wasm_runtime_set_exception(module_inst, "out of bounds memory access"); - return false; + app_offset + size < app_offset) { + goto fail; } - uint8 *memory_base = module_inst->default_memory->memory_data; - uint8 *addr = memory_base + app_offset; - uint8 *base_addr = module_inst->default_memory->base_addr; - uint8 *end_addr = module_inst->default_memory->end_addr; - bool ret = (base_addr <= addr - && addr + size <= end_addr); - if (!ret) - wasm_runtime_set_exception(module_inst, "out of bounds memory access"); - return ret; + memory = module_inst->default_memory; + if (app_offset < memory->heap_base_offset) { + addr = memory->memory_data + app_offset; + if (!(memory->base_addr <= addr && addr + size <= memory->end_addr)) + goto fail; + return true; + } + else { + addr = memory->heap_data + (app_offset - memory->heap_base_offset); + if (!(memory->heap_data <= addr && addr + size <= memory->heap_data_end)) + goto fail; + return true; + } + +fail: + wasm_runtime_set_exception(module_inst, "out of bounds memory access"); + return false; } bool @@ -1158,26 +1194,42 @@ wasm_runtime_validate_native_addr(WASMModuleInstance *module_inst, void *native_ptr, uint32 size) { uint8 *addr = native_ptr; - uint8 *base_addr = module_inst->default_memory->base_addr; - uint8 *end_addr = module_inst->default_memory->end_addr; - bool ret = (base_addr <= addr && addr + size <= end_addr); - if (!ret || (addr + size < addr)/* integer overflow */) - wasm_runtime_set_exception(module_inst, "out of bounds memory access"); - return ret; + WASMMemoryInstance *memory = module_inst->default_memory; + + if (addr + size < addr) { + goto fail; + } + + if ((memory->base_addr <= addr && addr + size <= memory->end_addr) + || (memory->heap_data <= addr && addr + size <= memory->heap_data_end)) + return true; + +fail: + wasm_runtime_set_exception(module_inst, "out of bounds memory access"); + return false; } void * wasm_runtime_addr_app_to_native(WASMModuleInstance *module_inst, int32 app_offset) { - return module_inst->default_memory->memory_data + app_offset; + WASMMemoryInstance *memory = module_inst->default_memory; + if (app_offset < memory->heap_base_offset) + return memory->memory_data + app_offset; + else + return memory->heap_data + (app_offset - memory->heap_base_offset); } int32 wasm_runtime_addr_native_to_app(WASMModuleInstance *module_inst, void *native_ptr) { - return (uint8*)native_ptr - module_inst->default_memory->memory_data; + WASMMemoryInstance *memory = module_inst->default_memory; + if ((uint8*)native_ptr < memory->heap_data) + return (uint8*)native_ptr - memory->memory_data; + else + return memory->heap_base_offset + + ((uint8*)native_ptr - memory->heap_data); } uint32 diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h index 649f8308..56e806b9 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h +++ b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h @@ -37,20 +37,14 @@ typedef struct WASMMemoryInstance { /* Size of addr_data */ uint32 addr_data_size; - /* Thunk data of argument strings */ - uint8 *thunk_argv_data; - uint32 thunk_argv_data_size; - /* Thunk argument count */ - uint32 thunk_argc; - /* Thunk argument offsets */ - uint8 *thunk_argv_offsets; - - /* Heap data */ + /* Heap data base address */ uint8 *heap_data; - /* Heap size */ - uint32 heap_data_size; + /* Heap data end address */ + uint8 *heap_data_end; /* The heap created */ void *heap_handle; + /* Heap base offset of wasm app */ + int32 heap_base_offset; /* Memory data */ uint8 *memory_data; @@ -63,7 +57,7 @@ typedef struct WASMMemoryInstance { /* Base address, the layout is: addr_data + thunk_argv data + thunk arg offsets + - heap data + memory data + global data + memory data + global data memory data init size is: NumBytesPerPage * cur_page_count addr data size and global data size is calculated in module instantiating Note: when memory is re-allocated, the addr data, thunk argv data, thunk diff --git a/core/shared-lib/include/bh_memory.h b/core/shared-lib/include/bh_memory.h index 51312cbf..352137a3 100644 --- a/core/shared-lib/include/bh_memory.h +++ b/core/shared-lib/include/bh_memory.h @@ -52,6 +52,12 @@ int bh_memory_init_with_allocator(void *malloc_func, void *free_func); */ void bh_memory_destroy(); +/** + * Get the pool size of memory, if memory is initialized with allocator, + * return 1GB by default. + */ +int bh_memory_pool_size(); + #if BEIHAI_ENABLE_MEMORY_PROFILING == 0 /** diff --git a/core/shared-lib/include/config.h b/core/shared-lib/include/config.h index e1926a4b..0c270cbc 100644 --- a/core/shared-lib/include/config.h +++ b/core/shared-lib/include/config.h @@ -80,6 +80,15 @@ #define WORKING_FLOW_HEAP_SIZE 0 */ +/* Support memory.grow opcode and enlargeMemory function */ +#define WASM_ENABLE_MEMORY_GROW 1 + +/* The max percentage of global heap that app memory space can grow */ +#define APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT 1 / 3 + +/* Default base offset of app heap space */ +#define DEFAULT_APP_HEAP_BASE_OFFSET (1 * BH_GB) + /* Default min/max heap size of each app */ #define APP_HEAP_SIZE_DEFAULT (8 * 1024) #define APP_HEAP_SIZE_MIN (2 * 1024) diff --git a/core/shared-lib/mem-alloc/bh_memory.c b/core/shared-lib/mem-alloc/bh_memory.c index 92b1fdd4..bca69705 100644 --- a/core/shared-lib/mem-alloc/bh_memory.c +++ b/core/shared-lib/mem-alloc/bh_memory.c @@ -49,7 +49,9 @@ static korp_mutex profile_lock; #ifndef MALLOC_MEMORY_FROM_SYSTEM typedef enum Memory_Mode { - MEMORY_MODE_UNKNOWN = 0, MEMORY_MODE_POOL, MEMORY_MODE_ALLOCATOR + MEMORY_MODE_UNKNOWN = 0, + MEMORY_MODE_POOL, + MEMORY_MODE_ALLOCATOR } Memory_Mode; static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN; @@ -59,6 +61,8 @@ static mem_allocator_t pool_allocator = NULL; static void *(*malloc_func)(unsigned int size) = NULL; static void (*free_func)(void *ptr) = NULL; +static unsigned int global_pool_size; + int bh_memory_init_with_pool(void *mem, unsigned int bytes) { mem_allocator_t _allocator = mem_allocator_create(mem, bytes); @@ -69,6 +73,7 @@ int bh_memory_init_with_pool(void *mem, unsigned int bytes) #if BEIHAI_ENABLE_MEMORY_PROFILING != 0 vm_mutex_init(&profile_lock); #endif + global_pool_size = bytes; return 0; } printf("Init memory with pool (%p, %u) failed.\n", mem, bytes); @@ -101,6 +106,14 @@ void bh_memory_destroy() memory_mode = MEMORY_MODE_UNKNOWN; } +int bh_memory_pool_size() +{ + if (memory_mode == MEMORY_MODE_POOL) + return global_pool_size; + else + return 1 * BH_GB; +} + void* bh_malloc_internal(unsigned int size) { if (memory_mode == MEMORY_MODE_UNKNOWN) { diff --git a/core/shared-lib/platform/linux/bh_thread.c b/core/shared-lib/platform/linux/bh_thread.c index 201c9b5e..d2cdd087 100755 --- a/core/shared-lib/platform/linux/bh_thread.c +++ b/core/shared-lib/platform/linux/bh_thread.c @@ -75,7 +75,7 @@ static void *vm_thread_wrapper(void *arg) { thread_wrapper_arg * targ = arg; LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ); - targ->stack = (void *) ((unsigned int) (&arg) & ~0xfff); + targ->stack = (void *)((uintptr_t)(&arg) & ~0xfff); _vm_tls_put(1, targ); targ->start(targ->arg); bh_free(targ);