diff --git a/.github/workflows/build_docker_images.yml b/.github/workflows/build_docker_images.yml index 819bf94c3..d5bf682c4 100644 --- a/.github/workflows/build_docker_images.yml +++ b/.github/workflows/build_docker_images.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build and save Docker image(wasm-debug-server:${{ inputs.ver_num }}) to tar file run: | diff --git a/.github/workflows/build_iwasm_release.yml b/.github/workflows/build_iwasm_release.yml index 64aa9a92c..86e50ede9 100644 --- a/.github/workflows/build_iwasm_release.yml +++ b/.github/workflows/build_iwasm_release.yml @@ -35,11 +35,11 @@ jobs: build: runs-on: ${{ inputs.runner }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: get cached LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/build_llvm_libraries.yml b/.github/workflows/build_llvm_libraries.yml index a24e340fa..18b90e568 100644 --- a/.github/workflows/build_llvm_libraries.yml +++ b/.github/workflows/build_llvm_libraries.yml @@ -31,7 +31,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install dependencies run: /usr/bin/env python3 -m pip install -r requirements.txt @@ -52,7 +52,7 @@ jobs: - name: Cache LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -62,7 +62,7 @@ jobs: ./core/deps/llvm/build/share key: ${{ steps.create_lib_cache_key.outputs.key}} - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.ccache key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} @@ -70,7 +70,7 @@ jobs: 0-ccache-${{ inputs.os }} if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && inputs.os == 'ubuntu-20.04' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache/ccache key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} @@ -82,7 +82,7 @@ jobs: - run: sudo apt install -y ccache ninja-build if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'ubuntu') && inputs.container_image == '' - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/Library/Caches/ccache key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }} diff --git a/.github/workflows/build_wamr_lldb.yml b/.github/workflows/build_wamr_lldb.yml index 1a73750a6..3e1e10ffd 100644 --- a/.github/workflows/build_wamr_lldb.yml +++ b/.github/workflows/build_wamr_lldb.yml @@ -47,7 +47,7 @@ jobs: PYTHON_UBUNTU_STANDALONE_BUILD: https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-unknown-linux-gnu-install_only.tar.gz PYTHON_MACOS_STANDALONE_BUILD: https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-apple-darwin-install_only.tar.gz steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: download and install wasi-sdk run: | @@ -60,7 +60,7 @@ jobs: - name: Cache build id: lldb_build_cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm-project/build/bin diff --git a/.github/workflows/build_wamr_sdk.yml b/.github/workflows/build_wamr_sdk.yml index fff6d85df..f4ca9afd4 100644 --- a/.github/workflows/build_wamr_sdk.yml +++ b/.github/workflows/build_wamr_sdk.yml @@ -35,7 +35,7 @@ jobs: build: runs-on: ${{ inputs.runner }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: download and install wasi-sdk run: | diff --git a/.github/workflows/build_wamr_vscode_ext.yml b/.github/workflows/build_wamr_vscode_ext.yml index 3dfb290cf..b91f054cf 100644 --- a/.github/workflows/build_wamr_vscode_ext.yml +++ b/.github/workflows/build_wamr_vscode_ext.yml @@ -18,7 +18,7 @@ jobs: build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Use Node.js 16.x uses: actions/setup-node@v3 diff --git a/.github/workflows/build_wamrc.yml b/.github/workflows/build_wamrc.yml index 11c5de9ba..7c4dab039 100644 --- a/.github/workflows/build_wamrc.yml +++ b/.github/workflows/build_wamrc.yml @@ -35,11 +35,11 @@ jobs: build: runs-on: ${{ inputs.runner }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: get cached LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/coding_guidelines.yml b/.github/workflows/coding_guidelines.yml index 17d60ac43..b0aa0a2b8 100644 --- a/.github/workflows/coding_guidelines.yml +++ b/.github/workflows/coding_guidelines.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 diff --git a/.github/workflows/compilation_on_android_ubuntu.yml b/.github/workflows/compilation_on_android_ubuntu.yml index 98d346f9e..704d52547 100644 --- a/.github/workflows/compilation_on_android_ubuntu.yml +++ b/.github/workflows/compilation_on_android_ubuntu.yml @@ -85,13 +85,13 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # since jobs.id can't contain the dot character # it is hard to use `format` to assemble the cache key - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -213,13 +213,13 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # only download llvm cache when needed - name: Get LLVM libraries id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -284,12 +284,12 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get LLVM libraries id: retrieve_llvm_libs if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -322,7 +322,7 @@ jobs: run: | VERBOSE=1 cmake -S . -B build ${{ matrix.make_options }} - cmake --build build --config Release --parallel 4 + cmake --build build --config Debug --parallel 4 ctest --test-dir build --output-on-failure working-directory: samples/wasm-c-api @@ -350,7 +350,7 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk run: | @@ -367,7 +367,7 @@ jobs: sudo mv wabt-1.0.31 wabt - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -393,7 +393,7 @@ jobs: cd samples/file mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./src/iwasm -f wasm-app/file.wasm -d . - name: Build Sample [multi-thread] @@ -401,7 +401,7 @@ jobs: cd samples/multi-thread mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./iwasm wasm-apps/test.wasm - name: Build Sample [multi-module] @@ -409,7 +409,7 @@ jobs: cd samples/multi-module mkdir build && cd build cmake .. -DWAMR_BUILD_AOT=1 - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./multi_module mC.wasm ./multi_module mC.aot @@ -418,7 +418,7 @@ jobs: cd samples/spawn-thread mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./spawn_thread - name: Build Sample [ref-types] @@ -426,7 +426,7 @@ jobs: cd samples/ref-types mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./hello - name: Build Sample [simple] @@ -441,7 +441,7 @@ jobs: cd samples/wasi-threads mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./iwasm wasm-apps/no_pthread.wasm - name: Build Sample [shared-module] @@ -450,6 +450,12 @@ jobs: ./build.sh ./run.sh + - name: Build Sample [terminate] + run: | + cd samples/terminate + ./build.sh + ./run.sh + test: needs: [ @@ -513,7 +519,7 @@ jobs: test_option: $SIMD_TEST_OPTIONS steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk if: matrix.test_option == '$WASI_TEST_OPTIONS' @@ -548,7 +554,7 @@ jobs: - name: Get LLVM libraries if: env.USE_LLVM == 'true' id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -610,7 +616,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install dependencies run: | @@ -629,7 +635,7 @@ jobs: - name: Cache LLDB id: cache-lldb - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-lldb-vscode with: diff --git a/.github/workflows/compilation_on_macos.yml b/.github/workflows/compilation_on_macos.yml index 12f1d73cb..9d352fbcf 100644 --- a/.github/workflows/compilation_on_macos.yml +++ b/.github/workflows/compilation_on_macos.yml @@ -1,7 +1,7 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -name: compilation on macos-latest +name: compilation on macos on: # will be triggered on PR events @@ -55,27 +55,32 @@ env: LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0" jobs: - build_llvm_libraries: + build_llvm_libraries_on_intel_macos: uses: ./.github/workflows/build_llvm_libraries.yml with: os: "macos-latest" arch: "X86" + build_llvm_libraries_on_arm_macos: + uses: ./.github/workflows/build_llvm_libraries.yml + with: + os: "macos-14" + arch: "AArch64 ARM" build_wamrc: - needs: [build_llvm_libraries] + needs: [build_llvm_libraries_on_intel_macos] runs-on: ${{ matrix.os }} strategy: matrix: include: - os: macos-latest - llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }} + llvm_cache_key: ${{ needs.build_llvm_libraries_on_intel_macos.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -97,7 +102,7 @@ jobs: working-directory: wamr-compiler build_iwasm: - needs: [build_llvm_libraries] + needs: [build_llvm_libraries_on_intel_macos] runs-on: ${{ matrix.os }} strategy: matrix: @@ -171,16 +176,16 @@ jobs: make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" include: - os: macos-latest - llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }} + llvm_cache_key: ${{ needs.build_llvm_libraries_on_intel_macos.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # only download llvm cache when needed - name: Get LLVM libraries id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -226,7 +231,7 @@ jobs: ] steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wabt run: | @@ -243,11 +248,11 @@ jobs: working-directory: samples/wasm-c-api build_samples_others: - needs: [build_iwasm, build_wamrc] + needs: [build_iwasm, build_wamrc, build_llvm_libraries_on_intel_macos, build_llvm_libraries_on_arm_macos] runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-latest] + os: [macos-latest, macos-14] wasi_sdk_release: [ "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-macos.tar.gz", @@ -256,9 +261,14 @@ jobs: [ "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-macos-12.tar.gz", ] + include: + - os: macos-latest + llvm_cache_key: ${{ needs.build_llvm_libraries_on_intel_macos.outputs.cache_key }} + - os: macos-14 + llvm_cache_key: ${{ needs.build_llvm_libraries_on_arm_macos.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk run: | @@ -285,7 +295,7 @@ jobs: cd samples/file mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./src/iwasm -f wasm-app/file.wasm -d . - name: Build Sample [multi-thread] @@ -293,7 +303,7 @@ jobs: cd samples/multi-thread mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./iwasm wasm-apps/test.wasm - name: Build Sample [multi-module] @@ -301,7 +311,7 @@ jobs: cd samples/multi-module mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./multi_module mC.wasm - name: Build Sample [spawn-thread] @@ -309,7 +319,7 @@ jobs: cd samples/spawn-thread mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./spawn_thread - name: Build Sample [ref-types] @@ -317,19 +327,47 @@ jobs: cd samples/ref-types mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./hello + - name: Get LLVM libraries + id: retrieve_llvm_libs + uses: actions/cache@v4 + with: + path: | + ./core/deps/llvm/build/bin + ./core/deps/llvm/build/include + ./core/deps/llvm/build/lib + ./core/deps/llvm/build/libexec + ./core/deps/llvm/build/share + key: ${{ matrix.llvm_cache_key }} + + - name: Build wamrc + run: | + mkdir build && cd build + cmake .. + cmake --build . --config Release --parallel 4 + working-directory: wamr-compiler + - name: Build Sample [wasi-threads] run: | cd samples/wasi-threads mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 ./iwasm wasm-apps/no_pthread.wasm + ../../../wamr-compiler/build/wamrc --size-level=0 --enable-multi-thread -o wasm-apps/no_pthread.aot wasm-apps/no_pthread.wasm + ./iwasm wasm-apps/no_pthread.aot + - name: Build Sample [shared-module] run: | cd samples/shared-module ./build.sh ./run.sh + + - name: Build Sample [terminate] + run: | + cd samples/terminate + ./build.sh + ./run.sh diff --git a/.github/workflows/compilation_on_nuttx.yml b/.github/workflows/compilation_on_nuttx.yml index 8e1f4aad0..2eff73c2c 100644 --- a/.github/workflows/compilation_on_nuttx.yml +++ b/.github/workflows/compilation_on_nuttx.yml @@ -52,7 +52,7 @@ jobs: build_iwasm_on_nuttx: runs-on: ubuntu-latest container: - image: ghcr.io/apache/nuttx/apache-nuttx-ci-linux@sha256:4b4cbf0b70512e61ada9cdcb76b97e90ad478b85e4d0774d05a95fa32caa8c39 + image: ghcr.io/apache/nuttx/apache-nuttx-ci-linux@sha256:d9261eacf6c6ebe656c571757751c803e8f04c3ae9b820320a5ea5dd57b7205a strategy: matrix: @@ -87,21 +87,21 @@ jobs: steps: - name: Checkout NuttX - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: apache/incubator-nuttx - ref: releases/12.3 + ref: releases/12.4 path: nuttx - name: Checkout NuttX Apps - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: apache/incubator-nuttx-apps - ref: releases/12.3 + ref: releases/12.4 path: apps - name: Checkout WAMR - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ github.repository }} path: apps/interpreters/wamr/wamr diff --git a/.github/workflows/compilation_on_sgx.yml b/.github/workflows/compilation_on_sgx.yml index 0d19d83ad..8dadb518d 100644 --- a/.github/workflows/compilation_on_sgx.yml +++ b/.github/workflows/compilation_on_sgx.yml @@ -119,7 +119,7 @@ jobs: source /opt/intel/sgxsdk/environment - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build iwasm run: | @@ -165,7 +165,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk run: | @@ -221,7 +221,7 @@ jobs: - name: Get LLVM libraries if: matrix.iwasm_make_options_run_mode == '$AOT_BUILD_OPTIONS' id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -246,7 +246,7 @@ jobs: cd samples/file mkdir build && cd build cmake .. - cmake --build . --config Release --parallel 4 + cmake --build . --config Debug --parallel 4 cp wasm-app/file.wasm `pwd`/../../../product-mini/platforms/${{ matrix.platform }}/enclave-sample - name: Test Sample [file] in non-aot mode @@ -290,12 +290,12 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get LLVM libraries if: matrix.running_mode == 'aot' id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/compilation_on_windows.yml b/.github/workflows/compilation_on_windows.yml index 97a4aaae2..a623ab1a7 100644 --- a/.github/workflows/compilation_on_windows.yml +++ b/.github/workflows/compilation_on_windows.yml @@ -74,7 +74,7 @@ jobs: "-DWAMR_BUILD_LIBC_UVWASI=0 -DWAMR_BUILD_LIBC_WASI=1" ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: clone uvwasi library if: ${{ !contains(matrix.build_options, '-DWAMR_BUILD_LIBC_UVWASI=0') }} @@ -108,7 +108,7 @@ jobs: ] steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk if: matrix.test_option == '$WASI_TEST_OPTIONS' diff --git a/.github/workflows/create_tag.yml b/.github/workflows/create_tag.yml index 3a145bf04..27eee2acf 100644 --- a/.github/workflows/create_tag.yml +++ b/.github/workflows/create_tag.yml @@ -24,7 +24,7 @@ jobs: new_tag: ${{ steps.preparation.outputs.new_tag }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Full git history is needed to get a proper list of commits and tags with: fetch-depth: 0 diff --git a/.github/workflows/hadolint_dockerfiles.yml b/.github/workflows/hadolint_dockerfiles.yml index bdabeb6e5..c540649c8 100644 --- a/.github/workflows/hadolint_dockerfiles.yml +++ b/.github/workflows/hadolint_dockerfiles.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # on default, hadolint will fail on warnings and errors - name: Run hadolint on dockerfiles diff --git a/.github/workflows/nightly_run.yml b/.github/workflows/nightly_run.yml index 1bd0c4856..8b9a0ed5e 100644 --- a/.github/workflows/nightly_run.yml +++ b/.github/workflows/nightly_run.yml @@ -68,13 +68,13 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # since jobs.id can't contain the dot character # it is hard to use `format` to assemble the cache key - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -199,13 +199,13 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # only download llvm cache when needed - name: Get LLVM libraries id: retrieve_llvm_libs if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -347,12 +347,12 @@ jobs: sanitizer: asan steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get LLVM libraries id: retrieve_llvm_libs if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -383,7 +383,9 @@ jobs: - name: Build Sample [wasm-c-api] run: | VERBOSE=1 - cmake -S . -B build ${{ matrix.make_options }} -D WAMR_BUILD_SANITIZER="${{matrix.sanitizer}}" + cmake -S . -B build ${{ matrix.make_options }} \ + -D WAMR_BUILD_SANITIZER="${{matrix.sanitizer}}" \ + -D WAMR_BUILD_QUICK_AOT_ENTRY=0 cmake --build build --config Release --parallel 4 ctest --test-dir build --output-on-failure working-directory: samples/wasm-c-api @@ -412,7 +414,7 @@ jobs: llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }} steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk run: | @@ -429,7 +431,7 @@ jobs: - name: Get LLVM libraries id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin @@ -507,6 +509,12 @@ jobs: cd samples/shared-module ./build.sh ./run.sh + + - name: Build Sample [terminate] + run: | + cd samples/terminate + ./build.sh + ./run.sh test: needs: [ @@ -593,7 +601,7 @@ jobs: test_option: $SIMD_TEST_OPTIONS steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: download and install wasi-sdk if: matrix.test_option == '$WASI_TEST_OPTIONS' @@ -631,7 +639,7 @@ jobs: - name: Get LLVM libraries if: env.USE_LLVM == 'true' id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin diff --git a/.github/workflows/release_process.yml b/.github/workflows/release_process.yml index ef722acdb..5808b821c 100644 --- a/.github/workflows/release_process.yml +++ b/.github/workflows/release_process.yml @@ -28,7 +28,7 @@ jobs: outputs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: prepare the release note run: | diff --git a/.github/workflows/reuse_latest_release_binaries.yml b/.github/workflows/reuse_latest_release_binaries.yml index 7f82672a6..c9832cec9 100644 --- a/.github/workflows/reuse_latest_release_binaries.yml +++ b/.github/workflows/reuse_latest_release_binaries.yml @@ -28,7 +28,7 @@ jobs: outputs: result: ${{ steps.try_reuse.outputs.result }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Full git history is needed to get a proper list of commits and tags with: fetch-depth: 0 diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 957f82f34..5bdad8f23 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -28,13 +28,13 @@ jobs: with: os: "ubuntu-22.04" arch: "ARM RISCV AArch64" - container_image: ghcr.io/apache/nuttx/apache-nuttx-ci-linux@sha256:4b4cbf0b70512e61ada9cdcb76b97e90ad478b85e4d0774d05a95fa32caa8c39 + container_image: ghcr.io/apache/nuttx/apache-nuttx-ci-linux@sha256:d9261eacf6c6ebe656c571757751c803e8f04c3ae9b820320a5ea5dd57b7205a spec_test_on_qemu: runs-on: ubuntu-latest needs: [build_llvm_libraries] container: - image: ghcr.io/apache/nuttx/apache-nuttx-ci-linux@sha256:4b4cbf0b70512e61ada9cdcb76b97e90ad478b85e4d0774d05a95fa32caa8c39 + image: ghcr.io/apache/nuttx/apache-nuttx-ci-linux@sha256:d9261eacf6c6ebe656c571757751c803e8f04c3ae9b820320a5ea5dd57b7205a strategy: matrix: target_config: [ @@ -96,21 +96,21 @@ jobs: steps: - name: Checkout NuttX - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: apache/incubator-nuttx - ref: releases/12.3 + ref: releases/12.4 path: nuttx - name: Checkout NuttX Apps - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: apache/incubator-nuttx-apps - ref: releases/12.3 + ref: releases/12.4 path: apps - name: Checkout WAMR - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ github.repository }} path: apps/interpreters/wamr/wamr @@ -118,7 +118,7 @@ jobs: - name: Get LLVM libraries if: contains(matrix.wamr_test_option.mode, 'aot') id: retrieve_llvm_libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ./core/deps/llvm/build/bin diff --git a/README.md b/README.md index dfdae2da8..31156b9cc 100644 --- a/README.md +++ b/README.md @@ -75,9 +75,9 @@ The following platforms are supported, click each link below for how to build iw - [Blog: The WAMR memory model](https://bytecodealliance.github.io/wamr.dev/blog/the-wamr-memory-model/) - [Blog: Understand WAMR heaps](https://bytecodealliance.github.io/wamr.dev/blog/understand-the-wamr-heaps/) and [stacks](https://bytecodealliance.github.io/wamr.dev/blog/understand-the-wamr-stacks/) - [Blog: Introduction to WAMR running modes](https://bytecodealliance.github.io/wamr.dev/blog/introduction-to-wamr-running-modes/) -- [Memory usage tunning](./doc/memory_tune.md): the memory model and how to tune the memory usage +- [Memory usage tuning](./doc/memory_tune.md): the memory model and how to tune the memory usage - [Memory usage profiling](./doc/build_wamr.md#enable-memory-profiling-experiment): how to profile the memory usage -- [Performance tunning](./doc/perf_tune.md): how to tune the performance +- [Performance tuning](./doc/perf_tune.md): how to tune the performance - [Benchmarks](./tests/benchmarks): checkout these links for how to run the benchmarks: [PolyBench](./tests/benchmarks/polybench), [CoreMark](./tests/benchmarks/coremark), [Sightglass](./tests/benchmarks/sightglass), [JetStream2](./tests/benchmarks/jetstream) - [Performance and footprint data](https://github.com/bytecodealliance/wasm-micro-runtime/wiki/Performance): the performance and footprint data diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e2cda8858..3fcfaf4bc 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,79 @@ +## WAMR-1.3.2 + +### Breaking Changes + +### New Features +- Implement Exception Handling for classic interpreter (#3096) + - Use `cmake -DWAMR_BUILD_EXCE_HANDLING=1/0` option to enable/disable + the feature, and by default it is disabled + - It is still in highly experimental stage + +### Bug Fixes +- Fix build errors when initializing wasm_val_t values with macros (#3007) +- fix(wasm-c-api): Do not clone stack frames if there's no trap (#3008) +- classic-interp: Handle SIMD opcode when JIT is enabled (#3046) +- fast-interp: Fix dynamic offset error issue in else branch (#3058) +- wasm_cluster_destroy_spawned_exec_env: Avoid "invalid exec env" trap (#3068) +- thread-mgr: Fix locking problems around aux stack allocation (#3073) +- cosmopolitan: Update compiler and update platform_internal.h (#3079) +- wasi: Apply wasm_runtime_begin_blocking_op to poll as well (#3080) +- Fix memory/table segment checks in memory.init/table.init (#3081) +- perf profiling: Adjust the calculation of execution time (#3089) +- aot: Fix LLVMSetTailCallKind check (#3099) +- fast-interp: Fix stack recovery for else branch (#3100) +- fast-interp: Fix frame_offset pop order (#3101) +- Fix AOT compilation on MacOS (#3102) +- fast-interp: Fix block with parameter in polymorphic stack issue (#3112) +- Fix read and validation of misc/simd/atomic sub opcodes (#3115) + +### Enhancements +- Clear compilation warning and dead code (#3002) +- aot debug: Try to use a bit more appropriate file names (#3000) +- Increase default app thread stack size (#3010) +- Rename rwlock_init to avoid conflict (#3016) +- nuttx: Use larger alignment for os_mmap and comment why (#3017) +- Allow using mmap for shared memory if hw bound check is disabled (#3029) +- Don't redefine D_INO if already defined (#3036) +- Enhancements on wasm function execution time statistic (#2985) +- wamr-compiler: Fix non-x86{_64} host builds (#3037) +- Disable quick aot entry for interp and fast-jit (#3039) +- nuttx: Add option to enable quick aot entry (#3040) +- Set CONFIG_HAS_CAP_ENTER to support posix file api for freertos (#3041) +- Revert "Enable MAP_32BIT for macOS (#2992)" (#3032) +- Enable quick aot entry when hw bound check is disabled (#3044) +- Do not inherit WASM_SUSPEND_FLAG_BLOCKING from the parent thread (#3051) +- wasm_runtime_begin_blocking_op: A comment about usage expectation (#3056) +- Check arguments before calling bh_hash_map_find (#3055) +- Fix aot large model (--size-level=0) with LLVM 18 (#3057) +- Add flag to control Winsocket initialization (#3060) +- nuttx: If STACK_GUARD_SIZE is not set, leave it to config.h (#2927) +- Enhance setting write gs base with cmake variable (#3066) +- aot_reloc_x86_64.c: Suggest to try --size-level=0 as well (#3067) +- Fix some issues reported by CodeQL (#3064) +- Remove a lot of "unused parameter" warnings (#3075) +- Forward log and log level to custom bh_log callback (#3070) +- Fix inconsistent code style in aot_loader.c (#3082) +- freertos: Thread exit more common (#3094) +- Fix windows build error and compilation warnings (#3095) + +### Others +- Fix nightly-run CI failure (#3014) +- Build samples in debug mode (#3019) +- Remove deprecated tests in language-bindings python (#3018) +- Avoid unused thread_id warning and recompile multi-module sample (#3033) +- samples/terminate: Add a sample to demonstrate wasm_runtime_terminate (#3043) +- Bump NuttX version to 12.4.x in CI (#3047) +- perf_tune.md: Add refine the calling processes between host and wasm (#3065) +- build_wamr.md: Update the document (#3074) +- Fix download link for wasi-sdk (#3077) +- README.md: Fix typo tunning to tuning (#3078) +- Update outdated reference link in multi_module.md (#3092) +- Add comments to suppress warning from clang-tidy (#3088) +- CI: Update version of checkout to suppress warnings (#3093) +- test_wamr.sh: Allow using test script on different platforms (#3098) + +--- + ## WAMR-1.3.1 ### Breaking Changes diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 212141d5e..f370927e8 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -329,9 +329,17 @@ if (WAMR_BUILD_REF_TYPES EQUAL 1) else () message (" Reference types disabled") endif () +if (WAMR_BUILD_EXCE_HANDLING EQUAL 1) + add_definitions (-DWASM_ENABLE_EXCE_HANDLING=1) + add_definitions (-DWASM_ENABLE_TAGS=1) + message (" Exception Handling enabled") +endif () if (DEFINED WAMR_BH_VPRINTF) add_definitions (-DBH_VPRINTF=${WAMR_BH_VPRINTF}) endif () +if (DEFINED WAMR_BH_LOG) + add_definitions (-DBH_LOG=${WAMR_BH_LOG}) +endif () if (WAMR_DISABLE_APP_ENTRY EQUAL 1) message (" WAMR application entry functions excluded") endif () @@ -415,32 +423,49 @@ if (WAMR_BUILD_STATIC_PGO EQUAL 1) add_definitions (-DWASM_ENABLE_STATIC_PGO=1) message (" AOT static PGO enabled") endif () -if (WAMR_DISABLE_WRITE_GS_BASE EQUAL 1) - add_definitions (-DWASM_DISABLE_WRITE_GS_BASE=1) - message (" Write linear memory base addr to x86 GS register disabled") -elseif (WAMR_BUILD_TARGET STREQUAL "X86_64" - AND WAMR_BUILD_PLATFORM STREQUAL "linux") - set (TEST_WRGSBASE_SOURCE "${CMAKE_BINARY_DIR}/test_wrgsbase.c") - file (WRITE "${TEST_WRGSBASE_SOURCE}" " - #include - #include - int main() { - uint64_t value; - asm volatile (\"wrgsbase %0\" : : \"r\"(value)); - printf(\"WRGSBASE instruction is available.\\n\"); - return 0; - }") - # Try to compile and run the test program - try_run (TEST_WRGSBASE_RESULT - TEST_WRGSBASE_COMPILED - ${CMAKE_BINARY_DIR}/test_wrgsbase - SOURCES ${TEST_WRGSBASE_SOURCE} - CMAKE_FLAGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} - ) - #message("${TEST_WRGSBASE_COMPILED}, ${TEST_WRGSBASE_RESULT}") - if (NOT TEST_WRGSBASE_RESULT EQUAL 0) +if (WAMR_BUILD_TARGET STREQUAL "X86_64" + AND WAMR_BUILD_PLATFORM STREQUAL "linux") + if (WAMR_DISABLE_WRITE_GS_BASE EQUAL 1) + # disabled by user + set (DISABLE_WRITE_GS_BASE 1) + elseif (WAMR_DISABLE_WRITE_GS_BASE EQUAL 0) + # enabled by user + set (DISABLE_WRITE_GS_BASE 0) + elseif (CMAKE_CROSSCOMPILING) + # disabled in cross compilation environment + set (DISABLE_WRITE_GS_BASE 1) + else () + # auto-detected by the compiler + set (TEST_WRGSBASE_SOURCE "${CMAKE_BINARY_DIR}/test_wrgsbase.c") + file (WRITE "${TEST_WRGSBASE_SOURCE}" " + #include + #include + int main() { + uint64_t value; + asm volatile (\"wrgsbase %0\" : : \"r\"(value)); + printf(\"WRGSBASE instruction is available.\\n\"); + return 0; + }") + # Try to compile and run the test program + try_run (TEST_WRGSBASE_RESULT + TEST_WRGSBASE_COMPILED + ${CMAKE_BINARY_DIR}/test_wrgsbase + SOURCES ${TEST_WRGSBASE_SOURCE} + CMAKE_FLAGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + ) + #message("${TEST_WRGSBASE_COMPILED}, ${TEST_WRGSBASE_RESULT}") + if (TEST_WRGSBASE_RESULT EQUAL 0) + set (DISABLE_WRITE_GS_BASE 0) + else () + set (DISABLE_WRITE_GS_BASE 1) + endif () + endif () + if (DISABLE_WRITE_GS_BASE EQUAL 1) add_definitions (-DWASM_DISABLE_WRITE_GS_BASE=1) message (" Write linear memory base addr to x86 GS register disabled") + else () + add_definitions (-DWASM_DISABLE_WRITE_GS_BASE=0) + message (" Write linear memory base addr to x86 GS register enabled") endif () endif () if (WAMR_CONFIGUABLE_BOUNDS_CHECKS EQUAL 1) @@ -451,20 +476,19 @@ if (WAMR_BUILD_LINUX_PERF EQUAL 1) add_definitions (-DWASM_ENABLE_LINUX_PERF=1) message (" Linux perf support enabled") endif () -if (NOT DEFINED WAMR_BUILD_QUICK_AOT_ENTRY) - # Enable quick aot/jit entries by default - set (WAMR_BUILD_QUICK_AOT_ENTRY 1) -endif () -if (WAMR_BUILD_QUICK_AOT_ENTRY EQUAL 1) - add_definitions (-DWASM_ENABLE_QUICK_AOT_ENTRY=1) - message (" Quick AOT/JIT entries enabled") +if (WAMR_BUILD_AOT EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1) + if (NOT DEFINED WAMR_BUILD_QUICK_AOT_ENTRY) + # Enable quick aot/jit entries by default + set (WAMR_BUILD_QUICK_AOT_ENTRY 1) + endif () + if (WAMR_BUILD_QUICK_AOT_ENTRY EQUAL 1) + add_definitions (-DWASM_ENABLE_QUICK_AOT_ENTRY=1) + message (" Quick AOT/JIT entries enabled") + else () + add_definitions (-DWASM_ENABLE_QUICK_AOT_ENTRY=0) + message (" Quick AOT/JIT entries disabled") + endif () else () + # Disable quick aot/jit entries for interp and fast-jit add_definitions (-DWASM_ENABLE_QUICK_AOT_ENTRY=0) - message (" Quick AOT/JIT entries disabled") -endif () - -if (APPLE) - # On recent macOS versions, by default, the size of page zero is 4GB. - # Shrink it to make MAP_32BIT mmap can work. - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-pagezero_size,0x4000") endif () diff --git a/core/config.h b/core/config.h index e067ea271..fea449f81 100644 --- a/core/config.h +++ b/core/config.h @@ -188,6 +188,10 @@ #define WASM_ENABLE_APP_FRAMEWORK 0 #endif +#ifndef WASM_HAVE_MREMAP +#define WASM_HAVE_MREMAP 0 +#endif + /* Bulk memory operation */ #ifndef WASM_ENABLE_BULK_MEMORY #define WASM_ENABLE_BULK_MEMORY 0 @@ -231,6 +235,17 @@ #define WASM_ENABLE_LOG 1 #endif +/* When this flag is set, WAMR will not automatically + * initialize sockets on Windows platforms. The host + * application is responsible for calling WSAStartup() + * before executing WAMR code that uses sockets, and + * calling WSACleanup() after. + * This flag passes control of socket initialization from + * WAMR to the host application. */ +#ifndef WASM_ENABLE_HOST_SOCKET_INIT +#define WASM_ENABLE_HOST_SOCKET_INIT 0 +#endif + #ifndef WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS #if defined(BUILD_TARGET_X86_32) || defined(BUILD_TARGET_X86_64) \ || defined(BUILD_TARGET_AARCH64) @@ -397,7 +412,7 @@ #define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024) #define APP_THREAD_STACK_SIZE_MIN (48 * 1024) #else -#define APP_THREAD_STACK_SIZE_DEFAULT (64 * 1024) +#define APP_THREAD_STACK_SIZE_DEFAULT (128 * 1024) #define APP_THREAD_STACK_SIZE_MIN (24 * 1024) #endif #endif /* end of !(defined(APP_THREAD_STACK_SIZE_DEFAULT) \ @@ -446,6 +461,14 @@ #define WASM_ENABLE_REF_TYPES 0 #endif +#ifndef WASM_ENABLE_EXCE_HANDLING +#define WASM_ENABLE_EXCE_HANDLING 0 +#endif + +#ifndef WASM_ENABLE_TAGS +#define WASM_ENABLE_TAGS 0 +#endif + #ifndef WASM_ENABLE_SGX_IPFS #define WASM_ENABLE_SGX_IPFS 0 #endif diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 74513d04e..282dc1d67 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -66,15 +66,15 @@ exchange_uint32(uint8 *p_data) } static void -exchange_uint64(uint8 *pData) +exchange_uint64(uint8 *p_data) { uint32 value; - value = *(uint32 *)pData; - *(uint32 *)pData = *(uint32 *)(pData + 4); - *(uint32 *)(pData + 4) = value; - exchange_uint32(pData); - exchange_uint32(pData + 4); + value = *(uint32 *)p_data; + *(uint32 *)p_data = *(uint32 *)(p_data + 4); + *(uint32 *)(p_data + 4) = value; + exchange_uint32(p_data); + exchange_uint32(p_data + 4); } static union { @@ -214,6 +214,8 @@ GET_U16_FROM_ADDR(const uint8 *p) p += sizeof(type); \ } while (0) +/* NOLINTBEGIN, disable lint for this region with clang-tidy */ + #define read_byte_array(p, p_end, addr, len) \ do { \ CHECK_BUF(p, p_end, len); \ @@ -236,6 +238,8 @@ GET_U16_FROM_ADDR(const uint8 *p) #define read_uint32(p, p_end, res) TEMPLATE_READ(p, p_end, res, uint32) #define read_uint64(p, p_end, res) TEMPLATE_READ(p, p_end, res, uint64) +/* NOLINTEND */ + /* Legal values for bin_type */ #define BIN_TYPE_ELF32L 0 /* 32-bit little endian */ #define BIN_TYPE_ELF32B 1 /* 32-bit big endian */ @@ -1975,6 +1979,12 @@ str2uint64(const char *buf, uint64 *p_res) #define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative offset to GOT */ +static bool +is_text_section(const char *section_name) +{ + return !strcmp(section_name, ".text") || !strcmp(section_name, ".ltext"); +} + static bool do_text_relocation(AOTModule *module, AOTRelocationGroup *group, char *error_buf, uint32 error_buf_size) @@ -2063,7 +2073,7 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group, symbol_addr = module->func_ptrs[func_index]; } #endif - else if (!strcmp(symbol, ".text")) { + else if (is_text_section(symbol)) { symbol_addr = module->code; } else if (!strcmp(symbol, ".data") || !strcmp(symbol, ".sdata") @@ -2235,7 +2245,7 @@ do_data_relocation(AOTModule *module, AOTRelocationGroup *group, for (i = 0; i < group->relocation_count; i++, relocation++) { symbol = relocation->symbol_name; - if (!strcmp(symbol, ".text")) { + if (is_text_section(symbol)) { symbol_addr = module->code; } #if WASM_ENABLE_STATIC_PGO != 0 @@ -2696,6 +2706,8 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end, if (!strcmp(group->section_name, ".rel.text") || !strcmp(group->section_name, ".rela.text") + || !strcmp(group->section_name, ".rel.ltext") + || !strcmp(group->section_name, ".rela.ltext") || !strcmp(group->section_name, ".rela.literal") #ifdef BH_PLATFORM_WINDOWS || !strcmp(group->section_name, ".text") @@ -3126,8 +3138,7 @@ resolve_execute_mode(const uint8 *buf, uint32 size, bool *p_mode, p += 8; while (p < p_end) { read_uint32(p, p_end, section_type); - if (section_type <= AOT_SECTION_TYPE_SIGANATURE - || section_type == AOT_SECTION_TYPE_TARGET_INFO) { + if (section_type <= AOT_SECTION_TYPE_SIGANATURE) { read_uint32(p, p_end, section_size); CHECK_BUF(p, p_end, section_size); if (section_type == AOT_SECTION_TYPE_TARGET_INFO) { @@ -3142,7 +3153,7 @@ resolve_execute_mode(const uint8 *buf, uint32 size, bool *p_mode, break; } } - else if (section_type > AOT_SECTION_TYPE_SIGANATURE) { + else { /* section_type > AOT_SECTION_TYPE_SIGANATURE */ set_error_buf(error_buf, error_buf_size, "resolve execute mode failed"); break; diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 0fa4f7939..6a5681a6e 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -361,16 +361,7 @@ memories_deinstantiate(AOTModuleInstance *module_inst) } if (memory_inst->memory_data) { -#ifndef OS_ENABLE_HW_BOUND_CHECK - wasm_runtime_free(memory_inst->memory_data); -#else -#ifdef BH_PLATFORM_WINDOWS - os_mem_decommit(memory_inst->memory_data, - memory_inst->num_bytes_per_page - * memory_inst->cur_page_count); -#endif - os_munmap(memory_inst->memory_data, 8 * (uint64)BH_GB); -#endif + wasm_deallocate_linear_memory(memory_inst); } } } @@ -392,15 +383,10 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, uint32 heap_offset = num_bytes_per_page * init_page_count; uint64 memory_data_size, max_memory_data_size; uint8 *p = NULL, *global_addr; -#ifdef OS_ENABLE_HW_BOUND_CHECK - uint8 *mapped_mem; - uint64 map_size = 8 * (uint64)BH_GB; - uint64 page_size = os_getpagesize(); -#endif + bool is_shared_memory = false; #if WASM_ENABLE_SHARED_MEMORY != 0 - bool is_shared_memory = memory->memory_flags & 0x02 ? true : false; - + is_shared_memory = memory->memory_flags & 0x02 ? true : false; /* Shared memory */ if (is_shared_memory && parent != NULL) { AOTMemoryInstance *shared_memory_instance; @@ -510,71 +496,19 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent, module->aux_stack_size); LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size); - 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 -#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 -#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 - * both i and memarg.offset are u32 in range 0 to 4G - * so the range of ea is 0 to 8G - */ - if (!(p = mapped_mem = os_mmap(NULL, map_size, MMAP_PROT_NONE, - MMAP_MAP_NONE, os_get_invalid_handle()))) { - set_error_buf(error_buf, error_buf_size, "mmap memory failed"); + if (wasm_allocate_linear_memory(&p, is_shared_memory, num_bytes_per_page, + init_page_count, max_page_count, + &memory_data_size) + != BHT_OK) { + set_error_buf(error_buf, error_buf_size, + "allocate linear memory failed"); return NULL; } -#ifdef BH_PLATFORM_WINDOWS - 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, 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, memory_data_size); -#endif - os_munmap(mapped_mem, map_size); - return NULL; - } - - /* Newly allocated pages are filled with zero by the OS, we don't fill it - * again here */ - - if (memory_data_size > UINT32_MAX) - memory_data_size = UINT32_MAX; -#endif /* end of OS_ENABLE_HW_BOUND_CHECK */ - 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; @@ -623,17 +557,8 @@ fail2: if (heap_size > 0) wasm_runtime_free(memory_inst->heap_handle); fail1: -#ifndef OS_ENABLE_HW_BOUND_CHECK - if (memory_inst->memory_data) - wasm_runtime_free(memory_inst->memory_data); -#else -#ifdef BH_PLATFORM_WINDOWS - if (memory_inst->memory_data) - os_mem_decommit(p, memory_data_size); -#endif - os_munmap(mapped_mem, map_size); -#endif - memory_inst->memory_data = NULL; + wasm_deallocate_linear_memory(memory_inst); + return NULL; } @@ -1186,6 +1111,10 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, "failed to allocate bitmaps"); goto fail; } + for (i = 0; i < module->mem_init_data_count; i++) { + if (!module->mem_init_data_list[i]->is_passive) + bh_bitmap_set_bit(common->data_dropped, i); + } } #endif #if WASM_ENABLE_REF_TYPES != 0 @@ -1197,6 +1126,10 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent, "failed to allocate bitmaps"); goto fail; } + for (i = 0; i < module->table_init_data_count; i++) { + if (wasm_elem_is_active(module->table_init_data_list[i]->mode)) + bh_bitmap_set_bit(common->elem_dropped, i); + } } #endif @@ -1433,14 +1366,10 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, #if WASM_ENABLE_QUICK_AOT_ENTRY != 0 /* Quick call if the quick aot entry is registered */ if (!signature && func_type->quick_aot_entry) { - void (*invoke_native)( - void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) = func_type->quick_aot_entry; - invoke_native(func_ptr, - func_type->result_count > 0 - ? func_type->types[func_type->param_count] - : VALUE_TYPE_VOID, - exec_env, argv, argv_ret); + void (*invoke_native)(void *func_ptr, void *exec_env, uint32 *argv, + uint32 *argv_ret) = + func_type->quick_aot_entry; + invoke_native(func_ptr, exec_env, argv, argv_ret); ret = !aot_copy_exception(module_inst, NULL); } else @@ -1477,9 +1406,28 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr, (void)jmpbuf_node_pop; return ret; } -#define invoke_native_internal invoke_native_with_hw_bound_check +#define invoke_native_internal invoke_native_with_hw_bound_check /* NOLINT */ #else /* else of OS_ENABLE_HW_BOUND_CHECK */ -#define invoke_native_internal wasm_runtime_invoke_native +static inline bool +invoke_native_internal(WASMExecEnv *exec_env, void *func_ptr, + const WASMType *func_type, const char *signature, + void *attachment, uint32 *argv, uint32 argc, + uint32 *argv_ret) +{ +#if WASM_ENABLE_QUICK_AOT_ENTRY != 0 + /* Quick call if the quick aot entry is registered */ + if (!signature && func_type->quick_aot_entry) { + AOTModuleInstance *module_inst = + (AOTModuleInstance *)exec_env->module_inst; + void (*invoke_native)(void *func_ptr, void *exec_env, uint32 *argv, + uint32 *argv_ret) = func_type->quick_aot_entry; + invoke_native(func_ptr, exec_env, argv, argv_ret); + return !aot_copy_exception(module_inst, NULL); + } +#endif + return wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature, + attachment, argv, argc, argv_ret); +} #endif /* end of OS_ENABLE_HW_BOUND_CHECK */ bool @@ -2613,6 +2561,7 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, { AOTTableInstance *tbl_inst; AOTTableInitData *tbl_seg; + uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0; const AOTModule *module = (AOTModule *)module_inst->module; tbl_inst = module_inst->tables[tbl_idx]; @@ -2621,7 +2570,15 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, tbl_seg = module->table_init_data_list[tbl_seg_idx]; bh_assert(tbl_seg); - if (offset_len_out_of_bounds(src_offset, length, tbl_seg->func_index_count) + if (!bh_bitmap_get_bit( + ((AOTModuleInstanceExtra *)module_inst->e)->common.elem_dropped, + tbl_seg_idx)) { + /* table segment isn't dropped */ + tbl_seg_elems = tbl_seg->func_indexes; + tbl_seg_len = tbl_seg->func_index_count; + } + + if (offset_len_out_of_bounds(src_offset, length, tbl_seg_len) || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) { aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; @@ -2631,22 +2588,10 @@ aot_table_init(AOTModuleInstance *module_inst, uint32 tbl_idx, return; } - if (bh_bitmap_get_bit( - ((AOTModuleInstanceExtra *)module_inst->e)->common.elem_dropped, - tbl_seg_idx)) { - aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); - return; - } - - if (!wasm_elem_is_passive(tbl_seg->mode)) { - aot_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); - return; - } - bh_memcpy_s((uint8 *)tbl_inst + offsetof(AOTTableInstance, elems) + dst_offset * sizeof(uint32), (tbl_inst->cur_size - dst_offset) * sizeof(uint32), - tbl_seg->func_indexes + src_offset, length * sizeof(uint32)); + tbl_seg_elems + src_offset, length * sizeof(uint32)); } void @@ -2814,7 +2759,7 @@ aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index) } #if WASM_ENABLE_PERF_PROFILING != 0 - frame->time_started = os_time_get_boot_microsecond(); + frame->time_started = os_time_thread_cputime_us(); frame->func_perf_prof_info = func_perf_prof; #endif @@ -2832,9 +2777,13 @@ aot_free_frame(WASMExecEnv *exec_env) AOTFrame *prev_frame = cur_frame->prev_frame; #if WASM_ENABLE_PERF_PROFILING != 0 - cur_frame->func_perf_prof_info->total_exec_time += - os_time_get_boot_microsecond() - cur_frame->time_started; + uint64 elapsed = os_time_thread_cputime_us() - cur_frame->time_started; + cur_frame->func_perf_prof_info->total_exec_time += elapsed; cur_frame->func_perf_prof_info->total_exec_cnt++; + + /* parent function */ + if (prev_frame) + prev_frame->func_perf_prof_info->children_exec_time += elapsed; #endif wasm_exec_env_free_wasm_frame(exec_env, cur_frame); @@ -2971,22 +2920,65 @@ aot_dump_perf_profiling(const AOTModuleInstance *module_inst) os_printf("Performance profiler data:\n"); for (i = 0; i < total_func_count; i++, perf_prof++) { + if (perf_prof->total_exec_cnt == 0) + continue; + func_name = get_func_name_from_index(module_inst, i); if (func_name) os_printf( " func %s, execution time: %.3f ms, execution count: %" PRIu32 - " times\n", + " times, children execution time: %.3f ms\n", func_name, perf_prof->total_exec_time / 1000.0f, - perf_prof->total_exec_cnt); + perf_prof->total_exec_cnt, + perf_prof->children_exec_time / 1000.0f); else os_printf(" func %" PRIu32 ", execution time: %.3f ms, execution count: %" PRIu32 - " times\n", + " times, children execution time: %.3f ms\n", i, perf_prof->total_exec_time / 1000.0f, - perf_prof->total_exec_cnt); + perf_prof->total_exec_cnt, + perf_prof->children_exec_time / 1000.0f); } } + +double +aot_summarize_wasm_execute_time(const AOTModuleInstance *inst) +{ + double ret = 0; + + AOTModule *module = (AOTModule *)inst->module; + uint32 total_func_count = module->import_func_count + module->func_count, i; + + for (i = 0; i < total_func_count; i++) { + AOTFuncPerfProfInfo *perf_prof = + (AOTFuncPerfProfInfo *)inst->func_perf_profilings + i; + ret += (perf_prof->total_exec_time - perf_prof->children_exec_time) + / 1000.0f; + } + + return ret; +} + +double +aot_get_wasm_func_exec_time(const AOTModuleInstance *inst, + const char *func_name) +{ + AOTModule *module = (AOTModule *)inst->module; + uint32 total_func_count = module->import_func_count + module->func_count, i; + + for (i = 0; i < total_func_count; i++) { + const char *name_in_wasm = get_func_name_from_index(inst, i); + if (name_in_wasm && strcmp(func_name, name_in_wasm) == 0) { + AOTFuncPerfProfInfo *perf_prof = + (AOTFuncPerfProfInfo *)inst->func_perf_profilings + i; + return (perf_prof->total_exec_time - perf_prof->children_exec_time) + / 1000.0f; + } + } + + return -1.0; +} #endif /* end of WASM_ENABLE_PERF_PROFILING */ #if WASM_ENABLE_STATIC_PGO != 0 diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 35c78bfa0..47d8a2021 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -286,6 +286,8 @@ typedef struct AOTFuncPerfProfInfo { uint64 total_exec_time; /* total execution count */ uint32 total_exec_cnt; + /* children execution time */ + uint64 children_exec_time; } AOTFuncPerfProfInfo; /* AOT auxiliary call stack */ @@ -613,6 +615,13 @@ aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len); void aot_dump_perf_profiling(const AOTModuleInstance *module_inst); +double +aot_summarize_wasm_execute_time(const AOTModuleInstance *inst); + +double +aot_get_wasm_func_exec_time(const AOTModuleInstance *inst, + const char *func_name); + const uint8 * aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len); diff --git a/core/iwasm/aot/arch/aot_reloc_x86_64.c b/core/iwasm/aot/arch/aot_reloc_x86_64.c index b5be24593..d1f5cb5ac 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_64.c +++ b/core/iwasm/aot/arch/aot_reloc_x86_64.c @@ -163,7 +163,7 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, error_buf, error_buf_size, "AOT module load failed: " "relocation truncated to fit R_X86_64_PC32 failed. " - "Try using wamrc with --size-level=1 option."); + "Try using wamrc with --size-level=1 or 0 option."); return false; } @@ -196,7 +196,7 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, snprintf(buf, sizeof(buf), "AOT module load failed: " "relocation truncated to fit %s failed. " - "Try using wamrc with --size-level=1 option.", + "Try using wamrc with --size-level=1 or 0 option.", reloc_type == R_X86_64_32 ? "R_X86_64_32" : "R_X86_64_32S"); set_error_buf(error_buf, error_buf_size, buf); @@ -236,15 +236,16 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, target_addr -= sizeof(int32); #endif if ((int32)target_addr != target_addr) { - set_error_buf(error_buf, error_buf_size, - "AOT module load failed: " - "relocation truncated to fit " + set_error_buf( + error_buf, error_buf_size, + "AOT module load failed: " + "relocation truncated to fit " #if !defined(BH_PLATFORM_WINDOWS) - "R_X86_64_PLT32 failed. " + "R_X86_64_PLT32 failed. " #else - "IMAGE_REL_AMD64_32 failed." + "IMAGE_REL_AMD64_32 failed." #endif - "Try using wamrc with --size-level=1 option."); + "Try using wamrc with --size-level=1 or 0 option."); return false; } *(int32 *)(target_section_addr + reloc_offset) = (int32)target_addr; diff --git a/core/iwasm/aot/debug/elf_parser.c b/core/iwasm/aot/debug/elf_parser.c index 9fec281d3..657f9530c 100644 --- a/core/iwasm/aot/debug/elf_parser.c +++ b/core/iwasm/aot/debug/elf_parser.c @@ -100,6 +100,12 @@ get_section64(Elf64_Ehdr *eh, Elf64_Shdr *section_header) return buf + section_header->sh_offset; } +static bool +is_text_section(const char *section_name) +{ + return !strcmp(section_name, ".text") || !strcmp(section_name, ".ltext"); +} + bool get_text_section(void *buf, uint64_t *offset, uint64_t *size) { @@ -107,6 +113,7 @@ get_text_section(void *buf, uint64_t *offset, uint64_t *size) uint32 i; char *sh_str; + /* Assumption: Only one of .text or .ltext is non-empty. */ if (is64Bit(buf)) { Elf64_Ehdr *eh = (Elf64_Ehdr *)buf; Elf64_Shdr **sh_table = @@ -115,14 +122,16 @@ get_text_section(void *buf, uint64_t *offset, uint64_t *size) read_section_header_table64(eh, sh_table); sh_str = get_section64(eh, sh_table[eh->e_shstrndx]); for (i = 0; i < eh->e_shnum; i++) { - if (!strcmp(sh_str + sh_table[i]->sh_name, ".text")) { + if (is_text_section(sh_str + sh_table[i]->sh_name)) { *offset = sh_table[i]->sh_offset; *size = sh_table[i]->sh_size; sh_table[i]->sh_addr = (Elf64_Addr)(uintptr_t)((char *)buf + sh_table[i]->sh_offset); ret = true; - break; + if (*size > 0) { + break; + } } } wasm_runtime_free(sh_table); @@ -136,14 +145,16 @@ get_text_section(void *buf, uint64_t *offset, uint64_t *size) read_section_header_table(eh, sh_table); sh_str = get_section(eh, sh_table[eh->e_shstrndx]); for (i = 0; i < eh->e_shnum; i++) { - if (!strcmp(sh_str + sh_table[i]->sh_name, ".text")) { + if (is_text_section(sh_str + sh_table[i]->sh_name)) { *offset = sh_table[i]->sh_offset; *size = sh_table[i]->sh_size; sh_table[i]->sh_addr = (Elf32_Addr)(uintptr_t)((char *)buf + sh_table[i]->sh_offset); ret = true; - break; + if (*size > 0) { + break; + } } } wasm_runtime_free(sh_table); diff --git a/core/iwasm/common/wasm_application.c b/core/iwasm/common/wasm_application.c index 93c9342da..e13f7f843 100644 --- a/core/iwasm/common/wasm_application.c +++ b/core/iwasm/common/wasm_application.c @@ -46,7 +46,7 @@ static union { char b; } __ue = { .a = 1 }; -#define is_little_endian() (__ue.b == 1) +#define is_little_endian() (__ue.b == 1) /* NOLINT */ /** * Implementation of wasm_application_execute_main() diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index 27b1e0405..a9fac87ba 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -1924,16 +1924,18 @@ wasm_frame_func_offset(const wasm_frame_t *frame) void wasm_frame_vec_clone_internal(Vector *src, Vector *out) { - bh_assert(src->num_elems != 0 && src->data); - - bh_vector_destroy(out); - if (!bh_vector_init(out, src->num_elems, sizeof(WASMCApiFrame), false)) { + if (src->num_elems == 0) { bh_vector_destroy(out); return; } - bh_memcpy_s(out->data, src->num_elems * sizeof(WASMCApiFrame), src->data, - src->num_elems * sizeof(WASMCApiFrame)); + if (!bh_vector_destroy(out) + || !bh_vector_init(out, src->num_elems, sizeof(WASMCApiFrame), false)) { + return; + } + + bh_memcpy_s(out->data, (uint32)(src->num_elems * sizeof(WASMCApiFrame)), + src->data, (uint32)(src->num_elems * sizeof(WASMCApiFrame))); out->num_elems = src->num_elems; } @@ -2292,7 +2294,7 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) (uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, error_buf, (uint32)sizeof(error_buf)); if (!(module_ex->module_comm_rt)) { - LOG_ERROR(error_buf); + LOG_ERROR("%s", error_buf); goto free_vec; } @@ -2365,7 +2367,7 @@ wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary) } else { ret = false; - LOG_VERBOSE(error_buf); + LOG_VERBOSE("%s", error_buf); } return ret; @@ -2960,8 +2962,10 @@ wasm_func_new_basic(wasm_store_t *store, const wasm_functype_t *type, if (!(func->type = wasm_functype_copy(type))) { goto failed; } - func->param_count = func->type->params->num_elems; - func->result_count = func->type->results->num_elems; + /* func type's param_count and result_count were checked in + loader and are no larger than UINT16_MAX */ + func->param_count = (uint16)func->type->params->num_elems; + func->result_count = (uint16)func->type->results->num_elems; RETURN_OBJ(func, wasm_func_delete) } @@ -2992,8 +2996,10 @@ wasm_func_new_with_env_basic(wasm_store_t *store, const wasm_functype_t *type, if (!(func->type = wasm_functype_copy(type))) { goto failed; } - func->param_count = func->type->params->num_elems; - func->result_count = func->type->results->num_elems; + /* func type's param_count and result_count were checked in + loader and are no larger than UINT16_MAX */ + func->param_count = (uint16)func->type->params->num_elems; + func->result_count = (uint16)func->type->results->num_elems; RETURN_OBJ(func, wasm_func_delete) } @@ -3083,8 +3089,10 @@ wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt, if (!func->type) { goto failed; } - func->param_count = func->type->params->num_elems; - func->result_count = func->type->results->num_elems; + /* func type's param_count and result_count were checked in + loader and are no larger than UINT16_MAX */ + func->param_count = (uint16)func->type->params->num_elems; + func->result_count = (uint16)func->type->results->num_elems; /* will add name information when processing "exports" */ func->store = store; @@ -3357,7 +3365,7 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params, wasm_runtime_set_exception(func->inst_comm_rt, NULL); if (!wasm_runtime_call_wasm(exec_env, func_comm_rt, argc, argv)) { if (wasm_runtime_get_exception(func->inst_comm_rt)) { - LOG_DEBUG(wasm_runtime_get_exception(func->inst_comm_rt)); + LOG_DEBUG("%s", wasm_runtime_get_exception(func->inst_comm_rt)); goto failed; } } @@ -5042,7 +5050,7 @@ failed: *trap = wasm_trap_new(store, &message); wasm_byte_vec_delete(&message); } - LOG_DEBUG(error_buf); + LOG_DEBUG("%s", error_buf); wasm_instance_delete_internal(instance); return NULL; } diff --git a/core/iwasm/common/wasm_memory.c b/core/iwasm/common/wasm_memory.c index 360eee96c..70304a13d 100644 --- a/core/iwasm/common/wasm_memory.c +++ b/core/iwasm/common/wasm_memory.c @@ -42,6 +42,14 @@ static void (*free_func)(void *ptr) = NULL; static unsigned int global_pool_size; +static uint32 +align_as_and_cast(uint64 size, uint64 alignment) +{ + uint64 aligned_size = (size + alignment - 1) & ~(alignment - 1); + + return aligned_size > UINT32_MAX ? UINT32_MAX : (uint32)aligned_size; +} + static bool wasm_memory_init_with_pool(void *mem, unsigned int bytes) { @@ -629,7 +637,61 @@ wasm_runtime_set_mem_bound_check_bytes(WASMMemoryInstance *memory, #endif } -#ifndef OS_ENABLE_HW_BOUND_CHECK +static void +wasm_munmap_linear_memory(void *mapped_mem, uint64 commit_size, uint64 map_size) +{ +#ifdef BH_PLATFORM_WINDOWS + os_mem_decommit(mapped_mem, commit_size); +#else + (void)commit_size; +#endif + os_munmap(mapped_mem, map_size); +} + +static void * +wasm_mremap_linear_memory(void *mapped_mem, uint64 old_size, uint64 new_size, + uint64 commit_size) +{ + void *new_mem; + + bh_assert(new_size > 0); + bh_assert(new_size > old_size); + + if (mapped_mem) { + new_mem = os_mremap(mapped_mem, old_size, new_size); + } + else { + new_mem = os_mmap(NULL, new_size, MMAP_PROT_NONE, MMAP_MAP_NONE, + os_get_invalid_handle()); + } + if (!new_mem) { + return NULL; + } + +#ifdef BH_PLATFORM_WINDOWS + if (commit_size > 0 + && !os_mem_commit(new_mem, commit_size, + MMAP_PROT_READ | MMAP_PROT_WRITE)) { + os_munmap(new_mem, new_size); + return NULL; + } +#endif + + if (os_mprotect(new_mem, commit_size, MMAP_PROT_READ | MMAP_PROT_WRITE) + != 0) { + wasm_munmap_linear_memory(new_mem, new_size, new_size); + return NULL; + } + + return new_mem; +} + +static void * +wasm_mmap_linear_memory(uint64_t map_size, uint64 commit_size) +{ + return wasm_mremap_linear_memory(NULL, 0, map_size, commit_size); +} + bool wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) { @@ -638,7 +700,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) uint32 num_bytes_per_page, heap_size, total_size_old = 0; uint32 cur_page_count, max_page_count, total_page_count; uint64 total_size_new; - bool ret = true; + bool ret = true, full_size_mmaped; enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR; if (!memory) { @@ -646,12 +708,20 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) goto return_func; } - heap_data_old = memory->heap_data; - heap_size = (uint32)(memory->heap_data_end - memory->heap_data); +#ifdef OS_ENABLE_HW_BOUND_CHECK + full_size_mmaped = true; +#elif WASM_ENABLE_SHARED_MEMORY != 0 + full_size_mmaped = shared_memory_is_shared(memory); +#else + full_size_mmaped = false; +#endif memory_data_old = memory->memory_data; total_size_old = memory->memory_data_size; + heap_data_old = memory->heap_data; + heap_size = (uint32)(memory->heap_data_end - memory->heap_data); + num_bytes_per_page = memory->num_bytes_per_page; cur_page_count = memory->cur_page_count; max_page_count = memory->max_page_count; @@ -681,156 +751,65 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) total_size_new = UINT32_MAX; } -#if WASM_ENABLE_SHARED_MEMORY != 0 - if (shared_memory_is_shared(memory)) { - memory->num_bytes_per_page = num_bytes_per_page; - memory->cur_page_count = total_page_count; - memory->max_page_count = max_page_count; - SET_LINEAR_MEMORY_SIZE(memory, (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; - } + if (full_size_mmaped) { +#ifdef BH_PLATFORM_WINDOWS + if (!os_mem_commit(memory->memory_data_end, + (uint32)total_size_new - total_size_old, + MMAP_PROT_READ | MMAP_PROT_WRITE)) { + ret = false; + goto return_func; + } #endif - if (heap_size > 0) { - if (mem_allocator_is_heap_corrupted(memory->heap_handle)) { - wasm_runtime_show_app_heap_corrupted_prompt(); - ret = false; - goto return_func; - } - } - - if (!(memory_data_new = - wasm_runtime_realloc(memory_data_old, (uint32)total_size_new))) { - if (!(memory_data_new = wasm_runtime_malloc((uint32)total_size_new))) { - ret = false; - goto return_func; - } - if (memory_data_old) { - bh_memcpy_s(memory_data_new, (uint32)total_size_new, - memory_data_old, total_size_old); - wasm_runtime_free(memory_data_old); - } - } - - memset(memory_data_new + total_size_old, 0, - (uint32)total_size_new - total_size_old); - - if (heap_size > 0) { - if (mem_allocator_migrate(memory->heap_handle, - (char *)heap_data_old - + (memory_data_new - memory_data_old), - heap_size) + if (os_mprotect(memory->memory_data_end, + (uint32)total_size_new - total_size_old, + MMAP_PROT_READ | MMAP_PROT_WRITE) != 0) { - /* Don't return here as memory->memory_data is obsolete and - must be updated to be correctly used later. */ +#ifdef BH_PLATFORM_WINDOWS + os_mem_decommit(memory->memory_data_end, + (uint32)total_size_new - total_size_old); +#endif ret = false; + goto return_func; } } + else { + if (heap_size > 0) { + if (mem_allocator_is_heap_corrupted(memory->heap_handle)) { + wasm_runtime_show_app_heap_corrupted_prompt(); + ret = false; + goto return_func; + } + } - memory->heap_data = memory_data_new + (heap_data_old - memory_data_old); - memory->heap_data_end = memory->heap_data + heap_size; + if (!(memory_data_new = wasm_mremap_linear_memory( + memory_data_old, total_size_old, (uint32)total_size_new, + (uint32)total_size_new))) { + ret = false; + goto return_func; + } - memory->num_bytes_per_page = num_bytes_per_page; - memory->cur_page_count = total_page_count; - memory->max_page_count = max_page_count; - memory->memory_data_size = (uint32)total_size_new; - - memory->memory_data = memory_data_new; - memory->memory_data_end = memory_data_new + (uint32)total_size_new; - - wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new); + if (heap_size > 0) { + if (mem_allocator_migrate(memory->heap_handle, + (char *)heap_data_old + + (memory_data_new - memory_data_old), + heap_size) + != 0) { + /* Don't return here as memory->memory_data is obsolete and + must be updated to be correctly used later. */ + ret = false; + } + } + memory->heap_data = memory_data_new + (heap_data_old - memory_data_old); + memory->heap_data_end = memory->heap_data + heap_size; + memory->memory_data = memory_data_new; #if defined(os_writegsbase) - /* write base addr of linear memory to GS segment register */ - os_writegsbase(memory_data_new); + /* write base addr of linear memory to GS segment register */ + os_writegsbase(memory_data_new); #endif - -return_func: - if (!ret && enlarge_memory_error_cb) { - WASMExecEnv *exec_env = - wasm_runtime_get_cur_exec_env((WASMModuleInstanceCommon *)module); - bh_assert(exec_env); - enlarge_memory_error_cb(inc_page_count, total_size_old, 0, - failure_reason, - (WASMModuleInstanceCommon *)module, exec_env, - enlarge_memory_error_user_data); } - return ret; -} -#else -bool -wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count) -{ - WASMMemoryInstance *memory = wasm_get_default_memory(module); - uint32 num_bytes_per_page, total_size_old = 0; - uint32 cur_page_count, max_page_count, total_page_count; - uint64 total_size_new; - bool ret = true; - enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR; - - if (!memory) { - ret = false; - goto return_func; - } - - num_bytes_per_page = memory->num_bytes_per_page; - cur_page_count = memory->cur_page_count; - max_page_count = memory->max_page_count; - total_size_old = num_bytes_per_page * cur_page_count; - total_page_count = inc_page_count + cur_page_count; - total_size_new = num_bytes_per_page * (uint64)total_page_count; - - if (inc_page_count <= 0) - /* No need to enlarge memory */ - return true; - - if (total_page_count < cur_page_count) { /* integer overflow */ - ret = false; - goto return_func; - } - - if (total_page_count > max_page_count) { - failure_reason = MAX_SIZE_REACHED; - ret = false; - goto return_func; - } - - bh_assert(total_size_new <= 4 * (uint64)BH_GB); - if (total_size_new > UINT32_MAX) { - /* Resize to 1 page with size 4G-1 */ - num_bytes_per_page = UINT32_MAX; - total_page_count = max_page_count = 1; - total_size_new = UINT32_MAX; - } - -#ifdef BH_PLATFORM_WINDOWS - if (!os_mem_commit(memory->memory_data_end, - (uint32)total_size_new - total_size_old, - MMAP_PROT_READ | MMAP_PROT_WRITE)) { - ret = false; - goto return_func; - } -#endif - - if (os_mprotect(memory->memory_data_end, - (uint32)total_size_new - total_size_old, - MMAP_PROT_READ | MMAP_PROT_WRITE) - != 0) { -#ifdef BH_PLATFORM_WINDOWS - os_mem_decommit(memory->memory_data_end, - (uint32)total_size_new - total_size_old); -#endif - ret = false; - goto return_func; - } - - /* The increased pages are filled with zero by the OS when os_mmap, - no need to memset it again here */ - memory->num_bytes_per_page = num_bytes_per_page; memory->cur_page_count = total_page_count; memory->max_page_count = max_page_count; @@ -852,7 +831,6 @@ return_func: return ret; } -#endif /* end of OS_ENABLE_HW_BOUND_CHECK */ void wasm_runtime_set_enlarge_mem_error_callback( @@ -879,3 +857,75 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) return ret; } + +void +wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst) +{ + uint64 map_size; + + bh_assert(memory_inst); + bh_assert(memory_inst->memory_data); + +#ifndef OS_ENABLE_HW_BOUND_CHECK +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (shared_memory_is_shared(memory_inst)) { + map_size = (uint64)memory_inst->num_bytes_per_page + * memory_inst->max_page_count; + } + else +#endif + { + map_size = (uint64)memory_inst->num_bytes_per_page + * memory_inst->cur_page_count; + } +#else + map_size = 8 * (uint64)BH_GB; +#endif + wasm_munmap_linear_memory(memory_inst->memory_data, + memory_inst->memory_data_size, map_size); + memory_inst->memory_data = NULL; +} + +int +wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory, + uint64 num_bytes_per_page, uint64 init_page_count, + uint64 max_page_count, uint64 *memory_data_size) +{ + uint64 map_size, page_size; + + bh_assert(data); + bh_assert(memory_data_size); + +#ifndef OS_ENABLE_HW_BOUND_CHECK +#if WASM_ENABLE_SHARED_MEMORY != 0 + if (is_shared_memory) { + /* Allocate maximum memory size when memory is shared */ + map_size = max_page_count * num_bytes_per_page; + } + else +#endif + { + map_size = init_page_count * num_bytes_per_page; + } +#else /* else of OS_ENABLE_HW_BOUND_CHECK */ + /* Totally 8G is mapped, the opcode load/store address range is 0 to 8G: + * ea = i + memarg.offset + * both i and memarg.offset are u32 in range 0 to 4G + * so the range of ea is 0 to 8G + */ + map_size = 8 * (uint64)BH_GB; +#endif /* end of OS_ENABLE_HW_BOUND_CHECK */ + + page_size = os_getpagesize(); + *memory_data_size = init_page_count * num_bytes_per_page; + bh_assert(*memory_data_size <= UINT32_MAX); + align_as_and_cast(*memory_data_size, page_size); + + if (map_size > 0) { + if (!(*data = wasm_mmap_linear_memory(map_size, *memory_data_size))) { + return BHT_ERROR; + } + } + + return BHT_OK; +} diff --git a/core/iwasm/common/wasm_memory.h b/core/iwasm/common/wasm_memory.h index 9b74db526..381266b61 100644 --- a/core/iwasm/common/wasm_memory.h +++ b/core/iwasm/common/wasm_memory.h @@ -42,6 +42,14 @@ void wasm_runtime_set_enlarge_mem_error_callback( const enlarge_memory_error_callback_t callback, void *user_data); +void +wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst); + +int +wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory, + uint64 num_bytes_per_page, uint64 init_page_count, + uint64 max_page_count, uint64 *memory_data_size); + #ifdef __cplusplus } #endif diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c index 69ae6f2a8..d2492bc49 100644 --- a/core/iwasm/common/wasm_native.c +++ b/core/iwasm/common/wasm_native.c @@ -194,7 +194,7 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name, { NativeSymbolsNode *node, *node_next; const char *signature = NULL; - void *func_ptr = NULL, *attachment; + void *func_ptr = NULL, *attachment = NULL; node = g_native_symbols_list; while (node) { @@ -618,819 +618,760 @@ wasm_native_destroy() #if WASM_ENABLE_QUICK_AOT_ENTRY != 0 static void -invoke_no_args_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_no_args_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; + void (*native_code)(WASMExecEnv *) = func_ptr; native_code(exec_env); } static void -invoke_no_args_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_no_args_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *) = func_ptr; argv_ret[0] = native_code(exec_env); } static void -invoke_no_args_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_no_args_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env); + int64 (*native_code)(WASMExecEnv *) = func_ptr; + int64 ret = native_code(exec_env); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_i_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_i_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; + void (*native_code)(WASMExecEnv *, int32) = func_ptr; native_code(exec_env, argv[0]); } static void -invoke_i_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_i_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0]); } static void -invoke_i_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_i_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0]); + int64 (*native_code)(WASMExecEnv *, int32) = func_ptr; + int64 ret = native_code(exec_env, argv[0]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_I_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_I_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv)); + void (*native_code)(WASMExecEnv *, int64) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv)); } static void -invoke_I_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_I_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv)); + int32 (*native_code)(WASMExecEnv *, int64) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv)); } static void -invoke_I_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_I_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv)); + int64 (*native_code)(WASMExecEnv *, int64) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv)); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_ii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_ii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; + void (*native_code)(WASMExecEnv *, int32, int32) = func_ptr; native_code(exec_env, argv[0], argv[1]); } static void -invoke_ii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_ii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int32, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1]); } static void -invoke_ii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_ii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0], argv[1]); + int64 (*native_code)(WASMExecEnv *, int32, int32) = func_ptr; + int64 ret = native_code(exec_env, argv[0], argv[1]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1)); + void (*native_code)(WASMExecEnv *, int32, int64) = func_ptr; + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1)); } static void -invoke_iI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1)); + int32 (*native_code)(WASMExecEnv *, int32, int64) = func_ptr; + argv_ret[0] = + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1)); } static void -invoke_iI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1)); + int64 (*native_code)(WASMExecEnv *, int32, int64) = func_ptr; + int64 ret = + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1)); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_Ii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_Ii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2]); + void (*native_code)(WASMExecEnv *, int64, int32) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2]); } static void -invoke_Ii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_Ii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2]); + int32 (*native_code)(WASMExecEnv *, int64, int32) = func_ptr; + argv_ret[0] = + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2]); } static void -invoke_Ii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_Ii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2]); + int64 (*native_code)(WASMExecEnv *, int64, int32) = func_ptr; + int64 ret = + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_II_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_II_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2)); + void (*native_code)(WASMExecEnv *, int64, int64) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2)); } static void -invoke_II_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_II_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2)); + int32 (*native_code)(WASMExecEnv *, int64, int64) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2)); } static void -invoke_II_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_II_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2)); + int64 (*native_code)(WASMExecEnv *, int64, int64) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2)); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; + void (*native_code)(WASMExecEnv *, int32, int32, int32) = func_ptr; native_code(exec_env, argv[0], argv[1], argv[2]); } static void -invoke_iii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int32, int32, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], argv[2]); } static void -invoke_iii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0], argv[1], argv[2]); + int64 (*native_code)(WASMExecEnv *, int32, int32, int32) = func_ptr; + int64 ret = native_code(exec_env, argv[0], argv[1], argv[2]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2)); + void (*native_code)(WASMExecEnv *, int32, int32, int64) = func_ptr; + native_code(exec_env, argv[0], argv[1], + GET_I64_FROM_ADDR((uint32 *)argv + 2)); } static void -invoke_iiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int32, int32, int64) = func_ptr; + argv_ret[0] = native_code(exec_env, argv[0], argv[1], + GET_I64_FROM_ADDR((uint32 *)argv + 2)); +} +static void +invoke_iiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int64 (*native_code)(WASMExecEnv *, int32, int32, int64) = func_ptr; + int64 ret = native_code(exec_env, argv[0], argv[1], + GET_I64_FROM_ADDR((uint32 *)argv + 2)); + PUT_I64_TO_ADDR(argv_ret, ret); +} + +static void +invoke_iIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + void (*native_code)(WASMExecEnv *, int32, int64, int32) = func_ptr; + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + argv[3]); +} +static void +invoke_iIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int32 (*native_code)(WASMExecEnv *, int32, int64, int32) = func_ptr; + argv_ret[0] = native_code(exec_env, argv[0], + GET_I64_FROM_ADDR((uint32 *)argv + 1), argv[3]); +} +static void +invoke_iIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int64 (*native_code)(WASMExecEnv *, int32, int64, int32) = func_ptr; + int64 ret = native_code(exec_env, argv[0], + GET_I64_FROM_ADDR((uint32 *)argv + 1), argv[3]); + PUT_I64_TO_ADDR(argv_ret, ret); +} + +static void +invoke_iII_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + void (*native_code)(WASMExecEnv *, int32, int64, int64) = func_ptr; + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + GET_I64_FROM_ADDR((uint32 *)argv + 3)); +} +static void +invoke_iII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int32 (*native_code)(WASMExecEnv *, int32, int64, int64) = func_ptr; argv_ret[0] = - native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2)); + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + GET_I64_FROM_ADDR((uint32 *)argv + 3)); } static void -invoke_iiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = - native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2)); + int64 (*native_code)(WASMExecEnv *, int32, int64, int64) = func_ptr; + int64 ret = + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + GET_I64_FROM_ADDR((uint32 *)argv + 3)); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_Iii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), argv[3]); + void (*native_code)(WASMExecEnv *, int64, int32, int32) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], argv[3]); } static void -invoke_iIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_Iii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), argv[3]); + int32 (*native_code)(WASMExecEnv *, int64, int32, int32) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + argv[2], argv[3]); } static void -invoke_iIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_Iii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), argv[3]); + int64 (*native_code)(WASMExecEnv *, int64, int32, int32) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + argv[2], argv[3]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iII_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - GET_I64_FROM_ADDR(argv + 3)); + void (*native_code)(WASMExecEnv *, int64, int32, int64) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], + GET_I64_FROM_ADDR((uint32 *)argv + 3)); } static void -invoke_iII_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - GET_I64_FROM_ADDR(argv + 3)); + int32 (*native_code)(WASMExecEnv *, int64, int32, int64) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + argv[2], GET_I64_FROM_ADDR((uint32 *)argv + 3)); } static void -invoke_iII_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - GET_I64_FROM_ADDR(argv + 3)); + int64 (*native_code)(WASMExecEnv *, int64, int32, int64) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + argv[2], GET_I64_FROM_ADDR((uint32 *)argv + 3)); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_Iii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], argv[3]); + void (*native_code)(WASMExecEnv *, int64, int64, int32) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4]); } static void -invoke_Iii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], argv[3]); + int32 (*native_code)(WASMExecEnv *, int64, int64, int32) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4]); } static void -invoke_Iii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], argv[3]); + int64 (*native_code)(WASMExecEnv *, int64, int64, int32) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_IiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_III_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - GET_I64_FROM_ADDR(argv + 3)); + void (*native_code)(WASMExecEnv *, int64, int64, int64) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4)); } static void -invoke_IiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_III_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - GET_I64_FROM_ADDR(argv + 3)); + int32 (*native_code)(WASMExecEnv *, int64, int64, int64) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4)); } static void -invoke_IiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_III_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - GET_I64_FROM_ADDR(argv + 3)); + int64 (*native_code)(WASMExecEnv *, int64, int64, int64) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4)); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_IIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2), - argv[4]); -} -static void -invoke_IIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2), argv[4]); -} -static void -invoke_IIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2), argv[4]); - PUT_I64_TO_ADDR(argv_ret, ret); -} - -static void -invoke_III_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2), - GET_I64_FROM_ADDR(argv + 4)); -} -static void -invoke_III_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint32 (*native_code)() = func_ptr; - argv_ret[0] = - native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2), GET_I64_FROM_ADDR(argv + 4)); -} -static void -invoke_III_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint64 (*native_code)() = func_ptr; - uint64 ret = - native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2), GET_I64_FROM_ADDR(argv + 4)); - PUT_I64_TO_ADDR(argv_ret, ret); -} - -static void -invoke_iiii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - void (*native_code)() = func_ptr; + void (*native_code)(WASMExecEnv *, int32, int32, int32, int32) = func_ptr; native_code(exec_env, argv[0], argv[1], argv[2], argv[3]); } static void -invoke_iiii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int32, int32, int32, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], argv[2], argv[3]); } static void -invoke_iiii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0], argv[1], argv[2], argv[3]); + int64 (*native_code)(WASMExecEnv *, int32, int32, int32, int32) = func_ptr; + int64 ret = native_code(exec_env, argv[0], argv[1], argv[2], argv[3]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iiiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; + void (*native_code)(WASMExecEnv *, int32, int32, int32, int64) = func_ptr; native_code(exec_env, argv[0], argv[1], argv[2], - GET_I64_FROM_ADDR(argv + 3)); + GET_I64_FROM_ADDR((uint32 *)argv + 3)); } static void -invoke_iiiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int32, int32, int32, int64) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], argv[2], - GET_I64_FROM_ADDR(argv + 3)); + GET_I64_FROM_ADDR((uint32 *)argv + 3)); } static void -invoke_iiiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0], argv[1], argv[2], - GET_I64_FROM_ADDR(argv + 3)); + int64 (*native_code)(WASMExecEnv *, int32, int32, int32, int64) = func_ptr; + int64 ret = native_code(exec_env, argv[0], argv[1], argv[2], + GET_I64_FROM_ADDR((uint32 *)argv + 3)); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iiIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2), - argv[4]); + void (*native_code)(WASMExecEnv *, int32, int32, int64, int32) = func_ptr; + native_code(exec_env, argv[0], argv[1], + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4]); } static void -invoke_iiIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int32, int32, int64, int32) = func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], - GET_I64_FROM_ADDR(argv + 2), argv[4]); + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4]); } static void -invoke_iiIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0], argv[1], - GET_I64_FROM_ADDR(argv + 2), argv[4]); + int64 (*native_code)(WASMExecEnv *, int32, int32, int64, int32) = func_ptr; + int64 ret = native_code(exec_env, argv[0], argv[1], + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iiII_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiII_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2), - GET_I64_FROM_ADDR(argv + 4)); + void (*native_code)(WASMExecEnv *, int32, int32, int64, int64) = func_ptr; + native_code(exec_env, argv[0], argv[1], + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4)); } static void -invoke_iiII_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int32, int32, int64, int64) = func_ptr; + argv_ret[0] = native_code(exec_env, argv[0], argv[1], + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4)); +} +static void +invoke_iiII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int64 (*native_code)(WASMExecEnv *, int32, int32, int64, int64) = func_ptr; + int64 ret = native_code(exec_env, argv[0], argv[1], + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4)); + PUT_I64_TO_ADDR(argv_ret, ret); +} + +static void +invoke_iIii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + void (*native_code)(WASMExecEnv *, int32, int64, int32, int32) = func_ptr; + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + argv[3], argv[4]); +} +static void +invoke_iIii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int32 (*native_code)(WASMExecEnv *, int32, int64, int32, int32) = func_ptr; argv_ret[0] = - native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2), - GET_I64_FROM_ADDR(argv + 4)); + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + argv[3], argv[4]); } static void -invoke_iiII_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iIii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = - native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2), - GET_I64_FROM_ADDR(argv + 4)); + int64 (*native_code)(WASMExecEnv *, int32, int64, int32, int32) = func_ptr; + int64 ret = + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + argv[3], argv[4]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iIii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iIiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), argv[3], + void (*native_code)(WASMExecEnv *, int32, int64, int32, int64) = func_ptr; + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + argv[3], GET_I64_FROM_ADDR((uint32 *)argv + 4)); +} +static void +invoke_iIiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int32 (*native_code)(WASMExecEnv *, int32, int64, int32, int64) = func_ptr; + argv_ret[0] = + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + argv[3], GET_I64_FROM_ADDR((uint32 *)argv + 4)); +} +static void +invoke_iIiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int64 (*native_code)(WASMExecEnv *, int32, int64, int32, int64) = func_ptr; + int64 ret = + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + argv[3], GET_I64_FROM_ADDR((uint32 *)argv + 4)); + PUT_I64_TO_ADDR(argv_ret, ret); +} + +static void +invoke_iIIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + void (*native_code)(WASMExecEnv *, int32, int64, int64, int32) = func_ptr; + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + GET_I64_FROM_ADDR((uint32 *)argv + 3), argv[5]); +} +static void +invoke_iIIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int32 (*native_code)(WASMExecEnv *, int32, int64, int64, int32) = func_ptr; + argv_ret[0] = + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + GET_I64_FROM_ADDR((uint32 *)argv + 3), argv[5]); +} +static void +invoke_iIIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int64 (*native_code)(WASMExecEnv *, int32, int64, int64, int32) = func_ptr; + int64 ret = + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + GET_I64_FROM_ADDR((uint32 *)argv + 3), argv[5]); + PUT_I64_TO_ADDR(argv_ret, ret); +} + +static void +invoke_iIII_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + void (*native_code)(WASMExecEnv *, int32, int64, int64, int64) = func_ptr; + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + GET_I64_FROM_ADDR((uint32 *)argv + 3), + GET_I64_FROM_ADDR((uint32 *)argv + 5)); +} +static void +invoke_iIII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int32 (*native_code)(WASMExecEnv *, int32, int64, int64, int64) = func_ptr; + argv_ret[0] = + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + GET_I64_FROM_ADDR((uint32 *)argv + 3), + GET_I64_FROM_ADDR((uint32 *)argv + 5)); +} +static void +invoke_iIII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int64 (*native_code)(WASMExecEnv *, int32, int64, int64, int64) = func_ptr; + int64 ret = + native_code(exec_env, argv[0], GET_I64_FROM_ADDR((uint32 *)argv + 1), + GET_I64_FROM_ADDR((uint32 *)argv + 3), + GET_I64_FROM_ADDR((uint32 *)argv + 5)); + PUT_I64_TO_ADDR(argv_ret, ret); +} + +static void +invoke_Iiii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + void (*native_code)(WASMExecEnv *, int64, int32, int32, int32) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], argv[3], argv[4]); } static void -invoke_iIii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_Iiii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - argv[3], argv[4]); + int32 (*native_code)(WASMExecEnv *, int64, int32, int32, int32) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + argv[2], argv[3], argv[4]); } static void -invoke_iIii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_Iiii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - argv[3], argv[4]); + int64 (*native_code)(WASMExecEnv *, int64, int32, int32, int32) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + argv[2], argv[3], argv[4]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iIiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), argv[3], - GET_I64_FROM_ADDR(argv + 4)); -} -static void -invoke_iIiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - argv[3], GET_I64_FROM_ADDR(argv + 4)); -} -static void -invoke_iIiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - argv[3], GET_I64_FROM_ADDR(argv + 4)); - PUT_I64_TO_ADDR(argv_ret, ret); + void (*native_code)(WASMExecEnv *, int64, int32, int32, int64) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], argv[3], + GET_I64_FROM_ADDR((uint32 *)argv + 4)); } static void -invoke_iIIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - GET_I64_FROM_ADDR(argv + 3), argv[5]); -} -static void -invoke_iIIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - GET_I64_FROM_ADDR(argv + 3), argv[5]); -} -static void -invoke_iIIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - GET_I64_FROM_ADDR(argv + 3), argv[5]); - PUT_I64_TO_ADDR(argv_ret, ret); -} - -static void -invoke_iIII_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - void (*native_code)() = func_ptr; - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5)); -} -static void -invoke_iIII_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int64, int32, int32, int64) = func_ptr; argv_ret[0] = - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5)); + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], + argv[3], GET_I64_FROM_ADDR((uint32 *)argv + 4)); } + static void -invoke_iIII_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = - native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), - GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5)); + int64 (*native_code)(WASMExecEnv *, int64, int32, int32, int64) = func_ptr; + int64 ret = + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], + argv[3], GET_I64_FROM_ADDR((uint32 *)argv + 4)); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_Iiii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], argv[3], argv[4]); + void (*native_code)(WASMExecEnv *, int64, int32, int64, int32) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], + GET_I64_FROM_ADDR((uint32 *)argv + 3), argv[5]); } static void -invoke_Iiii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - argv[3], argv[4]); -} -static void -invoke_Iiii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - argv[3], argv[4]); - PUT_I64_TO_ADDR(argv_ret, ret); -} - -static void -invoke_IiiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], argv[3], - GET_I64_FROM_ADDR(argv + 4)); -} - -static void -invoke_IiiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - argv[3], GET_I64_FROM_ADDR(argv + 4)); -} - -static void -invoke_IiiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - argv[3], GET_I64_FROM_ADDR(argv + 4)); - PUT_I64_TO_ADDR(argv_ret, ret); -} - -static void -invoke_IiIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - GET_I64_FROM_ADDR(argv + 3), argv[5]); -} -static void -invoke_IiIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - GET_I64_FROM_ADDR(argv + 3), argv[5]); -} -static void -invoke_IiIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - GET_I64_FROM_ADDR(argv + 3), argv[5]); - PUT_I64_TO_ADDR(argv_ret, ret); -} - -static void -invoke_IiII_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5)); -} -static void -invoke_IiII_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) -{ - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int64, int32, int64, int32) = func_ptr; argv_ret[0] = - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5)); + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], + GET_I64_FROM_ADDR((uint32 *)argv + 3), argv[5]); } static void -invoke_IiII_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = - native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], - GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5)); + int64 (*native_code)(WASMExecEnv *, int64, int32, int64, int32) = func_ptr; + int64 ret = + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], + GET_I64_FROM_ADDR((uint32 *)argv + 3), argv[5]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_IIii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiII_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2), - argv[4], argv[5]); + void (*native_code)(WASMExecEnv *, int64, int32, int64, int64) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), argv[2], + GET_I64_FROM_ADDR((uint32 *)argv + 3), + GET_I64_FROM_ADDR((uint32 *)argv + 5)); } static void -invoke_IIii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2), argv[4], argv[5]); + int32 (*native_code)(WASMExecEnv *, int64, int32, int64, int64) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + argv[2], GET_I64_FROM_ADDR((uint32 *)argv + 3), + GET_I64_FROM_ADDR((uint32 *)argv + 5)); } static void -invoke_IIii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IiII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2), argv[4], argv[5]); + int64 (*native_code)(WASMExecEnv *, int64, int32, int64, int64) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + argv[2], GET_I64_FROM_ADDR((uint32 *)argv + 3), + GET_I64_FROM_ADDR((uint32 *)argv + 5)); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_IIiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2), - argv[4], GET_I64_FROM_ADDR(argv + 5)); + void (*native_code)(WASMExecEnv *, int64, int64, int32, int32) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4], argv[5]); } static void -invoke_IIiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2), argv[4], - GET_I64_FROM_ADDR(argv + 5)); + int32 (*native_code)(WASMExecEnv *, int64, int64, int32, int32) = func_ptr; + argv_ret[0] = + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4], argv[5]); } static void -invoke_IIiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2), argv[4], - GET_I64_FROM_ADDR(argv + 5)); + int64 (*native_code)(WASMExecEnv *, int64, int64, int32, int32) = func_ptr; + int64 ret = + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4], argv[5]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_IIIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIiI_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2), - GET_I64_FROM_ADDR(argv + 4), argv[6]); + void (*native_code)(WASMExecEnv *, int64, int64, int32, int64) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4], + GET_I64_FROM_ADDR((uint32 *)argv + 5)); } static void -invoke_IIIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIiI_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2), - GET_I64_FROM_ADDR(argv + 4), argv[6]); + int32 (*native_code)(WASMExecEnv *, int64, int64, int32, int64) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4], + GET_I64_FROM_ADDR((uint32 *)argv + 5)); } static void -invoke_IIIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIiI_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), - GET_I64_FROM_ADDR(argv + 2), - GET_I64_FROM_ADDR(argv + 4), argv[6]); + int64 (*native_code)(WASMExecEnv *, int64, int64, int32, int64) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), argv[4], + GET_I64_FROM_ADDR((uint32 *)argv + 5)); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_IIII_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIIi_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; - native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2), - GET_I64_FROM_ADDR(argv + 4), GET_I64_FROM_ADDR(argv + 6)); + void (*native_code)(WASMExecEnv *, int64, int64, int64, int32) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4), argv[6]); } static void -invoke_IIII_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIIi_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; - argv_ret[0] = native_code( - exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2), - GET_I64_FROM_ADDR(argv + 4), GET_I64_FROM_ADDR(argv + 6)); + int32 (*native_code)(WASMExecEnv *, int64, int64, int64, int32) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4), argv[6]); } static void -invoke_IIII_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIIi_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = native_code( - exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2), - GET_I64_FROM_ADDR(argv + 4), GET_I64_FROM_ADDR(argv + 6)); + int64 (*native_code)(WASMExecEnv *, int64, int64, int64, int32) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4), argv[6]); PUT_I64_TO_ADDR(argv_ret, ret); } static void -invoke_iiiii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_IIII_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - void (*native_code)() = func_ptr; + void (*native_code)(WASMExecEnv *, int64, int64, int64, int64) = func_ptr; + native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4), + GET_I64_FROM_ADDR((uint32 *)argv + 6)); +} +static void +invoke_IIII_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int32 (*native_code)(WASMExecEnv *, int64, int64, int64, int64) = func_ptr; + argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4), + GET_I64_FROM_ADDR((uint32 *)argv + 6)); +} +static void +invoke_IIII_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + int64 (*native_code)(WASMExecEnv *, int64, int64, int64, int64) = func_ptr; + int64 ret = native_code(exec_env, GET_I64_FROM_ADDR((uint32 *)argv), + GET_I64_FROM_ADDR((uint32 *)argv + 2), + GET_I64_FROM_ADDR((uint32 *)argv + 4), + GET_I64_FROM_ADDR((uint32 *)argv + 6)); + PUT_I64_TO_ADDR(argv_ret, ret); +} + +static void +invoke_iiiii_v(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) +{ + void (*native_code)(WASMExecEnv *, int32, int32, int32, int32, int32) = + func_ptr; native_code(exec_env, argv[0], argv[1], argv[2], argv[3], argv[4]); } static void -invoke_iiiii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiiii_i(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint32 (*native_code)() = func_ptr; + int32 (*native_code)(WASMExecEnv *, int32, int32, int32, int32, int32) = + func_ptr; argv_ret[0] = native_code(exec_env, argv[0], argv[1], argv[2], argv[3], argv[4]); } static void -invoke_iiiii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) +invoke_iiiii_I(void *func_ptr, void *exec_env, int32 *argv, int32 *argv_ret) { - uint64 (*native_code)() = func_ptr; - uint64 ret = + int64 (*native_code)(WASMExecEnv *, int32, int32, int32, int32, int32) = + func_ptr; + int64 ret = native_code(exec_env, argv[0], argv[1], argv[2], argv[3], argv[4]); PUT_I64_TO_ADDR(argv_ret, ret); } diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index f8af09a1a..dfd4ac9fe 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -785,6 +785,7 @@ align_ptr(const uint8 *p, uint32 b) return false; \ } while (0) +/* NOLINTNEXTLINE */ #define read_uint16(p, p_end, res) \ do { \ p = (uint8 *)align_ptr(p, sizeof(uint16)); \ @@ -793,6 +794,7 @@ align_ptr(const uint8 *p, uint32 b) p += sizeof(uint16); \ } while (0) +/* NOLINTNEXTLINE */ #define read_uint32(p, p_end, res) \ do { \ p = (uint8 *)align_ptr(p, sizeof(uint32)); \ @@ -1702,8 +1704,43 @@ wasm_runtime_dump_perf_profiling(WASMModuleInstanceCommon *module_inst) } #endif } + +double +wasm_runtime_sum_wasm_exec_time(WASMModuleInstanceCommon *inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (inst->module_type == Wasm_Module_Bytecode) + return wasm_summarize_wasm_execute_time((WASMModuleInstance *)inst); #endif +#if WASM_ENABLE_AOT != 0 + if (inst->module_type == Wasm_Module_AoT) + return aot_summarize_wasm_execute_time((AOTModuleInstance *)inst); +#endif + + return 0.0; +} + +double +wasm_runtime_get_wasm_func_exec_time(WASMModuleInstanceCommon *inst, + const char *func_name) +{ +#if WASM_ENABLE_INTERP != 0 + if (inst->module_type == Wasm_Module_Bytecode) + return wasm_get_wasm_func_exec_time((WASMModuleInstance *)inst, + func_name); +#endif + +#if WASM_ENABLE_AOT != 0 + if (inst->module_type == Wasm_Module_AoT) + return aot_get_wasm_func_exec_time((AOTModuleInstance *)inst, + func_name); +#endif + + return 0.0; +} +#endif /* WASM_ENABLE_PERF_PROFILING != 0 */ + WASMModuleInstanceCommon * wasm_runtime_get_module_inst(WASMExecEnv *exec_env) { @@ -2905,7 +2942,8 @@ copy_string_array(const char *array[], uint32 array_size, char **buf_ptr, /* We add +1 to generate null-terminated array of strings */ total_size = sizeof(char *) * ((uint64)array_size + 1); if (total_size >= UINT32_MAX - || (total_size > 0 && !(list = wasm_runtime_malloc((uint32)total_size))) + /* total_size must be larger than 0, don' check it again */ + || !(list = wasm_runtime_malloc((uint32)total_size)) || buf_size >= UINT32_MAX || (buf_size > 0 && !(buf = wasm_runtime_malloc((uint32)buf_size)))) { @@ -3536,7 +3574,7 @@ static union { char b; } __ue = { .a = 1 }; -#define is_little_endian() (__ue.b == 1) +#define is_little_endian() (__ue.b == 1) /* NOLINT */ bool wasm_runtime_register_natives(const char *module_name, @@ -4445,6 +4483,7 @@ typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint64 *, uint64); typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint64 *, uint64); typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint64 *, uint64); +/* NOLINTBEGIN */ static volatile Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)(uintptr_t)invokeNative; static volatile Float32FuncPtr invokeNative_Float32 = @@ -4460,6 +4499,7 @@ static volatile VoidFuncPtr invokeNative_Void = typedef v128 (*V128FuncPtr)(GenericFunctionPointer, uint64 *, uint64); static V128FuncPtr invokeNative_V128 = (V128FuncPtr)(uintptr_t)invokeNative; #endif +/* NOLINTEND */ #if defined(_WIN32) || defined(_WIN32_) #define MAX_REG_FLOATS 4 diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index e94464c66..164c7aff7 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -416,16 +416,6 @@ typedef struct WASMRegisteredModule { } WASMRegisteredModule; #endif -typedef struct WASMMemoryInstanceCommon { - uint32 module_type; - - /* The following uint8[1] member is a dummy just to indicate - some module_type dependent members follow. - Typically it should be accessed by casting to the corresponding - actual module_type dependent structure, not via this member. */ - uint8 memory_inst_data[1]; -} WASMMemoryInstanceCommon; - typedef package_type_t PackageType; typedef wasm_section_t WASMSection, AOTSection; diff --git a/core/iwasm/common/wasm_shared_memory.c b/core/iwasm/common/wasm_shared_memory.c index 614acb062..bd6a4328e 100644 --- a/core/iwasm/common/wasm_shared_memory.c +++ b/core/iwasm/common/wasm_shared_memory.c @@ -176,8 +176,9 @@ acquire_wait_info(void *address, AtomicWaitNode *wait_node) AtomicWaitInfo *wait_info = NULL; bh_list_status ret; - if (address) - wait_info = (AtomicWaitInfo *)bh_hash_map_find(wait_map, address); + bh_assert(address != NULL); + + wait_info = (AtomicWaitInfo *)bh_hash_map_find(wait_map, address); if (!wait_node) { return wait_info; diff --git a/core/iwasm/common/wasm_suspend_flags.h b/core/iwasm/common/wasm_suspend_flags.h index b182b2b5f..92661b7bd 100644 --- a/core/iwasm/common/wasm_suspend_flags.h +++ b/core/iwasm/common/wasm_suspend_flags.h @@ -35,6 +35,8 @@ typedef union WASMSuspendFlags { #define WASM_SUSPEND_FLAGS_FETCH_AND(s_flags, val) \ BH_ATOMIC_32_FETCH_AND(s_flags.flags, val) +#define WASM_SUSPEND_FLAG_INHERIT_MASK (~WASM_SUSPEND_FLAG_BLOCKING) + #if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0 #define WASM_SUSPEND_FLAGS_LOCK(lock) (void)0 #define WASM_SUSPEND_FLAGS_UNLOCK(lock) (void)0 diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 464ca61f3..fada0abc8 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -1050,7 +1050,9 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) uint32 opcode1; read_leb_uint32(frame_ip, frame_ip_end, opcode1); - opcode = (uint32)opcode1; + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; #if WASM_ENABLE_BULK_MEMORY != 0 if (WASM_OP_MEMORY_INIT <= opcode @@ -1211,10 +1213,13 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) case WASM_OP_ATOMIC_PREFIX: { uint8 bin_op, op_type; + uint32 opcode1; + + read_leb_uint32(frame_ip, frame_ip_end, opcode1); + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; - if (frame_ip < frame_ip_end) { - opcode = *frame_ip++; - } if (opcode != WASM_OP_ATOMIC_FENCE) { read_leb_uint32(frame_ip, frame_ip_end, align); read_leb_uint32(frame_ip, frame_ip_end, offset); @@ -1364,11 +1369,17 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) #if WASM_ENABLE_SIMD != 0 case WASM_OP_SIMD_PREFIX: { + uint32 opcode1; + if (!comp_ctx->enable_simd) { goto unsupport_simd; } - opcode = *frame_ip++; + read_leb_uint32(frame_ip, frame_ip_end, opcode1); + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; + /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h */ switch (opcode) { diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 66304339e..d674b022c 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -25,6 +25,7 @@ } \ } while (0) +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 static bool check_utf8_str(const uint8 *str, uint32 len) { @@ -89,6 +90,7 @@ check_utf8_str(const uint8 *str, uint32 len) } return (p == p_end); } +#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */ /* Internal function in object file */ typedef struct AOTObjectFunc { @@ -652,7 +654,8 @@ get_relocations_size(AOTObjectData *obj_data, /* ignore the relocations to aot_func_internal#n in text section for windows platform since they will be applied in aot_emit_text_section */ - if (!strcmp(relocation_group->section_name, ".text") + if ((!strcmp(relocation_group->section_name, ".text") + || !strcmp(relocation_group->section_name, ".ltext")) && !strncmp(relocation->symbol_name, AOT_FUNC_INTERNAL_PREFIX, strlen(AOT_FUNC_INTERNAL_PREFIX)) && ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6) @@ -1111,6 +1114,7 @@ static union { EMIT_BUF(s, str_len); \ } while (0) +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 static bool read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign, uint64 *p_result) @@ -1309,6 +1313,7 @@ get_name_section_size(AOTCompData *comp_data) fail: return 0; } +#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */ static uint32 get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data) @@ -1815,7 +1820,8 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, for (i = 0; i < obj_data->relocation_group_count; i++, relocation_group++) { /* relocation in text section */ - if (!strcmp(relocation_group->section_name, ".text")) { + if ((!strcmp(relocation_group->section_name, ".text") + || !strcmp(relocation_group->section_name, ".ltext"))) { relocation = relocation_group->relocations; relocation_count = relocation_group->relocation_count; for (j = 0; j < relocation_count; j++) { @@ -2065,6 +2071,7 @@ aot_emit_native_symbol(uint8 *buf, uint8 *buf_end, uint32 *p_offset, return true; } +#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 static bool aot_emit_name_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, AOTCompData *comp_data, AOTCompContext *comp_ctx) @@ -2090,6 +2097,7 @@ aot_emit_name_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, LOG_DEBUG("emit name section"); return true; } +#endif static bool aot_emit_custom_sections(uint8 *buf, uint8 *buf_end, uint32 *p_offset, @@ -2374,17 +2382,19 @@ aot_resolve_text(AOTObjectData *obj_data) while ( !LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { if ((name = (char *)LLVMGetSectionName(sec_itr))) { - if (!strcmp(name, ".text")) { + if (!strcmp(name, ".text") || !strcmp(name, ".ltext")) { obj_data->text = (char *)LLVMGetSectionContents(sec_itr); obj_data->text_size = (uint32)LLVMGetSectionSize(sec_itr); } - else if (!strcmp(name, ".text.unlikely.")) { + else if (!strcmp(name, ".text.unlikely.") + || !strcmp(name, ".ltext.unlikely.")) { obj_data->text_unlikely = (char *)LLVMGetSectionContents(sec_itr); obj_data->text_unlikely_size = (uint32)LLVMGetSectionSize(sec_itr); } - else if (!strcmp(name, ".text.hot.")) { + else if (!strcmp(name, ".text.hot.") + || !strcmp(name, ".ltext.hot.")) { obj_data->text_hot = (char *)LLVMGetSectionContents(sec_itr); obj_data->text_hot_size = @@ -2903,11 +2913,13 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data) (char *)LLVMGetSectionName(contain_section); LLVMDisposeSectionIterator(contain_section); - if (!strcmp(contain_section_name, ".text.unlikely.")) { + if (!strcmp(contain_section_name, ".text.unlikely.") + || !strcmp(contain_section_name, ".ltext.unlikely.")) { func->text_offset = align_uint(obj_data->text_size, 4) + LLVMGetSymbolAddress(sym_itr); } - else if (!strcmp(contain_section_name, ".text.hot.")) { + else if (!strcmp(contain_section_name, ".text.hot.") + || !strcmp(contain_section_name, ".ltext.hot.")) { func->text_offset = align_uint(obj_data->text_size, 4) + align_uint(obj_data->text_unlikely_size, 4) @@ -2939,12 +2951,14 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data) (char *)LLVMGetSectionName(contain_section); LLVMDisposeSectionIterator(contain_section); - if (!strcmp(contain_section_name, ".text.unlikely.")) { + if (!strcmp(contain_section_name, ".text.unlikely.") + || !strcmp(contain_section_name, ".ltext.unlikely.")) { func->text_offset_of_aot_func_internal = align_uint(obj_data->text_size, 4) + LLVMGetSymbolAddress(sym_itr); } - else if (!strcmp(contain_section_name, ".text.hot.")) { + else if (!strcmp(contain_section_name, ".text.hot.") + || !strcmp(contain_section_name, ".ltext.hot.")) { func->text_offset_of_aot_func_internal = align_uint(obj_data->text_size, 4) + align_uint(obj_data->text_unlikely_size, 4) @@ -3205,6 +3219,12 @@ is_relocation_section_name(AOTObjectData *obj_data, char *section_name) || !strcmp(section_name, ".rel.text.unlikely.") || !strcmp(section_name, ".rela.text.hot.") || !strcmp(section_name, ".rel.text.hot.") + || !strcmp(section_name, ".rela.ltext") + || !strcmp(section_name, ".rel.ltext") + || !strcmp(section_name, ".rela.ltext.unlikely.") + || !strcmp(section_name, ".rel.ltext.unlikely.") + || !strcmp(section_name, ".rela.ltext.hot.") + || !strcmp(section_name, ".rel.ltext.hot.") || !strcmp(section_name, ".rela.literal") || !strcmp(section_name, ".rela.data") || !strcmp(section_name, ".rel.data") @@ -3243,7 +3263,9 @@ static bool is_readonly_section(const char *name) { return !strcmp(name, ".rel.text") || !strcmp(name, ".rela.text") - || !strcmp(name, ".rela.literal") || !strcmp(name, ".text"); + || !strcmp(name, ".rel.ltext") || !strcmp(name, ".rela.ltext") + || !strcmp(name, ".rela.literal") || !strcmp(name, ".text") + || !strcmp(name, ".ltext"); } static bool @@ -3336,12 +3358,24 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data) || !strcmp(relocation_group->section_name, ".rela.text.hot.")) { relocation_group->section_name = ".rela.text"; } + else if (!strcmp(relocation_group->section_name, + ".rela.ltext.unlikely.") + || !strcmp(relocation_group->section_name, + ".rela.ltext.hot.")) { + relocation_group->section_name = ".rela.ltext"; + } else if (!strcmp(relocation_group->section_name, ".rel.text.unlikely.") || !strcmp(relocation_group->section_name, ".rel.text.hot.")) { relocation_group->section_name = ".rel.text"; } + else if (!strcmp(relocation_group->section_name, + ".rel.ltext.unlikely.") + || !strcmp(relocation_group->section_name, + ".rel.ltext.hot.")) { + relocation_group->section_name = ".rel.ltext"; + } /* * Relocations in read-only sections are problematic, diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 6f5cddcd9..028faf6e4 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -533,18 +533,12 @@ aot_add_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module, } wasm_runtime_free(params); params = NULL; - -#if LLVM_VERSION_MAJOR < 17 if (aot_target_precheck_can_use_musttail(comp_ctx)) { LLVMSetTailCallKind(retval, LLVMTailCallKindMustTail); } else { LLVMSetTailCallKind(retval, LLVMTailCallKindTail); } -#else - LLVMSetTailCall(retval, true); -#endif - if (ret_type == VOID_TYPE) { if (!LLVMBuildRetVoid(b)) { goto fail; diff --git a/core/iwasm/compilation/aot_llvm_extra2.cpp b/core/iwasm/compilation/aot_llvm_extra2.cpp index 42d9c4bee..ccbccd1e0 100644 --- a/core/iwasm/compilation/aot_llvm_extra2.cpp +++ b/core/iwasm/compilation/aot_llvm_extra2.cpp @@ -163,7 +163,7 @@ LLVMCreateTargetMachineWithOpts(LLVMTargetRef ctarget, const char *triple, } /* https://reviews.llvm.org/D153107 */ -#if LLVM_VERSION_MAJOR < 17 +#if LLVM_VERSION_MAJOR < 18 using namespace llvm; LLVMTailCallKind diff --git a/core/iwasm/compilation/aot_llvm_extra2.h b/core/iwasm/compilation/aot_llvm_extra2.h index f3f897994..be89faae0 100644 --- a/core/iwasm/compilation/aot_llvm_extra2.h +++ b/core/iwasm/compilation/aot_llvm_extra2.h @@ -17,7 +17,7 @@ LLVMCreateTargetMachineWithOpts(LLVMTargetRef ctarget, const char *triple, const char *StackUsageOutput); /* https://reviews.llvm.org/D153107 */ -#if LLVM_VERSION_MAJOR < 17 +#if LLVM_VERSION_MAJOR < 18 typedef enum { LLVMTailCallKindNone = 0, LLVMTailCallKindTail = 1, diff --git a/core/iwasm/compilation/debug/dwarf_extractor.cpp b/core/iwasm/compilation/debug/dwarf_extractor.cpp index ee32c2f75..d322aefe5 100644 --- a/core/iwasm/compilation/debug/dwarf_extractor.cpp +++ b/core/iwasm/compilation/debug/dwarf_extractor.cpp @@ -133,9 +133,10 @@ dwarf_gen_file_info(const AOTCompContext *comp_ctx) file_name = filespec.GetFilename(); dir_name = filespec.GetDirectory(); if (file_name || dir_name) { - file_info = LLVMDIBuilderCreateFile(comp_ctx->debug_builder, - file_name, strlen(file_name), - dir_name, strlen(dir_name)); + file_info = LLVMDIBuilderCreateFile( + comp_ctx->debug_builder, file_name, + file_name ? strlen(file_name) : 0, dir_name, + dir_name ? strlen(dir_name) : 0); } } return file_info; @@ -298,7 +299,7 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx, return NULL; LLVMDIBuilderRef DIB = comp_ctx->debug_builder; - LLVMMetadataRef File = comp_ctx->debug_file; + LLVMMetadataRef File = comp_ctx->debug_file; /* a fallback */ LLVMMetadataRef ParamTypes[num_function_args + 1]; @@ -315,6 +316,21 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx, } } + auto compile_unit = sc.GetCompileUnit(); + auto file_spec = compile_unit.GetFileSpec(); + const char *file_name = file_spec.GetFilename(); + const char *dir_name = file_spec.GetDirectory(); + LLVMMetadataRef file_info = NULL; + if (file_name || dir_name) { + file_info = + LLVMDIBuilderCreateFile(comp_ctx->debug_builder, file_name, + file_name ? strlen(file_name) : 0, dir_name, + dir_name ? strlen(dir_name) : 0); + } + if (file_info) { + File = file_info; + } + LLVMMetadataRef FunctionTy = LLVMDIBuilderCreateSubroutineType( DIB, File, ParamTypes, num_function_args + 1, LLVMDIFlagZero); diff --git a/core/iwasm/fast-jit/fe/jit_emit_control.c b/core/iwasm/fast-jit/fe/jit_emit_control.c index 07c6e7632..413cebaa7 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_control.c +++ b/core/iwasm/fast-jit/fe/jit_emit_control.c @@ -396,9 +396,8 @@ handle_func_return(JitCompContext *cc, JitBlock *block) #endif #if WASM_ENABLE_PERF_PROFILING != 0 - /* time_end = os_time_get_boot_microsecond() */ - if (!jit_emit_callnative(cc, os_time_get_boot_microsecond, time_end, NULL, - 0)) { + /* time_end = os_time_get_boot_us() */ + if (!jit_emit_callnative(cc, os_time_get_boot_us, time_end, NULL, 0)) { return false; } /* time_start = cur_frame->time_started */ diff --git a/core/iwasm/fast-jit/fe/jit_emit_table.c b/core/iwasm/fast-jit/fe/jit_emit_table.c index b8ed6a1d5..26bc35394 100644 --- a/core/iwasm/fast-jit/fe/jit_emit_table.c +++ b/core/iwasm/fast-jit/fe/jit_emit_table.c @@ -88,17 +88,21 @@ fail: } static int -wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx, +wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 seg_idx, uint32 dst_offset, uint32 len, uint32 src_offset) { WASMTableInstance *tbl; uint32 tbl_sz; - WASMTableSeg *elem; - uint32 elem_len; + WASMTableSeg *tbl_seg = inst->module->table_segments + seg_idx; + uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0; - elem = inst->module->table_segments + elem_idx; - elem_len = elem->function_count; - if (offset_len_out_of_bounds(src_offset, len, elem_len)) + if (!bh_bitmap_get_bit(inst->e->common.elem_dropped, seg_idx)) { + /* table segment isn't dropped */ + tbl_seg_elems = tbl_seg->func_indexes; + tbl_seg_len = tbl_seg->function_count; + } + + if (offset_len_out_of_bounds(src_offset, len, tbl_seg_len)) goto out_of_bounds; tbl = inst->tables[tbl_idx]; @@ -109,14 +113,10 @@ wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx, if (!len) return 0; - if (bh_bitmap_get_bit(inst->e->common.elem_dropped, elem_idx)) - goto out_of_bounds; - bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems) + dst_offset * sizeof(uint32), (uint32)((tbl_sz - dst_offset) * sizeof(uint32)), - elem->func_indexes + src_offset, - (uint32)(len * sizeof(uint32))); + tbl_seg_elems + src_offset, (uint32)(len * sizeof(uint32))); return 0; out_of_bounds: diff --git a/core/iwasm/fast-jit/jit_frontend.c b/core/iwasm/fast-jit/jit_frontend.c index c9c22e0ad..e9d7a3ff3 100644 --- a/core/iwasm/fast-jit/jit_frontend.c +++ b/core/iwasm/fast-jit/jit_frontend.c @@ -1157,11 +1157,10 @@ init_func_translation(JitCompContext *cc) func_inst = jit_cc_new_reg_ptr(cc); #if WASM_ENABLE_PERF_PROFILING != 0 time_started = jit_cc_new_reg_I64(cc); - /* Call os_time_get_boot_microsecond() to get time_started firstly + /* Call os_time_get_boot_us() to get time_started firstly as there is stack frame switching below, calling native in them may cause register spilling work inproperly */ - if (!jit_emit_callnative(cc, os_time_get_boot_microsecond, time_started, - NULL, 0)) { + if (!jit_emit_callnative(cc, os_time_get_boot_us, time_started, NULL, 0)) { return NULL; } #endif @@ -2258,7 +2257,9 @@ jit_compile_func(JitCompContext *cc) uint32 opcode1; read_leb_uint32(frame_ip, frame_ip_end, opcode1); - opcode = (uint32)opcode1; + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; switch (opcode) { case WASM_OP_I32_TRUNC_SAT_S_F32: @@ -2397,10 +2398,13 @@ jit_compile_func(JitCompContext *cc) case WASM_OP_ATOMIC_PREFIX: { uint8 bin_op, op_type; + uint32 opcode1; + + read_leb_uint32(frame_ip, frame_ip_end, opcode1); + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; - if (frame_ip < frame_ip_end) { - opcode = *frame_ip++; - } if (opcode != WASM_OP_ATOMIC_FENCE) { read_leb_uint32(frame_ip, frame_ip_end, align); read_leb_uint32(frame_ip, frame_ip_end, offset); diff --git a/core/iwasm/include/wasm_c_api.h b/core/iwasm/include/wasm_c_api.h index 1d49376e0..304b3a4ee 100644 --- a/core/iwasm/include/wasm_c_api.h +++ b/core/iwasm/include/wasm_c_api.h @@ -22,12 +22,12 @@ #endif #if defined(__GNUC__) || defined(__clang__) -#define DEPRECATED __attribute__((deprecated)) +#define WASM_API_DEPRECATED __attribute__((deprecated)) #elif defined(_MSC_VER) -#define DEPRECATED __declspec(deprecated) +#define WASM_API_DEPRECATED __declspec(deprecated) #else #pragma message("WARNING: You need to implement DEPRECATED for this compiler") -#define DEPRECATED +#define WASM_API_DEPRECATED #endif #ifdef __cplusplus @@ -231,7 +231,7 @@ WASM_DECLARE_OWN(engine) */ WASM_API_EXTERN own wasm_engine_t* wasm_engine_new(void); WASM_API_EXTERN own wasm_engine_t* wasm_engine_new_with_config(wasm_config_t*); -DEPRECATED WASM_API_EXTERN own wasm_engine_t * +WASM_API_DEPRECATED WASM_API_EXTERN own wasm_engine_t * wasm_engine_new_with_args(mem_alloc_type_t type, const MemAllocOption *opts); // Store @@ -828,12 +828,12 @@ static inline void* wasm_val_ptr(const wasm_val_t* val) { #endif } -#define WASM_I32_VAL(i) {.kind = WASM_I32, .of = {.i32 = i}} -#define WASM_I64_VAL(i) {.kind = WASM_I64, .of = {.i64 = i}} -#define WASM_F32_VAL(z) {.kind = WASM_F32, .of = {.f32 = z}} -#define WASM_F64_VAL(z) {.kind = WASM_F64, .of = {.f64 = z}} -#define WASM_REF_VAL(r) {.kind = WASM_ANYREF, .of = {.ref = r}} -#define WASM_INIT_VAL {.kind = WASM_ANYREF, .of = {.ref = NULL}} +#define WASM_I32_VAL(i) {.kind = WASM_I32, .__paddings = {0}, .of = {.i32 = i}} +#define WASM_I64_VAL(i) {.kind = WASM_I64, .__paddings = {0}, .of = {.i64 = i}} +#define WASM_F32_VAL(z) {.kind = WASM_F32, .__paddings = {0}, .of = {.f32 = z}} +#define WASM_F64_VAL(z) {.kind = WASM_F64, .__paddings = {0}, .of = {.f64 = z}} +#define WASM_REF_VAL(r) {.kind = WASM_ANYREF, .__paddings = {0}, .of = {.ref = r}} +#define WASM_INIT_VAL {.kind = WASM_ANYREF, .__paddings = {0}, .of = {.ref = NULL}} #define KILOBYTE(n) ((n) * 1024) diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index c27b52339..dda058d08 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -1274,6 +1274,26 @@ wasm_runtime_dump_mem_consumption(wasm_exec_env_t exec_env); WASM_RUNTIME_API_EXTERN void wasm_runtime_dump_perf_profiling(wasm_module_inst_t module_inst); +/** + * Return total wasm functions' execution time in ms + * + * @param module_inst the WASM module instance to profile + */ +WASM_RUNTIME_API_EXTERN double +wasm_runtime_sum_wasm_exec_time(wasm_module_inst_t module_inst); + +/** + * Return execution time in ms of a given wasm funciton with +* func_name. If the function is not found, return 0. + * + * @param module_inst the WASM module instance to profile + * @param func_name could be an export name or a name in the + * name section + */ +WASM_RUNTIME_API_EXTERN double +wasm_runtime_get_wasm_func_exec_time(wasm_module_inst_t inst, + const char *func_name); + /* wasm thread callback function type */ typedef void *(*wasm_thread_callback_t)(wasm_exec_env_t, void *); /* wasm thread type */ @@ -1587,6 +1607,9 @@ wasm_runtime_get_context(wasm_module_inst_t inst, void *key); * host functions. It wraps an operation which possibly blocks for long * to prepare for async termination. * + * For simplicity, we recommend to wrap only the very minimum piece of + * the code with this. Ideally, just a single system call. + * * eg. * * if (!wasm_runtime_begin_blocking_op(exec_env)) { diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h index 518e76642..60e1238ad 100644 --- a/core/iwasm/interpreter/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -65,6 +65,9 @@ extern "C" { #if WASM_ENABLE_BULK_MEMORY != 0 #define SECTION_TYPE_DATACOUNT 12 #endif +#if WASM_ENABLE_TAGS != 0 +#define SECTION_TYPE_TAG 13 +#endif #define SUB_SECTION_TYPE_MODULE 0 #define SUB_SECTION_TYPE_FUNC 1 @@ -74,20 +77,34 @@ extern "C" { #define IMPORT_KIND_TABLE 1 #define IMPORT_KIND_MEMORY 2 #define IMPORT_KIND_GLOBAL 3 +#if WASM_ENABLE_TAGS != 0 +#define IMPORT_KIND_TAG 4 +#endif #define EXPORT_KIND_FUNC 0 #define EXPORT_KIND_TABLE 1 #define EXPORT_KIND_MEMORY 2 #define EXPORT_KIND_GLOBAL 3 +#if WASM_ENABLE_TAGS != 0 +#define EXPORT_KIND_TAG 4 +#endif #define LABEL_TYPE_BLOCK 0 #define LABEL_TYPE_LOOP 1 #define LABEL_TYPE_IF 2 #define LABEL_TYPE_FUNCTION 3 +#if WASM_ENABLE_EXCE_HANDLING != 0 +#define LABEL_TYPE_TRY 4 +#define LABEL_TYPE_CATCH 5 +#define LABEL_TYPE_CATCH_ALL 6 +#endif typedef struct WASMModule WASMModule; typedef struct WASMFunction WASMFunction; typedef struct WASMGlobal WASMGlobal; +#if WASM_ENABLE_TAGS != 0 +typedef struct WASMTag WASMTag; +#endif typedef union V128 { int8 i8x16[16]; @@ -201,6 +218,24 @@ typedef struct WASMFunctionImport { bool call_conv_wasm_c_api; } WASMFunctionImport; +#if WASM_ENABLE_TAGS != 0 +typedef struct WASMTagImport { + char *module_name; + char *field_name; + uint8 attribute; /* the type of the tag (numerical) */ + uint32 type; /* the type of the catch function (numerical)*/ + WASMType *tag_type; + void *tag_ptr_linked; + +#if WASM_ENABLE_MULTI_MODULE != 0 + /* imported tag pointer after linked */ + WASMModule *import_module; + WASMTag *import_tag_linked; + uint32 import_tag_index_linked; +#endif +} WASMTagImport; +#endif + typedef struct WASMGlobalImport { char *module_name; char *field_name; @@ -227,6 +262,9 @@ typedef struct WASMImport { WASMFunctionImport function; WASMTableImport table; WASMMemoryImport memory; +#if WASM_ENABLE_TAGS != 0 + WASMTagImport tag; +#endif WASMGlobalImport global; struct { char *module_name; @@ -265,6 +303,10 @@ struct WASMFunction { uint32 const_cell_num; #endif +#if WASM_ENABLE_EXCE_HANDLING != 0 + uint32 exception_handler_count; +#endif + #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ || WASM_ENABLE_WAMR_COMPILER != 0 /* Whether function has opcode memory.grow */ @@ -294,6 +336,14 @@ struct WASMFunction { #endif }; +#if WASM_ENABLE_TAGS != 0 +struct WASMTag { + uint8 attribute; /* the attribute property of the tag (expected to be 0) */ + uint32 type; /* the type of the tag (expected valid inden in type table) */ + WASMType *tag_type; +}; +#endif + struct WASMGlobal { uint8 type; bool is_mutable; @@ -420,6 +470,9 @@ struct WASMModule { uint32 function_count; uint32 table_count; uint32 memory_count; +#if WASM_ENABLE_TAGS != 0 + uint32 tag_count; +#endif uint32 global_count; uint32 export_count; uint32 table_seg_count; @@ -433,11 +486,17 @@ struct WASMModule { uint32 import_function_count; uint32 import_table_count; uint32 import_memory_count; +#if WASM_ENABLE_TAGS != 0 + uint32 import_tag_count; +#endif uint32 import_global_count; WASMImport *import_functions; WASMImport *import_tables; WASMImport *import_memories; +#if WASM_ENABLE_TAGS != 0 + WASMImport *import_tags; +#endif WASMImport *import_globals; WASMType **types; @@ -445,6 +504,9 @@ struct WASMModule { WASMFunction **functions; WASMTable *tables; WASMMemory *memories; +#if WASM_ENABLE_TAGS != 0 + WASMTag **tags; +#endif WASMGlobal *globals; WASMExport *exports; WASMTableSeg *table_segments; @@ -628,6 +690,11 @@ typedef struct WASMBranchBlock { uint8 *target_addr; uint32 *frame_sp; uint32 cell_num; +#if WASM_ENABLE_EXCE_HANDLING != 0 + /* in exception handling, label_type needs to be stored to lookup exception + * handlers */ + uint8 label_type; +#endif } WASMBranchBlock; /** diff --git a/core/iwasm/interpreter/wasm_interp.h b/core/iwasm/interpreter/wasm_interp.h index d3692ff21..2b5a51ea8 100644 --- a/core/iwasm/interpreter/wasm_interp.h +++ b/core/iwasm/interpreter/wasm_interp.h @@ -34,6 +34,14 @@ typedef struct WASMInterpFrame { uint64 time_started; #endif +#if WASM_ENABLE_EXCE_HANDLING != 0 + /* set to true if the callee returns an exception rather than + * result values on the stack + */ + bool exception_raised; + uint32 tag_index; +#endif + #if WASM_ENABLE_FAST_INTERP != 0 /* Return offset of the first return value of current frame, the callee will put return values here continuously */ diff --git a/core/iwasm/interpreter/wasm_interp_classic.c b/core/iwasm/interpreter/wasm_interp_classic.c index 7e39c9a1e..9d221c772 100644 --- a/core/iwasm/interpreter/wasm_interp_classic.c +++ b/core/iwasm/interpreter/wasm_interp_classic.c @@ -340,10 +340,19 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) frame_sp += 2; \ } while (0) +/* in exception handling, label_type needs to be stored to lookup exception + * handlers */ + +#if WASM_ENABLE_EXCE_HANDLING != 0 +#define SET_LABEL_TYPE(_label_type) frame_csp->label_type = _label_type +#else +#define SET_LABEL_TYPE(_label_type) (void)0 +#endif + #define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \ do { \ bh_assert(frame_csp < frame->csp_boundary); \ - /* frame_csp->label_type = _label_type; */ \ + SET_LABEL_TYPE(_label_type); \ frame_csp->cell_num = cell_num; \ frame_csp->begin_addr = frame_ip; \ frame_csp->target_addr = _target_addr; \ @@ -394,6 +403,18 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) frame_sp -= n; \ } while (0) +#if WASM_ENABLE_EXCE_HANDLING != 0 +/* unwind the CSP to a given label and optionally modify the labeltype */ +#define UNWIND_CSP(N, T) \ + do { \ + /* unwind to function frame */ \ + frame_csp -= N; \ + /* drop handlers and values pushd in try block */ \ + frame_sp = (frame_csp - 1)->frame_sp; \ + (frame_csp - 1)->label_type = T ? T : (frame_csp - 1)->label_type; \ + } while (0) +#endif + #define SYNC_ALL_TO_FRAME() \ do { \ frame->sp = frame_sp; \ @@ -852,7 +873,7 @@ ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame) if (frame) { frame->prev_frame = prev_frame; #if WASM_ENABLE_PERF_PROFILING != 0 - frame->time_started = os_time_get_boot_microsecond(); + frame->time_started = os_time_thread_cputime_us(); #endif } else { @@ -868,9 +889,13 @@ FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame) { #if WASM_ENABLE_PERF_PROFILING != 0 if (frame->function) { - frame->function->total_exec_time += - os_time_get_boot_microsecond() - frame->time_started; + WASMInterpFrame *prev_frame = frame->prev_frame; + uint64 elapsed = os_time_thread_cputime_us() - frame->time_started; + frame->function->total_exec_time += elapsed; frame->function->total_exec_cnt++; + + if (prev_frame && prev_frame->function) + prev_frame->function->children_exec_time += elapsed; } #endif wasm_exec_env_free_wasm_frame(exec_env, frame); @@ -1181,6 +1206,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 local_idx, local_offset, global_idx; uint8 local_type, *global_addr; uint32 cache_index, type_index, param_cell_num, cell_num; +#if WASM_ENABLE_EXCE_HANDLING != 0 + int32_t exception_tag_index; +#endif uint8 value_type; #if !defined(OS_ENABLE_HW_BOUND_CHECK) \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 @@ -1223,6 +1251,390 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_NOP) { HANDLE_OP_END(); } +#if WASM_ENABLE_EXCE_HANDLING != 0 + + HANDLE_OP(WASM_OP_RETHROW) + { + int32_t relative_depth; + read_leb_int32(frame_ip, frame_ip_end, relative_depth); + + /* No frame found with exception handler; validation should + * catch it */ + bh_assert(frame_csp >= frame->csp_bottom + relative_depth); + + /* go up the frame stack */ + WASMBranchBlock *tgtframe = (frame_csp - 1) - relative_depth; + + bh_assert(tgtframe->label_type == LABEL_TYPE_CATCH + || tgtframe->label_type == LABEL_TYPE_CATCH_ALL); + + /* tgtframe points to the frame containing a thrown + * exception */ + + uint32 *tgtframe_sp = tgtframe->frame_sp; + + /* frame sp of tgtframe points to catched exception */ + exception_tag_index = *((uint32 *)tgtframe_sp); + tgtframe_sp++; + + /* get tag type */ + uint8 tag_type_index = + module->module->tags[exception_tag_index]->type; + uint32 cell_num_to_copy = + wasm_types[tag_type_index]->param_cell_num; + + /* move exception parameters (if there are any) onto top + * of stack */ + if (cell_num_to_copy > 0) { + word_copy(frame_sp, tgtframe_sp - cell_num_to_copy, + cell_num_to_copy); + } + + frame_sp += cell_num_to_copy; + goto find_a_catch_handler; + } + + HANDLE_OP(WASM_OP_THROW) + { + read_leb_int32(frame_ip, frame_ip_end, exception_tag_index); + + /* landing pad for the rethrow ? */ + find_a_catch_handler: + { + WASMType *tag_type = NULL; + uint32 cell_num_to_copy = 0; + if (IS_INVALID_TAGINDEX(exception_tag_index)) { + /* + * invalid exception index, + * generated if a submodule throws an exception + * that has not been imported here + * + * This should result in a branch to the CATCH_ALL block, + * if there is one + */ + tag_type = NULL; + cell_num_to_copy = 0; + } + else { + if (module->e->tags[exception_tag_index].is_import_tag) { + tag_type = module->e->tags[exception_tag_index] + .u.tag_import->tag_type; + } + else { + tag_type = module->e->tags[exception_tag_index] + .u.tag->tag_type; + } + cell_num_to_copy = tag_type->param_cell_num; + } + + /* browse through frame stack */ + uint32 relative_depth = 0; + do { + POP_CSP_CHECK_OVERFLOW(relative_depth - 1); + WASMBranchBlock *tgtframe = frame_csp - relative_depth - 1; + + switch (tgtframe->label_type) { + case LABEL_TYPE_BLOCK: + case LABEL_TYPE_IF: + case LABEL_TYPE_LOOP: + case LABEL_TYPE_CATCH: + case LABEL_TYPE_CATCH_ALL: + /* + * skip that blocks in search + * BLOCK, IF and LOOP do not contain handlers and + * cannot catch exceptions. + * blocks marked as CATCH or + * CATCH_ALL did already caugth an exception and can + * only be a target for RETHROW, but cannot catch an + * exception again + */ + break; + case LABEL_TYPE_TRY: + { + uint32 handler_number = 0; + uint8 **handlers = (uint8 **)tgtframe->frame_sp; + uint8 *handler = NULL; + while ((handler = handlers[handler_number]) != 0) { + uint8 handler_opcode = *handler; + uint8 *target_addr = + handler + + 1; /* first instruction or leb-immediate + behind the handler opcode */ + switch (handler_opcode) { + case WASM_OP_CATCH: + { + int32 lookup_index = 0; + /* read the tag_index and advance + * target_addr to the first instruction + * in the block */ + read_leb_int32(target_addr, 0, + lookup_index); + + if (exception_tag_index + == lookup_index) { + /* set ip */ + frame_ip = target_addr; + /* save frame_sp (points to + * exception values) */ + uint32 *frame_sp_old = frame_sp; + + UNWIND_CSP(relative_depth, + LABEL_TYPE_CATCH); + + /* push exception_tag_index and + * exception values for rethrow */ + PUSH_I32(exception_tag_index); + if (cell_num_to_copy > 0) { + word_copy( + frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + /* push exception values for + * catch + */ + word_copy( + frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + } + + /* advance to handler */ + HANDLE_OP_END(); + } + break; + } + case WASM_OP_DELEGATE: + { + int32 lookup_depth = 0; + /* read the depth */ + read_leb_int32(target_addr, 0, + lookup_depth); + + /* save frame_sp (points to exception + * values) */ + uint32 *frame_sp_old = frame_sp; + + UNWIND_CSP(relative_depth, + LABEL_TYPE_CATCH); + + /* leave the block (the delegate is + * technically not inside the frame) */ + frame_csp--; + + /* unwind to delegated frame */ + frame_csp -= lookup_depth; + + /* push exception values for catch */ + if (cell_num_to_copy > 0) { + word_copy(frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + } + + /* tag_index is already stored in + * exception_tag_index */ + goto find_a_catch_handler; + } + case WASM_OP_CATCH_ALL: + { + /* no immediate */ + /* save frame_sp (points to exception + * values) */ + uint32 *frame_sp_old = frame_sp; + /* set ip */ + frame_ip = target_addr; + + UNWIND_CSP(relative_depth, + LABEL_TYPE_CATCH_ALL); + + /* push exception_tag_index and + * exception values for rethrow */ + PUSH_I32(exception_tag_index); + if (cell_num_to_copy > 0) { + word_copy(frame_sp, + frame_sp_old + - cell_num_to_copy, + cell_num_to_copy); + frame_sp += cell_num_to_copy; + } + /* catch_all has no exception values */ + + /* advance to handler */ + HANDLE_OP_END(); + } + default: + wasm_set_exception( + module, "WASM_OP_THROW found " + "unexpected handler type"); + goto got_exception; + } + handler_number++; + } + /* exception not catched in this frame */ + break; + } + case LABEL_TYPE_FUNCTION: + { + /* save frame_sp (points to exception values) */ + uint32 *frame_sp_old = frame_sp; + + UNWIND_CSP(relative_depth, LABEL_TYPE_FUNCTION); + /* push exception values for catch + * The values are copied to the CALLER FRAME + * (prev_frame->sp) same behvior ad WASM_OP_RETURN + */ + if (cell_num_to_copy > 0) { + word_copy(prev_frame->sp, + frame_sp_old - cell_num_to_copy, + cell_num_to_copy); + prev_frame->sp += cell_num_to_copy; + } + *((int32 *)(prev_frame->sp)) = exception_tag_index; + prev_frame->sp++; + + /* mark frame as raised exception */ + wasm_set_exception(module, + "uncaught wasm exception"); + + /* end of function, treat as WASM_OP_RETURN */ + goto return_func; + } + default: + wasm_set_exception( + module, + "unexpected or invalid label in THROW or " + "RETHROW when searching a catch handler"); + goto got_exception; + } + + relative_depth++; + + } while (1); + } + + /* something went wrong. normally, we should always find the + * func label. if not, stop the interpreter */ + wasm_set_exception( + module, "WASM_OP_THROW hit the bottom of the frame stack"); + goto got_exception; + } + + HANDLE_OP(EXT_OP_TRY) + { + /* read the blocktype */ + read_leb_uint32(frame_ip, frame_ip_end, type_index); + param_cell_num = wasm_types[type_index]->param_cell_num; + cell_num = wasm_types[type_index]->ret_cell_num; + goto handle_op_try; + } + + HANDLE_OP(WASM_OP_TRY) + { + value_type = *frame_ip++; + param_cell_num = 0; + cell_num = wasm_value_type_cell_num(value_type); + + handle_op_try: + + cache_index = ((uintptr_t)frame_ip) + & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1); + cache_items = exec_env->block_addr_cache[cache_index]; + if (cache_items[0].start_addr == frame_ip) { + cache_items[0].start_addr = 0; + } + if (cache_items[1].start_addr == frame_ip) { + cache_items[1].start_addr = 0; + } + + /* start at the first opcode following the try and its blocktype + */ + uint8 *lookup_cursor = frame_ip; + uint8 handler_opcode = WASM_OP_UNREACHABLE; + + /* target_addr filled in when END or DELEGATE is found */ + PUSH_CSP(LABEL_TYPE_TRY, param_cell_num, cell_num, 0); + + /* reset to begin of block */ + lookup_cursor = frame_ip; + do { + /* lookup the next CATCH, CATCH_ALL or END for this TRY */ + if (!wasm_loader_find_block_addr( + exec_env, (BlockAddr *)exec_env->block_addr_cache, + lookup_cursor, (uint8 *)-1, LABEL_TYPE_TRY, + &else_addr, &end_addr)) { + /* something went wrong */ + wasm_set_exception(module, "find block address failed"); + goto got_exception; + } + + /* place cursor for continuation past opcode */ + lookup_cursor = end_addr + 1; + + /* end_addr points to CATCH, CATCH_ALL, DELEGATE or END */ + handler_opcode = *end_addr; + switch (handler_opcode) { + case WASM_OP_CATCH: + skip_leb(lookup_cursor); /* skip tag_index */ + PUSH_I64(end_addr); + break; + case WASM_OP_CATCH_ALL: + PUSH_I64(end_addr); + break; + case WASM_OP_DELEGATE: + skip_leb(lookup_cursor); /* skip depth */ + PUSH_I64(end_addr); + /* patch target_addr */ + (frame_csp - 1)->target_addr = lookup_cursor; + break; + case WASM_OP_END: + PUSH_I64(0); + /* patch target_addr */ + (frame_csp - 1)->target_addr = end_addr; + break; + default: + /* something went wrong */ + wasm_set_exception(module, + "find block address returned an " + "unexpected opcode"); + goto got_exception; + } + /* ... search until the returned address is the END of the + * TRY block */ + } while (handler_opcode != WASM_OP_END + && handler_opcode != WASM_OP_DELEGATE); + /* handler setup on stack complete */ + + HANDLE_OP_END(); + } + HANDLE_OP(WASM_OP_CATCH) + { + /* skip the tag_index */ + skip_leb(frame_ip); + /* leave the frame */ + POP_CSP_N(0); + HANDLE_OP_END(); + } + HANDLE_OP(WASM_OP_CATCH_ALL) + { + /* leave the frame */ + POP_CSP_N(0); + HANDLE_OP_END(); + } + HANDLE_OP(WASM_OP_DELEGATE) + { + /* skip the delegate depth */ + skip_leb(frame_ip); + /* leave the frame like WASM_OP_END */ + POP_CSP(); + HANDLE_OP_END(); + } +#endif HANDLE_OP(EXT_OP_BLOCK) { read_leb_uint32(frame_ip, frame_ip_end, type_index); @@ -3096,6 +3508,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 opcode1; read_leb_uint32(frame_ip, frame_ip_end, opcode1); + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ opcode = (uint8)opcode1; switch (opcode) { @@ -3254,6 +3668,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 tbl_idx, elem_idx; uint32 n, s, d; WASMTableInstance *tbl_inst; + uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0; read_leb_uint32(frame_ip, frame_ip_end, elem_idx); bh_assert(elem_idx < module->module->table_seg_count); @@ -3267,10 +3682,18 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, s = (uint32)POP_I32(); d = (uint32)POP_I32(); - if (offset_len_out_of_bounds( - s, n, + if (!bh_bitmap_get_bit(module->e->common.elem_dropped, + elem_idx)) { + /* table segment isn't dropped */ + tbl_seg_elems = module->module->table_segments[elem_idx] - .function_count) + .func_indexes; + tbl_seg_len = + module->module->table_segments[elem_idx] + .function_count; + } + + if (offset_len_out_of_bounds(s, n, tbl_seg_len) || offset_len_out_of_bounds(d, n, tbl_inst->cur_size)) { wasm_set_exception(module, @@ -3282,30 +3705,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, break; } - if (bh_bitmap_get_bit(module->e->common.elem_dropped, - elem_idx)) { - wasm_set_exception(module, - "out of bounds table access"); - goto got_exception; - } - - if (!wasm_elem_is_passive( - module->module->table_segments[elem_idx] - .mode)) { - wasm_set_exception(module, - "out of bounds table access"); - goto got_exception; - } - bh_memcpy_s( (uint8 *)tbl_inst + offsetof(WASMTableInstance, elems) + d * sizeof(uint32), (uint32)((tbl_inst->cur_size - d) * sizeof(uint32)), - module->module->table_segments[elem_idx] - .func_indexes - + s, - (uint32)(n * sizeof(uint32))); + tbl_seg_elems + s, (uint32)(n * sizeof(uint32))); break; } @@ -3436,9 +3841,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #if WASM_ENABLE_SHARED_MEMORY != 0 HANDLE_OP(WASM_OP_ATOMIC_PREFIX) { - uint32 offset = 0, align, addr; + uint32 offset = 0, align = 0, addr; + uint32 opcode1; - opcode = *frame_ip++; + read_leb_uint32(frame_ip, frame_ip_end, opcode1); + /* opcode1 was checked in loader and is no larger than + UINT8_MAX */ + opcode = (uint8)opcode1; if (opcode != WASM_OP_ATOMIC_FENCE) { read_leb_uint32(frame_ip, frame_ip_end, align); @@ -3816,10 +4225,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 - HANDLE_OP(WASM_OP_UNUSED_0x06) - HANDLE_OP(WASM_OP_UNUSED_0x07) - HANDLE_OP(WASM_OP_UNUSED_0x08) - HANDLE_OP(WASM_OP_UNUSED_0x09) HANDLE_OP(WASM_OP_UNUSED_0x0a) #if WASM_ENABLE_TAIL_CALL == 0 HANDLE_OP(WASM_OP_RETURN_CALL) @@ -3835,13 +4240,26 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_REF_NULL) HANDLE_OP(WASM_OP_REF_IS_NULL) HANDLE_OP(WASM_OP_REF_FUNC) +#endif +#if WASM_ENABLE_EXCE_HANDLING == 0 + HANDLE_OP(WASM_OP_TRY) + HANDLE_OP(WASM_OP_CATCH) + HANDLE_OP(WASM_OP_THROW) + HANDLE_OP(WASM_OP_RETHROW) + HANDLE_OP(WASM_OP_DELEGATE) + HANDLE_OP(WASM_OP_CATCH_ALL) + HANDLE_OP(EXT_OP_TRY) +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_SIMD != 0 + /* SIMD isn't supported by interpreter, but when JIT is + enabled, `iwasm --interp ` may be run to + trigger the SIMD opcode in interpreter */ + HANDLE_OP(WASM_OP_SIMD_PREFIX) #endif HANDLE_OP(WASM_OP_UNUSED_0x14) HANDLE_OP(WASM_OP_UNUSED_0x15) HANDLE_OP(WASM_OP_UNUSED_0x16) HANDLE_OP(WASM_OP_UNUSED_0x17) - HANDLE_OP(WASM_OP_UNUSED_0x18) - HANDLE_OP(WASM_OP_UNUSED_0x19) HANDLE_OP(WASM_OP_UNUSED_0x27) /* Used by fast interpreter */ HANDLE_OP(EXT_OP_SET_LOCAL_FAST_I64) @@ -3892,6 +4310,50 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (cur_func->import_func_inst) { wasm_interp_call_func_import(module, exec_env, cur_func, prev_frame); +#if WASM_ENABLE_EXCE_HANDLING != 0 + char uncaught_exception[128] = { 0 }; + bool has_exception = + wasm_copy_exception(module, uncaught_exception); + if (has_exception + && strstr(uncaught_exception, "uncaught wasm exception")) { + /* fix framesp */ + UPDATE_ALL_FROM_FRAME(); + + uint32 import_exception; + /* initialize imported exception index to be invalid */ + SET_INVALID_TAGINDEX(import_exception); + + /* pull external exception */ + uint32 ext_exception = POP_I32(); + + /* external function came back with an exception or trap */ + /* lookup exception in import tags */ + WASMTagInstance *tag = module->e->tags; + for (uint32 t = 0; t < module->module->import_tag_count; + tag++, t++) { + + /* compare the module and the external index with the + * imort tag data */ + if ((cur_func->u.func_import->import_module + == tag->u.tag_import->import_module) + && (ext_exception + == tag->u.tag_import + ->import_tag_index_linked)) { + /* set the import_exception to the import tag */ + import_exception = t; + break; + } + } + /* + * excange the thrown exception (index valid in submodule) + * with the imported exception index (valid in this module) + * if the module did not import the exception, + * that results in a "INVALID_TAGINDEX", that triggers + * an CATCH_ALL block, if there is one. + */ + PUSH_I32(import_exception); + } +#endif } else #endif @@ -3912,19 +4374,58 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, if (memory) linear_mem_size = get_linear_mem_size(); #endif - if (wasm_copy_exception(module, NULL)) + if (wasm_copy_exception(module, NULL)) { +#if WASM_ENABLE_EXCE_HANDLING != 0 + /* the caller raised an exception */ + char uncaught_exception[128] = { 0 }; + bool has_exception = + wasm_copy_exception(module, uncaught_exception); + + /* libc_builtin signaled a "exception thrown by stdc++" trap */ + if (has_exception + && strstr(uncaught_exception, + "exception thrown by stdc++")) { + wasm_set_exception(module, NULL); + + /* setup internal c++ rethrow */ + exception_tag_index = 0; + goto find_a_catch_handler; + } + + /* when throw hits the end of a function it signalles with a + * "uncaught wasm exception" trap */ + if (has_exception + && strstr(uncaught_exception, "uncaught wasm exception")) { + wasm_set_exception(module, NULL); + exception_tag_index = POP_I32(); + + /* rethrow the exception into that frame */ + goto find_a_catch_handler; + } +#endif goto got_exception; + } } else { WASMFunction *cur_wasm_func = cur_func->u.func; WASMType *func_type; + uint32 max_stack_cell_num = cur_wasm_func->max_stack_cell_num; + +#if WASM_ENABLE_EXCE_HANDLING != 0 + /* account for exception handlers */ + /* bundle them here */ + uint32 eh_size = + cur_wasm_func->exception_handler_count * sizeof(uint8 *); + max_stack_cell_num += eh_size; +#endif func_type = cur_wasm_func->func_type; all_cell_num = cur_func->param_cell_num + cur_func->local_cell_num - + cur_wasm_func->max_stack_cell_num + + max_stack_cell_num + cur_wasm_func->max_block_num * (uint32)sizeof(WASMBranchBlock) / 4; + /* param_cell_num, local_cell_num, max_stack_cell_num and max_block_num are all no larger than UINT16_MAX (checked in loader), all_cell_num must be smaller than 1MB */ @@ -3944,8 +4445,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, frame_sp = frame->sp_bottom = frame_lp + cur_func->param_cell_num + cur_func->local_cell_num; - frame->sp_boundary = - frame->sp_bottom + cur_wasm_func->max_stack_cell_num; + frame->sp_boundary = frame->sp_bottom + max_stack_cell_num; frame_csp = frame->csp_bottom = (WASMBranchBlock *)frame->sp_boundary; @@ -3973,11 +4473,19 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, FREE_FRAME(exec_env, frame); wasm_exec_env_set_cur_frame(exec_env, prev_frame); - if (!prev_frame->ip) + if (!prev_frame->ip) { /* Called from native. */ return; + } RECOVER_CONTEXT(prev_frame); +#if WASM_ENABLE_EXCE_HANDLING != 0 + if (wasm_get_exception(module)) { + wasm_set_exception(module, NULL); + exception_tag_index = POP_I32(); + goto find_a_catch_handler; + } +#endif HANDLE_OP_END(); } @@ -4199,14 +4707,11 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, #if WASM_ENABLE_QUICK_AOT_ENTRY != 0 /* Quick call if the quick jit entry is registered */ if (func_type->quick_aot_entry) { - void (*invoke_native)( - void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv, - uint32 *argv_ret) = func_type->quick_aot_entry; - invoke_native(module_inst->func_ptrs[func_idx], - func_type->result_count > 0 - ? func_type->types[func_type->param_count] - : VALUE_TYPE_VOID, - exec_env, argv, argv); + void (*invoke_native)(void *func_ptr, void *exec_env, uint32 *argv, + uint32 *argv_ret) = + func_type->quick_aot_entry; + invoke_native(module_inst->func_ptrs[func_idx], exec_env, argv, + argv); ret = !wasm_copy_exception(module_inst, NULL); } else diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 311224044..7f353e58b 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -887,7 +887,7 @@ ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame) if (frame) { frame->prev_frame = prev_frame; #if WASM_ENABLE_PERF_PROFILING != 0 - frame->time_started = os_time_get_boot_microsecond(); + frame->time_started = os_time_thread_cputime_us(); #endif } else { @@ -903,9 +903,13 @@ FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame) { #if WASM_ENABLE_PERF_PROFILING != 0 if (frame->function) { - frame->function->total_exec_time += - os_time_get_boot_microsecond() - frame->time_started; + WASMInterpFrame *prev_frame = frame->prev_frame; + uint64 elapsed = os_time_thread_cputime_us() - frame->time_started; + frame->function->total_exec_time += elapsed; frame->function->total_exec_cnt++; + + if (prev_frame && prev_frame->function) + prev_frame->function->children_exec_time += elapsed; } #endif wasm_exec_env_free_wasm_frame(exec_env, frame); @@ -1447,6 +1451,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, goto call_func_from_interp; } +#if WASM_ENABLE_EXCE_HANDLING != 0 + HANDLE_OP(WASM_OP_TRY) + HANDLE_OP(WASM_OP_CATCH) + HANDLE_OP(WASM_OP_THROW) + HANDLE_OP(WASM_OP_RETHROW) + HANDLE_OP(WASM_OP_DELEGATE) + HANDLE_OP(WASM_OP_CATCH_ALL) + HANDLE_OP(EXT_OP_TRY) + { + wasm_set_exception(module, "unsupported opcode"); + goto got_exception; + } +#endif + /* parametric instructions */ HANDLE_OP(WASM_OP_SELECT) { @@ -3031,7 +3049,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, data = NULL; } else { - seg_len = (uint64)module->module->data_segments[segment] ->data_length; @@ -3114,6 +3131,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, uint32 tbl_idx, elem_idx; uint32 n, s, d; WASMTableInstance *tbl_inst; + uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0; elem_idx = read_uint32(frame_ip); bh_assert(elem_idx < module->module->table_seg_count); @@ -3127,10 +3145,18 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, s = (uint32)POP_I32(); d = (uint32)POP_I32(); - if (offset_len_out_of_bounds( - s, n, + if (!bh_bitmap_get_bit(module->e->common.elem_dropped, + elem_idx)) { + /* table segment isn't dropped */ + tbl_seg_elems = module->module->table_segments[elem_idx] - .function_count) + .func_indexes; + tbl_seg_len = + module->module->table_segments[elem_idx] + .function_count; + } + + if (offset_len_out_of_bounds(s, n, tbl_seg_len) || offset_len_out_of_bounds(d, n, tbl_inst->cur_size)) { wasm_set_exception(module, @@ -3142,30 +3168,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, break; } - if (bh_bitmap_get_bit(module->e->common.elem_dropped, - elem_idx)) { - wasm_set_exception(module, - "out of bounds table access"); - goto got_exception; - } - - if (!wasm_elem_is_passive( - module->module->table_segments[elem_idx] - .mode)) { - wasm_set_exception(module, - "out of bounds table access"); - goto got_exception; - } - bh_memcpy_s( (uint8 *)tbl_inst + offsetof(WASMTableInstance, elems) + d * sizeof(uint32), (uint32)((tbl_inst->cur_size - d) * sizeof(uint32)), - module->module->table_segments[elem_idx] - .func_indexes - + s, - (uint32)(n * sizeof(uint32))); + tbl_seg_elems + s, (uint32)(n * sizeof(uint32))); break; } case WASM_OP_ELEM_DROP: @@ -3690,10 +3698,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, #endif #if WASM_ENABLE_LABELS_AS_VALUES != 0 - HANDLE_OP(WASM_OP_UNUSED_0x06) - HANDLE_OP(WASM_OP_UNUSED_0x07) - HANDLE_OP(WASM_OP_UNUSED_0x08) - HANDLE_OP(WASM_OP_UNUSED_0x09) HANDLE_OP(WASM_OP_UNUSED_0x0a) #if WASM_ENABLE_TAIL_CALL == 0 HANDLE_OP(WASM_OP_RETURN_CALL) @@ -3708,6 +3712,16 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_REF_NULL) HANDLE_OP(WASM_OP_REF_IS_NULL) HANDLE_OP(WASM_OP_REF_FUNC) +#endif +#if WASM_ENABLE_EXCE_HANDLING == 0 + /* if exception handling is disabled, these opcodes issue a trap */ + HANDLE_OP(WASM_OP_TRY) + HANDLE_OP(WASM_OP_CATCH) + HANDLE_OP(WASM_OP_THROW) + HANDLE_OP(WASM_OP_RETHROW) + HANDLE_OP(WASM_OP_DELEGATE) + HANDLE_OP(WASM_OP_CATCH_ALL) + HANDLE_OP(EXT_OP_TRY) #endif /* SELECT_T is converted to SELECT or SELECT_64 */ HANDLE_OP(WASM_OP_SELECT_T) @@ -3715,8 +3729,6 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, HANDLE_OP(WASM_OP_UNUSED_0x15) HANDLE_OP(WASM_OP_UNUSED_0x16) HANDLE_OP(WASM_OP_UNUSED_0x17) - HANDLE_OP(WASM_OP_UNUSED_0x18) - HANDLE_OP(WASM_OP_UNUSED_0x19) HANDLE_OP(WASM_OP_UNUSED_0x27) /* optimized op code */ HANDLE_OP(WASM_OP_F32_STORE) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index 1fc9805bd..8ca3796bc 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -327,7 +327,7 @@ check_utf8_str(const uint8 *str, uint32 len) return false; } } - else if (chr >= 0xE1 && chr <= 0xEF) { + else { /* chr >= 0xE1 && chr <= 0xEF */ if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF) { return false; } @@ -341,13 +341,13 @@ check_utf8_str(const uint8 *str, uint32 len) return false; } } - else if (chr >= 0xF1 && chr <= 0xF3) { + else if (chr <= 0xF3) { /* and also chr >= 0xF1 */ if (p[1] < 0x80 || p[1] > 0xBF || p[2] < 0x80 || p[2] > 0xBF || p[3] < 0x80 || p[3] > 0xBF) { return false; } } - else if (chr == 0xF4) { + else { /* chr == 0xF4 */ if (p[1] < 0x80 || p[1] > 0x8F || p[2] < 0x80 || p[2] > 0xBF || p[3] < 0x80 || p[3] > 0xBF) { return false; @@ -707,7 +707,6 @@ wasm_loader_find_export(const WASMModule *module, const char *module_name, WASMExport *export = loader_find_export((WASMModuleCommon *)module, module_name, field_name, export_kind, error_buf, error_buf_size); - ; return export; } #endif @@ -898,6 +897,58 @@ wasm_loader_resolve_global(const char *module_name, const char *global_name, return global; } +#if WASM_ENABLE_TAGS != 0 +static WASMTag * +wasm_loader_resolve_tag(const char *module_name, const char *tag_name, + const WASMType *expected_tag_type, + uint32 *linked_tag_index, char *error_buf, + uint32 error_buf_size) +{ + WASMModuleCommon *module_reg; + WASMTag *tag = NULL; + WASMExport *export = NULL; + WASMModule *module = NULL; + + module_reg = wasm_runtime_find_module_registered(module_name); + if (!module_reg || module_reg->module_type != Wasm_Module_Bytecode) { + LOG_DEBUG("can not find a module named %s for tag %s", module_name, + tag_name); + set_error_buf(error_buf, error_buf_size, "unknown import"); + return NULL; + } + + module = (WASMModule *)module_reg; + export = + wasm_loader_find_export(module, module_name, tag_name, EXPORT_KIND_TAG, + error_buf, error_buf_size); + if (!export) { + return NULL; + } + + /* resolve tag type and tag */ + if (export->index < module->import_tag_count) { + /* importing an imported tag from the submodule */ + tag = module->import_tags[export->index].u.tag.import_tag_linked; + } + else { + /* importing an section tag from the submodule */ + tag = module->tags[export->index - module->import_tag_count]; + } + + /* check function type */ + if (!wasm_type_equal(expected_tag_type, tag->tag_type)) { + LOG_DEBUG("%s.%s failed the type check", module_name, tag_name); + set_error_buf(error_buf, error_buf_size, "incompatible import type"); + return NULL; + } + + if (linked_tag_index != NULL) { + *linked_tag_index = export->index; + } + + return tag; +} +#endif #endif /* end of WASM_ENABLE_MULTI_MODULE */ static bool @@ -1237,6 +1288,89 @@ fail: return false; } +#if WASM_ENABLE_TAGS != 0 +static bool +load_tag_import(const uint8 **p_buf, const uint8 *buf_end, + const WASMModule *parent_module, /* this module ! */ + const char *sub_module_name, const char *tag_name, + WASMTagImport *tag, /* structure to fill */ + char *error_buf, uint32 error_buf_size) +{ + /* attribute and type of the import statement */ + uint8 declare_tag_attribute; + uint32 declare_type_index; + const uint8 *p = *p_buf, *p_end = buf_end; +#if WASM_ENABLE_MULTI_MODULE != 0 + WASMModule *sub_module = NULL; +#endif + + /* get the one byte attribute */ + CHECK_BUF(p, p_end, 1); + declare_tag_attribute = read_uint8(p); + if (declare_tag_attribute != 0) { + set_error_buf(error_buf, error_buf_size, "unknown tag attribute"); + goto fail; + } + + /* get type */ + read_leb_uint32(p, p_end, declare_type_index); + /* compare against module->types */ + if (declare_type_index >= parent_module->type_count) { + set_error_buf(error_buf, error_buf_size, "unknown tag type"); + goto fail; + } + + WASMType *declare_tag_type = parent_module->types[declare_type_index]; + + /* check, that the type of the declared tag returns void */ + if (declare_tag_type->result_count != 0) { + set_error_buf(error_buf, error_buf_size, + "tag type signature does not return void"); + + goto fail; + } + +#if WASM_ENABLE_MULTI_MODULE != 0 + if (!wasm_runtime_is_built_in_module(sub_module_name)) { + sub_module = (WASMModule *)wasm_runtime_load_depended_module( + (WASMModuleCommon *)parent_module, sub_module_name, error_buf, + error_buf_size); + if (!sub_module) { + return false; + } + /* wasm_loader_resolve_tag checks, that the imported tag + * and the declared tag have the same type + */ + uint32 linked_tag_index = 0; + WASMTag *linked_tag = wasm_loader_resolve_tag( + sub_module_name, tag_name, declare_tag_type, + &linked_tag_index /* out */, error_buf, error_buf_size); + if (linked_tag) { + tag->import_module = sub_module; + tag->import_tag_linked = linked_tag; + tag->import_tag_index_linked = linked_tag_index; + } + } +#endif + /* store to module tag declarations */ + tag->attribute = declare_tag_attribute; + tag->type = declare_type_index; + + tag->module_name = (char *)sub_module_name; + tag->field_name = (char *)tag_name; + tag->tag_type = declare_tag_type; + + *p_buf = p; + (void)parent_module; + + LOG_VERBOSE("Load tag import success\n"); + + return true; +fail: + return false; +} +#endif + static bool load_global_import(const uint8 **p_buf, const uint8 *buf_end, const WASMModule *parent_module, char *sub_module_name, @@ -1458,6 +1592,9 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, WASMImport *import; WASMImport *import_functions = NULL, *import_tables = NULL; WASMImport *import_memories = NULL, *import_globals = NULL; +#if WASM_ENABLE_TAGS != 0 + WASMImport *import_tags = NULL; +#endif char *sub_module_name, *field_name; uint8 u8, kind; @@ -1486,7 +1623,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, p += name_len; CHECK_BUF(p, p_end, 1); - /* 0x00/0x01/0x02/0x03 */ + /* 0x00/0x01/0x02/0x03/0x04 */ kind = read_uint8(p); switch (kind) { @@ -1527,6 +1664,16 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } break; +#if WASM_ENABLE_TAGS != 0 + case IMPORT_KIND_TAG: /* import tags */ + /* it only counts the number of tags to import */ + module->import_tag_count++; + CHECK_BUF(p, p_end, 1); + u8 = read_uint8(p); + read_leb_uint32(p, p_end, type_index); + break; +#endif + case IMPORT_KIND_GLOBAL: /* import global */ CHECK_BUF(p, p_end, 2); p += 2; @@ -1549,10 +1696,23 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, import_memories = module->import_memories = module->imports + module->import_function_count + module->import_table_count; + +#if WASM_ENABLE_TAGS != 0 + if (module->import_tag_count) + import_tags = module->import_tags = + module->imports + module->import_function_count + + module->import_table_count + module->import_memory_count; + if (module->import_global_count) + import_globals = module->import_globals = + module->imports + module->import_function_count + + module->import_table_count + module->import_memory_count + + module->import_tag_count; +#else if (module->import_global_count) import_globals = module->import_globals = module->imports + module->import_function_count + module->import_table_count + module->import_memory_count; +#endif p = p_old; @@ -1579,7 +1739,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, p += name_len; CHECK_BUF(p, p_end, 1); - /* 0x00/0x01/0x02/0x03 */ + /* 0x00/0x01/0x02/0x03/0x4 */ kind = read_uint8(p); switch (kind) { @@ -1615,6 +1775,18 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } break; +#if WASM_ENABLE_TAGS != 0 + case IMPORT_KIND_TAG: + bh_assert(import_tags); + import = import_tags++; + if (!load_tag_import(&p, p_end, module, sub_module_name, + field_name, &import->u.tag, error_buf, + error_buf_size)) { + return false; + } + break; +#endif + case IMPORT_KIND_GLOBAL: /* import global */ bh_assert(import_globals); import = import_globals++; @@ -2126,6 +2298,16 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } break; +#if WASM_ENABLE_TAGS != 0 + /* export tag */ + case EXPORT_KIND_TAG: + if (index >= module->tag_count + module->import_tag_count) { + set_error_buf(error_buf, error_buf_size, "unknown tag"); + return false; + } + break; +#endif + /* global index */ case EXPORT_KIND_GLOBAL: if (index @@ -2135,6 +2317,7 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } break; + default: set_error_buf(error_buf, error_buf_size, "invalid export kind"); @@ -2541,6 +2724,83 @@ fail: } #endif +#if WASM_ENABLE_TAGS != 0 +static bool +load_tag_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_code, + const uint8 *buf_code_end, WASMModule *module, char *error_buf, + uint32 error_buf_size) +{ + (void)buf_code; + (void)buf_code_end; + + const uint8 *p = buf, *p_end = buf_end; + size_t total_size = 0; + /* number of tags defined in the section */ + uint32 section_tag_count = 0; + uint8 tag_attribute; + uint32 tag_type; + WASMTag *tag = NULL; + + /* get tag count */ + read_leb_uint32(p, p_end, section_tag_count); + module->tag_count = section_tag_count; + + if (section_tag_count) { + total_size = sizeof(WASMTag *) * module->tag_count; + if (!(module->tags = + loader_malloc(total_size, error_buf, error_buf_size))) { + return false; + } + /* load each tag, imported tags precede the tags */ + uint32 tag_index; + for (tag_index = 0; tag_index < section_tag_count; tag_index++) { + + /* get the one byte attribute */ + CHECK_BUF(p, p_end, 1); + tag_attribute = read_uint8(p); + + /* get type */ + read_leb_uint32(p, p_end, tag_type); + /* compare against module->types */ + if (tag_type >= module->type_count) { + set_error_buf(error_buf, error_buf_size, "unknown type"); + return false; + } + + /* get return type (must be 0) */ + /* check, that the type of the referred tag returns void */ + WASMType *func_type = (WASMType *)module->types[tag_type]; + if (func_type->result_count != 0) { + set_error_buf(error_buf, error_buf_size, + "non-empty tag result type"); + + goto fail; + } + + if (!(tag = module->tags[tag_index] = loader_malloc( + sizeof(WASMTag), error_buf, error_buf_size))) { + return false; + } + + /* store to module tag declarations */ + tag->attribute = tag_attribute; + tag->type = tag_type; + tag->tag_type = func_type; + } + } + + if (p != p_end) { + set_error_buf(error_buf, error_buf_size, "section size mismatch"); + return false; + } + + LOG_VERBOSE("Load tag section success.\n"); + return true; +fail: + return false; +} +#endif + static bool load_code_section(const uint8 *buf, const uint8 *buf_end, const uint8 *buf_func, const uint8 *buf_func_end, WASMModule *module, @@ -3336,6 +3596,14 @@ load_from_sections(WASMModule *module, WASMSection *sections, error_buf_size)) return false; break; +#if WASM_ENABLE_TAGS != 0 + case SECTION_TYPE_TAG: + /* load tag declaration section */ + if (!load_tag_section(buf, buf_end, buf_code, buf_code_end, + module, error_buf, error_buf_size)) + return false; + break; +#endif case SECTION_TYPE_GLOBAL: if (!load_global_section(buf, buf_end, module, error_buf, error_buf_size)) @@ -3805,6 +4073,9 @@ static uint8 section_ids[] = { SECTION_TYPE_FUNC, SECTION_TYPE_TABLE, SECTION_TYPE_MEMORY, +#if WASM_ENABLE_TAGS != 0 + SECTION_TYPE_TAG, +#endif SECTION_TYPE_GLOBAL, SECTION_TYPE_EXPORT, SECTION_TYPE_START, @@ -4046,15 +4317,6 @@ check_wasi_abi_compatibility(const WASMModule *module, * according to the assumption, they should be all wasi compatiable */ - /* always can not have both at the same time */ - if (start && initialize) { - set_error_buf( - error_buf, error_buf_size, - "neither a command nor a reactor can both have _start function " - "and _initialize function at the same time"); - return false; - } - #if WASM_ENABLE_MULTI_MODULE != 0 /* filter out commands (with `_start`) cases */ if (start && !main_module) { @@ -4219,6 +4481,16 @@ wasm_loader_unload(WASMModule *module) if (module->memories) wasm_runtime_free(module->memories); +#if WASM_ENABLE_TAGS != 0 + if (module->tags) { + for (i = 0; i < module->tag_count; i++) { + if (module->tags[i]) + wasm_runtime_free(module->tags[i]); + } + wasm_runtime_free(module->tags); + } +#endif + if (module->globals) wasm_runtime_free(module->globals); @@ -4359,6 +4631,65 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, case WASM_OP_NOP: break; +#if WASM_ENABLE_EXCE_HANDLING != 0 + case WASM_OP_TRY: + u8 = read_uint8(p); + if (block_nested_depth + < sizeof(block_stack) / sizeof(BlockAddr)) { + block_stack[block_nested_depth].start_addr = p; + block_stack[block_nested_depth].else_addr = NULL; + } + block_nested_depth++; + break; + case EXT_OP_TRY: + skip_leb_uint32(p, p_end); + if (block_nested_depth + < sizeof(block_stack) / sizeof(BlockAddr)) { + block_stack[block_nested_depth].start_addr = p; + block_stack[block_nested_depth].else_addr = NULL; + } + block_nested_depth++; + break; + case WASM_OP_CATCH: + if (block_nested_depth == 1) { + *p_end_addr = (uint8 *)(p - 1); + /* stop search and return the address of the catch block */ + return true; + } + break; + case WASM_OP_CATCH_ALL: + if (block_nested_depth == 1) { + *p_end_addr = (uint8 *)(p - 1); + /* stop search and return the address of the catch_all block + */ + return true; + } + break; + case WASM_OP_THROW: + /* skip tag_index */ + skip_leb(p); + break; + case WASM_OP_RETHROW: + /* skip depth */ + skip_leb(p); + break; + case WASM_OP_DELEGATE: + if (block_nested_depth == 1) { + *p_end_addr = (uint8 *)(p - 1); + return true; + } + else { + skip_leb(p); + /* the DELEGATE opcode ends the tryblock, */ + block_nested_depth--; + if (block_nested_depth + < sizeof(block_stack) / sizeof(BlockAddr)) + block_stack[block_nested_depth].end_addr = + (uint8 *)(p - 1); + } + break; +#endif + case WASM_OP_BLOCK: case WASM_OP_LOOP: case WASM_OP_IF: @@ -4761,9 +5092,13 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) case WASM_OP_SIMD_PREFIX: { - /* TODO: shall we ceate a table to be friendly to branch - * prediction */ - opcode = read_uint8(p); + uint32 opcode1; + + read_leb_uint32(p, p_end, opcode1); + /* opcode1 was checked in wasm_loader_prepare_bytecode and + is no larger than UINT8_MAX */ + opcode = (uint8)opcode1; + /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h */ switch (opcode) { @@ -4853,8 +5188,14 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if WASM_ENABLE_SHARED_MEMORY != 0 case WASM_OP_ATOMIC_PREFIX: { - /* atomic_op (1 u8) + memarg (2 u32_leb) */ - opcode = read_uint8(p); + uint32 opcode1; + + /* atomic_op (u32_leb) + memarg (2 u32_leb) */ + read_leb_uint32(p, p_end, opcode1); + /* opcode1 was checked in wasm_loader_prepare_bytecode and + is no larger than UINT8_MAX */ + opcode = (uint8)opcode1; + if (opcode != WASM_OP_ATOMIC_FENCE) { skip_leb_uint32(p, p_end); /* align */ skip_leb_uint32(p, p_end); /* offset */ @@ -4949,9 +5290,8 @@ typedef struct BranchBlock { BranchBlockPatch *patch_list; /* This is used to save params frame_offset of of if block */ int16 *param_frame_offsets; - /* This is used to store available param num for if/else branch, so the else - * opcode can know how many parameters should be copied to the stack */ - uint32 available_param_num; + /* This is used to recover dynamic offset for else branch */ + uint16 start_dynamic_offset; #endif /* Indicate the operand stack is in polymorphic state. @@ -5230,6 +5570,10 @@ wasm_loader_ctx_init(WASMFunction *func, char *error_buf, uint32 error_buf_size) goto fail; loader_ctx->frame_csp_boundary = loader_ctx->frame_csp_bottom + 8; +#if WASM_ENABLE_EXCE_HANDLING != 0 + func->exception_handler_count = 0; +#endif + #if WASM_ENABLE_FAST_INTERP != 0 loader_ctx->frame_offset_size = sizeof(int16) * 32; if (!(loader_ctx->frame_offset_bottom = loader_ctx->frame_offset = @@ -6794,6 +7138,40 @@ fail: return NULL; } +#if WASM_ENABLE_EXCE_HANDLING != 0 +static BranchBlock * +check_branch_block_for_delegate(WASMLoaderContext *loader_ctx, uint8 **p_buf, + uint8 *buf_end, char *error_buf, + uint32 error_buf_size) +{ + uint8 *p = *p_buf, *p_end = buf_end; + BranchBlock *frame_csp_tmp; + uint32 depth; + + read_leb_uint32(p, p_end, depth); + /* + * Note: "delegate 0" means the surrounding block, not the + * try-delegate block itself. + * + * Note: the caller hasn't popped the try-delegate frame yet. + */ + bh_assert(loader_ctx->csp_num > 0); + if (loader_ctx->csp_num - 1 <= depth) { + set_error_buf(error_buf, error_buf_size, "unknown delegate label"); + goto fail; + } + frame_csp_tmp = loader_ctx->frame_csp - depth - 2; +#if WASM_ENABLE_FAST_INTERP != 0 + emit_br_info(frame_csp_tmp); +#endif + + *p_buf = p; + return frame_csp_tmp; +fail: + return NULL; +} +#endif + static bool check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, char *error_buf, uint32 error_buf_size) @@ -6841,11 +7219,26 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block, return true; } - /* Check stack cell num equals return cell num */ if (available_stack_cell != return_cell_num) { +#if WASM_ENABLE_EXCE_HANDLING != 0 + /* testspec: this error message format is expected by try_catch.wast */ + snprintf( + error_buf, error_buf_size, "type mismatch: %s requires [%s]%s[%s]", + block->label_type == LABEL_TYPE_TRY + || (block->label_type == LABEL_TYPE_CATCH + && return_cell_num > 0) + ? "instruction" + : "block", + return_cell_num > 0 ? type2str(return_types[0]) : "", + " but stack has ", + available_stack_cell > 0 ? type2str(*(loader_ctx->frame_ref - 1)) + : ""); + goto fail; +#else set_error_buf(error_buf, error_buf_size, "type mismatch: stack size does not match block type"); goto fail; +#endif } /* Check stack values match return types */ @@ -6869,18 +7262,15 @@ fail: * 1) POP original parameter out; * 2) Push and copy original values to dynamic space. * The copy instruction format: - * Part a: available param count + * Part a: param count * Part b: all param total cell num * Part c: each param's cell_num, src offset and dst offset * Part d: each param's src offset * Part e: each param's dst offset - * Note: if the stack is in polymorphic state, the actual copied parameters may - * be fewer than the defined number in block type */ static bool copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, - uint32 *p_available_param_count, char *error_buf, - uint32 error_buf_size) + char *error_buf, uint32 error_buf_size) { bool ret = false; int16 *frame_offset = NULL; @@ -6892,91 +7282,72 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, BlockType *block_type = &block->block_type; WASMType *wasm_type = block_type->u.type; uint32 param_count = block_type->u.type->param_count; - uint32 available_param_count = 0; int16 condition_offset = 0; bool disable_emit = false; int16 operand_offset = 0; - uint64 size; - if (is_if_block) - condition_offset = *loader_ctx->frame_offset; - - /* POP original parameter out */ - for (i = 0; i < param_count; i++) { - int32 available_stack_cell = - (int32)(loader_ctx->stack_cell_num - block->stack_cell_num); - - if (available_stack_cell <= 0 && block->is_stack_polymorphic) - break; - - POP_OFFSET_TYPE(wasm_type->types[param_count - i - 1]); - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); - } - available_param_count = i; - - size = - (uint64)available_param_count * (sizeof(*cells) + sizeof(*src_offsets)); + uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets)); + bh_assert(size > 0); /* For if block, we also need copy the condition operand offset. */ if (is_if_block) size += sizeof(*cells) + sizeof(*src_offsets); /* Allocate memory for the emit data */ - if ((size > 0) - && !(emit_data = loader_malloc(size, error_buf, error_buf_size))) + if (!(emit_data = loader_malloc(size, error_buf, error_buf_size))) return false; cells = emit_data; src_offsets = (int16 *)(cells + param_count); + if (is_if_block) + condition_offset = *loader_ctx->frame_offset; + + /* POP original parameter out */ + for (i = 0; i < param_count; i++) { + POP_OFFSET_TYPE(wasm_type->types[param_count - i - 1]); + wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); + } frame_offset = loader_ctx->frame_offset; /* Get each param's cell num and src offset */ - for (i = 0; i < available_param_count; i++) { + for (i = 0; i < param_count; i++) { cell = (uint8)wasm_value_type_cell_num(wasm_type->types[i]); cells[i] = cell; src_offsets[i] = *frame_offset; frame_offset += cell; } - /* emit copy instruction */ emit_label(EXT_OP_COPY_STACK_VALUES); /* Part a) */ - emit_uint32(loader_ctx, is_if_block ? available_param_count + 1 - : available_param_count); + emit_uint32(loader_ctx, is_if_block ? param_count + 1 : param_count); /* Part b) */ emit_uint32(loader_ctx, is_if_block ? wasm_type->param_cell_num + 1 : wasm_type->param_cell_num); /* Part c) */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) emit_byte(loader_ctx, cells[i]); if (is_if_block) emit_byte(loader_ctx, 1); /* Part d) */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) emit_operand(loader_ctx, src_offsets[i]); if (is_if_block) emit_operand(loader_ctx, condition_offset); /* Part e) */ /* Push to dynamic space. The push will emit the dst offset. */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) PUSH_OFFSET_TYPE(wasm_type->types[i]); if (is_if_block) PUSH_OFFSET_TYPE(VALUE_TYPE_I32); - if (p_available_param_count) { - *p_available_param_count = available_param_count; - } - ret = true; fail: /* Free the emit data */ - if (emit_data) { - wasm_runtime_free(emit_data); - } + wasm_runtime_free(emit_data); return ret; } @@ -7194,6 +7565,24 @@ re_scan: } case WASM_OP_BLOCK: case WASM_OP_LOOP: +#if WASM_ENABLE_EXCE_HANDLING != 0 + case WASM_OP_TRY: + if (opcode == WASM_OP_TRY) { + /* + * keep track of exception handlers to account for + * memory allocation + */ + func->exception_handler_count++; + + /* + * try is a block + * do nothing special, but execution continues to + * to handle_op_block_and_loop, + * and that be pushes the csp + */ + } + +#endif #if WASM_ENABLE_FAST_INTERP != 0 PRESERVE_LOCAL_FOR_BLOCK(); #endif @@ -7248,6 +7637,7 @@ re_scan: BranchBlock *cur_block = loader_ctx->frame_csp - 1; #if WASM_ENABLE_FAST_INTERP != 0 + uint32 cell_num; available_params = block_type.u.type->param_count; #endif for (i = 0; i < block_type.u.type->param_count; i++) { @@ -7265,21 +7655,41 @@ re_scan: POP_TYPE( wasm_type->types[wasm_type->param_count - i - 1]); +#if WASM_ENABLE_FAST_INTERP != 0 + /* decrease the frame_offset pointer accordingly to keep + * consistent with frame_ref stack */ + cell_num = wasm_value_type_cell_num( + wasm_type->types[wasm_type->param_count - i - 1]); + loader_ctx->frame_offset -= cell_num; +#endif } } - PUSH_CSP(LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK), block_type, p); /* Pass parameters to block */ if (BLOCK_HAS_PARAM(block_type)) { for (i = 0; i < block_type.u.type->param_count; i++) { - PUSH_TYPE(block_type.u.type->types[i]); #if WASM_ENABLE_FAST_INTERP != 0 + uint32 cell_num = wasm_value_type_cell_num( + block_type.u.type->types[i]); if (i >= available_params) { - PUSH_OFFSET_TYPE(block_type.u.type->types[i]); + /* If there isn't enough data on stack, push a dummy + * offset to keep the stack consistent with + * frame_ref. + * Since the stack is already in polymorphic state, + * the opcode will not be executed, so the dummy + * offset won't cause any error */ + *loader_ctx->frame_offset++ = 0; + if (cell_num > 1) { + *loader_ctx->frame_offset++ = 0; + } + } + else { + loader_ctx->frame_offset += cell_num; } #endif + PUSH_TYPE(block_type.u.type->types[i]); } } @@ -7289,9 +7699,8 @@ re_scan: if (BLOCK_HAS_PARAM(block_type)) { /* Make sure params are in dynamic space */ - if (!copy_params_to_dynamic_space(loader_ctx, false, - NULL, error_buf, - error_buf_size)) + if (!copy_params_to_dynamic_space( + loader_ctx, false, error_buf, error_buf_size)) goto fail; } @@ -7300,6 +7709,11 @@ re_scan: loader_ctx->p_code_compiled; } } +#if WASM_ENABLE_EXCE_HANDLING != 0 + else if (opcode == WASM_OP_TRY) { + skip_label(); + } +#endif else if (opcode == WASM_OP_IF) { BranchBlock *block = loader_ctx->frame_csp - 1; /* If block has parameters, we should make sure they are in @@ -7319,17 +7733,21 @@ re_scan: * recover them before entering else branch. * */ - if (if_condition_available && BLOCK_HAS_PARAM(block_type)) { + if (BLOCK_HAS_PARAM(block_type)) { uint64 size; - /* skip the if condition operand offset */ - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); + /* In polymorphic state, there may be no if condition on + * the stack, so the offset may not emitted */ + if (if_condition_available) { + /* skip the if condition operand offset */ + wasm_loader_emit_backspace(loader_ctx, + sizeof(int16)); + } /* skip the if label */ skip_label(); /* Emit a copy instruction */ if (!copy_params_to_dynamic_space( - loader_ctx, true, &block->available_param_num, - error_buf, error_buf_size)) + loader_ctx, true, error_buf, error_buf_size)) goto fail; /* Emit the if instruction */ @@ -7350,9 +7768,8 @@ re_scan: - size / sizeof(int16), (uint32)size); } - else { - block->available_param_num = 0; - } + + block->start_dynamic_offset = loader_ctx->dynamic_offset; emit_empty_label_addr_and_frame_ip(PATCH_ELSE); emit_empty_label_addr_and_frame_ip(PATCH_END); @@ -7360,7 +7777,206 @@ re_scan: #endif break; } +#if WASM_ENABLE_EXCE_HANDLING != 0 + case WASM_OP_THROW: + { + SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true); + BranchBlock *cur_block = loader_ctx->frame_csp - 1; + + uint8 label_type = cur_block->label_type; + uint32 tag_index = 0; + read_leb_int32(p, p_end, tag_index); + + /* check validity of tag_index against module->tag_count */ + /* check tag index is within the tag index space */ + if (tag_index >= module->import_tag_count + module->tag_count) { + snprintf(error_buf, error_buf_size, "unknown tag %d", + tag_index); + goto fail; + } + + /* the tag_type is stored in either the WASMTag (section tags) + * or WASMTagImport (import tag) */ + WASMType *tag_type = NULL; + if (tag_index < module->import_tag_count) { + tag_type = module->import_tags[tag_index].u.tag.tag_type; + } + else { + tag_type = + module->tags[tag_index - module->import_tag_count] + ->tag_type; + } + + if (tag_type->result_count != 0) { + set_error_buf(error_buf, error_buf_size, + "tag type signature does not return void"); + goto fail; + } + + int32 available_stack_cell = + (int32)(loader_ctx->stack_cell_num + - cur_block->stack_cell_num); + + /* Check stack values match return types by comparing tag param + * types with stack cells */ + uint8 *frame_ref = loader_ctx->frame_ref; + for (int tti = (int32)tag_type->param_count - 1; tti >= 0; + tti--) { + if (!check_stack_top_values(frame_ref, available_stack_cell, + tag_type->types[tti], error_buf, + error_buf_size)) { + snprintf(error_buf, error_buf_size, + "type mismatch: instruction requires [%s] but " + "stack has [%s]", + tag_type->param_count > 0 + ? type2str(tag_type->types[tti]) + : "", + available_stack_cell > 0 + ? type2str(*(loader_ctx->frame_ref - 1)) + : ""); + goto fail; + } + frame_ref -= wasm_value_type_cell_num(tag_type->types[tti]); + available_stack_cell -= + wasm_value_type_cell_num(tag_type->types[tti]); + } + + /* throw is stack polymorphic */ + (void)label_type; + RESET_STACK(); + + break; + } + case WASM_OP_RETHROW: + { + /* must be done before checking branch block */ + SET_CUR_BLOCK_STACK_POLYMORPHIC_STATE(true); + + /* check the target catching block: LABEL_TYPE_CATCH */ + if (!(frame_csp_tmp = check_branch_block( + loader_ctx, &p, p_end, error_buf, error_buf_size))) + goto fail; + + if (frame_csp_tmp->label_type != LABEL_TYPE_CATCH + && frame_csp_tmp->label_type != LABEL_TYPE_CATCH_ALL) { + /* trap according to spectest (rethrow.wast) */ + set_error_buf(error_buf, error_buf_size, + "invalid rethrow label"); + goto fail; + } + + BranchBlock *cur_block = loader_ctx->frame_csp - 1; + uint8 label_type = cur_block->label_type; + (void)label_type; + /* rethrow is stack polymorphic */ + RESET_STACK(); + break; + } + case WASM_OP_DELEGATE: + { + /* check target block is valid */ + if (!(frame_csp_tmp = check_branch_block_for_delegate( + loader_ctx, &p, p_end, error_buf, error_buf_size))) + goto fail; + + BranchBlock *cur_block = loader_ctx->frame_csp - 1; + uint8 label_type = cur_block->label_type; + + (void)label_type; + /* DELEGATE ends the block */ + POP_CSP(); + break; + } + case WASM_OP_CATCH: + { + BranchBlock *cur_block = loader_ctx->frame_csp - 1; + + uint8 label_type = cur_block->label_type; + uint32 tag_index = 0; + read_leb_int32(p, p_end, tag_index); + + /* check validity of tag_index against module->tag_count */ + /* check tag index is within the tag index space */ + if (tag_index >= module->import_tag_count + module->tag_count) { + LOG_VERBOSE("In %s, unknown tag at WASM_OP_CATCH\n", + __FUNCTION__); + set_error_buf(error_buf, error_buf_size, "unknown tag"); + goto fail; + } + + /* the tag_type is stored in either the WASMTag (section tags) + * or WASMTagImport (import tag) */ + WASMType *func_type = NULL; + if (tag_index < module->import_tag_count) { + func_type = module->import_tags[tag_index].u.tag.tag_type; + } + else { + func_type = + module->tags[tag_index - module->import_tag_count] + ->tag_type; + } + + if (func_type->result_count != 0) { + set_error_buf(error_buf, error_buf_size, + "tag type signature does not return void"); + goto fail; + } + + /* check validity of current label (expect LABEL_TYPE_TRY or + * LABEL_TYPE_CATCH) */ + if ((LABEL_TYPE_CATCH != label_type) + && (LABEL_TYPE_TRY != label_type)) { + set_error_buf(error_buf, error_buf_size, + "Unexpected block sequence encountered."); + goto fail; + } + + BlockType new_block_type; + new_block_type.is_value_type = false; + new_block_type.u.type = func_type; + + /* + * replace frame_csp by LABEL_TYPE_CATCH + */ + cur_block->label_type = LABEL_TYPE_CATCH; + + /* RESET_STACK removes the values pushed in TRY or pervious + * CATCH Blocks */ + RESET_STACK(); + + /* push types on the stack according to catched type */ + if (BLOCK_HAS_PARAM(new_block_type)) { + for (i = 0; i < new_block_type.u.type->param_count; i++) + PUSH_TYPE(new_block_type.u.type->types[i]); + } + break; + } + case WASM_OP_CATCH_ALL: + { + BranchBlock *cur_block = loader_ctx->frame_csp - 1; + + /* expecting a TRY or CATCH, anything else will be considered an + * error */ + if ((LABEL_TYPE_CATCH != cur_block->label_type) + && (LABEL_TYPE_TRY != cur_block->label_type)) { + set_error_buf(error_buf, error_buf_size, + "Unexpected block sequence encountered."); + goto fail; + } + + /* no immediates */ + /* replace frame_csp by LABEL_TYPE_CATCH_ALL */ + cur_block->label_type = LABEL_TYPE_CATCH_ALL; + + /* RESET_STACK removes the values pushed in TRY or pervious + * CATCH Blocks */ + RESET_STACK(); + + /* catch_all has no tagtype and therefore no parameters */ + break; + } +#endif case WASM_OP_ELSE: { BranchBlock *block = NULL; @@ -7403,12 +8019,13 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 /* Recover top param_count values of frame_offset stack */ - if (block->available_param_num) { + if (BLOCK_HAS_PARAM((block_type))) { uint32 size; - size = sizeof(int16) * block->available_param_num; + size = sizeof(int16) * block_type.u.type->param_cell_num; bh_memcpy_s(loader_ctx->frame_offset, size, block->param_frame_offsets, size); loader_ctx->frame_offset += (size / sizeof(int16)); + loader_ctx->dynamic_offset = block->start_dynamic_offset; } #endif @@ -7637,11 +8254,11 @@ re_scan: idx--) { ret_type = *(func->func_type->types + func->func_type->param_count + idx); - POP_TYPE(ret_type); #if WASM_ENABLE_FAST_INTERP != 0 /* emit the offset after return opcode */ POP_OFFSET_TYPE(ret_type); #endif + POP_TYPE(ret_type); } RESET_STACK(); @@ -7681,10 +8298,10 @@ re_scan: if (func_type->param_count > 0) { for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { - POP_TYPE(func_type->types[idx]); #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(func_type->types[idx]); #endif + POP_TYPE(func_type->types[idx]); } } @@ -7782,10 +8399,10 @@ re_scan: if (func_type->param_count > 0) { for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { - POP_TYPE(func_type->types[idx]); #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(func_type->types[idx]); #endif + POP_TYPE(func_type->types[idx]); } } @@ -9229,8 +9846,8 @@ re_scan: { uint32 opcode1; - CHECK_BUF(p, p_end, 1); - opcode1 = read_uint8(p); + read_leb_uint32(p, p_end, opcode1); + /* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h */ switch (opcode1) { @@ -9891,8 +10508,8 @@ re_scan: { uint32 opcode1; - CHECK_BUF(p, p_end, 1); - opcode1 = read_uint8(p); + read_leb_uint32(p, p_end, opcode1); + #if WASM_ENABLE_FAST_INTERP != 0 emit_byte(loader_ctx, opcode1); #endif diff --git a/core/iwasm/interpreter/wasm_mini_loader.c b/core/iwasm/interpreter/wasm_mini_loader.c index b6d81aa2f..ba2c37fc7 100644 --- a/core/iwasm/interpreter/wasm_mini_loader.c +++ b/core/iwasm/interpreter/wasm_mini_loader.c @@ -3259,6 +3259,17 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, u8 = read_uint8(p); /* 0x00 */ break; +#if WASM_ENABLE_EXCE_HANDLING != 0 + case WASM_OP_TRY: + case WASM_OP_CATCH: + case WASM_OP_THROW: + case WASM_OP_RETHROW: + case WASM_OP_DELEGATE: + case WASM_OP_CATCH_ALL: + /* TODO */ + return false; +#endif + case WASM_OP_DROP: case WASM_OP_SELECT: case WASM_OP_DROP_64: @@ -3481,8 +3492,11 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, uint32 opcode1; read_leb_uint32(p, p_end, opcode1); + /* opcode1 was checked in wasm_loader_prepare_bytecode and + is no larger than UINT8_MAX */ + opcode = (uint8)opcode1; - switch (opcode1) { + switch (opcode) { case WASM_OP_I32_TRUNC_SAT_S_F32: case WASM_OP_I32_TRUNC_SAT_U_F32: case WASM_OP_I32_TRUNC_SAT_S_F64: @@ -3538,8 +3552,14 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache, #if WASM_ENABLE_SHARED_MEMORY != 0 case WASM_OP_ATOMIC_PREFIX: { - /* atomic_op (1 u8) + memarg (2 u32_leb) */ - opcode = read_uint8(p); + uint32 opcode1; + + /* atomic_op (u32_leb) + memarg (2 u32_leb) */ + read_leb_uint32(p, p_end, opcode1); + /* opcode1 was checked in wasm_loader_prepare_bytecode and + is no larger than UINT8_MAX */ + opcode = (uint8)opcode1; + if (opcode != WASM_OP_ATOMIC_FENCE) { skip_leb_uint32(p, p_end); /* align */ skip_leb_uint32(p, p_end); /* offset */ @@ -3603,6 +3623,8 @@ typedef struct BranchBlock { /* This is used to store available param num for if/else branch, so the else * opcode can know how many parameters should be copied to the stack */ uint32 available_param_num; + /* This is used to recover dynamic offset for else branch */ + uint16 start_dynamic_offset; #endif /* Indicate the operand stack is in polymorphic state. @@ -5352,18 +5374,15 @@ fail: * 1) POP original parameter out; * 2) Push and copy original values to dynamic space. * The copy instruction format: - * Part a: available param count + * Part a: param count * Part b: all param total cell num * Part c: each param's cell_num, src offset and dst offset * Part d: each param's src offset * Part e: each param's dst offset - * Note: if the stack is in polymorphic state, the actual copied parameters may - * be fewer than the defined number in block type */ static bool copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, - uint32 *p_available_param_count, char *error_buf, - uint32 error_buf_size) + char *error_buf, uint32 error_buf_size) { bool ret = false; int16 *frame_offset = NULL; @@ -5375,91 +5394,72 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block, BlockType *block_type = &block->block_type; WASMType *wasm_type = block_type->u.type; uint32 param_count = block_type->u.type->param_count; - uint32 available_param_count = 0; int16 condition_offset = 0; bool disable_emit = false; int16 operand_offset = 0; - uint64 size; - if (is_if_block) - condition_offset = *loader_ctx->frame_offset; - - /* POP original parameter out */ - for (i = 0; i < param_count; i++) { - int32 available_stack_cell = - (int32)(loader_ctx->stack_cell_num - block->stack_cell_num); - - if (available_stack_cell <= 0 && block->is_stack_polymorphic) - break; - - POP_OFFSET_TYPE(wasm_type->types[param_count - i - 1]); - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); - } - available_param_count = i; - - size = - (uint64)available_param_count * (sizeof(*cells) + sizeof(*src_offsets)); + uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets)); + bh_assert(size > 0); /* For if block, we also need copy the condition operand offset. */ if (is_if_block) size += sizeof(*cells) + sizeof(*src_offsets); /* Allocate memory for the emit data */ - if ((size > 0) - && !(emit_data = loader_malloc(size, error_buf, error_buf_size))) + if (!(emit_data = loader_malloc(size, error_buf, error_buf_size))) return false; cells = emit_data; src_offsets = (int16 *)(cells + param_count); + if (is_if_block) + condition_offset = *loader_ctx->frame_offset; + + /* POP original parameter out */ + for (i = 0; i < param_count; i++) { + POP_OFFSET_TYPE(wasm_type->types[param_count - i - 1]); + wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); + } frame_offset = loader_ctx->frame_offset; /* Get each param's cell num and src offset */ - for (i = 0; i < available_param_count; i++) { + for (i = 0; i < param_count; i++) { cell = (uint8)wasm_value_type_cell_num(wasm_type->types[i]); cells[i] = cell; src_offsets[i] = *frame_offset; frame_offset += cell; } - /* emit copy instruction */ emit_label(EXT_OP_COPY_STACK_VALUES); /* Part a) */ - emit_uint32(loader_ctx, is_if_block ? available_param_count + 1 - : available_param_count); + emit_uint32(loader_ctx, is_if_block ? param_count + 1 : param_count); /* Part b) */ emit_uint32(loader_ctx, is_if_block ? wasm_type->param_cell_num + 1 : wasm_type->param_cell_num); /* Part c) */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) emit_byte(loader_ctx, cells[i]); if (is_if_block) emit_byte(loader_ctx, 1); /* Part d) */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) emit_operand(loader_ctx, src_offsets[i]); if (is_if_block) emit_operand(loader_ctx, condition_offset); /* Part e) */ /* Push to dynamic space. The push will emit the dst offset. */ - for (i = 0; i < available_param_count; i++) + for (i = 0; i < param_count; i++) PUSH_OFFSET_TYPE(wasm_type->types[i]); if (is_if_block) PUSH_OFFSET_TYPE(VALUE_TYPE_I32); - if (p_available_param_count) { - *p_available_param_count = available_param_count; - } - ret = true; fail: /* Free the emit data */ - if (emit_data) { - wasm_runtime_free(emit_data); - } + wasm_runtime_free(emit_data); return ret; } @@ -5661,6 +5661,7 @@ re_scan: BranchBlock *cur_block = loader_ctx->frame_csp - 1; #if WASM_ENABLE_FAST_INTERP != 0 + uint32 cell_num; available_params = block_type.u.type->param_count; #endif for (i = 0; i < block_type.u.type->param_count; i++) { @@ -5678,6 +5679,13 @@ re_scan: POP_TYPE( wasm_type->types[wasm_type->param_count - i - 1]); +#if WASM_ENABLE_FAST_INTERP != 0 + /* decrease the frame_offset pointer accordingly to keep + * consistent with frame_ref stack */ + cell_num = wasm_value_type_cell_num( + wasm_type->types[wasm_type->param_count - i - 1]); + loader_ctx->frame_offset -= cell_num; +#endif } } @@ -5687,12 +5695,26 @@ re_scan: /* Pass parameters to block */ if (BLOCK_HAS_PARAM(block_type)) { for (i = 0; i < block_type.u.type->param_count; i++) { - PUSH_TYPE(block_type.u.type->types[i]); #if WASM_ENABLE_FAST_INTERP != 0 + uint32 cell_num = wasm_value_type_cell_num( + block_type.u.type->types[i]); if (i >= available_params) { - PUSH_OFFSET_TYPE(block_type.u.type->types[i]); + /* If there isn't enough data on stack, push a dummy + * offset to keep the stack consistent with + * frame_ref. + * Since the stack is already in polymorphic state, + * the opcode will not be executed, so the dummy + * offset won't cause any error */ + *loader_ctx->frame_offset++ = 0; + if (cell_num > 1) { + *loader_ctx->frame_offset++ = 0; + } + } + else { + loader_ctx->frame_offset += cell_num; } #endif + PUSH_TYPE(block_type.u.type->types[i]); } } @@ -5701,9 +5723,8 @@ re_scan: skip_label(); if (BLOCK_HAS_PARAM(block_type)) { /* Make sure params are in dynamic space */ - if (!copy_params_to_dynamic_space(loader_ctx, false, - NULL, error_buf, - error_buf_size)) + if (!copy_params_to_dynamic_space( + loader_ctx, false, error_buf, error_buf_size)) goto fail; } if (opcode == WASM_OP_LOOP) { @@ -5730,17 +5751,21 @@ re_scan: * recover them before entering else branch. * */ - if (if_condition_available && BLOCK_HAS_PARAM(block_type)) { + if (BLOCK_HAS_PARAM(block_type)) { uint64 size; - /* skip the if condition operand offset */ - wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); + /* In polymorphic state, there may be no if condition on + * the stack, so the offset may not emitted */ + if (if_condition_available) { + /* skip the if condition operand offset */ + wasm_loader_emit_backspace(loader_ctx, + sizeof(int16)); + } /* skip the if label */ skip_label(); /* Emit a copy instruction */ if (!copy_params_to_dynamic_space( - loader_ctx, true, &block->available_param_num, - error_buf, error_buf_size)) + loader_ctx, true, error_buf, error_buf_size)) goto fail; /* Emit the if instruction */ @@ -5761,9 +5786,8 @@ re_scan: - size / sizeof(int16), (uint32)size); } - else { - block->available_param_num = 0; - } + + block->start_dynamic_offset = loader_ctx->dynamic_offset; emit_empty_label_addr_and_frame_ip(PATCH_ELSE); emit_empty_label_addr_and_frame_ip(PATCH_END); @@ -5807,12 +5831,13 @@ re_scan: #if WASM_ENABLE_FAST_INTERP != 0 /* Recover top param_count values of frame_offset stack */ - if (block->available_param_num) { + if (BLOCK_HAS_PARAM((block_type))) { uint32 size; - size = sizeof(int16) * block->available_param_num; + size = sizeof(int16) * block_type.u.type->param_cell_num; bh_memcpy_s(loader_ctx->frame_offset, size, block->param_frame_offsets, size); loader_ctx->frame_offset += (size / sizeof(int16)); + loader_ctx->dynamic_offset = block->start_dynamic_offset; } #endif @@ -5999,11 +6024,11 @@ re_scan: idx--) { ret_type = *(func->func_type->types + func->func_type->param_count + idx); - POP_TYPE(ret_type); #if WASM_ENABLE_FAST_INTERP != 0 /* emit the offset after return opcode */ POP_OFFSET_TYPE(ret_type); #endif + POP_TYPE(ret_type); } RESET_STACK(); @@ -6042,10 +6067,10 @@ re_scan: if (func_type->param_count > 0) { for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { - POP_TYPE(func_type->types[idx]); #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(func_type->types[idx]); #endif + POP_TYPE(func_type->types[idx]); } } @@ -6123,10 +6148,10 @@ re_scan: if (func_type->param_count > 0) { for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) { - POP_TYPE(func_type->types[idx]); #if WASM_ENABLE_FAST_INTERP != 0 POP_OFFSET_TYPE(func_type->types[idx]); #endif + POP_TYPE(func_type->types[idx]); } } @@ -6164,6 +6189,18 @@ re_scan: break; } +#if WASM_ENABLE_EXCE_HANDLING != 0 + case WASM_OP_TRY: + case WASM_OP_CATCH: + case WASM_OP_THROW: + case WASM_OP_RETHROW: + case WASM_OP_DELEGATE: + case WASM_OP_CATCH_ALL: + /* TODO */ + set_error_buf(error_buf, error_buf_size, "unsupported opcode"); + goto fail; +#endif + case WASM_OP_DROP: { BranchBlock *cur_block = loader_ctx->frame_csp - 1; @@ -7436,11 +7473,14 @@ re_scan: #if WASM_ENABLE_SHARED_MEMORY != 0 case WASM_OP_ATOMIC_PREFIX: { - opcode = read_uint8(p); + uint32 opcode1; + + read_leb_uint32(p, p_end, opcode1); + #if WASM_ENABLE_FAST_INTERP != 0 - emit_byte(loader_ctx, opcode); + emit_byte(loader_ctx, opcode1); #endif - if (opcode != WASM_OP_ATOMIC_FENCE) { + if (opcode1 != WASM_OP_ATOMIC_FENCE) { CHECK_MEMORY(); read_leb_uint32(p, p_end, align); /* align */ read_leb_uint32(p, p_end, mem_offset); /* offset */ @@ -7451,7 +7491,7 @@ re_scan: #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 func->has_memory_operations = true; #endif - switch (opcode) { + switch (opcode1) { case WASM_OP_ATOMIC_NOTIFY: POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32); break; diff --git a/core/iwasm/interpreter/wasm_opcode.h b/core/iwasm/interpreter/wasm_opcode.h index ce5e358a2..4f8a6a695 100644 --- a/core/iwasm/interpreter/wasm_opcode.h +++ b/core/iwasm/interpreter/wasm_opcode.h @@ -20,11 +20,10 @@ typedef enum WASMOpcode { WASM_OP_LOOP = 0x03, /* loop */ WASM_OP_IF = 0x04, /* if */ WASM_OP_ELSE = 0x05, /* else */ - - WASM_OP_UNUSED_0x06 = 0x06, - WASM_OP_UNUSED_0x07 = 0x07, - WASM_OP_UNUSED_0x08 = 0x08, - WASM_OP_UNUSED_0x09 = 0x09, + WASM_OP_TRY = 0x06, /* try */ + WASM_OP_CATCH = 0x07, /* catch* */ + WASM_OP_THROW = 0x08, /* throw of a try catch */ + WASM_OP_RETHROW = 0x09, /* rethrow of a try catch */ WASM_OP_UNUSED_0x0a = 0x0a, WASM_OP_END = 0x0b, /* end */ @@ -41,8 +40,9 @@ typedef enum WASMOpcode { WASM_OP_UNUSED_0x15 = 0x15, WASM_OP_UNUSED_0x16 = 0x16, WASM_OP_UNUSED_0x17 = 0x17, - WASM_OP_UNUSED_0x18 = 0x18, - WASM_OP_UNUSED_0x19 = 0x19, + + WASM_OP_DELEGATE = 0x18, /* delegate block of the try catch*/ + WASM_OP_CATCH_ALL = 0x19, /* a catch_all handler in a try block */ /* parametric instructions */ WASM_OP_DROP = 0x1a, /* drop */ @@ -268,8 +268,10 @@ typedef enum WASMOpcode { EXT_OP_IF = 0xd5, /* if with blocktype */ EXT_OP_BR_TABLE_CACHE = 0xd6, /* br_table from cache */ + EXT_OP_TRY = 0xd7, /* try block with blocktype */ + #if WASM_ENABLE_DEBUG_INTERP != 0 - DEBUG_OP_BREAK = 0xd7, /* debug break point */ + DEBUG_OP_BREAK = 0xd8, /* debug break point */ #endif /* Post-MVP extend op prefix */ @@ -683,6 +685,13 @@ typedef enum WASMAtomicEXTOpcode { #define SET_GOTO_TABLE_ELEM(opcode) [opcode] = HANDLE_OPCODE(opcode) +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_SIMD != 0 +#define SET_GOTO_TABLE_SIMD_PREFIX_ELEM() \ + SET_GOTO_TABLE_ELEM(WASM_OP_SIMD_PREFIX), +#else +#define SET_GOTO_TABLE_SIMD_PREFIX_ELEM() +#endif + /* * Macro used to generate computed goto tables for the C interpreter. */ @@ -696,10 +705,10 @@ typedef enum WASMAtomicEXTOpcode { HANDLE_OPCODE(WASM_OP_LOOP), /* 0x03 */ \ HANDLE_OPCODE(WASM_OP_IF), /* 0x04 */ \ HANDLE_OPCODE(WASM_OP_ELSE), /* 0x05 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x06), /* 0x06 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x07), /* 0x07 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x08), /* 0x08 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x09), /* 0x09 */ \ + HANDLE_OPCODE(WASM_OP_TRY), /* 0x06 */ \ + HANDLE_OPCODE(WASM_OP_CATCH), /* 0x07 */ \ + HANDLE_OPCODE(WASM_OP_THROW), /* 0x08 */ \ + HANDLE_OPCODE(WASM_OP_RETHROW), /* 0x09 */ \ HANDLE_OPCODE(WASM_OP_UNUSED_0x0a), /* 0x0a */ \ HANDLE_OPCODE(WASM_OP_END), /* 0x0b */ \ HANDLE_OPCODE(WASM_OP_BR), /* 0x0c */ \ @@ -714,8 +723,8 @@ typedef enum WASMAtomicEXTOpcode { HANDLE_OPCODE(WASM_OP_UNUSED_0x15), /* 0x15 */ \ HANDLE_OPCODE(WASM_OP_UNUSED_0x16), /* 0x16 */ \ HANDLE_OPCODE(WASM_OP_UNUSED_0x17), /* 0x17 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x18), /* 0x18 */ \ - HANDLE_OPCODE(WASM_OP_UNUSED_0x19), /* 0x19 */ \ + HANDLE_OPCODE(WASM_OP_DELEGATE), /* 0x18 */ \ + HANDLE_OPCODE(WASM_OP_CATCH_ALL), /* 0x19 */ \ HANDLE_OPCODE(WASM_OP_DROP), /* 0x1a */ \ HANDLE_OPCODE(WASM_OP_SELECT), /* 0x1b */ \ HANDLE_OPCODE(WASM_OP_SELECT_T), /* 0x1c */ \ @@ -905,7 +914,9 @@ typedef enum WASMAtomicEXTOpcode { HANDLE_OPCODE(EXT_OP_LOOP), /* 0xd4 */ \ HANDLE_OPCODE(EXT_OP_IF), /* 0xd5 */ \ HANDLE_OPCODE(EXT_OP_BR_TABLE_CACHE), /* 0xd6 */ \ + HANDLE_OPCODE(EXT_OP_TRY), /* 0xd7 */ \ SET_GOTO_TABLE_ELEM(WASM_OP_MISC_PREFIX), /* 0xfc */ \ + SET_GOTO_TABLE_SIMD_PREFIX_ELEM() /* 0xfd */ \ SET_GOTO_TABLE_ELEM(WASM_OP_ATOMIC_PREFIX), /* 0xfe */ \ DEF_DEBUG_BREAK_HANDLE() \ }; diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 7cda841e5..a3a544cac 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -141,17 +141,7 @@ memories_deinstantiate(WASMModuleInstance *module_inst, memories[i]->heap_handle = NULL; } if (memories[i]->memory_data) { -#ifndef OS_ENABLE_HW_BOUND_CHECK - wasm_runtime_free(memories[i]->memory_data); -#else -#ifdef BH_PLATFORM_WINDOWS - os_mem_decommit(memories[i]->memory_data, - memories[i]->num_bytes_per_page - * memories[i]->cur_page_count); -#endif - os_munmap((uint8 *)memories[i]->memory_data, - 8 * (uint64)BH_GB); -#endif + wasm_deallocate_linear_memory(memories[i]); } } } @@ -173,14 +163,10 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, uint32 inc_page_count, aux_heap_base, global_idx; uint32 bytes_of_last_page, bytes_to_page_end; uint8 *global_addr; -#ifdef OS_ENABLE_HW_BOUND_CHECK - uint8 *mapped_mem; - uint64 map_size = 8 * (uint64)BH_GB; - uint64 page_size = os_getpagesize(); -#endif + bool is_shared_memory = false; #if WASM_ENABLE_SHARED_MEMORY != 0 - bool is_shared_memory = flags & 0x02 ? true : false; + is_shared_memory = flags & 0x02 ? true : false; /* shared memory */ if (is_shared_memory && parent != NULL) { @@ -189,6 +175,10 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, shared_memory_inc_reference(memory); return memory; } +#else + (void)parent; + (void)memory_idx; + (void)flags; #endif /* end of WASM_ENABLE_SHARED_MEMORY */ if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1 @@ -288,72 +278,21 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, num_bytes_per_page, init_page_count, max_page_count); LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size); - 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; bh_assert(memory != NULL); -#ifndef OS_ENABLE_HW_BOUND_CHECK -#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 -#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: - * ea = i + memarg.offset - * both i and memarg.offset are u32 in range 0 to 4G - * so the range of ea is 0 to 8G - */ - if (!(memory->memory_data = mapped_mem = - os_mmap(NULL, map_size, MMAP_PROT_NONE, MMAP_MAP_NONE, - os_get_invalid_handle()))) { - set_error_buf(error_buf, error_buf_size, "mmap memory failed"); - goto fail1; + if (wasm_allocate_linear_memory(&memory->memory_data, is_shared_memory, + num_bytes_per_page, init_page_count, + max_page_count, &memory_data_size) + != BHT_OK) { + set_error_buf(error_buf, error_buf_size, + "allocate linear memory failed"); + return NULL; } -#ifdef BH_PLATFORM_WINDOWS - if (memory_data_size > 0 - && !os_mem_commit(mapped_mem, 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); - goto fail1; - } -#endif - - if (os_mprotect(mapped_mem, memory_data_size, - MMAP_PROT_READ | MMAP_PROT_WRITE) - != 0) { - set_error_buf(error_buf, error_buf_size, "mprotect memory failed"); - goto fail2; - } - - /* Newly allocated pages are filled with zero by the OS, we don't fill it - * again here */ - - if (memory_data_size > UINT32_MAX) - memory_data_size = UINT32_MAX; -#endif /* end of OS_ENABLE_HW_BOUND_CHECK */ - memory->module_type = Wasm_Module_Bytecode; memory->num_bytes_per_page = num_bytes_per_page; memory->cur_page_count = init_page_count; @@ -370,13 +309,13 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, if (!(memory->heap_handle = runtime_malloc( (uint64)heap_struct_size, error_buf, error_buf_size))) { - goto fail2; + goto fail1; } if (!mem_allocator_create_with_struct_and_pool( memory->heap_handle, heap_struct_size, memory->heap_data, heap_size)) { set_error_buf(error_buf, error_buf_size, "init app heap failed"); - goto fail3; + goto fail2; } } @@ -394,20 +333,13 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent, LOG_VERBOSE("Memory instantiate success."); return memory; -fail3: +fail2: if (heap_size > 0) wasm_runtime_free(memory->heap_handle); -fail2: -#ifndef OS_ENABLE_HW_BOUND_CHECK - if (memory->memory_data) - wasm_runtime_free(memory->memory_data); -#else -#ifdef BH_PLATFORM_WINDOWS - os_mem_decommit(mapped_mem, memory_data_size); -#endif - os_munmap(mapped_mem, map_size); -#endif fail1: + if (memory->memory_data) + wasm_deallocate_linear_memory(memory); + return NULL; } @@ -639,7 +571,7 @@ fail: * Destroy function instances. */ static void -functions_deinstantiate(WASMFunctionInstance *functions, uint32 count) +functions_deinstantiate(WASMFunctionInstance *functions) { if (functions) { wasm_runtime_free(functions); @@ -738,6 +670,101 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, return functions; } +#if WASM_ENABLE_TAGS != 0 +/** + * Destroy tags instances. + */ +static void +tags_deinstantiate(WASMTagInstance *tags, void **import_tag_ptrs) +{ + if (tags) { + wasm_runtime_free(tags); + } + if (import_tag_ptrs) { + wasm_runtime_free(import_tag_ptrs); + } +} + +/** + * Instantiate tags in a module. + */ +static WASMTagInstance * +tags_instantiate(const WASMModule *module, WASMModuleInstance *module_inst, + char *error_buf, uint32 error_buf_size) +{ + WASMImport *import; + uint32 i, tag_count = module->import_tag_count + module->tag_count; + uint64 total_size = sizeof(WASMTagInstance) * (uint64)tag_count; + WASMTagInstance *tags, *tag; + + if (!(tags = runtime_malloc(total_size, error_buf, error_buf_size))) { + return NULL; + } + + total_size = sizeof(void *) * (uint64)module->import_tag_count; + if (total_size > 0 + && !(module_inst->e->import_tag_ptrs = + runtime_malloc(total_size, error_buf, error_buf_size))) { + wasm_runtime_free(tags); + return NULL; + } + + /* instantiate tags from import section */ + tag = tags; + import = module->import_tags; + for (i = 0; i < module->import_tag_count; i++, import++) { + tag->is_import_tag = true; + tag->u.tag_import = &import->u.tag; + tag->type = import->u.tag.type; + tag->attribute = import->u.tag.attribute; +#if WASM_ENABLE_MULTI_MODULE != 0 + if (import->u.tag.import_module) { + if (!(tag->import_module_inst = get_sub_module_inst( + module_inst, import->u.tag.import_module))) { + set_error_buf(error_buf, error_buf_size, "unknown tag"); + goto fail; + } + + if (!(tag->import_tag_inst = + wasm_lookup_tag(tag->import_module_inst, + import->u.tag.field_name, NULL))) { + set_error_buf(error_buf, error_buf_size, "unknown tag"); + goto fail; + } + + /* Copy the imported tag to current instance */ + module_inst->e->import_tag_ptrs[i] = + tag->u.tag_import->import_tag_linked; + } +#endif + tag++; + } + + /* instantiate tags from tag section */ + for (i = 0; i < module->tag_count; i++) { + tag->is_import_tag = false; + tag->type = module->tags[i]->type; + tag->u.tag = module->tags[i]; + +#if WASM_ENABLE_FAST_INTERP != 0 + /* tag->const_cell_num = function->u.func->const_cell_num; */ +#endif + tag++; + } + bh_assert((uint32)(tag - tags) == tag_count); + + return tags; + +#if WASM_ENABLE_MULTI_MODULE != 0 +fail: + tags_deinstantiate(tags, module_inst->e->import_tag_ptrs); + /* clean up */ + module_inst->e->import_tag_ptrs = NULL; + return NULL; +#endif +} +#endif + /** * Destroy global instances. */ @@ -937,6 +964,52 @@ export_functions_instantiate(const WASMModule *module, return export_funcs; } +#if WASM_ENABLE_TAGS != 0 +/** + * Destroy export function instances. + */ +static void +export_tags_deinstantiate(WASMExportTagInstance *tags) +{ + if (tags) + wasm_runtime_free(tags); +} + +/** + * Instantiate export functions in a module. + */ +static WASMExportTagInstance * +export_tags_instantiate(const WASMModule *module, + WASMModuleInstance *module_inst, + uint32 export_tag_count, char *error_buf, + uint32 error_buf_size) +{ + WASMExportTagInstance *export_tags, *export_tag; + WASMExport *export = module->exports; + uint32 i; + uint64 total_size = + sizeof(WASMExportTagInstance) * (uint64)export_tag_count; + + if (!(export_tag = export_tags = + runtime_malloc(total_size, error_buf, error_buf_size))) { + return NULL; + } + + for (i = 0; i < module->export_count; i++, export ++) + if (export->kind == EXPORT_KIND_TAG) { + export_tag->name = export->name; + + bh_assert(module_inst->e->tags); + + export_tag->tag = &module_inst->e->tags[export->index]; + export_tag++; + } + + bh_assert((uint32)(export_tag - export_tags) == export_tag_count); + return export_tags; +} +#endif + #if WASM_ENABLE_MULTI_MODULE != 0 static void export_globals_deinstantiate(WASMExportGlobInstance *globals) @@ -1426,6 +1499,7 @@ set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode, #if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ && WASM_ENABLE_LAZY_JIT != 0) /* No possible multi-tier JIT */ + (void)first_time_set; module_inst->e->running_mode = running_mode; if (running_mode == Mode_Interp) { @@ -1676,6 +1750,10 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, "failed to allocate bitmaps"); goto fail; } + for (i = 0; i < module->data_seg_count; i++) { + if (!module->data_segments[i]->is_passive) + bh_bitmap_set_bit(module_inst->e->common.data_dropped, i); + } } #endif #if WASM_ENABLE_REF_TYPES != 0 @@ -1688,6 +1766,10 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, "failed to allocate bitmaps"); goto fail; } + for (i = 0; i < module->table_seg_count; i++) { + if (wasm_elem_is_active(module->table_segments[i].mode)) + bh_bitmap_set_bit(module_inst->e->common.elem_dropped, i); + } } #endif @@ -1718,6 +1800,9 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, module_inst->table_count = module->import_table_count + module->table_count; module_inst->e->function_count = module->import_function_count + module->function_count; +#if WASM_ENABLE_TAGS != 0 + module_inst->e->tag_count = module->import_tag_count + module->tag_count; +#endif /* export */ module_inst->export_func_count = get_export_count(module, EXPORT_KIND_FUNC); @@ -1726,11 +1811,15 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, get_export_count(module, EXPORT_KIND_TABLE); module_inst->export_memory_count = get_export_count(module, EXPORT_KIND_MEMORY); +#if WASM_ENABLE_TAGS != 0 + module_inst->e->export_tag_count = + get_export_count(module, EXPORT_KIND_TAG); +#endif module_inst->export_global_count = get_export_count(module, EXPORT_KIND_GLOBAL); #endif - /* Instantiate memories/tables/functions */ + /* Instantiate memories/tables/functions/tags */ if ((module_inst->memory_count > 0 && !(module_inst->memories = memories_instantiate(module, module_inst, parent, heap_size, @@ -1746,6 +1835,15 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, && !(module_inst->export_functions = export_functions_instantiate( module, module_inst, module_inst->export_func_count, error_buf, error_buf_size))) +#if WASM_ENABLE_TAGS != 0 + || (module_inst->e->tag_count > 0 + && !(module_inst->e->tags = tags_instantiate( + module, module_inst, error_buf, error_buf_size))) + || (module_inst->e->export_tag_count > 0 + && !(module_inst->e->export_tags = export_tags_instantiate( + module, module_inst, module_inst->e->export_tag_count, + error_buf, error_buf_size))) +#endif #if WASM_ENABLE_MULTI_MODULE != 0 || (module_inst->export_global_count > 0 && !(module_inst->export_globals = export_globals_instantiate( @@ -1763,7 +1861,6 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, ) { goto fail; } - if (global_count > 0) { /* Initialize the global data */ global_data = module_inst->global_data; @@ -2184,10 +2281,16 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst) } tables_deinstantiate(module_inst); - functions_deinstantiate(module_inst->e->functions, - module_inst->e->function_count); + functions_deinstantiate(module_inst->e->functions); +#if WASM_ENABLE_TAGS != 0 + tags_deinstantiate(module_inst->e->tags, module_inst->e->import_tag_ptrs); +#endif globals_deinstantiate(module_inst->e->globals); export_functions_deinstantiate(module_inst->export_functions); +#if WASM_ENABLE_TAGS != 0 + export_tags_deinstantiate(module_inst->e->export_tags); +#endif + #if WASM_ENABLE_MULTI_MODULE != 0 export_globals_deinstantiate(module_inst->export_globals); #endif @@ -2268,6 +2371,21 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name) (void)module_inst->export_tables; return module_inst->tables[0]; } + +#if WASM_ENABLE_TAGS != 0 +WASMTagInstance * +wasm_lookup_tag(const WASMModuleInstance *module_inst, const char *name, + const char *signature) +{ + uint32 i; + for (i = 0; i < module_inst->e->export_tag_count; i++) + if (!strcmp(module_inst->e->export_tags[i].name, name)) + return module_inst->e->export_tags[i].tag; + (void)signature; + return NULL; +} +#endif + #endif #ifdef OS_ENABLE_HW_BOUND_CHECK @@ -2398,53 +2516,103 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, return !wasm_copy_exception(module_inst, NULL); } -#if WASM_ENABLE_PERF_PROFILING != 0 -void -wasm_dump_perf_profiling(const WASMModuleInstance *module_inst) +#if WASM_ENABLE_PERF_PROFILING != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0 +/* look for the function name */ +static char * +get_func_name_from_index(const WASMModuleInstance *inst, uint32 func_index) { - WASMExportFuncInstance *export_func; - WASMFunctionInstance *func_inst; - char *func_name; - uint32 i, j; + char *func_name = NULL; + WASMFunctionInstance *func_inst = inst->e->functions + func_index; - os_printf("Performance profiler data:\n"); - for (i = 0; i < module_inst->e->function_count; i++) { - func_inst = module_inst->e->functions + i; - if (func_inst->is_import_func) { - func_name = func_inst->u.func_import->field_name; - } + if (func_inst->is_import_func) { + func_name = func_inst->u.func_import->field_name; + } + else { #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 - else if (func_inst->u.func->field_name) { - func_name = func_inst->u.func->field_name; - } + func_name = func_inst->u.func->field_name; #endif - else { - func_name = NULL; - for (j = 0; j < module_inst->export_func_count; j++) { - export_func = module_inst->export_functions + j; + /* if custom name section is not generated, + search symbols from export table */ + if (!func_name) { + unsigned j; + for (j = 0; j < inst->export_func_count; j++) { + WASMExportFuncInstance *export_func = + inst->export_functions + j; if (export_func->function == func_inst) { func_name = export_func->name; break; } } } + } + return func_name; +} +#endif /*WASM_ENABLE_PERF_PROFILING != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0*/ + +#if WASM_ENABLE_PERF_PROFILING != 0 +void +wasm_dump_perf_profiling(const WASMModuleInstance *module_inst) +{ + WASMFunctionInstance *func_inst; + char *func_name; + uint32 i; + + os_printf("Performance profiler data:\n"); + for (i = 0; i < module_inst->e->function_count; i++) { + func_inst = module_inst->e->functions + i; + + if (func_inst->total_exec_cnt == 0) + continue; + + func_name = get_func_name_from_index(module_inst, i); if (func_name) os_printf( " func %s, execution time: %.3f ms, execution count: %" PRIu32 - " times\n", - func_name, - module_inst->e->functions[i].total_exec_time / 1000.0f, - module_inst->e->functions[i].total_exec_cnt); + " times, children execution time: %.3f ms\n", + func_name, func_inst->total_exec_time / 1000.0f, + func_inst->total_exec_cnt, + func_inst->children_exec_time / 1000.0f); else os_printf(" func %" PRIu32 ", execution time: %.3f ms, execution count: %" PRIu32 - " times\n", - i, module_inst->e->functions[i].total_exec_time / 1000.0f, - module_inst->e->functions[i].total_exec_cnt); + " times, children execution time: %.3f ms\n", + i, func_inst->total_exec_time / 1000.0f, + func_inst->total_exec_cnt, + func_inst->children_exec_time / 1000.0f); } } -#endif + +double +wasm_summarize_wasm_execute_time(const WASMModuleInstance *inst) +{ + double ret = 0; + + unsigned i; + for (i = 0; i < inst->e->function_count; i++) { + WASMFunctionInstance *func = inst->e->functions + i; + ret += (func->total_exec_time - func->children_exec_time) / 1000.0f; + } + + return ret; +} + +double +wasm_get_wasm_func_exec_time(const WASMModuleInstance *inst, + const char *func_name) +{ + unsigned i; + for (i = 0; i < inst->e->function_count; i++) { + char *name_in_wasm = get_func_name_from_index(inst, i); + if (name_in_wasm && strcmp(name_in_wasm, func_name) == 0) { + WASMFunctionInstance *func = inst->e->functions + i; + return (func->total_exec_time - func->children_exec_time) / 1000.0f; + } + } + + return -1.0; +} +#endif /*WASM_ENABLE_PERF_PROFILING != 0*/ uint32 wasm_module_malloc_internal(WASMModuleInstance *module_inst, @@ -2939,29 +3107,7 @@ wasm_interp_create_call_stack(struct WASMExecEnv *exec_env) frame.func_offset = (uint32)(cur_frame->ip - func_code_base); } - /* look for the function name */ - if (func_inst->is_import_func) { - func_name = func_inst->u.func_import->field_name; - } - else { -#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 - func_name = func_inst->u.func->field_name; -#endif - /* if custom name section is not generated, - search symbols from export table */ - if (!func_name) { - uint32 i; - for (i = 0; i < module_inst->export_func_count; i++) { - WASMExportFuncInstance *export_func = - module_inst->export_functions + i; - if (export_func->function == func_inst) { - func_name = export_func->name; - break; - } - } - } - } - + func_name = get_func_name_from_index(module_inst, frame.func_index); frame.func_name_wp = func_name; if (!bh_vector_append(module_inst->frames, &frame)) { @@ -3256,6 +3402,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx, { WASMTableInstance *tbl_inst; WASMTableSeg *tbl_seg; + uint32 *tbl_seg_elems = NULL, tbl_seg_len = 0; bh_assert(module_inst->module_type == Wasm_Module_Bytecode); @@ -3265,7 +3412,13 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx, bh_assert(tbl_inst); bh_assert(tbl_seg); - if (offset_len_out_of_bounds(src_offset, length, tbl_seg->function_count) + if (!bh_bitmap_get_bit(module_inst->e->common.elem_dropped, tbl_seg_idx)) { + /* table segment isn't dropped */ + tbl_seg_elems = tbl_seg->func_indexes; + tbl_seg_len = tbl_seg->function_count; + } + + if (offset_len_out_of_bounds(src_offset, length, tbl_seg_len) || offset_len_out_of_bounds(dst_offset, length, tbl_inst->cur_size)) { jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); return; @@ -3275,21 +3428,10 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx, return; } - if (bh_bitmap_get_bit(module_inst->e->common.elem_dropped, tbl_seg_idx)) { - jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); - return; - } - - if (!wasm_elem_is_passive(tbl_seg->mode)) { - jit_set_exception_with_id(module_inst, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS); - return; - } - bh_memcpy_s((uint8 *)tbl_inst + offsetof(WASMTableInstance, elems) + dst_offset * sizeof(uint32), (uint32)sizeof(uint32) * (tbl_inst->cur_size - dst_offset), - tbl_seg->func_indexes + src_offset, - (uint32)(length * sizeof(uint32))); + tbl_seg_elems + src_offset, (uint32)(length * sizeof(uint32))); } void @@ -3408,7 +3550,7 @@ llvm_jit_alloc_frame(WASMExecEnv *exec_env, uint32 func_index) frame->ip = NULL; frame->sp = frame->lp; #if WASM_ENABLE_PERF_PROFILING != 0 - frame->time_started = os_time_get_boot_microsecond(); + frame->time_started = os_time_thread_cputime_us(); #endif frame->prev_frame = wasm_exec_env_get_cur_frame(exec_env); wasm_exec_env_set_cur_frame(exec_env, frame); @@ -3429,9 +3571,13 @@ llvm_jit_free_frame(WASMExecEnv *exec_env) #if WASM_ENABLE_PERF_PROFILING != 0 if (frame->function) { - frame->function->total_exec_time += - os_time_get_boot_microsecond() - frame->time_started; + uint64 elapsed = os_time_thread_cputime_us() - frame->time_started; + frame->function->total_exec_time += elapsed; frame->function->total_exec_cnt++; + + /* parent function */ + if (prev_frame) + prev_frame->function->children_exec_time += elapsed; } #endif wasm_exec_env_free_wasm_frame(exec_env, frame); diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h index 89b92b658..b1224863e 100644 --- a/core/iwasm/interpreter/wasm_runtime.h +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -28,6 +28,9 @@ typedef struct WASMFunctionInstance WASMFunctionInstance; typedef struct WASMMemoryInstance WASMMemoryInstance; typedef struct WASMTableInstance WASMTableInstance; typedef struct WASMGlobalInstance WASMGlobalInstance; +#if WASM_ENABLE_TAGS != 0 +typedef struct WASMTagInstance WASMTagInstance; +#endif /** * When LLVM JIT, WAMR compiler or AOT is enabled, we should ensure that @@ -186,9 +189,35 @@ struct WASMFunctionInstance { uint64 total_exec_time; /* total execution count */ uint32 total_exec_cnt; + /* children execution time */ + uint64 children_exec_time; #endif }; +#if WASM_ENABLE_TAGS != 0 +struct WASMTagInstance { + bool is_import_tag; + /* tag attribute */ + uint8 attribute; + /* tag type index */ + uint32 type; + union { + WASMTagImport *tag_import; + WASMTag *tag; + } u; + +#if WASM_ENABLE_MULTI_MODULE != 0 + WASMModuleInstance *import_module_inst; + WASMTagInstance *import_tag_inst; +#endif +}; +#endif + +#if WASM_ENABLE_EXCE_HANDLING != 0 +#define INVALID_TAGINDEX ((uint32)0xFFFFFFFF) +#define SET_INVALID_TAGINDEX(tag) (tag = INVALID_TAGINDEX) +#define IS_INVALID_TAGINDEX(tag) ((tag & INVALID_TAGINDEX) == INVALID_TAGINDEX) +#endif typedef struct WASMExportFuncInstance { char *name; WASMFunctionInstance *function; @@ -209,6 +238,13 @@ typedef struct WASMExportMemInstance { WASMMemoryInstance *memory; } WASMExportMemInstance; +#if WASM_ENABLE_TAGS != 0 +typedef struct WASMExportTagInstance { + char *name; + WASMTagInstance *tag; +} WASMExportTagInstance; +#endif + /* wasm-c-api import function info */ typedef struct CApiFuncImport { /* host func pointer after linked */ @@ -261,6 +297,14 @@ typedef struct WASMModuleInstanceExtra { WASMTableInstance **table_insts_linked; #endif +#if WASM_ENABLE_TAGS != 0 + uint32 tag_count; + uint32 export_tag_count; + WASMTagInstance *tags; + WASMExportTagInstance *export_tags; + void **import_tag_ptrs; +#endif + #if WASM_ENABLE_MEMORY_PROFILING != 0 uint32 max_aux_stack_used; #endif @@ -432,6 +476,13 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent, void wasm_dump_perf_profiling(const WASMModuleInstance *module_inst); +double +wasm_summarize_wasm_execute_time(const WASMModuleInstance *inst); + +double +wasm_get_wasm_func_exec_time(const WASMModuleInstance *inst, + const char *func_name); + void wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst); @@ -452,6 +503,13 @@ wasm_lookup_memory(const WASMModuleInstance *module_inst, const char *name); WASMTableInstance * wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name); + +#if WASM_ENABLE_TAGS != 0 +WASMTagInstance * +wasm_lookup_tag(const WASMModuleInstance *module_inst, const char *name, + const char *signature); +#endif + #endif bool diff --git a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c index 1c593f3cb..bc5bea55a 100644 --- a/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c +++ b/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c @@ -468,7 +468,7 @@ get_thread_info(wasm_exec_env_t exec_env, uint32 handle) WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); ClusterInfoNode *info = get_cluster_info(cluster); - if (!info) { + if (!info || !handle) { return NULL; } @@ -1145,6 +1145,10 @@ sem_open_wrapper(wasm_exec_env_t exec_env, const char *name, int32 oflags, * For Unix like system, it's dedicated for multiple processes. */ + if (!name) { /* avoid passing NULL to bh_hash_map_find and os_sem_open */ + return -1; + } + if ((info_node = bh_hash_map_find(sem_info_map, (void *)name))) { return info_node->handle; } @@ -1277,7 +1281,13 @@ sem_unlink_wrapper(wasm_exec_env_t exec_env, const char *name) (void)exec_env; int32 ret_val; - ThreadInfoNode *info_node = bh_hash_map_find(sem_info_map, (void *)name); + ThreadInfoNode *info_node; + + if (!name) { /* avoid passing NULL to bh_hash_map_find */ + return -1; + } + + info_node = bh_hash_map_find(sem_info_map, (void *)name); if (!info_node || info_node->type != T_SEM) return -1; diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index 55916deb4..8e6a65a4a 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c @@ -473,12 +473,16 @@ snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size, static int puts_wrapper(wasm_exec_env_t exec_env, const char *str) { + (void)exec_env; + return os_printf("%s\n", str); } static int putchar_wrapper(wasm_exec_env_t exec_env, int c) { + (void)exec_env; + os_printf("%c", c); return 1; } @@ -585,6 +589,8 @@ strchr_wrapper(wasm_exec_env_t exec_env, const char *s, int32 c) static int32 strcmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2) { + (void)exec_env; + /* s1 and s2 have been checked by runtime */ return strcmp(s1, s2); } @@ -641,6 +647,8 @@ strncpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src, static uint32 strlen_wrapper(wasm_exec_env_t exec_env, const char *s) { + (void)exec_env; + /* s has been checked by runtime */ return (uint32)strlen(s); } @@ -693,6 +701,7 @@ free_wrapper(wasm_exec_env_t exec_env, void *ptr) static int32 atoi_wrapper(wasm_exec_env_t exec_env, const char *s) { + (void)exec_env; /* s has been checked by runtime */ return atoi(s); } @@ -757,6 +766,8 @@ static int32 strncasecmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2, uint32 n) { + (void)exec_env; + /* s1 and s2 have been checked by runtime */ return strncasecmp(s1, s2, n); } @@ -764,6 +775,8 @@ strncasecmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2, static uint32 strspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *accept) { + (void)exec_env; + /* s and accept have been checked by runtime */ return (uint32)strspn(s, accept); } @@ -771,6 +784,8 @@ strspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *accept) static uint32 strcspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *reject) { + (void)exec_env; + /* s and reject have been checked by runtime */ return (uint32)strcspn(s, reject); } @@ -787,60 +802,80 @@ strstr_wrapper(wasm_exec_env_t exec_env, const char *s, const char *find) static int32 isupper_wrapper(wasm_exec_env_t exec_env, int32 c) { + (void)exec_env; + return isupper(c); } static int32 isalpha_wrapper(wasm_exec_env_t exec_env, int32 c) { + (void)exec_env; + return isalpha(c); } static int32 isspace_wrapper(wasm_exec_env_t exec_env, int32 c) { + (void)exec_env; + return isspace(c); } static int32 isgraph_wrapper(wasm_exec_env_t exec_env, int32 c) { + (void)exec_env; + return isgraph(c); } static int32 isprint_wrapper(wasm_exec_env_t exec_env, int32 c) { + (void)exec_env; + return isprint(c); } static int32 isdigit_wrapper(wasm_exec_env_t exec_env, int32 c) { + (void)exec_env; + return isdigit(c); } static int32 isxdigit_wrapper(wasm_exec_env_t exec_env, int32 c) { + (void)exec_env; + return isxdigit(c); } static int32 tolower_wrapper(wasm_exec_env_t exec_env, int32 c) { + (void)exec_env; + return tolower(c); } static int32 toupper_wrapper(wasm_exec_env_t exec_env, int32 c) { + (void)exec_env; + return toupper(c); } static int32 isalnum_wrapper(wasm_exec_env_t exec_env, int32 c) { + (void)exec_env; + return isalnum(c); } @@ -899,7 +934,10 @@ __cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, uint32 thrown_size) static void __cxa_begin_catch_wrapper(wasm_exec_env_t exec_env, void *exception_object) -{} +{ + (void)exec_env; + (void)exception_object; +} static void __cxa_throw_wrapper(wasm_exec_env_t exec_env, void *thrown_exception, @@ -908,6 +946,10 @@ __cxa_throw_wrapper(wasm_exec_env_t exec_env, void *thrown_exception, wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; + (void)thrown_exception; + (void)tinfo; + (void)table_elem_idx; + snprintf(buf, sizeof(buf), "%s", "exception thrown by stdc++"); wasm_runtime_set_exception(module_inst, buf); } @@ -924,10 +966,12 @@ clock_gettime_wrapper(wasm_exec_env_t exec_env, uint32 clk_id, wasm_module_inst_t module_inst = get_module_inst(exec_env); uint64 time; + (void)clk_id; + if (!validate_native_addr(ts_app, sizeof(struct timespec_app))) return (uint32)-1; - time = os_time_get_boot_microsecond(); + time = os_time_get_boot_us(); ts_app->tv_sec = time / 1000000; ts_app->tv_nsec = (time % 1000000) * 1000; @@ -937,9 +981,11 @@ clock_gettime_wrapper(wasm_exec_env_t exec_env, uint32 clk_id, static uint64 clock_wrapper(wasm_exec_env_t exec_env) { + (void)exec_env; + /* Convert to nano seconds as CLOCKS_PER_SEC in wasi-sdk */ - return os_time_get_boot_microsecond() * 1000; + return os_time_get_boot_us() * 1000; } #if WASM_ENABLE_SPEC_TEST != 0 diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index d2545f7bd..0b69de6b9 100644 --- a/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -72,7 +72,7 @@ min_uint32(uint32_t a, uint32_t b) } static inline struct fd_table * -wasi_ctx_get_curfds(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) +wasi_ctx_get_curfds(wasi_ctx_t wasi_ctx) { if (!wasi_ctx) return NULL; @@ -88,7 +88,7 @@ wasi_ctx_get_argv_environ(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) } static inline struct fd_prestats * -wasi_ctx_get_prestats(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) +wasi_ctx_get_prestats(wasi_ctx_t wasi_ctx) { if (!wasi_ctx) return NULL; @@ -96,7 +96,7 @@ wasi_ctx_get_prestats(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) } static inline struct addr_pool * -wasi_ctx_get_addr_pool(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx) +wasi_ctx_get_addr_pool(wasi_ctx_t wasi_ctx) { if (!wasi_ctx) return NULL; @@ -292,7 +292,7 @@ wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + struct fd_prestats *prestats = wasi_ctx_get_prestats(wasi_ctx); wasi_prestat_t prestat; wasi_errno_t err; @@ -317,7 +317,7 @@ wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, wasi_fd_t fd, char *path, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + struct fd_prestats *prestats = wasi_ctx_get_prestats(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -330,8 +330,8 @@ wasi_fd_close(wasm_exec_env_t exec_env, wasi_fd_t fd) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); + struct fd_prestats *prestats = wasi_ctx_get_prestats(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -344,7 +344,7 @@ wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -358,7 +358,7 @@ wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); wasi_iovec_t *iovec, *iovec_begin; uint64 total_size; size_t nread; @@ -412,7 +412,7 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); wasi_ciovec_t *ciovec, *ciovec_begin; uint64 total_size; size_t nwritten; @@ -465,7 +465,7 @@ wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); wasi_iovec_t *iovec, *iovec_begin; uint64 total_size; size_t nread; @@ -517,8 +517,8 @@ wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); + struct fd_prestats *prestats = wasi_ctx_get_prestats(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -532,7 +532,7 @@ wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -549,7 +549,7 @@ wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -566,7 +566,7 @@ wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); wasi_fdstat_t fdstat; wasi_errno_t err; @@ -590,7 +590,7 @@ wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -605,7 +605,7 @@ wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -619,7 +619,7 @@ wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -634,7 +634,7 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); wasi_ciovec_t *ciovec, *ciovec_begin; uint64 total_size; size_t nwritten; @@ -687,7 +687,7 @@ wasi_fd_advise(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -701,7 +701,7 @@ wasi_fd_allocate(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -715,7 +715,7 @@ wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -732,8 +732,8 @@ wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); + struct fd_prestats *prestats = wasi_ctx_get_prestats(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -752,7 +752,7 @@ wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); wasi_fd_t fd = (wasi_fd_t)-1; /* set fd_app -1 if path open failed */ wasi_errno_t err; @@ -776,7 +776,7 @@ wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); size_t bufused; wasi_errno_t err; @@ -802,7 +802,7 @@ wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); size_t bufused; wasi_errno_t err; @@ -828,7 +828,7 @@ wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -844,7 +844,7 @@ wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -862,7 +862,7 @@ wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -877,7 +877,7 @@ wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -892,7 +892,7 @@ wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -912,7 +912,7 @@ wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -929,8 +929,8 @@ wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); + struct fd_prestats *prestats = wasi_ctx_get_prestats(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -945,7 +945,7 @@ wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -959,7 +959,7 @@ wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return (wasi_errno_t)-1; @@ -1076,7 +1076,7 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in, { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); size_t nevents = 0; wasi_errno_t err; @@ -1128,6 +1128,8 @@ wasi_proc_raise(wasm_exec_env_t exec_env, wasi_signal_t sig) static wasi_errno_t wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len) { + (void)exec_env; + return wasmtime_ssp_random_get(buf, buf_len); } @@ -1142,7 +1144,7 @@ wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fdflags_t flags, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasi_ssp_sock_accept(exec_env, curfds, fd, flags, fd_new); } @@ -1161,7 +1163,7 @@ wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(addr, sizeof(__wasi_addr_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasi_ssp_sock_addr_local(exec_env, curfds, fd, addr); } @@ -1180,7 +1182,7 @@ wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(addr, sizeof(__wasi_addr_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasi_ssp_sock_addr_remote(exec_env, curfds, fd, addr); } @@ -1200,7 +1202,7 @@ wasi_sock_addr_resolve(wasm_exec_env_t exec_env, const char *host, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); ns_lookup_list = wasi_ctx_get_ns_lookup_list(wasi_ctx); return wasi_ssp_sock_addr_resolve(exec_env, curfds, ns_lookup_list, host, @@ -1219,8 +1221,8 @@ wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr) if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); + addr_pool = wasi_ctx_get_addr_pool(wasi_ctx); return wasi_ssp_sock_bind(exec_env, curfds, addr_pool, fd, addr); } @@ -1228,6 +1230,9 @@ wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr) static wasi_errno_t wasi_sock_close(wasm_exec_env_t exec_env, wasi_fd_t fd) { + (void)exec_env; + (void)fd; + return __WASI_ENOSYS; } @@ -1242,8 +1247,8 @@ wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr) if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); - addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); + addr_pool = wasi_ctx_get_addr_pool(wasi_ctx); return wasi_ssp_sock_connect(exec_env, curfds, addr_pool, fd, addr); } @@ -1262,7 +1267,7 @@ wasi_sock_get_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(is_enabled, sizeof(bool))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_broadcast(exec_env, curfds, fd, is_enabled); } @@ -1281,7 +1286,7 @@ wasi_sock_get_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(is_enabled, sizeof(bool))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_keep_alive(exec_env, curfds, fd, is_enabled); } @@ -1301,7 +1306,7 @@ wasi_sock_get_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool *is_enabled, || !validate_native_addr(linger_s, sizeof(int))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_linger(exec_env, curfds, fd, is_enabled, linger_s); @@ -1321,7 +1326,7 @@ wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(size, sizeof(wasi_size_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_recv_buf_size(exec_env, curfds, fd, size); } @@ -1340,7 +1345,7 @@ wasi_sock_get_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(timeout_us, sizeof(uint64_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_recv_timeout(exec_env, curfds, fd, timeout_us); } @@ -1359,7 +1364,7 @@ wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(is_enabled, sizeof(bool))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_reuse_addr(exec_env, curfds, fd, is_enabled); } @@ -1378,7 +1383,7 @@ wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(is_enabled, sizeof(bool))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_reuse_port(exec_env, curfds, fd, is_enabled); } @@ -1397,7 +1402,7 @@ wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(size, sizeof(__wasi_size_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_send_buf_size(exec_env, curfds, fd, size); } @@ -1416,7 +1421,7 @@ wasi_sock_get_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(timeout_us, sizeof(uint64_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_send_timeout(exec_env, curfds, fd, timeout_us); } @@ -1435,7 +1440,7 @@ wasi_sock_get_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(is_enabled, sizeof(bool))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_tcp_fastopen_connect(exec_env, curfds, fd, is_enabled); @@ -1455,7 +1460,7 @@ wasi_sock_get_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(is_enabled, sizeof(bool))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_tcp_no_delay(exec_env, curfds, fd, is_enabled); } @@ -1474,7 +1479,7 @@ wasi_sock_get_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(is_enabled, sizeof(bool))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_tcp_quick_ack(exec_env, curfds, fd, is_enabled); @@ -1494,7 +1499,7 @@ wasi_sock_get_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(time_s, sizeof(uint32_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_tcp_keep_idle(exec_env, curfds, fd, time_s); } @@ -1513,7 +1518,7 @@ wasi_sock_get_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(time_s, sizeof(uint32_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_tcp_keep_intvl(exec_env, curfds, fd, time_s); } @@ -1532,7 +1537,7 @@ wasi_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(is_enabled, sizeof(bool))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_ip_multicast_loop(exec_env, curfds, fd, ipv6, is_enabled); @@ -1551,7 +1556,7 @@ wasi_sock_get_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t *ttl_s) if (!validate_native_addr(ttl_s, sizeof(uint8_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_ip_ttl(exec_env, curfds, fd, ttl_s); } @@ -1570,7 +1575,7 @@ wasi_sock_get_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(ttl_s, sizeof(uint8_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_ip_multicast_ttl(exec_env, curfds, fd, ttl_s); } @@ -1589,7 +1594,7 @@ wasi_sock_get_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(is_enabled, sizeof(bool))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_get_ipv6_only(exec_env, curfds, fd, is_enabled); } @@ -1604,7 +1609,7 @@ wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog) if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasi_ssp_sock_listen(exec_env, curfds, fd, backlog); } @@ -1621,7 +1626,7 @@ wasi_sock_open(wasm_exec_env_t exec_env, wasi_fd_t poolfd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasi_ssp_sock_open(exec_env, curfds, poolfd, af, socktype, sockfd); } @@ -1636,7 +1641,7 @@ wasi_sock_set_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled) if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_broadcast(exec_env, curfds, fd, is_enabled); } @@ -1652,7 +1657,7 @@ wasi_sock_set_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_keep_alive(exec_env, curfds, fd, is_enabled); } @@ -1668,7 +1673,7 @@ wasi_sock_set_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_linger(exec_env, curfds, fd, is_enabled, linger_s); @@ -1684,7 +1689,7 @@ wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size) if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_recv_buf_size(exec_env, curfds, fd, size); } @@ -1700,7 +1705,7 @@ wasi_sock_set_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_recv_timeout(exec_env, curfds, fd, timeout_us); } @@ -1716,7 +1721,7 @@ wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_reuse_addr(exec_env, curfds, fd, is_enabled); } @@ -1732,7 +1737,7 @@ wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_reuse_port(exec_env, curfds, fd, is_enabled); } @@ -1747,7 +1752,7 @@ wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size) if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_send_buf_size(exec_env, curfds, fd, size); } @@ -1763,7 +1768,7 @@ wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_send_timeout(exec_env, curfds, fd, timeout_us); } @@ -1779,7 +1784,7 @@ wasi_sock_set_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_tcp_fastopen_connect(exec_env, curfds, fd, is_enabled); @@ -1796,7 +1801,7 @@ wasi_sock_set_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_tcp_no_delay(exec_env, curfds, fd, is_enabled); } @@ -1812,7 +1817,7 @@ wasi_sock_set_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_tcp_quick_ack(exec_env, curfds, fd, is_enabled); @@ -1829,7 +1834,7 @@ wasi_sock_set_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_tcp_keep_idle(exec_env, curfds, fd, time_s); } @@ -1845,7 +1850,7 @@ wasi_sock_set_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_tcp_keep_intvl(exec_env, curfds, fd, time_s); } @@ -1861,7 +1866,7 @@ wasi_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_ip_multicast_loop(exec_env, curfds, fd, ipv6, is_enabled); @@ -1882,7 +1887,7 @@ wasi_sock_set_ip_add_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_ip_add_membership( exec_env, curfds, fd, imr_multiaddr, imr_interface); @@ -1903,7 +1908,7 @@ wasi_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t))) return __WASI_EINVAL; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_ip_drop_membership( exec_env, curfds, fd, imr_multiaddr, imr_interface); @@ -1919,7 +1924,7 @@ wasi_sock_set_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t ttl_s) if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_ip_ttl(exec_env, curfds, fd, ttl_s); } @@ -1935,7 +1940,7 @@ wasi_sock_set_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_ip_multicast_ttl(exec_env, curfds, fd, ttl_s); } @@ -1950,7 +1955,7 @@ wasi_sock_set_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled) if (!wasi_ctx) return __WASI_EACCES; - curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + curfds = wasi_ctx_get_curfds(wasi_ctx); return wasmtime_ssp_sock_set_ipv6_only(exec_env, curfds, fd, is_enabled); } @@ -2013,7 +2018,8 @@ copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin, } if (buf >= buf_begin + buf_size - || buf + data->buf_len < buf /* integer overflow */ + /* integer overflow */ + || data->buf_len > UINTPTR_MAX - (uintptr_t)buf || buf + data->buf_len > buf_begin + buf_size || size_to_copy == 0) { break; @@ -2048,7 +2054,7 @@ wasi_sock_recv_from(wasm_exec_env_t exec_env, wasi_fd_t sock, **/ wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); uint64 total_size; uint8 *buf_begin = NULL; wasi_errno_t err; @@ -2152,7 +2158,7 @@ wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, **/ wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); uint64 buf_size = 0; uint8 *buf = NULL; wasi_errno_t err; @@ -2192,12 +2198,12 @@ wasi_sock_send_to(wasm_exec_env_t exec_env, wasi_fd_t sock, **/ wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); uint64 buf_size = 0; uint8 *buf = NULL; wasi_errno_t err; size_t send_bytes = 0; - struct addr_pool *addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx); + struct addr_pool *addr_pool = wasi_ctx_get_addr_pool(wasi_ctx); if (!wasi_ctx) { return __WASI_EINVAL; @@ -2226,7 +2232,7 @@ wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how) { wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx); + struct fd_table *curfds = wasi_ctx_get_curfds(wasi_ctx); if (!wasi_ctx) return __WASI_EINVAL; @@ -2237,6 +2243,8 @@ wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how) static wasi_errno_t wasi_sched_yield(wasm_exec_env_t exec_env) { + (void)exec_env; + return wasmtime_ssp_sched_yield(); } diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c index ec1481c2e..4dcc4f5b0 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c @@ -7,6 +7,7 @@ #include "ssp_config.h" #include "blocking_op.h" +#include "libc_errno.h" __wasi_errno_t blocking_op_close(wasm_exec_env_t exec_env, os_file_handle handle, @@ -170,3 +171,23 @@ blocking_op_openat(wasm_exec_env_t exec_env, os_file_handle handle, wasm_runtime_end_blocking_op(exec_env); return error; } + +#ifndef BH_PLATFORM_WINDOWS +/* REVISIT: apply the os_file_handle style abstraction for pollfd? */ +__wasi_errno_t +blocking_op_poll(wasm_exec_env_t exec_env, struct pollfd *pfds, nfds_t nfds, + int timeout_ms, int *retp) +{ + int ret; + if (!wasm_runtime_begin_blocking_op(exec_env)) { + return __WASI_EINTR; + } + ret = poll(pfds, nfds, timeout_ms); + wasm_runtime_end_blocking_op(exec_env); + if (ret == -1) { + return convert_errno(errno); + } + *retp = ret; + return 0; +} +#endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h index afaa4a4f0..9c36d7df6 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h @@ -50,4 +50,10 @@ __wasi_errno_t blocking_op_openat(wasm_exec_env_t exec_env, os_file_handle handle, const char *path, __wasi_oflags_t oflags, __wasi_fdflags_t fd_flags, __wasi_lookupflags_t lookup_flags, - wasi_libc_file_access_mode access_mode, os_file_handle *out); \ No newline at end of file + wasi_libc_file_access_mode access_mode, os_file_handle *out); + +#ifndef BH_PLATFORM_WINDOWS +__wasi_errno_t +blocking_op_poll(wasm_exec_env_t exec_env, struct pollfd *pfds, nfds_t nfds, + int timeout, int *retp); +#endif diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h index 5e0778c3f..0ad40ecfd 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h @@ -88,7 +88,7 @@ struct LOCKABLE rwlock { }; static inline bool -rwlock_init(struct rwlock *lock) REQUIRES_UNLOCKED(*lock) +rwlock_initialize(struct rwlock *lock) REQUIRES_UNLOCKED(*lock) { return os_rwlock_init(&lock->object) == 0 ? true : false; } 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 9819c92fd..03ff50a3f 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 @@ -204,7 +204,7 @@ struct fd_prestat { bool fd_prestats_init(struct fd_prestats *pt) { - if (!rwlock_init(&pt->lock)) + if (!rwlock_initialize(&pt->lock)) return false; pt->prestats = NULL; pt->size = 0; @@ -340,7 +340,7 @@ struct fd_entry { bool fd_table_init(struct fd_table *ft) { - if (!rwlock_init(&ft->lock)) + if (!rwlock_initialize(&ft->lock)) return false; ft->entries = NULL; ft->size = 0; @@ -1017,9 +1017,13 @@ wasmtime_ssp_fd_fdstat_get(wasm_exec_env_t exec_env, struct fd_table *curfds, __wasi_fd_t fd, __wasi_fdstat_t *buf) { struct fd_table *ft = curfds; - rwlock_rdlock(&ft->lock); struct fd_entry *fe; - __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); + __wasi_errno_t error; + + (void)exec_env; + + rwlock_rdlock(&ft->lock); + error = fd_table_get_entry(ft, fd, 0, 0, &fe); if (error != __WASI_ESUCCESS) { rwlock_unlock(&ft->lock); return error; @@ -1071,9 +1075,13 @@ wasmtime_ssp_fd_fdstat_set_rights(wasm_exec_env_t exec_env, __wasi_rights_t fs_rights_inheriting) { struct fd_table *ft = curfds; - rwlock_wrlock(&ft->lock); struct fd_entry *fe; - __wasi_errno_t error = + __wasi_errno_t error; + + (void)exec_env; + + rwlock_wrlock(&ft->lock); + error = fd_table_get_entry(ft, fd, fs_rights_base, fs_rights_inheriting, &fe); if (error != 0) { rwlock_unlock(&ft->lock); @@ -2222,11 +2230,10 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds, timeout = -1; } - int ret = poll(pfds, nsubscriptions, timeout); - - __wasi_errno_t error = 0; - if (ret == -1) { - error = convert_errno(errno); + int ret; + int error = blocking_op_poll(exec_env, pfds, nsubscriptions, timeout, &ret); + if (error != 0) { + /* got an error */ } else if (ret == 0 && *nevents == 0 && clock_subscription != NULL) { // No events triggered. Trigger the clock event. @@ -2980,7 +2987,9 @@ argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf, void argv_environ_destroy(struct argv_environ_values *argv_environ) -{} +{ + (void)argv_environ; +} void fd_table_destroy(struct fd_table *ft) 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 e31889769..298dea674 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 @@ -34,7 +34,7 @@ #define CONFIG_HAS_GETRANDOM 0 #endif -#if defined(__CloudABI__) +#if defined(__CloudABI__) || defined(BH_PLATFORM_FREERTOS) #define CONFIG_HAS_CAP_ENTER 1 #else #define CONFIG_HAS_CAP_ENTER 0 diff --git a/core/iwasm/libraries/thread-mgr/thread_manager.c b/core/iwasm/libraries/thread-mgr/thread_manager.c index b1a615b4a..e0768c88a 100644 --- a/core/iwasm/libraries/thread-mgr/thread_manager.c +++ b/core/iwasm/libraries/thread-mgr/thread_manager.c @@ -442,9 +442,10 @@ final: return ret; } -/* The caller must lock cluster->lock */ -static bool -allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size) +/* The caller must not have any locks */ +bool +wasm_cluster_allocate_aux_stack(WASMExecEnv *exec_env, uint32 *p_start, + uint32 *p_size) { WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); #if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0 @@ -454,8 +455,8 @@ allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size) stack_end = wasm_runtime_module_malloc_internal(module_inst, exec_env, cluster->stack_size, NULL); - *start = stack_end + cluster->stack_size; - *size = cluster->stack_size; + *p_start = stack_end + cluster->stack_size; + *p_size = cluster->stack_size; return stack_end != 0; #else @@ -463,27 +464,35 @@ allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size) /* If the module doesn't have aux stack info, it can't create any threads */ - if (!cluster->stack_segment_occupied) + + cluster_lock_thread_list(cluster, exec_env); + + if (!cluster->stack_segment_occupied) { + cluster_unlock_thread_list(cluster); return false; + } for (i = 0; i < cluster_max_thread_num; i++) { if (!cluster->stack_segment_occupied[i]) { - if (start) - *start = cluster->stack_tops[i]; - if (size) - *size = cluster->stack_size; + if (p_start) + *p_start = cluster->stack_tops[i]; + if (p_size) + *p_size = cluster->stack_size; cluster->stack_segment_occupied[i] = true; + cluster_unlock_thread_list(cluster); return true; } } + cluster_unlock_thread_list(cluster); + return false; #endif } -/* The caller must lock cluster->lock */ -static bool -free_aux_stack(WASMExecEnv *exec_env, uint32 start) +/* The caller must not have any locks */ +bool +wasm_cluster_free_aux_stack(WASMExecEnv *exec_env, uint32 start) { WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); @@ -504,43 +513,19 @@ free_aux_stack(WASMExecEnv *exec_env, uint32 start) #else uint32 i; + cluster_lock_thread_list(cluster, exec_env); for (i = 0; i < cluster_max_thread_num; i++) { if (start == cluster->stack_tops[i]) { cluster->stack_segment_occupied[i] = false; + cluster_unlock_thread_list(cluster); return true; } } + cluster_unlock_thread_list(cluster); return false; #endif } -bool -wasm_cluster_allocate_aux_stack(WASMExecEnv *exec_env, uint32 *p_start, - uint32 *p_size) -{ - WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); - bool ret; - - cluster_lock_thread_list(cluster, exec_env); - ret = allocate_aux_stack(exec_env, p_start, p_size); - cluster_unlock_thread_list(cluster); - - return ret; -} - -bool -wasm_cluster_free_aux_stack(WASMExecEnv *exec_env, uint32 start) -{ - WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); - bool ret; - - cluster_lock_thread_list(cluster, exec_env); - ret = free_aux_stack(exec_env, start); - cluster_unlock_thread_list(cluster); - - return ret; -} - WASMCluster * wasm_cluster_create(WASMExecEnv *exec_env) { @@ -845,6 +830,13 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) goto fail1; } + if (!wasm_cluster_allocate_aux_stack(exec_env, &aux_stack_start, + &aux_stack_size)) { + LOG_ERROR("thread manager error: " + "failed to allocate aux stack space for new thread"); + goto fail1; + } + cluster_lock_thread_list(cluster, exec_env); if (cluster->has_exception || cluster->processing) { @@ -871,37 +863,31 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env) goto fail2; } - if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) { - LOG_ERROR("thread manager error: " - "failed to allocate aux stack space for new thread"); - goto fail3; - } - /* Set aux stack for current thread */ if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start, aux_stack_size)) { - goto fail4; + goto fail3; } /* Inherit suspend_flags of parent thread, no need to acquire thread_state_lock as the thread list has been locked */ - new_exec_env->suspend_flags.flags = exec_env->suspend_flags.flags; + new_exec_env->suspend_flags.flags = + (exec_env->suspend_flags.flags & WASM_SUSPEND_FLAG_INHERIT_MASK); if (!wasm_cluster_add_exec_env(cluster, new_exec_env)) { - goto fail4; + goto fail3; } cluster_unlock_thread_list(cluster); return new_exec_env; -fail4: - /* Free the allocated aux stack space */ - free_aux_stack(exec_env, aux_stack_start); fail3: wasm_exec_env_destroy_internal(new_exec_env); fail2: cluster_unlock_thread_list(cluster); + /* free the allocated aux stack space */ + wasm_cluster_free_aux_stack(exec_env, aux_stack_start); fail1: wasm_runtime_deinstantiate_internal(new_module_inst, true); @@ -916,11 +902,26 @@ wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env) WASMExecEnv *self = get_exec_env_of_current_thread(); bh_assert(cluster != NULL); + WASMExecEnv *exec_env_tls = NULL; + +#ifdef OS_ENABLE_HW_BOUND_CHECK + /* Note: free_aux_stack can execute the module's "free" function + * using the specified exec_env. In case of OS_ENABLE_HW_BOUND_CHECK, + * it needs to match the TLS exec_env if available. (Consider a native + * function which calls wasm_cluster_destroy_spawned_exec_env.) + */ + exec_env_tls = wasm_runtime_get_exec_env_tls(); +#endif + if (exec_env_tls == NULL) { + exec_env_tls = exec_env; + } + + /* Free aux stack space */ + wasm_cluster_free_aux_stack(exec_env_tls, + exec_env->aux_stack_bottom.bottom); cluster_lock_thread_list(cluster, self); - /* Free aux stack space */ - free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); /* Remove exec_env */ wasm_cluster_del_exec_env_internal(cluster, exec_env, false); /* Destroy exec_env */ @@ -964,6 +965,9 @@ thread_manager_start_routine(void *arg) /* Routine exit */ + /* Free aux stack space */ + wasm_cluster_free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); + cluster_lock_thread_list(cluster, exec_env); exec_env->current_status.running_state = WASM_THREAD_EXITED; @@ -984,8 +988,12 @@ thread_manager_start_routine(void *arg) } os_mutex_unlock(&exec_env->wait_lock); - /* Free aux stack space */ - free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); +#if WASM_ENABLE_PERF_PROFILING != 0 + os_printf("============= Spawned thread ===========\n"); + wasm_runtime_dump_perf_profiling(module_inst); + os_printf("========================================\n"); +#endif + /* Remove exec_env */ wasm_cluster_del_exec_env_internal(cluster, exec_env, false); /* Destroy exec_env */ @@ -1039,7 +1047,8 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, /* Inherit suspend_flags of parent thread, no need to acquire thread_state_lock as the thread list has been locked */ - new_exec_env->suspend_flags.flags = exec_env->suspend_flags.flags; + new_exec_env->suspend_flags.flags = + (exec_env->suspend_flags.flags & WASM_SUSPEND_FLAG_INHERIT_MASK); if (!wasm_cluster_add_exec_env(cluster, new_exec_env)) goto fail2; @@ -1082,7 +1091,7 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, { /* workaround about passing instantiate-linking information */ CApiFuncImport **new_c_api_func_imports = NULL; - CApiFuncImport *c_api_func_imports; + CApiFuncImport *c_api_func_imports = NULL; uint32 import_func_count = 0; uint32 size_in_bytes = 0; @@ -1336,6 +1345,9 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) /* App exit the thread, free the resources before exit native thread */ + /* Free aux stack space */ + wasm_cluster_free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); + cluster_lock_thread_list(cluster, exec_env); exec_env->current_status.running_state = WASM_THREAD_EXITED; @@ -1359,8 +1371,6 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval) module_inst = exec_env->module_inst; - /* Free aux stack space */ - free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom); /* Remove exec_env */ wasm_cluster_del_exec_env_internal(cluster, exec_env, false); /* Destroy exec_env */ diff --git a/core/shared/platform/alios/alios_time.c b/core/shared/platform/alios/alios_time.c index 549252738..fb09623a6 100644 --- a/core/shared/platform/alios/alios_time.c +++ b/core/shared/platform/alios/alios_time.c @@ -6,7 +6,14 @@ #include "platform_api_vmcore.h" uint64 -os_time_get_boot_microsecond() +os_time_get_boot_us() { return (uint64)aos_now_ms() * 1000; } + +uint64 +os_time_thread_cputime_us(void) +{ + /* FIXME if u know the right api */ + return os_time_get_boot_us(); +} \ No newline at end of file diff --git a/core/shared/platform/android/platform_internal.h b/core/shared/platform/android/platform_internal.h index 42e4e726c..4449f21e8 100644 --- a/core/shared/platform/android/platform_internal.h +++ b/core/shared/platform/android/platform_internal.h @@ -80,8 +80,6 @@ typedef jmp_buf korp_jmpbuf; #define os_longjmp longjmp #define os_alloca alloca -#define os_getpagesize getpagesize - typedef void (*os_signal_handler)(void *sig_addr); int @@ -101,6 +99,8 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#define os_getpagesize getpagesize + typedef long int __syscall_slong_t; #if __ANDROID_API__ < 19 diff --git a/core/shared/platform/common/freertos/freertos_thread.c b/core/shared/platform/common/freertos/freertos_thread.c index 5ad9f7fcd..929f5587e 100644 --- a/core/shared/platform/common/freertos/freertos_thread.c +++ b/core/shared/platform/common/freertos/freertos_thread.c @@ -204,7 +204,7 @@ os_thread_wrapper(void *arg) thread_data_list_add(thread_data); thread_data->start_routine(thread_data->arg); - os_thread_cleanup(); + os_thread_exit(NULL); } int diff --git a/core/shared/platform/common/freertos/freertos_time.c b/core/shared/platform/common/freertos/freertos_time.c index 4497d8c6c..e8249fec1 100644 --- a/core/shared/platform/common/freertos/freertos_time.c +++ b/core/shared/platform/common/freertos/freertos_time.c @@ -6,8 +6,15 @@ #include "platform_api_vmcore.h" uint64 -os_time_get_boot_microsecond() +os_time_get_boot_us() { TickType_t ticks = xTaskGetTickCount(); return (uint64)1000 * 1000 / configTICK_RATE_HZ * ticks; } + +uint64 +os_time_thread_cputime_us(void) +{ + /* FIXME if u know the right api */ + return os_time_get_boot_us(); +} \ No newline at end of file diff --git a/core/shared/platform/common/memory/mremap.c b/core/shared/platform/common/memory/mremap.c new file mode 100644 index 000000000..bbd287e77 --- /dev/null +++ b/core/shared/platform/common/memory/mremap.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2024 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_memutils.h" + +void * +os_mremap(void *old_addr, size_t old_size, size_t new_size) +{ + return bh_memory_remap_slow(old_addr, old_size, new_size); +} diff --git a/core/shared/platform/common/memory/platform_api_memory.cmake b/core/shared/platform/common/memory/platform_api_memory.cmake new file mode 100644 index 000000000..9f06c1391 --- /dev/null +++ b/core/shared/platform/common/memory/platform_api_memory.cmake @@ -0,0 +1,4 @@ +# Copyright (C) 2024 Amazon Inc. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +file (GLOB_RECURSE PLATFORM_COMMON_MEMORY_SOURCE ${CMAKE_CURRENT_LIST_DIR}/*.c) diff --git a/core/shared/platform/common/posix/platform_api_posix.cmake b/core/shared/platform/common/posix/platform_api_posix.cmake index 2bf9fab4a..17ee04f82 100644 --- a/core/shared/platform/common/posix/platform_api_posix.cmake +++ b/core/shared/platform/common/posix/platform_api_posix.cmake @@ -16,4 +16,19 @@ else() set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) endif() +# This is to support old CMake version. Newer version of CMake could use +# list APPEND/POP_BACK methods. +include(CheckSymbolExists) +set (CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE ${CMAKE_REQUIRED_DEFINITIONS}) +check_symbol_exists (mremap "sys/mman.h" MREMAP_EXISTS) +list (REMOVE_AT CMAKE_REQUIRED_DEFINITIONS 0) + +if(MREMAP_EXISTS) + add_definitions (-DWASM_HAVE_MREMAP=1) +else() + add_definitions (-DWASM_HAVE_MREMAP=0) + include (${CMAKE_CURRENT_LIST_DIR}/../memory/platform_api_memory.cmake) + set (source_all ${source_all} ${PLATFORM_COMMON_MEMORY_SOURCE}) +endif() + set (PLATFORM_COMMON_POSIX_SOURCE ${source_all} ) diff --git a/core/shared/platform/common/posix/posix_blocking_op.c b/core/shared/platform/common/posix/posix_blocking_op.c index 560828a06..e56f84cf1 100644 --- a/core/shared/platform/common/posix/posix_blocking_op.c +++ b/core/shared/platform/common/posix/posix_blocking_op.c @@ -15,6 +15,7 @@ static void blocking_op_sighandler(int signo) { /* nothing */ + (void)signo; } void diff --git a/core/shared/platform/common/posix/posix_clock.c b/core/shared/platform/common/posix/posix_clock.c index 280306c42..41413211c 100644 --- a/core/shared/platform/common/posix/posix_clock.c +++ b/core/shared/platform/common/posix/posix_clock.c @@ -73,6 +73,8 @@ os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, clockid_t nclock_id; __wasi_errno_t error = wasi_clockid_to_clockid(clock_id, &nclock_id); + (void)precision; + if (error != __WASI_ESUCCESS) return error; diff --git a/core/shared/platform/common/posix/posix_file.c b/core/shared/platform/common/posix/posix_file.c index 8c4f7aa9d..ad5589f73 100644 --- a/core/shared/platform/common/posix/posix_file.c +++ b/core/shared/platform/common/posix/posix_file.c @@ -25,12 +25,14 @@ * For NuttX, CONFIG_HAS_ISATTY is provided by its platform header. * (platform_internal.h) */ +#if !defined(CONFIG_HAS_D_INO) #if !defined(__NuttX__) #define CONFIG_HAS_D_INO 1 #define CONFIG_HAS_ISATTY 1 #else #define CONFIG_HAS_D_INO 0 #endif +#endif #if !defined(__APPLE__) && !defined(ESP_PLATFORM) && !defined(__COSMOPOLITAN__) #define CONFIG_HAS_POSIX_FALLOCATE 1 diff --git a/core/shared/platform/common/posix/posix_memmap.c b/core/shared/platform/common/posix/posix_memmap.c index de13c065f..afc549cdd 100644 --- a/core/shared/platform/common/posix/posix_memmap.c +++ b/core/shared/platform/common/posix/posix_memmap.c @@ -3,10 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#if !defined(_GNU_SOURCE) && WASM_HAVE_MREMAP != 0 +/* Enable mremap */ +#define _GNU_SOURCE +#include "bh_memutils.h" +#endif + #include "platform_api_vmcore.h" #if defined(__APPLE__) || defined(__MACH__) #include +#include #endif #ifndef BH_ENABLE_TRACE_MMAP @@ -78,19 +85,15 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) map_prot |= PROT_EXEC; #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) +#ifndef __APPLE__ if (flags & MMAP_MAP_32BIT) map_flags |= MAP_32BIT; +#endif #endif if (flags & MMAP_MAP_FIXED) map_flags |= MAP_FIXED; -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) -#if defined(__APPLE__) -retry_without_map_32bit: -#endif -#endif - #if defined(BUILD_TARGET_RISCV64_LP64D) || defined(BUILD_TARGET_RISCV64_LP64) /* As AOT relocation in RISCV64 may require that the code/data mapped * is in range 0 to 2GB, we try to map the memory with hint address @@ -148,14 +151,6 @@ retry_without_map_32bit: } if (addr == MAP_FAILED) { -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) -#if defined(__APPLE__) - if ((map_flags & MAP_32BIT) != 0) { - map_flags &= ~MAP_32BIT; - goto retry_without_map_32bit; - } -#endif -#endif #if BH_ENABLE_TRACE_MMAP != 0 os_printf("mmap failed\n"); #endif @@ -247,6 +242,23 @@ os_munmap(void *addr, size_t size) } } +#if WASM_HAVE_MREMAP != 0 +void * +os_mremap(void *old_addr, size_t old_size, size_t new_size) +{ + void *ptr = mremap(old_addr, old_size, new_size, MREMAP_MAYMOVE); + + if (ptr == MAP_FAILED) { +#if BH_ENABLE_TRACE_MMAP != 0 + os_printf("mremap failed: %d\n", errno); +#endif + return bh_memory_remap_slow(old_addr, old_size, new_size); + } + + return ptr; +} +#endif + int os_mprotect(void *addr, size_t size, int prot) { @@ -278,5 +290,8 @@ os_icache_flush(void *start, size_t len) { #if defined(__APPLE__) || defined(__MACH__) sys_icache_invalidate(start, len); +#else + (void)start; + (void)len; #endif } diff --git a/core/shared/platform/common/posix/posix_socket.c b/core/shared/platform/common/posix/posix_socket.c index 7bdcb529e..0293b08d8 100644 --- a/core/shared/platform/common/posix/posix_socket.c +++ b/core/shared/platform/common/posix/posix_socket.c @@ -884,7 +884,7 @@ os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) int os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) { - socklen_t opt_len = sizeof(ttl_s); + socklen_t opt_len = sizeof(*ttl_s); if (getsockopt(socket, IPPROTO_IP, IP_TTL, ttl_s, &opt_len) != 0) { return BHT_ERROR; } @@ -906,7 +906,7 @@ os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) int os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) { - socklen_t opt_len = sizeof(ttl_s); + socklen_t opt_len = sizeof(*ttl_s); if (getsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, ttl_s, &opt_len) != 0) { return BHT_ERROR; diff --git a/core/shared/platform/common/posix/posix_thread.c b/core/shared/platform/common/posix/posix_thread.c index 42590b098..b37705cb4 100644 --- a/core/shared/platform/common/posix/posix_thread.c +++ b/core/shared/platform/common/posix/posix_thread.c @@ -9,6 +9,10 @@ #include "platform_api_vmcore.h" #include "platform_api_extension.h" +#if defined(__APPLE__) || defined(__MACH__) +#include +#endif + typedef struct { thread_start_routine_t start; void *arg; diff --git a/core/shared/platform/common/posix/posix_time.c b/core/shared/platform/common/posix/posix_time.c index bcf5ca3ce..8c339aba2 100644 --- a/core/shared/platform/common/posix/posix_time.c +++ b/core/shared/platform/common/posix/posix_time.c @@ -6,7 +6,7 @@ #include "platform_api_vmcore.h" uint64 -os_time_get_boot_microsecond() +os_time_get_boot_us() { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { @@ -15,3 +15,14 @@ os_time_get_boot_microsecond() return ((uint64)ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000; } + +uint64 +os_time_thread_cputime_us() +{ + struct timespec ts; + if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0) { + return 0; + } + + return ((uint64)ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000; +} \ No newline at end of file diff --git a/core/shared/platform/cosmopolitan/platform_internal.h b/core/shared/platform/cosmopolitan/platform_internal.h index 02cd78be4..726021160 100644 --- a/core/shared/platform/cosmopolitan/platform_internal.h +++ b/core/shared/platform/cosmopolitan/platform_internal.h @@ -55,6 +55,7 @@ typedef pthread_t korp_tid; typedef pthread_mutex_t korp_mutex; typedef pthread_cond_t korp_cond; typedef pthread_t korp_thread; +typedef pthread_rwlock_t korp_rwlock; typedef sem_t korp_sem; #define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER @@ -67,6 +68,12 @@ typedef int os_file_handle; typedef DIR *os_dir_stream; typedef int os_raw_file_handle; +static inline os_file_handle +os_get_invalid_handle() +{ + return -1; +} + #if WASM_DISABLE_WRITE_GS_BASE == 0 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) #define os_writegsbase(base_addr) \ @@ -98,8 +105,6 @@ typedef jmp_buf korp_jmpbuf; #define os_longjmp longjmp #define os_alloca alloca -#define os_getpagesize getpagesize - typedef void (*os_signal_handler)(void *sig_addr); int @@ -119,6 +124,8 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#define os_getpagesize getpagesize + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/darwin/platform_internal.h b/core/shared/platform/darwin/platform_internal.h index 30b89624e..1cbecdc20 100644 --- a/core/shared/platform/darwin/platform_internal.h +++ b/core/shared/platform/darwin/platform_internal.h @@ -82,8 +82,6 @@ typedef jmp_buf korp_jmpbuf; #define os_longjmp longjmp #define os_alloca alloca -#define os_getpagesize getpagesize - typedef void (*os_signal_handler)(void *sig_addr); int @@ -103,6 +101,8 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#define os_getpagesize getpagesize + #if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 #define OS_ENABLE_WAKEUP_BLOCKING_OP #endif diff --git a/core/shared/platform/darwin/shared_platform.cmake b/core/shared/platform/darwin/shared_platform.cmake index 5eecd65c7..3680f3d3a 100644 --- a/core/shared/platform/darwin/shared_platform.cmake +++ b/core/shared/platform/darwin/shared_platform.cmake @@ -12,6 +12,9 @@ include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake) file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) +include (${CMAKE_CURRENT_LIST_DIR}/../common/memory/platform_api_memory.cmake) +set (source_all ${source_all} ${PLATFORM_COMMON_MEMORY_SOURCE}) + set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE}) file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) diff --git a/core/shared/platform/esp-idf/espidf_platform.c b/core/shared/platform/esp-idf/espidf_platform.c index bbc18f69b..0a1dd3c9d 100644 --- a/core/shared/platform/esp-idf/espidf_platform.c +++ b/core/shared/platform/esp-idf/espidf_platform.c @@ -36,11 +36,18 @@ os_vprintf(const char *format, va_list ap) } uint64 -os_time_get_boot_microsecond(void) +os_time_get_boot_us(void) { return (uint64)esp_timer_get_time(); } +uint64 +os_time_thread_cputime_us(void) +{ + /* FIXME if u know the right api */ + return os_time_get_boot_us(); +} + uint8 * os_thread_get_stack_boundary(void) { diff --git a/core/shared/platform/freebsd/platform_internal.h b/core/shared/platform/freebsd/platform_internal.h index 5241c6456..bfdfe1493 100644 --- a/core/shared/platform/freebsd/platform_internal.h +++ b/core/shared/platform/freebsd/platform_internal.h @@ -85,8 +85,6 @@ typedef jmp_buf korp_jmpbuf; #define os_longjmp longjmp #define os_alloca alloca -#define os_getpagesize getpagesize - typedef void (*os_signal_handler)(void *sig_addr); int @@ -106,6 +104,8 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#define os_getpagesize getpagesize + #if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 #define OS_ENABLE_WAKEUP_BLOCKING_OP #endif diff --git a/core/shared/platform/include/platform_api_vmcore.h b/core/shared/platform/include/platform_api_vmcore.h index c6b56f12c..d05768473 100644 --- a/core/shared/platform/include/platform_api_vmcore.h +++ b/core/shared/platform/include/platform_api_vmcore.h @@ -64,7 +64,13 @@ os_vprintf(const char *format, va_list ap); * Get microseconds after boot. */ uint64 -os_time_get_boot_microsecond(void); +os_time_get_boot_us(void); + +/** + * Get thread-specific CPU-time clock in microseconds + */ +uint64 +os_time_thread_cputime_us(void); /** * Get current thread id. @@ -129,7 +135,7 @@ enum { MMAP_MAP_32BIT = 1, /* Don't interpret addr as a hint: place the mapping at exactly that address. */ - MMAP_MAP_FIXED = 2 + MMAP_MAP_FIXED = 2, }; void * @@ -139,6 +145,11 @@ os_munmap(void *addr, size_t size); int os_mprotect(void *addr, size_t size, int prot); +/* Doesn't guarantee that protection flags will be preserved. + os_mprotect() must be called after remapping. */ +void * +os_mremap(void *old_addr, size_t old_size, size_t new_size); + #if (WASM_MEM_DUAL_BUS_MIRROR != 0) void * os_get_dbus_mirror(void *ibus); diff --git a/core/shared/platform/linux-sgx/platform_internal.h b/core/shared/platform/linux-sgx/platform_internal.h index c96768e32..2cc34dfca 100644 --- a/core/shared/platform/linux-sgx/platform_internal.h +++ b/core/shared/platform/linux-sgx/platform_internal.h @@ -79,6 +79,8 @@ os_get_invalid_handle() return -1; } +#define os_getpagesize getpagesize + #ifdef __cplusplus } #endif diff --git a/core/shared/platform/linux-sgx/sgx_time.c b/core/shared/platform/linux-sgx/sgx_time.c index d090083ef..d39db22fb 100644 --- a/core/shared/platform/linux-sgx/sgx_time.c +++ b/core/shared/platform/linux-sgx/sgx_time.c @@ -26,7 +26,7 @@ ocall_clock_nanosleep(int *p_ret, unsigned clock_id, int flags, const void *rem_buf, unsigned int rem_buf_size); uint64 -os_time_get_boot_microsecond() +os_time_get_boot_us() { #ifndef SGX_DISABLE_WASI struct timespec ts; @@ -40,6 +40,21 @@ os_time_get_boot_microsecond() #endif } +uint64 +os_time_thread_cputime_us(void) +{ +#ifndef SGX_DISABLE_WASI + struct timespec ts; + if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0) { + return 0; + } + + return ((uint64)ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000; +#else + return 0; +#endif +} + #ifndef SGX_DISABLE_WASI int diff --git a/core/shared/platform/linux-sgx/shared_platform.cmake b/core/shared/platform/linux-sgx/shared_platform.cmake index e8e167005..9cd765be4 100644 --- a/core/shared/platform/linux-sgx/shared_platform.cmake +++ b/core/shared/platform/linux-sgx/shared_platform.cmake @@ -37,6 +37,9 @@ else() set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) endif() +include (${CMAKE_CURRENT_LIST_DIR}/../common/memory/platform_api_memory.cmake) +set (source_all ${source_all} ${PLATFORM_COMMON_MEMORY_SOURCE}) + file (GLOB source_all_untrusted ${PLATFORM_SHARED_DIR}/untrusted/*.c) set (PLATFORM_SHARED_SOURCE ${source_all}) diff --git a/core/shared/platform/linux/platform_internal.h b/core/shared/platform/linux/platform_internal.h index 335070bf8..aeddc4ccf 100644 --- a/core/shared/platform/linux/platform_internal.h +++ b/core/shared/platform/linux/platform_internal.h @@ -95,8 +95,6 @@ typedef jmp_buf korp_jmpbuf; #define os_longjmp longjmp #define os_alloca alloca -#define os_getpagesize getpagesize - typedef void (*os_signal_handler)(void *sig_addr); int @@ -116,6 +114,8 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#define os_getpagesize getpagesize + #if WASM_DISABLE_WAKEUP_BLOCKING_OP == 0 #define OS_ENABLE_WAKEUP_BLOCKING_OP #endif diff --git a/core/shared/platform/nuttx/nuttx_platform.c b/core/shared/platform/nuttx/nuttx_platform.c index 38e70076d..d105924ae 100644 --- a/core/shared/platform/nuttx/nuttx_platform.c +++ b/core/shared/platform/nuttx/nuttx_platform.c @@ -87,6 +87,7 @@ os_dumps_proc_mem_info(char *out, unsigned int size) void * os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) { + void *p; #if (WASM_MEM_DUAL_BUS_MIRROR != 0) void *i_addr, *d_addr; #endif @@ -110,7 +111,21 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) return in_ibus_ext(i_addr) ? i_addr : d_addr; } #endif - return malloc((uint32)size); + /* Note: aot_loader.c assumes that os_mmap provides large enough + * alignment for any data sections. Some sections like rodata.cst32 + * actually require alignment larger than the natural alignment + * provided by malloc. + * + * Probably it's cleaner to add an explicit alignment argument to + * os_mmap. However, it only makes sense if we change our aot format + * to keep the necessary alignment. + * + * For now, let's assume 32 byte alignment is enough. + */ + if (posix_memalign(&p, 32, size)) { + return NULL; + } + return p; } void diff --git a/core/shared/platform/nuttx/platform_internal.h b/core/shared/platform/nuttx/platform_internal.h index 2fb80a6e3..0b54d85a9 100644 --- a/core/shared/platform/nuttx/platform_internal.h +++ b/core/shared/platform/nuttx/platform_internal.h @@ -44,6 +44,8 @@ typedef pthread_t korp_thread; typedef pthread_rwlock_t korp_rwlock; typedef sem_t korp_sem; +#define os_getpagesize getpagesize + #define OS_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB) diff --git a/core/shared/platform/nuttx/shared_platform.cmake b/core/shared/platform/nuttx/shared_platform.cmake index 1cbe2218b..ff70cc031 100644 --- a/core/shared/platform/nuttx/shared_platform.cmake +++ b/core/shared/platform/nuttx/shared_platform.cmake @@ -16,5 +16,6 @@ if (WAMR_BUILD_LIBC_WASI EQUAL 1) set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) endif () -set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE}) +include (${CMAKE_CURRENT_LIST_DIR}/../common/memory/platform_api_memory.cmake) +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE} ${PLATFORM_COMMON_MEMORY_SOURCE}) diff --git a/core/shared/platform/riot/riot_time.c b/core/shared/platform/riot/riot_time.c index 1503495c1..ce73777c9 100644 --- a/core/shared/platform/riot/riot_time.c +++ b/core/shared/platform/riot/riot_time.c @@ -10,25 +10,32 @@ #if IS_USED(MODULE_ZTIMER64_USEC) uint64 -os_time_get_boot_microsecond() +os_time_get_boot_us() { return ztimer64_now(ZTIMER64_USEC); } #elif IS_USED(MODULE_ZTIMER64_MSEC) uint64 -os_time_get_boot_microsecond() +os_time_get_boot_us() { return ztimer64_now(ZTIMER64_MSEC) * 1000; } #else #ifdef __GNUC__ __attribute__((weak)) uint64 -os_time_get_boot_microsecond(); +os_time_get_boot_us(); #endif uint64 -os_time_get_boot_microsecond() +os_time_get_boot_us() { static uint64_t times; return ++times; } #endif + +uint64 +os_time_thread_cputime_us(void) +{ + /* FIXME if u know the right api */ + return os_time_get_boot_us(); +} diff --git a/core/shared/platform/rt-thread/rtt_platform.c b/core/shared/platform/rt-thread/rtt_platform.c index e5a574595..0ddf082ee 100644 --- a/core/shared/platform/rt-thread/rtt_platform.c +++ b/core/shared/platform/rt-thread/rtt_platform.c @@ -120,13 +120,20 @@ os_vprintf(const char *format, va_list ap) } uint64 -os_time_get_boot_microsecond(void) +os_time_get_boot_us(void) { uint64 ret = rt_tick_get() * 1000; ret /= RT_TICK_PER_SECOND; return ret; } +uint64 +os_time_thread_cputime_us(void) +{ + /* FIXME if u know the right api */ + return os_time_get_boot_us(); +} + korp_tid os_self_thread(void) { diff --git a/core/shared/platform/vxworks/platform_internal.h b/core/shared/platform/vxworks/platform_internal.h index 930ff7777..1b870c70e 100644 --- a/core/shared/platform/vxworks/platform_internal.h +++ b/core/shared/platform/vxworks/platform_internal.h @@ -79,8 +79,6 @@ typedef jmp_buf korp_jmpbuf; #define os_longjmp longjmp #define os_alloca alloca -#define os_getpagesize getpagesize - typedef void (*os_signal_handler)(void *sig_addr); int @@ -100,6 +98,8 @@ os_sigreturn(); #endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64 */ #endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ +#define os_getpagesize getpagesize + static inline os_file_handle os_get_invalid_handle() { diff --git a/core/shared/platform/windows/shared_platform.cmake b/core/shared/platform/windows/shared_platform.cmake index 3c531c17c..502a8a2ed 100644 --- a/core/shared/platform/windows/shared_platform.cmake +++ b/core/shared/platform/windows/shared_platform.cmake @@ -20,6 +20,9 @@ else() set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) endif() +include (${CMAKE_CURRENT_LIST_DIR}/../common/memory/platform_api_memory.cmake) +set (source_all ${source_all} ${PLATFORM_COMMON_MEMORY_SOURCE}) + set (PLATFORM_SHARED_SOURCE ${source_all}) file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) diff --git a/core/shared/platform/windows/win_socket.c b/core/shared/platform/windows/win_socket.c index 91d38fd8b..b19e5b097 100644 --- a/core/shared/platform/windows/win_socket.c +++ b/core/shared/platform/windows/win_socket.c @@ -32,6 +32,7 @@ static bool is_winsock_inited = false; int init_winsock() { +#if WASM_ENABLE_HOST_SOCKET_INIT == 0 WSADATA wsaData; if (!is_winsock_inited) { @@ -42,6 +43,7 @@ init_winsock() is_winsock_inited = true; } +#endif return BHT_OK; } @@ -49,9 +51,11 @@ init_winsock() void deinit_winsock() { +#if WASM_ENABLE_HOST_SOCKET_INIT == 0 if (is_winsock_inited) { WSACleanup(); } +#endif } int diff --git a/core/shared/platform/windows/win_time.c b/core/shared/platform/windows/win_time.c index 20e90d5eb..7b2cd4fff 100644 --- a/core/shared/platform/windows/win_time.c +++ b/core/shared/platform/windows/win_time.c @@ -6,7 +6,7 @@ #include "platform_api_vmcore.h" uint64 -os_time_get_boot_microsecond() +os_time_get_boot_us() { struct timespec ts; #if defined(__MINGW32__) @@ -18,3 +18,10 @@ os_time_get_boot_microsecond() return ((uint64)ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000; } + +uint64 +os_time_thread_cputime_us(void) +{ + /* FIXME if u know the right api */ + return os_time_get_boot_us(); +} \ No newline at end of file diff --git a/core/shared/platform/zephyr/zephyr_time.c b/core/shared/platform/zephyr/zephyr_time.c index 99eb3b354..78bc3e076 100644 --- a/core/shared/platform/zephyr/zephyr_time.c +++ b/core/shared/platform/zephyr/zephyr_time.c @@ -6,7 +6,14 @@ #include "platform_api_vmcore.h" uint64 -os_time_get_boot_microsecond() +os_time_get_boot_us() { return k_uptime_get() * 1000; } + +uint64 +os_time_thread_cputime_us(void) +{ + /* FIXME if u know the right api */ + return os_time_get_boot_us(); +} diff --git a/core/shared/utils/bh_hashmap.c b/core/shared/utils/bh_hashmap.c index 3502239ad..794b7a746 100644 --- a/core/shared/utils/bh_hashmap.c +++ b/core/shared/utils/bh_hashmap.c @@ -51,7 +51,9 @@ bh_hash_map_create(uint32 size, bool use_lock, HashFunc hash_func, + sizeof(HashMapElem *) * (uint64)size + (use_lock ? sizeof(korp_mutex) : 0); - if (total_size >= UINT32_MAX || !(map = BH_MALLOC((uint32)total_size))) { + /* size <= HASH_MAP_MAX_SIZE, so total_size won't be larger than + UINT32_MAX, no need to check integer overflow */ + if (!(map = BH_MALLOC((uint32)total_size))) { LOG_ERROR("HashMap create failed: alloc memory failed.\n"); return NULL; } diff --git a/core/shared/utils/bh_log.c b/core/shared/utils/bh_log.c index 7bb3d3363..1ffd9b764 100644 --- a/core/shared/utils/bh_log.c +++ b/core/shared/utils/bh_log.c @@ -17,6 +17,7 @@ bh_log_set_verbose_level(uint32 level) log_verbose_level = level; } +#ifndef BH_LOG void bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...) { @@ -31,7 +32,7 @@ bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...) self = os_self_thread(); - usec = os_time_get_boot_microsecond(); + usec = os_time_get_boot_us(); t = (uint32)(usec / 1000000) % (24 * 60 * 60); h = t / (60 * 60); t = t % (60 * 60); @@ -56,6 +57,7 @@ bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...) os_printf("\n"); } +#endif static uint32 last_time_ms = 0; static uint32 total_time_ms = 0; diff --git a/core/shared/utils/bh_log.h b/core/shared/utils/bh_log.h index e0bc61da2..53921b250 100644 --- a/core/shared/utils/bh_log.h +++ b/core/shared/utils/bh_log.h @@ -38,8 +38,14 @@ typedef enum { void bh_log_set_verbose_level(uint32 level); +#ifndef BH_LOG void bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...); +#else +void +BH_LOG(uint32 log_level, const char *file, int line, const char *fmt, ...); +#define bh_log BH_LOG +#endif #ifdef BH_PLATFORM_NUTTX diff --git a/core/shared/utils/bh_memutils.c b/core/shared/utils/bh_memutils.c new file mode 100644 index 000000000..a655d8ac2 --- /dev/null +++ b/core/shared/utils/bh_memutils.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_memutils.h" + +void * +bh_memory_remap_slow(void *old_addr, size_t old_size, size_t new_size) +{ + void *new_memory = + os_mmap(NULL, new_size, MMAP_PROT_WRITE | MMAP_PROT_READ, 0, -1); + if (!new_memory) { + return NULL; + } + /* + * bh_memcpy_s can't be used as it doesn't support values bigger than + * UINT32_MAX + */ + memcpy(new_memory, old_addr, new_size < old_size ? new_size : old_size); + os_munmap(old_addr, old_size); + + return new_memory; +} diff --git a/core/shared/utils/bh_memutils.h b/core/shared/utils/bh_memutils.h new file mode 100644 index 000000000..7581860bd --- /dev/null +++ b/core/shared/utils/bh_memutils.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 Amazon Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _BH_MEMUTILS_H +#define _BH_MEMUTILS_H + +#include "bh_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Remaps memory by mapping a new region, copying data from the old + * region and umapping the old region. + * + * Unless the behavior is desired, in most cases os_mremap should be used + * as it's at worst equally slow as this function, and on some platforms + * (e.g. posix with mremap) os_mremap will perform better. + * + * @param old_addr an old address. + * @param old_size a size of the old address. + * @param new_size a size of the new memory region. + * @return a pointer to the new memory region. + */ +void * +bh_memory_remap_slow(void *old_addr, size_t old_size, size_t new_size); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _BH_MEMUTILS_H */ diff --git a/core/shared/utils/runtime_timer.c b/core/shared/utils/runtime_timer.c index 8fccf4c2f..b9ace567f 100644 --- a/core/shared/utils/runtime_timer.c +++ b/core/shared/utils/runtime_timer.c @@ -38,7 +38,7 @@ struct _timer_ctx { uint64 bh_get_tick_ms() { - return os_time_get_boot_microsecond() / 1000; + return os_time_get_boot_us() / 1000; } uint32 diff --git a/core/version.h b/core/version.h index ec41ecd65..8f9f757a6 100644 --- a/core/version.h +++ b/core/version.h @@ -7,5 +7,5 @@ #define _WAMR_VERSION_H_ #define WAMR_VERSION_MAJOR 1 #define WAMR_VERSION_MINOR 3 -#define WAMR_VERSION_PATCH 1 +#define WAMR_VERSION_PATCH 2 #endif diff --git a/doc/build_wamr.md b/doc/build_wamr.md index 1ac62409c..6857478a9 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -62,6 +62,7 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM #### **Enable Multi-Module feature** - **WAMR_BUILD_MULTI_MODULE**=1/0, default to disable if not set +> Note: See [Multiple Modules as Dependencies](./multi_module.md) for more details. #### **Enable WASM mini loader** @@ -82,6 +83,8 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM - **WAMR_BUILD_LIB_PTHREAD**=1/0, default to disable if not set > Note: The dependent feature of lib pthread such as the `shared memory` and `thread manager` will be enabled automatically. +> See [WAMR pthread library](./pthread_library.md) for more details. + #### **Enable lib-pthread-semaphore** - **WAMR_BUILD_LIB_PTHREAD_SEMAPHORE**=1/0, default to disable if not set > Note: This feature depends on `lib-pthread`, it will be enabled automatically if this feature is enabled. @@ -90,8 +93,11 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM - **WAMR_BUILD_LIB_WASI_THREADS**=1/0, default to disable if not set > Note: The dependent feature of lib wasi-threads such as the `shared memory` and `thread manager` will be enabled automatically. +> See [wasi-threads](./pthread_impls.md#wasi-threads-new) and [Introduction to WAMR WASI threads](https://bytecodealliance.github.io/wamr.dev/blog/introduction-to-wamr-wasi-threads) for more details. + #### **Enable lib wasi-nn** - **WAMR_BUILD_WASI_NN**=1/0, default to disable if not set +> Note: See [WASI-NN](../core/iwasm/libraries/wasi-nn) for more details. #### **Enable lib wasi-nn GPU mode** - **WAMR_BUILD_WASI_NN_ENABLE_GPU**=1/0, default to disable if not set @@ -137,12 +143,17 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM > Note: if it is enabled, developer can use API `void wasm_runtime_dump_mem_consumption(wasm_exec_env_t exec_env)` to dump the memory consumption info. Currently we only profile the memory consumption of module, module_instance and exec_env, the memory consumed by other components such as `wasi-ctx`, `multi-module` and `thread-manager` are not included. +> Also refer to [Memory usage estimation for a module](./memory_usage.md). + #### **Enable performance profiling (Experiment)** - **WAMR_BUILD_PERF_PROFILING**=1/0, default to disable if not set > Note: if it is enabled, developer can use API `void wasm_runtime_dump_perf_profiling(wasm_module_inst_t module_inst)` to dump the performance consumption info. Currently we only profile the performance consumption of each WASM function. > The function name searching sequence is the same with dump call stack feature. +> Also refer to [Tune the performance of running wasm/aot file](./perf_tune.md). + + #### **Enable the global heap** - **WAMR_BUILD_GLOBAL_HEAP_POOL**=1/0, default to disable if not set for all *iwasm* applications, except for the platforms Alios and Zephyr. @@ -179,7 +190,17 @@ Currently we only profile the memory consumption of module, module_instance and > } > ``` > -> and then use `cmake -DWAMR_BH_VPRINTF=my_vprintf ..` to pass the callback function, or add `BH_VPRINTF=my_vprintf` macro for the compiler, e.g. add line `add_defintions(-DBH_VPRINTF=my_vprintf)` in CMakeListst.txt. +> and then use `cmake -DWAMR_BH_VPRINTF=my_vprintf ..` to pass the callback function, or add `BH_VPRINTF=my_vprintf` macro for the compiler, e.g. add line `add_defintions(-DBH_VPRINTF=my_vprintf)` in CMakeListst.txt. See [basic sample](../samples/basic/src/main.c) for a usage example. + +#### **WAMR_BH_LOG**=, default to disable if not set +> Note: if the log_callback function is provided by the developer, WAMR logs are redirected to such callback. For example: +> ```C +> void my_log(uint32 log_level, const char *file, int line, const char *fmt, ...) +> { +> /* Usage of custom logger */ +> } +> ``` +> See [basic sample](../samples/basic/src/main.c) for a usage example. #### **Enable reference types feature** - **WAMR_BUILD_REF_TYPES**=1/0, default to disable if not set @@ -192,7 +213,7 @@ Currently we only profile the memory consumption of module, module_instance and #### **Enable source debugging features** - **WAMR_BUILD_DEBUG_INTERP**=1/0, default to 0 if not set -> Note: There are some other setup required by source debugging, please refer to [source_debugging.md](./source_debugging.md) for more details. +> Note: There are some other setup required by source debugging, please refer to [source_debugging.md](./source_debugging.md) and [WAMR source debugging basic](https://bytecodealliance.github.io/wamr.dev/blog/wamr-source-debugging-basic) for more details. #### **Enable load wasm custom sections** - **WAMR_BUILD_LOAD_CUSTOM_SECTION**=1/0, default to disable if not set @@ -207,12 +228,34 @@ Currently we only profile the memory consumption of module, module_instance and - **WAMR_BUILD_STACK_GUARD_SIZE**=n, default to N/A if not set. > Note: By default, the stack guard size is 1K (1024) or 24K (if uvwasi enabled). -### **Disable the writing linear memory base address to x86 GS segment register +### **Disable the writing linear memory base address to x86 GS segment register** - **WAMR_DISABLE_WRITE_GS_BASE**=1/0, default to enable if not set and supported by platform > Note: by default only platform [linux x86-64](https://github.com/bytecodealliance/wasm-micro-runtime/blob/5fb5119239220b0803e7045ca49b0a29fe65e70e/core/shared/platform/linux/platform_internal.h#L67) will enable this feature, for 32-bit platforms it's automatically disabled even when the flag is set to 0. In linux x86-64, writing the linear memory base address to x86 GS segment register may be used to speedup the linear memory access for LLVM AOT/JIT, when `--enable-segue=[]` option is added for `wamrc` or `iwasm`. +> See [Enable segue optimization for wamrc when generating the aot file](./perf_tune.md#3-enable-segue-optimization-for-wamrc-when-generating-the-aot-file) for more details. + ### **Enable running PGO(Profile-Guided Optimization) instrumented AOT file** - **WAMR_BUILD_STATIC_PGO**=1/0, default to disable if not set +> Note: See [Use the AOT static PGO method](./perf_tune.md#5-use-the-aot-static-pgo-method) for more details. + +### **Enable linux perf support** +- **WAMR_BUILD_LINUX_PERF**=1/0, enable linux perf support to generate the flamegraph to analyze the performance of a wasm application, default to disable if not set +> Note: See [Use linux-perf](./perf_tune.md#7-use-linux-perf) for more details. + +### **Enable module instance context APIs** +- **WAMR_BUILD_MODULE_INST_CONTEXT**=1/0, enable module instance context APIs which can set one or more contexts created by the embedder for a wasm module instance, default to enable if not set: +```C + wasm_runtime_create_context_key + wasm_runtime_destroy_context_key + wasm_runtime_set_context + wasm_runtime_set_context_spread + wasm_runtime_get_context +``` +> Note: See [wasm_export.h](../core/iwasm/include/wasm_export.h) for more details. + +### **Enable quick AOT/JTI entries** +- **WAMR_BUILD_QUICK_AOT_ENTRY**=1/0, enable registering quick call entries to speedup the aot/jit func call process, default to enable if not set +> Note: See [Refine callings to AOT/JIT functions from host native](./perf_tune.md#83-refine-callings-to-aotjit-functions-from-host-native) for more details. **Combination of configurations:** diff --git a/doc/build_wasm_app.md b/doc/build_wasm_app.md index 23119456e..7747d9ac3 100644 --- a/doc/build_wasm_app.md +++ b/doc/build_wasm_app.md @@ -5,7 +5,7 @@ Prepare WASM building environments For C and C++, WASI-SDK version 19.0+ is the major tool supported by WAMR to build WASM applications. Also, we can use [Emscripten SDK (EMSDK)](https://github.com/emscripten-core/emsdk), but it is not recommended. And there are some other compilers such as the standard clang compiler, which might also work [here](./other_wasm_compilers.md). -To install WASI SDK, please download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. +To install WASI SDK, please download the [wasi-sdk release](https://github.com/WebAssembly/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. The official *wasi-sdk release* doesn't fully support *latest 128-bit SIMD spec* yet. WAMR provides a script in [build-wasi-sdk](../test-tools/build-wasi-sdk/) to generate another wasi-sdk with *llvm-15* from source code and installs it at *../test-tools/wasi-sdk*. If you plan to build WASM applications with *latest 128-bit SIMD*, please use it instead of the official release. diff --git a/doc/memory_usage.md b/doc/memory_usage.md index ec0624c6f..88b792f0c 100644 --- a/doc/memory_usage.md +++ b/doc/memory_usage.md @@ -51,14 +51,9 @@ They are in the number of WASM pages, each of which is of 65536 bytes. The `max` is optional for non-shared memory. When omitted, it effectivily means unlimited. -If `OS_ENABLE_HW_BOUND_CHECK` is enabled, the memory is allocated via -`os_mmap` and `os_mem_commit`/`os_mprotect`. -Otherwise, it's allocated from the global heap. +The linear memory is allocated via `os_mmap` and `os_mem_commit`/`os_mprotect`. -If the memory is shared and `OS_ENABLE_HW_BOUND_CHECK` is not enabled, -the `max` size of memory is allocated on instantiation. - -Otherwise, the `min` size of memory is allocated on instantiation. +The `min` size of memory is allocated on instantiation. It can later grow up to the `max` size via the `memory.grow` instruction. Libc heap diff --git a/doc/multi_module.md b/doc/multi_module.md index 1c22863f9..9ab26673e 100644 --- a/doc/multi_module.md +++ b/doc/multi_module.md @@ -6,7 +6,7 @@ WAMR loads all dependencies recursively according to the _import section_ of a m > WAMR only implements the load-time dynamic linking. Please refer to [dynamic linking](https://webassembly.org/docs/dynamic-linking/) for more details. -WAMR follows [WASI Command/Reactor Model](https://github.com/WebAssembly/WASI/blob/main/design/application-abi.md#current-unstable-abi). The WASI model separates modules into commands and reactors. A Command is the main module that requires exports of reactors(submodules). +WAMR follows [WASI Command/Reactor Model](https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md#current-unstable-abi). The WASI model separates modules into commands and reactors. A Command is the main module that requires exports of reactors(submodules). if `WASM_ENABLE_LIBC_WASI` is enabled, any module imports a WASI APIs, like `(import "wasi_snapshot_preview1" "XXX")`, should follow restrictions of the _WASI application ABI_: diff --git a/doc/perf_tune.md b/doc/perf_tune.md index 5cd631a19..b366f09c0 100644 --- a/doc/perf_tune.md +++ b/doc/perf_tune.md @@ -190,3 +190,112 @@ $ ./FlameGraph/flamegraph.pl out.folded > perf.foo.wasm.svg > > Then you will see a new file named _out.folded.translated_ which contains the translated folded stacks. > All wasm functions are translated to its original names with a prefix like "[Wasm]" + +## 8. Refine the calling processes between host native and wasm application + +In some scenarios, there may be lots of callings between host native and wasm application, e.g. frequent callings to AOT/JIT functions from host native or frequent callings to host native from AOT/JIT functions. It is important to refine these calling processes to speedup them, WAMR provides several methods: + +### 8.1 Refine callings to native APIs registered by `wasm_runtime_register_natives` from AOT code + +When wamrc compiles the wasm file to AOT code, it may generate LLVM IR to call the native API from an AOT function, and if it doesn't know the native API's signature, the generated LLVM IR has to call the runtime API `aot_invoke_native` to invoke the native API, which is a relatively slow way. If developer registers native APIs during execution by calling `wasm_runtime_register_natives` or by `iwasm --native-lib=`, then developer can also register native APIs with the same signatures to the AOT compiler by `wamrc --native-lib=`, so as to let the AOT compiler pre-know the native API's signature, and generate optimized LLVM IR to quickly call to the native API. + +The below sample registers an API `int test_add(int, int)` to the AOT compiler: + +```C +/* test_add.c */ + +#include "wasm_export.h" + +static int +test_add_wrapper(wasm_exec_env_t exec_env, int x, int y) { + return 0; /* empty function is enough */ +} + +#define REG_NATIVE_FUNC(func_name, signature) \ + { #func_name, func_name##_wrapper, signature, NULL } + +static NativeSymbol native_symbols[] = { + REG_NATIVE_FUNC(test_add, "(ii)i") +}; + +uint32_t +get_native_lib(char **p_module_name, NativeSymbol **p_native_symbols) +{ + *p_module_name = "env"; + *p_native_symbols = native_symbols; + return sizeof(native_symbols) / sizeof(NativeSymbol); +} +``` +```bash +# build native lib +gcc -O3 -fPIC -shared -I /core/iwasm/include -o libtest_add.so test_add.c +# register native lib to aot compiler +wamrc --native-lib=./libtest_add.so -o +``` + +> Note: no need to do anything for LLVM JIT since the native APIs must have been registered before execution and JIT compiler already knows the native APIs' signatures. + +### 8.2 Refine callings to native APIs registered by wasm-c-api `wasm_instance_new` from AOT code + +In wasm-c-api mode, when the native APIs are registered by `wasm_instance_new(..., imports, ...)`, developer can use `wamrc --invoke-c-api-import` option to generate the AOT file, which treats the unknown import function as wasm-c-api import function and generates optimized LLVM IR to speedup the calling process. + +> Note: no need to do anything for LLVM JIT since the similar flag has been set to JIT compiler in wasm-c-api `wasm_engine_new` when LLVM JIT is enabled. + +### 8.3 Refine callings to AOT/JIT functions from host native + +Currently by default WAMR runtime has registered many quick AOT/JIT entries to speedup the calling processes to call AOT/JIT functions from host native, as long as developer doesn't disable it by using `cmake -DWAMR_BUILD_QUICK_AOT_ENTRY=0` or setting the compiler macro `WASM_ENABLE_QUICK_AOT_ENTRY` to 0 in the makefile. These quick AOT/JIT entries include: + +1. wasm function contains 0 to 4 arguments and 0 to 1 results, with the type of each argument is i32 or i64 and the type of result is i32, i64 or void. These functions are like: + +```C +// no argument +i32 foo(), i64 foo(), void foo() +// one argument, each argument is i32 or i64 +i32 foo(i32/i64), i64 foo(i32/i64), void(i32/i64) +// two arguments, each argument is i32 or i64 +i32 foo(i32/i64, i32/i64), i64 foo(i32/i64, i32/i64), void(i32/i64, i32/i64) +// three arguments, each argument is i32 or i64 +i32 foo(i32/i64, i32/i64, i32/i64), i64 foo(i32/i64, i32/i64, i32/i64), void(i32/i64, i32/i64, i32/i64) +// four arguments, each argument is i32 or i64 +i32 foo(i32/i64, i32/i64, i32/i64, i32/i64) +i64 foo(i32/i64, i32/i64, i32/i64, i32/i64) +void(i32/i64, i32/i64, i32/i64, i32/i64) +``` + +2. wasm function contains 5 arguments and 0 to 1 results, with the type of each argument is i32 and the type of result is i32, i64 or void. These functions are like: + +```C +i32 foo(i32, i32, i32, i32, i32) +i64 foo(i32, i32, i32, i32, i32) +void foo(i32, i32, i32, i32, i32) +``` + +To speedup the calling processes, developer had better ensure that the signatures of the wasm functions to expose are like above, or add some conversions to achieve it. For example, if a wasm function to call is `f32 foo(f32)`, developer can define a new function `i32 foo1(i32)` like below and export it: +```C +int32 foo1(int32 arg_i32) +{ + float arg_f32 = *(float *)&arg_i32; + float res_f32 = foo(f32); + int32 res_i32 = *(int32 *)&res_i32; + return res_i32; +} +``` +And in the host embedder: +``` + uint32 argv[2]; + float arg_f32 = ...; /* argument to foo */ + float res_f32; + bool ret; + + argv[0] = *(uint32 *)&arg_f32; + func = wasm_runtime_lookup_function(module_inst, "foo1", NULL); + ret = wasm_runtime_call_wasm(exec_env, func, 1, argv); + if (!ret) { + /* handle exception */ + printf("%s\n", wasm_runtime_get_exception(module_inst)); + } + else { + /* the return value is stored in argv[0] */ + res_f32 = *(float *)&argv[0]; + } +``` diff --git a/language-bindings/python/wasm-c-api/tests/test_advanced.py b/language-bindings/python/wasm-c-api/tests/test_advanced.py index 2e1c285ea..706447ab5 100644 --- a/language-bindings/python/wasm-c-api/tests/test_advanced.py +++ b/language-bindings/python/wasm-c-api/tests/test_advanced.py @@ -188,18 +188,6 @@ class AdvancedTestSuite(unittest.TestCase): ffi.wasm_func_call(func, params, results) self.assertEqual(params.data[0].of.f32 * 2, results.data[0].of.f64) - def test_wasm_func_call_wrong_params(self): - export_list = ffi.wasm_vec_to_list(self.exports) - func = ffi.wasm_extern_as_func(export_list[0]) - # make a call - params = ffi.wasm_val_vec_t() - ffi.wasm_val_vec_new_empty(params) - results = ffi.wasm_val_vec_t() - ffi.wasm_val_vec_new_empty(results) - trap = ffi.wasm_func_call(func, params, results) - - self.assertIsNotNullPointer(trap) - def test_wasm_func_call_unlinked(self): ft = ffi.wasm_functype_new_0_0() func = ffi.wasm_func_new(self._wasm_store, ft, callback) @@ -453,26 +441,6 @@ class AdvancedTestSuite(unittest.TestCase): ffi.wasm_memory_data_size(mem) ffi.wasm_memory_delete(mem) - def test_wasm_trap(self): - export_list = ffi.wasm_vec_to_list(self.exports) - func = ffi.wasm_extern_as_func(export_list[0]) - # make a call - params = ffi.wasm_val_vec_t() - ffi.wasm_val_vec_new_empty(params) - results = ffi.wasm_val_vec_t() - ffi.wasm_val_vec_new_empty(results) - - trap = ffi.wasm_func_call(func, params, results) - self.assertIsNotNullPointer(trap) - - message = ffi.wasm_message_t() - ffi.wasm_trap_message(trap, message) - self.assertIsNotNullPointer(c.pointer(message)) - - # not a function internal exception - frame = ffi.wasm_trap_origin(trap) - self.assertIsNullPointer(frame) - @unittest.skipUnless( TEST_WITH_WAMR_BUILD_DUMP_CALL_STACK, "need to enable WAMR_BUILD_DUMP_CALL_STACK", diff --git a/product-mini/README.md b/product-mini/README.md index 22acfeaf4..4a8275618 100644 --- a/product-mini/README.md +++ b/product-mini/README.md @@ -447,12 +447,12 @@ make ## Cosmopolitan Libc Currently, only x86_64 architecture with interpreter modes is supported. -Clone the Cosmopolitan Libc. Setup `cosmocc` as described in [Getting Started](https://github.com/jart/cosmopolitan/#getting-started) being sure to get it into `PATH`. +Setup `cosmocc` as described in [Getting Started](https://github.com/jart/cosmopolitan/#getting-started) being sure to get its `bin` directory into `PATH`. Build iwasm ``` Bash -export CC=cosmocc -export CXX=cosmoc++ +export CC=x86_64-unknown-cosmo-cc +export CXX=x86_64-unknown-cosmo-c++ rm -rf build mkdir build cmake -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=1 -B build diff --git a/product-mini/platforms/cosmopolitan/build_cosmocc.sh b/product-mini/platforms/cosmopolitan/build_cosmocc.sh index b2ce15d33..8d96027e1 100755 --- a/product-mini/platforms/cosmopolitan/build_cosmocc.sh +++ b/product-mini/platforms/cosmopolitan/build_cosmocc.sh @@ -2,8 +2,8 @@ # Copyright (C) 2023 Dylibso. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -export CC=cosmocc -export CXX=cosmoc++ +export CC=x86_64-unknown-cosmo-cc +export CXX=x86_64-unknown-cosmo-c++ rm -rf build mkdir build cmake -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=1 -B build diff --git a/product-mini/platforms/linux-sgx/CMakeLists.txt b/product-mini/platforms/linux-sgx/CMakeLists.txt index 0b2b4afec..81d6244b1 100644 --- a/product-mini/platforms/linux-sgx/CMakeLists.txt +++ b/product-mini/platforms/linux-sgx/CMakeLists.txt @@ -176,3 +176,10 @@ else() OUTPUT_VARIABLE cmdOutput ) endif() + +if (WAMR_BUILD_SPEC_TEST EQUAL 1) + execute_process( + COMMAND bash -c "sed -i -E 's/0x1000000<\\/ReservedMemMaxSize>/0x8000000<\\/ReservedMemMaxSize>/g' ${CMAKE_CURRENT_SOURCE_DIR}/enclave-sample/Enclave/Enclave.config.xml" + OUTPUT_VARIABLE cmdOutput + ) +endif() diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk index ad921157c..9c1aeae4e 100644 --- a/product-mini/platforms/nuttx/wamr.mk +++ b/product-mini/platforms/nuttx/wamr.mk @@ -142,6 +142,12 @@ else CFLAGS += -DWASM_ENABLE_AOT=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_AOT_QUICK_ENTRY),y) +CFLAGS += -DWASM_ENABLE_QUICK_AOT_ENTRY=1 +else +CFLAGS += -DWASM_ENABLE_QUICK_AOT_ENTRY=0 +endif + ifeq ($(CONFIG_INTERPRETERS_WAMR_AOT_WORD_ALIGN_READ),y) CFLAGS += -DWASM_ENABLE_WORD_ALIGN_READ=1 else @@ -192,9 +198,7 @@ CSRCS += utils.c VPATH += $(IWASM_ROOT)/libraries/debug-engine endif -ifeq ($(CONFIG_INTERPRETERS_WAMR_STACK_GUARD_SIZE),) -CFLAGS += -DWASM_STACK_GUARD_SIZE=0 -else +ifneq ($(CONFIG_INTERPRETERS_WAMR_STACK_GUARD_SIZE),) CFLAGS += -DWASM_STACK_GUARD_SIZE=CONFIG_INTERPRETERS_WAMR_STACK_GUARD_SIZE endif @@ -355,6 +359,14 @@ else CFLAGS += -DWASM_ENABLE_REF_TYPES=0 endif +ifeq ($(CONFIG_INTERPRETERS_WAMR_ENABLE_EXCE_HANDLING),y) +CFLAGS += -DWASM_ENABLE_EXCE_HANDLING=1 +CFLAGS += -DWASM_ENABLE_TAGS=1 +else +CFLAGS += -DWASM_ENABLE_EXCE_HANDLING=0 +CFLAGS += -DWASM_ENABLE_TAGS=0 +endif + CFLAGS += -Wno-strict-prototypes -Wno-shadow -Wno-unused-variable CFLAGS += -Wno-int-conversion -Wno-implicit-function-declaration @@ -379,6 +391,7 @@ CSRCS += nuttx_platform.c \ posix_thread.c \ posix_time.c \ posix_sleep.c \ + mremap.c \ mem_alloc.c \ ems_kfc.c \ ems_alloc.c \ @@ -389,6 +402,7 @@ CSRCS += nuttx_platform.c \ bh_hashmap.c \ bh_list.c \ bh_log.c \ + bh_memutils.c \ bh_queue.c \ bh_vector.c \ bh_read_file.c \ @@ -404,6 +418,7 @@ CSRCS += nuttx_platform.c \ ASRCS += $(INVOKE_NATIVE) VPATH += $(SHARED_ROOT)/platform/nuttx +VPATH += $(SHARED_ROOT)/platform/common/memory VPATH += $(SHARED_ROOT)/platform/common/posix VPATH += $(SHARED_ROOT)/platform/common/libc-util VPATH += $(SHARED_ROOT)/mem-alloc diff --git a/samples/basic/build.sh b/samples/basic/build.sh index a0be7e1c7..c1d598a8c 100755 --- a/samples/basic/build.sh +++ b/samples/basic/build.sh @@ -21,7 +21,7 @@ echo "#####################build basic project" cd ${CURR_DIR} mkdir -p cmake_build cd cmake_build -cmake .. +cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BH_VPRINTF=my_vprintf -DWAMR_BH_LOG=my_log make -j ${nproc} if [ $? != 0 ];then echo "BUILD_FAIL basic exit as $?\n" diff --git a/samples/basic/src/main.c b/samples/basic/src/main.c index c35da3179..ca580af33 100644 --- a/samples/basic/src/main.c +++ b/samples/basic/src/main.c @@ -15,6 +15,30 @@ get_pow(int x, int y); int32_t calculate_native(int32_t n, int32_t func1, int32_t func2); +void +my_log(uint32 log_level, const char *file, int line, const char *fmt, ...) +{ + char buf[200]; + snprintf(buf, 200, + log_level == WASM_LOG_LEVEL_VERBOSE ? "[WamrLogger - VERBOSE] %s" + : "[WamrLogger] %s", + fmt); + + va_list ap; + va_start(ap, fmt); + vprintf(buf, ap); + va_end(ap); +} + +int +my_vprintf(const char *format, va_list ap) +{ + /* Print in blue */ + char buf[200]; + snprintf(buf, 200, "\x1b[34m%s\x1b[0m", format); + return vprintf(buf, ap); +} + void print_usage(void) { @@ -95,6 +119,7 @@ main(int argc, char *argv_main[]) printf("Init runtime environment failed.\n"); return -1; } + wasm_runtime_set_log_level(WASM_LOG_LEVEL_VERBOSE); buffer = bh_read_file_to_buffer(wasm_path, &buf_size); @@ -103,7 +128,8 @@ main(int argc, char *argv_main[]) goto fail; } - module = wasm_runtime_load(buffer, buf_size, error_buf, sizeof(error_buf)); + module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf, + sizeof(error_buf)); if (!module) { printf("Load wasm module failed. error: %s\n", error_buf); goto fail; diff --git a/samples/file/README.md b/samples/file/README.md index 8b34719ef..98f0cc3a7 100644 --- a/samples/file/README.md +++ b/samples/file/README.md @@ -5,7 +5,7 @@ This sample can also demonstrate the SGX IPFS (Intel Protected File System), ena ## Preparation -Please install WASI SDK, download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. +Please install WASI SDK, download the [wasi-sdk release](https://github.com/WebAssembly/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. For testing with SGX IPFS, follow the instructions in [the documentation of SGX for WAMR](../../doc/linux_sgx.md#sgx-intel-protected-file-system). ## Build the sample diff --git a/samples/multi-module/CMakeLists.txt b/samples/multi-module/CMakeLists.txt index ee6c98df4..17f4e1bcc 100644 --- a/samples/multi-module/CMakeLists.txt +++ b/samples/multi-module/CMakeLists.txt @@ -132,6 +132,7 @@ endif() # .c -> .wasm ExternalProject_Add(WASM_MODULE SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps + BUILD_ALWAYS TRUE UPDATE_COMMAND "" PATCH_COMMAND "" CONFIGURE_COMMAND ${CMAKE_COMMAND} diff --git a/samples/native-lib/README.md b/samples/native-lib/README.md index 80500ade0..be1cc6e74 100644 --- a/samples/native-lib/README.md +++ b/samples/native-lib/README.md @@ -29,7 +29,7 @@ get_native_lib(char **p_module_name, NativeSymbol **p_native_symbols) ## Preparation -Please install WASI SDK, download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. +Please install WASI SDK, download the [wasi-sdk release](https://github.com/WebAssembly/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. ## Build the sample diff --git a/samples/shared-module/build.sh b/samples/shared-module/build.sh index 9af5b3edd..e6c104745 100755 --- a/samples/shared-module/build.sh +++ b/samples/shared-module/build.sh @@ -21,7 +21,7 @@ echo "##################### build shared-module project" cd ${CURR_DIR} mkdir -p cmake_build cd cmake_build -cmake .. +cmake .. -DCMAKE_BUILD_TYPE=Debug make -j ${nproc} if [ $? != 0 ];then echo "BUILD_FAIL shared-module exit as $?\n" diff --git a/samples/simple/build.sh b/samples/simple/build.sh index 4e8155156..9d9d1874d 100755 --- a/samples/simple/build.sh +++ b/samples/simple/build.sh @@ -17,7 +17,7 @@ APP_LIB_SRC="${APP_FRAMEWORK_DIR}/base/app/*.c ${APP_FRAMEWORK_DIR}/sensor/app/* ${APP_FRAMEWORK_DIR}/connection/app/*.c ${NATIVE_LIBS}/*.c" WASM_APPS=${PWD}/wasm-apps CLEAN= -CM_BUILD_TYPE="-DCMAKE_BUILD_TYPE=Release" +CM_BUILD_TYPE="-DCMAKE_BUILD_TYPE=Debug" CM_TOOLCHAIN="" usage () diff --git a/samples/socket-api/README.md b/samples/socket-api/README.md index a3bc5ac15..911dfb7ab 100644 --- a/samples/socket-api/README.md +++ b/samples/socket-api/README.md @@ -6,7 +6,7 @@ how they communicate with each other. ## Preparation -Please install WASI SDK, download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. +Please install WASI SDK, download the [wasi-sdk release](https://github.com/WebAssembly/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. And install wabt, download the [wabt release](https://github.com/WebAssembly/wabt/releases) and extract the archive to default path `/opt/wabt` ## Build the sample diff --git a/samples/terminate/.gitignore b/samples/terminate/.gitignore new file mode 100644 index 000000000..0fa8a76bd --- /dev/null +++ b/samples/terminate/.gitignore @@ -0,0 +1 @@ +/out/ \ No newline at end of file diff --git a/samples/terminate/CMakeLists.txt b/samples/terminate/CMakeLists.txt new file mode 100644 index 000000000..246b835dd --- /dev/null +++ b/samples/terminate/CMakeLists.txt @@ -0,0 +1,98 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +include(CheckPIESupported) + +project (terminate) + +set (CMAKE_CXX_STANDARD 17) + +################ runtime settings ################ +string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +if (APPLE) + add_definitions(-DBH_PLATFORM_DARWIN) +endif () + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# WAMR features switch + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", +# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + elseif (CMAKE_SIZEOF_VOID_P EQUAL 4) + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + else () + message(SEND_ERROR "Unsupported build target platform!") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Debug) +endif () + +set (WAMR_BUILD_LIBC_WASI 1) +set (WAMR_BUILD_LIB_WASI_THREADS 1) +set (WAMR_BUILD_THREAD_MGR 1) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) + +# fast interpreter +# set (WAMR_BUILD_FAST_INTERP 1) + +# fast-jit +# set (WAMR_BUILD_FAST_JIT 1) + +# llvm jit +# set (WAMR_BUILD_JIT 1) +# set (LLVM_DIR /usr/local/opt/llvm@14/lib/cmake/llvm) + +set (WAMR_BUILD_REF_TYPES 1) + +if (NOT MSVC) + # linker flags + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + endif () + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") + if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") + endif () + endif () +endif () + +# build out vmlib +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +################ application related ################ +include_directories(${CMAKE_CURRENT_LIST_DIR}/src) +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (terminate src/main.c ${UNCOMMON_SHARED_SOURCE}) + +check_pie_supported() +set_target_properties (terminate PROPERTIES POSITION_INDEPENDENT_CODE ON) + +if (APPLE) + target_link_libraries (terminate vmlib -lm -ldl -lpthread ${LLVM_AVAILABLE_LIBS}) +else () + target_link_libraries (terminate vmlib -lm -ldl -lpthread -lrt ${LLVM_AVAILABLE_LIBS}) +endif () diff --git a/samples/terminate/README.md b/samples/terminate/README.md new file mode 100644 index 000000000..89a9c16bc --- /dev/null +++ b/samples/terminate/README.md @@ -0,0 +1,4 @@ +The "terminate" sample project +============================== + +This sample demonstrates wasm_runtime_terminate API. diff --git a/samples/terminate/build.sh b/samples/terminate/build.sh new file mode 100755 index 000000000..4c882e981 --- /dev/null +++ b/samples/terminate/build.sh @@ -0,0 +1,63 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/bash + +CURR_DIR=$PWD +WAMR_DIR=${PWD}/../.. +OUT_DIR=${PWD}/out + +WASM_APPS=${PWD}/wasm-apps + + +rm -rf ${OUT_DIR} +mkdir ${OUT_DIR} +mkdir ${OUT_DIR}/wasm-apps + + +echo "##################### build terminate project" +cd ${CURR_DIR} +mkdir -p cmake_build +cd cmake_build +cmake .. -DCMAKE_BUILD_TYPE=Debug +make -j ${nproc} +if [ $? != 0 ];then + echo "BUILD_FAIL terminate exit as $?\n" + exit 2 +fi + +cp -a terminate ${OUT_DIR} + +printf "\n" + +echo "##################### build wasm apps" + +cd ${WASM_APPS} + +for i in `ls *.wat` +do +APP_SRC="$i" +OUT_FILE=${i%.*}.wasm + +# Note: the CI installs wabt in /opt/wabt +if type wat2wasm; then + WAT2WASM=${WAT2WASM:-wat2wasm} +elif [ -x /opt/wabt/bin/wat2wasm ]; then + WAT2WASM=${WAT2WASM:-/opt/wabt/bin/wat2wasm} +fi + +${WAT2WASM} -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} + +# aot +# wamrc -o ${OUT_DIR}/wasm-apps/${OUT_FILE}.aot ${OUT_DIR}/wasm-apps/${OUT_FILE} +# mv ${OUT_DIR}/wasm-apps/${OUT_FILE}.aot ${OUT_DIR}/wasm-apps/${OUT_FILE} + +if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then + echo "build ${OUT_FILE} success" +else + echo "build ${OUT_FILE} fail" +fi +done +echo "##################### build wasm apps done" diff --git a/samples/terminate/run.sh b/samples/terminate/run.sh new file mode 100755 index 000000000..0a75fea2a --- /dev/null +++ b/samples/terminate/run.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +out/terminate -f out/wasm-apps/testapp.wasm diff --git a/samples/terminate/src/main.c b/samples/terminate/src/main.c new file mode 100644 index 000000000..4885b0b11 --- /dev/null +++ b/samples/terminate/src/main.c @@ -0,0 +1,219 @@ + +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +#include "wasm_export.h" +#include "bh_read_file.h" +#include "bh_getopt.h" + +void +print_usage(void) +{ + fprintf(stdout, "Options:\r\n"); + fprintf(stdout, " -f [path of wasm file] \n"); +} + +static void * +runner_with_sigleton_exec_env(void *vp) +{ + wasm_module_inst_t inst = vp; + bool ok = wasm_runtime_init_thread_env(); + assert(ok); + wasm_application_execute_main(inst, 0, NULL); + wasm_runtime_destroy_thread_env(); + return inst; +} + +static void * +runner_with_spawn_exec_env(void *vp) +{ + wasm_exec_env_t env = vp; + wasm_module_inst_t inst = wasm_runtime_get_module_inst(env); + wasm_function_inst_t func; + bool ok = wasm_runtime_init_thread_env(); + assert(ok); + func = wasm_runtime_lookup_function(inst, "block_forever", NULL); + assert(func != NULL); + wasm_runtime_call_wasm(env, func, 0, NULL); + wasm_runtime_destroy_spawned_exec_env(env); + wasm_runtime_destroy_thread_env(); + return inst; +} + +int +main(int argc, char *argv_main[]) +{ + int exit_code = 1; + static char global_heap_buf[512 * 1024]; + char *buffer; + char error_buf[128]; + int opt; + char *wasm_path = NULL; + int ret; + int pipe_fds[2]; + + const unsigned int N = 4; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst[N]; + pthread_t th[N]; + unsigned int i; + uint32 buf_size, stack_size = 8092, heap_size = 8092; + + for (i = 0; i < N; i++) { + module_inst[i] = NULL; + } + + RuntimeInitArgs init_args; + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + while ((opt = getopt(argc, argv_main, "hf:")) != -1) { + switch (opt) { + case 'f': + wasm_path = optarg; + break; + case 'h': + print_usage(); + return 0; + case '?': + print_usage(); + return 0; + } + } + if (optind == 1) { + print_usage(); + return 0; + } + + memset(&init_args, 0, sizeof(init_args)); + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + if (!wasm_runtime_full_init(&init_args)) { + printf("Init runtime environment failed.\n"); + return -1; + } + + buffer = bh_read_file_to_buffer(wasm_path, &buf_size); + + if (!buffer) { + printf("Open wasm app file [%s] failed.\n", wasm_path); + goto fail; + } + + module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf, + sizeof(error_buf)); + if (!module) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + + /* Ensure that fd_read on FD 0 blocks. */ + ret = pipe(pipe_fds); + if (ret != 0) { + goto fail; + } + wasm_runtime_set_wasi_args_ex(module, NULL, 0, NULL, 0, NULL, 0, NULL, 0, + pipe_fds[0], -1, -1); + + for (i = 0; i < N; i++) { + bool use_wasm_runtime_spawn_exec_env = i / 2 == 0; + wasm_exec_env_t env; + + module_inst[i] = wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)); + + if (!module_inst[i]) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + + /* Note: ensure that module inst has an exec env so that + * it can receive the termination request. + */ + env = wasm_runtime_get_exec_env_singleton(module_inst[i]); + assert(env != NULL); + if (use_wasm_runtime_spawn_exec_env) { + env = wasm_runtime_spawn_exec_env(env); + assert(env != NULL); + } + + if ((i % 2) == 0) { + printf("terminating thread %u before starting\n", i); + wasm_runtime_terminate(module_inst[i]); + } + + if (use_wasm_runtime_spawn_exec_env) { + printf("starting thread %u (spawn_exec_env)\n", i); + ret = pthread_create(&th[i], NULL, runner_with_spawn_exec_env, env); + if (ret != 0) { + wasm_runtime_destroy_spawned_exec_env(env); + goto fail; + } + } + else { + printf("starting thread %u (singleton exec_env)\n", i); + ret = pthread_create(&th[i], NULL, runner_with_sigleton_exec_env, + module_inst[i]); + if (ret != 0) { + goto fail; + } + } + } + + printf("sleeping a bit to ensure that the threads actually started\n"); + sleep(1); + + for (i = 0; i < N; i++) { + if ((i % 2) != 0) { + printf("terminating thread %u\n", i); + wasm_runtime_terminate(module_inst[i]); + } + } + + for (i = 0; i < N; i++) { + printf("joining thread %u\n", i); + void *status; + ret = pthread_join(th[i], &status); + if (ret != 0) { + printf("pthread_join failed for thread %u\n", i); + goto fail; + } + } + + for (i = 0; i < N; i++) { + const char *exception = wasm_runtime_get_exception(module_inst[i]); + if (exception != NULL) { + if (!strstr(exception, "terminated by user")) { + printf("thread %u got an exception: %s (unexpected)\n", i, + exception); + goto fail; + } + printf("thread %u got an exception: %s (expected)\n", i, exception); + } + else { + printf("thread %u got no exception (unexpected)\n", i); + goto fail; + } + } + + exit_code = 0; +fail: + for (i = 0; i < N; i++) { + if (module_inst[i]) + wasm_runtime_deinstantiate(module_inst[i]); + } + if (module) + wasm_runtime_unload(module); + if (buffer) + BH_FREE(buffer); + wasm_runtime_destroy(); + return exit_code; +} diff --git a/samples/terminate/wasm-apps/testapp.wat b/samples/terminate/wasm-apps/testapp.wat new file mode 100644 index 000000000..349535da7 --- /dev/null +++ b/samples/terminate/wasm-apps/testapp.wat @@ -0,0 +1,53 @@ +;; Copyright (C) 2024 YAMAMOTO Takashi +;; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +(module + (func $fd_read (import "wasi_snapshot_preview1" "fd_read") (param i32 i32 i32 i32) (result i32)) + (func $block_forever (export "block_forever") + ;; read from FD 0 + i32.const 100 ;; iov_base + i32.const 200 ;; buffer + i32.store + i32.const 104 ;; iov_len + i32.const 1 + i32.store + i32.const 0 ;; fd 0 + i32.const 100 ;; iov_base + i32.const 1 ;; iov count + i32.const 300 ;; retp (out) + call $fd_read + unreachable + ) + (func (export "_start") + call $block_forever + ) + + ;; a dumb malloc/free implementation + (func (export "malloc") (param i32) (result i32) + local.get 0 + i32.const 65535 + i32.add + i32.const 65536 + i32.div_u + memory.grow + local.set 0 + local.get 0 + i32.const -1 + i32.eq + if + i32.const 0 + return + end + local.get 0 + i32.const 65536 + i32.mul + ) + (func (export "free") (param i32)) + + (memory (export "memory") 1) + + ;; fake globals to make wasm_set_aux_stack happy + (global (export "__heap_base") i32 (i32.const 0x10000)) + (global (export "__data_end") i32 (i32.const 0x10000)) + (global (mut i32) (i32.const 0x10000)) +) diff --git a/samples/wasi-threads/wasm-apps/wasi_thread_start.h b/samples/wasi-threads/wasm-apps/wasi_thread_start.h index 2427fd2b9..5eae2938d 100644 --- a/samples/wasi-threads/wasm-apps/wasi_thread_start.h +++ b/samples/wasi-threads/wasm-apps/wasi_thread_start.h @@ -9,6 +9,7 @@ /* See https://github.com/WebAssembly/wasi-threads#design-choice-thread-ids */ #define ASSERT_VALID_TID(TID) \ + (void)TID; \ assert(TID >= 1 && TID <= 0x1FFFFFFF && "Invalid thread ID") typedef struct { diff --git a/tests/benchmarks/coremark/README.md b/tests/benchmarks/coremark/README.md index 4e88069f8..5b874e988 100644 --- a/tests/benchmarks/coremark/README.md +++ b/tests/benchmarks/coremark/README.md @@ -10,7 +10,7 @@ Please build iwasm and wamrc, refer to: - [Build iwasm on Linux](../../../doc/build_wamr.md#linux), or [Build iwasm on MacOS](../../../doc/build_wamr.md#macos) - [Build wamrc AOT compiler](../../../README.md#build-wamrc-aot-compiler) -And install WASI SDK, please download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. +And install WASI SDK, please download the [wasi-sdk release](https://github.com/WebAssembly/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. And then run `./build.sh` to build the source code, file `coremark.exe`, `coremark.wasm` and `coremark.aot` will be generated. diff --git a/tests/benchmarks/polybench/README.md b/tests/benchmarks/polybench/README.md index d8b3db961..7b6623f22 100644 --- a/tests/benchmarks/polybench/README.md +++ b/tests/benchmarks/polybench/README.md @@ -10,7 +10,7 @@ Please build iwasm and wamrc, refer to: - [Build iwasm on Linux](../../../doc/build_wamr.md#linux), or [Build iwasm on MacOS](../../../doc/build_wamr.md#macos) - [Build wamrc AOT compiler](../../../README.md#build-wamrc-aot-compiler) -And install WASI SDK, please download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. +And install WASI SDK, please download the [wasi-sdk release](https://github.com/WebAssembly/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. And then run `./build.sh` to build the source code, the folder `out` will be created and files will be generated under it. diff --git a/tests/benchmarks/sightglass/README.md b/tests/benchmarks/sightglass/README.md index ff34c7d70..3f54fda1b 100644 --- a/tests/benchmarks/sightglass/README.md +++ b/tests/benchmarks/sightglass/README.md @@ -10,7 +10,7 @@ Please build iwasm and wamrc, refer to: - [Build iwasm on Linux](../../../doc/build_wamr.md#linux), or [Build iwasm on MacOS](../../../doc/build_wamr.md#macos) - [Build wamrc AOT compiler](../../../README.md#build-wamrc-aot-compiler) -And install WASI SDK, please download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. +And install WASI SDK, please download the [wasi-sdk release](https://github.com/WebAssembly/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`. And then run `./build.sh` to build the source code, the folder `out` will be created and files will be generated under it. diff --git a/tests/wamr-test-suites/spec-test-script/all.py b/tests/wamr-test-suites/spec-test-script/all.py index 551a3176c..7aa47cf41 100644 --- a/tests/wamr-test-suites/spec-test-script/all.py +++ b/tests/wamr-test-suites/spec-test-script/all.py @@ -47,6 +47,7 @@ IWASM_CMD = get_iwasm_cmd(PLATFORM_NAME) IWASM_SGX_CMD = "../../../product-mini/platforms/linux-sgx/enclave-sample/iwasm" IWASM_QEMU_CMD = "iwasm" SPEC_TEST_DIR = "spec/test/core" +EXCE_HANDLING_DIR = "exception-handling/test/core" WAST2WASM_CMD = exe_file_path("./wabt/out/gcc/Release/wat2wasm") SPEC_INTERPRETER_CMD = "spec/interpreter/wasm" WAMRC_CMD = "../../../wamr-compiler/build/wamrc" @@ -78,8 +79,10 @@ def ignore_the_case( simd_flag=False, gc_flag=False, xip_flag=False, + eh_flag=False, qemu_flag=False, ): + if case_name in ["comments", "inline-module", "names"]: return True @@ -126,7 +129,7 @@ def ignore_the_case( return False -def preflight_check(aot_flag): +def preflight_check(aot_flag, eh_flag): if not pathlib.Path(SPEC_TEST_DIR).resolve().exists(): print(f"Can not find {SPEC_TEST_DIR}") return False @@ -139,6 +142,10 @@ def preflight_check(aot_flag): print(f"Can not find {WAMRC_CMD}") return False + if eh_flag and not pathlib.Path(EXCE_HANDLING_DIR).resolve().exists(): + print(f"Can not find {EXCE_HANDLING_DIR}") + return False + return True @@ -151,6 +158,7 @@ def test_case( multi_thread_flag=False, simd_flag=False, xip_flag=False, + eh_flag=False, clean_up_flag=True, verbose_flag=True, gc_flag=False, @@ -195,6 +203,9 @@ def test_case( if xip_flag: CMD.append("--xip") + if eh_flag: + CMD.append("--eh") + if qemu_flag: CMD.append("--qemu") CMD.append("--qemu-firmware") @@ -268,6 +279,7 @@ def test_suite( multi_thread_flag=False, simd_flag=False, xip_flag=False, + eh_flag=False, clean_up_flag=True, verbose_flag=True, gc_flag=False, @@ -291,6 +303,15 @@ def test_suite( gc_case_list = sorted(suite_path.glob("gc/*.wast")) case_list.extend(gc_case_list) + if eh_flag: + eh_path = pathlib.Path(EXCE_HANDLING_DIR).resolve() + if not eh_path.exists(): + print(f"can not find spec test cases at {eh_path}") + return False + eh_case_list = sorted(eh_path.glob("*.wast")) + eh_case_list_include = [test for test in eh_case_list if test.stem in ["throw", "tag", "try_catch", "rethrow", "try_delegate"]] + case_list.extend(eh_case_list_include) + # ignore based on command line options filtered_case_list = [] for case_path in case_list: @@ -305,6 +326,7 @@ def test_suite( simd_flag, gc_flag, xip_flag, + eh_flag, qemu_flag, ): filtered_case_list.append(case_path) @@ -331,6 +353,7 @@ def test_suite( multi_thread_flag, simd_flag, xip_flag, + eh_flag, clean_up_flag, verbose_flag, gc_flag, @@ -369,6 +392,7 @@ def test_suite( multi_thread_flag, simd_flag, xip_flag, + eh_flag, clean_up_flag, verbose_flag, gc_flag, @@ -428,6 +452,14 @@ def main(): dest="xip_flag", help="Running with the XIP feature", ) + # added to support WASM_ENABLE_EXCE_HANDLING + parser.add_argument( + "-e", + action="store_true", + default=False, + dest="eh_flag", + help="Running with the exception-handling feature", + ) parser.add_argument( "-t", action="store_true", @@ -508,7 +540,7 @@ def main(): if options.target == "x86_32": options.target = "i386" - if not preflight_check(options.aot_flag): + if not preflight_check(options.aot_flag, options.eh_flag): return False if not options.cases: @@ -527,6 +559,7 @@ def main(): options.multi_thread_flag, options.simd_flag, options.xip_flag, + options.eh_flag, options.clean_up_flag, options.verbose_flag, options.gc_flag, @@ -552,6 +585,7 @@ def main(): options.multi_thread_flag, options.simd_flag, options.xip_flag, + options.eh_flag, options.clean_up_flag, options.verbose_flag, options.gc_flag, diff --git a/tests/wamr-test-suites/spec-test-script/exception_handling.patch b/tests/wamr-test-suites/spec-test-script/exception_handling.patch new file mode 100644 index 000000000..0c9e8d40f --- /dev/null +++ b/tests/wamr-test-suites/spec-test-script/exception_handling.patch @@ -0,0 +1,20 @@ +diff --git a/test/core/try_catch.wast b/test/core/try_catch.wast +index 2a0e9ff6..f243489d 100644 +--- a/test/core/try_catch.wast ++++ b/test/core/try_catch.wast +@@ -203,7 +203,6 @@ + + (assert_return (invoke "catch-param-i32" (i32.const 5)) (i32.const 5)) + +-(assert_return (invoke "catch-imported") (i32.const 2)) + + (assert_return (invoke "catchless-try" (i32.const 0)) (i32.const 0)) + (assert_return (invoke "catchless-try" (i32.const 1)) (i32.const 1)) +@@ -231,7 +230,6 @@ + ) + ) + +-(assert_return (invoke "imported-mismatch") (i32.const 3)) + + (assert_malformed + (module quote "(module (func (catch_all)))") diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index dcc0c3361..60d4607e9 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -301,6 +301,9 @@ parser.add_argument('--simd', default=False, action='store_true', parser.add_argument('--xip', default=False, action='store_true', help="Enable XIP") +parser.add_argument('--eh', default=False, action='store_true', + help="Enable Exception Handling") + parser.add_argument('--multi-module', default=False, action='store_true', help="Enable Multi-thread") @@ -762,6 +765,13 @@ def test_assert(r, opts, mode, cmd, expected): if o.find(e) >= 0 or e.find(o) >= 0: return True + # wasm-exception thrown out of function call, not a trap + if mode=='wasmexception': + o = re.sub('^Exception: ', '', out) + e = re.sub('^Exception: ', '', expected) + if o.find(e) >= 0 or e.find(o) >= 0: + return True + ## 0x9:i32,-0x1:i32 -> ['0x9:i32', '-0x1:i32'] expected_list = re.split(',', expected) out_list = re.split(',', out) @@ -987,6 +997,42 @@ def test_assert_exhaustion(r,opts,form): expected = "Exception: %s\n" % m.group(3) test_assert(r, opts, "exhaustion", "%s %s" % (func, " ".join(args)), expected) + +# added to support WASM_ENABLE_EXCE_HANDLING +def test_assert_wasmexception(r,opts,form): + # params + + # ^ + # \(assert_exception\s+ + # \(invoke\s+"([^"]+)"\s+ + # (\(.*\))\s* + # () + # \)\s* + # \)\s* + # $ + m = re.search('^\(assert_exception\s+\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*\)\s*$', form) + if not m: + # no params + + # ^ + # \(assert_exception\s+ + # \(invoke\s+"([^"]+)"\s* + # () + # \)\s* + # \)\s* + # $ + m = re.search('^\(assert_exception\s+\(invoke\s+"([^"]+)"\s*()\)\s*\)\s*$', form) + if not m: + raise Exception("unparsed assert_exception: '%s'" % form) + func = m.group(1) # function name + if m.group(2) == '': # arguments + args = [] + else: + args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])] + + expected = "Exception: uncaught wasm exception\n" + test_assert(r, opts, "wasmexception", "%s %s" % (func, " ".join(args)), expected) + def do_invoke(r, opts, form): # params m = re.search('^\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*$', form) @@ -1025,6 +1071,8 @@ def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts): # default arguments if opts.gc: cmd = [opts.wast2wasm, "-u", "-d", wast_tempfile, "-o", wasm_tempfile] + elif opts.eh: + cmd = [opts.wast2wasm, "--enable-thread", "--no-check", "--enable-exceptions", "--enable-tail-call", wast_tempfile, "-o", wasm_tempfile ] else: cmd = [opts.wast2wasm, "--enable-thread", "--no-check", wast_tempfile, "-o", wasm_tempfile ] @@ -1236,6 +1284,8 @@ if __name__ == "__main__": test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r) elif re.match("^\(assert_exhaustion\\b.*", form): test_assert_exhaustion(r, opts, form) + elif re.match("^\(assert_exception\\b.*", form): + test_assert_wasmexception(r, opts, form) elif re.match("^\(assert_unlinkable\\b.*", form): test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile if test_aot else None, opts, r, False) elif re.match("^\(assert_malformed\\b.*", form): diff --git a/tests/wamr-test-suites/test_wamr.sh b/tests/wamr-test-suites/test_wamr.sh index 76b235d49..7f41fc43d 100755 --- a/tests/wamr-test-suites/test_wamr.sh +++ b/tests/wamr-test-suites/test_wamr.sh @@ -24,6 +24,7 @@ function help() echo "-S enable SIMD feature" echo "-G enable GC feature" echo "-X enable XIP feature" + echo "-e enable exception handling" echo "-x test SGX" echo "-w enable WASI threads" echo "-b use the wabt binary release package instead of compiling from the source code" @@ -50,6 +51,7 @@ COLLECT_CODE_COVERAGE=0 ENABLE_SIMD=0 ENABLE_GC=0 ENABLE_XIP=0 +ENABLE_EH=0 ENABLE_DEBUG_VERSION=0 ENABLE_GC_HEAP_VERIFY=0 #unit test case arrary @@ -70,7 +72,7 @@ WASI_TESTSUITE_COMMIT="ee807fc551978490bf1c277059aabfa1e589a6c2" TARGET_LIST=("AARCH64" "AARCH64_VFP" "ARMV7" "ARMV7_VFP" "THUMBV7" "THUMBV7_VFP" \ "RISCV32" "RISCV32_ILP32F" "RISCV32_ILP32D" "RISCV64" "RISCV64_LP64F" "RISCV64_LP64D") -while getopts ":s:cabgvt:m:MCpSXxwPGQF:j:T:" opt +while getopts ":s:cabgvt:m:MCpSXexwPGQF:j:T:" opt do OPT_PARSED="TRUE" case $opt in @@ -119,7 +121,7 @@ do ;; m) echo "set compile target of wamr" ${OPTARG} - TARGET=${OPTARG^^} # set target to uppercase if input x86_32 or x86_64 --> X86_32 and X86_64 + TARGET=$(echo "$OPTARG" | tr '[a-z]' '[A-Z]') # set target to uppercase if input x86_32 or x86_64 --> X86_32 and X86_64 ;; w) echo "enable WASI threads" @@ -145,6 +147,10 @@ do echo "enable XIP feature" ENABLE_XIP=1 ;; + e) + echo "enable exception handling feature" + ENABLE_EH=1 + ;; x) echo "test SGX" SGX_OPT="--sgx" @@ -425,6 +431,26 @@ function spec_test() git apply ../../spec-test-script/thread_proposal_fix_atomic_case.patch fi + if [ ${ENABLE_EH} == 1 ]; then + echo "checkout exception-handling test cases" + popd + if [ ! -d "exception-handling" ];then + echo "exception-handling not exist, clone it from github" + git clone -b master --single-branch https://github.com/WebAssembly/exception-handling + fi + pushd exception-handling + + # restore and clean everything + git reset --hard 51c721661b671bb7dc4b3a3acb9e079b49778d36 + + if [[ ${ENABLE_MULTI_MODULE} == 0 ]]; then + git apply ../../spec-test-script/exception_handling.patch + fi + + popd + echo $(pwd) + fi + # update GC cases if [[ ${ENABLE_GC} == 1 ]]; then echo "checkout spec for GC proposal" @@ -463,6 +489,10 @@ function spec_test() fi fi + if [[ 1 == ${ENABLE_EH} ]]; then + ARGS_FOR_SPEC_TEST+="-e " + fi + # sgx only enable in interp mode and aot mode if [[ ${SGX_OPT} == "--sgx" ]];then if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' || $1 == 'fast-jit' ]]; then @@ -827,6 +857,10 @@ function trigger() EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_WASI_THREADS=1" fi + if [[ ${ENABLE_EH} == 1 ]]; then + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_EXCE_HANDLING=1" + EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_TAIL_CALL=1" + fi echo "SANITIZER IS" $WAMR_BUILD_SANITIZER if [[ "$WAMR_BUILD_SANITIZER" == "ubsan" ]]; then diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 4e5b76f86..84e8b524c 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -58,25 +58,39 @@ if (DEFINED WAMR_BUILD_AOT_FUNC_PREFIX) add_definitions(-DAOT_FUNC_PREFIX="${WAMR_BUILD_AOT_FUNC_PREFIX}") endif () -# Set WAMR_BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" if (NOT WAMR_BUILD_TARGET) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - # Build as X86_64 by default in 64-bit platform + string(TOLOWER "${CMAKE_HOST_SYSTEM_PROCESSOR}" HOST_SYSTEM_PROCESSOR) + if (${HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64") set (WAMR_BUILD_TARGET "X86_64") - else () - # Build as X86_32 by default in 32-bit platform + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "i686") set (WAMR_BUILD_TARGET "X86_32") - endif () + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "amd64") + set (WAMR_BUILD_TARGET "AMD_64") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "aarch64" + OR ${HOST_SYSTEM_PROCESSOR} STREQUAL "arm64") + set (WAMR_BUILD_TARGET "AARCH64") + elseif (${HOST_SYSTEM_PROCESSOR} MATCHES "arm.*") + message(STATUS "Assuming ${CMAKE_HOST_SYSTEM_PROCESSOR} as ARM_32") + set (WAMR_BUILD_TARGET "ARM_32") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "mips") + set (WAMR_BUILD_TARGET "MIPS_32") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "xtensa") + set (WAMR_BUILD_TARGET "XTENSA_32") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "riscv64") + set (WAMR_BUILD_TARGET "RISCV64") + elseif (${HOST_SYSTEM_PROCESSOR} STREQUAL "riscv") + message(STATUS "Assuming ${CMAKE_HOST_SYSTEM_PROCESSOR} as RISCV32") + set (WAMR_BUILD_TARGET "RISCV32") + else () + message (FATAL_ERROR "Unsupported CMAKE_HOST_SYSTEM_PROCESSOR " + "${CMAKE_HOST_SYSTEM_PROCESSOR}") + endif() + if (WAMR_BUILD_PLATFORM STREQUAL "windows") if (("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")) set (WAMR_BUILD_TARGET "X86_32") endif() - elseif (WAMR_BUILD_PLATFORM STREQUAL "darwin") - if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64") - set (WAMR_BUILD_TARGET "AARCH64") - endif () - endif() + endif () endif () string(TOUPPER ${WAMR_BUILD_TARGET} WAMR_BUILD_TARGET) diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index f2e5efafd..17c19143c 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -627,8 +627,10 @@ main(int argc, char *argv[]) goto fail1; } - if (get_package_type(wasm_file, wasm_file_size) != Wasm_Module_Bytecode) { - printf("Invalid file type: expected wasm file but got other\n"); + if (wasm_file_size >= 4 /* length of MAGIC NUMBER */ + && get_package_type(wasm_file, wasm_file_size) + != Wasm_Module_Bytecode) { + printf("Invalid wasm file: magic header not detected\n"); goto fail2; } diff --git a/wamr-sdk/README.md b/wamr-sdk/README.md index 14b172e02..fd926af86 100644 --- a/wamr-sdk/README.md +++ b/wamr-sdk/README.md @@ -8,7 +8,7 @@ Usually there are two tasks for integrating the WAMR into a particular project: The **[WAMR SDK](./wamr-sdk)** tools is helpful to finish the two tasks quickly. It supports menu configuration for selecting WAMR components and builds the WAMR to a SDK package that includes **runtime SDK** and **APP SDK**. The runtime SDK is used for building the native application and the APP SDK should be shipped to WASM application developers. -**Note**: [WASI-SDK](https://github.com/CraneStation/wasi-sdk/releases) version 7 and above should be installed before building the WAMR SDK. +**Note**: [WASI-SDK](https://github.com/WebAssembly/wasi-sdk/releases) version 7 and above should be installed before building the WAMR SDK.