From 7863f3758267f7e6632468ffd6bb08ba47448c94 Mon Sep 17 00:00:00 2001 From: wenyongh Date: Tue, 27 Aug 2019 14:09:23 +0800 Subject: [PATCH] Refine binary size and fix several minor issues (#104) * 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 * Add a new extension library: connection * Fix bug of reading magic number and version in big endian platform * Re-org platform APIs: move most platform APIs from iwasm to shared-lib * Enhance wasm loader to fix some security issues * Fix issue about illegal load of EXC_RETURN into PC on stm32 board * Updates that let a restricted version of the interpreter run in SGX * Enable native/app address validation and conversion for wasm app * Remove wasm_application_exectue_* APIs from wasm_export.h which makes confused * Refine binary size and fix several minor issues Optimize interpreter LOAD/STORE opcodes to decrease the binary size Fix issues when using iwasm library: _bh_log undefined, bh_memory.h not found Remove unused _stdin/_stdout/_stderr global variables resolve in libc wrapper Add macros of global heap size, stack size, heap size for Zephyr main.c Clear compile warning of wasm_application.c --- core/iwasm/lib/native/libc/libc_wrapper.c | 17 -- core/iwasm/products/linux/CMakeLists.txt | 7 +- core/iwasm/products/zephyr/simple/src/main.c | 31 +-- core/iwasm/runtime/include/bh_memory.h | 110 ++++++++++ .../runtime/vmcore-wasm/wasm_application.c | 7 +- core/iwasm/runtime/vmcore-wasm/wasm_interp.c | 192 ++++++++++++------ core/iwasm/runtime/vmcore-wasm/wasm_runtime.c | 17 +- 7 files changed, 274 insertions(+), 107 deletions(-) create mode 100644 core/iwasm/runtime/include/bh_memory.h diff --git a/core/iwasm/lib/native/libc/libc_wrapper.c b/core/iwasm/lib/native/libc/libc_wrapper.c index 74b2c0ccb8..d443888cf6 100644 --- a/core/iwasm/lib/native/libc/libc_wrapper.c +++ b/core/iwasm/lib/native/libc/libc_wrapper.c @@ -984,23 +984,6 @@ wasm_native_global_lookup(const char *module_name, const char *global_name, global_def++; } - /* Lookup non-constant globals which cannot be defined by table */ - if (!strcmp(module_name, "env")) { - if (!strcmp(global_name, "_stdin")) { - global->global_data_linked.addr = (uintptr_t)stdin; - global->is_addr = true; - return true; - } else if (!strcmp(global_name, "_stdout")) { - global->global_data_linked.addr = (uintptr_t)stdout; - global->is_addr = true; - return true; - } else if (!strcmp(global_name, "_stderr")) { - global->global_data_linked.addr = (uintptr_t)stderr; - global->is_addr = true; - return true; - } - } - return false; } diff --git a/core/iwasm/products/linux/CMakeLists.txt b/core/iwasm/products/linux/CMakeLists.txt index a2510790e4..6e89367075 100644 --- a/core/iwasm/products/linux/CMakeLists.txt +++ b/core/iwasm/products/linux/CMakeLists.txt @@ -68,6 +68,7 @@ include (../../lib/native/base/wasm_lib_base.cmake) include (../../lib/native/libc/wasm_libc.cmake) include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) include (${SHARED_LIB_DIR}/mem-alloc/mem_alloc.cmake) +include (${SHARED_LIB_DIR}/utils/shared_utils.cmake) add_library (vmlib ${WASM_PLATFORM_LIB_SOURCE} @@ -76,7 +77,8 @@ add_library (vmlib ${WASM_LIB_BASE_DIR}/base_lib_export.c ${WASM_LIBC_SOURCE} ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE}) + ${MEM_ALLOC_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE}) add_executable (iwasm main.c ext_lib_export.c) @@ -91,7 +93,8 @@ add_library (libiwasm SHARED ${WASM_LIB_BASE_DIR}/base_lib_export.c ${WASM_LIBC_SOURCE} ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE}) + ${MEM_ALLOC_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE}) install (TARGETS libiwasm DESTINATION lib) diff --git a/core/iwasm/products/zephyr/simple/src/main.c b/core/iwasm/products/zephyr/simple/src/main.c index fee58f9def..da85a3bba4 100644 --- a/core/iwasm/products/zephyr/simple/src/main.c +++ b/core/iwasm/products/zephyr/simple/src/main.c @@ -26,6 +26,11 @@ #include "bh_memory.h" #include "test_wasm.h" +#define CONFIG_GLOBAL_HEAP_BUF_SIZE 131072 +#define CONFIG_APP_STACK_SIZE 8192 +#define CONFIG_APP_HEAP_SIZE 8192 +#define CONFIG_MAIN_THREAD_STACK_SIZE 4096 + static int app_argc; static char **app_argv; @@ -54,7 +59,7 @@ app_instance_main(wasm_module_inst_t module_inst) return NULL; } -static char global_heap_buf[512 * 1024] = { 0 }; +static char global_heap_buf[CONFIG_GLOBAL_HEAP_BUF_SIZE] = { 0 }; void iwasm_main(void *arg1, void *arg2, void *arg3) { @@ -72,7 +77,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) (void) arg3; if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) - != 0) { + != 0) { wasm_printf("Init global heap failed.\n"); return; } @@ -91,14 +96,17 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) /* 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 fail2; } /* 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, + CONFIG_APP_STACK_SIZE, + CONFIG_APP_HEAP_SIZE, + error_buf, + sizeof(error_buf)))) { wasm_printf("%s\n", error_buf); goto fail3; } @@ -119,24 +127,23 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) fail1: bh_memory_destroy(); } -#define DEFAULT_THREAD_STACKSIZE (6 * 1024) -#define DEFAULT_THREAD_PRIORITY 5 +#define MAIN_THREAD_STACK_SIZE (CONFIG_MAIN_THREAD_STACK_SIZE) +#define MAIN_THREAD_PRIORITY 5 -K_THREAD_STACK_DEFINE(iwasm_main_thread_stack, DEFAULT_THREAD_STACKSIZE); +K_THREAD_STACK_DEFINE(iwasm_main_thread_stack, MAIN_THREAD_STACK_SIZE); static struct k_thread iwasm_main_thread; bool iwasm_init(void) { k_tid_t tid = k_thread_create(&iwasm_main_thread, iwasm_main_thread_stack, - DEFAULT_THREAD_STACKSIZE, iwasm_main, NULL, NULL, NULL, - DEFAULT_THREAD_PRIORITY, 0, K_NO_WAIT); + MAIN_THREAD_STACK_SIZE, + iwasm_main, NULL, NULL, NULL, + MAIN_THREAD_PRIORITY, 0, K_NO_WAIT); return tid ? true : false; } -#ifndef CONFIG_AEE_ENABLE void main(void) { iwasm_init(); } -#endif diff --git a/core/iwasm/runtime/include/bh_memory.h b/core/iwasm/runtime/include/bh_memory.h new file mode 100644 index 0000000000..352137a347 --- /dev/null +++ b/core/iwasm/runtime/include/bh_memory.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _BH_MEMORY_H +#define _BH_MEMORY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define BH_KB (1024) +#define BH_MB ((BH_KB)*1024) +#define BH_GB ((BH_MB)*1024) + +/** + * Initialize memory allocator with a pool, the bh_malloc/bh_free function + * will malloc/free memory from the pool + * + * @param mem the pool buffer + * @param bytes the size bytes of the buffer + * + * @return 0 if success, -1 otherwise + */ +int bh_memory_init_with_pool(void *mem, unsigned int bytes); + +/** + * Initialize memory allocator with memory allocator, the bh_malloc/bh_free + * function will malloc/free memory with the allocator passed + * + * @param malloc_func the malloc function + * @param free_func the free function + * + * @return 0 if success, -1 otherwise + */ +int bh_memory_init_with_allocator(void *malloc_func, void *free_func); + +/** + * Destroy memory + */ +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 + +/** + * This function allocates a memory chunk from system + * + * @param size bytes need allocate + * + * @return the pointer to memory allocated + */ +void* bh_malloc(unsigned int size); + +/** + * This function frees memory chunk + * + * @param ptr the pointer to memory need free + */ +void bh_free(void *ptr); + +#else + +void* bh_malloc_profile(const char *file, int line, const char *func, unsigned int size); +void bh_free_profile(const char *file, int line, const char *func, void *ptr); + +#define bh_malloc(size) bh_malloc_profile(__FILE__, __LINE__, __func__, size) +#define bh_free(ptr) bh_free_profile(__FILE__, __LINE__, __func__, ptr) + +/** + * Print current memory profiling data + * + * @param file file name of the caller + * @param line line of the file of the caller + * @param func function name of the caller + */ +void memory_profile_print(const char *file, int line, const char *func, int alloc); + +/** + * Summarize memory usage and print it out + * Can use awk to analyze the output like below: + * awk -F: '{print $2,$4,$6,$8,$9}' OFS="\t" ./out.txt | sort -n -r -k 1 + */ +void memory_usage_summarize(); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef _BH_MEMORY_H */ + diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_application.c b/core/iwasm/runtime/vmcore-wasm/wasm_application.c index 5073ef2e37..cdcb568093 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_application.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_application.c @@ -293,10 +293,15 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, break; case VALUE_TYPE_I64: { + char buf[16]; union { uint64 val; uint32 parts[2]; } u; u.parts[0] = argv1[0]; u.parts[1] = argv1[1]; - wasm_printf("0x%llx:i64", u.val); + if (sizeof(long) == 4) + snprintf(buf, sizeof(buf), "%s", "0x%llx:i64"); + else + snprintf(buf, sizeof(buf), "%s", "0x%lx:i64"); + wasm_printf(buf, u.val); break; } case VALUE_TYPE_F32: diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c b/core/iwasm/runtime/vmcore-wasm/wasm_interp.c index f0b0beba4f..04cf744008 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_interp.c @@ -753,7 +753,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, uint32 i, depth, cond, count, fidx, tidx, frame_size = 0, all_cell_num = 0; int32 didx, val; uint8 *else_addr, *end_addr; - uint8 *maddr; + uint8 *maddr = NULL; #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op @@ -1148,70 +1148,98 @@ wasm_interp_call_func_bytecode(WASMThread *self, /* memory load instructions */ HANDLE_OP (WASM_OP_I32_LOAD): - DEF_OP_LOAD(PUSH_I32(*(int32*)maddr)); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I64_LOAD): - DEF_OP_LOAD(PUSH_I64(GET_I64_FROM_ADDR((uint32*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_F32_LOAD): - DEF_OP_LOAD(PUSH_F32(*(float32*)maddr)); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_F64_LOAD): - DEF_OP_LOAD(PUSH_F64(GET_F64_FROM_ADDR((uint32*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I32_LOAD8_S): - DEF_OP_LOAD(PUSH_I32(sign_ext_8_32(*(int8*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I32_LOAD8_U): - DEF_OP_LOAD(PUSH_I32((uint32)(*(uint8*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I32_LOAD16_S): - DEF_OP_LOAD(PUSH_I32(sign_ext_16_32(*(int16*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I32_LOAD16_U): - DEF_OP_LOAD(PUSH_I32((uint32)(*(uint16*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I64_LOAD8_S): - DEF_OP_LOAD(PUSH_I64(sign_ext_8_64(*(int8*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I64_LOAD8_U): - DEF_OP_LOAD(PUSH_I64((uint64)(*(uint8*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I64_LOAD16_S): - DEF_OP_LOAD(PUSH_I64(sign_ext_16_64(*(int16*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I64_LOAD16_U): - DEF_OP_LOAD(PUSH_I64((uint64)(*(uint16*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I64_LOAD32_S): - DEF_OP_LOAD(PUSH_I64(sign_ext_32_64(*(int32*)maddr))); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I64_LOAD32_U): - DEF_OP_LOAD(PUSH_I64((uint64)(*(uint32*)maddr))); - HANDLE_OP_END (); + { + uint32 offset, flags, addr; + GET_OPCODE(); + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(); +#if WASM_ENABLE_LABELS_AS_VALUES != 0 + static const void *handle_load_table[] = { + &&HANDLE_LOAD_WASM_OP_I32_LOAD, + &&HANDLE_LOAD_WASM_OP_I64_LOAD, + &&HANDLE_LOAD_WASM_OP_F32_LOAD, + &&HANDLE_LOAD_WASM_OP_F64_LOAD, + &&HANDLE_LOAD_WASM_OP_I32_LOAD8_S, + &&HANDLE_LOAD_WASM_OP_I32_LOAD8_U, + &&HANDLE_LOAD_WASM_OP_I32_LOAD16_S, + &&HANDLE_LOAD_WASM_OP_I32_LOAD16_U, + &&HANDLE_LOAD_WASM_OP_I64_LOAD8_S, + &&HANDLE_LOAD_WASM_OP_I64_LOAD8_U, + &&HANDLE_LOAD_WASM_OP_I64_LOAD16_S, + &&HANDLE_LOAD_WASM_OP_I64_LOAD16_U, + &&HANDLE_LOAD_WASM_OP_I64_LOAD32_S, + &&HANDLE_LOAD_WASM_OP_I64_LOAD32_U + }; + #define HANDLE_OP_LOAD(opcode) HANDLE_LOAD_##opcode + goto *handle_load_table[opcode - WASM_OP_I32_LOAD]; +#else + #define HANDLE_OP_LOAD(opcode) case opcode + switch (opcode) +#endif + { + HANDLE_OP_LOAD(WASM_OP_I32_LOAD): + PUSH_I32(*(int32*)maddr); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD): + PUSH_I64(GET_I64_FROM_ADDR((uint32*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_F32_LOAD): + PUSH_F32(*(float32*)maddr); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_F64_LOAD): + PUSH_F64(GET_F64_FROM_ADDR((uint32*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I32_LOAD8_S): + PUSH_I32(sign_ext_8_32(*(int8*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I32_LOAD8_U): + PUSH_I32((uint32)(*(uint8*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I32_LOAD16_S): + PUSH_I32(sign_ext_16_32(*(int16*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I32_LOAD16_U): + PUSH_I32((uint32)(*(uint16*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD8_S): + PUSH_I64(sign_ext_8_64(*(int8*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD8_U): + PUSH_I64((uint64)(*(uint8*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD16_S): + PUSH_I64(sign_ext_16_64(*(int16*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD16_U): + PUSH_I64((uint64)(*(uint16*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD32_S): + PUSH_I64(sign_ext_32_64(*(int32*)maddr)); + HANDLE_OP_END(); + HANDLE_OP_LOAD(WASM_OP_I64_LOAD32_U): + PUSH_I64((uint64)(*(uint32*)maddr)); + HANDLE_OP_END(); + } + (void)flags; + HANDLE_OP_END (); + } /* memory store instructions */ - HANDLE_OP (WASM_OP_I32_STORE): - DEF_OP_STORE(uint32, I32, *(int32*)maddr = sval); - HANDLE_OP_END (); - - HANDLE_OP (WASM_OP_I64_STORE): - DEF_OP_STORE(uint64, I64, PUT_I64_TO_ADDR((uint32*)maddr, sval)); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_F32_STORE): { uint32 offset, flags, addr; @@ -1241,25 +1269,63 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP_END (); } + HANDLE_OP (WASM_OP_I32_STORE): HANDLE_OP (WASM_OP_I32_STORE8): - DEF_OP_STORE(uint32, I32, *(uint8*)maddr = (uint8)sval); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I32_STORE16): - DEF_OP_STORE(uint32, I32, *(uint16*)maddr = (uint16)sval); - HANDLE_OP_END (); + { + uint32 offset, flags, addr; + uint32 sval; + GET_OPCODE(); + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + sval = POP_I32(); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(); + switch (opcode) { + case WASM_OP_I32_STORE: + *(int32*)maddr = sval; + break; + case WASM_OP_I32_STORE8: + *(uint8*)maddr = (uint8)sval; + break; + case WASM_OP_I32_STORE16: + *(uint16*)maddr = (uint16)sval; + break; + } + (void)flags; + HANDLE_OP_END (); + } + HANDLE_OP (WASM_OP_I64_STORE): HANDLE_OP (WASM_OP_I64_STORE8): - DEF_OP_STORE(uint64, I64, *(uint8*)maddr = (uint8)sval); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I64_STORE16): - DEF_OP_STORE(uint64, I64, *(uint16*)maddr = (uint16)sval); - HANDLE_OP_END (); - HANDLE_OP (WASM_OP_I64_STORE32): - DEF_OP_STORE(uint64, I64, *(uint32*)maddr = (uint32)sval); - HANDLE_OP_END (); + { + uint32 offset, flags, addr; + uint64 sval; + GET_OPCODE(); + read_leb_uint32(frame_ip, frame_ip_end, flags); + read_leb_uint32(frame_ip, frame_ip_end, offset); + sval = POP_I64(); + addr = POP_I32(); + CHECK_MEMORY_OVERFLOW(); + switch (opcode) { + case WASM_OP_I64_STORE: + PUT_I64_TO_ADDR((uint32*)maddr, sval); + break; + case WASM_OP_I64_STORE8: + *(uint8*)maddr = (uint8)sval; + break; + case WASM_OP_I64_STORE16: + *(uint16*)maddr = (uint16)sval; + break; + case WASM_OP_I64_STORE32: + *(uint32*)maddr = (uint32)sval; + break; + } + (void)flags; + HANDLE_OP_END (); + } /* memory size and memory grow instructions */ HANDLE_OP (WASM_OP_MEMORY_SIZE): diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c index 35efd7a998..ec37222bd0 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c @@ -947,18 +947,11 @@ wasm_runtime_instantiate(WASMModule *module, wasm_runtime_set_tlr(&module_inst->main_tlr); module_inst->main_tlr.handle = ws_self_thread(); - /* Execute __post_instantiate function */ - if (!execute_post_inst_function(module_inst)) { - const char *exception = wasm_runtime_get_exception(module_inst); - wasm_printf("%s\n", exception); - wasm_runtime_deinstantiate(module_inst); - return NULL; - } - - /* Execute start function */ - if (!execute_start_function(module_inst)) { - const char *exception = wasm_runtime_get_exception(module_inst); - wasm_printf("%s\n", exception); + /* Execute __post_instantiate and start function */ + if (!execute_post_inst_function(module_inst) + || !execute_start_function(module_inst)) { + set_error_buf(error_buf, error_buf_size, + module_inst->cur_exception); wasm_runtime_deinstantiate(module_inst); return NULL; }