- Translate all the opcodes of threads spec proposal for Fast JIT
- Add the atomic flag for Fast JIT load/store IRs to support atomic load/store
- Add new atomic related Fast JIT IRs and translate them in the codegen
- Add suspend_flags check in branch opcodes and before/after call function
- Modify CI to enable Fast JIT multi-threading test
Co-authored-by: TianlongLiang <tianlong.liang@intel.com>
In LLVM AOT/JIT compiler, only need to check the suspend_flags when memory is
a shared memory since the shared memory must be enabled for multi-threading,
so as not to impact the performance in non-multi-threading memory mode. Also
refine the LLVM IRs to check the suspend_flags.
And fix an issue of multi-tier jit for multi-threading, the instance of the child thread
should be removed from the instance list before it is de-instantiated.
Load memory data size in each time memory access boundary check in
multi-threading mode since it may be changed by other threads when
memory growing.
And use `memory->memory_data_size` instead of
`memory->num_bytes_per_page * memory->cur_page_count` to refine
the code.
When ref.func opcode refers to a function whose function index no smaller than
current function, the destination func should be forward-declared: it is declared
in the table element segments, or is declared in the export list.
Try using existing exec_env to execute wasm app's malloc/free func and
execute post instantiation functions. Create a new exec_env only when
no existing exec_env was found.
Use pre-created exec_env for instantiation and module_malloc/free,
use the same exec_env of the current thread to avoid potential
unexpected behavior.
And remove unnecessary shared_mem_lock in wasm_module_free,
which may cause dead lock.
Use the shared memory's shared_mem_lock to lock the whole atomic.wait and
atomic.notify processes, and use it for os_cond_reltimedwait and os_cond_notify,
so as to make the whole processes actual atomic operations:
the original implementation accesses the wait address with shared_mem_lock
and uses wait_node->wait_lock for os_cond_reltimedwait, which is not an atomic
operation.
And remove the unnecessary wait_map_lock and wait_lock, since the whole
processes are already locked by shared_mem_lock.
- Remove notify_stale_threads_on_exception and change atomic.wait
to be interruptible by keep waiting and checking every one second,
like the implementation of poll_oneoff in libc-wasi
- Wait all other threads exit and then get wasi exit_code to avoid
getting invalid value
- Inherit suspend_flags of parent thread while creating new thread to
avoid terminated flag isn't set for new thread
- Fix wasi-threads test case update_shared_data_and_alloc_heap
- Add "Lib wasi-threads enabled" prompt for cmake
- Fix aot get exception, use aot_copy_exception instead
- Add python script to test socket-api cases
- Fix issues in socket-api send_recv wasm app
- Fix issues in building samples/workload/meshoptimizer
- Enhance build script of sample workload
- Implement atomic.fence to ensure a proper memory synchronization order
- Destroy exec_env_singleton first in wasm/aot deinstantiation
- Change terminate other threads to wait for other threads in
wasm_exec_env_destroy
- Fix detach thread in thread_manager_start_routine
- Fix duplicated lock cluster->lock in wasm_cluster_cancel_thread
- Add lib-pthread and lib-wasi-threads compilation to Windows CI
In wasm_cluster_create_thread, the new_exec_env is added into the cluster's
exec_env list before the thread is created, so other threads can access the
fields of new_exec_env once the cluster->lock is unlocked, while the
new_exec_env's handle is set later inside the thread routine. This may result
in the new_exec_env's handle be invalidly accessed by other threads.
- CMakeLists.txt: add lib_export.h to install list
- Fast JIT: enlarge spill cache size to enable several standalone cases
when hw bound check is disabled
- Thread manager: wasm_cluster_exit_thread may destroy an invalid
exec_env->module_inst when exec_env was destroyed before
- samples/socket-api: fix failure to run timeout_client.wasm
- enhance CI build wasi-libc and sample/wasm-c-api-imports CMakeLlist.txt
Support collecting code coverage with wamr-test-suites script by using
lcov and genhtml tools, eg.:
cd tests/wamr-test-suites
./test_wamr.sh -s spec -b -P -C
The default code coverage and html files are generated at:
tests/wamr-test-suites/workspace/wamr.lcov
tests/wamr-test-suites/workspace/wamr-lcov.zip
And update wamr-test-suites scripts to support testing GC spec cases to
avoid frequent synchronization conflicts between branch main and dev/gc.
Raising "wasi proc exit" exception, spreading it to other threads and then
clearing it in all threads may result in unexpected behavior: the sub thread
may end first, handle the "wasi proc exit" exception and clear exceptions
of other threads, including the main thread. And when main thread's
exception is cleared, it may continue to run and throw "unreachable"
exception. This also leads to some assertion failed.
Ignore exception spreading for "wasi proc exit" and don't clear exception
of other threads to resolve the issue.
And add suspend flag check after atomic wait since the atomic wait may
be notified by other thread when exception occurs.
- Use execute_post_instantiate_functions to call start, _initialize,
__post_instantiate, __wasm_call_ctors functions after instantiation
- Always call start function for both main instance and sub instance
- Only call _initialize and __post_instantiate for main instance
- Only call ___wasm_call_ctors for main instance and when bulk memory
is enabled and wasi import functions are not found
- When hw bound check is enabled, use the existing exec_env_tls
to call func for sub instance, and switch exec_env_tls's module inst
to current module inst to avoid checking failure and using the wrong
module inst
Destroy child thread's exec_env before destroying its module instance and
add the process into cluster's lock to avoid possible data race: if exec_env
is removed from custer's exec_env_list and destroyed later, the main thread
may not wait it and start to destroy the wasm runtime, and the destroying
of the sub thread's exec_env may free or overread/written an destroyed or
re-initialized resource.
And fix an issue in wasm_cluster_cancel_thread.
The start/initialize functions of wasi module are to do some initialization work
during instantiation, which should be only called one time in the instantiation
of main instance. For example, they may initialize the data in linear memory,
if the data is changed later by the main instance, and re-initialized again by
the child instance, unexpected behaviors may occur.
And clear a shadow warning in classic interpreter.
When de-instantiating the wasm module instance, remove it from the module's
instance list before freeing func_ptrs and fast_jit_func_ptrs of the instance, to avoid
accessing these freed memory in the JIT backend compilation threads.
Enable setting running mode when executing a wasm bytecode file
- Four running modes are supported: interpreter, fast-jit, llvm-jit and multi-tier-jit
- Add APIs to set/get the default running mode of the runtime
- Add APIs to set/get the running mode of a wasm module instance
- Add running mode options for iwasm command line tool
And add size/opt level options for LLVM JIT
The definitions `enum WASMExceptionID` in the compilation of wamrc and the compilation
of Fast JIT are different, since the latter enables the Fast JIT macro while the former doesn't.
This causes that the exception ID in AOT file generated by wamrc may be different from
iwasm binary compiled with Fast JIT enabled, and may result in unexpected behavior.
Remove the macro control to resolve it.
Change an error to warning when checking wasi abi compatibility in loader, for rust case below:
#[no_mangle]
pub extern "C" fn main() {
println!("foo");
}
compile it with `cargo build --target wasm32-wasi`, a wasm file is generated with wasi apis imported
and a "void main(void)" function exported.
Other runtime e.g. wasmtime allows to load it and execute the main function with `--invoke` option.
Upgrade the version of related toolkits:
- upgrade llvm to 15.0
- upgrade wasi-sdk to 19.0
- upgrade emsdk to 3.1.28
- upgrade wabt to 1.0.31
- upgrade binaryen to 111
And upgrade the CI scripts, sample workload build scripts, Dockerfiles, and documents.
The original CI didn't actually run wasi test suite for x86-32 since the `TEST_ON_X86_32=true`
isn't written into $GITHUB_ENV.
And refine the error output when failed to link import global.
Add thread_wait_list_end node for thread data and cond for Windows platform
to speedup the thread join and cond wait operations: no need to traverse the
wait list to get the end node to append the wait node.
Should use import_function_count but not import_count to calculate
the func_index in handle_name_section when custom name section
feature is enabled.
And clear the compile warnings of mini loader.
Implement 2-level Multi-tier JIT engine: tier-up from Fast JIT to LLVM JIT to
get quick cold startup by Fast JIT and better performance by gradually
switching to LLVM JIT when the LLVM JIT functions are compiled by the
backend threads.
Refer to:
https://github.com/bytecodealliance/wasm-micro-runtime/issues/1302
Error was reported when building docker image:
/usr/bin/ld: libaotclib.a(aot_llvm_extra.cpp.o): relocation R_X86_64_32S against symbol
`_ZN4llvm30TargetTransformInfoWrapperPass2IDE' can not be used when making a PIE object;
recompile with -fPIC
Add `-fPIC` to `CMAKE_CXX_FLAGS` and `CMAKE_SHARED_LIBRARY_LINK_C_FLAGS` to fix it.
When a wasm module is duplicated instantiated with wasm_instance_new,
the function import info of the previous instantiation may be overwritten by
the later instantiation, which may cause unexpected behavior.
Store the function import info into the module instance to fix the issue.
Implement 2-level Multi-tier JIT engine: tier-up from Fast JIT to LLVM JIT to
get quick cold startup by Fast JIT and better performance by gradually
switching to LLVM JIT when the LLVM JIT functions are compiled by the
backend threads.
Refer to:
https://github.com/bytecodealliance/wasm-micro-runtime/issues/1302
Error was reported when building docker image:
/usr/bin/ld: libaotclib.a(aot_llvm_extra.cpp.o): relocation R_X86_64_32S against symbol
`_ZN4llvm30TargetTransformInfoWrapperPass2IDE' can not be used when making a PIE object;
recompile with -fPIC
Add `-fPIC` to `CMAKE_CXX_FLAGS` and `CMAKE_SHARED_LIBRARY_LINK_C_FLAGS` to fix it.
When a wasm module is duplicated instantiated with wasm_instance_new,
the function import info of the previous instantiation may be overwritten by
the later instantiation, which may cause unexpected behavior.
Store the function import info into the module instance to fix the issue.
Enable bulk memory by default since it is a finished wasm spec proposal
and is enabled by default in latest wasi-sdk. Developer often encounters
"invalid section id" or "unsupported opcode" error if it isn't enabled.
Refine AOT exception check in the caller when returning from callee function,
remove the exception check instructions when hw bound check is enabled to
improve the performance: create guard page to trigger signal handler when
exception occurs.
Current SGX lib-rats wasm module hash is stored in a global buffer,
which may be overwritten if there are multiple wasm module loadings.
We move the module hash into the enclave module to resolve the issue.
And rename the SGX_IPFS macro/variable in Makefile and Enclave.edl to
make the code more consistent.
And refine the sgx-ra sample document.
Enlarge the default wasm operand stack size to 64KB since the original default
size 16KB is a little small, and the operand stack overflow exception is often
thrown when running wasm apps.
Limit max_stack_cell_num/max_csp_num to be no larger than UINT16_MAX,
and don't check all_cell_num in interpreter again.
And refine some codes in interpreter.
Update build wasm app document, add how to set buildflags for Rust
project to reduce the footprint.
Clear Windows warnings and a shadow warning in aot_emit_numberic.c
Fix build error in sample ref-types and wasm-c-api caused by the
version of wat2wasm: refine makefile to auto detect the wat2wasm
version and add the compile flag accordingly.
Refine the generated LLVM IRs at the beginning of each LLVM AOT/JIT function
to fasten the LLVM IR optimization:
- Only create argv_buf if there are func calls in this function
- Only create native stack bound if stack bound check is enabled
- Only create aux stack info if there is opcode set_global_aux_stack
- Only create native symbol if indirect_mode is enabled
- Only create memory info if there are memory operations
- Only create func_type_indexes if there is opcode call_indirect
Clear warnings like below when building LLVM JIT and wamrc:
llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h:73:25:
warning: redundant move in return statement [-Wredundant-move]
73 | return std::move(Err);
Add a new options to control the native stack hw bound check feature:
- Besides the original option `cmake -DWAMR_DISABLE_HW_BOUND_CHECK=1/0`,
add a new option `cmake -DWAMR_DISABLE_STACK_HW_BOUND_CHECK=1/0`
- When the linear memory hw bound check is disabled, the stack hw bound check
will be disabled automatically, no matter what the input option is
- When the linear memory hw bound check is enabled, the stack hw bound check
is enabled/disabled according to the value of input option
- Besides the original option `--bounds-checks=1/0`, add a new option
`--stack-bounds-checks=1/0` for wamrc
Refer to: https://github.com/bytecodealliance/wasm-micro-runtime/issues/1677
Currently we initialize and destroy LLVM environment in aot_create_comp_context
and aot_destroy_comp_context, which are called in wasm_module_load/unload,
and the latter may be invoked multiple times, which leads to duplicated LLVM
initialization/destroy and may result in unexpected behaviors.
Move the LLVM init/destroy into runtime init/destroy to resolve the issue.
The host embedder may new/delete wasm-c-api engine simultaneously
in multiple threads, which requires lock for the operations. Since there
isn't one time called global init/destroy APIs provided by wasm-c-api,
we define a global lock and initialize it with thread mutex initializer if
the platform supports that, and use it to lock the operations of engine.
If the platform doesn't support thread mutex initializer, we require
developer to create the lock by himself to ensure the thread-safe of the
engine operations.
Add CIs to enable the release process of a new version of WAMR,
and build and publish the binary files when a version is released,
including iwasm, wamrc, lldb, vscode-extension and wamr-ide for
Ubuntu-20.04, Ubuntu-22.04 and MacOS.
And refine the CIs to test spec cases.
Some offsets can be directly gotten at the compilation stage after the interp/AOT
module instance refactoring PR was merged, so as to reduce some unnecessary
load instructions and improve the Fast JIT performance:
- Access fields of wasm memory instance structure
- Access fields of wasm table instance structure
- Access the global data
Translate call_indirect opcode by calling wasm functions with Fast JIT IRs instead of
calling jit_call_indirect runtime API, so as to improve the performance.
Translate call native function process with Fast JIT IRs to validate each pointer argument
and convert it into native address, and then call the native function directly instead
of calling jit_invoke_native runtime API, so as to improve the performance.
Refactor LLVM JIT for some purposes:
- To simplify the source code of JIT compilation
- To simplify the JIT modes
- To align with LLVM latest changes
- To prepare for the Multi-tier JIT compilation, refer to #1302
The changes mainly include:
- Remove the MCJIT mode, replace it with ORC JIT eager mode
- Remove the LLVM legacy pass manager (only keep the LLVM new pass manager)
- Change the lazy mode's LLVM module/function binding:
change each function in an individual LLVM module into all functions in a single LLVM module
- Upgraded ORC JIT to ORCv2 JIT to enable lazy compilation
Refer to #1468
Refactor the layout of interpreter and AOT module instance:
- Unify the interp/AOT module instance, use the same WASMModuleInstance/
WASMMemoryInstance/WASMTableInstance data structures for both interpreter
and AOT
- Make the offset of most fields the same in module instance for both interpreter
and AOT, append memory instance structure, global data and table instances to
the end of module instance for interpreter mode (like AOT mode)
- For extra fields in WASM module instance, use WASMModuleInstanceExtra to
create a field `e` for interpreter
- Change the LLVM JIT module instance creating process, LLVM JIT uses the WASM
module and module instance same as interpreter/Fast-JIT mode. So that Fast JIT
and LLVM JIT can access the same data structures, and make it possible to
implement the Multi-tier JIT (tier-up from Fast JIT to LLVM JIT) in the future
- Unify some APIs: merge some APIs for module instance and memory instance's
related operations (only implement one copy)
Note that the AOT ABI is same, the AOT file format, AOT relocation types, how AOT
code accesses the AOT module instance and so on are kept unchanged.
Refer to:
https://github.com/bytecodealliance/wasm-micro-runtime/issues/1384
Memory num_bytes_per_page was incorrectly set in memory enlarging for
shared memory, we fix it. And don't set memory_data_size again for shared
memory.
Implement more socket APIs, refer to #1336 and below PRs:
- Implement wasi_addr_resolve function (#1319)
- Fix socket-api byte order issue when host/network order are the same (#1327)
- Enhance sock_addr_local syscall (#1320)
- Implement sock_addr_remote syscall (#1360)
- Add support for IPv6 in WAMR (#1411)
- Implement ns lookup allowlist (#1420)
- Implement sock_send_to and sock_recv_from system calls (#1457)
- Added http downloader and multicast socket options (#1467)
- Fix `bind()` calls to receive the correct size of `sockaddr` structure (#1490)
- Assert on correct parameters (#1505)
- Copy only received bytes from socket recv buffer into the app buffer (#1497)
Co-authored-by: Marcin Kolny <mkolny@amazon.com>
Co-authored-by: Marcin Kolny <marcin.kolny@gmail.com>
Co-authored-by: Callum Macmillan <callumimacmillan@gmail.com>
And enable classic interpreter instead fast interpreter when llvm jit is enabled,
so as to fix the issue that llvm jit cannot handle opcode drop_64/select_64.