From e73993709e3f254bea39573adb555cbb41e79891 Mon Sep 17 00:00:00 2001 From: "liang.he" Date: Tue, 10 Oct 2023 10:52:37 +0800 Subject: [PATCH 01/14] Use another default pipeline when opt-level is 0 (#2624) According to the description of `buildPerModuleDefaultPipeline()` and `buildLTOPreLinkDefaultPipeline()`, it is not allowed to call them with `O0` level. Use `buildO0DefaultPipeline` instead when the opt-level is 0. --- core/iwasm/compilation/aot_llvm_extra.cpp | 25 ++++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index ab6c621a0..72e163fa2 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -343,18 +343,23 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module) ExitOnErr(PB.parsePassPipeline(MPM, comp_ctx->llvm_passes)); } - if (!disable_llvm_lto) { - /* Apply LTO for AOT mode */ - if (comp_ctx->comp_data->func_count >= 10 - || comp_ctx->enable_llvm_pgo || comp_ctx->use_prof_file) - /* Add the pre-link optimizations if the func count - is large enough or PGO is enabled */ - MPM.addPass(PB.buildLTOPreLinkDefaultPipeline(OL)); - else - MPM.addPass(PB.buildLTODefaultPipeline(OL, NULL)); + if (OptimizationLevel::O0 == OL) { + MPM.addPass(PB.buildO0DefaultPipeline(OL)); } else { - MPM.addPass(PB.buildPerModuleDefaultPipeline(OL)); + if (!disable_llvm_lto) { + /* Apply LTO for AOT mode */ + if (comp_ctx->comp_data->func_count >= 10 + || comp_ctx->enable_llvm_pgo || comp_ctx->use_prof_file) + /* Add the pre-link optimizations if the func count + is large enough or PGO is enabled */ + MPM.addPass(PB.buildLTOPreLinkDefaultPipeline(OL)); + else + MPM.addPass(PB.buildLTODefaultPipeline(OL, NULL)); + } + else { + MPM.addPass(PB.buildPerModuleDefaultPipeline(OL)); + } } /* Run specific passes for AOT indirect mode in last since general From 72b34eaf300f62d66dbf093099589cdb24ee8623 Mon Sep 17 00:00:00 2001 From: Marcin Kolny Date: Wed, 11 Oct 2023 04:22:34 +0100 Subject: [PATCH 02/14] Fix AOT shift operations for indirect constants (#2627) When doing more investigations related to this PR: https://github.com/bytecodealliance/wasm-micro-runtime/pull/2619 We found that in some scenarios the constant might not be directly available to the LLVM IR builder, e.g.: ``` (func $const_ret (result i32) i32.const -5 ) (func $foo (i32.shr_u (i32.const -1) (call $const_ret)) (i32.const 31) ) ``` In that case, the right parameter to `i32.shr_u` is not constant, therefore the `SHIFT_COUNT_MASK` isn't applied. However, when the optimization is enabled (`--opt-level` is 2 or 3), the optimization passes resolve the call into constant, and that constant is poisoned, causing the compiler to resolve the whole function to an exception. --- core/iwasm/compilation/aot_emit_numberic.c | 18 ++------- .../test_shift_negative_constants.wat | 37 ++++++++++++++++++- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index bda64f831..04cfaada3 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -171,15 +171,6 @@ right = shift_count_mask; \ } while (0) -static bool -is_shift_count_mask_needed(AOTCompContext *comp_ctx, LLVMValueRef left, - LLVMValueRef right) -{ - return (strcmp(comp_ctx->target_arch, "x86_64") != 0 - && strcmp(comp_ctx->target_arch, "i386") != 0) - || (LLVMIsEfficientConstInt(left) && LLVMIsEfficientConstInt(right)); -} - /* Call llvm constrained floating-point intrinsic */ static LLVMValueRef call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx, @@ -737,8 +728,7 @@ compile_int_shl(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right, { LLVMValueRef res; - if (is_shift_count_mask_needed(comp_ctx, left, right)) - SHIFT_COUNT_MASK; + SHIFT_COUNT_MASK; /* Build shl */ LLVM_BUILD_OP(Shl, left, right, res, "shl", NULL); @@ -752,8 +742,7 @@ compile_int_shr_s(AOTCompContext *comp_ctx, LLVMValueRef left, { LLVMValueRef res; - if (is_shift_count_mask_needed(comp_ctx, left, right)) - SHIFT_COUNT_MASK; + SHIFT_COUNT_MASK; /* Build shl */ LLVM_BUILD_OP(AShr, left, right, res, "shr_s", NULL); @@ -767,8 +756,7 @@ compile_int_shr_u(AOTCompContext *comp_ctx, LLVMValueRef left, { LLVMValueRef res; - if (is_shift_count_mask_needed(comp_ctx, left, right)) - SHIFT_COUNT_MASK; + SHIFT_COUNT_MASK; /* Build shl */ LLVM_BUILD_OP(LShr, left, right, res, "shr_u", NULL); diff --git a/tests/wamr-compiler/test_shift_negative_constants.wat b/tests/wamr-compiler/test_shift_negative_constants.wat index 030cc8983..83bc3c44d 100644 --- a/tests/wamr-compiler/test_shift_negative_constants.wat +++ b/tests/wamr-compiler/test_shift_negative_constants.wat @@ -7,6 +7,7 @@ ;; any problems. See: https://github.com/bytecodealliance/wasm-micro-runtime/pull/2619 (module (memory (export "memory") 1 1) + (func $assert_eq (param i32 i32) (i32.ne (local.get 0) (local.get 1)) if @@ -23,7 +24,7 @@ (func $i32_shr_s (call $assert_eq - (i32.shr_u (i32.const 32) (i32.const -30)) + (i32.shr_s (i32.const 32) (i32.const -30)) (i32.const 8) ) ) @@ -35,9 +36,43 @@ ) ) + (func $const_ret (result i32) + i32.const -5 + ) + + ;; *_func_call tests validate the potential LLVM optimizations + ;; where the right parameter of the shift operation is an + ;; indirect constant value. + (func $i32_shr_u_func_call + (call $assert_eq + (i32.shr_u (i32.const -1) (call $const_ret)) + (i32.const 31) + ) + ) + + (func $i32_shr_s_func_call + (call $assert_eq + (i32.shr_s + (i32.const 1073741824) ;; 2^30 + (call $const_ret) + ) + (i32.const 8) + ) + ) + + (func $i32_shl_func_call + (call $assert_eq + (i32.shl (i32.const -1) (call $const_ret)) + (i32.const -134217728) + ) + ) + (func (export "_start") call $i32_shr_u call $i32_shr_s call $i32_shl + call $i32_shr_u_func_call + call $i32_shr_s_func_call + call $i32_shl_func_call ) ) From 9ed26404d5f0f5b76c803228d58ad0fd5ac64248 Mon Sep 17 00:00:00 2001 From: Wang Xin Date: Fri, 13 Oct 2023 15:30:59 +0800 Subject: [PATCH 03/14] Vote for nomination of Woods, Chris and Trenner, Thomas as TSC members (#2638) * Add architecture diagram for wasm function * Update functions.excalidraw.png * Update functions.excalidraw.png * Update README.md * changed to svg for smaller size * add architecture document for wasm export * Update wasm_exports.svg * Update wasm_exports.MD * Update wasm_exports.MD * update * Update wasm_exports.MD * draft for stack frame and globals * update * add architecture of globals and ci stack format * update blog links * Update README.md * update * Update stack_format_ci.excalidraw * update * Update wasm_function.MD * Update wasm_function.MD * update * update * Nominate Woods, Chris and Trenner, Thomas as TSC member --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 486ca0fd0..dfdae2da8 100644 --- a/README.md +++ b/README.md @@ -92,8 +92,10 @@ The current TSC members: - [lum1n0us](https://github.com/lum1n0us) - **Liang He**, - [no1wudi](https://github.com/no1wudi) **Qi Huang**, - [qinxk-inter](https://github.com/qinxk-inter) - **Xiaokang Qin**, +- [ttrenner ](https://github.com/ttrenner) - **Trenner, Thomas**, - [wei-tang](https://github.com/wei-tang) - **Wei Tang**, - [wenyongh](https://github.com/wenyongh) - **Wenyong Huang**, +- [woodsmc](https://github.com/woodsmc) - **Woods, Chris**, - [xujuntwt95329](https://github.com/xujuntwt95329) - **Jun Xu**, - [xwang98](https://github.com/xwang98) - **Xin Wang**, (chair) - [yamt](https://github.com/yamt) - **Takashi Yamamoto**, From 9d7931e1d255bc1d937c200ec6bc8bbd7267a503 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 24 Oct 2023 09:19:45 +0800 Subject: [PATCH 04/14] Fix several typo/warning/unused-code issues (#2655) - Fix typo in wamr-test-suites script - Fix compilation warnings in libc-wasi posix.c - Remove unused code fast-jit jit_frontend.c - Remove duplicated exception print in `iwasm -f ` - Fix return value in void function wasm_runtime_set_wasi_ctx --- core/iwasm/common/wasm_application.c | 5 +- core/iwasm/common/wasm_native.c | 3 +- core/iwasm/fast-jit/jit_frontend.c | 74 ------------------- .../sandboxed-system-primitives/src/posix.c | 4 +- ...ch => multi_module_aot_ignore_cases.patch} | 0 tests/wamr-test-suites/test_wamr.sh | 4 +- 6 files changed, 6 insertions(+), 84 deletions(-) rename tests/wamr-test-suites/spec-test-script/{muti_module_aot_ignore_cases.patch => multi_module_aot_ignore_cases.patch} (100%) diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 02999584f..d29d379b3 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -312,7 +312,6 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name, #endif int32 i, p, module_type; uint64 total_size; - const char *exception; char buf[128]; bh_assert(argc >= 0); @@ -632,9 +631,7 @@ fail: if (argv1) wasm_runtime_free(argv1); - exception = wasm_runtime_get_exception(module_inst); - bh_assert(exception); - os_printf("%s\n", exception); + bh_assert(wasm_runtime_get_exception(module_inst)); return false; } diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index 0a5851349..c42bf7b31 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -542,8 +542,7 @@ void wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm, WASIContext *wasi_ctx) { - return wasm_native_set_context(module_inst_comm, g_wasi_context_key, - wasi_ctx); + wasm_native_set_context(module_inst_comm, g_wasi_context_key, wasi_ctx); } static void diff --git a/core/iwasm/fast-jit/jit_frontend.c b/core/iwasm/fast-jit/jit_frontend.c index ec68ad91d..b24657246 100644 --- a/core/iwasm/fast-jit/jit_frontend.c +++ b/core/iwasm/fast-jit/jit_frontend.c @@ -2311,77 +2311,3 @@ jit_frontend_get_jitted_return_addr_offset() { return (uint32)offsetof(WASMInterpFrame, jitted_return_addr); } - -#if 0 -#if WASM_ENABLE_THREAD_MGR != 0 -bool -check_suspend_flags(JitCompContext *cc, JITFuncContext *func_ctx) -{ - LLVMValueRef terminate_addr, terminate_flags, flag, offset, res; - JitBasicBlock *terminate_check_block, non_terminate_block; - JITFuncType *jit_func_type = func_ctx->jit_func->func_type; - JitBasicBlock *terminate_block; - - /* Offset of suspend_flags */ - offset = I32_FIVE; - - if (!(terminate_addr = LLVMBuildInBoundsGEP( - cc->builder, func_ctx->exec_env, &offset, 1, "terminate_addr"))) { - jit_set_last_error("llvm build in bounds gep failed"); - return false; - } - if (!(terminate_addr = - LLVMBuildBitCast(cc->builder, terminate_addr, INT32_PTR_TYPE, - "terminate_addr_ptr"))) { - jit_set_last_error("llvm build bit cast failed"); - return false; - } - - if (!(terminate_flags = - LLVMBuildLoad(cc->builder, terminate_addr, "terminate_flags"))) { - jit_set_last_error("llvm build bit cast failed"); - return false; - } - /* Set terminate_flags memory accecc to volatile, so that the value - will always be loaded from memory rather than register */ - LLVMSetVolatile(terminate_flags, true); - - CREATE_BASIC_BLOCK(terminate_check_block, "terminate_check"); - MOVE_BASIC_BLOCK_AFTER_CURR(terminate_check_block); - - CREATE_BASIC_BLOCK(non_terminate_block, "non_terminate"); - MOVE_BASIC_BLOCK_AFTER_CURR(non_terminate_block); - - BUILD_ICMP(LLVMIntSGT, terminate_flags, I32_ZERO, res, "need_terminate"); - BUILD_COND_BR(res, terminate_check_block, non_terminate_block); - - /* Move builder to terminate check block */ - SET_BUILDER_POS(terminate_check_block); - - CREATE_BASIC_BLOCK(terminate_block, "terminate"); - MOVE_BASIC_BLOCK_AFTER_CURR(terminate_block); - - if (!(flag = LLVMBuildAnd(cc->builder, terminate_flags, I32_ONE, - "termination_flag"))) { - jit_set_last_error("llvm build AND failed"); - return false; - } - - BUILD_ICMP(LLVMIntSGT, flag, I32_ZERO, res, "need_terminate"); - BUILD_COND_BR(res, terminate_block, non_terminate_block); - - /* Move builder to terminate block */ - SET_BUILDER_POS(terminate_block); - if (!jit_build_zero_function_ret(cc, func_ctx, jit_func_type)) { - goto fail; - } - - /* Move builder to terminate block */ - SET_BUILDER_POS(non_terminate_block); - return true; - -fail: - return false; -} -#endif /* End of WASM_ENABLE_THREAD_MGR */ -#endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 0ba91a7e9..d5d181f8b 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -3169,8 +3169,8 @@ wasi_ssp_sock_open(wasm_exec_env_t exec_env, struct fd_table *curfds, bool is_tcp = SOCKET_DGRAM == socktype ? false : true; bool is_ipv4 = INET6 == af ? false : true; int ret; - __wasi_filetype_t wasi_type; - __wasi_rights_t max_base, max_inheriting; + __wasi_filetype_t wasi_type = __WASI_FILETYPE_UNKNOWN; + __wasi_rights_t max_base = 0, max_inheriting = 0; __wasi_errno_t error; (void)poolfd; diff --git a/tests/wamr-test-suites/spec-test-script/muti_module_aot_ignore_cases.patch b/tests/wamr-test-suites/spec-test-script/multi_module_aot_ignore_cases.patch similarity index 100% rename from tests/wamr-test-suites/spec-test-script/muti_module_aot_ignore_cases.patch rename to tests/wamr-test-suites/spec-test-script/multi_module_aot_ignore_cases.patch diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 81844f0e7..b41fc9014 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -386,7 +386,7 @@ function spec_test() git apply ../../spec-test-script/simd_ignore_cases.patch fi if [[ ${ENABLE_MULTI_MODULE} == 1 && $1 == 'aot' ]]; then - git apply ../../spec-test-script/muti_module_aot_ignore_cases.patch + git apply ../../spec-test-script/multi_module_aot_ignore_cases.patch fi # udpate thread cases @@ -948,4 +948,4 @@ fi echo -e "Test finish. Reports are under ${REPORT_DIR}" DEBUG set +xv pipefail echo "TEST SUCCESSFUL" -exit 0 \ No newline at end of file +exit 0 From d6bba13e867c0289d09e3b89a0edbef8f371012e Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 24 Oct 2023 10:47:17 +0800 Subject: [PATCH 05/14] Fix fast-interp "pre-compiled label offset out of range" issue (#2659) When labels-as-values is enabled in a target which doesn't support unaligned address access, 16-bit offset is used to store the relative offset between two opcode labels. But it is a little small and the loader may report "pre-compiled label offset out of range" error. Emitting 32-bit data instead to resolve the issue: emit label address in 32-bit target and emit 32-bit relative offset in 64-bit target. See also: https://github.com/bytecodealliance/wasm-micro-runtime/issues/2635 --- core/iwasm/interpreter/wasm_interp_fast.c | 27 +++++++-- core/iwasm/interpreter/wasm_loader.c | 68 ++++++++++++----------- core/iwasm/interpreter/wasm_mini_loader.c | 67 +++++++++++----------- 3 files changed, 92 insertions(+), 70 deletions(-) diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index e565c2c89..701886d60 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -1128,12 +1128,27 @@ wasm_interp_dump_op_count() goto *p_label_addr; \ } while (0) #else -#define FETCH_OPCODE_AND_DISPATCH() \ - do { \ - const void *p_label_addr = label_base + *(int16 *)frame_ip; \ - frame_ip += sizeof(int16); \ - goto *p_label_addr; \ +#if UINTPTR_MAX == UINT64_MAX +#define FETCH_OPCODE_AND_DISPATCH() \ + do { \ + const void *p_label_addr; \ + bh_assert(((uintptr_t)frame_ip & 1) == 0); \ + /* int32 relative offset was emitted in 64-bit target */ \ + p_label_addr = label_base + (int32)LOAD_U32_WITH_2U16S(frame_ip); \ + frame_ip += sizeof(int32); \ + goto *p_label_addr; \ } while (0) +#else +#define FETCH_OPCODE_AND_DISPATCH() \ + do { \ + const void *p_label_addr; \ + bh_assert(((uintptr_t)frame_ip & 1) == 0); \ + /* uint32 label address was emitted in 32-bit target */ \ + p_label_addr = (void *)(uintptr_t)LOAD_U32_WITH_2U16S(frame_ip); \ + frame_ip += sizeof(int32); \ + goto *p_label_addr; \ + } while (0) +#endif #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ #define HANDLE_OP_END() FETCH_OPCODE_AND_DISPATCH() @@ -1183,7 +1198,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, register uint8 *frame_ip = &opcode_IMPDEP; /* cache of frame->ip */ register uint32 *frame_lp = NULL; /* cache of frame->lp */ #if WASM_ENABLE_LABELS_AS_VALUES != 0 -#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 +#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 && UINTPTR_MAX == UINT64_MAX /* cache of label base addr */ register uint8 *label_base = &&HANDLE_WASM_OP_UNREACHABLE; #endif diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index cf8b7719c..4afa1157c 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -5389,21 +5389,27 @@ fail: LOG_OP("\ndelete last op\n"); \ } while (0) #else /* else of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ +#if UINTPTR_MAX == UINT64_MAX #define emit_label(opcode) \ do { \ int32 offset = \ (int32)((uint8 *)handle_table[opcode] - (uint8 *)handle_table[0]); \ - if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \ - set_error_buf(error_buf, error_buf_size, \ - "pre-compiled label offset out of range"); \ - goto fail; \ - } \ - wasm_loader_emit_int16(loader_ctx, offset); \ + /* emit int32 relative offset in 64-bit target */ \ + wasm_loader_emit_uint32(loader_ctx, offset); \ LOG_OP("\nemit_op [%02x]\t", opcode); \ } while (0) +#else +#define emit_label(opcode) \ + do { \ + uint32 label_addr = (uint32)(uintptr_t)handle_table[opcode]; \ + /* emit uint32 label address in 32-bit target */ \ + wasm_loader_emit_uint32(loader_ctx, label_addr); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) +#endif #define skip_label() \ do { \ - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \ + wasm_loader_emit_backspace(loader_ctx, sizeof(int32)); \ LOG_OP("\ndelete last op\n"); \ } while (0) #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ @@ -5733,12 +5739,6 @@ preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode, (void)error_buf; (void)error_buf_size; return true; -#if WASM_ENABLE_LABELS_AS_VALUES != 0 -#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 -fail: - return false; -#endif -#endif } static bool @@ -7793,6 +7793,9 @@ re_scan: uint8 ref_type; BranchBlock *cur_block = loader_ctx->frame_csp - 1; int32 available_stack_cell; +#if WASM_ENABLE_FAST_INTERP != 0 + uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled; +#endif POP_I32(); @@ -7821,26 +7824,26 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 if (loader_ctx->p_code_compiled) { uint8 opcode_tmp = WASM_OP_SELECT_64; - uint8 *p_code_compiled_tmp = - loader_ctx->p_code_compiled - 2; #if WASM_ENABLE_LABELS_AS_VALUES != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 *(void **)(p_code_compiled_tmp - sizeof(void *)) = handle_table[opcode_tmp]; #else +#if UINTPTR_MAX == UINT64_MAX + /* emit int32 relative offset in 64-bit target + */ int32 offset = (int32)((uint8 *)handle_table[opcode_tmp] - (uint8 *)handle_table[0]); - if (!(offset >= INT16_MIN - && offset < INT16_MAX)) { - set_error_buf(error_buf, error_buf_size, - "pre-compiled label offset " - "out of range"); - goto fail; - } - *(int16 *)(p_code_compiled_tmp - - sizeof(int16)) = (int16)offset; + *(int32 *)(p_code_compiled_tmp + - sizeof(int32)) = offset; +#else + /* emit uint32 label address in 32-bit target */ + *(uint32 *)(p_code_compiled_tmp + - sizeof(uint32)) = + (uint32)(uintptr_t)handle_table[opcode_tmp]; +#endif #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ #else /* else of WASM_ENABLE_LABELS_AS_VALUES */ #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 @@ -7934,16 +7937,17 @@ re_scan: *(void **)(p_code_compiled_tmp - sizeof(void *)) = handle_table[opcode_tmp]; #else +#if UINTPTR_MAX == UINT64_MAX + /* emit int32 relative offset in 64-bit target */ int32 offset = (int32)((uint8 *)handle_table[opcode_tmp] - (uint8 *)handle_table[0]); - if (!(offset >= INT16_MIN && offset < INT16_MAX)) { - set_error_buf( - error_buf, error_buf_size, - "pre-compiled label offset out of range"); - goto fail; - } - *(int16 *)(p_code_compiled_tmp - sizeof(int16)) = - (int16)offset; + *(int32 *)(p_code_compiled_tmp - sizeof(int32)) = + offset; +#else + /* emit uint32 label address in 32-bit target */ + *(uint32 *)(p_code_compiled_tmp - sizeof(uint32)) = + (uint32)(uintptr_t)handle_table[opcode_tmp]; +#endif #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ #else /* else of WASM_ENABLE_LABELS_AS_VALUES */ #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index d16bc1a24..44aab2654 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -4009,21 +4009,27 @@ wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, char *error_buf, LOG_OP("\ndelete last op\n"); \ } while (0) #else /* else of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ +#if UINTPTR_MAX == UINT64_MAX #define emit_label(opcode) \ do { \ int32 offset = \ (int32)((uint8 *)handle_table[opcode] - (uint8 *)handle_table[0]); \ - if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \ - set_error_buf(error_buf, error_buf_size, \ - "pre-compiled label offset out of range"); \ - goto fail; \ - } \ - wasm_loader_emit_int16(loader_ctx, offset); \ + /* emit int32 relative offset in 64-bit target */ \ + wasm_loader_emit_uint32(loader_ctx, offset); \ LOG_OP("\nemit_op [%02x]\t", opcode); \ } while (0) +#else +#define emit_label(opcode) \ + do { \ + uint32 label_addr = (uint32)(uintptr_t)handle_table[opcode]; \ + /* emit uint32 label address in 32-bit target */ \ + wasm_loader_emit_uint32(loader_ctx, label_addr); \ + LOG_OP("\nemit_op [%02x]\t", opcode); \ + } while (0) +#endif #define skip_label() \ do { \ - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \ + wasm_loader_emit_backspace(loader_ctx, sizeof(int32)); \ LOG_OP("\ndelete last op\n"); \ } while (0) #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ @@ -4351,13 +4357,6 @@ preserve_referenced_local(WASMLoaderContext *loader_ctx, uint8 opcode, } return true; - -#if WASM_ENABLE_LABELS_AS_VALUES != 0 -#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 -fail: - return false; -#endif -#endif } static bool @@ -6146,6 +6145,9 @@ re_scan: uint8 ref_type; BranchBlock *cur_block = loader_ctx->frame_csp - 1; int32 available_stack_cell; +#if WASM_ENABLE_FAST_INTERP != 0 + uint8 *p_code_compiled_tmp = loader_ctx->p_code_compiled; +#endif POP_I32(); @@ -6168,26 +6170,26 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 if (loader_ctx->p_code_compiled) { uint8 opcode_tmp = WASM_OP_SELECT_64; - uint8 *p_code_compiled_tmp = - loader_ctx->p_code_compiled - 2; #if WASM_ENABLE_LABELS_AS_VALUES != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 *(void **)(p_code_compiled_tmp - sizeof(void *)) = handle_table[opcode_tmp]; #else +#if UINTPTR_MAX == UINT64_MAX + /* emit int32 relative offset in 64-bit target + */ int32 offset = (int32)((uint8 *)handle_table[opcode_tmp] - (uint8 *)handle_table[0]); - if (!(offset >= INT16_MIN - && offset < INT16_MAX)) { - set_error_buf(error_buf, error_buf_size, - "pre-compiled label offset " - "out of range"); - goto fail; - } - *(int16 *)(p_code_compiled_tmp - - sizeof(int16)) = (int16)offset; + *(int32 *)(p_code_compiled_tmp + - sizeof(int32)) = offset; +#else + /* emit uint32 label address in 32-bit target */ + *(uint32 *)(p_code_compiled_tmp + - sizeof(uint32)) = + (uint32)(uintptr_t)handle_table[opcode_tmp]; +#endif #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ #else /* else of WASM_ENABLE_LABELS_AS_VALUES */ #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 @@ -6263,15 +6265,16 @@ re_scan: *(void **)(p_code_compiled_tmp - sizeof(void *)) = handle_table[opcode_tmp]; #else +#if UINTPTR_MAX == UINT64_MAX + /* emit int32 relative offset in 64-bit target */ int32 offset = (int32)((uint8 *)handle_table[opcode_tmp] - (uint8 *)handle_table[0]); - if (!(offset >= INT16_MIN && offset < INT16_MAX)) { - set_error_buf(error_buf, error_buf_size, - "pre-compiled label offset out of range"); - goto fail; - } - *(int16 *)(p_code_compiled_tmp - sizeof(int16)) = - (int16)offset; + *(int32 *)(p_code_compiled_tmp - sizeof(int32)) = offset; +#else + /* emit uint32 label address in 32-bit target */ + *(uint32 *)(p_code_compiled_tmp - sizeof(uint32)) = + (uint32)(uintptr_t)handle_table[opcode_tmp]; +#endif #endif /* end of WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS */ #else /* else of WASM_ENABLE_LABELS_AS_VALUES */ #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 From 4f5ad4dc12cd26598a685fa43dd563471a84bff7 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Wed, 25 Oct 2023 08:05:26 +0800 Subject: [PATCH 06/14] Apply no_sanitize_address for clang compiler in several places (#2663) Apply `no_sanitize_address` for clang compiler in several places in which it has been applied to gcc compiler. And refine the comment. --- core/iwasm/common/wasm_runtime_common.c | 10 ++++--- core/iwasm/interpreter/wasm_interp_classic.c | 10 ++++--- .../platform/common/posix/posix_thread.c | 26 +++++++++++++------ 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 8faa5e444..8af58370a 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -4339,10 +4339,12 @@ static V128FuncPtr invokeNative_V128 = (V128FuncPtr)(uintptr_t)invokeNative; || defined(BUILD_TARGET_RISCV64_LP64) */ #endif /* end of defined(_WIN32) || defined(_WIN32_) */ -/* ASAN is not designed to work with custom stack unwind or other low-level \ - things. > Ignore a function that does some low-level magic. (e.g. walking \ - through the thread's stack bypassing the frame boundaries) */ -#if defined(__GNUC__) +/* + * ASAN is not designed to work with custom stack unwind or other low-level + * things. Ignore a function that does some low-level magic. (e.g. walking + * through the thread's stack bypassing the frame boundaries) + */ +#if defined(__GNUC__) || defined(__clang__) __attribute__((no_sanitize_address)) #endif bool diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 50860d3a3..71b8644de 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -4009,10 +4009,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, } #if WASM_ENABLE_FAST_JIT != 0 -/* ASAN is not designed to work with custom stack unwind or other low-level \ - things. > Ignore a function that does some low-level magic. (e.g. walking \ - through the thread's stack bypassing the frame boundaries) */ -#if defined(__GNUC__) +/* + * ASAN is not designed to work with custom stack unwind or other low-level + * things. Ignore a function that does some low-level magic. (e.g. walking + * through the thread's stack bypassing the frame boundaries) + */ +#if defined(__GNUC__) || defined(__clang__) __attribute__((no_sanitize_address)) #endif static void diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index 498f5f5a2..46a4bd993 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -441,8 +441,14 @@ static os_thread_local_attribute bool thread_signal_inited = false; /* The signal alternate stack base addr */ static os_thread_local_attribute uint8 *sigalt_stack_base_addr; +/* + * ASAN is not designed to work with custom stack unwind or other low-level + * things. Ignore a function that does some low-level magic. (e.g. walking + * through the thread's stack bypassing the frame boundaries) + */ #if defined(__clang__) #pragma clang optimize off +__attribute__((no_sanitize_address)) #elif defined(__GNUC__) #pragma GCC push_options #pragma GCC optimize("O0") @@ -503,10 +509,12 @@ destroy_stack_guard_pages() } #endif /* end of WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 */ -/* ASAN is not designed to work with custom stack unwind or other low-level \ - things. > Ignore a function that does some low-level magic. (e.g. walking \ - through the thread's stack bypassing the frame boundaries) */ -#if defined(__GNUC__) +/* + * ASAN is not designed to work with custom stack unwind or other low-level + * things. Ignore a function that does some low-level magic. (e.g. walking + * through the thread's stack bypassing the frame boundaries) + */ +#if defined(__GNUC__) || defined(__clang__) __attribute__((no_sanitize_address)) #endif static void @@ -523,10 +531,12 @@ mask_signals(int how) static struct sigaction prev_sig_act_SIGSEGV; static struct sigaction prev_sig_act_SIGBUS; -/* ASAN is not designed to work with custom stack unwind or other low-level \ - things. > Ignore a function that does some low-level magic. (e.g. walking \ - through the thread's stack bypassing the frame boundaries) */ -#if defined(__GNUC__) +/* + * ASAN is not designed to work with custom stack unwind or other low-level + * things. Ignore a function that does some low-level magic. (e.g. walking + * through the thread's stack bypassing the frame boundaries) + */ +#if defined(__GNUC__) || defined(__clang__) __attribute__((no_sanitize_address)) #endif static void From 9a5c777aff0bd5692baec9dba83da6fafc67f28f Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 25 Oct 2023 21:46:49 +0900 Subject: [PATCH 07/14] Revert "Strip static and shared libraries of iwasm to reduce the binary size (#2431)" (#2669) This reverts commit 7e3a29d5e4564406c91ada436b1e33d53d1232cf: * it doesn't work for macOS. ("unrecognized option: --strip-all") * it doesn't work for ubuntu. https://github.com/bytecodealliance/wasm-micro-runtime/issues/2665 --- CMakeLists.txt | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fbea2616e..1c8799494 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,11 +107,6 @@ endif () set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -# Set the strip command based on the system (GNU or Clang) -if (CMAKE_STRIP) - set (CMAKE_STRIP_FLAGS "--strip-all") -endif () - include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wshadow -Wno-unused-parameter") @@ -146,15 +141,6 @@ endif () install (TARGETS iwasm_static ARCHIVE DESTINATION lib) -# If it's a Release build, strip the static library -if (CMAKE_STRIP AND CMAKE_BUILD_TYPE STREQUAL "Release") - # Strip static library - message (STATUS "Stripping static library after build!") - add_custom_command (TARGET iwasm_static POST_BUILD - COMMAND ${CMAKE_STRIP} ${CMAKE_STRIP_FLAGS} $ - ) -endif () - # SHARED LIBRARY add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE}) set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm) @@ -176,12 +162,3 @@ install (FILES ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h ${WAMR_ROOT_DIR}/core/iwasm/include/lib_export.h DESTINATION include) - -# If it's a Release build, strip the shared library -if (CMAKE_STRIP AND CMAKE_BUILD_TYPE STREQUAL "Release") - # Strip shared library - message (STATUS "Stripping shared library after build!") - add_custom_command (TARGET iwasm_shared POST_BUILD - COMMAND ${CMAKE_STRIP} ${CMAKE_STRIP_FLAGS} $ - ) -endif () From 8038b9c524d239fe3322ba004e7c830dbadc4c69 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Fri, 27 Oct 2023 12:20:25 +0800 Subject: [PATCH 08/14] Fix fast-jit f32/f64 truncate to i32/i64 (#2671) The f32/f64 value to be truncated may be a const, add checks for whether it is nan and whether it is out of the legal range. Fixes issue #2661. --- core/iwasm/fast-jit/fe/jit_emit_conversion.c | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/core/iwasm/fast-jit/fe/jit_emit_conversion.c b/core/iwasm/fast-jit/fe/jit_emit_conversion.c index 8308a3ca9..89d84f142 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_conversion.c +++ b/core/iwasm/fast-jit/fe/jit_emit_conversion.c @@ -192,6 +192,55 @@ jit_compile_check_value_range(JitCompContext *cc, JitReg value, JitReg min_fp, bh_assert(JIT_REG_KIND_F32 == kind || JIT_REG_KIND_F64 == kind); + if (JIT_REG_KIND_F32 == kind && jit_reg_is_const(value)) { + /* value is an f32 const */ + float value_f32_const = jit_cc_get_const_F32(cc, value); + float min_fp_f32_const = jit_cc_get_const_F32(cc, min_fp); + float max_fp_f32_const = jit_cc_get_const_F32(cc, max_fp); + + if (isnan(value_f32_const)) { + /* throw exception if value is nan */ + if (!jit_emit_exception(cc, EXCE_INVALID_CONVERSION_TO_INTEGER, + JIT_OP_JMP, 0, NULL)) + goto fail; + } + + if (value_f32_const <= min_fp_f32_const + || value_f32_const >= max_fp_f32_const) { + /* throw exception if value is out of range */ + if (!jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_JMP, 0, + NULL)) + goto fail; + } + + /* value is in range, do nothing */ + return true; + } + else if (JIT_REG_KIND_F64 == kind && jit_reg_is_const(value)) { + /* value is an f64 const */ + double value_f64_const = jit_cc_get_const_F64(cc, value); + double min_fp_f64_const = jit_cc_get_const_F64(cc, min_fp); + double max_fp_f64_const = jit_cc_get_const_F64(cc, max_fp); + + if (isnan(value_f64_const)) { + /* throw exception if value is nan */ + if (!jit_emit_exception(cc, EXCE_INVALID_CONVERSION_TO_INTEGER, + JIT_OP_JMP, 0, NULL)) + goto fail; + } + + if (value_f64_const <= min_fp_f64_const + || value_f64_const >= max_fp_f64_const) { + /* throw exception if value is out of range */ + if (!jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_JMP, 0, + NULL)) + goto fail; + } + + /* value is in range, do nothing */ + return true; + } + /* If value is NaN, throw exception */ if (JIT_REG_KIND_F32 == kind) emit_ret = jit_emit_callnative(cc, local_isnanf, nan_ret, &value, 1); From 9b8fe049b3b7fb5b372513e9c35cd8f837e62226 Mon Sep 17 00:00:00 2001 From: "Alfred E. Neumayer" Date: Fri, 27 Oct 2023 06:48:10 +0200 Subject: [PATCH 09/14] core/iwasm: Support mapped file system access on non-libuv WASI (#2628) This patch enables mapping host directories to guest directories by parsing the `map_dir_list` argument in API `wasm_runtime_init_wasi` for libc-wasi. It follows the format `::`. It also adds argument `--map-dir=` argument for `iwasm` common line tool, and allows to add multiple mappings: ```bash iwasm --map-dir= --map-dir= ... ``` --- core/iwasm/common/wasm_runtime_common.c | 78 ++++++++++++++++++++++++- core/iwasm/include/wasm_export.h | 1 + product-mini/platforms/posix/main.c | 20 ++++++- 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 8af58370a..031fb539d 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -3012,8 +3012,82 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, goto fail; } - fd_table_insert_existing(curfds, wasm_fd, raw_fd); - fd_prestats_insert(prestats, dir_list[i], wasm_fd); + if (!fd_table_insert_existing(curfds, wasm_fd, raw_fd) + || !fd_prestats_insert(prestats, dir_list[i], wasm_fd)) { + if (error_buf) + snprintf( + error_buf, error_buf_size, + "error while pre-opening directory %s: insertion failed\n", + dir_list[i]); + goto fail; + } + } + + for (i = 0; i < map_dir_count; i++, wasm_fd++) { + char mapping_copy_buf[256]; + char *mapping_copy = mapping_copy_buf; + char *map_mapped = NULL, *map_host = NULL; + const unsigned long max_len = strlen(map_dir_list[i]) * 2 + 3; + + /* Allocation limit for runtime environments with reduced stack size */ + if (max_len > 256) { + if (!(mapping_copy = wasm_runtime_malloc(max_len))) { + snprintf(error_buf, error_buf_size, + "error while allocating for directory mapping\n"); + goto fail; + } + } + + strncpy(mapping_copy, map_dir_list[i], strlen(map_dir_list[i]) + 1); + map_mapped = strtok(mapping_copy, "::"); + map_host = strtok(NULL, "::"); + + if (!map_mapped || !map_host) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "error while pre-opening mapped directory: " + "invalid map\n"); + if (mapping_copy != mapping_copy_buf) + wasm_runtime_free(mapping_copy); + goto fail; + } + + path = realpath(map_host, resolved_path); + if (!path) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "error while pre-opening mapped directory %s: %d\n", + map_host, errno); + if (mapping_copy != mapping_copy_buf) + wasm_runtime_free(mapping_copy); + goto fail; + } + + raw_fd = open(path, O_RDONLY | O_DIRECTORY, 0); + if (raw_fd == -1) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "error while pre-opening mapped directory %s: %d\n", + map_host, errno); + if (mapping_copy != mapping_copy_buf) + wasm_runtime_free(mapping_copy); + goto fail; + } + + if (!fd_table_insert_existing(curfds, wasm_fd, raw_fd) + || !fd_prestats_insert(prestats, map_mapped, wasm_fd)) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "error while pre-opening mapped directory %s: " + "insertion failed\n", + dir_list[i]); + if (mapping_copy != mapping_copy_buf) + wasm_runtime_free(mapping_copy); + goto fail; + } + + if (mapping_copy != mapping_copy_buf) + wasm_runtime_free(mapping_copy); } /* addr_pool(textual) -> apool */ diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 2a30ddc93..1d90cc37a 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -423,6 +423,7 @@ wasm_runtime_get_module_hash(wasm_module_t module); * @param dir_list The list of directories to preopen. (real path) * @param dir_count The number of elements in dir_list. * @param map_dir_list The list of directories to preopen. (mapped path) + * Format for each map entry: :: * @param map_dir_count The number of elements in map_dir_list. * If map_dir_count is smaller than dir_count, * mapped path is assumed to be same as the diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index b27bd8c2e..08fd65f16 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -75,6 +75,9 @@ print_help() printf(" --dir= Grant wasi access to the given host directories\n"); printf(" to the program, for example:\n"); printf(" --dir= --dir=\n"); + printf(" --map-dir= Grant wasi access to the given host directories\n"); + printf(" to the program at a specific guest path, for example:\n"); + printf(" --map-dir= --map-dir=\n"); printf(" --addr-pool= Grant wasi access to the given network addresses in\n"); printf(" CIRD notation to the program, seperated with ',',\n"); printf(" for example:\n"); @@ -573,6 +576,8 @@ main(int argc, char *argv[]) #if WASM_ENABLE_LIBC_WASI != 0 const char *dir_list[8] = { NULL }; uint32 dir_list_size = 0; + const char *map_dir_list[8] = { NULL }; + uint32 map_dir_list_size = 0; const char *env_list[8] = { NULL }; uint32 env_list_size = 0; const char *addr_pool[8] = { NULL }; @@ -711,6 +716,16 @@ main(int argc, char *argv[]) } dir_list[dir_list_size++] = argv[0] + 6; } + else if (!strncmp(argv[0], "--map-dir=", 10)) { + if (argv[0][10] == '\0') + return print_help(); + if (map_dir_list_size >= sizeof(map_dir_list) / sizeof(char *)) { + printf("Only allow max map dir number %d\n", + (int)(sizeof(map_dir_list) / sizeof(char *))); + return 1; + } + map_dir_list[map_dir_list_size++] = argv[0] + 10; + } else if (!strncmp(argv[0], "--env=", 6)) { char *tmp_env; @@ -920,8 +935,9 @@ main(int argc, char *argv[]) } #if WASM_ENABLE_LIBC_WASI != 0 - wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, - env_list, env_list_size, argv, argc); + wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, + map_dir_list, map_dir_list_size, env_list, + env_list_size, argv, argc); wasm_runtime_set_wasi_addr_pool(wasm_module, addr_pool, addr_pool_size); wasm_runtime_set_wasi_ns_lookup_pool(wasm_module, ns_lookup_pool, From 51a6b069d215133fe6a13a1488438071319368be Mon Sep 17 00:00:00 2001 From: Gavin Hayes Date: Fri, 27 Oct 2023 02:07:16 -0400 Subject: [PATCH 10/14] Fix use getrandom on cosmopolitan libc (#2674) Fixes the Cosmopolitan Libc platform attempting to use `/dev/urandom` on operating systems that do not have it. Signed-off-by: G4Vi --- .../libc-wasi/sandboxed-system-primitives/src/ssp_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h index a69d6ca38..6a1db8690 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h @@ -26,8 +26,8 @@ // On Linux, prefer to use getrandom, though it isn't available in // GLIBC before 2.25. -#if (defined(__linux__) || defined(ESP_PLATFORM)) \ - && (!defined(__GLIBC__) || __GLIBC__ > 2 \ +#if (defined(__linux__) || defined(ESP_PLATFORM) || defined(__COSMOPOLITAN__)) \ + && (!defined(__GLIBC__) || __GLIBC__ > 2 \ || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) #define CONFIG_HAS_GETRANDOM 1 #else From 4b1a6e5017cb7ffec98a9fa2d8db28d37334a7cf Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Mon, 30 Oct 2023 11:07:01 +0800 Subject: [PATCH 11/14] Fix repeatedly initialize shared memory data and protect the memory's fields (#2673) Avoid repeatedly initializing the shared memory data when creating the child thread in lib-pthread or lib-wasi-threads. Add shared memory lock when accessing some fields of the memory instance if the memory instance is shared. Init shared memory's memory_data_size/memory_data_end fields according to the current page count but not max page count. Add wasm_runtime_set_mem_bound_check_bytes, and refine the error message when shared memory flag is found but the feature isn't enabled. --- core/iwasm/aot/aot_runtime.c | 89 ++++++++++++--------- core/iwasm/common/wasm_memory.c | 102 +++++++++++++++++------- core/iwasm/common/wasm_memory.h | 4 + core/iwasm/common/wasm_runtime_common.c | 3 +- core/iwasm/common/wasm_runtime_common.h | 8 ++ core/iwasm/common/wasm_shared_memory.c | 5 ++ core/iwasm/interpreter/wasm_loader.c | 10 ++- core/iwasm/interpreter/wasm_runtime.c | 84 ++++++++++--------- 8 files changed, 195 insertions(+), 110 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 0799d625f..3b3d2d743 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -7,6 +7,7 @@ #include "bh_log.h" #include "mem_alloc.h" #include "../common/wasm_runtime_common.h" +#include "../common/wasm_memory.h" #include "../interpreter/wasm_runtime.h" #if WASM_ENABLE_SHARED_MEMORY != 0 #include "../common/wasm_shared_memory.h" @@ -382,7 +383,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, uint32 inc_page_count, aux_heap_base, global_idx; uint32 bytes_of_last_page, bytes_to_page_end; uint32 heap_offset = num_bytes_per_page * init_page_count; - uint64 total_size; + uint64 memory_data_size, max_memory_data_size; uint8 *p = NULL, *global_addr; #ifdef OS_ENABLE_HW_BOUND_CHECK uint8 *mapped_mem; @@ -496,23 +497,34 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, module->aux_stack_size); LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size); - total_size = (uint64)num_bytes_per_page * init_page_count; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (is_shared_memory) { - /* Allocate max page for shared memory */ - total_size = (uint64)num_bytes_per_page * max_page_count; - } -#endif - bh_assert(total_size <= UINT32_MAX); + memory_data_size = (uint64)num_bytes_per_page * init_page_count; + max_memory_data_size = (uint64)num_bytes_per_page * max_page_count; + bh_assert(memory_data_size <= UINT32_MAX); + bh_assert(max_memory_data_size <= 4 * (uint64)BH_GB); + (void)max_memory_data_size; #ifndef OS_ENABLE_HW_BOUND_CHECK - /* Allocate memory */ - if (total_size > 0 - && !(p = runtime_malloc(total_size, error_buf, error_buf_size))) { - return NULL; +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (is_shared_memory) { + /* Allocate maximum memory size when memory is shared */ + if (max_memory_data_size > 0 + && !(p = runtime_malloc(max_memory_data_size, error_buf, + error_buf_size))) { + return NULL; + } } -#else - total_size = (total_size + page_size - 1) & ~(page_size - 1); + else +#endif + { + /* Allocate initial memory size when memory is not shared */ + if (memory_data_size > 0 + && !(p = runtime_malloc(memory_data_size, error_buf, + error_buf_size))) { + return NULL; + } + } +#else /* else of OS_ENABLE_HW_BOUND_CHECK */ + memory_data_size = (memory_data_size + page_size - 1) & ~(page_size - 1); /* Totally 8G is mapped, the opcode load/store address range is 0 to 8G: * ea = i + memarg.offset @@ -526,17 +538,18 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, } #ifdef BH_PLATFORM_WINDOWS - if (!os_mem_commit(p, total_size, MMAP_PROT_READ | MMAP_PROT_WRITE)) { + if (!os_mem_commit(p, memory_data_size, MMAP_PROT_READ | MMAP_PROT_WRITE)) { set_error_buf(error_buf, error_buf_size, "commit memory failed"); os_munmap(mapped_mem, map_size); return NULL; } #endif - if (os_mprotect(p, total_size, MMAP_PROT_READ | MMAP_PROT_WRITE) != 0) { + if (os_mprotect(p, memory_data_size, MMAP_PROT_READ | MMAP_PROT_WRITE) + != 0) { set_error_buf(error_buf, error_buf_size, "mprotect memory failed"); #ifdef BH_PLATFORM_WINDOWS - os_mem_decommit(p, total_size); + os_mem_decommit(p, memory_data_size); #endif os_munmap(mapped_mem, map_size); return NULL; @@ -545,18 +558,15 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, * again here */ #endif /* end of OS_ENABLE_HW_BOUND_CHECK */ - if (total_size > UINT32_MAX) - total_size = UINT32_MAX; - memory_inst->module_type = Wasm_Module_AoT; memory_inst->num_bytes_per_page = num_bytes_per_page; memory_inst->cur_page_count = init_page_count; memory_inst->max_page_count = max_page_count; - memory_inst->memory_data_size = (uint32)total_size; + memory_inst->memory_data_size = (uint32)memory_data_size; /* Init memory info */ memory_inst->memory_data = p; - memory_inst->memory_data_end = p + (uint32)total_size; + memory_inst->memory_data_end = p + (uint32)memory_data_size; /* Initialize heap info */ memory_inst->heap_data = p + heap_offset; @@ -579,20 +589,8 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, } } - if (total_size > 0) { -#if UINTPTR_MAX == UINT64_MAX - memory_inst->mem_bound_check_1byte.u64 = total_size - 1; - memory_inst->mem_bound_check_2bytes.u64 = total_size - 2; - memory_inst->mem_bound_check_4bytes.u64 = total_size - 4; - memory_inst->mem_bound_check_8bytes.u64 = total_size - 8; - memory_inst->mem_bound_check_16bytes.u64 = total_size - 16; -#else - memory_inst->mem_bound_check_1byte.u32[0] = (uint32)total_size - 1; - memory_inst->mem_bound_check_2bytes.u32[0] = (uint32)total_size - 2; - memory_inst->mem_bound_check_4bytes.u32[0] = (uint32)total_size - 4; - memory_inst->mem_bound_check_8bytes.u32[0] = (uint32)total_size - 8; - memory_inst->mem_bound_check_16bytes.u32[0] = (uint32)total_size - 16; -#endif + if (memory_data_size > 0) { + wasm_runtime_set_mem_bound_check_bytes(memory_inst, memory_data_size); } #if WASM_ENABLE_SHARED_MEMORY != 0 @@ -613,7 +611,7 @@ fail1: #else #ifdef BH_PLATFORM_WINDOWS if (memory_inst->memory_data) - os_mem_decommit(p, total_size); + os_mem_decommit(p, memory_data_size); #endif os_munmap(mapped_mem, map_size); #endif @@ -673,6 +671,10 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, if (data_seg->is_passive) continue; #endif + if (parent != NULL) + /* Ignore setting memory init data if the memory has been + initialized */ + continue; bh_assert(data_seg->offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST || data_seg->offset.init_expr_type @@ -1897,6 +1899,13 @@ aot_module_free_internal(AOTModuleInstance *module_inst, WASMExecEnv *exec_env, if (ptr) { uint8 *addr = memory_inst->memory_data + ptr; + uint8 *memory_data_end; + + /* memory->memory_data_end may be changed in memory grow */ + SHARED_MEMORY_LOCK(memory_inst); + memory_data_end = memory_inst->memory_data_end; + SHARED_MEMORY_UNLOCK(memory_inst); + if (memory_inst->heap_handle && memory_inst->heap_data < addr && addr < memory_inst->heap_data_end) { mem_allocator_free(memory_inst->heap_handle, addr); @@ -1904,7 +1913,7 @@ aot_module_free_internal(AOTModuleInstance *module_inst, WASMExecEnv *exec_env, else if (module->malloc_func_index != (uint32)-1 && module->free_func_index != (uint32)-1 && memory_inst->memory_data <= addr - && addr < memory_inst->memory_data_end) { + && addr < memory_data_end) { AOTFunctionInstance *free_func; char *free_func_name; @@ -2298,7 +2307,9 @@ aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index, uint32 offset, maddr = wasm_runtime_addr_app_to_native( (WASMModuleInstanceCommon *)module_inst, dst); + SHARED_MEMORY_LOCK(memory_inst); bh_memcpy_s(maddr, memory_inst->memory_data_size - dst, data + offset, len); + SHARED_MEMORY_UNLOCK(memory_inst); return true; } diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 05635ef51..cf29afe0e 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -298,10 +298,15 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm, goto fail; } + SHARED_MEMORY_LOCK(memory_inst); + if (app_offset + size <= memory_inst->memory_data_size) { + SHARED_MEMORY_UNLOCK(memory_inst); return true; } + SHARED_MEMORY_UNLOCK(memory_inst); + fail: wasm_set_exception(module_inst, "out of bounds memory access"); return false; @@ -364,11 +369,16 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm, goto fail; } + SHARED_MEMORY_LOCK(memory_inst); + if (memory_inst->memory_data <= addr && addr + size <= memory_inst->memory_data_end) { + SHARED_MEMORY_UNLOCK(memory_inst); return true; } + SHARED_MEMORY_UNLOCK(memory_inst); + fail: wasm_set_exception(module_inst, "out of bounds memory access"); return false; @@ -393,20 +403,24 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm, return NULL; } + SHARED_MEMORY_LOCK(memory_inst); + addr = memory_inst->memory_data + app_offset; if (bounds_checks) { if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end) { - + SHARED_MEMORY_UNLOCK(memory_inst); return addr; } } /* If bounds checks is disabled, return the address directly */ else if (app_offset != 0) { + SHARED_MEMORY_UNLOCK(memory_inst); return addr; } + SHARED_MEMORY_UNLOCK(memory_inst); return NULL; } @@ -418,6 +432,7 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm, WASMMemoryInstance *memory_inst; uint8 *addr = (uint8 *)native_ptr; bool bounds_checks; + uint32 ret; bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode || module_inst_comm->module_type == Wasm_Module_AoT); @@ -429,16 +444,24 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm, return 0; } + SHARED_MEMORY_LOCK(memory_inst); + if (bounds_checks) { if (memory_inst->memory_data <= addr - && addr < memory_inst->memory_data_end) - return (uint32)(addr - memory_inst->memory_data); + && addr < memory_inst->memory_data_end) { + ret = (uint32)(addr - memory_inst->memory_data); + SHARED_MEMORY_UNLOCK(memory_inst); + return ret; + } } /* If bounds checks is disabled, return the offset directly */ else if (addr != NULL) { - return (uint32)(addr - memory_inst->memory_data); + ret = (uint32)(addr - memory_inst->memory_data); + SHARED_MEMORY_UNLOCK(memory_inst); + return ret; } + SHARED_MEMORY_UNLOCK(memory_inst); return 0; } @@ -459,6 +482,8 @@ wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst_comm, return false; } + SHARED_MEMORY_LOCK(memory_inst); + memory_data_size = memory_inst->memory_data_size; if (app_offset < memory_data_size) { @@ -466,9 +491,11 @@ wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst_comm, *p_app_start_offset = 0; if (p_app_end_offset) *p_app_end_offset = memory_data_size; + SHARED_MEMORY_UNLOCK(memory_inst); return true; } + SHARED_MEMORY_UNLOCK(memory_inst); return false; } @@ -490,15 +517,19 @@ wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst_comm, return false; } + SHARED_MEMORY_LOCK(memory_inst); + if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end) { if (p_native_start_addr) *p_native_start_addr = memory_inst->memory_data; if (p_native_end_addr) *p_native_end_addr = memory_inst->memory_data_end; + SHARED_MEMORY_UNLOCK(memory_inst); return true; } + SHARED_MEMORY_UNLOCK(memory_inst); return false; } @@ -512,9 +543,12 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, bool bounds_checks; if (!memory_inst) { - goto fail; + wasm_set_exception(module_inst, "out of bounds memory access"); + return false; } + SHARED_MEMORY_LOCK(memory_inst); + native_addr = memory_inst->memory_data + app_buf_addr; bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst); @@ -551,12 +585,18 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, } #endif + SHARED_MEMORY_UNLOCK(memory_inst); + success: *p_native_addr = (void *)native_addr; return true; + +#ifndef OS_ENABLE_HW_BOUND_CHECK fail: + SHARED_MEMORY_UNLOCK(memory_inst); wasm_set_exception(module_inst, "out of bounds memory access"); return false; +#endif } WASMMemoryInstance * @@ -568,6 +608,27 @@ wasm_get_default_memory(WASMModuleInstance *module_inst) return NULL; } +void +wasm_runtime_set_mem_bound_check_bytes(WASMMemoryInstance *memory, + uint64 memory_data_size) +{ +#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0 +#if UINTPTR_MAX == UINT64_MAX + memory->mem_bound_check_1byte.u64 = memory_data_size - 1; + memory->mem_bound_check_2bytes.u64 = memory_data_size - 2; + memory->mem_bound_check_4bytes.u64 = memory_data_size - 4; + memory->mem_bound_check_8bytes.u64 = memory_data_size - 8; + memory->mem_bound_check_16bytes.u64 = memory_data_size - 16; +#else + memory->mem_bound_check_1byte.u32[0] = (uint32)memory_data_size - 1; + memory->mem_bound_check_2bytes.u32[0] = (uint32)memory_data_size - 2; + memory->mem_bound_check_4bytes.u32[0] = (uint32)memory_data_size - 4; + memory->mem_bound_check_8bytes.u32[0] = (uint32)memory_data_size - 8; + memory->mem_bound_check_16bytes.u32[0] = (uint32)memory_data_size - 16; +#endif +#endif +} + #ifndef OS_ENABLE_HW_BOUND_CHECK bool wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) @@ -625,9 +686,10 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) memory->num_bytes_per_page = num_bytes_per_page; memory->cur_page_count = total_page_count; memory->max_page_count = max_page_count; - /* No need to update memory->memory_data_size as it is - initialized with the maximum memory data size for - shared memory */ + memory->memory_data_size = (uint32)total_size_new; + memory->memory_data_end = memory->memory_data + (uint32)total_size_new; + + wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new); return true; } #endif @@ -679,21 +741,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) memory->memory_data = memory_data_new; memory->memory_data_end = memory_data_new + (uint32)total_size_new; -#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0 -#if UINTPTR_MAX == UINT64_MAX - memory->mem_bound_check_1byte.u64 = total_size_new - 1; - memory->mem_bound_check_2bytes.u64 = total_size_new - 2; - memory->mem_bound_check_4bytes.u64 = total_size_new - 4; - memory->mem_bound_check_8bytes.u64 = total_size_new - 8; - memory->mem_bound_check_16bytes.u64 = total_size_new - 16; -#else - memory->mem_bound_check_1byte.u32[0] = (uint32)total_size_new - 1; - memory->mem_bound_check_2bytes.u32[0] = (uint32)total_size_new - 2; - memory->mem_bound_check_4bytes.u32[0] = (uint32)total_size_new - 4; - memory->mem_bound_check_8bytes.u32[0] = (uint32)total_size_new - 8; - memory->mem_bound_check_16bytes.u32[0] = (uint32)total_size_new - 16; -#endif -#endif + wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new); #if defined(os_writegsbase) /* write base addr of linear memory to GS segment register */ @@ -799,13 +847,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) memory->memory_data_size = (uint32)total_size_new; memory->memory_data_end = memory->memory_data + (uint32)total_size_new; -#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0 - memory->mem_bound_check_1byte.u64 = total_size_new - 1; - memory->mem_bound_check_2bytes.u64 = total_size_new - 2; - memory->mem_bound_check_4bytes.u64 = total_size_new - 4; - memory->mem_bound_check_8bytes.u64 = total_size_new - 8; - memory->mem_bound_check_16bytes.u64 = total_size_new - 16; -#endif + wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new); return_func: if (!ret && enlarge_memory_error_cb) { diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h index daca2b71e..c46b32ea7 100644 --- a/core/iwasm/common/wasm_memory.h +++ b/core/iwasm/common/wasm_memory.h @@ -24,6 +24,10 @@ wasm_runtime_memory_destroy(); unsigned wasm_runtime_memory_pool_size(); +void +wasm_runtime_set_mem_bound_check_bytes(WASMMemoryInstance *memory, + uint64 memory_data_size); + void wasm_runtime_set_enlarge_mem_error_callback( const enlarge_memory_error_callback_t callback, void *user_data); diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index 031fb539d..36d9c33a6 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -3038,7 +3038,8 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, } } - strncpy(mapping_copy, map_dir_list[i], strlen(map_dir_list[i]) + 1); + bh_memcpy_s(mapping_copy, max_len, map_dir_list[i], + (uint32)(strlen(map_dir_list[i]) + 1)); map_mapped = strtok(mapping_copy, "::"); map_host = strtok(NULL, "::"); diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index a834d67f2..4e14ed4a1 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -298,6 +298,14 @@ LOAD_I16(void *addr) #endif /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */ +#if WASM_ENABLE_SHARED_MEMORY != 0 +#define SHARED_MEMORY_LOCK(memory) shared_memory_lock(memory) +#define SHARED_MEMORY_UNLOCK(memory) shared_memory_unlock(memory) +#else +#define SHARED_MEMORY_LOCK(memory) (void)0 +#define SHARED_MEMORY_UNLOCK(memory) (void)0 +#endif + typedef struct WASMModuleCommon { /* Module type, for module loaded from WASM bytecode binary, this field is Wasm_Module_Bytecode, and this structure should diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index c95d4b7ed..d36ca1833 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -301,12 +301,15 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, return -1; } + shared_memory_lock(module_inst->memories[0]); if ((uint8 *)address < module_inst->memories[0]->memory_data || (uint8 *)address + (wait64 ? 8 : 4) > module_inst->memories[0]->memory_data_end) { + shared_memory_unlock(module_inst->memories[0]); wasm_runtime_set_exception(module, "out of bounds memory access"); return -1; } + shared_memory_unlock(module_inst->memories[0]); #if WASM_ENABLE_THREAD_MGR != 0 exec_env = @@ -423,9 +426,11 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address, bh_assert(module->module_type == Wasm_Module_Bytecode || module->module_type == Wasm_Module_AoT); + shared_memory_lock(module_inst->memories[0]); out_of_bounds = ((uint8 *)address < module_inst->memories[0]->memory_data || (uint8 *)address + 4 > module_inst->memories[0]->memory_data_end); + shared_memory_unlock(module_inst->memories[0]); if (out_of_bounds) { wasm_runtime_set_exception(module, "out of bounds memory access"); diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 4afa1157c..ea2eb70f5 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -1375,7 +1375,15 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory, return false; } if (memory->flags > 1) { - set_error_buf(error_buf, error_buf_size, "integer too large"); + if (memory->flags & 2) { + set_error_buf(error_buf, error_buf_size, + "shared memory flag was found, " + "please enable shared memory, lib-pthread " + "or lib-wasi-threads"); + } + else { + set_error_buf(error_buf, error_buf_size, "invalid memory flags"); + } return false; } #else diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 8fb19d52e..d89470652 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -10,6 +10,7 @@ #include "bh_log.h" #include "mem_alloc.h" #include "../common/wasm_runtime_common.h" +#include "../common/wasm_memory.h" #if WASM_ENABLE_SHARED_MEMORY != 0 #include "../common/wasm_shared_memory.h" #endif @@ -167,7 +168,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, char *error_buf, uint32 error_buf_size) { WASMModule *module = module_inst->module; - uint64 memory_data_size; + uint64 memory_data_size, max_memory_data_size; uint32 heap_offset = num_bytes_per_page * init_page_count; uint32 inc_page_count, aux_heap_base, global_idx; uint32 bytes_of_last_page, bytes_to_page_end; @@ -282,22 +283,33 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size); memory_data_size = (uint64)num_bytes_per_page * init_page_count; -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (is_shared_memory) { - /* Allocate max page for shared memory */ - memory_data_size = (uint64)num_bytes_per_page * max_page_count; - } -#endif - bh_assert(memory_data_size <= 4 * (uint64)BH_GB); + max_memory_data_size = (uint64)num_bytes_per_page * max_page_count; + bh_assert(memory_data_size <= UINT32_MAX); + bh_assert(max_memory_data_size <= 4 * (uint64)BH_GB); + (void)max_memory_data_size; bh_assert(memory != NULL); #ifndef OS_ENABLE_HW_BOUND_CHECK - if (memory_data_size > 0 - && !(memory->memory_data = - runtime_malloc(memory_data_size, error_buf, error_buf_size))) { - goto fail1; +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (is_shared_memory) { + /* Allocate maximum memory size when memory is shared */ + if (max_memory_data_size > 0 + && !(memory->memory_data = runtime_malloc( + max_memory_data_size, error_buf, error_buf_size))) { + goto fail1; + } } -#else + else +#endif + { + /* Allocate initial memory size when memory is not shared */ + if (memory_data_size > 0 + && !(memory->memory_data = runtime_malloc( + memory_data_size, error_buf, error_buf_size))) { + goto fail1; + } + } +#else /* else of OS_ENABLE_HW_BOUND_CHECK */ memory_data_size = (memory_data_size + page_size - 1) & ~(page_size - 1); /* Totally 8G is mapped, the opcode load/store address range is 0 to 8G: @@ -330,9 +342,6 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, * again here */ #endif /* end of OS_ENABLE_HW_BOUND_CHECK */ - if (memory_data_size > UINT32_MAX) - memory_data_size = (uint32)memory_data_size; - memory->module_type = Wasm_Module_Bytecode; memory->num_bytes_per_page = num_bytes_per_page; memory->cur_page_count = init_page_count; @@ -359,23 +368,9 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, } } -#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 if (memory_data_size > 0) { -#if UINTPTR_MAX == UINT64_MAX - memory->mem_bound_check_1byte.u64 = memory_data_size - 1; - memory->mem_bound_check_2bytes.u64 = memory_data_size - 2; - memory->mem_bound_check_4bytes.u64 = memory_data_size - 4; - memory->mem_bound_check_8bytes.u64 = memory_data_size - 8; - memory->mem_bound_check_16bytes.u64 = memory_data_size - 16; -#else - memory->mem_bound_check_1byte.u32[0] = (uint32)memory_data_size - 1; - memory->mem_bound_check_2bytes.u32[0] = (uint32)memory_data_size - 2; - memory->mem_bound_check_4bytes.u32[0] = (uint32)memory_data_size - 4; - memory->mem_bound_check_8bytes.u32[0] = (uint32)memory_data_size - 8; - memory->mem_bound_check_16bytes.u32[0] = (uint32)memory_data_size - 16; -#endif + wasm_runtime_set_mem_bound_check_bytes(memory, memory_data_size); } -#endif #if WASM_ENABLE_SHARED_MEMORY != 0 if (is_shared_memory) { @@ -1779,6 +1774,10 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, if (data_seg->is_passive) continue; #endif + if (is_sub_inst) + /* Ignore setting memory init data if the memory has been + initialized */ + continue; /* has check it in loader */ memory = module_inst->memories[data_seg->memory_index]; @@ -2472,15 +2471,20 @@ void wasm_module_free_internal(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, uint32 ptr) { + WASMMemoryInstance *memory = wasm_get_default_memory(module_inst); + + if (!memory) { + return; + } + if (ptr) { - WASMMemoryInstance *memory = wasm_get_default_memory(module_inst); - uint8 *addr; + uint8 *addr = memory->memory_data + ptr; + uint8 *memory_data_end; - if (!memory) { - return; - } - - addr = memory->memory_data + ptr; + /* memory->memory_data_end may be changed in memory grow */ + SHARED_MEMORY_LOCK(memory); + memory_data_end = memory->memory_data_end; + SHARED_MEMORY_UNLOCK(memory); if (memory->heap_handle && memory->heap_data <= addr && addr < memory->heap_data_end) { @@ -2488,7 +2492,7 @@ wasm_module_free_internal(WASMModuleInstance *module_inst, } else if (module_inst->e->malloc_function && module_inst->e->free_function && memory->memory_data <= addr - && addr < memory->memory_data_end) { + && addr < memory_data_end) { execute_free_function(module_inst, exec_env, module_inst->e->free_function, ptr); } @@ -3150,7 +3154,9 @@ llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index, maddr = wasm_runtime_addr_app_to_native( (WASMModuleInstanceCommon *)module_inst, dst); + SHARED_MEMORY_LOCK(memory_inst); bh_memcpy_s(maddr, memory_inst->memory_data_size - dst, data + offset, len); + SHARED_MEMORY_UNLOCK(memory_inst); return true; } From 613c7ca48f7dcc6e6ede6a3a0826d065036fa542 Mon Sep 17 00:00:00 2001 From: Benedikt Becker Date: Mon, 30 Oct 2023 06:50:48 +0100 Subject: [PATCH 12/14] Minor fixes for Go bindings (#2676) --- language-bindings/go/go.mod | 2 +- language-bindings/go/samples/test.go | 2 +- language-bindings/go/wamr/instance.go | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/language-bindings/go/go.mod b/language-bindings/go/go.mod index 60afebbff..b7e428654 100644 --- a/language-bindings/go/go.mod +++ b/language-bindings/go/go.mod @@ -1,4 +1,4 @@ -module gitlab.alipay-inc.com/TNT_Runtime/ant-runtime/bindings/go +module github.com/bytecodealliance/wasm-micro-runtime/language-bindings/go go 1.15 diff --git a/language-bindings/go/samples/test.go b/language-bindings/go/samples/test.go index aacb4a950..d0fc7d8b2 100644 --- a/language-bindings/go/samples/test.go +++ b/language-bindings/go/samples/test.go @@ -6,7 +6,7 @@ package main import ( - "gitlab.alipay-inc.com/TNT_Runtime/ant-runtime/bindings/go/wamr" + "github.com/bytecodealliance/wasm-micro-runtime/language-bindings/go/wamr" "fmt" ) diff --git a/language-bindings/go/wamr/instance.go b/language-bindings/go/wamr/instance.go index 08757f4dc..7c761ee99 100644 --- a/language-bindings/go/wamr/instance.go +++ b/language-bindings/go/wamr/instance.go @@ -272,7 +272,9 @@ func (self *Instance) CallFuncV(funcName string, for i = 0; i < result_count; i++ { switch result_types[i] { case C.WASM_I32: + fallthrough case C.WASM_FUNCREF: + fallthrough case C.WASM_ANYREF: i32 := (int32)(argv[argc]) results[i] = i32 From 3570a94a089bff3cf25fc2609e6a71efc0bc4616 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 31 Oct 2023 10:48:51 +0800 Subject: [PATCH 13/14] Fix issues reported by Coverity (#2681) Fix multi-module issues and gui sample issues reported by Coverity. And refine the build script of go language-binding sample. --- language-bindings/go/samples/build.sh | 14 +++----------- product-mini/platforms/posix/main.c | 2 +- product-mini/platforms/windows/main.c | 2 +- samples/gui/wasm-apps/decrease/src/main.c | 16 ++++++++-------- samples/gui/wasm-apps/increase/src/main.c | 16 ++++++++-------- samples/multi-module/src/main.c | 5 +++-- 6 files changed, 24 insertions(+), 31 deletions(-) diff --git a/language-bindings/go/samples/build.sh b/language-bindings/go/samples/build.sh index 1b0a80719..0799fe5a0 100755 --- a/language-bindings/go/samples/build.sh +++ b/language-bindings/go/samples/build.sh @@ -3,19 +3,11 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -PLATFORM=$(uname -s | tr A-Z a-z) CUR_DIR=$PWD -WAMR_DIR=$PWD/../../.. -WAMR_GO_DIR=$PWD/../wamr -cp -a ${WAMR_DIR}/core/iwasm/include/*.h ${WAMR_GO_DIR}/packaged/include - -mkdir -p build && cd build -cmake ${WAMR_DIR}/product-mini/platforms/${PLATFORM} \ - -DWAMR_BUILD_LIB_PTHREAD=1 -DWAMR_BUILD_DUMP_CALL_STACK=1 \ - -DWAMR_BUILD_MEMORY_PROFILING=1 -make -j ${nproc} -cp -a libvmlib.a ${WAMR_GO_DIR}/packaged/lib/${PLATFORM}-amd64 +pushd ${CUR_DIR}/.. > /dev/null 2>&1 +./build.sh +popd > /dev/null 2>& 1 cd ${CUR_DIR} rm -f test diff --git a/product-mini/platforms/posix/main.c b/product-mini/platforms/posix/main.c index 08fd65f16..09bf7c551 100644 --- a/product-mini/platforms/posix/main.c +++ b/product-mini/platforms/posix/main.c @@ -438,7 +438,7 @@ module_reader_callback(package_type_t module_type, const char *module_name, const char *format = "%s/%s%s"; int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + strlen(file_format) + 1; - char *wasm_file_name = BH_MALLOC(sz); + char *wasm_file_name = wasm_runtime_malloc(sz); if (!wasm_file_name) { return false; } diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c index f6347919b..bba427302 100644 --- a/product-mini/platforms/windows/main.c +++ b/product-mini/platforms/windows/main.c @@ -219,7 +219,7 @@ module_reader_callback(package_type_t module_type, const char *module_name, const char *format = "%s/%s%s"; int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + strlen(file_format) + 1; - char *wasm_file_name = BH_MALLOC(sz); + char *wasm_file_name = wasm_runtime_malloc(sz); if (!wasm_file_name) { return false; } diff --git a/samples/gui/wasm-apps/decrease/src/main.c b/samples/gui/wasm-apps/decrease/src/main.c index a6c30aa1a..9635ebea8 100644 --- a/samples/gui/wasm-apps/decrease/src/main.c +++ b/samples/gui/wasm-apps/decrease/src/main.c @@ -46,14 +46,14 @@ on_init() count_label = lv_label_create(NULL, NULL); lv_obj_align(count_label, NULL, LV_ALIGN_IN_TOP_MID, 0, 0); - btn1 = lv_btn_create( - NULL, NULL); /*Create a button on the currently loaded screen*/ - lv_obj_set_event_cb( - btn1, - btn_event_cb); /*Set function to be called when the button is released*/ - lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, 0); /*Align below the label*/ + /* Create a button on the currently loaded screen */ + btn1 = lv_btn_create(NULL, NULL); + /* Set function to be called when the button is released */ + lv_obj_set_event_cb(btn1, (lv_event_cb_t)btn_event_cb); + /* Align below the label */ + lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, 0); - /*Create a label on the button*/ + /* Create a label on the button */ lv_obj_t *btn_label = lv_label_create(btn1, NULL); lv_label_set_text(btn_label, "Click --"); @@ -61,7 +61,7 @@ on_init() lv_label_set_text(label_count1, "100"); lv_obj_align(label_count1, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0); - /* set up a timer */ + /* Set up a timer */ user_timer_t timer; timer = api_timer_create(10, true, false, timer1_update); if (timer) diff --git a/samples/gui/wasm-apps/increase/src/main.c b/samples/gui/wasm-apps/increase/src/main.c index b5271830a..31118f7be 100644 --- a/samples/gui/wasm-apps/increase/src/main.c +++ b/samples/gui/wasm-apps/increase/src/main.c @@ -46,14 +46,14 @@ on_init() count_label = lv_label_create(NULL, NULL); lv_obj_align(count_label, NULL, LV_ALIGN_IN_TOP_MID, 0, 0); - btn1 = lv_btn_create( - NULL, NULL); /*Create a button on the currently loaded screen*/ - lv_obj_set_event_cb( - btn1, - btn_event_cb); /*Set function to be called when the button is released*/ - lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, 0); /*Align below the label*/ + /* Create a button on the current loaded screen */ + btn1 = lv_btn_create(NULL, NULL); + /* Set function to be called when the button is released */ + lv_obj_set_event_cb(btn1, (lv_event_cb_t)btn_event_cb); + /* Align below the label */ + lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, 0); - /*Create a label on the button*/ + /* Create a label on the button */ lv_obj_t *btn_label = lv_label_create(btn1, NULL); lv_label_set_text(btn_label, "Click ++"); @@ -61,7 +61,7 @@ on_init() lv_label_set_text(label_count1, "1"); lv_obj_align(label_count1, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0); - /* set up a timer */ + /* Set up a timer */ user_timer_t timer; timer = api_timer_create(10, true, false, timer1_update); if (timer) diff --git a/samples/multi-module/src/main.c b/samples/multi-module/src/main.c index 361856136..c63cf6b8c 100644 --- a/samples/multi-module/src/main.c +++ b/samples/multi-module/src/main.c @@ -11,7 +11,7 @@ static bool module_reader_callback(package_type_t module_type, const char *module_name, uint8 **p_buffer, uint32 *p_size) { - char *file_format; + char *file_format = NULL; #if WASM_ENABLE_INTERP != 0 if (module_type == Wasm_Module_Bytecode) file_format = ".wasm"; @@ -21,10 +21,11 @@ module_reader_callback(package_type_t module_type, const char *module_name, file_format = ".aot"; #endif + bh_assert(file_format != NULL); const char *format = "%s/%s%s"; int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + strlen(file_format) + 1; - char *wasm_file_name = BH_MALLOC(sz); + char *wasm_file_name = wasm_runtime_malloc(sz); if (!wasm_file_name) { return false; } From 52db362b897221c2a438197a0f2e4a9a300becd4 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Tue, 31 Oct 2023 11:46:03 +0800 Subject: [PATCH 14/14] Refine lock/unlock shared memory (#2682) Split memory instance's field `uint32 ref_count` into `bool is_shared_memory` and `uint16 ref_count`, and lock the memory only when `is_shared_memory` flag is true, no need to acquire a lock for non-shared memory when shared memory feature is enabled. --- core/iwasm/aot/aot_runtime.c | 1 + core/iwasm/common/wasm_memory.c | 6 +-- core/iwasm/common/wasm_shared_memory.c | 72 +++++++------------------- core/iwasm/common/wasm_shared_memory.h | 29 ++++++++--- core/iwasm/interpreter/wasm_runtime.c | 1 + core/iwasm/interpreter/wasm_runtime.h | 5 +- core/shared/utils/bh_atomic.h | 60 +++++++++++++++++++++ 7 files changed, 110 insertions(+), 64 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 3b3d2d743..954da4153 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -595,6 +595,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, #if WASM_ENABLE_SHARED_MEMORY != 0 if (is_shared_memory) { + memory_inst->is_shared_memory = true; memory_inst->ref_count = 1; } #endif diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index cf29afe0e..e97f92df3 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -547,8 +547,6 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, return false; } - SHARED_MEMORY_LOCK(memory_inst); - native_addr = memory_inst->memory_data + app_buf_addr; bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst); @@ -563,6 +561,8 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, /* No need to check the app_offset and buf_size if memory access boundary check with hardware trap is enabled */ #ifndef OS_ENABLE_HW_BOUND_CHECK + SHARED_MEMORY_LOCK(memory_inst); + if (app_buf_addr >= memory_inst->memory_data_size) { goto fail; } @@ -583,9 +583,9 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str, if (str == str_end) goto fail; } -#endif SHARED_MEMORY_UNLOCK(memory_inst); +#endif success: *p_native_addr = (void *)native_addr; diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index d36ca1833..70e84a375 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -18,7 +18,7 @@ * - If you care performance, it's better to make the interpreters * use atomic ops. */ -static korp_mutex _shared_memory_lock; +korp_mutex g_shared_memory_lock; /* clang-format off */ enum { @@ -55,13 +55,13 @@ destroy_wait_info(void *wait_info); bool wasm_shared_memory_init() { - if (os_mutex_init(&_shared_memory_lock) != 0) + if (os_mutex_init(&g_shared_memory_lock) != 0) return false; /* wait map not exists, create new map */ if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash, (KeyEqualFunc)wait_address_equal, NULL, destroy_wait_info))) { - os_mutex_destroy(&_shared_memory_lock); + os_mutex_destroy(&g_shared_memory_lock); return false; } return true; @@ -71,79 +71,47 @@ void wasm_shared_memory_destroy() { bh_hash_map_destroy(wait_map); - os_mutex_destroy(&_shared_memory_lock); + os_mutex_destroy(&g_shared_memory_lock); } -uint32 +uint16 shared_memory_inc_reference(WASMMemoryInstance *memory) { bh_assert(shared_memory_is_shared(memory)); - uint32 old; -#if BH_ATOMIC_32_IS_ATOMIC == 0 - os_mutex_lock(&_shared_memory_lock); + uint16 old; +#if BH_ATOMIC_16_IS_ATOMIC == 0 + os_mutex_lock(&g_shared_memory_lock); #endif - old = BH_ATOMIC_32_FETCH_ADD(memory->ref_count, 1); -#if BH_ATOMIC_32_IS_ATOMIC == 0 - os_mutex_unlock(&_shared_memory_lock); + old = BH_ATOMIC_16_FETCH_ADD(memory->ref_count, 1); +#if BH_ATOMIC_16_IS_ATOMIC == 0 + os_mutex_unlock(&g_shared_memory_lock); #endif bh_assert(old >= 1); - bh_assert(old < UINT32_MAX); + bh_assert(old < UINT16_MAX); return old + 1; } -uint32 +uint16 shared_memory_dec_reference(WASMMemoryInstance *memory) { bh_assert(shared_memory_is_shared(memory)); - uint32 old; -#if BH_ATOMIC_32_IS_ATOMIC == 0 - os_mutex_lock(&_shared_memory_lock); + uint16 old; +#if BH_ATOMIC_16_IS_ATOMIC == 0 + os_mutex_lock(&g_shared_memory_lock); #endif - old = BH_ATOMIC_32_FETCH_SUB(memory->ref_count, 1); -#if BH_ATOMIC_32_IS_ATOMIC == 0 - os_mutex_unlock(&_shared_memory_lock); + old = BH_ATOMIC_16_FETCH_SUB(memory->ref_count, 1); +#if BH_ATOMIC_16_IS_ATOMIC == 0 + os_mutex_unlock(&g_shared_memory_lock); #endif bh_assert(old > 0); return old - 1; } -bool -shared_memory_is_shared(WASMMemoryInstance *memory) -{ - uint32 old; -#if BH_ATOMIC_32_IS_ATOMIC == 0 - os_mutex_lock(&_shared_memory_lock); -#endif - old = BH_ATOMIC_32_LOAD(memory->ref_count); -#if BH_ATOMIC_32_IS_ATOMIC == 0 - os_mutex_unlock(&_shared_memory_lock); -#endif - return old > 0; -} - static korp_mutex * shared_memory_get_lock_pointer(WASMMemoryInstance *memory) { bh_assert(memory != NULL); - return &_shared_memory_lock; -} - -void -shared_memory_lock(WASMMemoryInstance *memory) -{ - /* - * Note: exception logic is currently abusing this lock. - * cf. https://github.com/bytecodealliance/wasm-micro-runtime/issues/2407 - */ - bh_assert(memory != NULL); - os_mutex_lock(&_shared_memory_lock); -} - -void -shared_memory_unlock(WASMMemoryInstance *memory) -{ - bh_assert(memory != NULL); - os_mutex_unlock(&_shared_memory_lock); + return &g_shared_memory_lock; } /* Atomics wait && notify APIs */ diff --git a/core/iwasm/common/wasm_shared_memory.h b/core/iwasm/common/wasm_shared_memory.h index 6a6538d21..8bbc4a800 100644 --- a/core/iwasm/common/wasm_shared_memory.h +++ b/core/iwasm/common/wasm_shared_memory.h @@ -14,26 +14,39 @@ extern "C" { #endif +extern korp_mutex g_shared_memory_lock; + bool wasm_shared_memory_init(); void wasm_shared_memory_destroy(); -uint32 +uint16 shared_memory_inc_reference(WASMMemoryInstance *memory); -uint32 +uint16 shared_memory_dec_reference(WASMMemoryInstance *memory); -bool -shared_memory_is_shared(WASMMemoryInstance *memory); +#define shared_memory_is_shared(memory) memory->is_shared_memory -void -shared_memory_lock(WASMMemoryInstance *memory); +#define shared_memory_lock(memory) \ + do { \ + /* \ + * Note: exception logic is currently abusing this lock. \ + * cf. \ + * https://github.com/bytecodealliance/wasm-micro-runtime/issues/2407 \ + */ \ + bh_assert(memory != NULL); \ + if (memory->is_shared_memory) \ + os_mutex_lock(&g_shared_memory_lock); \ + } while (0) -void -shared_memory_unlock(WASMMemoryInstance *memory); +#define shared_memory_unlock(memory) \ + do { \ + if (memory->is_shared_memory) \ + os_mutex_unlock(&g_shared_memory_lock); \ + } while (0) uint32 wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address, diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index d89470652..a87001696 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -374,6 +374,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, #if WASM_ENABLE_SHARED_MEMORY != 0 if (is_shared_memory) { + memory->is_shared_memory = true; memory->ref_count = 1; } #endif diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index d6661fa0f..7d78df14f 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -79,8 +79,11 @@ typedef union { struct WASMMemoryInstance { /* Module type */ uint32 module_type; + + bool is_shared_memory; + /* Shared memory flag */ - bh_atomic_32_t ref_count; /* 0: non-shared, > 0: reference count */ + bh_atomic_16_t ref_count; /* 0: non-shared, > 0: reference count */ /* Number bytes per page */ uint32 num_bytes_per_page; diff --git a/core/shared/utils/bh_atomic.h b/core/shared/utils/bh_atomic.h index 64dfee1b6..ac3417c30 100644 --- a/core/shared/utils/bh_atomic.h +++ b/core/shared/utils/bh_atomic.h @@ -45,6 +45,7 @@ extern "C" { */ typedef uint32 bh_atomic_32_t; +typedef uint16 bh_atomic_16_t; #if defined(__GNUC_PREREQ) #if __GNUC_PREREQ(4, 7) @@ -59,6 +60,7 @@ typedef uint32 bh_atomic_32_t; #if defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) #define BH_ATOMIC_32_IS_ATOMIC 1 #define BH_ATOMIC_32_LOAD(v) __atomic_load_n(&(v), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_32_STORE(v, val) __atomic_store_n(&(v), val, __ATOMIC_SEQ_CST) #define BH_ATOMIC_32_FETCH_OR(v, val) \ __atomic_fetch_or(&(v), (val), __ATOMIC_SEQ_CST) #define BH_ATOMIC_32_FETCH_AND(v, val) \ @@ -67,13 +69,33 @@ typedef uint32 bh_atomic_32_t; __atomic_fetch_add(&(v), (val), __ATOMIC_SEQ_CST) #define BH_ATOMIC_32_FETCH_SUB(v, val) \ __atomic_fetch_sub(&(v), (val), __ATOMIC_SEQ_CST) + +#define BH_ATOMIC_16_IS_ATOMIC 1 +#define BH_ATOMIC_16_LOAD(v) __atomic_load_n(&(v), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_16_STORE(v, val) __atomic_store_n(&(v), val, __ATOMIC_SEQ_CST) +#define BH_ATOMIC_16_FETCH_OR(v, val) \ + __atomic_fetch_or(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_16_FETCH_AND(v, val) \ + __atomic_fetch_and(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_16_FETCH_ADD(v, val) \ + __atomic_fetch_add(&(v), (val), __ATOMIC_SEQ_CST) +#define BH_ATOMIC_16_FETCH_SUB(v, val) \ + __atomic_fetch_sub(&(v), (val), __ATOMIC_SEQ_CST) #else /* else of defined(CLANG_GCC_HAS_ATOMIC_BUILTIN) */ #define BH_ATOMIC_32_LOAD(v) (v) +#define BH_ATOMIC_32_STORE(v, val) (v) = val #define BH_ATOMIC_32_FETCH_OR(v, val) nonatomic_32_fetch_or(&(v), val) #define BH_ATOMIC_32_FETCH_AND(v, val) nonatomic_32_fetch_and(&(v), val) #define BH_ATOMIC_32_FETCH_ADD(v, val) nonatomic_32_fetch_add(&(v), val) #define BH_ATOMIC_32_FETCH_SUB(v, val) nonatomic_32_fetch_sub(&(v), val) +#define BH_ATOMIC_16_LOAD(v) (v) +#define BH_ATOMIC_16_STORE(v) (v) = val +#define BH_ATOMIC_16_FETCH_OR(v, val) nonatomic_16_fetch_or(&(v), val) +#define BH_ATOMIC_16_FETCH_AND(v, val) nonatomic_16_fetch_and(&(v), val) +#define BH_ATOMIC_16_FETCH_ADD(v, val) nonatomic_16_fetch_add(&(v), val) +#define BH_ATOMIC_16_FETCH_SUB(v, val) nonatomic_16_fetch_sub(&(v), val) + static inline uint32 nonatomic_32_fetch_or(bh_atomic_32_t *p, uint32 val) { @@ -106,6 +128,38 @@ nonatomic_32_fetch_sub(bh_atomic_32_t *p, uint32 val) return old; } +static inline uint16 +nonatomic_16_fetch_or(bh_atomic_16_t *p, uint16 val) +{ + uint16 old = *p; + *p |= val; + return old; +} + +static inline uint16 +nonatomic_16_fetch_and(bh_atomic_16_t *p, uint16 val) +{ + uint16 old = *p; + *p &= val; + return old; +} + +static inline uint16 +nonatomic_16_fetch_add(bh_atomic_16_t *p, uint16 val) +{ + uint16 old = *p; + *p += val; + return old; +} + +static inline uint16 +nonatomic_16_fetch_sub(bh_atomic_16_t *p, uint16 val) +{ + uint16 old = *p; + *p -= val; + return old; +} + /* The flag can be defined by the user if the platform supports atomic access to uint32 aligned memory. */ #ifdef WASM_UINT32_IS_ATOMIC @@ -114,6 +168,12 @@ nonatomic_32_fetch_sub(bh_atomic_32_t *p, uint32 val) #define BH_ATOMIC_32_IS_ATOMIC 0 #endif /* WASM_UINT32_IS_ATOMIC */ +#ifdef WASM_UINT16_IS_ATOMIC +#define BH_ATOMIC_16_IS_ATOMIC 1 +#else /* else of WASM_UINT16_IS_ATOMIC */ +#define BH_ATOMIC_16_IS_ATOMIC 0 +#endif /* WASM_UINT16_IS_ATOMIC */ + #endif #ifdef __cplusplus