Merge pull request #2017 from bytecodealliance/main

Merge branch main into dev/exce_handling
This commit is contained in:
Wenyong Huang 2023-03-09 14:41:01 +08:00 committed by GitHub
commit 9a77f1ab44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
292 changed files with 11006 additions and 3103 deletions

View File

@ -12,7 +12,7 @@ ENV TZ=Asian/Shanghai
# hadolint ignore=DL3008 # hadolint ignore=DL3008
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y apt-transport-https apt-utils build-essential \ && apt-get install -y apt-transport-https apt-utils build-essential \
ca-certificates curl g++-multilib git gnupg \ ca-certificates ccache curl g++-multilib git gnupg \
libgcc-9-dev lib32gcc-9-dev lsb-release \ libgcc-9-dev lib32gcc-9-dev lsb-release \
ninja-build ocaml ocamlbuild python2.7 \ ninja-build ocaml ocamlbuild python2.7 \
software-properties-common tree tzdata \ software-properties-common tree tzdata \
@ -20,6 +20,15 @@ RUN apt-get update \
&& apt-get clean -y \ && apt-get clean -y \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
#
# binaryen
ARG BINARYEN_VER=111
WORKDIR /opt
RUN wget -c --progress=dot:giga https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VER}/binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \
&& tar xf binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \
&& ln -sf /opt/binaryen-version_111 /opt/binaryen \
&& rm binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz
# #
# CMAKE (https://apt.kitware.com/) # CMAKE (https://apt.kitware.com/)
SHELL ["/bin/bash", "-o", "pipefail", "-c"] SHELL ["/bin/bash", "-o", "pipefail", "-c"]
@ -31,25 +40,26 @@ RUN wget --progress=dot:giga -O - https://apt.kitware.com/keys/kitware-archive-l
&& apt-get install -y kitware-archive-keyring --no-install-recommends \ && apt-get install -y kitware-archive-keyring --no-install-recommends \
&& apt-get install -y cmake --no-install-recommends \ && apt-get install -y cmake --no-install-recommends \
&& apt-get clean -y \ && apt-get clean -y \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# #
# install emsdk # install emsdk
WORKDIR /opt WORKDIR /opt
RUN git clone https://github.com/emscripten-core/emsdk.git RUN git clone https://github.com/emscripten-core/emsdk.git
ARG EMSDK_VER=3.0.0
WORKDIR /opt/emsdk WORKDIR /opt/emsdk
RUN git pull \ RUN git pull \
&& ./emsdk install 2.0.26 \ && ./emsdk install ${EMSDK_VER} \
&& ./emsdk activate 2.0.26 \ && ./emsdk activate ${EMSDK_VER} \
&& echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc && echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc
# #
# install wasi-sdk # install wasi-sdk
ARG WASI_SDK_VER=16 ARG WASI_SDK_VER=19
RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt \ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt \
&& tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \ && tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \
&& ln -fs /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \ && ln -sf /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \
&& rm /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz && rm /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz
# #
@ -57,29 +67,29 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases
ARG WABT_VER=1.0.29 ARG WABT_VER=1.0.29
RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -P /opt \ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -P /opt \
&& tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \ && tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \
&& ln -fs /opt/wabt-${WABT_VER} /opt/wabt \ && ln -sf /opt/wabt-${WABT_VER} /opt/wabt \
&& rm /opt/wabt-${WABT_VER}-ubuntu.tar.gz && rm /opt/wabt-${WABT_VER}-ubuntu.tar.gz
# #
# install bazelisk # install bazelisk
ARG BAZELISK_VER=1.12.0 ARG BAZELISK_VER=1.12.0
RUN mkdir /opt/bazelisk \ RUN mkdir /opt/bazelisk \
&& wget -c --progress=dot:giga https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -P /opt/bazelisk \ && wget -c --progress=dot:giga https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -P /opt/bazelisk \
&& chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \ && chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \
&& ln -fs /opt/bazelisk/bazelisk-linux-amd64 /opt/bazelisk/bazel && ln -fs /opt/bazelisk/bazelisk-linux-amd64 /opt/bazelisk/bazel
# #
# install clang+llvm # install clang+llvm
ARG LLVM_VER=14
RUN apt-get purge -y clang-10 llvm-10 && apt autoremove -y
WORKDIR /etc/apt/apt.conf.d WORKDIR /etc/apt/apt.conf.d
RUN touch 99verfiy-peer.conf \ RUN touch 99verfiy-peer.conf \
&& echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf && echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf
WORKDIR /tmp WORKDIR /tmp
RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \ RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
&& chmod a+x ./llvm.sh \ && chmod a+x ./llvm.sh \
&& /tmp/llvm.sh 12 all \ && ./llvm.sh ${LLVM_VER} all
&& ln -sf /usr/bin/clang-format-12 /usr/bin/clang-format \
&& rm -rf /tmp/*
# #
# [Optional] # [Optional]
@ -96,17 +106,28 @@ RUN apt-get update \
# Install required python packages # Install required python packages
# hadolint ignore=DL3013 # hadolint ignore=DL3013
RUN python3 -m pip install --no-cache-dir --upgrade pip \ RUN python3 -m pip install --no-cache-dir --upgrade pip \
&& pip3 install --no-cache-dir --user black nose pycparser pylint && pip3 install --no-cache-dir black nose pycparser pylint
# set path, PS and clean up #
ENV PATH "/opt/bazelisk:/opt/clang-llvm/bin:${PATH}" # Install github-cli. It doens't work as a feature of devcontainer.json
RUN echo "export PATH=/opt/bazelisk:/opt/clang-llvm/bin:${PATH}" >> /root/.bashrc \ RUN cd /tmp \
&& printf "%s\n" "PS1='\n[ \u@wamr-dev-docker \W ]\n$ '" >> /root/.bashrc \ && wget https://github.com/cli/cli/releases/download/v2.20.2/gh_2.20.2_linux_amd64.deb \
&& dpkg -i gh_2.20.2_linux_amd64.deb
#
# Install NodeJS
RUN curl -fsSL https://deb.nodesource.com/setup_19.x | bash -
RUN apt-get install -y nodejs
# set path
ENV PATH="/opt/bazelisk:/usr/lib/llvm-${LLVM_VER}/bin:${PATH}"
ENV CC=/usr/lib/llvm-${LLVM_VER}/bin/clang CXX=/usr/lib/llvm-${LLVM_VER}/bin/clang++
RUN printf "%s\n" "PS1='\n[ \u@wamr-dev-docker \W ]\n$ '" >> /root/.bashrc \
&& apt-get autoremove -y \ && apt-get autoremove -y \
&& apt-get clean -y \ && apt-get clean -y \
&& rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/apt/lists/* \
&& rm -rf /tmp/* && rm -rf /tmp/*
# set workdir when container run # set workdir when container run
VOLUME /workspace VOLUME /workspaces
WORKDIR /workspace WORKDIR /workspaces

View File

@ -1,6 +1,5 @@
// Copyright (C) 2019 Intel Corporation. All rights reserved. // Copyright (C) 2019 Intel Corporation. All rights reserved.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp // https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp
{ {
@ -10,7 +9,12 @@
// Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04 // Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04
// Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon // Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon
"args": { "args": {
"VARIANT": "ubuntu-20.04" "BINARYEN_VER": "111",
"EMSDK_VER": "3.0.0",
"LLVM_VER": "15",
"VARIANT": "ubuntu-20.04",
"WASI_SDK_VER": "19",
"WABT_VER": "1.0.31"
} }
}, },
"runArgs": [ "runArgs": [
@ -27,12 +31,10 @@
// Add the IDs of extensions you want installed when the container is created. // Add the IDs of extensions you want installed when the container is created.
"extensions": [ "extensions": [
"dtsvet.vscode-wasm", "dtsvet.vscode-wasm",
"esbenp.prettier-vscode", "llvm-vs-code-extensions.vscode-clangd",
"ms-python.python", "ms-python.python",
"ms-python.vscode-pylance", "ms-python.vscode-pylance",
"ms-vscode.cmake-tools", "ms-vscode.cmake-tools",
"ms-vscode.cpptools",
"twxs.cmake"
] ]
} }
}, },

View File

@ -36,7 +36,7 @@ jobs:
- name: generate iwasm binary release - name: generate iwasm binary release
run: | run: |
cmake -S . -B build \ cmake -S . -B build \
-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 \ -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 \
-DWAMR_BUILD_CUSTOM_NAME_SECTION=0 \ -DWAMR_BUILD_CUSTOM_NAME_SECTION=0 \
-DWAMR_BUILD_DEBUG_INTERP=0 \ -DWAMR_BUILD_DEBUG_INTERP=0 \
-DWAMR_BUILD_DEBUG_AOT=0 \ -DWAMR_BUILD_DEBUG_AOT=0 \

View File

@ -5,23 +5,46 @@ name: Reusable workflow-build_llvm_libraries
on: on:
workflow_call: workflow_call:
inputs: inputs:
runs-on: os:
required: true required: true
type: string type: string
arch:
required: true
type: string
outputs:
cache_key:
description: "A cached key of LLVM libraries"
value: ${{ jobs.build_llvm_libraries.outputs.key}}
jobs: jobs:
build_llvm_libraries: build_llvm_libraries:
runs-on: ${{ matrix.os }} runs-on: ${{ inputs.os }}
strategy: outputs:
matrix: key: ${{ steps.create_lib_cache_key.outputs.key}}
os: ${{ fromJson(inputs.runs-on) }}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: install dependencies
run: /usr/bin/env python3 -m pip install -r requirements.txt
working-directory: build-scripts
- name: retrive the last commit ID
id: get_last_commit
run: echo "last_commit=$(GH_TOKEN=${{ secrets.GITHUB_TOKEN }} /usr/bin/env python3 ./build_llvm.py --llvm-ver)" >> $GITHUB_OUTPUT
working-directory: build-scripts
# Bump the prefix number to evict all previous caches and
# enforce a clean build, in the unlikely case that some
# weird build error occur and llvm/build becomes a potential
# suspect.
- name: form the cache key of libraries
id: create_lib_cache_key
run: echo "key=0-llvm-libraries-${{ inputs.os }}-${{ inputs.arch }}-${{ steps.get_last_commit.outputs.last_commit }}" >> $GITHUB_OUTPUT
- name: Cache LLVM libraries - name: Cache LLVM libraries
id: cache_llvm id: retrieve_llvm_libs
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
@ -30,10 +53,39 @@ jobs:
./core/deps/llvm/build/lib ./core/deps/llvm/build/lib
./core/deps/llvm/build/libexec ./core/deps/llvm/build/libexec
./core/deps/llvm/build/share ./core/deps/llvm/build/share
key: ${{ matrix.os }}-build-llvm_libraries_ex key: ${{ steps.create_lib_cache_key.outputs.key}}
- name: Build llvm - uses: actions/cache@v3
id: build_llvm with:
if: ${{ steps.cache_llvm.outputs.cache-hit != 'true' }} path: ~/.ccache
run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }}
restore-keys: |
0-ccache-${{ inputs.os }}
if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && inputs.os == 'ubuntu-20.04'
- uses: actions/cache@v3
with:
path: ~/.cache/ccache
key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }}
restore-keys: |
0-ccache-${{ inputs.os }}
if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && inputs.os == 'ubuntu-22.04'
- run: sudo apt install -y ccache ninja-build
if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'ubuntu')
- uses: actions/cache@v3
with:
path: ~/Library/Caches/ccache
key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }}
restore-keys: |
0-ccache-${{ inputs.os }}
if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'macos')
- run: brew install ccache ninja
if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'macos')
- name: Build LLVM libraries
if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
run: /usr/bin/env python3 ./build_llvm.py --arch ${{ inputs.arch }}
working-directory: build-scripts working-directory: build-scripts

View File

@ -32,11 +32,14 @@ jobs:
working-directory: test-tools/wamr-ide/VSCode-Extension working-directory: test-tools/wamr-ide/VSCode-Extension
- name: generate wamr ide vscode extension - name: generate wamr ide vscode extension
env:
credentials: ${{ secrets.TOKEN }}
run: | run: |
npm install -g vsce npm install -g vsce
rm -rf node_modules rm -rf node_modules
npm install npm install
vsce package vsce package
vsce publish -p ${{ secrets.TOKEN }}
working-directory: test-tools/wamr-ide/VSCode-Extension working-directory: test-tools/wamr-ide/VSCode-Extension
- name: compress the vscode extension - name: compress the vscode extension

View File

@ -15,7 +15,7 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
complinace_job: compliance_job:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout

View File

@ -53,33 +53,47 @@ env:
FAST_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" FAST_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
LLVM_LAZY_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1" LLVM_LAZY_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0" LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
# LLVM MULTI_TIER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
# For Spec Test # For Spec Test
DEFAULT_TEST_OPTIONS: "-s spec -b -P" DEFAULT_TEST_OPTIONS: "-s spec -b -P"
MULTI_MODULES_TEST_OPTIONS: "-s spec -b -M -P" MULTI_MODULES_TEST_OPTIONS: "-s spec -b -M -P"
SIMD_TEST_OPTIONS: "-s spec -b -S -P" SIMD_TEST_OPTIONS: "-s spec -b -S -P"
THREADS_TEST_OPTIONS: "-s spec -b -p -P" THREADS_TEST_OPTIONS: "-s spec -b -p -P"
X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P" X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P"
WASI_TEST_OPTIONS: "-s wasi_certification -w"
jobs: jobs:
build_llvm_libraries: build_llvm_libraries_on_ubuntu_2004:
uses: ./.github/workflows/build_llvm_libraries.yml uses: ./.github/workflows/build_llvm_libraries.yml
with: with:
runs-on: "['ubuntu-20.04', 'ubuntu-22.04']" os: "ubuntu-20.04"
arch: "X86"
build_llvm_libraries_on_ubuntu_2204:
uses: ./.github/workflows/build_llvm_libraries.yml
with:
os: "ubuntu-22.04"
arch: "X86"
build_wamrc: build_wamrc:
needs: [build_llvm_libraries] needs:
[build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2204]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ubuntu-20.04, ubuntu-22.04] include:
- os: ubuntu-20.04
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}
- os: ubuntu-22.04
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
# since jobs.id can't contain the dot character
# it is hard to use `format` to assemble the cache key
- name: Get LLVM libraries - name: Get LLVM libraries
id: cache_llvm id: retrieve_llvm_libs
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
@ -88,10 +102,10 @@ jobs:
./core/deps/llvm/build/lib ./core/deps/llvm/build/lib
./core/deps/llvm/build/libexec ./core/deps/llvm/build/libexec
./core/deps/llvm/build/share ./core/deps/llvm/build/share
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} key: ${{ matrix.llvm_cache_key }}
- name: Quit if cache miss - name: Quit if cache miss
if: steps.cache_llvm.outputs.cache-hit != 'true' if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
run: echo "::error::can not get prebuilt llvm libraries" && exit 1 run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: Build wamrc - name: Build wamrc
@ -102,7 +116,8 @@ jobs:
working-directory: wamr-compiler working-directory: wamr-compiler
build_iwasm: build_iwasm:
needs: [build_llvm_libraries] needs:
[build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2204]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
@ -114,6 +129,7 @@ jobs:
$FAST_JIT_BUILD_OPTIONS, $FAST_JIT_BUILD_OPTIONS,
$LLVM_LAZY_JIT_BUILD_OPTIONS, $LLVM_LAZY_JIT_BUILD_OPTIONS,
$LLVM_EAGER_JIT_BUILD_OPTIONS, $LLVM_EAGER_JIT_BUILD_OPTIONS,
$MULTI_TIER_JIT_BUILD_OPTIONS,
] ]
make_options_feature: [ make_options_feature: [
# Features # Features
@ -146,6 +162,8 @@ jobs:
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1" make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
# SIMD only on JIT/AOT mode # SIMD only on JIT/AOT mode
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_SIMD=1" make_options_feature: "-DWAMR_BUILD_SIMD=1"
@ -162,6 +180,8 @@ jobs:
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1" make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1" make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
# DEBUG_AOT only on JIT/AOT mode # DEBUG_AOT only on JIT/AOT mode
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
@ -174,6 +194,8 @@ jobs:
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1" make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
# MINI_LOADER only on INTERP mode # MINI_LOADER only on INTERP mode
- make_options_run_mode: $AOT_BUILD_OPTIONS - make_options_run_mode: $AOT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
@ -183,16 +205,28 @@ jobs:
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Fast-JIT mode doesn't support android(X86-32) - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Fast-JIT and Multi-Tier-JIT mode don't support android(X86-32)
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
platform: android platform: android
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
platform: android
# only test andorid on ubuntu latest
- os: ubuntu-20.04
platform: android
include:
- os: ubuntu-20.04
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}
- os: ubuntu-22.04
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
# only download llvm cache when needed # only download llvm cache when needed
- name: Get LLVM libraries - name: Get LLVM libraries
id: cache_llvm id: retrieve_llvm_libs
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
@ -202,10 +236,10 @@ jobs:
./core/deps/llvm/build/lib ./core/deps/llvm/build/lib
./core/deps/llvm/build/libexec ./core/deps/llvm/build/libexec
./core/deps/llvm/build/share ./core/deps/llvm/build/share
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} key: ${{ matrix.llvm_cache_key }}
- name: Quit if cache miss - name: Quit if cache miss
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.cache_llvm.outputs.cache-hit != 'true') if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true')
run: echo "::error::can not get prebuilt llvm libraries" && exit 1 run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: Build iwasm - name: Build iwasm
@ -216,7 +250,13 @@ jobs:
working-directory: product-mini/platforms/${{ matrix.platform }} working-directory: product-mini/platforms/${{ matrix.platform }}
build_samples_wasm_c_api: build_samples_wasm_c_api:
needs: [build_iwasm, build_llvm_libraries, build_wamrc] needs:
[
build_iwasm,
build_llvm_libraries_on_ubuntu_2004,
build_llvm_libraries_on_ubuntu_2204,
build_wamrc,
]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
@ -228,22 +268,28 @@ jobs:
$FAST_JIT_BUILD_OPTIONS, $FAST_JIT_BUILD_OPTIONS,
$LLVM_LAZY_JIT_BUILD_OPTIONS, $LLVM_LAZY_JIT_BUILD_OPTIONS,
$LLVM_EAGER_JIT_BUILD_OPTIONS, $LLVM_EAGER_JIT_BUILD_OPTIONS,
$MULTI_TIER_JIT_BUILD_OPTIONS,
] ]
os: [ubuntu-20.04, ubuntu-22.04] os: [ubuntu-20.04, ubuntu-22.04]
wasi_sdk_release: wasi_sdk_release:
[ [
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz", "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz",
] ]
wabt_release: wabt_release:
[ [
"https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz", "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz",
] ]
include:
- os: ubuntu-20.04
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}
- os: ubuntu-22.04
llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Get LLVM libraries - name: Get LLVM libraries
id: cache_llvm id: retrieve_llvm_libs
if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
@ -253,18 +299,18 @@ jobs:
./core/deps/llvm/build/lib ./core/deps/llvm/build/lib
./core/deps/llvm/build/libexec ./core/deps/llvm/build/libexec
./core/deps/llvm/build/share ./core/deps/llvm/build/share
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} key: ${{ matrix.llvm_cache_key }}
- name: Quit if cache miss - name: Quit if cache miss
if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true') if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true')
run: echo "::error::can not get prebuilt llvm libraries" && exit 1 run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: download and install wabt - name: download and install wabt
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wabt_release }} sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.24-*.tar.gz sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.24 wabt sudo mv wabt-1.0.31 wabt
- name: Build wamrc - name: Build wamrc
if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
@ -276,19 +322,9 @@ jobs:
- name: Build Sample [wasm-c-api] - name: Build Sample [wasm-c-api]
run: | run: |
mkdir build && cd build cmake -S . -B build ${{ matrix.make_options }}
cmake .. ${{ matrix.make_options }} cmake --build build --config Release --parallel 4
cmake --build . --config Release --parallel 4 ctest --test-dir build
./callback
./callback_chain
./empty_imports
./global
./hello
./hostref
./memory
./reflect
./table
./trap
working-directory: samples/wasm-c-api working-directory: samples/wasm-c-api
build_samples_others: build_samples_others:
@ -297,14 +333,13 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-20.04, ubuntu-22.04] os: [ubuntu-20.04, ubuntu-22.04]
wasi_sdk_release: include:
[ - os: ubuntu-20.04
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz", wasi_sdk_release: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz"
] wabt_release: "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz"
wabt_release: - os: ubuntu-22.04
[ wasi_sdk_release: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz"
"https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz", wabt_release: "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz"
]
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
@ -313,15 +348,31 @@ jobs:
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wasi_sdk_release }} sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-12.0-*.tar.gz sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-12.0 wasi-sdk sudo mv wasi-sdk-19.0 wasi-sdk
- name: download and install wabt - name: download and install wabt
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wabt_release }} sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.24-*.tar.gz sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.24 wabt sudo mv wabt-1.0.31 wabt
- name: build wasi-libc (needed for wasi-threads)
run: |
mkdir wasi-libc
cd wasi-libc
git init
# "Rename thread_spawn import" commit on main branch
git fetch https://github.com/WebAssembly/wasi-libc \
8f5275796a82f8ecfd0833a4f3f444fa37ed4546
git checkout FETCH_HEAD
make -j \
AR=/opt/wasi-sdk/bin/llvm-ar \
NM=/opt/wasi-sdk/bin/llvm-nm \
CC=/opt/wasi-sdk/bin/clang \
THREAD_MODEL=posix
working-directory: core/deps
- name: Build Sample [basic] - name: Build Sample [basic]
run: | run: |
@ -376,20 +427,42 @@ jobs:
exit $? exit $?
working-directory: ./samples/simple working-directory: ./samples/simple
spec_test: - name: Build Sample [wasi-threads]
needs: [build_iwasm, build_llvm_libraries, build_wamrc] run: |
cd samples/wasi-threads
mkdir build && cd build
cmake -DWASI_SYSROOT=`pwd`/../../../core/deps/wasi-libc/sysroot ..
cmake --build . --config Release --parallel 4
./iwasm wasm-apps/no_pthread.wasm
test:
needs: [build_iwasm, build_llvm_libraries_on_ubuntu_2004, build_wamrc]
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
strategy: strategy:
matrix: matrix:
running_mode: running_mode:
["classic-interp", "fast-interp", "jit", "aot", "fast-jit"] [
"classic-interp",
"fast-interp",
"jit",
"aot",
"fast-jit",
"multi-tier-jit",
]
test_option: test_option:
[ [
$DEFAULT_TEST_OPTIONS, $DEFAULT_TEST_OPTIONS,
$MULTI_MODULES_TEST_OPTIONS, $MULTI_MODULES_TEST_OPTIONS,
$SIMD_TEST_OPTIONS, $SIMD_TEST_OPTIONS,
$THREADS_TEST_OPTIONS, $THREADS_TEST_OPTIONS,
$WASI_TEST_OPTIONS,
] ]
wasi_sdk_release:
[
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz",
]
llvm_cache_key:
["${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}"]
exclude: exclude:
# uncompatiable modes and features # uncompatiable modes and features
# classic-interp and fast-interp don't support simd # classic-interp and fast-interp don't support simd
@ -402,31 +475,68 @@ jobs:
test_option: $MULTI_MODULES_TEST_OPTIONS test_option: $MULTI_MODULES_TEST_OPTIONS
- running_mode: "jit" - running_mode: "jit"
test_option: $MULTI_MODULES_TEST_OPTIONS test_option: $MULTI_MODULES_TEST_OPTIONS
# fast-jit is only tested on default mode, exclude other three # fast-jit doesn't support multi module, simd, and threads
- running_mode: "fast-jit" - running_mode: "fast-jit"
test_option: $MULTI_MODULES_TEST_OPTIONS test_option: $MULTI_MODULES_TEST_OPTIONS
- running_mode: "fast-jit" - running_mode: "fast-jit"
test_option: $SIMD_TEST_OPTIONS test_option: $SIMD_TEST_OPTIONS
- running_mode: "fast-jit" - running_mode: "fast-jit"
test_option: $THREADS_TEST_OPTIONS test_option: $THREADS_TEST_OPTIONS
- running_mode: "fast-jit"
test_option: $WASI_TEST_OPTIONS
# multi-tier-jit doesn't support multi module, simd, and threads
- running_mode: "multi-tier-jit"
test_option: $MULTI_MODULES_TEST_OPTIONS
- running_mode: "multi-tier-jit"
test_option: $SIMD_TEST_OPTIONS
- running_mode: "multi-tier-jit"
test_option: $THREADS_TEST_OPTIONS
- running_mode: "multi-tier-jit"
test_option: $WASI_TEST_OPTIONS
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: download and install wasi-sdk
if: matrix.test_option == '$WASI_TEST_OPTIONS'
run: |
cd /opt
sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-19.0 wasi-sdk
- name: build wasi-libc (needed for wasi-threads)
if: matrix.test_option == '$WASI_TEST_OPTIONS'
run: |
mkdir wasi-libc
cd wasi-libc
git init
# "Rename thread_spawn import" commit on main branch
git fetch https://github.com/WebAssembly/wasi-libc \
8f5275796a82f8ecfd0833a4f3f444fa37ed4546
git checkout FETCH_HEAD
make \
AR=/opt/wasi-sdk/bin/llvm-ar \
NM=/opt/wasi-sdk/bin/llvm-nm \
CC=/opt/wasi-sdk/bin/clang \
THREAD_MODEL=posix
working-directory: core/deps
- name: set env variable(if llvm are used) - name: set env variable(if llvm are used)
if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit'
run: echo "USE_LLVM=true" >> $GITHUB_ENV run: echo "USE_LLVM=true" >> $GITHUB_ENV
- name: set env variable(if x86_32 test needed) - name: set env variable(if x86_32 test needed)
if: > if: >
(matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS') (matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS'
&& matrix.running_mode != 'fast-jit' && matrix.running_mode != 'jit' || matrix.test_option == '$WASI_TEST_OPTIONS')
&& matrix.running_mode != 'fast-jit' && matrix.running_mode != 'jit' && matrix.running_mode != 'multi-tier-jit'
run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV
#only download llvm libraries in jit and aot mode #only download llvm libraries in jit and aot mode
- name: Get LLVM libraries - name: Get LLVM libraries
if: env.USE_LLVM == 'true' if: env.USE_LLVM == 'true'
id: cache_llvm id: retrieve_llvm_libs
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
@ -435,13 +545,28 @@ jobs:
./core/deps/llvm/build/lib ./core/deps/llvm/build/lib
./core/deps/llvm/build/libexec ./core/deps/llvm/build/libexec
./core/deps/llvm/build/share ./core/deps/llvm/build/share
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }} key: ${{ matrix.llvm_cache_key }}
- name: Quit if cache miss - name: Quit if cache miss
if: env.USE_LLVM == 'true' && steps.cache_llvm.outputs.cache-hit != 'true' if: env.USE_LLVM == 'true' && steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
run: echo "::error::can not get prebuilt llvm libraries" && exit 1 run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: run spec tests default and extra - name: install jq JSON processor
if: matrix.running_mode == 'aot' && matrix.test_option == '$WASI_TEST_OPTIONS'
run: sudo apt-get update && sudo apt install -y jq
- name: Build WASI thread tests
if: matrix.test_option == '$WASI_TEST_OPTIONS'
run: WASI_SYSROOT=../../../../../core/deps/wasi-libc/sysroot bash build.sh
working-directory: ./core/iwasm/libraries/lib-wasi-threads/test/
- name: build socket api tests
if: matrix.test_option == '$WASI_TEST_OPTIONS'
run: WASI_SYSROOT=../../../../../core/deps/wasi-libc/sysroot bash build.sh
working-directory: ./core/iwasm/libraries/lib-socket/test/
- name: run tests
timeout-minutes: 10
run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }} run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
working-directory: ./tests/wamr-test-suites working-directory: ./tests/wamr-test-suites
@ -456,7 +581,8 @@ jobs:
sudo apt-get update && sudo apt-get update &&
sudo apt install -y g++-multilib lib32gcc-9-dev sudo apt install -y g++-multilib lib32gcc-9-dev
- name: run spec tests x86_32 - name: run tests x86_32
timeout-minutes: 10
if: env.TEST_ON_X86_32 == 'true' if: env.TEST_ON_X86_32 == 'true'
run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }} run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
working-directory: ./tests/wamr-test-suites working-directory: ./tests/wamr-test-suites

View File

@ -51,26 +51,28 @@ env:
FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1" LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
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" 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"
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
jobs: jobs:
build_llvm_libraries: build_llvm_libraries:
uses: ./.github/workflows/build_llvm_libraries.yml uses: ./.github/workflows/build_llvm_libraries.yml
with: with:
runs-on: "['macos-latest']" os: "macos-latest"
arch: "X86"
build_wamrc: build_wamrc:
needs: [build_llvm_libraries] needs: [build_llvm_libraries]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [macos-latest] include:
- os: macos-latest
llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Get LLVM libraries - name: Get LLVM libraries
id: cache_llvm id: retrieve_llvm_libs
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
@ -79,10 +81,10 @@ jobs:
./core/deps/llvm/build/lib ./core/deps/llvm/build/lib
./core/deps/llvm/build/libexec ./core/deps/llvm/build/libexec
./core/deps/llvm/build/share ./core/deps/llvm/build/share
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} key: ${{ matrix.llvm_cache_key }}
- name: Quit if cache miss - name: Quit if cache miss
if: steps.cache_llvm.outputs.cache-hit != 'true' if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
run: echo "::error::can not get prebuilt llvm libraries" && exit 1 run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: Build wamrc - name: Build wamrc
@ -166,13 +168,16 @@ jobs:
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1" make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
include:
- os: macos-latest
llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
# only download llvm cache when needed # only download llvm cache when needed
- name: Get LLVM libraries - name: Get LLVM libraries
id: cache_llvm id: retrieve_llvm_libs
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
@ -182,10 +187,10 @@ jobs:
./core/deps/llvm/build/lib ./core/deps/llvm/build/lib
./core/deps/llvm/build/libexec ./core/deps/llvm/build/libexec
./core/deps/llvm/build/share ./core/deps/llvm/build/share
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} key: ${{ matrix.llvm_cache_key }}
- name: Quit if cache miss - name: Quit if cache miss
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.cache_llvm.outputs.cache-hit != 'true') if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true')
run: echo "::error::can not get prebuilt llvm libraries" && exit 1 run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: Build iwasm - name: Build iwasm
@ -210,8 +215,14 @@ jobs:
#$AOT_BUILD_OPTIONS, #$AOT_BUILD_OPTIONS,
] ]
os: [macos-latest] os: [macos-latest]
wasi_sdk_release: ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz"] wasi_sdk_release:
wabt_release: ["https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz"] [
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz",
]
wabt_release:
[
"https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-macos-12.tar.gz",
]
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
@ -220,24 +231,14 @@ jobs:
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wabt_release }} sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.24-*.tar.gz sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.24 wabt sudo mv wabt-1.0.31 wabt
- name: Build Sample [wasm-c-api] - name: Build Sample [wasm-c-api]
run: | run: |
mkdir build && cd build cmake -S . -B build ${{ matrix.make_options }}
cmake .. ${{ matrix.make_options }} cmake --build build --config Release --parallel 4
cmake --build . --config Release --parallel 4 ctest --test-dir build
./callback
./callback_chain
./empty_imports
./global
./hello
./hostref
./memory
./reflect
./table
./trap
working-directory: samples/wasm-c-api working-directory: samples/wasm-c-api
build_samples_others: build_samples_others:
@ -246,8 +247,14 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [macos-latest] os: [macos-latest]
wasi_sdk_release: ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz"] wasi_sdk_release:
wabt_release: ["https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz"] [
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz",
]
wabt_release:
[
"https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-macos-12.tar.gz",
]
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
@ -256,15 +263,31 @@ jobs:
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wasi_sdk_release }} sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-12.0-*.tar.gz sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-12.0 wasi-sdk sudo mv wasi-sdk-19.0 wasi-sdk
- name: download and install wabt - name: download and install wabt
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wabt_release }} sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.24-*.tar.gz sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.24 wabt sudo mv wabt-1.0.31 wabt
- name: build wasi-libc (needed for wasi-threads)
run: |
mkdir wasi-libc
cd wasi-libc
git init
# "Rename thread_spawn import" commit on main branch
git fetch https://github.com/WebAssembly/wasi-libc \
8f5275796a82f8ecfd0833a4f3f444fa37ed4546
git checkout FETCH_HEAD
make \
AR=/opt/wasi-sdk/bin/llvm-ar \
NM=/opt/wasi-sdk/bin/llvm-nm \
CC=/opt/wasi-sdk/bin/clang \
THREAD_MODEL=posix
working-directory: core/deps
- name: Build Sample [basic] - name: Build Sample [basic]
run: | run: |
@ -311,3 +334,11 @@ jobs:
cmake .. cmake ..
cmake --build . --config Release --parallel 4 cmake --build . --config Release --parallel 4
./hello ./hello
- name: Build Sample [wasi-threads]
run: |
cd samples/wasi-threads
mkdir build && cd build
cmake -DWASI_SYSROOT=`pwd`/../../../core/deps/wasi-libc/sysroot ..
cmake --build . --config Release --parallel 4
./iwasm wasm-apps/no_pthread.wasm

View File

@ -45,6 +45,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
env:
WASI_SDK_PATH: "/opt/wasi-sdk"
jobs: jobs:
build_iwasm_on_nuttx: build_iwasm_on_nuttx:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
@ -65,9 +68,12 @@ jobs:
"boards/risc-v/k210/maix-bit/configs/nsh", "boards/risc-v/k210/maix-bit/configs/nsh",
] ]
wamr_config_option: [ wamr_config_option: [
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n",
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n", "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n",
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_WASI=y\\n",
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n",
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\n", "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\n",
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_WASI=y\\n",
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n",
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n", "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n",
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\n", "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\n",
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n", "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n",
@ -92,6 +98,12 @@ jobs:
tar xvf riscv.tar.gz tar xvf riscv.tar.gz
echo "$PWD/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin" >> $GITHUB_PATH echo "$PWD/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin" >> $GITHUB_PATH
- name: Install WASI-SDK
run: |
curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz > wasi-sdk.tar.gz
tar xvf wasi-sdk.tar.gz
sudo mv wasi-sdk-* /opt/wasi-sdk
- name: Checkout NuttX - name: Checkout NuttX
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
@ -112,7 +124,7 @@ jobs:
- name: Enable WAMR for NuttX - name: Enable WAMR for NuttX
run: | run: |
find nuttx/boards -name defconfig | xargs sed -i '$a\CONFIG_EOL_IS_LF=y\n${{ matrix.wamr_config_option }}' find nuttx/boards -name defconfig | xargs sed -i '$a\CONFIG_EOL_IS_LF=y\nCONFIG_PSEUDOFS_SOFTLINKS=y\n${{ matrix.wamr_config_option }}'
find nuttx/boards/sim -name defconfig | xargs sed -i '$a\CONFIG_LIBM=y\n' find nuttx/boards/sim -name defconfig | xargs sed -i '$a\CONFIG_LIBM=y\n'
- name: Build - name: Build

View File

@ -51,13 +51,13 @@ env:
FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0" FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1" LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
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" 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"
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
jobs: jobs:
build_llvm_libraries: build_llvm_libraries:
uses: ./.github/workflows/build_llvm_libraries.yml uses: ./.github/workflows/build_llvm_libraries.yml
with: with:
runs-on: "['ubuntu-20.04']" os: "ubuntu-20.04"
arch: "X86"
build_iwasm: build_iwasm:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -131,7 +131,9 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ubuntu-20.04] include:
- os: ubuntu-20.04
llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
steps: steps:
- name: install SGX SDK and necessary libraries - name: install SGX SDK and necessary libraries
run: | run: |
@ -150,7 +152,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Get LLVM libraries - name: Get LLVM libraries
id: cache_llvm id: retrieve_llvm_libs
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
@ -159,10 +161,10 @@ jobs:
./core/deps/llvm/build/lib ./core/deps/llvm/build/lib
./core/deps/llvm/build/libexec ./core/deps/llvm/build/libexec
./core/deps/llvm/build/share ./core/deps/llvm/build/share
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} key: ${{ matrix.llvm_cache_key }}
- name: Quit if cache miss - name: Quit if cache miss
if: steps.cache_llvm.outputs.cache-hit != 'true' if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
run: echo "::error::can not get prebuilt llvm libraries" && exit 1 run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: Build wamrc - name: Build wamrc
@ -189,11 +191,11 @@ jobs:
os: [ubuntu-20.04] os: [ubuntu-20.04]
wasi_sdk_release: wasi_sdk_release:
[ [
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz", "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz",
] ]
wabt_release: wabt_release:
[ [
"https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz", "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz",
] ]
steps: steps:
- name: checkout - name: checkout
@ -203,8 +205,8 @@ jobs:
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wabt_release }} sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.24-*.tar.gz sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.24 wabt sudo mv wabt-1.0.31 wabt
- name: install SGX SDK and necessary libraries - name: install SGX SDK and necessary libraries
run: | run: |
@ -221,19 +223,9 @@ jobs:
- name: Build Sample [wasm-c-api] - name: Build Sample [wasm-c-api]
run: | run: |
mkdir build && cd build cmake -S . -B build ${{ matrix.make_options }}
cmake .. ${{ matrix.make_options }} cmake --build build --config Release --parallel 4
cmake --build . --config Release --parallel 4 ctest --test-dir build
./callback
./callback_chain
./empty_imports
./global
./hello
./hostref
./memory
./reflect
./table
./trap
working-directory: samples/wasm-c-api working-directory: samples/wasm-c-api
build_samples_others: build_samples_others:
@ -244,11 +236,11 @@ jobs:
os: [ubuntu-20.04] os: [ubuntu-20.04]
wasi_sdk_release: wasi_sdk_release:
[ [
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz", "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz",
] ]
wabt_release: wabt_release:
[ [
"https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz", "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz",
] ]
steps: steps:
- name: checkout - name: checkout
@ -258,15 +250,31 @@ jobs:
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wasi_sdk_release }} sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-12.0-*.tar.gz sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-12.0 wasi-sdk sudo mv wasi-sdk-19.0 wasi-sdk
- name: download and install wabt - name: download and install wabt
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wabt_release }} sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.24-*.tar.gz sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.24 wabt sudo mv wabt-1.0.31 wabt
- name: build wasi-libc (needed for wasi-threads)
run: |
mkdir wasi-libc
cd wasi-libc
git init
# "Rename thread_spawn import" commit on main branch
git fetch https://github.com/WebAssembly/wasi-libc \
8f5275796a82f8ecfd0833a4f3f444fa37ed4546
git checkout FETCH_HEAD
make \
AR=/opt/wasi-sdk/bin/llvm-ar \
NM=/opt/wasi-sdk/bin/llvm-nm \
CC=/opt/wasi-sdk/bin/clang \
THREAD_MODEL=posix
working-directory: core/deps
- name: install SGX SDK and necessary libraries - name: install SGX SDK and necessary libraries
run: | run: |
@ -327,6 +335,14 @@ jobs:
cmake --build . --config Release --parallel 4 cmake --build . --config Release --parallel 4
./hello ./hello
- name: Build Sample [wasi-threads]
run: |
cd samples/wasi-threads
mkdir build && cd build
cmake -DWASI_SYSROOT=`pwd`/../../../core/deps/wasi-libc/sysroot ..
cmake --build . --config Release --parallel 4
./iwasm wasm-apps/no_pthread.wasm
spec_test_default: spec_test_default:
needs: [build_iwasm, build_llvm_libraries, build_wamrc] needs: [build_iwasm, build_llvm_libraries, build_wamrc]
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
@ -334,6 +350,7 @@ jobs:
matrix: matrix:
running_mode: ["classic-interp", "fast-interp", "aot"] running_mode: ["classic-interp", "fast-interp", "aot"]
test_option: ["-x -p -s spec -b -P", "-x -p -s spec -S -b -P"] test_option: ["-x -p -s spec -b -P", "-x -p -s spec -S -b -P"]
llvm_cache_key: ["${{ needs.build_llvm_libraries.outputs.cache_key }}"]
# classic-interp and fast-interp don't support simd # classic-interp and fast-interp don't support simd
exclude: exclude:
- running_mode: "classic-interp" - running_mode: "classic-interp"
@ -347,7 +364,7 @@ jobs:
- name: Get LLVM libraries - name: Get LLVM libraries
if: matrix.running_mode == 'aot' if: matrix.running_mode == 'aot'
id: cache_llvm id: retrieve_llvm_libs
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
@ -356,10 +373,10 @@ jobs:
./core/deps/llvm/build/lib ./core/deps/llvm/build/lib
./core/deps/llvm/build/libexec ./core/deps/llvm/build/libexec
./core/deps/llvm/build/share ./core/deps/llvm/build/share
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }} key: ${{ matrix.llvm_cache_key }}
- name: Quit if cache miss - name: Quit if cache miss
if: matrix.running_mode == 'aot' && steps.cache_llvm.outputs.cache-hit != 'true' if: matrix.running_mode == 'aot' && steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
run: echo "::error::can not get prebuilt llvm libraries" && exit 1 run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: install SGX SDK and necessary libraries - name: install SGX SDK and necessary libraries

View File

@ -118,3 +118,17 @@ jobs:
cmake .. -DWAMR_BUILD_DEBUG_INTERP=1 cmake .. -DWAMR_BUILD_DEBUG_INTERP=1
cmake --build . --config Release --parallel 4 cmake --build . --config Release --parallel 4
cd .. && rm -force -r build cd .. && rm -force -r build
- name: Build iwasm [lib pthread]
run: |
cd product-mini/platforms/windows
mkdir build && cd build
cmake .. -DWAMR_BUILD_LIB_PTHREAD=1
cmake --build . --config Release --parallel 4
cd .. && rm -force -r build
- name: Build iwasm [lib wasi-thread]
run: |
cd product-mini/platforms/windows
mkdir build && cd build
cmake .. -DWAMR_BUILD_LIB_WASI_THREADS=1
cmake --build . --config Release --parallel 4
cd .. && rm -force -r build

View File

@ -123,7 +123,7 @@ jobs:
runner: ubuntu-20.04 runner: ubuntu-20.04
upload_url: ${{ needs.create_release.outputs.upload_url }} upload_url: ${{ needs.create_release.outputs.upload_url }}
ver_num: ${{ needs.create_tag.outputs.new_ver}} ver_num: ${{ needs.create_tag.outputs.new_ver}}
wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz
release_wamr_sdk_on_ubuntu_2204: release_wamr_sdk_on_ubuntu_2204:
needs: [create_tag, create_release] needs: [create_tag, create_release]
@ -133,7 +133,7 @@ jobs:
runner: ubuntu-22.04 runner: ubuntu-22.04
upload_url: ${{ needs.create_release.outputs.upload_url }} upload_url: ${{ needs.create_release.outputs.upload_url }}
ver_num: ${{ needs.create_tag.outputs.new_ver}} ver_num: ${{ needs.create_tag.outputs.new_ver}}
wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz
release_wamr_sdk_on_macos: release_wamr_sdk_on_macos:
needs: [create_tag, create_release] needs: [create_tag, create_release]
@ -143,13 +143,14 @@ jobs:
runner: macos-latest runner: macos-latest
upload_url: ${{ needs.create_release.outputs.upload_url }} upload_url: ${{ needs.create_release.outputs.upload_url }}
ver_num: ${{ needs.create_tag.outputs.new_ver}} ver_num: ${{ needs.create_tag.outputs.new_ver}}
wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz
# #
# vscode extension cross-platform # vscode extension cross-platform
release_wamr_ide_vscode_ext: release_wamr_ide_vscode_ext:
needs: [create_tag, create_release] needs: [create_tag, create_release]
uses: ./.github/workflows/build_wamr_vscode_ext.yml uses: ./.github/workflows/build_wamr_vscode_ext.yml
secrets: inherit
with: with:
upload_url: ${{ needs.create_release.outputs.upload_url }} upload_url: ${{ needs.create_release.outputs.upload_url }}
ver_num: ${{ needs.create_tag.outputs.new_ver }} ver_num: ${{ needs.create_tag.outputs.new_ver }}

View File

@ -11,12 +11,14 @@ on:
env: env:
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex" LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
WASI_SDK_PATH: "/opt/wasi-sdk"
jobs: jobs:
build_llvm_libraries: build_llvm_libraries:
uses: ./.github/workflows/build_llvm_libraries.yml uses: ./.github/workflows/build_llvm_libraries.yml
with: with:
runs-on: "['ubuntu-22.04']" os: "ubuntu-22.04"
arch: "ARM RISCV AArch64"
spec_test_on_qemu: spec_test_on_qemu:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -37,6 +39,7 @@ jobs:
"-t aot", "-t aot",
"-t aot -X" "-t aot -X"
] ]
llvm_cache_key: [ "${{ needs.build_llvm_libraries.outputs.cache_key }}" ]
steps: steps:
- name: Install Utilities - name: Install Utilities
run: | run: |
@ -53,6 +56,12 @@ jobs:
tar xvf riscv.tar.gz tar xvf riscv.tar.gz
echo "$PWD/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin" >> $GITHUB_PATH echo "$PWD/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin" >> $GITHUB_PATH
- name: Install WASI-SDK
run: |
curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz > wasi-sdk.tar.gz
tar xvf wasi-sdk.tar.gz
sudo mv wasi-sdk-* /opt/wasi-sdk
- name: Checkout NuttX - name: Checkout NuttX
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
@ -72,7 +81,7 @@ jobs:
path: apps/interpreters/wamr/wamr path: apps/interpreters/wamr/wamr
- name: Get LLVM libraries - name: Get LLVM libraries
id: cache_llvm id: retrieve_llvm_libs
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
@ -81,10 +90,10 @@ jobs:
./core/deps/llvm/build/lib ./core/deps/llvm/build/lib
./core/deps/llvm/build/libexec ./core/deps/llvm/build/libexec
./core/deps/llvm/build/share ./core/deps/llvm/build/share
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }} key: ${{ matrix.llvm_cache_key }}
- name: Quit if cache miss - name: Quit if cache miss
if: steps.cache_llvm.outputs.cache-hit != 'true' if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
run: echo "::error::can not get prebuilt llvm libraries" && exit 1 run: echo "::error::can not get prebuilt llvm libraries" && exit 1
- name: Copy LLVM - name: Copy LLVM

7
.gitignore vendored
View File

@ -13,6 +13,8 @@
core/deps/** core/deps/**
core/shared/mem-alloc/tlsf core/shared/mem-alloc/tlsf
core/app-framework/wgl core/app-framework/wgl
core/iwasm/libraries/lib-wasi-threads/test/*.wasm
core/iwasm/libraries/lib-socket/test/*.wasm
wamr-sdk/out/ wamr-sdk/out/
wamr-sdk/runtime/build_runtime_sdk/ wamr-sdk/runtime/build_runtime_sdk/
@ -32,3 +34,8 @@ samples/socket-api/wasm-src/inc/pthread.h
**/__pycache__ **/__pycache__
tests/benchmarks/coremark/coremark* tests/benchmarks/coremark/coremark*
samples/workload/include/**
!samples/workload/include/.gitkeep
# core/iwasm/libraries/wasi-threads

View File

@ -7,7 +7,9 @@ project (iwasm)
set (CMAKE_VERBOSE_MAKEFILE OFF) set (CMAKE_VERBOSE_MAKEFILE OFF)
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) if (NOT DEFINED WAMR_BUILD_PLATFORM)
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
endif ()
# Reset default linker flags # Reset default linker flags
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
@ -83,6 +85,11 @@ if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
set (WAMR_BUILD_LIB_PTHREAD 0) set (WAMR_BUILD_LIB_PTHREAD 0)
endif () endif ()
if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS)
# Disable wasi threads library by default
set (WAMR_BUILD_LIB_WASI_THREADS 0)
endif ()
if (NOT DEFINED WAMR_BUILD_MINI_LOADER) if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
# Disable wasm mini loader by default # Disable wasm mini loader by default
set (WAMR_BUILD_MINI_LOADER 0) set (WAMR_BUILD_MINI_LOADER 0)
@ -98,11 +105,6 @@ if (NOT DEFINED WAMR_BUILD_REF_TYPES)
set (WAMR_BUILD_REF_TYPES 0) set (WAMR_BUILD_REF_TYPES 0)
endif () endif ()
if (COLLECT_CODE_COVERAGE EQUAL 1)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
endif ()
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
@ -130,23 +132,26 @@ include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
# STATIC LIBRARY # STATIC LIBRARY
add_library(iwasm_static STATIC ${WAMR_RUNTIME_LIB_SOURCE}) add_library(iwasm_static STATIC ${WAMR_RUNTIME_LIB_SOURCE})
if (WAMR_BUILD_WASM_CACHE EQUAL 1)
target_link_libraries(iwasm_static PUBLIC boringssl_crypto)
endif ()
set_target_properties (iwasm_static PROPERTIES OUTPUT_NAME vmlib) set_target_properties (iwasm_static PROPERTIES OUTPUT_NAME vmlib)
target_include_directories(iwasm_static INTERFACE ${WAMR_ROOT_DIR}/core/iwasm/include)
target_link_libraries (iwasm_static INTERFACE ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread)
if (WAMR_BUILD_WASM_CACHE EQUAL 1)
target_link_libraries(iwasm_static INTERFACE boringssl_crypto)
endif ()
install (TARGETS iwasm_static ARCHIVE DESTINATION lib) install (TARGETS iwasm_static ARCHIVE DESTINATION lib)
# SHARED LIBRARY # SHARED LIBRARY
add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE}) add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE})
set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm) set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm)
target_link_libraries (iwasm_shared ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread) target_include_directories(iwasm_shared INTERFACE ${WAMR_ROOT_DIR}/core/iwasm/include)
target_link_libraries (iwasm_shared INTERFACE ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread)
if (WAMR_BUILD_WASM_CACHE EQUAL 1) if (WAMR_BUILD_WASM_CACHE EQUAL 1)
target_link_libraries(iwasm_shared boringssl_crypto) target_link_libraries(iwasm_shared INTERFACE boringssl_crypto)
endif () endif ()
if (MINGW) if (MINGW)
target_link_libraries (iwasm_shared -lWs2_32) target_link_libraries (iwasm_shared -lWs2_32)
endif () endif ()
install (TARGETS iwasm_shared LIBRARY DESTINATION lib) install (TARGETS iwasm_shared LIBRARY DESTINATION lib)
@ -155,4 +160,5 @@ install (TARGETS iwasm_shared LIBRARY DESTINATION lib)
install (FILES install (FILES
${WAMR_ROOT_DIR}/core/iwasm/include/wasm_c_api.h ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_c_api.h
${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h
${WAMR_ROOT_DIR}/core/iwasm/include/lib_export.h
DESTINATION include) DESTINATION include)

View File

@ -7,6 +7,7 @@
import argparse import argparse
import os import os
import pathlib import pathlib
import requests
import shlex import shlex
import shutil import shutil
import subprocess import subprocess
@ -21,28 +22,44 @@ def clone_llvm(dst_dir, llvm_repo, llvm_branch):
llvm_dir = dst_dir.joinpath("llvm").resolve() llvm_dir = dst_dir.joinpath("llvm").resolve()
if not llvm_dir.exists(): if not llvm_dir.exists():
print(f"Clone llvm to {llvm_dir} ...")
GIT_CLONE_CMD = f"git clone --depth 1 --branch {llvm_branch} {llvm_repo} llvm" GIT_CLONE_CMD = f"git clone --depth 1 --branch {llvm_branch} {llvm_repo} llvm"
print(GIT_CLONE_CMD)
subprocess.check_output(shlex.split(GIT_CLONE_CMD), cwd=dst_dir) subprocess.check_output(shlex.split(GIT_CLONE_CMD), cwd=dst_dir)
else:
print(f"There is an LLVM local repo in {llvm_dir}, clean and keep using it")
return llvm_dir return llvm_dir
def build_llvm(llvm_dir, platform, backends, projects): def query_llvm_version(llvm_info):
github_token = os.environ['GH_TOKEN']
owner_project = llvm_info['repo'].replace("https://github.com/", "").replace(".git", "")
url = f"https://api.github.com/repos/{owner_project}/commits/{llvm_info['branch']}"
headers = {
'Authorization': f"Bearer {github_token}"
}
try:
response = requests.request("GET", url, headers=headers, data={})
response.raise_for_status()
except requests.exceptions.HTTPError as error:
print (error) # for debugging purpose
return None
response = response.json()
return response['sha']
def build_llvm(llvm_dir, platform, backends, projects, use_clang=False, extra_flags=''):
LLVM_COMPILE_OPTIONS = [ LLVM_COMPILE_OPTIONS = [
'-DCMAKE_BUILD_TYPE:STRING="Release"', '-DCMAKE_BUILD_TYPE:STRING="Release"',
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
"-DLLVM_APPEND_VC_REV:BOOL=ON", "-DLLVM_APPEND_VC_REV:BOOL=ON",
"-DLLVM_BUILD_BENCHMARKS:BOOL=OFF",
"-DLLVM_BUILD_DOCS:BOOL=OFF",
"-DLLVM_BUILD_EXAMPLES:BOOL=OFF", "-DLLVM_BUILD_EXAMPLES:BOOL=OFF",
"-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF", "-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF",
"-DLLVM_BUILD_TESTS:BOOL=OFF", "-DLLVM_BUILD_TESTS:BOOL=OFF",
"-DLLVM_CCACHE_BUILD:BOOL=OFF", "-DLLVM_CCACHE_BUILD:BOOL=ON",
"-DLLVM_ENABLE_BINDINGS:BOOL=OFF", "-DLLVM_ENABLE_BINDINGS:BOOL=OFF",
"-DLLVM_ENABLE_IDE:BOOL=OFF", "-DLLVM_ENABLE_IDE:BOOL=OFF",
"-DLLVM_ENABLE_LIBEDIT=OFF",
"-DLLVM_ENABLE_TERMINFO:BOOL=OFF", "-DLLVM_ENABLE_TERMINFO:BOOL=OFF",
"-DLLVM_ENABLE_ZLIB:BOOL=OFF", "-DLLVM_ENABLE_ZLIB:BOOL=OFF",
"-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF", "-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF",
@ -54,6 +71,18 @@ def build_llvm(llvm_dir, platform, backends, projects):
"-DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON", "-DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON",
] ]
# use clang/clang++/lld. but macos doesn't support lld
if not sys.platform.startswith("darwin") and use_clang:
if shutil.which("clang") and shutil.which("clang++") and shutil.which("lld"):
os.environ["CC"] = "clang"
os.environ["CXX"] = "clang++"
LLVM_COMPILE_OPTIONS.append('-DLLVM_USE_LINKER:STRING="lld"')
print("Use the clang toolchain")
else:
print("Can not find clang, clang++ and lld, keep using the gcc toolchain")
else:
print("Use the gcc toolchain")
LLVM_EXTRA_COMPILE_OPTIONS = { LLVM_EXTRA_COMPILE_OPTIONS = {
"arc": [ "arc": [
'-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="ARC"', '-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="ARC"',
@ -99,8 +128,10 @@ def build_llvm(llvm_dir, platform, backends, projects):
lib_llvm_core_library = build_dir.joinpath("lib/libLLVMCore.a").resolve() lib_llvm_core_library = build_dir.joinpath("lib/libLLVMCore.a").resolve()
if lib_llvm_core_library.exists(): if lib_llvm_core_library.exists():
print(f"Please remove {build_dir} manually and try again") print(
return build_dir f"It has already been fully compiled. If want to a re-build, please remove {build_dir} manually and try again"
)
return None
compile_options = " ".join( compile_options = " ".join(
LLVM_COMPILE_OPTIONS LLVM_COMPILE_OPTIONS
@ -113,16 +144,17 @@ def build_llvm(llvm_dir, platform, backends, projects):
+ LLVM_INCLUDE_TOOLS_OPTION + LLVM_INCLUDE_TOOLS_OPTION
) )
CONFIG_CMD = f"cmake {compile_options} ../llvm" CONFIG_CMD = f"cmake {compile_options} {extra_flags} ../llvm"
if "windows" == platform: if "windows" == platform:
if "mingw" in sysconfig.get_platform().lower(): if "mingw" in sysconfig.get_platform().lower():
CONFIG_CMD += " -G'Unix Makefiles'" CONFIG_CMD += " -G'Unix Makefiles'"
else: else:
CONFIG_CMD += " -A x64" CONFIG_CMD += " -A x64"
print(f"{CONFIG_CMD}") else:
CONFIG_CMD += " -G'Ninja'"
subprocess.check_call(shlex.split(CONFIG_CMD), cwd=build_dir) subprocess.check_call(shlex.split(CONFIG_CMD), cwd=build_dir)
BUILD_CMD = f"cmake --build . --target package --parallel {os.cpu_count()}" + ( BUILD_CMD = "cmake --build . --target package" + (
" --config Release" if "windows" == platform else "" " --config Release" if "windows" == platform else ""
) )
subprocess.check_call(shlex.split(BUILD_CMD), cwd=build_dir) subprocess.check_call(shlex.split(BUILD_CMD), cwd=build_dir)
@ -133,23 +165,25 @@ def build_llvm(llvm_dir, platform, backends, projects):
def repackage_llvm(llvm_dir): def repackage_llvm(llvm_dir):
build_dir = llvm_dir.joinpath("./build").resolve() build_dir = llvm_dir.joinpath("./build").resolve()
packs = [f for f in build_dir.glob("LLVM-13*.tar.gz")] packs = [f for f in build_dir.glob("LLVM-*.tar.gz")]
if len(packs) > 1: if len(packs) > 1:
raise Exception("Find more than one LLVM-13*.tar.gz") raise Exception("Find more than one LLVM-*.tar.gz")
if not packs: if not packs:
return return
llvm_package = packs[0].name llvm_package = packs[0].name
# mv build/LLVM-13.0.0*.gz . # mv build/LLVM-*.gz .
shutil.move(str(build_dir.joinpath(llvm_package).resolve()), str(llvm_dir)) shutil.move(str(build_dir.joinpath(llvm_package).resolve()), str(llvm_dir))
# rm -r build # rm -r build
shutil.rmtree(str(build_dir)) shutil.rmtree(str(build_dir))
# mkdir build # mkdir build
build_dir.mkdir() build_dir.mkdir()
# tar xf ./LLVM-13.0.0-*.tar.gz --strip-components=1 --directory=build # tar xf ./LLVM-*.tar.gz --strip-components=1 --directory=build
CMD = f"tar xf {llvm_dir.joinpath(llvm_package).resolve()} --strip-components=1 --directory={build_dir}" CMD = f"tar xf {llvm_dir.joinpath(llvm_package).resolve()} --strip-components=1 --directory={build_dir}"
subprocess.check_call(shlex.split(CMD), cwd=llvm_dir) subprocess.check_call(shlex.split(CMD), cwd=llvm_dir)
# rm ./LLVM-1*.gz
os.remove(llvm_dir.joinpath(llvm_package).resolve())
def main(): def main():
@ -184,8 +218,23 @@ def main():
choices=["clang", "lldb"], choices=["clang", "lldb"],
help="identify extra LLVM projects, separate by space, like '--project clang lldb'", help="identify extra LLVM projects, separate by space, like '--project clang lldb'",
) )
parser.add_argument(
"--llvm-ver",
action="store_true",
help="return the version info of generated llvm libraries",
)
parser.add_argument(
"--use-clang",
action="store_true",
help="use clang instead of gcc",
)
parser.add_argument(
"--extra-cmake-flags",
type=str,
default="",
help="custom extra cmake flags",
)
options = parser.parse_args() options = parser.parse_args()
print(f"options={options}")
# if the "platform" is not identified in the command line option, # if the "platform" is not identified in the command line option,
# detect it # detect it
@ -199,20 +248,21 @@ def main():
else: else:
platform = options.platform platform = options.platform
print(f"========== Build LLVM for {platform} ==========\n")
llvm_repo_and_branch = { llvm_repo_and_branch = {
"arc": { "arc": {
"repo": "https://github.com/llvm/llvm-project.git", "repo": "https://github.com/llvm/llvm-project.git",
"branch": "release/13.x", "repo_ssh": "git@github.com:llvm/llvm-project.git",
"branch": "release/15.x",
}, },
"xtensa": { "xtensa": {
"repo": "https://github.com/espressif/llvm-project.git", "repo": "https://github.com/espressif/llvm-project.git",
"repo_ssh": "git@github.com:espressif/llvm-project.git",
"branch": "xtensa_release_15.x", "branch": "xtensa_release_15.x",
}, },
"default": { "default": {
"repo": "https://github.com/llvm/llvm-project.git", "repo": "https://github.com/llvm/llvm-project.git",
"branch": "release/13.x", "repo_ssh": "git@github.com:llvm/llvm-project.git",
"branch": "release/15.x",
}, },
} }
@ -225,19 +275,29 @@ def main():
deps_dir = current_dir.joinpath("../core/deps").resolve() deps_dir = current_dir.joinpath("../core/deps").resolve()
try: try:
print(f"==================== CLONE LLVM ====================")
llvm_info = llvm_repo_and_branch.get(platform, llvm_repo_and_branch["default"]) llvm_info = llvm_repo_and_branch.get(platform, llvm_repo_and_branch["default"])
llvm_dir = clone_llvm(deps_dir, llvm_info["repo"], llvm_info["branch"])
print() if options.llvm_ver:
print(f"==================== BUILD LLVM ====================") commit_hash = query_llvm_version(llvm_info)
build_llvm(llvm_dir, platform, options.arch, options.project) print(commit_hash)
return commit_hash is not None
repo_addr = llvm_info["repo"]
if os.environ.get('USE_GIT_SSH') == "true":
repo_addr = llvm_info["repo_ssh"]
else:
print("To use ssh for git clone, run: export USE_GIT_SSH=true")
llvm_dir = clone_llvm(deps_dir, repo_addr, llvm_info["branch"])
if (
build_llvm(
llvm_dir, platform, options.arch, options.project, options.use_clang,
options.extra_cmake_flags
)
is not None
):
repackage_llvm(llvm_dir)
print()
print(f"==================== PACKAGE LLVM ====================")
repackage_llvm(llvm_dir)
print()
return True return True
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
return False return False

View File

@ -337,6 +337,11 @@ if (WAMR_BUILD_SGX_IPFS EQUAL 1)
endif () endif ()
if (WAMR_BUILD_WASI_NN EQUAL 1) if (WAMR_BUILD_WASI_NN EQUAL 1)
message (" WASI-NN enabled") message (" WASI-NN enabled")
add_definitions (-DWASM_ENABLE_WASI_NN=1)
if (WASI_NN_ENABLE_GPU EQUAL 1)
message (" WASI-NN: GPU enabled")
add_definitions (-DWASI_NN_ENABLE_GPU=1)
endif ()
endif () endif ()
if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 1) if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 1)
add_definitions(-DWASM_MEM_ALLOC_WITH_USER_DATA=1) add_definitions(-DWASM_MEM_ALLOC_WITH_USER_DATA=1)
@ -345,3 +350,13 @@ if (WAMR_BUILD_WASM_CACHE EQUAL 1)
add_definitions (-DWASM_ENABLE_WASM_CACHE=1) add_definitions (-DWASM_ENABLE_WASM_CACHE=1)
message (" Wasm files cache enabled") message (" Wasm files cache enabled")
endif () endif ()
if (WAMR_BUILD_GC_HEAP_VERIFY EQUAL 1)
add_definitions (-DWASM_ENABLE_GC_VERIFY=1)
message (" GC heap verification enabled")
endif ()
if ("$ENV{COLLECT_CODE_COVERAGE}" STREQUAL "1" OR COLLECT_CODE_COVERAGE EQUAL 1)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
add_definitions (-DCOLLECT_CODE_COVERAGE)
message (" Collect code coverage enabled")
endif ()

View File

@ -0,0 +1 @@
requests==2.28.2

View File

@ -19,6 +19,11 @@ endif ()
if (NOT DEFINED DEPS_DIR) if (NOT DEFINED DEPS_DIR)
set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps) set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps)
endif () endif ()
if (NOT DEFINED SHARED_PLATFORM_CONFIG)
# CMake file for platform configuration. The PLATFORM_SHARED_SOURCE varable
# should point to a list of platform-specfic source files to compile.
set (SHARED_PLATFORM_CONFIG ${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake)
endif ()
if (DEFINED EXTRA_SDK_INCLUDE_PATH) if (DEFINED EXTRA_SDK_INCLUDE_PATH)
message(STATUS, "EXTRA_SDK_INCLUDE_PATH = ${EXTRA_SDK_INCLUDE_PATH} ") message(STATUS, "EXTRA_SDK_INCLUDE_PATH = ${EXTRA_SDK_INCLUDE_PATH} ")
@ -96,10 +101,21 @@ if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1)
endif () endif ()
if (WAMR_BUILD_WASI_NN EQUAL 1) if (WAMR_BUILD_WASI_NN EQUAL 1)
execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh if (NOT EXISTS "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
RESULT_VARIABLE TENSORFLOW_RESULT execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh
) RESULT_VARIABLE TENSORFLOW_RESULT
)
else ()
message("Tensorflow is already downloaded.")
endif()
set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src") set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
if (WASI_NN_ENABLE_GPU EQUAL 1)
# Tensorflow specific:
# * https://www.tensorflow.org/lite/guide/build_cmake#available_options_to_build_tensorflow_lite
set (TFLITE_ENABLE_GPU ON)
endif ()
include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include) include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include)
include_directories (${TENSORFLOW_SOURCE_DIR}) include_directories (${TENSORFLOW_SOURCE_DIR})
add_subdirectory( add_subdirectory(
@ -116,6 +132,14 @@ if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
set (WAMR_BUILD_SHARED_MEMORY 1) set (WAMR_BUILD_SHARED_MEMORY 1)
endif () endif ()
if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1)
include (${IWASM_DIR}/libraries/lib-wasi-threads/lib_wasi_threads.cmake)
# Enable the dependent feature if lib wasi threads is enabled
set (WAMR_BUILD_THREAD_MGR 1)
set (WAMR_BUILD_BULK_MEMORY 1)
set (WAMR_BUILD_SHARED_MEMORY 1)
endif ()
if (WAMR_BUILD_DEBUG_INTERP EQUAL 1) if (WAMR_BUILD_DEBUG_INTERP EQUAL 1)
set (WAMR_BUILD_THREAD_MGR 1) set (WAMR_BUILD_THREAD_MGR 1)
include (${IWASM_DIR}/libraries/debug-engine/debug_engine.cmake) include (${IWASM_DIR}/libraries/debug-engine/debug_engine.cmake)
@ -161,7 +185,7 @@ LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
enable_language (ASM) enable_language (ASM)
include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) include (${SHARED_PLATFORM_CONFIG})
include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake)
include (${IWASM_DIR}/common/iwasm_common.cmake) include (${IWASM_DIR}/common/iwasm_common.cmake)
include (${SHARED_DIR}/utils/shared_utils.cmake) include (${SHARED_DIR}/utils/shared_utils.cmake)
@ -182,6 +206,7 @@ set (source_all
${WASM_APP_LIB_SOURCE_ALL} ${WASM_APP_LIB_SOURCE_ALL}
${NATIVE_INTERFACE_SOURCE} ${NATIVE_INTERFACE_SOURCE}
${APP_MGR_SOURCE} ${APP_MGR_SOURCE}
${LIB_WASI_THREADS_SOURCE}
${LIB_PTHREAD_SOURCE} ${LIB_PTHREAD_SOURCE}
${THREAD_MGR_SOURCE} ${THREAD_MGR_SOURCE}
${LIBC_EMCC_SOURCE} ${LIBC_EMCC_SOURCE}

View File

@ -7,11 +7,14 @@
typedef union jvalue { typedef union jvalue {
bool z; bool z;
int8_t b; int8_t i8;
uint16_t c; uint8_t u8;
int16_t s; int16_t i16;
int32_t i; uint16_t u16;
int64_t j; int32_t i32;
uint32_t u32;
int64_t i64;
uint64_t u64;
float f; float f;
double d; double d;
} jvalue; } jvalue;
@ -27,7 +30,9 @@ get_int16(const char *buf)
static inline uint16_t static inline uint16_t
get_uint16(const char *buf) get_uint16(const char *buf)
{ {
return get_int16(buf); uint16_t ret;
bh_memcpy_s(&ret, sizeof(uint16_t), buf, sizeof(uint16_t));
return ret;
} }
static inline int32_t static inline int32_t
@ -41,7 +46,9 @@ get_int32(const char *buf)
static inline uint32_t static inline uint32_t
get_uint32(const char *buf) get_uint32(const char *buf)
{ {
return get_int32(buf); uint32_t ret;
bh_memcpy_s(&ret, sizeof(uint32_t), buf, sizeof(uint32_t));
return ret;
} }
static inline int64_t static inline int64_t
@ -55,7 +62,9 @@ get_int64(const char *buf)
static inline uint64_t static inline uint64_t
get_uint64(const char *buf) get_uint64(const char *buf)
{ {
return get_int64(buf); uint64_t ret;
bh_memcpy_s(&ret, sizeof(uint64_t), buf, sizeof(uint64_t));
return ret;
} }
static inline void static inline void
@ -145,8 +154,8 @@ attr_container_get_attr_next(const char *curr_attr)
p += sizeof(uint16_t) + get_uint16(p); p += sizeof(uint16_t) + get_uint16(p);
type = *p++; type = *p++;
/* Short type to Boolean type */ /* Byte type to Boolean type */
if (type >= ATTR_TYPE_SHORT && type <= ATTR_TYPE_BOOLEAN) { if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN) {
p += 1 << (type & 3); p += 1 << (type & 3);
return p; return p;
} }
@ -342,7 +351,7 @@ attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
/* key len + key + '\0' + type */ /* key len + key + '\0' + type */
attr_len = sizeof(uint16_t) + strlen(key) + 1 + 1; attr_len = sizeof(uint16_t) + strlen(key) + 1 + 1;
if (type >= ATTR_TYPE_SHORT && type <= ATTR_TYPE_BOOLEAN) if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN)
attr_len += 1 << (type & 3); attr_len += 1 << (type & 3);
else if (type == ATTR_TYPE_STRING) else if (type == ATTR_TYPE_STRING)
attr_len += sizeof(uint16_t) + value_length; attr_len += sizeof(uint16_t) + value_length;
@ -362,7 +371,7 @@ attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
p += str_len; p += str_len;
*p++ = type; *p++ = type;
if (type >= ATTR_TYPE_SHORT && type <= ATTR_TYPE_BOOLEAN) if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN)
bh_memcpy_s(p, 1 << (type & 3), value, 1 << (type & 3)); bh_memcpy_s(p, 1 << (type & 3), value, 1 << (type & 3));
else if (type == ATTR_TYPE_STRING) { else if (type == ATTR_TYPE_STRING) {
set_uint16(p, value_length); set_uint16(p, value_length);
@ -460,6 +469,14 @@ attr_container_set_short(attr_container_t **p_attr_cont, const char *key,
2); 2);
} }
bool
attr_container_set_int16(attr_container_t **p_attr_cont, const char *key,
int16_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT16, &value,
2);
}
bool bool
attr_container_set_int(attr_container_t **p_attr_cont, const char *key, attr_container_set_int(attr_container_t **p_attr_cont, const char *key,
int value) int value)
@ -467,6 +484,22 @@ attr_container_set_int(attr_container_t **p_attr_cont, const char *key,
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT, &value, 4); return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT, &value, 4);
} }
bool
attr_container_set_int32(attr_container_t **p_attr_cont, const char *key,
int32_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT32, &value,
4);
}
bool
attr_container_set_uint32(attr_container_t **p_attr_cont, const char *key,
uint32_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT32, &value,
4);
}
bool bool
attr_container_set_int64(attr_container_t **p_attr_cont, const char *key, attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
int64_t value) int64_t value)
@ -475,6 +508,14 @@ attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
8); 8);
} }
bool
attr_container_set_uint64(attr_container_t **p_attr_cont, const char *key,
uint64_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT64, &value,
8);
}
bool bool
attr_container_set_byte(attr_container_t **p_attr_cont, const char *key, attr_container_set_byte(attr_container_t **p_attr_cont, const char *key,
int8_t value) int8_t value)
@ -482,6 +523,21 @@ attr_container_set_byte(attr_container_t **p_attr_cont, const char *key,
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BYTE, &value, 1); return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BYTE, &value, 1);
} }
bool
attr_container_set_int8(attr_container_t **p_attr_cont, const char *key,
int8_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT8, &value, 1);
}
bool
attr_container_set_uint8(attr_container_t **p_attr_cont, const char *key,
uint8_t value)
{
return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT8, &value,
1);
}
bool bool
attr_container_set_uint16(attr_container_t **p_attr_cont, const char *key, attr_container_set_uint16(attr_container_t **p_attr_cont, const char *key,
uint16_t value) uint16_t value)
@ -552,7 +608,7 @@ attr_container_get_attr(const attr_container_t *attr_cont, const char *key)
if (!(attr_addr = attr_container_find_attr(attr_cont, key))) { if (!(attr_addr = attr_container_find_attr(attr_cont, key))) {
attr_container_printf("Get attribute failed: lookup key failed.\r\n"); attr_container_printf("Get attribute failed: lookup key failed.\r\n");
return false; return NULL;
} }
/* key len + key + '\0' */ /* key len + key + '\0' */
@ -566,14 +622,17 @@ attr_container_get_attr(const attr_container_t *attr_cont, const char *key)
uint8_t type; \ uint8_t type; \
if (!addr) \ if (!addr) \
return 0; \ return 0; \
val.j = 0; \ val.i64 = 0; \
type = *(uint8_t *)addr++; \ type = *(uint8_t *)addr++; \
switch (type) { \ switch (type) { \
case ATTR_TYPE_SHORT: \ case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */ \
case ATTR_TYPE_INT: \ case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */ \
case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */ \
case ATTR_TYPE_INT64: \ case ATTR_TYPE_INT64: \
case ATTR_TYPE_BYTE: \ case ATTR_TYPE_UINT8: \
case ATTR_TYPE_UINT16: \ case ATTR_TYPE_UINT16: \
case ATTR_TYPE_UINT32: \
case ATTR_TYPE_UINT64: \
case ATTR_TYPE_FLOAT: \ case ATTR_TYPE_FLOAT: \
case ATTR_TYPE_DOUBLE: \ case ATTR_TYPE_DOUBLE: \
case ATTR_TYPE_BOOLEAN: \ case ATTR_TYPE_BOOLEAN: \
@ -608,31 +667,67 @@ attr_container_get_attr(const attr_container_t *attr_cont, const char *key)
short short
attr_container_get_as_short(const attr_container_t *attr_cont, const char *key) attr_container_get_as_short(const attr_container_t *attr_cont, const char *key)
{ {
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, s); TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i16);
}
int16_t
attr_container_get_as_int16(const attr_container_t *attr_cont, const char *key)
{
return (int16_t)attr_container_get_as_short(attr_cont, key);
} }
int int
attr_container_get_as_int(const attr_container_t *attr_cont, const char *key) attr_container_get_as_int(const attr_container_t *attr_cont, const char *key)
{ {
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i); TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i32);
}
int32_t
attr_container_get_as_int32(const attr_container_t *attr_cont, const char *key)
{
return (int32_t)attr_container_get_as_int(attr_cont, key);
}
uint32_t
attr_container_get_as_uint32(const attr_container_t *attr_cont, const char *key)
{
return (uint32_t)attr_container_get_as_int(attr_cont, key);
} }
int64_t int64_t
attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key) attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key)
{ {
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, j); TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i64);
}
uint64_t
attr_container_get_as_uint64(const attr_container_t *attr_cont, const char *key)
{
return (uint64_t)attr_container_get_as_int64(attr_cont, key);
} }
int8_t int8_t
attr_container_get_as_byte(const attr_container_t *attr_cont, const char *key) attr_container_get_as_byte(const attr_container_t *attr_cont, const char *key)
{ {
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, b); TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i8);
}
int8_t
attr_container_get_as_int8(const attr_container_t *attr_cont, const char *key)
{
return attr_container_get_as_byte(attr_cont, key);
}
uint8_t
attr_container_get_as_uint8(const attr_container_t *attr_cont, const char *key)
{
return (uint8_t)attr_container_get_as_byte(attr_cont, key);
} }
uint16_t uint16_t
attr_container_get_as_uint16(const attr_container_t *attr_cont, const char *key) attr_container_get_as_uint16(const attr_container_t *attr_cont, const char *key)
{ {
TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, s); return (uint16_t)attr_container_get_as_short(attr_cont, key);
} }
float float
@ -671,11 +766,14 @@ attr_container_get_as_bytearray(const attr_container_t *attr_cont,
type = *(uint8_t *)addr++; type = *(uint8_t *)addr++;
switch (type) { switch (type) {
case ATTR_TYPE_SHORT: case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */
case ATTR_TYPE_INT: case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */
case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */
case ATTR_TYPE_INT64: case ATTR_TYPE_INT64:
case ATTR_TYPE_BYTE: case ATTR_TYPE_UINT8:
case ATTR_TYPE_UINT16: case ATTR_TYPE_UINT16:
case ATTR_TYPE_UINT32:
case ATTR_TYPE_UINT64:
case ATTR_TYPE_FLOAT: case ATTR_TYPE_FLOAT:
case ATTR_TYPE_DOUBLE: case ATTR_TYPE_DOUBLE:
case ATTR_TYPE_BOOLEAN: case ATTR_TYPE_BOOLEAN:
@ -807,34 +905,52 @@ attr_container_dump(const attr_container_t *attr_cont)
attr_container_printf(" key: %s", key); attr_container_printf(" key: %s", key);
switch (type) { switch (type) {
case ATTR_TYPE_SHORT: case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */
bh_memcpy_s(&value.s, sizeof(int16_t), p, sizeof(int16_t)); bh_memcpy_s(&value.i8, 1, p, 1);
attr_container_printf(", type: byte, value: 0x%x\n",
value.i8 & 0xFF);
p++;
break;
case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */
bh_memcpy_s(&value.i16, sizeof(int16_t), p, sizeof(int16_t));
attr_container_printf(", type: short, value: 0x%x\n", attr_container_printf(", type: short, value: 0x%x\n",
value.s & 0xFFFF); value.i16 & 0xFFFF);
p += 2; p += 2;
break; break;
case ATTR_TYPE_INT: case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */
bh_memcpy_s(&value.i, sizeof(int32_t), p, sizeof(int32_t)); bh_memcpy_s(&value.i32, sizeof(int32_t), p, sizeof(int32_t));
attr_container_printf(", type: int, value: 0x%x\n", value.i); attr_container_printf(", type: int, value: 0x%x\n", value.i32);
p += 4; p += 4;
break; break;
case ATTR_TYPE_INT64: case ATTR_TYPE_INT64:
bh_memcpy_s(&value.j, sizeof(uint64_t), p, sizeof(uint64_t)); bh_memcpy_s(&value.i64, sizeof(int64_t), p, sizeof(int64_t));
attr_container_printf(", type: int64, value: 0x%llx\n", attr_container_printf(", type: int64, value: 0x%llx\n",
(long long unsigned int)(value.j)); (long long unsigned int)(value.i64));
p += 8; p += 8;
break; break;
case ATTR_TYPE_BYTE: case ATTR_TYPE_UINT8:
bh_memcpy_s(&value.b, 1, p, 1); bh_memcpy_s(&value.u8, 1, p, 1);
attr_container_printf(", type: byte, value: 0x%x\n", attr_container_printf(", type: uint8, value: 0x%x\n", value.u8);
value.b & 0xFF);
p++; p++;
break; break;
case ATTR_TYPE_UINT16: case ATTR_TYPE_UINT16:
bh_memcpy_s(&value.c, sizeof(uint16_t), p, sizeof(uint16_t)); bh_memcpy_s(&value.u16, sizeof(uint16_t), p, sizeof(uint16_t));
attr_container_printf(", type: uint16, value: 0x%x\n", value.c); attr_container_printf(", type: uint16, value: 0x%x\n",
value.u16);
p += 2; p += 2;
break; break;
case ATTR_TYPE_UINT32:
bh_memcpy_s(&value.u32, sizeof(uint32_t), p, sizeof(uint32_t));
attr_container_printf(", type: uint32, value: 0x%x\n",
value.u32);
p += 4;
break;
case ATTR_TYPE_UINT64:
bh_memcpy_s(&value.u64, sizeof(uint64_t), p, sizeof(uint64_t));
attr_container_printf(", type: int64, value: 0x%llx\n",
(long long unsigned int)(value.u64));
p += 8;
break;
case ATTR_TYPE_FLOAT: case ATTR_TYPE_FLOAT:
bh_memcpy_s(&value.f, sizeof(float), p, sizeof(float)); bh_memcpy_s(&value.f, sizeof(float), p, sizeof(float));
attr_container_printf(", type: float, value: %f\n", value.f); attr_container_printf(", type: float, value: %f\n", value.f);

View File

@ -20,13 +20,27 @@ extern "C" {
/* Attribute type */ /* Attribute type */
enum { enum {
ATTR_TYPE_BEGIN = 1, ATTR_TYPE_BEGIN = 0,
ATTR_TYPE_SHORT = ATTR_TYPE_BEGIN, ATTR_TYPE_BYTE = ATTR_TYPE_BEGIN,
ATTR_TYPE_INT8 = ATTR_TYPE_BYTE,
ATTR_TYPE_SHORT,
ATTR_TYPE_INT16 = ATTR_TYPE_SHORT,
ATTR_TYPE_INT, ATTR_TYPE_INT,
ATTR_TYPE_INT32 = ATTR_TYPE_INT,
ATTR_TYPE_INT64, ATTR_TYPE_INT64,
ATTR_TYPE_BYTE, ATTR_TYPE_UINT8,
ATTR_TYPE_UINT16, ATTR_TYPE_UINT16,
ATTR_TYPE_FLOAT, ATTR_TYPE_UINT32,
ATTR_TYPE_UINT64,
/**
* Why ATTR_TYPE_FLOAT = 10?
* We determine the number of bytes that should be copied through 1<<(type &
* 3). ATTR_TYPE_BYTE = 0, so the number of bytes is 1 << 0 = 1.
* ATTR_TYPE_UINT64 = 7, so the number of bytes is 1 << 3 = 8.
* Since the float type takes up 4 bytes, ATTR_TYPE_FLOAT should be 10.
* Calculation: (1 << (10&3)) = (1 << 2) = 4
*/
ATTR_TYPE_FLOAT = 10,
ATTR_TYPE_DOUBLE, ATTR_TYPE_DOUBLE,
ATTR_TYPE_BOOLEAN, ATTR_TYPE_BOOLEAN,
ATTR_TYPE_STRING, ATTR_TYPE_STRING,
@ -89,6 +103,20 @@ bool
attr_container_set_short(attr_container_t **p_attr_cont, const char *key, attr_container_set_short(attr_container_t **p_attr_cont, const char *key,
short value); short value);
/**
* Set int16 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_int16(attr_container_t **p_attr_cont, const char *key,
int16_t value);
/** /**
* Set int attribute in attribute container * Set int attribute in attribute container
* *
@ -103,6 +131,34 @@ bool
attr_container_set_int(attr_container_t **p_attr_cont, const char *key, attr_container_set_int(attr_container_t **p_attr_cont, const char *key,
int value); int value);
/**
* Set int32 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_int32(attr_container_t **p_attr_cont, const char *key,
int32_t value);
/**
* Set uint32 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_uint32(attr_container_t **p_attr_cont, const char *key,
uint32_t value);
/** /**
* Set int64 attribute in attribute container * Set int64 attribute in attribute container
* *
@ -117,6 +173,20 @@ bool
attr_container_set_int64(attr_container_t **p_attr_cont, const char *key, attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
int64_t value); int64_t value);
/**
* Set uint64 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_uint64(attr_container_t **p_attr_cont, const char *key,
uint64_t value);
/** /**
* Set byte attribute in attribute container * Set byte attribute in attribute container
* *
@ -131,6 +201,34 @@ bool
attr_container_set_byte(attr_container_t **p_attr_cont, const char *key, attr_container_set_byte(attr_container_t **p_attr_cont, const char *key,
int8_t value); int8_t value);
/**
* Set int8 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_int8(attr_container_t **p_attr_cont, const char *key,
int8_t value);
/**
* Set uint8 attribute in attribute container
*
* @param p_attr_cont pointer to attribute container to set attribute, and
* return the new attribute container if it is re-created
* @param key the attribute key
* @param value the attribute value
*
* @return true if success, false otherwise
*/
bool
attr_container_set_uint8(attr_container_t **p_attr_cont, const char *key,
uint8_t value);
/** /**
* Set uint16 attribute in attribute container * Set uint16 attribute in attribute container
* *
@ -259,6 +357,18 @@ attr_container_contain_key(const attr_container_t *attr_cont, const char *key);
short short
attr_container_get_as_short(const attr_container_t *attr_cont, const char *key); attr_container_get_as_short(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as int16 value,
* return 0 if attribute isn't found in message.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the short value of the attribute, 0 if key isn't found
*/
int16_t
attr_container_get_as_int16(const attr_container_t *attr_cont, const char *key);
/** /**
* Get attribute from attribute container and return it as int value, * Get attribute from attribute container and return it as int value,
* return 0 if attribute isn't found in message. * return 0 if attribute isn't found in message.
@ -271,6 +381,31 @@ attr_container_get_as_short(const attr_container_t *attr_cont, const char *key);
int int
attr_container_get_as_int(const attr_container_t *attr_cont, const char *key); attr_container_get_as_int(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as int32 value,
* return 0 if attribute isn't found in message.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the int value of the attribute, 0 if key isn't found
*/
int32_t
attr_container_get_as_int32(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as uint32 value,
* return 0 if attribute isn't found in message.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the unsigned int value of the attribute, 0 if key isn't found
*/
uint32_t
attr_container_get_as_uint32(const attr_container_t *attr_cont,
const char *key);
/** /**
* Get attribute from attribute container and return it as int64 value, * Get attribute from attribute container and return it as int64 value,
* return 0 if attribute isn't found in attribute container. * return 0 if attribute isn't found in attribute container.
@ -283,6 +418,19 @@ attr_container_get_as_int(const attr_container_t *attr_cont, const char *key);
int64_t int64_t
attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key); attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as uint64 value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the unsigned long value of the attribute, 0 if key isn't found
*/
uint64_t
attr_container_get_as_uint64(const attr_container_t *attr_cont,
const char *key);
/** /**
* Get attribute from attribute container and return it as byte value, * Get attribute from attribute container and return it as byte value,
* return 0 if attribute isn't found in attribute container. * return 0 if attribute isn't found in attribute container.
@ -295,6 +443,30 @@ attr_container_get_as_int64(const attr_container_t *attr_cont, const char *key);
int8_t int8_t
attr_container_get_as_byte(const attr_container_t *attr_cont, const char *key); attr_container_get_as_byte(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as int8 value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the byte value of the attribute, 0 if key isn't found
*/
int8_t
attr_container_get_as_int8(const attr_container_t *attr_cont, const char *key);
/**
* Get attribute from attribute container and return it as uint8 value,
* return 0 if attribute isn't found in attribute container.
*
* @param attr_cont the attribute container
* @param key the attribute key
*
* @return the uint8 value of the attribute, 0 if key isn't found
*/
uint8_t
attr_container_get_as_uint8(const attr_container_t *attr_cont, const char *key);
/** /**
* Get attribute from attribute container and return it as uint16 value, * Get attribute from attribute container and return it as uint16 value,
* return 0 if attribute isn't found in attribute container. * return 0 if attribute isn't found in attribute container.

View File

@ -993,6 +993,14 @@ wasm_app_module_uninstall(request_t *msg)
app_manager_printf("Uninstall WASM app successful!\n"); app_manager_printf("Uninstall WASM app successful!\n");
#ifdef COLLECT_CODE_COVERAGE
/* Exit app manager so as to collect code coverage data */
if (!strcmp(m_name, "__exit_app_manager__")) {
app_manager_printf("Exit app manager\n");
bh_queue_exit_loop_run(get_app_manager_queue());
}
#endif
#if VALGRIND_CHECK != 0 #if VALGRIND_CHECK != 0
bh_queue_exit_loop_run(get_app_manager_queue()); bh_queue_exit_loop_run(get_app_manager_queue());
#endif #endif

View File

@ -161,6 +161,17 @@
#define WASM_ENABLE_LIB_PTHREAD_SEMAPHORE 0 #define WASM_ENABLE_LIB_PTHREAD_SEMAPHORE 0
#endif #endif
#ifndef WASM_ENABLE_LIB_WASI_THREADS
#define WASM_ENABLE_LIB_WASI_THREADS 0
#endif
#ifndef WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION
#define WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION WASM_ENABLE_LIB_WASI_THREADS
#elif WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0 \
&& WASM_ENABLE_LIB_WASI_THREADS == 1
#error "Heap aux stack allocation must be enabled for WASI threads"
#endif
#ifndef WASM_ENABLE_BASE_LIB #ifndef WASM_ENABLE_BASE_LIB
#define WASM_ENABLE_BASE_LIB 0 #define WASM_ENABLE_BASE_LIB 0
#endif #endif

View File

@ -1226,7 +1226,10 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end,
} }
import_globals[i].global_data_linked = import_globals[i].global_data_linked =
tmp_global.global_data_linked; tmp_global.global_data_linked;
import_globals[i].is_linked = true;
} }
#else
import_globals[i].is_linked = false;
#endif #endif
import_globals[i].size = wasm_value_type_size(import_globals[i].type); import_globals[i].size = wasm_value_type_size(import_globals[i].type);

View File

@ -30,6 +30,8 @@ bh_static_assert(offsetof(WASMExecEnv, aux_stack_boundary)
bh_static_assert(offsetof(WASMExecEnv, aux_stack_bottom) bh_static_assert(offsetof(WASMExecEnv, aux_stack_bottom)
== 7 * sizeof(uintptr_t)); == 7 * sizeof(uintptr_t));
bh_static_assert(offsetof(WASMExecEnv, native_symbol) == 8 * sizeof(uintptr_t)); bh_static_assert(offsetof(WASMExecEnv, native_symbol) == 8 * sizeof(uintptr_t));
bh_static_assert(offsetof(WASMExecEnv, native_stack_top_min)
== 9 * sizeof(uintptr_t));
bh_static_assert(offsetof(AOTModuleInstance, memories) == 1 * sizeof(uint64)); bh_static_assert(offsetof(AOTModuleInstance, memories) == 1 * sizeof(uint64));
bh_static_assert(offsetof(AOTModuleInstance, func_ptrs) == 5 * sizeof(uint64)); bh_static_assert(offsetof(AOTModuleInstance, func_ptrs) == 5 * sizeof(uint64));
@ -899,83 +901,169 @@ create_exports(AOTModuleInstance *module_inst, AOTModule *module,
return create_export_funcs(module_inst, module, error_buf, error_buf_size); return create_export_funcs(module_inst, module, error_buf, error_buf_size);
} }
static bool static AOTFunctionInstance *
clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst) lookup_post_instantiate_func(AOTModuleInstance *module_inst,
const char *func_name)
{ {
#if WASM_ENABLE_LIBC_WASI != 0 AOTFunctionInstance *func;
const char *exception = aot_get_exception(module_inst); AOTFuncType *func_type;
if (exception && !strcmp(exception, "Exception: wasi proc exit")) {
/* The "wasi proc exit" exception is thrown by native lib to
let wasm app exit, which is a normal behavior, we clear
the exception here. */
aot_set_exception(module_inst, NULL);
return true;
}
return false;
#else
return false;
#endif
}
static bool if (!(func = aot_lookup_function(module_inst, func_name, NULL)))
execute_post_inst_function(AOTModuleInstance *module_inst)
{
AOTFunctionInstance *post_inst_func =
aot_lookup_function(module_inst, "__post_instantiate", "()");
if (!post_inst_func)
/* Not found */ /* Not found */
return true; return NULL;
return aot_create_exec_env_and_call_function(module_inst, post_inst_func, 0, func_type = func->u.func.func_type;
NULL); if (!(func_type->param_count == 0 && func_type->result_count == 0))
/* Not a valid function type, ignore it */
return NULL;
return func;
} }
static bool static bool
execute_start_function(AOTModuleInstance *module_inst) execute_post_instantiate_functions(AOTModuleInstance *module_inst,
bool is_sub_inst)
{ {
AOTModule *module = (AOTModule *)module_inst->module; AOTModule *module = (AOTModule *)module_inst->module;
WASMExecEnv *exec_env; AOTFunctionInstance *initialize_func = NULL;
typedef void (*F)(WASMExecEnv *); AOTFunctionInstance *post_inst_func = NULL;
union { AOTFunctionInstance *call_ctors_func = NULL;
F f; #ifdef OS_ENABLE_HW_BOUND_CHECK
void *v; WASMModuleInstanceCommon *module_inst_main = NULL;
} u; WASMExecEnv *exec_env_tls = NULL;
#endif
WASMExecEnv *exec_env = NULL;
bool ret = false;
if (!module->start_function) #if WASM_ENABLE_LIBC_WASI != 0
/*
* WASI reactor instances may assume that _initialize will be called by
* the environment at most once, and that none of their other exports
* are accessed before that call.
*/
if (!is_sub_inst && module->import_wasi_api) {
initialize_func =
lookup_post_instantiate_func(module_inst, "_initialize");
}
#endif
/* Execute possible "__post_instantiate" function if wasm app is
compiled by emsdk's early version */
if (!is_sub_inst) {
post_inst_func =
lookup_post_instantiate_func(module_inst, "__post_instantiate");
}
#if WASM_ENABLE_BULK_MEMORY != 0
/* Only execute the memory init function for main instance since
the data segments will be dropped once initialized */
if (!is_sub_inst
#if WASM_ENABLE_LIBC_WASI != 0
&& !module->import_wasi_api
#endif
) {
call_ctors_func =
lookup_post_instantiate_func(module_inst, "__wasm_call_ctors");
}
#endif
if (!module->start_function && !initialize_func && !post_inst_func
&& !call_ctors_func) {
/* No post instantiation functions to call */
return true; return true;
}
if (!(exec_env = #ifdef OS_ENABLE_HW_BOUND_CHECK
wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst, if (is_sub_inst) {
module_inst->default_wasm_stack_size))) { exec_env = exec_env_tls = wasm_runtime_get_exec_env_tls();
if (exec_env_tls) {
/* Temporarily replace exec_env_tls's module inst to current
module inst to avoid checking failure when calling the
wasm functions, and ensure that the exec_env's module inst
is the correct one. */
module_inst_main = exec_env_tls->module_inst;
exec_env_tls->module_inst = (WASMModuleInstanceCommon *)module_inst;
}
}
#endif
if (!exec_env
&& !(exec_env =
wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
module_inst->default_wasm_stack_size))) {
aot_set_exception(module_inst, "allocate memory failed"); aot_set_exception(module_inst, "allocate memory failed");
return false; return false;
} }
u.v = module->start_function; /* Execute start function for both main insance and sub instance */
u.f(exec_env); if (module->start_function) {
AOTFunctionInstance start_func = { 0 };
uint32 func_type_idx;
start_func.func_name = "";
start_func.func_index = module->start_func_index;
start_func.is_import_func = false;
func_type_idx = module->func_type_indexes[module->start_func_index
- module->import_func_count];
start_func.u.func.func_type = module->func_types[func_type_idx];
start_func.u.func.func_ptr = module->start_function;
if (!aot_call_function(exec_env, &start_func, 0, NULL)) {
goto fail;
}
}
if (initialize_func
&& !aot_call_function(exec_env, initialize_func, 0, NULL)) {
goto fail;
}
if (post_inst_func
&& !aot_call_function(exec_env, post_inst_func, 0, NULL)) {
goto fail;
}
if (call_ctors_func
&& !aot_call_function(exec_env, call_ctors_func, 0, NULL)) {
goto fail;
}
ret = true;
fail:
#ifdef OS_ENABLE_HW_BOUND_CHECK
if (is_sub_inst && exec_env_tls) {
bh_assert(exec_env == exec_env_tls);
/* Restore the exec_env_tls's module inst */
exec_env_tls->module_inst = module_inst_main;
}
else
wasm_exec_env_destroy(exec_env);
#else
wasm_exec_env_destroy(exec_env); wasm_exec_env_destroy(exec_env);
(void)clear_wasi_proc_exit_exception(module_inst);
return !aot_get_exception(module_inst);
}
#if WASM_ENABLE_BULK_MEMORY != 0
static bool
execute_memory_init_function(AOTModuleInstance *module_inst)
{
AOTFunctionInstance *memory_init_func =
aot_lookup_function(module_inst, "__wasm_call_ctors", "()");
if (!memory_init_func)
/* Not found */
return true;
return aot_create_exec_env_and_call_function(module_inst, memory_init_func,
0, NULL);
}
#endif #endif
return ret;
}
static bool
check_linked_symbol(AOTModule *module, char *error_buf, uint32 error_buf_size)
{
uint32 i;
/* init_func_ptrs() will go through import functions */
for (i = 0; i < module->import_global_count; i++) {
AOTImportGlobal *global = module->import_globals + i;
if (!global->is_linked) {
set_error_buf_v(error_buf, error_buf_size,
"failed to link import global (%s, %s)",
global->module_name, global->global_name);
return false;
}
}
return true;
}
AOTModuleInstance * AOTModuleInstance *
aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size, aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size,
uint32 heap_size, char *error_buf, uint32 error_buf_size) uint32 heap_size, char *error_buf, uint32 error_buf_size)
@ -1059,6 +1147,9 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size,
if (!init_func_type_indexes(module_inst, module, error_buf, error_buf_size)) if (!init_func_type_indexes(module_inst, module, error_buf, error_buf_size))
goto fail; goto fail;
if (!check_linked_symbol(module, error_buf, error_buf_size))
goto fail;
if (!create_exports(module_inst, module, error_buf, error_buf_size)) if (!create_exports(module_inst, module, error_buf, error_buf_size))
goto fail; goto fail;
@ -1079,6 +1170,17 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size,
} }
#endif #endif
#if WASM_ENABLE_WASI_NN != 0
if (!is_sub_inst) {
if (!(((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx =
wasi_nn_initialize())) {
set_error_buf(error_buf, error_buf_size,
"wasi nn initialization failed");
goto fail;
}
}
#endif
/* Initialize the thread related data */ /* Initialize the thread related data */
if (stack_size == 0) if (stack_size == 0)
stack_size = DEFAULT_WASM_STACK_SIZE; stack_size = DEFAULT_WASM_STACK_SIZE;
@ -1104,32 +1206,11 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size,
} }
#endif #endif
/* Execute __post_instantiate function and start function*/ if (!execute_post_instantiate_functions(module_inst, is_sub_inst)) {
if (!execute_post_inst_function(module_inst)
|| !execute_start_function(module_inst)) {
set_error_buf(error_buf, error_buf_size, module_inst->cur_exception); set_error_buf(error_buf, error_buf_size, module_inst->cur_exception);
goto fail; goto fail;
} }
#if WASM_ENABLE_BULK_MEMORY != 0
#if WASM_ENABLE_LIBC_WASI != 0
if (!module->import_wasi_api) {
#endif
/* Only execute the memory init function for main instance because
the data segments will be dropped once initialized.
*/
if (!is_sub_inst) {
if (!execute_memory_init_function(module_inst)) {
set_error_buf(error_buf, error_buf_size,
module_inst->cur_exception);
goto fail;
}
}
#if WASM_ENABLE_LIBC_WASI != 0
}
#endif
#endif
#if WASM_ENABLE_MEMORY_TRACING != 0 #if WASM_ENABLE_MEMORY_TRACING != 0
wasm_runtime_dump_module_inst_mem_consumption( wasm_runtime_dump_module_inst_mem_consumption(
(WASMModuleInstanceCommon *)module_inst); (WASMModuleInstanceCommon *)module_inst);
@ -1145,6 +1226,15 @@ fail:
void void
aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst) aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
{ {
if (module_inst->exec_env_singleton) {
/* wasm_exec_env_destroy will call
wasm_cluster_wait_for_all_except_self to wait for other
threads, so as to destroy their exec_envs and module
instances first, and avoid accessing the shared resources
of current module instance after it is deinstantiated. */
wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton);
}
#if WASM_ENABLE_LIBC_WASI != 0 #if WASM_ENABLE_LIBC_WASI != 0
/* Destroy wasi resource before freeing app heap, since some fields of /* Destroy wasi resource before freeing app heap, since some fields of
wasi contex are allocated from app heap, and if app heap is freed, wasi contex are allocated from app heap, and if app heap is freed,
@ -1183,13 +1273,19 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
if (module_inst->func_type_indexes) if (module_inst->func_type_indexes)
wasm_runtime_free(module_inst->func_type_indexes); wasm_runtime_free(module_inst->func_type_indexes);
if (module_inst->exec_env_singleton)
wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton);
if (((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports) if (((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports)
wasm_runtime_free( wasm_runtime_free(
((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports); ((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports);
#if WASM_ENABLE_WASI_NN != 0
if (!is_sub_inst) {
WASINNContext *wasi_nn_ctx =
((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx;
if (wasi_nn_ctx)
wasi_nn_destroy(wasi_nn_ctx);
}
#endif
wasm_runtime_free(module_inst); wasm_runtime_free(module_inst);
} }
@ -1233,6 +1329,7 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
/* Check native stack overflow firstly to ensure we have enough /* Check native stack overflow firstly to ensure we have enough
native stack to run the following codes before actually calling native stack to run the following codes before actually calling
the aot function in invokeNative function. */ the aot function in invokeNative function. */
RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst);
if ((uint8 *)&module_inst < exec_env->native_stack_boundary if ((uint8 *)&module_inst < exec_env->native_stack_boundary
+ page_size * (guard_page_count + 1)) { + page_size * (guard_page_count + 1)) {
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
@ -1384,13 +1481,6 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
ret = invoke_native_internal(exec_env, function->u.func.func_ptr, ret = invoke_native_internal(exec_env, function->u.func.func_ptr,
func_type, NULL, NULL, argv1, argc, argv); func_type, NULL, NULL, argv1, argc, argv);
if (!ret || aot_get_exception(module_inst)) {
if (clear_wasi_proc_exit_exception(module_inst))
ret = true;
else
ret = false;
}
#if WASM_ENABLE_DUMP_CALL_STACK != 0 #if WASM_ENABLE_DUMP_CALL_STACK != 0
if (!ret) { if (!ret) {
if (aot_create_call_stack(exec_env)) { if (aot_create_call_stack(exec_env)) {
@ -1450,9 +1540,6 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
ret = invoke_native_internal(exec_env, function->u.func.func_ptr, ret = invoke_native_internal(exec_env, function->u.func.func_ptr,
func_type, NULL, NULL, argv, argc, argv); func_type, NULL, NULL, argv, argc, argv);
if (clear_wasi_proc_exit_exception(module_inst))
ret = true;
#if WASM_ENABLE_DUMP_CALL_STACK != 0 #if WASM_ENABLE_DUMP_CALL_STACK != 0
if (aot_get_exception(module_inst)) { if (aot_get_exception(module_inst)) {
if (aot_create_call_stack(exec_env)) { if (aot_create_call_stack(exec_env)) {
@ -1493,7 +1580,7 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
} }
} }
ret = aot_call_function(exec_env, func, argc, argv); ret = wasm_runtime_call_wasm(exec_env, func, argc, argv);
/* don't destroy the exec_env if it isn't created in this function */ /* don't destroy the exec_env if it isn't created in this function */
if (!existing_exec_env) if (!existing_exec_env)
@ -1764,7 +1851,9 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
AOTModuleInstanceExtra *module_inst_extra = AOTModuleInstanceExtra *module_inst_extra =
(AOTModuleInstanceExtra *)module_inst->e; (AOTModuleInstanceExtra *)module_inst->e;
CApiFuncImport *c_api_func_import = CApiFuncImport *c_api_func_import =
module_inst_extra->c_api_func_imports + func_idx; module_inst_extra->c_api_func_imports
? module_inst_extra->c_api_func_imports + func_idx
: NULL;
uint32 *func_type_indexes = module_inst->func_type_indexes; uint32 *func_type_indexes = module_inst->func_type_indexes;
uint32 func_type_idx = func_type_indexes[func_idx]; uint32 func_type_idx = func_type_indexes[func_idx];
AOTFuncType *func_type = aot_module->func_types[func_type_idx]; AOTFuncType *func_type = aot_module->func_types[func_type_idx];
@ -1780,7 +1869,8 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
import_func = aot_module->import_funcs + func_idx; import_func = aot_module->import_funcs + func_idx;
if (import_func->call_conv_wasm_c_api) if (import_func->call_conv_wasm_c_api)
func_ptr = c_api_func_import->func_ptr_linked; func_ptr =
c_api_func_import ? c_api_func_import->func_ptr_linked : NULL;
if (!func_ptr) { if (!func_ptr) {
snprintf(buf, sizeof(buf), snprintf(buf, sizeof(buf),
@ -1839,6 +1929,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
exec_env->native_stack_boundary must have been set, we don't set exec_env->native_stack_boundary must have been set, we don't set
it again */ it again */
RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst);
if ((uint8 *)&module_inst < exec_env->native_stack_boundary) { if ((uint8 *)&module_inst < exec_env->native_stack_boundary) {
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
goto fail; goto fail;
@ -1980,9 +2071,6 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
} }
fail: fail:
if (clear_wasi_proc_exit_exception(module_inst))
return true;
#ifdef OS_ENABLE_HW_BOUND_CHECK #ifdef OS_ENABLE_HW_BOUND_CHECK
wasm_runtime_access_exce_check_guard_page(); wasm_runtime_access_exce_check_guard_page();
#endif #endif

View File

@ -11,6 +11,10 @@
#include "../interpreter/wasm_runtime.h" #include "../interpreter/wasm_runtime.h"
#include "../compilation/aot.h" #include "../compilation/aot.h"
#if WASM_ENABLE_WASI_NN != 0
#include "../libraries/wasi-nn/src/wasi_nn_private.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -75,6 +79,9 @@ typedef struct AOTFunctionInstance {
typedef struct AOTModuleInstanceExtra { typedef struct AOTModuleInstanceExtra {
CApiFuncImport *c_api_func_imports; CApiFuncImport *c_api_func_imports;
#if WASM_ENABLE_WASI_NN != 0
WASINNContext *wasi_nn_ctx;
#endif
} AOTModuleInstanceExtra; } AOTModuleInstanceExtra;
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS) #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)

View File

@ -16,9 +16,14 @@ _invokeNative:
push %ebp push %ebp
movl %esp, %ebp movl %esp, %ebp
movl 16(%ebp), %ecx /* ecx = argc */ movl 16(%ebp), %ecx /* ecx = argc */
movl 12(%ebp), %edx /* edx = argv */ leal 2(%ecx), %edx /* edx = ecx + 2 (count return address and saved ebp) */
andl $3, %edx /* edx = edx % 4 */
jz stack_aligned /* if edx == 0, stack is already 16 bytes aligned */
leal -16(%esp, %edx, 4), %esp /* esp = esp - 16 + edx * 4 */
stack_aligned:
test %ecx, %ecx test %ecx, %ecx
jz skip_push_args /* if ecx == 0, skip pushing arguments */ jz skip_push_args /* if ecx == 0, skip pushing arguments */
movl 12(%ebp), %edx /* edx = argv */
leal -4(%edx,%ecx,4), %edx /* edx = edx + ecx * 4 - 4 */ leal -4(%edx,%ecx,4), %edx /* edx = edx + ecx * 4 - 4 */
subl %esp, %edx /* edx = edx - esp */ subl %esp, %edx /* edx = edx - esp */
1: 1:

View File

@ -203,22 +203,12 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
char *argv[]) char *argv[])
{ {
bool ret; bool ret;
#if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_MEMORY_PROFILING != 0
WASMCluster *cluster;
#endif
#if WASM_ENABLE_THREAD_MGR != 0 || WASM_ENABLE_MEMORY_PROFILING != 0
WASMExecEnv *exec_env; WASMExecEnv *exec_env;
#endif #endif
ret = execute_main(module_inst, argc, argv); ret = execute_main(module_inst, argc, argv);
#if WASM_ENABLE_THREAD_MGR != 0
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (exec_env && (cluster = wasm_exec_env_get_cluster(exec_env))) {
wasm_cluster_wait_for_all_except_self(cluster, exec_env);
}
#endif
#if WASM_ENABLE_MEMORY_PROFILING != 0 #if WASM_ENABLE_MEMORY_PROFILING != 0
exec_env = wasm_runtime_get_exec_env_singleton(module_inst); exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (exec_env) { if (exec_env) {
@ -622,22 +612,12 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
const char *name, int32 argc, char *argv[]) const char *name, int32 argc, char *argv[])
{ {
bool ret; bool ret;
#if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_MEMORY_PROFILING != 0
WASMCluster *cluster;
#endif
#if WASM_ENABLE_THREAD_MGR != 0 || WASM_ENABLE_MEMORY_PROFILING != 0
WASMExecEnv *exec_env; WASMExecEnv *exec_env;
#endif #endif
ret = execute_func(module_inst, name, argc, argv); ret = execute_func(module_inst, name, argc, argv);
#if WASM_ENABLE_THREAD_MGR != 0
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (exec_env && (cluster = wasm_exec_env_get_cluster(exec_env))) {
wasm_cluster_wait_for_all_except_self(cluster, exec_env);
}
#endif
#if WASM_ENABLE_MEMORY_PROFILING != 0 #if WASM_ENABLE_MEMORY_PROFILING != 0
exec_env = wasm_runtime_get_exec_env_singleton(module_inst); exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (exec_env) { if (exec_env) {

View File

@ -276,7 +276,7 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete) WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
#ifndef NDEBUG #ifndef NDEBUG
#if WAMR_BUILD_MEMORY_PROFILING != 0 #if WASM_ENABLE_MEMORY_PROFILING != 0
#define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM() #define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM()
#else #else
#define WASM_C_DUMP_PROC_MEM() (void)0 #define WASM_C_DUMP_PROC_MEM() (void)0
@ -398,7 +398,7 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
} }
/* global engine instance */ /* global engine instance */
static wasm_engine_t *singleton_engine = NULL; static wasm_engine_t *singleton_engine;
#ifdef os_thread_local_attribute #ifdef os_thread_local_attribute
/* categorize wasm_store_t as threads*/ /* categorize wasm_store_t as threads*/
static os_thread_local_attribute unsigned thread_local_stores_num = 0; static os_thread_local_attribute unsigned thread_local_stores_num = 0;
@ -1458,6 +1458,30 @@ wasm_importtype_type(const wasm_importtype_t *import_type)
return import_type->extern_type; return import_type->extern_type;
} }
bool
wasm_importtype_is_linked(const wasm_importtype_t *import_type)
{
if (!import_type)
return false;
const wasm_name_t *module_name = wasm_importtype_module(import_type);
const wasm_name_t *field_name = wasm_importtype_name(import_type);
switch (wasm_externtype_kind(wasm_importtype_type(import_type))) {
case WASM_EXTERN_FUNC:
return wasm_runtime_is_import_func_linked(module_name->data,
field_name->data);
case WASM_EXTERN_GLOBAL:
return wasm_runtime_is_import_global_linked(module_name->data,
field_name->data);
case WASM_EXTERN_MEMORY:
case WASM_EXTERN_TABLE:
default:
break;
}
return false;
}
own wasm_exporttype_t * own wasm_exporttype_t *
wasm_exporttype_new(own wasm_byte_vec_t *name, wasm_exporttype_new(own wasm_byte_vec_t *name,
own wasm_externtype_t *extern_type) own wasm_externtype_t *extern_type)
@ -1633,8 +1657,6 @@ wasm_val_to_rt_val(WASMModuleInstanceCommon *inst_comm_rt, uint8 val_type_rt,
ret = ret =
wasm_externref_obj2ref(inst_comm_rt, v->of.ref, (uint32 *)data); wasm_externref_obj2ref(inst_comm_rt, v->of.ref, (uint32 *)data);
break; break;
#else
(void)inst_comm_rt;
#endif #endif
default: default:
LOG_WARNING("unexpected value type %d", val_type_rt); LOG_WARNING("unexpected value type %d", val_type_rt);
@ -1642,6 +1664,7 @@ wasm_val_to_rt_val(WASMModuleInstanceCommon *inst_comm_rt, uint8 val_type_rt,
break; break;
} }
(void)inst_comm_rt;
return ret; return ret;
} }
@ -2537,12 +2560,12 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
bh_assert(extern_type); bh_assert(extern_type);
wasm_name_new_from_string(&module_name, module_name_rt); wasm_name_new_from_string_nt(&module_name, module_name_rt);
if (strlen(module_name_rt) && !module_name.data) { if (strlen(module_name_rt) && !module_name.data) {
goto failed; goto failed;
} }
wasm_name_new_from_string(&name, field_name_rt); wasm_name_new_from_string_nt(&name, field_name_rt);
if (strlen(field_name_rt) && !name.data) { if (strlen(field_name_rt) && !name.data) {
goto failed; goto failed;
} }
@ -2622,7 +2645,7 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
} }
/* byte* -> wasm_byte_vec_t */ /* byte* -> wasm_byte_vec_t */
wasm_name_new_from_string(&name, export->name); wasm_name_new_from_string_nt(&name, export->name);
if (strlen(export->name) && !name.data) { if (strlen(export->name) && !name.data) {
goto failed; goto failed;
} }
@ -3008,6 +3031,20 @@ failed:
return NULL; return NULL;
} }
static wasm_func_t *
wasm_func_new_empty(wasm_store_t *store)
{
wasm_func_t *func = NULL;
if (!(func = malloc_internal(sizeof(wasm_func_t))))
goto failed;
func->store = store;
func->kind = WASM_EXTERN_FUNC;
RETURN_OBJ(func, wasm_func_delete)
}
void void
wasm_func_delete(wasm_func_t *func) wasm_func_delete(wasm_func_t *func)
{ {
@ -3211,7 +3248,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
wasm_name_t message = { 0 }; wasm_name_t message = { 0 };
wasm_trap_t *trap; wasm_trap_t *trap;
wasm_name_new_from_string(&message, "failed to call unlinked function"); wasm_name_new_from_string_nt(&message,
"failed to call unlinked function");
trap = wasm_trap_new(func->store, &message); trap = wasm_trap_new(func->store, &message);
wasm_byte_vec_delete(&message); wasm_byte_vec_delete(&message);
@ -3371,6 +3409,25 @@ failed:
return NULL; return NULL;
} }
static wasm_global_t *
wasm_global_new_empty(wasm_store_t *store)
{
wasm_global_t *global = NULL;
global = malloc_internal(sizeof(wasm_global_t));
if (!global)
goto failed;
global->store = store;
global->kind = WASM_EXTERN_GLOBAL;
return global;
failed:
LOG_DEBUG("%s failed", __FUNCTION__);
wasm_global_delete(global);
return NULL;
}
/* almost same with wasm_global_new */ /* almost same with wasm_global_new */
wasm_global_t * wasm_global_t *
wasm_global_copy(const wasm_global_t *src) wasm_global_copy(const wasm_global_t *src)
@ -4205,7 +4262,8 @@ wasm_memory_data_size(const wasm_memory_t *memory)
(WASMModuleInstance *)module_inst_comm; (WASMModuleInstance *)module_inst_comm;
WASMMemoryInstance *memory_inst = WASMMemoryInstance *memory_inst =
module_inst->memories[memory->memory_idx_rt]; module_inst->memories[memory->memory_idx_rt];
return memory_inst->cur_page_count * memory_inst->num_bytes_per_page; return (size_t)memory_inst->cur_page_count
* memory_inst->num_bytes_per_page;
} }
#endif #endif
@ -4215,7 +4273,8 @@ wasm_memory_data_size(const wasm_memory_t *memory)
AOTMemoryInstance *memory_inst = AOTMemoryInstance *memory_inst =
((AOTMemoryInstance **) ((AOTMemoryInstance **)
module_inst->memories)[memory->memory_idx_rt]; module_inst->memories)[memory->memory_idx_rt];
return memory_inst->cur_page_count * memory_inst->num_bytes_per_page; return (size_t)memory_inst->cur_page_count
* memory_inst->num_bytes_per_page;
} }
#endif #endif
@ -4286,6 +4345,11 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp,
imported_func_interp = module_interp->import_functions + func_idx_rt; imported_func_interp = module_interp->import_functions + func_idx_rt;
bh_assert(imported_func_interp); bh_assert(imported_func_interp);
bh_assert(imported_func_interp->kind == IMPORT_KIND_FUNC);
/* it is a placeholder and let's skip it*/
if (!import->type)
return true;
/* type comparison */ /* type comparison */
if (!wasm_functype_same_internal( if (!wasm_functype_same_internal(
@ -4300,6 +4364,8 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp,
imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb; imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb;
else else
imported_func_interp->u.function.func_ptr_linked = import->u.cb; imported_func_interp->u.function.func_ptr_linked = import->u.cb;
bh_assert(imported_func_interp->u.function.func_ptr_linked);
import->func_idx_rt = func_idx_rt; import->func_idx_rt = func_idx_rt;
(void)inst; (void)inst;
@ -4318,12 +4384,19 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt,
imported_global_interp = module_interp->import_globals + global_idx_rt; imported_global_interp = module_interp->import_globals + global_idx_rt;
bh_assert(imported_global_interp); bh_assert(imported_global_interp);
bh_assert(imported_global_interp->kind == IMPORT_KIND_GLOBAL);
/* it is a placeholder and let's skip it*/
if (!import->type)
return true;
/* type comparison */
if (!cmp_val_kind_with_val_type(wasm_valtype_kind(import->type->val_type), if (!cmp_val_kind_with_val_type(wasm_valtype_kind(import->type->val_type),
imported_global_interp->u.global.type)) imported_global_interp->u.global.type))
return false; return false;
/* set init value */ /* set init value */
bh_assert(import->init);
switch (wasm_valtype_kind(import->type->val_type)) { switch (wasm_valtype_kind(import->type->val_type)) {
case WASM_I32: case WASM_I32:
imported_global_interp->u.global.global_data_linked.i32 = imported_global_interp->u.global.global_data_linked.i32 =
@ -4350,58 +4423,6 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt,
return true; return true;
} }
static bool
interp_link(const wasm_instance_t *inst, const WASMModule *module_interp,
wasm_extern_t *imports[])
{
uint32 i = 0;
uint32 import_func_i = 0;
uint32 import_global_i = 0;
bh_assert(inst && module_interp && imports);
for (i = 0; i < module_interp->import_count; ++i) {
wasm_extern_t *import = imports[i];
WASMImport *import_rt = module_interp->imports + i;
switch (import_rt->kind) {
case IMPORT_KIND_FUNC:
{
if (!interp_link_func(inst, module_interp, import_func_i,
wasm_extern_as_func(import))) {
LOG_WARNING("link #%d function failed", import_func_i);
goto failed;
}
import_func_i++;
break;
}
case IMPORT_KIND_GLOBAL:
{
if (!interp_link_global(module_interp, import_global_i,
wasm_extern_as_global(import))) {
LOG_WARNING("link #%d global failed", import_global_i);
goto failed;
}
import_global_i++;
break;
}
case IMPORT_KIND_MEMORY:
case IMPORT_KIND_TABLE:
default:
ASSERT_NOT_IMPLEMENTED();
LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
import_rt->kind);
goto failed;
}
}
return true;
failed:
LOG_DEBUG("%s failed", __FUNCTION__);
return false;
}
static bool static bool
interp_process_export(wasm_store_t *store, interp_process_export(wasm_store_t *store,
const WASMModuleInstance *inst_interp, const WASMModuleInstance *inst_interp,
@ -4501,6 +4522,10 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot,
import_aot_func = module_aot->import_funcs + import_func_idx_rt; import_aot_func = module_aot->import_funcs + import_func_idx_rt;
bh_assert(import_aot_func); bh_assert(import_aot_func);
/* it is a placeholder and let's skip it*/
if (!import->type)
return true;
/* type comparison */ /* type comparison */
if (!wasm_functype_same_internal(import->type, import_aot_func->func_type)) if (!wasm_functype_same_internal(import->type, import_aot_func->func_type))
return false; return false;
@ -4513,6 +4538,8 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot,
import_aot_func->func_ptr_linked = import->u.cb_env.cb; import_aot_func->func_ptr_linked = import->u.cb_env.cb;
else else
import_aot_func->func_ptr_linked = import->u.cb; import_aot_func->func_ptr_linked = import->u.cb;
bh_assert(import_aot_func->func_ptr_linked);
import->func_idx_rt = import_func_idx_rt; import->func_idx_rt = import_func_idx_rt;
return true; return true;
@ -4530,6 +4557,10 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
import_aot_global = module_aot->import_globals + global_idx_rt; import_aot_global = module_aot->import_globals + global_idx_rt;
bh_assert(import_aot_global); bh_assert(import_aot_global);
/* it is a placeholder and let's skip it*/
if (!import->type)
return true;
val_type = wasm_globaltype_content(import->type); val_type = wasm_globaltype_content(import->type);
bh_assert(val_type); bh_assert(val_type);
@ -4537,6 +4568,7 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
import_aot_global->type)) import_aot_global->type))
return false; return false;
bh_assert(import->init);
switch (wasm_valtype_kind(val_type)) { switch (wasm_valtype_kind(val_type)) {
case WASM_I32: case WASM_I32:
import_aot_global->global_data_linked.i32 = import->init->of.i32; import_aot_global->global_data_linked.i32 = import->init->of.i32;
@ -4555,63 +4587,8 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
} }
import->global_idx_rt = global_idx_rt; import->global_idx_rt = global_idx_rt;
import_aot_global->is_linked = true;
return true; return true;
failed:
LOG_DEBUG("%s failed", __FUNCTION__);
return false;
}
static bool
aot_link(const wasm_instance_t *inst, const AOTModule *module_aot,
wasm_extern_t *imports[])
{
uint32 i = 0;
uint32 import_func_i = 0;
uint32 import_global_i = 0;
wasm_extern_t *import = NULL;
wasm_func_t *func = NULL;
wasm_global_t *global = NULL;
bh_assert(inst && module_aot && imports);
while (import_func_i < module_aot->import_func_count
|| import_global_i < module_aot->import_global_count) {
import = imports[i++];
bh_assert(import);
switch (wasm_extern_kind(import)) {
case WASM_EXTERN_FUNC:
bh_assert(import_func_i < module_aot->import_func_count);
func = wasm_extern_as_func((wasm_extern_t *)import);
if (!aot_link_func(inst, module_aot, import_func_i, func)) {
LOG_WARNING("link #%d function failed", import_func_i);
goto failed;
}
import_func_i++;
break;
case WASM_EXTERN_GLOBAL:
bh_assert(import_global_i < module_aot->import_global_count);
global = wasm_extern_as_global((wasm_extern_t *)import);
if (!aot_link_global(module_aot, import_global_i, global)) {
LOG_WARNING("link #%d global failed", import_global_i);
goto failed;
}
import_global_i++;
break;
case WASM_EXTERN_MEMORY:
case WASM_EXTERN_TABLE:
default:
ASSERT_NOT_IMPLEMENTED();
goto failed;
}
}
return true;
failed: failed:
LOG_DEBUG("%s failed", __FUNCTION__); LOG_DEBUG("%s failed", __FUNCTION__);
return false; return false;
@ -4692,7 +4669,7 @@ aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot,
goto failed; goto failed;
} }
wasm_name_new_from_string(external->name, export->name); wasm_name_new_from_string_nt(external->name, export->name);
if (strlen(export->name) && !external->name->data) { if (strlen(export->name) && !external->name->data) {
goto failed; goto failed;
} }
@ -4710,6 +4687,95 @@ failed:
} }
#endif /* WASM_ENABLE_AOT */ #endif /* WASM_ENABLE_AOT */
static bool
do_link(const wasm_instance_t *inst, const wasm_module_t *module,
const wasm_extern_vec_t *imports)
{
uint32 i, import_func_i, import_global_i;
bh_assert(inst && module);
/* we have run a module_type check before. */
for (i = 0, import_func_i = 0, import_global_i = 0; i < imports->num_elems;
i++) {
wasm_extern_t *import = imports->data[i];
if (!import) {
LOG_ERROR("imports[%d] is NULL and it is fatal\n", i);
goto failed;
}
switch (wasm_extern_kind(import)) {
case WASM_EXTERN_FUNC:
{
bool ret = false;
#if WASM_ENABLE_INTERP != 0
if ((*module)->module_type == Wasm_Module_Bytecode) {
ret = interp_link_func(inst, MODULE_INTERP(module),
import_func_i,
wasm_extern_as_func(import));
}
#endif
#if WASM_ENABLE_AOT != 0
if ((*module)->module_type == Wasm_Module_AoT) {
ret = aot_link_func(inst, MODULE_AOT(module), import_func_i,
wasm_extern_as_func(import));
}
#endif
if (!ret) {
LOG_WARNING("link function #%d failed", import_func_i);
goto failed;
}
import_func_i++;
break;
}
case WASM_EXTERN_GLOBAL:
{
bool ret = false;
#if WASM_ENABLE_INTERP != 0
if ((*module)->module_type == Wasm_Module_Bytecode) {
ret = interp_link_global(MODULE_INTERP(module),
import_global_i,
wasm_extern_as_global(import));
}
#endif
#if WASM_ENABLE_AOT != 0
if ((*module)->module_type == Wasm_Module_AoT) {
ret = aot_link_global(MODULE_AOT(module), import_global_i,
wasm_extern_as_global(import));
}
#endif
if (!ret) {
LOG_WARNING("link global #%d failed", import_global_i);
goto failed;
}
import_global_i++;
break;
}
case WASM_EXTERN_MEMORY:
case WASM_EXTERN_TABLE:
{
LOG_WARNING("doesn't support import memories and tables for "
"now, ignore them");
break;
}
default:
{
UNREACHABLE();
break;
}
}
}
return true;
failed:
LOG_DEBUG("%s failed", __FUNCTION__);
return false;
}
wasm_instance_t * wasm_instance_t *
wasm_instance_new(wasm_store_t *store, const wasm_module_t *module, wasm_instance_new(wasm_store_t *store, const wasm_module_t *module,
const wasm_extern_vec_t *imports, own wasm_trap_t **trap) const wasm_extern_vec_t *imports, own wasm_trap_t **trap)
@ -4718,57 +4784,6 @@ wasm_instance_new(wasm_store_t *store, const wasm_module_t *module,
KILOBYTE(32), KILOBYTE(32)); KILOBYTE(32), KILOBYTE(32));
} }
static bool
compare_imports(const wasm_module_t *module, const wasm_extern_vec_t *imports)
{
unsigned import_func_count = 0;
unsigned import_global_count = 0;
unsigned import_memory_count = 0;
unsigned import_table_count = 0;
unsigned i = 0;
for (i = 0; imports && i < imports->num_elems; i++) {
wasm_extern_t *import = imports->data[i];
switch (wasm_extern_kind(import)) {
case WASM_EXTERN_FUNC:
import_func_count++;
break;
case WASM_EXTERN_GLOBAL:
import_global_count++;
break;
case WASM_EXTERN_MEMORY:
import_memory_count++;
break;
case WASM_EXTERN_TABLE:
import_table_count++;
break;
default:
UNREACHABLE();
return false;
}
}
#if WASM_ENABLE_INTERP != 0
if ((*module)->module_type == Wasm_Module_Bytecode)
return import_func_count == MODULE_INTERP(module)->import_function_count
&& import_global_count
== MODULE_INTERP(module)->import_global_count
&& import_memory_count
== MODULE_INTERP(module)->import_memory_count
&& import_table_count
== MODULE_INTERP(module)->import_table_count;
#endif
#if WASM_ENABLE_AOT != 0
if ((*module)->module_type == Wasm_Module_AoT)
return import_func_count == MODULE_AOT(module)->import_func_count
&& import_global_count == MODULE_AOT(module)->import_global_count
&& import_memory_count == MODULE_AOT(module)->import_memory_count
&& import_table_count == MODULE_AOT(module)->import_table_count;
#endif
return false;
}
wasm_instance_t * wasm_instance_t *
wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module, wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
const wasm_extern_vec_t *imports, const wasm_extern_vec_t *imports,
@ -4778,7 +4793,6 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
char sub_error_buf[128] = { 0 }; char sub_error_buf[128] = { 0 };
char error_buf[256] = { 0 }; char error_buf[256] = { 0 };
wasm_instance_t *instance = NULL; wasm_instance_t *instance = NULL;
WASMModuleInstance *inst_rt;
CApiFuncImport *func_import = NULL, **p_func_imports = NULL; CApiFuncImport *func_import = NULL, **p_func_imports = NULL;
uint32 i = 0, import_func_count = 0; uint32 i = 0, import_func_count = 0;
uint64 total_size; uint64 total_size;
@ -4789,11 +4803,9 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
if (!module) if (!module)
return NULL; return NULL;
if (!compare_imports(module, imports)) { /*
snprintf(sub_error_buf, sizeof(sub_error_buf), * will do the check at the end of wasm_runtime_instantiate
"Failed to match imports"); */
goto failed;
}
WASM_C_DUMP_PROC_MEM(); WASM_C_DUMP_PROC_MEM();
@ -4804,43 +4816,17 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
goto failed; goto failed;
} }
/* link module and imports */ /* executes the instantiate-time linking if provided */
if (imports && imports->num_elems) { if (imports) {
bool link = false; if (!do_link(instance, module, imports)) {
#if WASM_ENABLE_INTERP != 0
if ((*module)->module_type == Wasm_Module_Bytecode) {
if (!interp_link(instance, MODULE_INTERP(module),
(wasm_extern_t **)imports->data)) {
snprintf(sub_error_buf, sizeof(sub_error_buf),
"Failed to validate imports");
goto failed;
}
link = true;
}
#endif
#if WASM_ENABLE_AOT != 0
if ((*module)->module_type == Wasm_Module_AoT) {
if (!aot_link(instance, MODULE_AOT(module),
(wasm_extern_t **)imports->data)) {
snprintf(sub_error_buf, sizeof(sub_error_buf),
"Failed to validate imports");
goto failed;
}
link = true;
}
#endif
/*
* a wrong combination of module filetype and compilation flags
* also leads to below branch
*/
if (!link) {
snprintf(sub_error_buf, sizeof(sub_error_buf), snprintf(sub_error_buf, sizeof(sub_error_buf),
"Failed to verify import count"); "Failed to validate imports");
goto failed; goto failed;
} }
} }
/*
* will do the linking result check at the end of wasm_runtime_instantiate
*/
instance->inst_comm_rt = wasm_runtime_instantiate( instance->inst_comm_rt = wasm_runtime_instantiate(
*module, stack_size, heap_size, sub_error_buf, sizeof(sub_error_buf)); *module, stack_size, heap_size, sub_error_buf, sizeof(sub_error_buf));
@ -4855,18 +4841,22 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
} }
/* create the c-api func import list */ /* create the c-api func import list */
inst_rt = (WASMModuleInstance *)instance->inst_comm_rt;
#if WASM_ENABLE_INTERP != 0 #if WASM_ENABLE_INTERP != 0
if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) { if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
p_func_imports = &inst_rt->e->c_api_func_imports; WASMModuleInstanceExtra *e =
import_func_count = inst_rt->module->import_function_count; ((WASMModuleInstance *)instance->inst_comm_rt)->e;
p_func_imports = &(e->c_api_func_imports);
import_func_count = MODULE_INTERP(module)->import_function_count;
} }
#endif #endif
#if WASM_ENABLE_AOT != 0 #if WASM_ENABLE_AOT != 0
if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) { if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) {
p_func_imports = AOTModuleInstanceExtra *e =
&((AOTModuleInstanceExtra *)inst_rt->e)->c_api_func_imports; (AOTModuleInstanceExtra *)((AOTModuleInstance *)
import_func_count = ((AOTModule *)inst_rt->module)->import_func_count; instance->inst_comm_rt)
->e;
p_func_imports = &(e->c_api_func_imports);
import_func_count = MODULE_AOT(module)->import_func_count;
} }
#endif #endif
bh_assert(p_func_imports); bh_assert(p_func_imports);
@ -4879,16 +4869,21 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
goto failed; goto failed;
} }
/* fill in c-api func import list */ /* fill in module_inst->e->c_api_func_imports */
for (i = 0; imports && i < imports->num_elems; i++) { for (i = 0; imports && i < imports->num_elems; i++) {
wasm_func_t *func_host; wasm_func_t *func_host = NULL;
wasm_extern_t *in; wasm_extern_t *in = imports->data[i];
bh_assert(in);
in = imports->data[i];
if (wasm_extern_kind(in) != WASM_EXTERN_FUNC) if (wasm_extern_kind(in) != WASM_EXTERN_FUNC)
continue; continue;
func_host = wasm_extern_as_func(in); func_host = wasm_extern_as_func(in);
/* it is a placeholder and let's skip it*/
if (!func_host->type) {
func_import++;
continue;
}
func_import->with_env_arg = func_host->with_env; func_import->with_env_arg = func_host->with_env;
if (func_host->with_env) { if (func_host->with_env) {
@ -4899,6 +4894,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
func_import->func_ptr_linked = func_host->u.cb; func_import->func_ptr_linked = func_host->u.cb;
func_import->env_arg = NULL; func_import->env_arg = NULL;
} }
bh_assert(func_import->func_ptr_linked);
func_import++; func_import++;
} }
@ -4906,6 +4902,8 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
/* fill with inst */ /* fill with inst */
for (i = 0; imports && imports->data && i < imports->num_elems; ++i) { for (i = 0; imports && imports->data && i < imports->num_elems; ++i) {
wasm_extern_t *import = imports->data[i]; wasm_extern_t *import = imports->data[i];
bh_assert(import);
switch (import->kind) { switch (import->kind) {
case WASM_EXTERN_FUNC: case WASM_EXTERN_FUNC:
wasm_extern_as_func(import)->inst_comm_rt = wasm_extern_as_func(import)->inst_comm_rt =
@ -5001,7 +4999,7 @@ failed:
sub_error_buf); sub_error_buf);
if (trap != NULL) { if (trap != NULL) {
wasm_message_t message = { 0 }; wasm_message_t message = { 0 };
wasm_name_new_from_string(&message, error_buf); wasm_name_new_from_string_nt(&message, error_buf);
*trap = wasm_trap_new(store, &message); *trap = wasm_trap_new(store, &message);
wasm_byte_vec_delete(&message); wasm_byte_vec_delete(&message);
} }
@ -5201,3 +5199,16 @@ BASIC_FOUR_LIST(WASM_EXTERN_AS_OTHER_CONST)
BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN_CONST) BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN_CONST)
#undef WASM_OTHER_AS_EXTERN_CONST #undef WASM_OTHER_AS_EXTERN_CONST
wasm_extern_t *
wasm_extern_new_empty(wasm_store_t *store, wasm_externkind_t extern_kind)
{
if (extern_kind == WASM_EXTERN_FUNC)
return wasm_func_as_extern(wasm_func_new_empty(store));
if (extern_kind == WASM_EXTERN_GLOBAL)
return wasm_global_as_extern(wasm_global_new_empty(store));
LOG_ERROR("Don't support linking table and memory for now");
return NULL;
}

View File

@ -172,15 +172,18 @@ void
wasm_exec_env_destroy(WASMExecEnv *exec_env) wasm_exec_env_destroy(WASMExecEnv *exec_env)
{ {
#if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_THREAD_MGR != 0
/* Terminate all sub-threads */ /* Wait for all sub-threads */
WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
if (cluster) { if (cluster) {
wasm_cluster_terminate_all_except_self(cluster, exec_env); wasm_cluster_wait_for_all_except_self(cluster, exec_env);
#if WASM_ENABLE_DEBUG_INTERP != 0 #if WASM_ENABLE_DEBUG_INTERP != 0
/* Must fire exit event after other threads exits, otherwise /* Must fire exit event after other threads exits, otherwise
the stopped thread will be overrided by other threads */ the stopped thread will be overrided by other threads */
wasm_cluster_thread_exited(exec_env); wasm_cluster_thread_exited(exec_env);
#endif #endif
/* We have waited for other threads, this is the only alive thread, so
* we don't acquire cluster->lock because the cluster will be destroyed
* inside this function */
wasm_cluster_del_exec_env(cluster, exec_env); wasm_cluster_del_exec_env(cluster, exec_env);
} }
#endif /* end of WASM_ENABLE_THREAD_MGR */ #endif /* end of WASM_ENABLE_THREAD_MGR */
@ -205,9 +208,17 @@ void
wasm_exec_env_set_thread_info(WASMExecEnv *exec_env) wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
{ {
uint8 *stack_boundary = os_thread_get_stack_boundary(); uint8 *stack_boundary = os_thread_get_stack_boundary();
#if WASM_ENABLE_THREAD_MGR != 0
os_mutex_lock(&exec_env->wait_lock);
#endif
exec_env->handle = os_self_thread(); exec_env->handle = os_self_thread();
exec_env->native_stack_boundary = exec_env->native_stack_boundary =
stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL; stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL;
exec_env->native_stack_top_min = (void *)UINTPTR_MAX;
#if WASM_ENABLE_THREAD_MGR != 0
os_mutex_unlock(&exec_env->wait_lock);
#endif
} }
#if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_THREAD_MGR != 0

View File

@ -84,6 +84,12 @@ typedef struct WASMExecEnv {
void **native_symbol; void **native_symbol;
#endif #endif
/*
* The lowest stack pointer value observed.
* Assumption: native stack grows to the lower address.
*/
uint8 *native_stack_top_min;
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
/** /**
* Cache for * Cache for
@ -165,6 +171,17 @@ typedef struct WASMExecEnv {
} wasm_stack; } wasm_stack;
} WASMExecEnv; } WASMExecEnv;
#if WASM_ENABLE_MEMORY_PROFILING != 0
#define RECORD_STACK_USAGE(e, p) \
do { \
if ((e)->native_stack_top_min > (p)) { \
(e)->native_stack_top_min = (p); \
} \
} while (0)
#else
#define RECORD_STACK_USAGE(e, p) (void)0
#endif
WASMExecEnv * WASMExecEnv *
wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst, wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
uint32 stack_size); uint32 stack_size);
@ -179,6 +196,13 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
void void
wasm_exec_env_destroy(WASMExecEnv *exec_env); wasm_exec_env_destroy(WASMExecEnv *exec_env);
static inline bool
wasm_exec_env_is_aux_stack_managed_by_runtime(WASMExecEnv *exec_env)
{
return exec_env->aux_stack_boundary.boundary != 0
|| exec_env->aux_stack_bottom.bottom != 0;
}
/** /**
* Allocate a WASM frame from the WASM stack. * Allocate a WASM frame from the WASM stack.
* *

View File

@ -8,6 +8,10 @@
#include "bh_platform.h" #include "bh_platform.h"
#include "mem_alloc.h" #include "mem_alloc.h"
#if WASM_ENABLE_SHARED_MEMORY != 0
#include "../common/wasm_shared_memory.h"
#endif
typedef enum Memory_Mode { typedef enum Memory_Mode {
MEMORY_MODE_UNKNOWN = 0, MEMORY_MODE_UNKNOWN = 0,
MEMORY_MODE_POOL, MEMORY_MODE_POOL,
@ -506,7 +510,7 @@ wasm_get_default_memory(WASMModuleInstance *module_inst)
#ifndef OS_ENABLE_HW_BOUND_CHECK #ifndef OS_ENABLE_HW_BOUND_CHECK
bool bool
wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
{ {
WASMMemoryInstance *memory = wasm_get_default_memory(module); WASMMemoryInstance *memory = wasm_get_default_memory(module);
uint8 *memory_data_old, *memory_data_new, *heap_data_old; uint8 *memory_data_old, *memory_data_new, *heap_data_old;
@ -624,7 +628,7 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
} }
#else #else
bool bool
wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
{ {
WASMMemoryInstance *memory = wasm_get_default_memory(module); WASMMemoryInstance *memory = wasm_get_default_memory(module);
uint32 num_bytes_per_page, total_size_old; uint32 num_bytes_per_page, total_size_old;
@ -697,3 +701,59 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
return true; return true;
} }
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */ #endif /* end of OS_ENABLE_HW_BOUND_CHECK */
bool
wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
{
bool ret = false;
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
if (node)
os_mutex_lock(&node->shared_mem_lock);
#endif
ret = wasm_enlarge_memory_internal(module, inc_page_count);
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&node->shared_mem_lock);
#endif
return ret;
}
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|| WASM_ENABLE_BULK_MEMORY != 0
uint32
wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node)
{
uint32 num_bytes_per_page;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock);
#endif
num_bytes_per_page = memory->num_bytes_per_page;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock);
#endif
return num_bytes_per_page;
}
uint32
wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node)
{
uint32 linear_mem_size;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock);
#endif
linear_mem_size = memory->num_bytes_per_page * memory->cur_page_count;
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock);
#endif
return linear_mem_size;
}
#endif

View File

@ -8,6 +8,7 @@
#include "bh_common.h" #include "bh_common.h"
#include "../include/wasm_export.h" #include "../include/wasm_export.h"
#include "../interpreter/wasm_runtime.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -23,6 +24,16 @@ wasm_runtime_memory_destroy();
unsigned unsigned
wasm_runtime_memory_pool_size(); wasm_runtime_memory_pool_size();
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|| WASM_ENABLE_BULK_MEMORY != 0
uint32
wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node);
uint32
wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -53,6 +53,17 @@ uint32
get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis); get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
#endif #endif
#if WASM_ENABLE_LIB_WASI_THREADS != 0
bool
lib_wasi_threads_init(void);
void
lib_wasi_threads_destroy(void);
uint32
get_lib_wasi_threads_export_apis(NativeSymbol **p_lib_wasi_threads_apis);
#endif
uint32 uint32
get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis); get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis);
@ -239,6 +250,10 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
return NULL; return NULL;
} }
/**
* allow func_type and all outputs, like p_signature, p_attachment and
* p_call_conv_raw to be NULL
*/
void * void *
wasm_native_resolve_symbol(const char *module_name, const char *field_name, wasm_native_resolve_symbol(const char *module_name, const char *field_name,
const WASMType *func_type, const char **p_signature, const WASMType *func_type, const char **p_signature,
@ -264,10 +279,13 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name,
node = node_next; node = node_next;
} }
if (!p_signature || !p_attachment || !p_call_conv_raw)
return func_ptr;
if (func_ptr) { if (func_ptr) {
if (signature && signature[0] != '\0') { if (signature && signature[0] != '\0') {
/* signature is not empty, check its format */ /* signature is not empty, check its format */
if (!check_symbol_signature(func_type, signature)) { if (!func_type || !check_symbol_signature(func_type, signature)) {
#if WASM_ENABLE_WAMR_COMPILER == 0 #if WASM_ENABLE_WAMR_COMPILER == 0
/* Output warning except running aot compiler */ /* Output warning except running aot compiler */
LOG_WARNING("failed to check signature '%s' and resolve " LOG_WARNING("failed to check signature '%s' and resolve "
@ -383,7 +401,7 @@ wasm_native_init()
|| WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \
|| WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \
|| WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \ || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \
|| WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
NativeSymbol *native_symbols; NativeSymbol *native_symbols;
uint32 n_native_symbols; uint32 n_native_symbols;
#endif #endif
@ -438,6 +456,17 @@ wasm_native_init()
goto fail; goto fail;
#endif #endif
#if WASM_ENABLE_LIB_WASI_THREADS != 0
if (!lib_wasi_threads_init())
goto fail;
n_native_symbols = get_lib_wasi_threads_export_apis(&native_symbols);
if (n_native_symbols > 0
&& !wasm_native_register_natives("wasi", native_symbols,
n_native_symbols))
goto fail;
#endif
#if WASM_ENABLE_LIBC_EMCC != 0 #if WASM_ENABLE_LIBC_EMCC != 0
n_native_symbols = get_libc_emcc_export_apis(&native_symbols); n_native_symbols = get_libc_emcc_export_apis(&native_symbols);
if (n_native_symbols > 0 if (n_native_symbols > 0
@ -458,7 +487,7 @@ wasm_native_init()
n_native_symbols = get_wasi_nn_export_apis(&native_symbols); n_native_symbols = get_wasi_nn_export_apis(&native_symbols);
if (!wasm_native_register_natives("wasi_nn", native_symbols, if (!wasm_native_register_natives("wasi_nn", native_symbols,
n_native_symbols)) n_native_symbols))
return false; goto fail;
#endif #endif
return true; return true;
@ -466,7 +495,7 @@ wasm_native_init()
|| WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \ || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \
|| WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \ || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \
|| WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \ || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \
|| WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
fail: fail:
wasm_native_destroy(); wasm_native_destroy();
return false; return false;
@ -482,6 +511,10 @@ wasm_native_destroy()
lib_pthread_destroy(); lib_pthread_destroy();
#endif #endif
#if WASM_ENABLE_LIB_WASI_THREADS != 0
lib_wasi_threads_destroy();
#endif
node = g_native_symbols_list; node = g_native_symbols_list;
while (node) { while (node) {
node_next = node->next; node_next = node->next;

View File

@ -7,6 +7,7 @@
#include "bh_common.h" #include "bh_common.h"
#include "bh_assert.h" #include "bh_assert.h"
#include "bh_log.h" #include "bh_log.h"
#include "wasm_native.h"
#include "wasm_runtime_common.h" #include "wasm_runtime_common.h"
#include "wasm_memory.h" #include "wasm_memory.h"
#if WASM_ENABLE_INTERP != 0 #if WASM_ENABLE_INTERP != 0
@ -128,6 +129,12 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
static JitCompOptions jit_options = { 0 }; static JitCompOptions jit_options = { 0 };
#endif #endif
#if WASM_ENABLE_JIT != 0
static LLVMJITOptions llvm_jit_options = { 3, 3 };
#endif
static RunningMode runtime_running_mode = Mode_Default;
#ifdef OS_ENABLE_HW_BOUND_CHECK #ifdef OS_ENABLE_HW_BOUND_CHECK
/* The exec_env of thread local storage, set before calling function /* The exec_env of thread local storage, set before calling function
and used in signal handler, as we cannot get it from the argument and used in signal handler, as we cannot get it from the argument
@ -187,7 +194,7 @@ runtime_signal_handler(void *sig_addr)
else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr
&& (uint8 *)sig_addr && (uint8 *)sig_addr
< exec_env_tls->exce_check_guard_page + page_size) { < exec_env_tls->exce_check_guard_page + page_size) {
bh_assert(wasm_get_exception(module_inst)); bh_assert(wasm_copy_exception(module_inst, NULL));
os_longjmp(jmpbuf_node->jmpbuf, 1); os_longjmp(jmpbuf_node->jmpbuf, 1);
} }
} }
@ -243,7 +250,7 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr
&& (uint8 *)sig_addr && (uint8 *)sig_addr
< exec_env_tls->exce_check_guard_page + page_size) { < exec_env_tls->exce_check_guard_page + page_size) {
bh_assert(wasm_get_exception(module_inst)); bh_assert(wasm_copy_exception(module_inst, NULL));
if (module_inst->module_type == Wasm_Module_Bytecode) { if (module_inst->module_type == Wasm_Module_Bytecode) {
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
@ -514,6 +521,20 @@ wasm_runtime_destroy()
wasm_runtime_memory_destroy(); wasm_runtime_memory_destroy();
} }
RunningMode
wasm_runtime_get_default_running_mode(void)
{
return runtime_running_mode;
}
#if WASM_ENABLE_JIT != 0
LLVMJITOptions
wasm_runtime_get_llvm_jit_options(void)
{
return llvm_jit_options;
}
#endif
bool bool
wasm_runtime_full_init(RuntimeInitArgs *init_args) wasm_runtime_full_init(RuntimeInitArgs *init_args)
{ {
@ -521,10 +542,20 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
&init_args->mem_alloc_option)) &init_args->mem_alloc_option))
return false; return false;
if (!wasm_runtime_set_default_running_mode(init_args->running_mode)) {
wasm_runtime_memory_destroy();
return false;
}
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
jit_options.code_cache_size = init_args->fast_jit_code_cache_size; jit_options.code_cache_size = init_args->fast_jit_code_cache_size;
#endif #endif
#if WASM_ENABLE_JIT != 0
llvm_jit_options.size_level = init_args->llvm_jit_size_level;
llvm_jit_options.opt_level = init_args->llvm_jit_opt_level;
#endif
if (!wasm_runtime_env_init()) { if (!wasm_runtime_env_init()) {
wasm_runtime_memory_destroy(); wasm_runtime_memory_destroy();
return false; return false;
@ -554,6 +585,47 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
return true; return true;
} }
bool
wasm_runtime_is_running_mode_supported(RunningMode running_mode)
{
if (running_mode == Mode_Default) {
return true;
}
else if (running_mode == Mode_Interp) {
#if WASM_ENABLE_INTERP != 0
return true;
#endif
}
else if (running_mode == Mode_Fast_JIT) {
#if WASM_ENABLE_FAST_JIT != 0
return true;
#endif
}
else if (running_mode == Mode_LLVM_JIT) {
#if WASM_ENABLE_JIT != 0
return true;
#endif
}
else if (running_mode == Mode_Multi_Tier_JIT) {
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
return true;
#endif
}
return false;
}
bool
wasm_runtime_set_default_running_mode(RunningMode running_mode)
{
if (wasm_runtime_is_running_mode_supported(running_mode)) {
runtime_running_mode = running_mode;
return true;
}
return false;
}
PackageType PackageType
get_package_type(const uint8 *buf, uint32 size) get_package_type(const uint8 *buf, uint32 size)
{ {
@ -1171,6 +1243,41 @@ wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
#endif #endif
} }
bool
wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
RunningMode running_mode)
{
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT)
return true;
#endif
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
WASMModuleInstance *module_inst_interp =
(WASMModuleInstance *)module_inst;
return wasm_set_running_mode(module_inst_interp, running_mode);
}
#endif
return false;
}
RunningMode
wasm_runtime_get_running_mode(wasm_module_inst_t module_inst)
{
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
WASMModuleInstance *module_inst_interp =
(WASMModuleInstance *)module_inst;
return module_inst_interp->e->running_mode;
}
#endif
return Mode_Default;
}
void void
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst) wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst)
{ {
@ -1399,6 +1506,22 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env)
else else
os_printf("Total aux stack used: no enough info to profile\n"); os_printf("Total aux stack used: no enough info to profile\n");
/*
* Report the native stack usage estimation.
*
* Unlike the aux stack above, we report the amount unused
* because we don't know the stack "bottom".
*
* Note that this is just about what the runtime itself observed.
* It doesn't cover host func implementations, signal handlers, etc.
*/
if (exec_env->native_stack_top_min != (void *)UINTPTR_MAX)
os_printf("Native stack left: %zd\n",
exec_env->native_stack_top_min
- exec_env->native_stack_boundary);
else
os_printf("Native stack left: no enough info to profile\n");
os_printf("Total app heap used: %u\n", app_heap_peak_size); os_printf("Total app heap used: %u\n", app_heap_peak_size);
} }
#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \ #endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
@ -1743,6 +1866,33 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
} }
#endif #endif
static bool
clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm)
{
#if WASM_ENABLE_LIBC_WASI != 0
bool has_exception;
char exception[EXCEPTION_BUF_LEN];
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
has_exception = wasm_copy_exception(module_inst, exception);
if (has_exception && !strcmp(exception, "Exception: wasi proc exit")) {
/* The "wasi proc exit" exception is thrown by native lib to
let wasm app exit, which is a normal behavior, we clear
the exception here. And just clear the exception of current
thread, don't call `wasm_set_exception(module_inst, NULL)`
which will clear the exception of all threads. */
module_inst->cur_exception[0] = '\0';
return true;
}
return false;
#else
return false;
#endif
}
bool bool
wasm_runtime_call_wasm(WASMExecEnv *exec_env, wasm_runtime_call_wasm(WASMExecEnv *exec_env,
WASMFunctionInstanceCommon *function, uint32 argc, WASMFunctionInstanceCommon *function, uint32 argc,
@ -1783,10 +1933,15 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
param_argc, new_argv); param_argc, new_argv);
#endif #endif
if (!ret) { if (!ret) {
if (new_argv != argv) { if (clear_wasi_proc_exit_exception(exec_env->module_inst)) {
wasm_runtime_free(new_argv); ret = true;
}
else {
if (new_argv != argv) {
wasm_runtime_free(new_argv);
}
return false;
} }
return false;
} }
#if WASM_ENABLE_REF_TYPES != 0 #if WASM_ENABLE_REF_TYPES != 0
@ -2150,11 +2305,41 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm)
void void
wasm_set_exception(WASMModuleInstance *module_inst, const char *exception) wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
{ {
if (exception) WASMExecEnv *exec_env = NULL;
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module);
if (node)
os_mutex_lock(&node->shared_mem_lock);
#endif
if (exception) {
snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception), snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception),
"Exception: %s", exception); "Exception: %s", exception);
else }
else {
module_inst->cur_exception[0] = '\0'; module_inst->cur_exception[0] = '\0';
}
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&node->shared_mem_lock);
#endif
#if WASM_ENABLE_THREAD_MGR != 0
exec_env =
wasm_clusters_search_exec_env((WASMModuleInstanceCommon *)module_inst);
if (exec_env) {
wasm_cluster_spread_exception(exec_env, exception ? false : true);
}
#if WASM_ENABLE_SHARED_MEMORY
if (exception) {
notify_stale_threads_on_exception(
(WASMModuleInstanceCommon *)module_inst);
}
#endif
#else
(void)exec_env;
#endif
} }
/* clang-format off */ /* clang-format off */
@ -2176,9 +2361,7 @@ static const char *exception_msgs[] = {
"wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */ "wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
"out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */ "out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
"wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */ "wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */
#if WASM_ENABLE_FAST_JIT != 0
"failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */ "failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
#endif
"", /* EXCE_ALREADY_THROWN */ "", /* EXCE_ALREADY_THROWN */
}; };
/* clang-format on */ /* clang-format on */
@ -2201,6 +2384,36 @@ wasm_get_exception(WASMModuleInstance *module_inst)
return module_inst->cur_exception; return module_inst->cur_exception;
} }
bool
wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf)
{
bool has_exception = false;
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module_inst->module);
if (node)
os_mutex_lock(&node->shared_mem_lock);
#endif
if (module_inst->cur_exception[0] != '\0') {
/* NULL is passed if the caller is not interested in getting the
* exception content, but only in knowing if an exception has been
* raised
*/
if (exception_buf != NULL)
bh_memcpy_s(exception_buf, sizeof(module_inst->cur_exception),
module_inst->cur_exception,
sizeof(module_inst->cur_exception));
has_exception = true;
}
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&node->shared_mem_lock);
#endif
return has_exception;
}
void void
wasm_runtime_set_exception(WASMModuleInstanceCommon *module_inst_comm, wasm_runtime_set_exception(WASMModuleInstanceCommon *module_inst_comm,
const char *exception) const char *exception)
@ -2222,6 +2435,17 @@ wasm_runtime_get_exception(WASMModuleInstanceCommon *module_inst_comm)
return wasm_get_exception(module_inst); return wasm_get_exception(module_inst);
} }
bool
wasm_runtime_copy_exception(WASMModuleInstanceCommon *module_inst_comm,
char *exception_buf)
{
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
return wasm_copy_exception(module_inst, exception_buf);
}
void void
wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst_comm) wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst_comm)
{ {
@ -3145,7 +3369,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
} }
} }
ret = !wasm_runtime_get_exception(module) ? true : false; ret = !wasm_runtime_copy_exception(module, NULL);
fail: fail:
if (argv1 != argv_buf) if (argv1 != argv_buf)
@ -3620,7 +3844,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
} }
exec_env->attachment = NULL; exec_env->attachment = NULL;
ret = !wasm_runtime_get_exception(module) ? true : false; ret = !wasm_runtime_copy_exception(module, NULL);
fail: fail:
if (argv1 != argv_buf) if (argv1 != argv_buf)
@ -3834,7 +4058,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
} }
exec_env->attachment = NULL; exec_env->attachment = NULL;
ret = !wasm_runtime_get_exception(module) ? true : false; ret = !wasm_runtime_copy_exception(module, NULL);
fail: fail:
if (argv1 != argv_buf) if (argv1 != argv_buf)
@ -4161,7 +4385,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
} }
exec_env->attachment = NULL; exec_env->attachment = NULL;
ret = !wasm_runtime_get_exception(module) ? true : false; ret = !wasm_runtime_copy_exception(module, NULL);
fail: fail:
if (argv1 != argv_buf) if (argv1 != argv_buf)
wasm_runtime_free(argv1); wasm_runtime_free(argv1);
@ -4176,9 +4400,11 @@ fail:
|| defined(BUILD_TARGET_RISCV64_LP64) */ || defined(BUILD_TARGET_RISCV64_LP64) */
bool bool
wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices, wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_index,
uint32 argc, uint32 argv[]) uint32 argc, uint32 argv[])
{ {
bool ret = false;
if (!wasm_runtime_exec_env_check(exec_env)) { if (!wasm_runtime_exec_env_check(exec_env)) {
LOG_ERROR("Invalid exec env stack info."); LOG_ERROR("Invalid exec env stack info.");
return false; return false;
@ -4190,13 +4416,18 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices,
#if WASM_ENABLE_INTERP != 0 #if WASM_ENABLE_INTERP != 0
if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) if (exec_env->module_inst->module_type == Wasm_Module_Bytecode)
return wasm_call_indirect(exec_env, 0, element_indices, argc, argv); ret = wasm_call_indirect(exec_env, 0, element_index, argc, argv);
#endif #endif
#if WASM_ENABLE_AOT != 0 #if WASM_ENABLE_AOT != 0
if (exec_env->module_inst->module_type == Wasm_Module_AoT) if (exec_env->module_inst->module_type == Wasm_Module_AoT)
return aot_call_indirect(exec_env, 0, element_indices, argc, argv); ret = aot_call_indirect(exec_env, 0, element_index, argc, argv);
#endif #endif
return false;
if (!ret && clear_wasi_proc_exit_exception(exec_env->module_inst)) {
ret = true;
}
return ret;
} }
static void static void
@ -5155,3 +5386,24 @@ wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
*minor = WAMR_VERSION_MINOR; *minor = WAMR_VERSION_MINOR;
*patch = WAMR_VERSION_PATCH; *patch = WAMR_VERSION_PATCH;
} }
bool
wasm_runtime_is_import_func_linked(const char *module_name,
const char *func_name)
{
return wasm_native_resolve_symbol(module_name, func_name, NULL, NULL, NULL,
NULL);
}
bool
wasm_runtime_is_import_global_linked(const char *module_name,
const char *global_name)
{
#if WASM_ENABLE_LIBC_BUILTIN != 0
WASMGlobalImport global = { 0 };
return wasm_native_lookup_libc_builtin_global(module_name, global_name,
&global);
#else
return false;
#endif
}

View File

@ -25,6 +25,9 @@
extern "C" { extern "C" {
#endif #endif
/* Internal use for setting default running mode */
#define Mode_Default 0
#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
#define PUT_I64_TO_ADDR(addr, value) \ #define PUT_I64_TO_ADDR(addr, value) \
@ -413,6 +416,13 @@ typedef struct wasm_frame_t {
const char *func_name_wp; const char *func_name_wp;
} WASMCApiFrame; } WASMCApiFrame;
#ifdef WASM_ENABLE_JIT
typedef struct LLVMJITOptions {
uint32 opt_level;
uint32 size_level;
} LLVMJITOptions;
#endif
#ifdef OS_ENABLE_HW_BOUND_CHECK #ifdef OS_ENABLE_HW_BOUND_CHECK
/* Signal info passing to interp/aot signal handler */ /* Signal info passing to interp/aot signal handler */
typedef struct WASMSignalInfo { typedef struct WASMSignalInfo {
@ -437,10 +447,28 @@ wasm_runtime_get_exec_env_tls(void);
WASM_RUNTIME_API_EXTERN bool WASM_RUNTIME_API_EXTERN bool
wasm_runtime_init(void); wasm_runtime_init(void);
/* Internal API */
RunningMode
wasm_runtime_get_default_running_mode(void);
#if WASM_ENABLE_JIT != 0
/* Internal API */
LLVMJITOptions
wasm_runtime_get_llvm_jit_options(void);
#endif
/* See wasm_export.h for description */ /* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN bool WASM_RUNTIME_API_EXTERN bool
wasm_runtime_full_init(RuntimeInitArgs *init_args); wasm_runtime_full_init(RuntimeInitArgs *init_args);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_running_mode_supported(RunningMode running_mode);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_set_default_running_mode(RunningMode running_mode);
/* See wasm_export.h for description */ /* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void WASM_RUNTIME_API_EXTERN void
wasm_runtime_destroy(void); wasm_runtime_destroy(void);
@ -484,6 +512,15 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size,
uint32 heap_size, char *error_buf, uint32 heap_size, char *error_buf,
uint32 error_buf_size); uint32 error_buf_size);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
RunningMode running_mode);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN RunningMode
wasm_runtime_get_running_mode(wasm_module_inst_t module_inst);
/* See wasm_export.h for description */ /* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN void WASM_RUNTIME_API_EXTERN void
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst); wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst);
@ -578,6 +615,11 @@ wasm_runtime_call_wasm_v(WASMExecEnv *exec_env,
uint32 num_results, wasm_val_t *results, uint32 num_results, wasm_val_t *results,
uint32 num_args, ...); uint32 num_args, ...);
/* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_index,
uint32 argc, uint32 argv[]);
#if WASM_ENABLE_DEBUG_INTERP != 0 #if WASM_ENABLE_DEBUG_INTERP != 0
/* See wasm_export.h for description */ /* See wasm_export.h for description */
WASM_RUNTIME_API_EXTERN uint32 WASM_RUNTIME_API_EXTERN uint32
@ -589,27 +631,6 @@ WASM_RUNTIME_API_EXTERN uint32
wasm_runtime_start_debug_instance(WASMExecEnv *exec_env); wasm_runtime_start_debug_instance(WASMExecEnv *exec_env);
#endif #endif
/**
* Call a function reference of a given WASM runtime instance with
* arguments.
*
* @param exec_env the execution environment to call the function
* which must be created from wasm_create_exec_env()
* @param element_indices the function ference indicies, usually
* prvovided by the caller of a registed native function
* @param argc the number of arguments
* @param argv the arguments. If the function method has return value,
* the first (or first two in case 64-bit return value) element of
* argv stores the return value of the called WASM function after this
* function returns.
*
* @return true if success, false otherwise and exception will be thrown,
* the caller can call wasm_runtime_get_exception to get exception info.
*/
bool
wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices,
uint32 argc, uint32 argv[]);
bool bool
wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst); wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
@ -956,6 +977,14 @@ void
wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list); wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list);
#endif #endif
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_import_func_linked(const char *module_name,
const char *func_name);
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_import_global_linked(const char *module_name,
const char *global_name);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -30,8 +30,14 @@ typedef struct AtomicWaitNode {
korp_cond wait_cond; korp_cond wait_cond;
} AtomicWaitNode; } AtomicWaitNode;
typedef struct AtomicWaitAddressArgs {
uint32 index;
void **addr;
} AtomicWaitAddressArgs;
/* Atomic wait map */ /* Atomic wait map */
static HashMap *wait_map; static HashMap *wait_map;
static korp_mutex wait_map_lock;
static uint32 static uint32
wait_address_hash(void *address); wait_address_hash(void *address);
@ -47,11 +53,18 @@ wasm_shared_memory_init()
{ {
if (os_mutex_init(&shared_memory_list_lock) != 0) if (os_mutex_init(&shared_memory_list_lock) != 0)
return false; return false;
if (os_mutex_init(&wait_map_lock) != 0) {
os_mutex_destroy(&shared_memory_list_lock);
return false;
}
/* wait map not exists, create new map */ /* wait map not exists, create new map */
if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash, if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash,
(KeyEqualFunc)wait_address_equal, NULL, (KeyEqualFunc)wait_address_equal, NULL,
destroy_wait_info))) { destroy_wait_info))) {
os_mutex_destroy(&shared_memory_list_lock); os_mutex_destroy(&shared_memory_list_lock);
os_mutex_destroy(&wait_map_lock);
return false; return false;
} }
@ -62,6 +75,7 @@ void
wasm_shared_memory_destroy() wasm_shared_memory_destroy()
{ {
os_mutex_destroy(&shared_memory_list_lock); os_mutex_destroy(&shared_memory_list_lock);
os_mutex_destroy(&wait_map_lock);
if (wait_map) { if (wait_map) {
bh_hash_map_destroy(wait_map); bh_hash_map_destroy(wait_map);
} }
@ -87,6 +101,61 @@ search_module(WASMModuleCommon *module)
return NULL; return NULL;
} }
static void
wait_map_address_count_callback(void *key, void *value,
void *p_total_elem_count)
{
*(uint32 *)p_total_elem_count = *(uint32 *)p_total_elem_count + 1;
}
static void
create_list_of_waiter_addresses(void *key, void *value, void *user_data)
{
AtomicWaitAddressArgs *data = (AtomicWaitAddressArgs *)user_data;
data->addr[data->index++] = key;
}
void
notify_stale_threads_on_exception(WASMModuleInstanceCommon *module_inst)
{
AtomicWaitAddressArgs args = { 0 };
uint32 i = 0, total_elem_count = 0;
uint64 total_elem_count_size = 0;
os_mutex_lock(&wait_map_lock); /* Make the two traversals atomic */
/* count number of addresses in wait_map */
bh_hash_map_traverse(wait_map, wait_map_address_count_callback,
(void *)&total_elem_count);
if (!total_elem_count) {
os_mutex_unlock(&wait_map_lock);
return;
}
/* allocate memory */
total_elem_count_size = (uint64)sizeof(void *) * total_elem_count;
if (total_elem_count_size >= UINT32_MAX
|| !(args.addr = wasm_runtime_malloc((uint32)total_elem_count_size))) {
LOG_ERROR(
"failed to allocate memory for list of atomic wait addresses");
os_mutex_unlock(&wait_map_lock);
return;
}
/* set values in list of addresses */
bh_hash_map_traverse(wait_map, create_list_of_waiter_addresses, &args);
os_mutex_unlock(&wait_map_lock);
/* notify */
for (i = 0; i < args.index; i++) {
wasm_runtime_atomic_notify(module_inst, args.addr[i], UINT32_MAX);
}
/* free memory allocated to args data */
wasm_runtime_free(args.addr);
}
WASMSharedMemNode * WASMSharedMemNode *
wasm_module_get_shared_memory(WASMModuleCommon *module) wasm_module_get_shared_memory(WASMModuleCommon *module)
{ {
@ -97,13 +166,13 @@ int32
shared_memory_inc_reference(WASMModuleCommon *module) shared_memory_inc_reference(WASMModuleCommon *module)
{ {
WASMSharedMemNode *node = search_module(module); WASMSharedMemNode *node = search_module(module);
uint32 ref_count = -1;
if (node) { if (node) {
os_mutex_lock(&node->lock); os_mutex_lock(&node->lock);
node->ref_count++; ref_count = ++node->ref_count;
os_mutex_unlock(&node->lock); os_mutex_unlock(&node->lock);
return node->ref_count;
} }
return -1; return ref_count;
} }
int32 int32
@ -120,6 +189,7 @@ shared_memory_dec_reference(WASMModuleCommon *module)
bh_list_remove(shared_memory_list, node); bh_list_remove(shared_memory_list, node);
os_mutex_unlock(&shared_memory_list_lock); os_mutex_unlock(&shared_memory_list_lock);
os_mutex_destroy(&node->shared_mem_lock);
os_mutex_destroy(&node->lock); os_mutex_destroy(&node->lock);
wasm_runtime_free(node); wasm_runtime_free(node);
} }
@ -148,7 +218,14 @@ shared_memory_set_memory_inst(WASMModuleCommon *module,
node->module = module; node->module = module;
node->memory_inst = memory; node->memory_inst = memory;
node->ref_count = 1; node->ref_count = 1;
if (os_mutex_init(&node->shared_mem_lock) != 0) {
wasm_runtime_free(node);
return NULL;
}
if (os_mutex_init(&node->lock) != 0) { if (os_mutex_init(&node->lock) != 0) {
os_mutex_destroy(&node->shared_mem_lock);
wasm_runtime_free(node); wasm_runtime_free(node);
return NULL; return NULL;
} }
@ -208,9 +285,11 @@ notify_wait_list(bh_list *wait_list, uint32 count)
bh_assert(node); bh_assert(node);
next = bh_list_elem_next(node); next = bh_list_elem_next(node);
os_mutex_lock(&node->wait_lock);
node->status = S_NOTIFIED; node->status = S_NOTIFIED;
/* wakeup */ /* wakeup */
os_cond_signal(&node->wait_cond); os_cond_signal(&node->wait_cond);
os_mutex_unlock(&node->wait_lock);
node = next; node = next;
} }
@ -224,13 +303,13 @@ acquire_wait_info(void *address, bool create)
AtomicWaitInfo *wait_info = NULL; AtomicWaitInfo *wait_info = NULL;
bh_list_status ret; bh_list_status ret;
os_mutex_lock(&shared_memory_list_lock); os_mutex_lock(&wait_map_lock); /* Make find + insert atomic */
if (address) if (address)
wait_info = (AtomicWaitInfo *)bh_hash_map_find(wait_map, address); wait_info = (AtomicWaitInfo *)bh_hash_map_find(wait_map, address);
if (!create) { if (!create) {
os_mutex_unlock(&shared_memory_list_lock); os_mutex_unlock(&wait_map_lock);
return wait_info; return wait_info;
} }
@ -257,7 +336,7 @@ acquire_wait_info(void *address, bool create)
} }
} }
os_mutex_unlock(&shared_memory_list_lock); os_mutex_unlock(&wait_map_lock);
bh_assert(wait_info); bh_assert(wait_info);
(void)ret; (void)ret;
@ -270,7 +349,7 @@ fail2:
wasm_runtime_free(wait_info); wasm_runtime_free(wait_info);
fail1: fail1:
os_mutex_unlock(&shared_memory_list_lock); os_mutex_unlock(&wait_map_lock);
return NULL; return NULL;
} }
@ -297,17 +376,16 @@ destroy_wait_info(void *wait_info)
} }
} }
static void static bool
release_wait_info(HashMap *wait_map_, AtomicWaitInfo *wait_info, void *address) map_remove_wait_info(HashMap *wait_map_, AtomicWaitInfo *wait_info,
void *address)
{ {
os_mutex_lock(&shared_memory_list_lock); if (wait_info->wait_list->len > 0) {
return false;
if (wait_info->wait_list->len == 0) {
bh_hash_map_remove(wait_map_, address, NULL, NULL);
destroy_wait_info(wait_info);
} }
os_mutex_unlock(&shared_memory_list_lock); bh_hash_map_remove(wait_map_, address, NULL, NULL);
return true;
} }
uint32 uint32
@ -317,11 +395,16 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
WASMModuleInstance *module_inst = (WASMModuleInstance *)module; WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
AtomicWaitInfo *wait_info; AtomicWaitInfo *wait_info;
AtomicWaitNode *wait_node; AtomicWaitNode *wait_node;
bool check_ret, is_timeout; WASMSharedMemNode *node;
bool check_ret, is_timeout, no_wait, removed_from_map;
bh_assert(module->module_type == Wasm_Module_Bytecode bh_assert(module->module_type == Wasm_Module_Bytecode
|| module->module_type == Wasm_Module_AoT); || module->module_type == Wasm_Module_AoT);
if (wasm_copy_exception(module_inst, NULL)) {
return -1;
}
/* Currently we have only one memory instance */ /* Currently we have only one memory instance */
if (!module_inst->memories[0]->is_shared) { if (!module_inst->memories[0]->is_shared) {
wasm_runtime_set_exception(module, "expected shared memory"); wasm_runtime_set_exception(module, "expected shared memory");
@ -343,11 +426,13 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
return -1; return -1;
} }
os_mutex_lock(&wait_info->wait_list_lock); node = search_module((WASMModuleCommon *)module_inst->module);
os_mutex_lock(&node->shared_mem_lock);
no_wait = (!wait64 && *(uint32 *)address != (uint32)expect)
|| (wait64 && *(uint64 *)address != expect);
os_mutex_unlock(&node->shared_mem_lock);
if ((!wait64 && *(uint32 *)address != (uint32)expect) if (no_wait) {
|| (wait64 && *(uint64 *)address != expect)) {
os_mutex_unlock(&wait_info->wait_list_lock);
return 1; return 1;
} }
else { else {
@ -355,33 +440,29 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) { if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) {
wasm_runtime_set_exception(module, "failed to create wait node"); wasm_runtime_set_exception(module, "failed to create wait node");
os_mutex_unlock(&wait_info->wait_list_lock);
return -1; return -1;
} }
memset(wait_node, 0, sizeof(AtomicWaitNode)); memset(wait_node, 0, sizeof(AtomicWaitNode));
if (0 != os_mutex_init(&wait_node->wait_lock)) { if (0 != os_mutex_init(&wait_node->wait_lock)) {
wasm_runtime_free(wait_node); wasm_runtime_free(wait_node);
os_mutex_unlock(&wait_info->wait_list_lock);
return -1; return -1;
} }
if (0 != os_cond_init(&wait_node->wait_cond)) { if (0 != os_cond_init(&wait_node->wait_cond)) {
os_mutex_destroy(&wait_node->wait_lock); os_mutex_destroy(&wait_node->wait_lock);
wasm_runtime_free(wait_node); wasm_runtime_free(wait_node);
os_mutex_unlock(&wait_info->wait_list_lock);
return -1; return -1;
} }
wait_node->status = S_WAITING; wait_node->status = S_WAITING;
os_mutex_lock(&wait_info->wait_list_lock);
ret = bh_list_insert(wait_info->wait_list, wait_node); ret = bh_list_insert(wait_info->wait_list, wait_node);
os_mutex_unlock(&wait_info->wait_list_lock);
bh_assert(ret == BH_LIST_SUCCESS); bh_assert(ret == BH_LIST_SUCCESS);
(void)ret; (void)ret;
} }
os_mutex_unlock(&wait_info->wait_list_lock);
/* condition wait start */ /* condition wait start */
os_mutex_lock(&wait_node->wait_lock); os_mutex_lock(&wait_node->wait_lock);
@ -389,22 +470,27 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
timeout < 0 ? BHT_WAIT_FOREVER timeout < 0 ? BHT_WAIT_FOREVER
: (uint64)timeout / 1000); : (uint64)timeout / 1000);
is_timeout = wait_node->status == S_WAITING ? true : false;
os_mutex_unlock(&wait_node->wait_lock); os_mutex_unlock(&wait_node->wait_lock);
/* Check the wait node status */ os_mutex_lock(&node->shared_mem_lock);
os_mutex_lock(&wait_info->wait_list_lock); os_mutex_lock(&wait_info->wait_list_lock);
check_ret = is_wait_node_exists(wait_info->wait_list, wait_node); check_ret = is_wait_node_exists(wait_info->wait_list, wait_node);
bh_assert(check_ret); bh_assert(check_ret);
is_timeout = wait_node->status == S_WAITING ? true : false; /* Remove wait node */
bh_list_remove(wait_info->wait_list, wait_node); bh_list_remove(wait_info->wait_list, wait_node);
os_mutex_destroy(&wait_node->wait_lock); os_mutex_destroy(&wait_node->wait_lock);
os_cond_destroy(&wait_node->wait_cond); os_cond_destroy(&wait_node->wait_cond);
wasm_runtime_free(wait_node); wasm_runtime_free(wait_node);
os_mutex_unlock(&wait_info->wait_list_lock);
release_wait_info(wait_map, wait_info, address); /* Release wait info if no wait nodes attached */
removed_from_map = map_remove_wait_info(wait_map, wait_info, address);
os_mutex_unlock(&wait_info->wait_list_lock);
if (removed_from_map)
destroy_wait_info(wait_info);
os_mutex_unlock(&node->shared_mem_lock);
(void)check_ret; (void)check_ret;
return is_timeout ? 2 : 0; return is_timeout ? 2 : 0;
@ -417,12 +503,22 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
WASMModuleInstance *module_inst = (WASMModuleInstance *)module; WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
uint32 notify_result; uint32 notify_result;
AtomicWaitInfo *wait_info; AtomicWaitInfo *wait_info;
WASMSharedMemNode *node;
bool out_of_bounds;
bh_assert(module->module_type == Wasm_Module_Bytecode bh_assert(module->module_type == Wasm_Module_Bytecode
|| module->module_type == Wasm_Module_AoT); || module->module_type == Wasm_Module_AoT);
if ((uint8 *)address < module_inst->memories[0]->memory_data node = search_module((WASMModuleCommon *)module_inst->module);
|| (uint8 *)address + 4 > module_inst->memories[0]->memory_data_end) { if (node)
os_mutex_lock(&node->shared_mem_lock);
out_of_bounds =
((uint8 *)address < module_inst->memories[0]->memory_data
|| (uint8 *)address + 4 > module_inst->memories[0]->memory_data_end);
if (out_of_bounds) {
if (node)
os_mutex_unlock(&node->shared_mem_lock);
wasm_runtime_set_exception(module, "out of bounds memory access"); wasm_runtime_set_exception(module, "out of bounds memory access");
return -1; return -1;
} }
@ -430,12 +526,18 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
wait_info = acquire_wait_info(address, false); wait_info = acquire_wait_info(address, false);
/* Nobody wait on this address */ /* Nobody wait on this address */
if (!wait_info) if (!wait_info) {
if (node)
os_mutex_unlock(&node->shared_mem_lock);
return 0; return 0;
}
os_mutex_lock(&wait_info->wait_list_lock); os_mutex_lock(&wait_info->wait_list_lock);
notify_result = notify_wait_list(wait_info->wait_list, count); notify_result = notify_wait_list(wait_info->wait_list, count);
os_mutex_unlock(&wait_info->wait_list_lock); os_mutex_unlock(&wait_info->wait_list_lock);
if (node)
os_mutex_unlock(&node->shared_mem_lock);
return notify_result; return notify_result;
} }

View File

@ -26,6 +26,8 @@ typedef struct WASMSharedMemNode {
WASMModuleCommon *module; WASMModuleCommon *module;
/* The memory information */ /* The memory information */
WASMMemoryInstanceCommon *memory_inst; WASMMemoryInstanceCommon *memory_inst;
/* Lock used for atomic operations */
korp_mutex shared_mem_lock;
/* reference count */ /* reference count */
uint32 ref_count; uint32 ref_count;
@ -37,6 +39,9 @@ wasm_shared_memory_init();
void void
wasm_shared_memory_destroy(); wasm_shared_memory_destroy();
void
notify_stale_threads_on_exception(WASMModuleInstanceCommon *module);
WASMSharedMemNode * WASMSharedMemNode *
wasm_module_get_shared_memory(WASMModuleCommon *module); wasm_module_get_shared_memory(WASMModuleCommon *module);

View File

@ -149,6 +149,7 @@ typedef struct AOTImportGlobal {
uint32 data_offset; uint32 data_offset;
/* global data after linked */ /* global data after linked */
WASMValue global_data_linked; WASMValue global_data_linked;
bool is_linked;
} AOTImportGlobal; } AOTImportGlobal;
/** /**

View File

@ -1240,6 +1240,8 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
case WASM_OP_ATOMIC_FENCE: case WASM_OP_ATOMIC_FENCE:
/* Skip memory index */ /* Skip memory index */
frame_ip++; frame_ip++;
if (!aot_compiler_op_atomic_fence(comp_ctx, func_ctx))
return false;
break; break;
case WASM_OP_ATOMIC_I32_LOAD: case WASM_OP_ATOMIC_I32_LOAD:
bytes = 4; bytes = 4;

View File

@ -259,6 +259,7 @@ check_type_compatible(uint8 src_type, uint8 dst_type)
#define I32_SIX LLVM_CONST(i32_six) #define I32_SIX LLVM_CONST(i32_six)
#define I32_SEVEN LLVM_CONST(i32_seven) #define I32_SEVEN LLVM_CONST(i32_seven)
#define I32_EIGHT LLVM_CONST(i32_eight) #define I32_EIGHT LLVM_CONST(i32_eight)
#define I32_NINE LLVM_CONST(i32_nine)
#define I32_NEG_ONE LLVM_CONST(i32_neg_one) #define I32_NEG_ONE LLVM_CONST(i32_neg_one)
#define I64_NEG_ONE LLVM_CONST(i64_neg_one) #define I64_NEG_ONE LLVM_CONST(i64_neg_one)
#define I32_MIN LLVM_CONST(i32_min) #define I32_MIN LLVM_CONST(i32_min)

View File

@ -9,6 +9,36 @@
#include "../aot/aot_intrinsic.h" #include "../aot/aot_intrinsic.h"
#include "../aot/aot_runtime.h" #include "../aot/aot_runtime.h"
static LLVMValueRef
call_fcmp_intrinsic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
enum AOTFloatCond cond, LLVMRealPredicate op,
LLVMValueRef lhs, LLVMValueRef rhs, LLVMTypeRef src_type,
const char *name)
{
LLVMValueRef res = NULL;
if (comp_ctx->disable_llvm_intrinsics
&& aot_intrinsic_check_capability(
comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) {
LLVMTypeRef param_types[3];
LLVMValueRef opcond = LLVMConstInt(I32_TYPE, cond, true);
param_types[0] = I32_TYPE;
param_types[1] = src_type;
param_types[2] = src_type;
res = aot_call_llvm_intrinsic(
comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp",
I32_TYPE, param_types, 3, opcond, lhs, rhs);
if (!res) {
goto fail;
}
res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast");
}
else {
res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, name);
}
fail:
return res;
}
static bool static bool
trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMValueRef operand, LLVMTypeRef src_type, LLVMValueRef operand, LLVMTypeRef src_type,
@ -18,26 +48,8 @@ trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMBasicBlockRef check_nan_succ, check_overflow_succ; LLVMBasicBlockRef check_nan_succ, check_overflow_succ;
LLVMValueRef is_less, is_greater, res; LLVMValueRef is_less, is_greater, res;
if (comp_ctx->disable_llvm_intrinsics res = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_UNO, LLVMRealUNO,
&& aot_intrinsic_check_capability( operand, operand, src_type, "fcmp_is_nan");
comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) {
LLVMTypeRef param_types[3];
LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_UNO, true);
param_types[0] = I32_TYPE;
param_types[1] = src_type;
param_types[2] = src_type;
res = aot_call_llvm_intrinsic(
comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp",
I32_TYPE, param_types, 3, opcond, operand, operand);
if (!res) {
goto fail;
}
res = LLVMBuildIntCast(comp_ctx->builder, res, INT1_TYPE, "bit_cast");
}
else {
res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, operand, operand,
"fcmp_is_nan");
}
if (!res) { if (!res) {
aot_set_last_error("llvm build fcmp failed."); aot_set_last_error("llvm build fcmp failed.");
@ -58,54 +70,18 @@ trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
check_nan_succ))) check_nan_succ)))
goto fail; goto fail;
if (comp_ctx->disable_llvm_intrinsics is_less =
&& aot_intrinsic_check_capability( call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_LE, LLVMRealOLE, operand,
comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) { min_value, src_type, "fcmp_min_value");
LLVMTypeRef param_types[3];
LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_LE, true);
param_types[0] = I32_TYPE;
param_types[1] = src_type;
param_types[2] = src_type;
is_less = aot_call_llvm_intrinsic(
comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp",
I32_TYPE, param_types, 3, opcond, operand, min_value);
if (!is_less) {
goto fail;
}
is_less =
LLVMBuildIntCast(comp_ctx->builder, is_less, INT1_TYPE, "bit_cast");
}
else {
is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand,
min_value, "fcmp_min_value");
}
if (!is_less) { if (!is_less) {
aot_set_last_error("llvm build fcmp failed."); aot_set_last_error("llvm build fcmp failed.");
goto fail; goto fail;
} }
if (comp_ctx->disable_llvm_intrinsics is_greater =
&& aot_intrinsic_check_capability( call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_GE, LLVMRealOGE, operand,
comp_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp")) { max_value, src_type, "fcmp_min_value");
LLVMTypeRef param_types[3];
LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_GE, true);
param_types[0] = I32_TYPE;
param_types[1] = src_type;
param_types[2] = src_type;
is_greater = aot_call_llvm_intrinsic(
comp_ctx, func_ctx, src_type == F32_TYPE ? "f32_cmp" : "f64_cmp",
I32_TYPE, param_types, 3, opcond, operand, max_value);
if (!is_greater) {
goto fail;
}
is_greater = LLVMBuildIntCast(comp_ctx->builder, is_greater, INT1_TYPE,
"bit_cast");
}
else {
is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand,
max_value, "fcmp_min_value");
}
if (!is_greater) { if (!is_greater) {
aot_set_last_error("llvm build fcmp failed."); aot_set_last_error("llvm build fcmp failed.");
@ -183,8 +159,9 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMValueRef zero = (dest_type == I32_TYPE) ? I32_ZERO : I64_ZERO; LLVMValueRef zero = (dest_type == I32_TYPE) ? I32_ZERO : I64_ZERO;
LLVMValueRef vmin, vmax; LLVMValueRef vmin, vmax;
if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, operand, operand, if (!(res =
"fcmp_is_nan"))) { call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_UNO, LLVMRealUNO,
operand, operand, src_type, "fcmp_is_nan"))) {
aot_set_last_error("llvm build fcmp failed."); aot_set_last_error("llvm build fcmp failed.");
goto fail; goto fail;
} }
@ -212,8 +189,9 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* Start to translate check_nan_succ block */ /* Start to translate check_nan_succ block */
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_nan_succ); LLVMPositionBuilderAtEnd(comp_ctx->builder, check_nan_succ);
if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand, if (!(is_less = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_LE,
min_value, "fcmp_min_value"))) { LLVMRealOLE, operand, min_value,
src_type, "fcmp_min_value"))) {
aot_set_last_error("llvm build fcmp failed."); aot_set_last_error("llvm build fcmp failed.");
goto fail; goto fail;
} }
@ -232,8 +210,9 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* Start to translate check_less_succ block */ /* Start to translate check_less_succ block */
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_less_succ); LLVMPositionBuilderAtEnd(comp_ctx->builder, check_less_succ);
if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand, if (!(is_greater = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_GE,
max_value, "fcmp_max_value"))) { LLVMRealOGE, operand, max_value,
src_type, "fcmp_max_value"))) {
aot_set_last_error("llvm build fcmp failed."); aot_set_last_error("llvm build fcmp failed.");
goto fail; goto fail;
} }

View File

@ -366,6 +366,87 @@ fail:
#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \ #endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \
|| (WASM_ENABLE_PERF_PROFILING != 0) */ || (WASM_ENABLE_PERF_PROFILING != 0) */
static bool
record_stack_usage(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 callee_cell_num)
{
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMBasicBlockRef block_update;
LLVMBasicBlockRef block_after_update;
LLVMValueRef callee_local_size, new_sp, cmp;
LLVMValueRef native_stack_top_min;
LLVMTypeRef ptrdiff_type;
if (comp_ctx->pointer_size == sizeof(uint64_t)) {
ptrdiff_type = I64_TYPE;
}
else {
ptrdiff_type = I32_TYPE;
}
/*
* new_sp = last_alloca - callee_local_size;
* if (*native_stack_top_min_addr > new_sp) {
* *native_stack_top_min_addr = new_sp;
* }
*/
if (!(callee_local_size = LLVMConstInt(
ptrdiff_type, -(int64_t)callee_cell_num * 4, true))) {
aot_set_last_error("llvm build const failed.");
return false;
}
if (!(new_sp = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
func_ctx->last_alloca,
&callee_local_size, 1, "new_sp"))) {
aot_set_last_error("llvm build gep failed");
return false;
}
if (!(native_stack_top_min = LLVMBuildLoad2(
comp_ctx->builder, OPQ_PTR_TYPE,
func_ctx->native_stack_top_min_addr, "native_stack_top_min"))) {
aot_set_last_error("llvm build load failed");
return false;
}
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT, new_sp,
native_stack_top_min, "cmp"))) {
aot_set_last_error("llvm build icmp failed.");
return false;
}
if (!(block_update = LLVMAppendBasicBlockInContext(
comp_ctx->context, func_ctx->func, "block_update"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
if (!(block_after_update = LLVMAppendBasicBlockInContext(
comp_ctx->context, func_ctx->func, "block_after_update"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
LLVMMoveBasicBlockAfter(block_update, block_curr);
LLVMMoveBasicBlockAfter(block_after_update, block_update);
if (!LLVMBuildCondBr(comp_ctx->builder, cmp, block_update,
block_after_update)) {
aot_set_last_error("llvm build cond br failed.");
return false;
}
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_update);
if (!LLVMBuildStore(comp_ctx->builder, new_sp,
func_ctx->native_stack_top_min_addr)) {
aot_set_last_error("llvm build store failed");
return false;
}
if (!LLVMBuildBr(comp_ctx->builder, block_after_update)) {
aot_set_last_error("llvm build br failed.");
return false;
}
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_after_update);
return true;
}
static bool static bool
check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 callee_cell_num) uint32 callee_cell_num)
@ -409,6 +490,19 @@ check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return true; return true;
} }
static bool
check_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 callee_cell_num)
{
if (comp_ctx->enable_stack_estimation
&& !record_stack_usage(comp_ctx, func_ctx, callee_cell_num))
return false;
if (comp_ctx->enable_stack_bound_check
&& !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
return false;
return true;
}
/** /**
* Check whether the app address and its buffer are inside the linear memory, * Check whether the app address and its buffer are inside the linear memory,
* if no, throw exception * if no, throw exception
@ -852,8 +946,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
callee_cell_num = callee_cell_num =
aot_func->param_cell_num + aot_func->local_cell_num + 1; aot_func->param_cell_num + aot_func->local_cell_num + 1;
if (comp_ctx->enable_stack_bound_check if (!check_stack(comp_ctx, func_ctx, callee_cell_num))
&& !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
goto fail; goto fail;
#if LLVM_VERSION_MAJOR >= 14 #if LLVM_VERSION_MAJOR >= 14
@ -906,6 +999,14 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
} }
#endif #endif
#if WASM_ENABLE_THREAD_MGR != 0
/* Insert suspend check point */
if (comp_ctx->enable_thread_mgr) {
if (!check_suspend_flags(comp_ctx, func_ctx))
goto fail;
}
#endif
ret = true; ret = true;
fail: fail:
if (param_types) if (param_types)
@ -1467,12 +1568,11 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* Translate call non-import block */ /* Translate call non-import block */
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import); LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import);
if (comp_ctx->enable_stack_bound_check if (!check_stack(comp_ctx, func_ctx,
&& !check_stack_boundary(comp_ctx, func_ctx, param_cell_num + ext_cell_num
param_cell_num + ext_cell_num + 1
+ 1 /* Reserve some local variables */
/* Reserve some local variables */ + 16))
+ 16))
goto fail; goto fail;
/* Load function pointer */ /* Load function pointer */
@ -1553,6 +1653,14 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
} }
#endif #endif
#if WASM_ENABLE_THREAD_MGR != 0
/* Insert suspend check point */
if (comp_ctx->enable_thread_mgr) {
if (!check_suspend_flags(comp_ctx, func_ctx))
goto fail;
}
#endif
ret = true; ret = true;
fail: fail:

View File

@ -7,6 +7,7 @@
#include "aot_emit_exception.h" #include "aot_emit_exception.h"
#include "../aot/aot_runtime.h" #include "../aot/aot_runtime.h"
#include "aot_intrinsic.h" #include "aot_intrinsic.h"
#include "aot_emit_control.h"
#define BUILD_ICMP(op, left, right, res, name) \ #define BUILD_ICMP(op, left, right, res, name) \
do { \ do { \
@ -1344,7 +1345,7 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return false; return false;
} }
BUILD_ICMP(LLVMIntSGT, ret_value, I32_ZERO, cmp, "atomic_wait_ret"); BUILD_ICMP(LLVMIntNE, ret_value, I32_NEG_ONE, cmp, "atomic_wait_ret");
ADD_BASIC_BLOCK(wait_fail, "atomic_wait_fail"); ADD_BASIC_BLOCK(wait_fail, "atomic_wait_fail");
ADD_BASIC_BLOCK(wait_success, "wait_success"); ADD_BASIC_BLOCK(wait_success, "wait_success");
@ -1368,6 +1369,14 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
PUSH_I32(ret_value); PUSH_I32(ret_value);
#if WASM_ENABLE_THREAD_MGR != 0
/* Insert suspend check point */
if (comp_ctx->enable_thread_mgr) {
if (!check_suspend_flags(comp_ctx, func_ctx))
return false;
}
#endif
return true; return true;
fail: fail:
return false; return false;
@ -1414,4 +1423,13 @@ fail:
return false; return false;
} }
bool
aot_compiler_op_atomic_fence(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{
return LLVMBuildFence(comp_ctx->builder,
LLVMAtomicOrderingSequentiallyConsistent, false, "")
? true
: false;
}
#endif /* end of WASM_ENABLE_SHARED_MEMORY */ #endif /* end of WASM_ENABLE_SHARED_MEMORY */

View File

@ -97,6 +97,10 @@ bool
aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx, aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx, uint32 align, AOTFuncContext *func_ctx, uint32 align,
uint32 offset, uint32 bytes); uint32 offset, uint32 bytes);
bool
aot_compiler_op_atomic_fence(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -286,6 +286,21 @@ create_native_stack_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
return true; return true;
} }
static bool
create_native_stack_top_min(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{
LLVMValueRef offset = I32_NINE;
if (!(func_ctx->native_stack_top_min_addr = LLVMBuildInBoundsGEP2(
comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1,
"native_stack_top_min_addr"))) {
aot_set_last_error("llvm build in bounds gep failed");
return false;
}
return true;
}
static bool static bool
create_aux_stack_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) create_aux_stack_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{ {
@ -434,7 +449,8 @@ create_local_variables(AOTCompData *comp_data, AOTCompContext *comp_ctx,
} }
} }
if (comp_ctx->enable_stack_bound_check) { if (comp_ctx->enable_stack_bound_check
|| comp_ctx->enable_stack_estimation) {
if (aot_func_type->param_count + func->local_count > 0) { if (aot_func_type->param_count + func->local_count > 0) {
func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count
+ func->local_count - 1]; + func->local_count - 1];
@ -963,6 +979,10 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
&& !create_native_stack_bound(comp_ctx, func_ctx)) { && !create_native_stack_bound(comp_ctx, func_ctx)) {
goto fail; goto fail;
} }
if (comp_ctx->enable_stack_estimation
&& !create_native_stack_top_min(comp_ctx, func_ctx)) {
goto fail;
}
/* Get auxiliary stack info */ /* Get auxiliary stack info */
if (wasm_func->has_op_set_global_aux_stack if (wasm_func->has_op_set_global_aux_stack
@ -1622,6 +1642,9 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
if (option->disable_llvm_lto) if (option->disable_llvm_lto)
comp_ctx->disable_llvm_lto = true; comp_ctx->disable_llvm_lto = true;
if (option->enable_stack_estimation)
comp_ctx->enable_stack_estimation = true;
comp_ctx->opt_level = option->opt_level; comp_ctx->opt_level = option->opt_level;
comp_ctx->size_level = option->size_level; comp_ctx->size_level = option->size_level;

View File

@ -163,6 +163,7 @@ typedef struct AOTFuncContext {
LLVMValueRef aot_inst; LLVMValueRef aot_inst;
LLVMValueRef argv_buf; LLVMValueRef argv_buf;
LLVMValueRef native_stack_bound; LLVMValueRef native_stack_bound;
LLVMValueRef native_stack_top_min_addr;
LLVMValueRef aux_stack_bound; LLVMValueRef aux_stack_bound;
LLVMValueRef aux_stack_bottom; LLVMValueRef aux_stack_bottom;
LLVMValueRef native_symbol; LLVMValueRef native_symbol;
@ -313,6 +314,9 @@ typedef struct AOTCompContext {
/* Native stack bounday Check */ /* Native stack bounday Check */
bool enable_stack_bound_check; bool enable_stack_bound_check;
/* Native stack usage estimation */
bool enable_stack_estimation;
/* 128-bit SIMD */ /* 128-bit SIMD */
bool enable_simd; bool enable_simd;
@ -403,6 +407,7 @@ typedef struct AOTCompOption {
bool enable_aux_stack_frame; bool enable_aux_stack_frame;
bool disable_llvm_intrinsics; bool disable_llvm_intrinsics;
bool disable_llvm_lto; bool disable_llvm_lto;
bool enable_stack_estimation;
uint32 opt_level; uint32 opt_level;
uint32 size_level; uint32 size_level;
uint32 output_format; uint32 output_format;

View File

@ -135,7 +135,8 @@ check_and_seek(JitCompContext *cc, JitReg addr, uint32 offset, uint32 bytes)
#ifndef OS_ENABLE_HW_BOUND_CHECK #ifndef OS_ENABLE_HW_BOUND_CHECK
/* ---------- check ---------- */ /* ---------- check ---------- */
/* 1. shortcut if the memory size is 0 */ /* 1. shortcut if the memory size is 0 */
if (0 == cc->cur_wasm_module->memories[mem_idx].init_page_count) { if (cc->cur_wasm_module->memories != NULL
&& 0 == cc->cur_wasm_module->memories[mem_idx].init_page_count) {
JitReg module_inst, cur_page_count; JitReg module_inst, cur_page_count;
uint32 cur_page_count_offset = uint32 cur_page_count_offset =
(uint32)offsetof(WASMModuleInstance, global_table_data.bytes) (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
@ -176,6 +177,18 @@ fail:
return 0; return 0;
} }
#define CHECK_ALIGNMENT(maddr, memory_data, offset1) \
do { \
GEN_INSN(ADD, maddr, memory_data, offset1); \
JitReg align_mask = NEW_CONST(I64, ((uint64)1 << align) - 1); \
JitReg AND_res = jit_cc_new_reg_I64(cc); \
GEN_INSN(AND, AND_res, maddr, align_mask); \
GEN_INSN(CMP, cc->cmp_reg, AND_res, NEW_CONST(I64, 0)); \
if (!jit_emit_exception(cc, EXCE_UNALIGNED_ATOMIC, JIT_OP_BNE, \
cc->cmp_reg, NULL)) \
goto fail; \
} while (0)
bool bool
jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset, jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset,
uint32 bytes, bool sign, bool atomic) uint32 bytes, bool sign, bool atomic)
@ -779,6 +792,51 @@ bool
jit_compile_op_atomic_wait(JitCompContext *cc, uint8 op_type, uint32 align, jit_compile_op_atomic_wait(JitCompContext *cc, uint8 op_type, uint32 align,
uint32 offset, uint32 bytes) uint32 offset, uint32 bytes)
{ {
bh_assert(op_type == VALUE_TYPE_I32 || op_type == VALUE_TYPE_I64);
// Pop atomic.wait arguments
JitReg timeout, expect, expect_64, addr;
POP_I64(timeout);
if (op_type == VALUE_TYPE_I32) {
POP_I32(expect);
expect_64 = jit_cc_new_reg_I64(cc);
GEN_INSN(I32TOI64, expect_64, expect);
}
else {
POP_I64(expect_64);
}
POP_I32(addr);
// Get referenced address and store it in `maddr`
JitReg memory_data = get_memory_data_reg(cc->jit_frame, 0);
JitReg offset1 = check_and_seek(cc, addr, offset, bytes);
if (!offset1)
goto fail;
JitReg maddr = jit_cc_new_reg_I64(cc);
CHECK_ALIGNMENT(maddr, memory_data, offset1);
// Prepare `wasm_runtime_atomic_wait` arguments
JitReg res = jit_cc_new_reg_I32(cc);
JitReg args[5] = { 0 };
args[0] = get_module_inst_reg(cc->jit_frame);
args[1] = maddr;
args[2] = expect_64;
args[3] = timeout;
args[4] = NEW_CONST(I32, false);
if (!jit_emit_callnative(cc, wasm_runtime_atomic_wait, res, args,
sizeof(args) / sizeof(args[0])))
goto fail;
// Handle return code
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, -1));
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ, cc->cmp_reg,
NULL))
goto fail;
PUSH_I32(res);
return true;
fail:
return false; return false;
} }
@ -786,6 +844,39 @@ bool
jit_compiler_op_atomic_notify(JitCompContext *cc, uint32 align, uint32 offset, jit_compiler_op_atomic_notify(JitCompContext *cc, uint32 align, uint32 offset,
uint32 bytes) uint32 bytes)
{ {
// Pop atomic.notify arguments
JitReg notify_count, addr;
POP_I32(notify_count);
POP_I32(addr);
// Get referenced address and store it in `maddr`
JitReg memory_data = get_memory_data_reg(cc->jit_frame, 0);
JitReg offset1 = check_and_seek(cc, addr, offset, bytes);
if (!offset1)
goto fail;
JitReg maddr = jit_cc_new_reg_I64(cc);
CHECK_ALIGNMENT(maddr, memory_data, offset1);
// Prepare `wasm_runtime_atomic_notify` arguments
JitReg res = jit_cc_new_reg_I32(cc);
JitReg args[3] = { 0 };
args[0] = get_module_inst_reg(cc->jit_frame);
args[1] = maddr;
args[2] = notify_count;
if (!jit_emit_callnative(cc, wasm_runtime_atomic_notify, res, args,
sizeof(args) / sizeof(args[0])))
goto fail;
// Handle return code
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
NULL))
goto fail;
PUSH_I32(res);
return true;
fail:
return false; return false;
} }
#endif #endif

View File

@ -56,9 +56,31 @@ jit_code_cache_free(void *ptr)
bool bool
jit_pass_register_jitted_code(JitCompContext *cc) jit_pass_register_jitted_code(JitCompContext *cc)
{ {
uint32 jit_func_idx = WASMModuleInstance *instance;
cc->cur_wasm_func_idx - cc->cur_wasm_module->import_function_count; WASMModule *module = cc->cur_wasm_module;
cc->cur_wasm_module->fast_jit_func_ptrs[jit_func_idx] = WASMFunction *func = cc->cur_wasm_func;
cc->cur_wasm_func->fast_jit_jitted_code = cc->jitted_addr_begin; uint32 jit_func_idx = cc->cur_wasm_func_idx - module->import_function_count;
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
os_mutex_lock(&module->instance_list_lock);
#endif
module->fast_jit_func_ptrs[jit_func_idx] = func->fast_jit_jitted_code =
cc->jitted_addr_begin;
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
instance = module->instance_list;
while (instance) {
if (instance->e->running_mode == Mode_Fast_JIT)
instance->fast_jit_func_ptrs[jit_func_idx] = cc->jitted_addr_begin;
instance = instance->e->next;
}
os_mutex_unlock(&module->instance_list_lock);
#else
(void)instance;
#endif
return true; return true;
} }

View File

@ -157,8 +157,16 @@ jit_compiler_compile(WASMModule *module, uint32 func_idx)
/* Apply compiler passes */ /* Apply compiler passes */
if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) { if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) {
last_error = jit_get_last_error(cc); last_error = jit_get_last_error(cc);
#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
char *function_name = cc->cur_wasm_func->field_name;
os_printf("fast jit compilation failed: %s (function_name=%s)\n",
last_error ? last_error : "unknown error", function_name);
#else
os_printf("fast jit compilation failed: %s\n", os_printf("fast jit compilation failed: %s\n",
last_error ? last_error : "unknown error"); last_error ? last_error : "unknown error");
#endif
goto fail; goto fail;
} }
@ -246,6 +254,8 @@ jit_compiler_set_call_to_fast_jit(WASMModule *module, uint32 func_idx)
func_ptr = jit_codegen_compile_call_to_fast_jit(module, func_idx); func_ptr = jit_codegen_compile_call_to_fast_jit(module, func_idx);
if (func_ptr) { if (func_ptr) {
uint32 i = func_idx - module->import_function_count;
module->functions[i]->call_to_fast_jit_from_llvm_jit = func_ptr;
jit_compiler_set_llvm_jit_func_ptr(module, func_idx, func_ptr); jit_compiler_set_llvm_jit_func_ptr(module, func_idx, func_ptr);
} }
@ -259,12 +269,14 @@ jit_compiler_set_llvm_jit_func_ptr(WASMModule *module, uint32 func_idx,
WASMModuleInstance *instance; WASMModuleInstance *instance;
uint32 i = func_idx - module->import_function_count; uint32 i = func_idx - module->import_function_count;
module->functions[i]->llvm_jit_func_ptr = module->func_ptrs[i] = func_ptr;
os_mutex_lock(&module->instance_list_lock); os_mutex_lock(&module->instance_list_lock);
module->func_ptrs[i] = func_ptr;
instance = module->instance_list; instance = module->instance_list;
while (instance) { while (instance) {
instance->func_ptrs[func_idx] = func_ptr; if (instance->e->running_mode == Mode_Multi_Tier_JIT)
instance->func_ptrs[func_idx] = func_ptr;
instance = instance->e->next; instance = instance->e->next;
} }
os_mutex_unlock(&module->instance_list_lock); os_mutex_unlock(&module->instance_list_lock);

View File

@ -841,7 +841,7 @@ init_func_translation(JitCompContext *cc)
cc->spill_cache_offset = wasm_interp_interp_frame_size(total_cell_num); cc->spill_cache_offset = wasm_interp_interp_frame_size(total_cell_num);
/* Set spill cache size according to max local cell num, max stack cell /* Set spill cache size according to max local cell num, max stack cell
num and virtual fixed register num */ num and virtual fixed register num */
cc->spill_cache_size = (max_locals + max_stacks) * 4 + sizeof(void *) * 5; cc->spill_cache_size = (max_locals + max_stacks) * 4 + sizeof(void *) * 16;
cc->total_frame_size = cc->spill_cache_offset + cc->spill_cache_size; cc->total_frame_size = cc->spill_cache_offset + cc->spill_cache_size;
cc->jitted_return_address_offset = cc->jitted_return_address_offset =
offsetof(WASMInterpFrame, jitted_return_addr); offsetof(WASMInterpFrame, jitted_return_addr);

View File

@ -560,6 +560,7 @@ address_of_const(JitCompContext *cc, JitReg reg, unsigned size)
unsigned no = jit_reg_no(reg); unsigned no = jit_reg_no(reg);
unsigned idx = no & ~_JIT_REG_CONST_IDX_FLAG; unsigned idx = no & ~_JIT_REG_CONST_IDX_FLAG;
bh_assert(kind < JIT_REG_KIND_L32);
bh_assert(jit_reg_is_const_idx(reg) && idx < cc->_const_val._num[kind]); bh_assert(jit_reg_is_const_idx(reg) && idx < cc->_const_val._num[kind]);
return cc->_const_val._value[kind] + size * idx; return cc->_const_val._value[kind] + size * idx;
@ -572,6 +573,7 @@ next_of_const(JitCompContext *cc, JitReg reg)
unsigned no = jit_reg_no(reg); unsigned no = jit_reg_no(reg);
unsigned idx = no & ~_JIT_REG_CONST_IDX_FLAG; unsigned idx = no & ~_JIT_REG_CONST_IDX_FLAG;
bh_assert(kind < JIT_REG_KIND_L32);
bh_assert(jit_reg_is_const_idx(reg) && idx < cc->_const_val._num[kind]); bh_assert(jit_reg_is_const_idx(reg) && idx < cc->_const_val._num[kind]);
return cc->_const_val._next[kind][idx]; return cc->_const_val._next[kind][idx];

View File

@ -1688,6 +1688,7 @@ jit_cc_is_hreg(JitCompContext *cc, JitReg reg)
unsigned kind = jit_reg_kind(reg); unsigned kind = jit_reg_kind(reg);
unsigned no = jit_reg_no(reg); unsigned no = jit_reg_no(reg);
bh_assert(jit_reg_is_variable(reg)); bh_assert(jit_reg_is_variable(reg));
bh_assert(kind < JIT_REG_KIND_L32);
return no < cc->hreg_info->info[kind].num; return no < cc->hreg_info->info[kind].num;
} }
@ -1705,6 +1706,7 @@ jit_cc_is_hreg_fixed(JitCompContext *cc, JitReg reg)
unsigned kind = jit_reg_kind(reg); unsigned kind = jit_reg_kind(reg);
unsigned no = jit_reg_no(reg); unsigned no = jit_reg_no(reg);
bh_assert(jit_cc_is_hreg(cc, reg)); bh_assert(jit_cc_is_hreg(cc, reg));
bh_assert(kind < JIT_REG_KIND_L32);
return !!cc->hreg_info->info[kind].fixed[no]; return !!cc->hreg_info->info[kind].fixed[no];
} }
@ -1722,6 +1724,7 @@ jit_cc_is_hreg_caller_saved_native(JitCompContext *cc, JitReg reg)
unsigned kind = jit_reg_kind(reg); unsigned kind = jit_reg_kind(reg);
unsigned no = jit_reg_no(reg); unsigned no = jit_reg_no(reg);
bh_assert(jit_cc_is_hreg(cc, reg)); bh_assert(jit_cc_is_hreg(cc, reg));
bh_assert(kind < JIT_REG_KIND_L32);
return !!cc->hreg_info->info[kind].caller_saved_native[no]; return !!cc->hreg_info->info[kind].caller_saved_native[no];
} }
@ -1739,6 +1742,7 @@ jit_cc_is_hreg_caller_saved_jitted(JitCompContext *cc, JitReg reg)
unsigned kind = jit_reg_kind(reg); unsigned kind = jit_reg_kind(reg);
unsigned no = jit_reg_no(reg); unsigned no = jit_reg_no(reg);
bh_assert(jit_cc_is_hreg(cc, reg)); bh_assert(jit_cc_is_hreg(cc, reg));
bh_assert(kind < JIT_REG_KIND_L32);
return !!cc->hreg_info->info[kind].caller_saved_jitted[no]; return !!cc->hreg_info->info[kind].caller_saved_jitted[no];
} }

View File

@ -156,6 +156,7 @@ rc_get_vr(RegallocContext *rc, JitReg vreg)
unsigned no = jit_reg_no(vreg); unsigned no = jit_reg_no(vreg);
bh_assert(jit_reg_is_variable(vreg)); bh_assert(jit_reg_is_variable(vreg));
bh_assert(kind < JIT_REG_KIND_L32);
return &rc->vregs[kind][no]; return &rc->vregs[kind][no];
} }
@ -175,6 +176,7 @@ rc_get_hr(RegallocContext *rc, JitReg hreg)
unsigned no = jit_reg_no(hreg); unsigned no = jit_reg_no(hreg);
bh_assert(jit_reg_is_variable(hreg) && jit_cc_is_hreg(rc->cc, hreg)); bh_assert(jit_reg_is_variable(hreg) && jit_cc_is_hreg(rc->cc, hreg));
bh_assert(kind < JIT_REG_KIND_L32);
return &rc->hregs[kind][no]; return &rc->hregs[kind][no];
} }
@ -208,7 +210,9 @@ static unsigned
get_reg_stride(JitReg reg) get_reg_stride(JitReg reg)
{ {
static const uint8 strides[] = { 0, 1, 2, 1, 2, 2, 4, 8, 0 }; static const uint8 strides[] = { 0, 1, 2, 1, 2, 2, 4, 8, 0 };
return strides[jit_reg_kind(reg)]; uint32 kind = jit_reg_kind(reg);
bh_assert(kind <= JIT_REG_KIND_L32);
return strides[kind];
} }
/** /**
@ -582,13 +586,17 @@ static JitReg
allocate_hreg(RegallocContext *rc, JitReg vreg, JitInsn *insn, int distance) allocate_hreg(RegallocContext *rc, JitReg vreg, JitInsn *insn, int distance)
{ {
const int kind = jit_reg_kind(vreg); const int kind = jit_reg_kind(vreg);
const HardReg *hregs = rc->hregs[kind]; const HardReg *hregs;
const unsigned hreg_num = jit_cc_hreg_num(rc->cc, kind); unsigned hreg_num;
JitReg hreg, vreg_to_reload = 0; JitReg hreg, vreg_to_reload = 0;
int min_distance = distance, vr_distance; int min_distance = distance, vr_distance;
VirtualReg *vr = rc_get_vr(rc, vreg); VirtualReg *vr = rc_get_vr(rc, vreg);
unsigned i; unsigned i;
bh_assert(kind < JIT_REG_KIND_L32);
hregs = rc->hregs[kind];
hreg_num = jit_cc_hreg_num(rc->cc, kind);
if (hreg_num == 0) if (hreg_num == 0)
/* Unsupported hard register kind. */ /* Unsupported hard register kind. */
{ {

View File

@ -55,6 +55,7 @@ typedef struct AOTCompOption {
bool enable_aux_stack_frame; bool enable_aux_stack_frame;
bool disable_llvm_intrinsics; bool disable_llvm_intrinsics;
bool disable_llvm_lto; bool disable_llvm_lto;
bool enable_stack_estimation;
uint32_t opt_level; uint32_t opt_level;
uint32_t size_level; uint32_t size_level;
uint32_t output_format; uint32_t output_format;

View File

@ -354,6 +354,7 @@ WASM_API_EXTERN own wasm_importtype_t* wasm_importtype_new(
WASM_API_EXTERN const wasm_name_t* wasm_importtype_module(const wasm_importtype_t*); WASM_API_EXTERN const wasm_name_t* wasm_importtype_module(const wasm_importtype_t*);
WASM_API_EXTERN const wasm_name_t* wasm_importtype_name(const wasm_importtype_t*); WASM_API_EXTERN const wasm_name_t* wasm_importtype_name(const wasm_importtype_t*);
WASM_API_EXTERN const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t*); WASM_API_EXTERN const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t*);
WASM_API_EXTERN bool wasm_importtype_is_linked(const wasm_importtype_t*);
// Export Types // Export Types
@ -797,6 +798,9 @@ static inline void* wasm_val_ptr(const wasm_val_t* val) {
#define KILOBYTE(n) ((n) * 1024) #define KILOBYTE(n) ((n) * 1024)
// Create placeholders filled in `wasm_externvec_t* imports` for `wasm_instance_new()`
WASM_API_EXTERN wasm_extern_t *wasm_extern_new_empty(wasm_store_t *, wasm_externkind_t);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#undef own #undef own

View File

@ -131,6 +131,14 @@ typedef struct mem_alloc_info_t {
uint32_t highmark_size; uint32_t highmark_size;
} mem_alloc_info_t; } mem_alloc_info_t;
/* Running mode of runtime and module instance*/
typedef enum RunningMode {
Mode_Interp = 1,
Mode_Fast_JIT,
Mode_LLVM_JIT,
Mode_Multi_Tier_JIT,
} RunningMode;
/* WASM runtime initialize arguments */ /* WASM runtime initialize arguments */
typedef struct RuntimeInitArgs { typedef struct RuntimeInitArgs {
mem_alloc_type_t mem_alloc_type; mem_alloc_type_t mem_alloc_type;
@ -152,6 +160,13 @@ typedef struct RuntimeInitArgs {
/* Fast JIT code cache size */ /* Fast JIT code cache size */
uint32_t fast_jit_code_cache_size; uint32_t fast_jit_code_cache_size;
/* Default running mode of the runtime */
RunningMode running_mode;
/* LLVM JIT opt and size level */
uint32_t llvm_jit_opt_level;
uint32_t llvm_jit_size_level;
} RuntimeInitArgs; } RuntimeInitArgs;
#ifndef WASM_VALKIND_T_DEFINED #ifndef WASM_VALKIND_T_DEFINED
@ -195,9 +210,9 @@ WASM_RUNTIME_API_EXTERN bool
wasm_runtime_init(void); wasm_runtime_init(void);
/** /**
* Initialize the WASM runtime environment, and also initialize * Initialize the WASM runtime environment, WASM running mode,
* the memory allocator and register native symbols, which are specified * and also initialize the memory allocator and register native symbols,
* with init arguments * which are specified with init arguments
* *
* @param init_args specifies the init arguments * @param init_args specifies the init arguments
* *
@ -206,6 +221,28 @@ wasm_runtime_init(void);
WASM_RUNTIME_API_EXTERN bool WASM_RUNTIME_API_EXTERN bool
wasm_runtime_full_init(RuntimeInitArgs *init_args); wasm_runtime_full_init(RuntimeInitArgs *init_args);
/**
* Query whether a certain running mode is supported for the runtime
*
* @param running_mode the running mode to query
*
* @return true if this running mode is supported, false otherwise
*/
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_running_mode_supported(RunningMode running_mode);
/**
* Set the default running mode for the runtime. It is inherited
* to set the running mode of a module instance when it is instantiated,
* and can be changed by calling wasm_runtime_set_running_mode
*
* @param running_mode the running mode to set
*
* @return true if success, false otherwise
*/
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_set_default_running_mode(RunningMode running_mode);
/** /**
* Destroy the WASM runtime environment. * Destroy the WASM runtime environment.
*/ */
@ -450,6 +487,34 @@ wasm_runtime_instantiate(const wasm_module_t module,
uint32_t stack_size, uint32_t heap_size, uint32_t stack_size, uint32_t heap_size,
char *error_buf, uint32_t error_buf_size); char *error_buf, uint32_t error_buf_size);
/**
* Set the running mode of a WASM module instance, override the
* default running mode of the runtime. Note that it only makes sense when
* the input is a wasm bytecode file: for the AOT file, runtime always runs
* it with AOT engine, and this function always returns true.
*
* @param module_inst the WASM module instance to set running mode
* @param running_mode the running mode to set
*
* @return true if success, false otherwise
*/
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
RunningMode running_mode);
/**
* Get the running mode of a WASM module instance, if no running mode
* is explicitly set the default running mode of runtime will
* be used and returned. Note that it only makes sense when the input is a
* wasm bytecode file: for the AOT file, this function always returns 0.
*
* @param module_inst the WASM module instance to query for running mode
*
* @return the running mode this module instance currently use
*/
WASM_RUNTIME_API_EXTERN RunningMode
wasm_runtime_get_running_mode(wasm_module_inst_t module_inst);
/** /**
* Deinstantiate a WASM module instance, destroy the resources. * Deinstantiate a WASM module instance, destroy the resources.
* *
@ -735,6 +800,31 @@ wasm_runtime_call_wasm_v(wasm_exec_env_t exec_env,
uint32_t num_results, wasm_val_t results[], uint32_t num_results, wasm_val_t results[],
uint32_t num_args, ...); uint32_t num_args, ...);
/**
* Call a function reference of a given WASM runtime instance with
* arguments.
*
* Note: this can be used to call a function which is not exported
* by the module explicitly. You might consider it as an abstraction
* violation.
*
* @param exec_env the execution environment to call the function
* which must be created from wasm_create_exec_env()
* @param element_index the function reference index, usually
* prvovided by the caller of a registed native function
* @param argc the number of arguments
* @param argv the arguments. If the function method has return value,
* the first (or first two in case 64-bit return value) element of
* argv stores the return value of the called WASM function after this
* function returns.
*
* @return true if success, false otherwise and exception will be thrown,
* the caller can call wasm_runtime_get_exception to get exception info.
*/
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_call_indirect(wasm_exec_env_t exec_env, uint32_t element_index,
uint32_t argc, uint32_t argv[]);
/** /**
* Find the unique main function from a WASM module instance * Find the unique main function from a WASM module instance
* and execute that function. * and execute that function.
@ -1259,6 +1349,22 @@ wasm_runtime_get_custom_section(wasm_module_t const module_comm,
*/ */
WASM_RUNTIME_API_EXTERN void WASM_RUNTIME_API_EXTERN void
wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch); wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch);
/**
* Check whether an import func `(import <module_name> <func_name> (func ...))` is linked or not
* with runtime registered natvie functions
*/
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_import_func_linked(const char *module_name,
const char *func_name);
/**
* Check whether an import global `(import <module_name> <global_name> (global ...))` is linked or not
* with runtime registered natvie globals
*/
WASM_RUNTIME_API_EXTERN bool
wasm_runtime_is_import_global_linked(const char *module_name,
const char *global_name);
/* clang-format on */ /* clang-format on */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -278,9 +278,14 @@ struct WASMFunction {
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
/* The compiled fast jit jitted code block of this function */
void *fast_jit_jitted_code; void *fast_jit_jitted_code;
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
/* The compiled llvm jit func ptr of this function */
void *llvm_jit_func_ptr; void *llvm_jit_func_ptr;
/* Code block to call fast jit jitted code of this function
from the llvm jit jitted code */
void *call_to_fast_jit_from_llvm_jit;
#endif #endif
#endif #endif
}; };
@ -505,15 +510,14 @@ struct WASMModule {
uint64 load_size; uint64 load_size;
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \ #if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0) && WASM_ENABLE_LAZY_JIT != 0)
/** /**
* List of instances referred to this module. When source debugging * List of instances referred to this module. When source debugging
* feature is enabled, the debugger may modify the code section of * feature is enabled, the debugger may modify the code section of
* the module, so we need to report a warning if user create several * the module, so we need to report a warning if user create several
* instances based on the same module. Sub instances created by * instances based on the same module.
* lib-pthread or spawn API won't be added into the list.
* *
* Also add the instance to the list for Fast JIT to LLVM JIT * Also add the instance to the list for Fast JIT to LLVM JIT
* tier-up, since we need to lazily update the LLVM func pointers * tier-up, since we need to lazily update the LLVM func pointers
@ -533,7 +537,22 @@ struct WASMModule {
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
/* func pointers of Fast JITed (un-imported) functions */ /**
* func pointers of Fast JITed (un-imported) functions
* for non Multi-Tier JIT mode:
* (1) when lazy jit is disabled, each pointer is set to the compiled
* fast jit jitted code
* (2) when lazy jit is enabled, each pointer is firstly inited as
* jit_global->compile_fast_jit_and_then_call, and then set to the
* compiled fast jit jitted code when it is called (the stub will
* compile the jit function and then update itself)
* for Multi-Tier JIT mode:
* each pointer is firstly inited as compile_fast_jit_and_then_call,
* and then set to the compiled fast jit jitted code when it is called,
* and when the llvm jit func ptr of the same function is compiled, it
* will be set to call_to_llvm_jit_from_fast_jit of this function type
* (tier-up from fast-jit to llvm-jit)
*/
void **fast_jit_func_ptrs; void **fast_jit_func_ptrs;
/* locks for Fast JIT lazy compilation */ /* locks for Fast JIT lazy compilation */
korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM]; korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM];
@ -543,7 +562,16 @@ struct WASMModule {
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_JIT != 0
struct AOTCompData *comp_data; struct AOTCompData *comp_data;
struct AOTCompContext *comp_ctx; struct AOTCompContext *comp_ctx;
/* func pointers of LLVM JITed (un-imported) functions */ /**
* func pointers of LLVM JITed (un-imported) functions
* for non Multi-Tier JIT mode:
* each pointer is set to the lookuped llvm jit func ptr, note that it
* is a stub and will trigger the actual compilation when it is called
* for Multi-Tier JIT mode:
* each pointer is inited as call_to_fast_jit code block, when the llvm
* jit func ptr is actually compiled, it is set to the compiled llvm jit
* func ptr
*/
void **func_ptrs; void **func_ptrs;
/* whether the func pointers are compiled */ /* whether the func pointers are compiled */
bool *func_ptrs_compiled; bool *func_ptrs_compiled;
@ -568,6 +596,12 @@ struct WASMModule {
korp_tid llvm_jit_init_thread; korp_tid llvm_jit_init_thread;
/* whether the llvm jit is initialized */ /* whether the llvm jit is initialized */
bool llvm_jit_inited; bool llvm_jit_inited;
/* Whether to enable llvm jit compilation:
it is set to true only when there is a module instance starts to
run with running mode Mode_LLVM_JIT or Mode_Multi_Tier_JIT,
since no need to enable llvm jit compilation for Mode_Interp and
Mode_Fast_JIT, so as to improve performance for them */
bool enable_llvm_jit_compilation;
#endif #endif
}; };

View File

@ -8,6 +8,7 @@
#include "wasm_runtime.h" #include "wasm_runtime.h"
#include "wasm_opcode.h" #include "wasm_opcode.h"
#include "wasm_loader.h" #include "wasm_loader.h"
#include "wasm_memory.h"
#include "../common/wasm_exec_env.h" #include "../common/wasm_exec_env.h"
#if WASM_ENABLE_SHARED_MEMORY != 0 #if WASM_ENABLE_SHARED_MEMORY != 0
#include "../common/wasm_shared_memory.h" #include "../common/wasm_shared_memory.h"
@ -696,28 +697,28 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \ CHECK_ATOMIC_MEMORY_ACCESS(); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint32)(*(uint8 *)maddr); \ readv = (uint32)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \ *(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \ CHECK_ATOMIC_MEMORY_ACCESS(); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint32)LOAD_U16(maddr); \ readv = (uint32)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \ STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
else { \ else { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \ CHECK_ATOMIC_MEMORY_ACCESS(); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = LOAD_I32(maddr); \ readv = LOAD_I32(maddr); \
STORE_U32(maddr, readv op sval); \ STORE_U32(maddr, readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
PUSH_I32(readv); \ PUSH_I32(readv); \
break; \ break; \
@ -736,39 +737,39 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \ CHECK_ATOMIC_MEMORY_ACCESS(); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)(*(uint8 *)maddr); \ readv = (uint64)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \ *(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \ CHECK_ATOMIC_MEMORY_ACCESS(); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_U16(maddr); \ readv = (uint64)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \ STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \ CHECK_ATOMIC_MEMORY_ACCESS(); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_U32(maddr); \ readv = (uint64)LOAD_U32(maddr); \
STORE_U32(maddr, (uint32)(readv op sval)); \ STORE_U32(maddr, (uint32)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
else { \ else { \
uint64 op_result; \ uint64 op_result; \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(); \ CHECK_ATOMIC_MEMORY_ACCESS(); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_I64(maddr); \ readv = (uint64)LOAD_I64(maddr); \
op_result = readv op sval; \ op_result = readv op sval; \
STORE_I64(maddr, op_result); \ STORE_I64(maddr, op_result); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
PUSH_I64(readv); \ PUSH_I64(readv); \
break; \ break; \
@ -891,7 +892,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
if (!func_import->call_conv_wasm_c_api) { if (!func_import->call_conv_wasm_c_api) {
native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; native_func_pointer = module_inst->import_func_ptrs[cur_func_index];
} }
else { else if (module_inst->e->c_api_func_imports) {
c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index; c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index;
native_func_pointer = c_api_func_import->func_ptr_linked; native_func_pointer = c_api_func_import->func_ptr_linked;
} }
@ -954,7 +955,7 @@ fast_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
WASMFunctionInstance *cur_func = module_inst->e->functions + func_idx; WASMFunctionInstance *cur_func = module_inst->e->functions + func_idx;
wasm_interp_call_func_native(module_inst, exec_env, cur_func, prev_frame); wasm_interp_call_func_native(module_inst, exec_env, cur_func, prev_frame);
return wasm_get_exception(module_inst) ? false : true; return wasm_copy_exception(module_inst, NULL) ? false : true;
} }
#endif #endif
@ -1023,7 +1024,7 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst; exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
/* transfer exception if it is thrown */ /* transfer exception if it is thrown */
if (wasm_get_exception(sub_module_inst)) { if (wasm_copy_exception(sub_module_inst, NULL)) {
bh_memcpy_s(module_inst->cur_exception, bh_memcpy_s(module_inst->cur_exception,
sizeof(module_inst->cur_exception), sizeof(module_inst->cur_exception),
sub_module_inst->cur_exception, sub_module_inst->cur_exception,
@ -1036,21 +1037,25 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
#if WASM_ENABLE_DEBUG_INTERP != 0 #if WASM_ENABLE_DEBUG_INTERP != 0
#define CHECK_SUSPEND_FLAGS() \ #define CHECK_SUSPEND_FLAGS() \
do { \ do { \
os_mutex_lock(&exec_env->wait_lock); \
if (IS_WAMR_TERM_SIG(exec_env->current_status->signal_flag)) { \ if (IS_WAMR_TERM_SIG(exec_env->current_status->signal_flag)) { \
os_mutex_unlock(&exec_env->wait_lock); \
return; \ return; \
} \ } \
if (IS_WAMR_STOP_SIG(exec_env->current_status->signal_flag)) { \ if (IS_WAMR_STOP_SIG(exec_env->current_status->signal_flag)) { \
SYNC_ALL_TO_FRAME(); \ SYNC_ALL_TO_FRAME(); \
wasm_cluster_thread_stopped(exec_env); \
wasm_cluster_thread_waiting_run(exec_env); \ wasm_cluster_thread_waiting_run(exec_env); \
} \ } \
os_mutex_unlock(&exec_env->wait_lock); \
} while (0) } while (0)
#else #else
#define CHECK_SUSPEND_FLAGS() \ #define CHECK_SUSPEND_FLAGS() \
do { \ do { \
os_mutex_lock(&exec_env->wait_lock); \
if (exec_env->suspend_flags.flags != 0) { \ if (exec_env->suspend_flags.flags != 0) { \
if (exec_env->suspend_flags.flags & 0x01) { \ if (exec_env->suspend_flags.flags & 0x01) { \
/* terminate current thread */ \ /* terminate current thread */ \
os_mutex_unlock(&exec_env->wait_lock); \
return; \ return; \
} \ } \
while (exec_env->suspend_flags.flags & 0x02) { \ while (exec_env->suspend_flags.flags & 0x02) { \
@ -1058,6 +1063,7 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \ os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \
} \ } \
} \ } \
os_mutex_unlock(&exec_env->wait_lock); \
} while (0) } while (0)
#endif /* WASM_ENABLE_DEBUG_INTERP */ #endif /* WASM_ENABLE_DEBUG_INTERP */
#endif /* WASM_ENABLE_THREAD_MGR */ #endif /* WASM_ENABLE_THREAD_MGR */
@ -1077,7 +1083,6 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
&& exec_env->current_status->step_count++ == 1) { \ && exec_env->current_status->step_count++ == 1) { \
exec_env->current_status->step_count = 0; \ exec_env->current_status->step_count = 0; \
SYNC_ALL_TO_FRAME(); \ SYNC_ALL_TO_FRAME(); \
wasm_cluster_thread_stopped(exec_env); \
wasm_cluster_thread_waiting_run(exec_env); \ wasm_cluster_thread_waiting_run(exec_env); \
} \ } \
goto *handle_table[*frame_ip++]; \ goto *handle_table[*frame_ip++]; \
@ -1094,7 +1099,6 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
&& exec_env->current_status->step_count++ == 2) { \ && exec_env->current_status->step_count++ == 2) { \
exec_env->current_status->step_count = 0; \ exec_env->current_status->step_count = 0; \
SYNC_ALL_TO_FRAME(); \ SYNC_ALL_TO_FRAME(); \
wasm_cluster_thread_stopped(exec_env); \
wasm_cluster_thread_waiting_run(exec_env); \ wasm_cluster_thread_waiting_run(exec_env); \
} \ } \
continue continue
@ -1123,14 +1127,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMFunctionInstance *cur_func, WASMFunctionInstance *cur_func,
WASMInterpFrame *prev_frame) WASMInterpFrame *prev_frame)
{ {
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
#else
void *node = NULL;
#endif
WASMMemoryInstance *memory = wasm_get_default_memory(module); WASMMemoryInstance *memory = wasm_get_default_memory(module);
uint8 *global_data = module->global_data; uint8 *global_data = module->global_data;
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ #if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|| WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_BULK_MEMORY != 0
uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; uint32 num_bytes_per_page =
memory ? wasm_get_num_bytes_per_page(memory, node) : 0;
uint32 linear_mem_size = uint32 linear_mem_size =
memory ? num_bytes_per_page * memory->cur_page_count : 0; memory ? wasm_get_linear_memory_size(memory, node) : 0;
#endif #endif
WASMType **wasm_types = module->module->types; WASMType **wasm_types = module->module->types;
WASMGlobalInstance *globals = module->e->globals, *global; WASMGlobalInstance *globals = module->e->globals, *global;
@ -1365,7 +1377,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(EXT_OP_BR_TABLE_CACHE) HANDLE_OP(EXT_OP_BR_TABLE_CACHE)
{ {
BrTableCache *node = BrTableCache *node_cache =
bh_list_first_elem(module->module->br_table_cache_list); bh_list_first_elem(module->module->br_table_cache_list);
BrTableCache *node_next; BrTableCache *node_next;
@ -1374,13 +1386,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#endif #endif
lidx = POP_I32(); lidx = POP_I32();
while (node) { while (node_cache) {
node_next = bh_list_elem_next(node); node_next = bh_list_elem_next(node_cache);
if (node->br_table_op_addr == frame_ip - 1) { if (node_cache->br_table_op_addr == frame_ip - 1) {
depth = node->br_depths[lidx]; depth = node_cache->br_depths[lidx];
goto label_pop_csp_n; goto label_pop_csp_n;
} }
node = node_next; node_cache = node_next;
} }
bh_assert(0); bh_assert(0);
HANDLE_OP_END(); HANDLE_OP_END();
@ -3434,6 +3446,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (ret == (uint32)-1) if (ret == (uint32)-1)
goto got_exception; goto got_exception;
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
PUSH_I32(ret); PUSH_I32(ret);
break; break;
} }
@ -3454,6 +3470,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (ret == (uint32)-1) if (ret == (uint32)-1)
goto got_exception; goto got_exception;
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
PUSH_I32(ret); PUSH_I32(ret);
break; break;
} }
@ -3461,6 +3481,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{ {
/* Skip the memory index */ /* Skip the memory index */
frame_ip++; frame_ip++;
os_atomic_thread_fence(os_memory_order_release);
break; break;
} }
@ -3475,23 +3496,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)(*(uint8 *)maddr); readv = (uint32)(*(uint8 *)maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)LOAD_U16(maddr); readv = (uint32)LOAD_U16(maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I32(maddr); readv = LOAD_I32(maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
PUSH_I32(readv); PUSH_I32(readv);
@ -3510,30 +3531,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)(*(uint8 *)maddr); readv = (uint64)(*(uint8 *)maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U16(maddr); readv = (uint64)LOAD_U16(maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U32(maddr); readv = (uint64)LOAD_U32(maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I64(maddr); readv = LOAD_I64(maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
PUSH_I64(readv); PUSH_I64(readv);
@ -3552,23 +3573,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I32_STORE8) { if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
*(uint8 *)maddr = (uint8)sval; *(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
STORE_U16(maddr, (uint16)sval); STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
STORE_U32(maddr, frame_sp[1]); STORE_U32(maddr, frame_sp[1]);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
break; break;
} }
@ -3586,31 +3607,31 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I64_STORE8) { if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
*(uint8 *)maddr = (uint8)sval; *(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) { else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
STORE_U16(maddr, (uint16)sval); STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
STORE_U32(maddr, (uint32)sval); STORE_U32(maddr, (uint32)sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
PUT_I64_TO_ADDR((uint32 *)maddr, PUT_I64_TO_ADDR((uint32 *)maddr,
GET_I64_FROM_ADDR(frame_sp + 1)); GET_I64_FROM_ADDR(frame_sp + 1));
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
break; break;
} }
@ -3630,32 +3651,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint8)expect; expect = (uint8)expect;
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)(*(uint8 *)maddr); readv = (uint32)(*(uint8 *)maddr);
if (readv == expect) if (readv == expect)
*(uint8 *)maddr = (uint8)(sval); *(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint16)expect; expect = (uint16)expect;
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)LOAD_U16(maddr); readv = (uint32)LOAD_U16(maddr);
if (readv == expect) if (readv == expect)
STORE_U16(maddr, (uint16)(sval)); STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I32(maddr); readv = LOAD_I32(maddr);
if (readv == expect) if (readv == expect)
STORE_U32(maddr, sval); STORE_U32(maddr, sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
PUSH_I32(readv); PUSH_I32(readv);
break; break;
@ -3676,44 +3697,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint8)expect; expect = (uint8)expect;
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)(*(uint8 *)maddr); readv = (uint64)(*(uint8 *)maddr);
if (readv == expect) if (readv == expect)
*(uint8 *)maddr = (uint8)(sval); *(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint16)expect; expect = (uint16)expect;
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U16(maddr); readv = (uint64)LOAD_U16(maddr);
if (readv == expect) if (readv == expect)
STORE_U16(maddr, (uint16)(sval)); STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
expect = (uint32)expect; expect = (uint32)expect;
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U32(maddr); readv = (uint64)LOAD_U32(maddr);
if (readv == expect) if (readv == expect)
STORE_U32(maddr, (uint32)(sval)); STORE_U32(maddr, (uint32)(sval));
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(); CHECK_ATOMIC_MEMORY_ACCESS();
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_I64(maddr); readv = (uint64)LOAD_I64(maddr);
if (readv == expect) { if (readv == expect) {
STORE_I64(maddr, sval); STORE_I64(maddr, sval);
} }
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
PUSH_I64(readv); PUSH_I64(readv);
break; break;
@ -3859,7 +3880,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (memory) if (memory)
linear_mem_size = num_bytes_per_page * memory->cur_page_count; linear_mem_size = num_bytes_per_page * memory->cur_page_count;
#endif #endif
if (wasm_get_exception(module)) if (wasm_copy_exception(module, NULL))
goto got_exception; goto got_exception;
} }
else { else {
@ -3908,10 +3929,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
PUSH_CSP(LABEL_TYPE_FUNCTION, 0, cell_num, frame_ip_end - 1); PUSH_CSP(LABEL_TYPE_FUNCTION, 0, cell_num, frame_ip_end - 1);
wasm_exec_env_set_cur_frame(exec_env, frame); wasm_exec_env_set_cur_frame(exec_env, frame);
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
} }
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
HANDLE_OP_END(); HANDLE_OP_END();
} }
@ -4002,7 +4023,8 @@ fast_jit_call_func_bytecode(WASMModuleInstance *module_inst,
module_inst->fast_jit_func_ptrs[func_idx_non_import]); module_inst->fast_jit_func_ptrs[func_idx_non_import]);
bh_assert(action == JIT_INTERP_ACTION_NORMAL bh_assert(action == JIT_INTERP_ACTION_NORMAL
|| (action == JIT_INTERP_ACTION_THROWN || (action == JIT_INTERP_ACTION_THROWN
&& wasm_runtime_get_exception(exec_env->module_inst))); && wasm_copy_exception(
(WASMModuleInstance *)exec_env->module_inst, NULL)));
/* Get the return values form info.out.ret */ /* Get the return values form info.out.ret */
if (func_type->result_count) { if (func_type->result_count) {
@ -4034,24 +4056,6 @@ fast_jit_call_func_bytecode(WASMModuleInstance *module_inst,
#endif /* end of WASM_ENABLE_FAST_JIT != 0 */ #endif /* end of WASM_ENABLE_FAST_JIT != 0 */
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_JIT != 0
static bool
clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst)
{
#if WASM_ENABLE_LIBC_WASI != 0
const char *exception = wasm_get_exception(module_inst);
if (exception && !strcmp(exception, "Exception: wasi proc exit")) {
/* The "wasi proc exit" exception is thrown by native lib to
let wasm app exit, which is a normal behavior, we clear
the exception here. */
wasm_set_exception(module_inst, NULL);
return true;
}
return false;
#else
return false;
#endif
}
static bool static bool
llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst, llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
WASMExecEnv *exec_env, WASMExecEnv *exec_env,
@ -4111,14 +4115,6 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
ret = wasm_runtime_invoke_native( ret = wasm_runtime_invoke_native(
exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL, exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL,
argv1, argc, argv); argv1, argc, argv);
if (!ret || wasm_get_exception(module_inst)) {
if (clear_wasi_proc_exit_exception(module_inst))
ret = true;
else
ret = false;
}
if (!ret) { if (!ret) {
if (argv1 != argv1_buf) if (argv1 != argv1_buf)
wasm_runtime_free(argv1); wasm_runtime_free(argv1);
@ -4163,10 +4159,7 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL, exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL,
argv, argc, argv); argv, argc, argv);
if (clear_wasi_proc_exit_exception(module_inst)) return ret && !wasm_copy_exception(module_inst, NULL) ? true : false;
ret = true;
return ret && !wasm_get_exception(module_inst) ? true : false;
} }
} }
#endif /* end of WASM_ENABLE_JIT != 0 */ #endif /* end of WASM_ENABLE_JIT != 0 */
@ -4186,6 +4179,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num); unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
unsigned i; unsigned i;
bool copy_argv_from_frame = true; bool copy_argv_from_frame = true;
char exception[EXCEPTION_BUF_LEN];
if (argc < function->param_cell_num) { if (argc < function->param_cell_num) {
char buf[128]; char buf[128];
@ -4198,6 +4192,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
} }
argc = function->param_cell_num; argc = function->param_cell_num;
RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame);
#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \ #if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
&& WASM_DISABLE_STACK_HW_BOUND_CHECK == 0) && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) { if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
@ -4242,58 +4237,51 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
} }
} }
else { else {
#if WASM_ENABLE_LAZY_JIT != 0 RunningMode running_mode =
wasm_runtime_get_running_mode((wasm_module_inst_t)module_inst);
/* Fast JIT to LLVM JIT tier-up is enabled */ if (running_mode == Mode_Interp) {
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 wasm_interp_call_func_bytecode(module_inst, exec_env, function,
/* Fast JIT and LLVM JIT are both enabled, call llvm jit function frame);
if it is compiled, else call fast jit function */ }
uint32 func_idx = (uint32)(function - module_inst->e->functions); #if WASM_ENABLE_FAST_JIT != 0
if (module_inst->module->func_ptrs_compiled else if (running_mode == Mode_Fast_JIT) {
[func_idx - module_inst->module->import_function_count]) { fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
}
#endif
#if WASM_ENABLE_JIT != 0
else if (running_mode == Mode_LLVM_JIT) {
llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc, llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
argv); argv);
/* For llvm jit, the results have been stored in argv, /* For llvm jit, the results have been stored in argv,
no need to copy them from stack frame again */ no need to copy them from stack frame again */
copy_argv_from_frame = false; copy_argv_from_frame = false;
} }
else { #endif
fast_jit_call_func_bytecode(module_inst, exec_env, function, frame); #if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \
&& WASM_ENABLE_JIT != 0
else if (running_mode == Mode_Multi_Tier_JIT) {
/* Tier-up from Fast JIT to LLVM JIT, call llvm jit function
if it is compiled, else call fast jit function */
uint32 func_idx = (uint32)(function - module_inst->e->functions);
if (module_inst->module->func_ptrs_compiled
[func_idx - module_inst->module->import_function_count]) {
llvm_jit_call_func_bytecode(module_inst, exec_env, function,
argc, argv);
/* For llvm jit, the results have been stored in argv,
no need to copy them from stack frame again */
copy_argv_from_frame = false;
}
else {
fast_jit_call_func_bytecode(module_inst, exec_env, function,
frame);
}
} }
#elif WASM_ENABLE_JIT != 0
/* Only LLVM JIT is enabled */
llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
argv);
/* For llvm jit, the results have been stored in argv,
no need to copy them from stack frame again */
copy_argv_from_frame = false;
#elif WASM_ENABLE_FAST_JIT != 0
/* Only Fast JIT is enabled */
fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
#else
/* Both Fast JIT and LLVM JIT are disabled */
wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
#endif #endif
else {
#else /* else of WASM_ENABLE_LAZY_JIT != 0 */ /* There should always be a supported running mode selected */
bh_assert(0);
/* Fast JIT to LLVM JIT tier-up is enabled */ }
#if WASM_ENABLE_JIT != 0
/* LLVM JIT is enabled */
llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
argv);
/* For llvm jit, the results have been stored in argv,
no need to copy them from stack frame again */
copy_argv_from_frame = false;
#elif WASM_ENABLE_FAST_JIT != 0
/* Fast JIT is enabled */
fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
#else
/* Both Fast JIT and LLVM JIT are disabled */
wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
#endif
#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */
(void)wasm_interp_call_func_bytecode; (void)wasm_interp_call_func_bytecode;
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
@ -4302,7 +4290,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
} }
/* Output the return value to the caller */ /* Output the return value to the caller */
if (!wasm_get_exception(module_inst)) { if (!wasm_copy_exception(module_inst, NULL)) {
if (copy_argv_from_frame) { if (copy_argv_from_frame) {
for (i = 0; i < function->ret_cell_num; i++) { for (i = 0; i < function->ret_cell_num; i++) {
argv[i] = *(frame->sp + i - function->ret_cell_num); argv[i] = *(frame->sp + i - function->ret_cell_num);
@ -4315,7 +4303,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
wasm_interp_dump_call_stack(exec_env, true, NULL, 0); wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
} }
#endif #endif
LOG_DEBUG("meet an exception %s", wasm_get_exception(module_inst)); wasm_copy_exception(module_inst, exception);
LOG_DEBUG("meet an exception %s", exception);
} }
wasm_exec_env_set_cur_frame(exec_env, prev_frame); wasm_exec_env_set_cur_frame(exec_env, prev_frame);

View File

@ -8,6 +8,7 @@
#include "wasm_runtime.h" #include "wasm_runtime.h"
#include "wasm_opcode.h" #include "wasm_opcode.h"
#include "wasm_loader.h" #include "wasm_loader.h"
#include "wasm_memory.h"
#include "../common/wasm_exec_env.h" #include "../common/wasm_exec_env.h"
#if WASM_ENABLE_SHARED_MEMORY != 0 #if WASM_ENABLE_SHARED_MEMORY != 0
#include "../common/wasm_shared_memory.h" #include "../common/wasm_shared_memory.h"
@ -469,28 +470,28 @@ LOAD_PTR(void *addr)
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(1); \ CHECK_ATOMIC_MEMORY_ACCESS(1); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint32)(*(uint8 *)maddr); \ readv = (uint32)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \ *(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \ else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(2); \ CHECK_ATOMIC_MEMORY_ACCESS(2); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint32)LOAD_U16(maddr); \ readv = (uint32)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \ STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
else { \ else { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(4); \ CHECK_ATOMIC_MEMORY_ACCESS(4); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = LOAD_I32(maddr); \ readv = LOAD_I32(maddr); \
STORE_U32(maddr, readv op sval); \ STORE_U32(maddr, readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
PUSH_I32(readv); \ PUSH_I32(readv); \
break; \ break; \
@ -509,39 +510,39 @@ LOAD_PTR(void *addr)
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(1); \ CHECK_ATOMIC_MEMORY_ACCESS(1); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)(*(uint8 *)maddr); \ readv = (uint64)(*(uint8 *)maddr); \
*(uint8 *)maddr = (uint8)(readv op sval); \ *(uint8 *)maddr = (uint8)(readv op sval); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(2); \ CHECK_ATOMIC_MEMORY_ACCESS(2); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_U16(maddr); \ readv = (uint64)LOAD_U16(maddr); \
STORE_U16(maddr, (uint16)(readv op sval)); \ STORE_U16(maddr, (uint16)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \ else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(4); \ CHECK_ATOMIC_MEMORY_ACCESS(4); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_U32(maddr); \ readv = (uint64)LOAD_U32(maddr); \
STORE_U32(maddr, (uint32)(readv op sval)); \ STORE_U32(maddr, (uint32)(readv op sval)); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
else { \ else { \
uint64 op_result; \ uint64 op_result; \
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \ CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
CHECK_ATOMIC_MEMORY_ACCESS(8); \ CHECK_ATOMIC_MEMORY_ACCESS(8); \
\ \
os_mutex_lock(&module->e->mem_lock); \ os_mutex_lock(&node->shared_mem_lock); \
readv = (uint64)LOAD_I64(maddr); \ readv = (uint64)LOAD_I64(maddr); \
op_result = readv op sval; \ op_result = readv op sval; \
STORE_I64(maddr, op_result); \ STORE_I64(maddr, op_result); \
os_mutex_unlock(&module->e->mem_lock); \ os_mutex_unlock(&node->shared_mem_lock); \
} \ } \
PUSH_I64(readv); \ PUSH_I64(readv); \
break; \ break; \
@ -925,7 +926,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
if (!func_import->call_conv_wasm_c_api) { if (!func_import->call_conv_wasm_c_api) {
native_func_pointer = module_inst->import_func_ptrs[cur_func_index]; native_func_pointer = module_inst->import_func_ptrs[cur_func_index];
} }
else { else if (module_inst->e->c_api_func_imports) {
c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index; c_api_func_import = module_inst->e->c_api_func_imports + cur_func_index;
native_func_pointer = c_api_func_import->func_ptr_linked; native_func_pointer = c_api_func_import->func_ptr_linked;
} }
@ -1042,7 +1043,7 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst; exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
/* transfer exception if it is thrown */ /* transfer exception if it is thrown */
if (wasm_get_exception(sub_module_inst)) { if (wasm_copy_exception(sub_module_inst, NULL)) {
bh_memcpy_s(module_inst->cur_exception, bh_memcpy_s(module_inst->cur_exception,
sizeof(module_inst->cur_exception), sizeof(module_inst->cur_exception),
sub_module_inst->cur_exception, sub_module_inst->cur_exception,
@ -1054,13 +1055,16 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
#if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_THREAD_MGR != 0
#define CHECK_SUSPEND_FLAGS() \ #define CHECK_SUSPEND_FLAGS() \
do { \ do { \
os_mutex_lock(&exec_env->wait_lock); \
if (exec_env->suspend_flags.flags != 0) { \ if (exec_env->suspend_flags.flags != 0) { \
if (exec_env->suspend_flags.flags & 0x01) { \ if (exec_env->suspend_flags.flags & 0x01) { \
/* terminate current thread */ \ /* terminate current thread */ \
os_mutex_unlock(&exec_env->wait_lock); \
return; \ return; \
} \ } \
/* TODO: support suspend and breakpoint */ \ /* TODO: support suspend and breakpoint */ \
} \ } \
os_mutex_unlock(&exec_env->wait_lock); \
} while (0) } while (0)
#endif #endif
@ -1151,13 +1155,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMFunctionInstance *cur_func, WASMFunctionInstance *cur_func,
WASMInterpFrame *prev_frame) WASMInterpFrame *prev_frame)
{ {
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node =
wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
#else
void *node = NULL;
#endif
WASMMemoryInstance *memory = wasm_get_default_memory(module); WASMMemoryInstance *memory = wasm_get_default_memory(module);
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \ #if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \ || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|| WASM_ENABLE_BULK_MEMORY != 0 || WASM_ENABLE_BULK_MEMORY != 0
uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0; uint32 num_bytes_per_page =
memory ? wasm_get_num_bytes_per_page(memory, node) : 0;
uint32 linear_mem_size = uint32 linear_mem_size =
memory ? num_bytes_per_page * memory->cur_page_count : 0; memory ? wasm_get_linear_memory_size(memory, node) : 0;
#endif #endif
uint8 *global_data = module->global_data; uint8 *global_data = module->global_data;
WASMGlobalInstance *globals = module->e ? module->e->globals : NULL; WASMGlobalInstance *globals = module->e ? module->e->globals : NULL;
@ -3275,6 +3288,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (ret == (uint32)-1) if (ret == (uint32)-1)
goto got_exception; goto got_exception;
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
PUSH_I32(ret); PUSH_I32(ret);
break; break;
} }
@ -3295,9 +3312,18 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (ret == (uint32)-1) if (ret == (uint32)-1)
goto got_exception; goto got_exception;
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
PUSH_I32(ret); PUSH_I32(ret);
break; break;
} }
case WASM_OP_ATOMIC_FENCE:
{
os_atomic_thread_fence(os_memory_order_release);
break;
}
case WASM_OP_ATOMIC_I32_LOAD: case WASM_OP_ATOMIC_I32_LOAD:
case WASM_OP_ATOMIC_I32_LOAD8_U: case WASM_OP_ATOMIC_I32_LOAD8_U:
@ -3310,23 +3336,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) { if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1); CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)(*(uint8 *)maddr); readv = (uint32)(*(uint8 *)maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) { else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2); CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)LOAD_U16(maddr); readv = (uint32)LOAD_U16(maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4); CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I32(maddr); readv = LOAD_I32(maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
PUSH_I32(readv); PUSH_I32(readv);
@ -3345,30 +3371,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) { if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1); CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)(*(uint8 *)maddr); readv = (uint64)(*(uint8 *)maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) { else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2); CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U16(maddr); readv = (uint64)LOAD_U16(maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) { else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4); CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U32(maddr); readv = (uint64)LOAD_U32(maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8); CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I64(maddr); readv = LOAD_I64(maddr);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
PUSH_I64(readv); PUSH_I64(readv);
@ -3386,23 +3412,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I32_STORE8) { if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1); CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
*(uint8 *)maddr = (uint8)sval; *(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) { else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2); CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
STORE_U16(maddr, (uint16)sval); STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4); CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
STORE_U32(maddr, sval); STORE_U32(maddr, sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
break; break;
} }
@ -3420,30 +3446,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode == WASM_OP_ATOMIC_I64_STORE8) { if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(1); CHECK_ATOMIC_MEMORY_ACCESS(1);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
*(uint8 *)maddr = (uint8)sval; *(uint8 *)maddr = (uint8)sval;
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) { else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2); CHECK_ATOMIC_MEMORY_ACCESS(2);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
STORE_U16(maddr, (uint16)sval); STORE_U16(maddr, (uint16)sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) { else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4); CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
STORE_U32(maddr, (uint32)sval); STORE_U32(maddr, (uint32)sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8); CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
STORE_I64(maddr, sval); STORE_I64(maddr, sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
break; break;
} }
@ -3463,32 +3489,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS(1); CHECK_ATOMIC_MEMORY_ACCESS(1);
expect = (uint8)expect; expect = (uint8)expect;
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)(*(uint8 *)maddr); readv = (uint32)(*(uint8 *)maddr);
if (readv == expect) if (readv == expect)
*(uint8 *)maddr = (uint8)(sval); *(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) { else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2); CHECK_ATOMIC_MEMORY_ACCESS(2);
expect = (uint16)expect; expect = (uint16)expect;
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint32)LOAD_U16(maddr); readv = (uint32)LOAD_U16(maddr);
if (readv == expect) if (readv == expect)
STORE_U16(maddr, (uint16)(sval)); STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4); CHECK_ATOMIC_MEMORY_ACCESS(4);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = LOAD_I32(maddr); readv = LOAD_I32(maddr);
if (readv == expect) if (readv == expect)
STORE_U32(maddr, sval); STORE_U32(maddr, sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
PUSH_I32(readv); PUSH_I32(readv);
break; break;
@ -3509,44 +3535,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_ATOMIC_MEMORY_ACCESS(1); CHECK_ATOMIC_MEMORY_ACCESS(1);
expect = (uint8)expect; expect = (uint8)expect;
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)(*(uint8 *)maddr); readv = (uint64)(*(uint8 *)maddr);
if (readv == expect) if (readv == expect)
*(uint8 *)maddr = (uint8)(sval); *(uint8 *)maddr = (uint8)(sval);
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) { else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(2); CHECK_ATOMIC_MEMORY_ACCESS(2);
expect = (uint16)expect; expect = (uint16)expect;
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U16(maddr); readv = (uint64)LOAD_U16(maddr);
if (readv == expect) if (readv == expect)
STORE_U16(maddr, (uint16)(sval)); STORE_U16(maddr, (uint16)(sval));
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) { else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(4); CHECK_ATOMIC_MEMORY_ACCESS(4);
expect = (uint32)expect; expect = (uint32)expect;
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_U32(maddr); readv = (uint64)LOAD_U32(maddr);
if (readv == expect) if (readv == expect)
STORE_U32(maddr, (uint32)(sval)); STORE_U32(maddr, (uint32)(sval));
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
else { else {
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
CHECK_ATOMIC_MEMORY_ACCESS(8); CHECK_ATOMIC_MEMORY_ACCESS(8);
os_mutex_lock(&module->e->mem_lock); os_mutex_lock(&node->shared_mem_lock);
readv = (uint64)LOAD_I64(maddr); readv = (uint64)LOAD_I64(maddr);
if (readv == expect) { if (readv == expect) {
STORE_I64(maddr, sval); STORE_I64(maddr, sval);
} }
os_mutex_unlock(&module->e->mem_lock); os_mutex_unlock(&node->shared_mem_lock);
} }
PUSH_I64(readv); PUSH_I64(readv);
break; break;
@ -3797,7 +3823,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (memory) if (memory)
linear_mem_size = num_bytes_per_page * memory->cur_page_count; linear_mem_size = num_bytes_per_page * memory->cur_page_count;
#endif #endif
if (wasm_get_exception(module)) if (wasm_copy_exception(module, NULL))
goto got_exception; goto got_exception;
} }
else { else {
@ -3837,6 +3863,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)frame); wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)frame);
} }
#if WASM_ENABLE_THREAD_MGR != 0
CHECK_SUSPEND_FLAGS();
#endif
HANDLE_OP_END(); HANDLE_OP_END();
} }
@ -3905,6 +3934,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
/* This frame won't be used by JITed code, so only allocate interp /* This frame won't be used by JITed code, so only allocate interp
frame here. */ frame here. */
unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num); unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
char exception[EXCEPTION_BUF_LEN];
if (argc < function->param_cell_num) { if (argc < function->param_cell_num) {
char buf[128]; char buf[128];
@ -3917,6 +3947,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
} }
argc = function->param_cell_num; argc = function->param_cell_num;
RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame);
#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \ #if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
&& WASM_DISABLE_STACK_HW_BOUND_CHECK == 0) && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) { if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
@ -3969,7 +4000,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
} }
/* Output the return value to the caller */ /* Output the return value to the caller */
if (!wasm_get_exception(module_inst)) { if (!wasm_copy_exception(module_inst, NULL)) {
for (i = 0; i < function->ret_cell_num; i++) for (i = 0; i < function->ret_cell_num; i++)
argv[i] = *(frame->lp + i); argv[i] = *(frame->lp + i);
} }
@ -3979,7 +4010,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
wasm_interp_dump_call_stack(exec_env, true, NULL, 0); wasm_interp_dump_call_stack(exec_env, true, NULL, 0);
} }
#endif #endif
LOG_DEBUG("meet an exception %s", wasm_get_exception(module_inst)); wasm_copy_exception(module_inst, exception);
LOG_DEBUG("meet an exception %s", exception);
} }
wasm_exec_env_set_cur_frame(exec_env, prev_frame); wasm_exec_env_set_cur_frame(exec_env, prev_frame);

View File

@ -1399,6 +1399,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
WASMModule *sub_module = NULL; WASMModule *sub_module = NULL;
WASMGlobal *linked_global = NULL; WASMGlobal *linked_global = NULL;
#endif #endif
bool ret = false;
CHECK_BUF(p, p_end, 2); CHECK_BUF(p, p_end, 2);
declare_type = read_uint8(p); declare_type = read_uint8(p);
@ -1411,15 +1412,16 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
} }
#if WASM_ENABLE_LIBC_BUILTIN != 0 #if WASM_ENABLE_LIBC_BUILTIN != 0
global->is_linked = wasm_native_lookup_libc_builtin_global( ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name,
sub_module_name, global_name, global); global);
if (global->is_linked) { if (ret) {
if (global->type != declare_type if (global->type != declare_type
|| global->is_mutable != declare_mutable) { || global->is_mutable != declare_mutable) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"incompatible import type"); "incompatible import type");
return false; return false;
} }
global->is_linked = true;
} }
#endif #endif
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
@ -1449,6 +1451,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
global->is_mutable = (declare_mutable == 1); global->is_mutable = (declare_mutable == 1);
(void)parent_module; (void)parent_module;
(void)ret;
return true; return true;
fail: fail:
return false; return false;
@ -2989,6 +2992,7 @@ static bool
init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
uint32 error_buf_size) uint32 error_buf_size)
{ {
LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
AOTCompOption option = { 0 }; AOTCompOption option = { 0 };
char *aot_last_error; char *aot_last_error;
uint64 size; uint64 size;
@ -3027,8 +3031,11 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
} }
option.is_jit_mode = true; option.is_jit_mode = true;
option.opt_level = 3;
option.size_level = 3; llvm_jit_options = wasm_runtime_get_llvm_jit_options();
option.opt_level = llvm_jit_options.opt_level;
option.size_level = llvm_jit_options.size_level;
#if WASM_ENABLE_BULK_MEMORY != 0 #if WASM_ENABLE_BULK_MEMORY != 0
option.enable_bulk_memory = true; option.enable_bulk_memory = true;
#endif #endif
@ -3048,6 +3055,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0) #if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
option.enable_aux_stack_frame = true; option.enable_aux_stack_frame = true;
#endif #endif
#if WASM_ENABLE_MEMORY_PROFILING != 0
option.enable_stack_estimation = true;
#endif
module->comp_ctx = aot_create_comp_context(module->comp_data, &option); module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
if (!module->comp_ctx) { if (!module->comp_ctx) {
@ -3109,6 +3119,8 @@ init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf,
module->func_ptrs[i] = (void *)func_addr; module->func_ptrs[i] = (void *)func_addr;
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
if (module->orcjit_stop_compiling) if (module->orcjit_stop_compiling)
return false; return false;
#endif #endif
@ -3199,9 +3211,9 @@ orcjit_thread_callback(void *arg)
/* Wait until init_llvm_jit_functions_stage2 finishes */ /* Wait until init_llvm_jit_functions_stage2 finishes */
os_mutex_lock(&module->tierup_wait_lock); os_mutex_lock(&module->tierup_wait_lock);
while (!module->llvm_jit_inited) { while (!(module->llvm_jit_inited && module->enable_llvm_jit_compilation)) {
os_cond_reltimedwait(&module->tierup_wait_cond, os_cond_reltimedwait(&module->tierup_wait_cond,
&module->tierup_wait_lock, 10); &module->tierup_wait_lock, 10000);
if (module->orcjit_stop_compiling) { if (module->orcjit_stop_compiling) {
/* init_llvm_jit_functions_stage2 failed */ /* init_llvm_jit_functions_stage2 failed */
os_mutex_unlock(&module->tierup_wait_lock); os_mutex_unlock(&module->tierup_wait_lock);
@ -3852,8 +3864,8 @@ create_module(char *error_buf, uint32 error_buf_size)
bh_assert(ret == BH_LIST_SUCCESS); bh_assert(ret == BH_LIST_SUCCESS);
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \ #if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0) && WASM_ENABLE_LAZY_JIT != 0)
if (os_mutex_init(&module->instance_list_lock) != 0) { if (os_mutex_init(&module->instance_list_lock) != 0) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
@ -4148,10 +4160,8 @@ check_wasi_abi_compatibility(const WASMModule *module,
/* should have one at least */ /* should have one at least */
if (module->import_wasi_api && !start && !initialize) { if (module->import_wasi_api && !start && !initialize) {
set_error_buf( LOG_WARNING("warning: a module with WASI apis should be either "
error_buf, error_buf_size, "a command or a reactor");
"a module with WASI apis must be either a command or a reactor");
return false;
} }
/* /*
@ -4185,7 +4195,20 @@ check_wasi_abi_compatibility(const WASMModule *module,
memory = wasm_loader_find_export(module, "", "memory", EXPORT_KIND_MEMORY, memory = wasm_loader_find_export(module, "", "memory", EXPORT_KIND_MEMORY,
error_buf, error_buf_size); error_buf, error_buf_size);
if (!memory) { if (!memory
#if WASM_ENABLE_LIB_WASI_THREADS != 0
/*
* with wasi-threads, it's still an open question if a memory
* should be exported.
*
* https://github.com/WebAssembly/wasi-threads/issues/22
* https://github.com/WebAssembly/WASI/issues/502
*
* Note: this code assumes the number of memories is at most 1.
*/
&& module->import_memory_count == 0
#endif
) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"a module with WASI apis must export memory by default"); "a module with WASI apis must export memory by default");
return false; return false;
@ -4243,7 +4266,8 @@ wasm_loader_unload(WASMModule *module)
if (!module) if (!module)
return; return;
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
module->orcjit_stop_compiling = true; module->orcjit_stop_compiling = true;
if (module->llvm_jit_init_thread) if (module->llvm_jit_init_thread)
os_thread_join(module->llvm_jit_init_thread, NULL); os_thread_join(module->llvm_jit_init_thread, NULL);
@ -4264,7 +4288,8 @@ wasm_loader_unload(WASMModule *module)
aot_destroy_comp_data(module->comp_data); aot_destroy_comp_data(module->comp_data);
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
if (module->tierup_wait_lock_inited) { if (module->tierup_wait_lock_inited) {
os_mutex_destroy(&module->tierup_wait_lock); os_mutex_destroy(&module->tierup_wait_lock);
os_cond_destroy(&module->tierup_wait_cond); os_cond_destroy(&module->tierup_wait_cond);
@ -4299,9 +4324,9 @@ wasm_loader_unload(WASMModule *module)
module->functions[i]->fast_jit_jitted_code); module->functions[i]->fast_jit_jitted_code);
} }
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
if (module->functions[i]->llvm_jit_func_ptr) { if (module->functions[i]->call_to_fast_jit_from_llvm_jit) {
jit_code_cache_free( jit_code_cache_free(
module->functions[i]->llvm_jit_func_ptr); module->functions[i]->call_to_fast_jit_from_llvm_jit);
} }
#endif #endif
#endif #endif
@ -4393,8 +4418,8 @@ wasm_loader_unload(WASMModule *module)
} }
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \ #if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0) && WASM_ENABLE_LAZY_JIT != 0)
os_mutex_destroy(&module->instance_list_lock); os_mutex_destroy(&module->instance_list_lock);
#endif #endif

View File

@ -1835,6 +1835,7 @@ static bool
init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf, init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
uint32 error_buf_size) uint32 error_buf_size)
{ {
LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
AOTCompOption option = { 0 }; AOTCompOption option = { 0 };
char *aot_last_error; char *aot_last_error;
uint64 size; uint64 size;
@ -1873,8 +1874,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
} }
option.is_jit_mode = true; option.is_jit_mode = true;
option.opt_level = 3; option.opt_level = llvm_jit_options.opt_level;
option.size_level = 3; option.size_level = llvm_jit_options.size_level;
#if WASM_ENABLE_BULK_MEMORY != 0 #if WASM_ENABLE_BULK_MEMORY != 0
option.enable_bulk_memory = true; option.enable_bulk_memory = true;
#endif #endif
@ -1894,6 +1896,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0) #if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
option.enable_aux_stack_frame = true; option.enable_aux_stack_frame = true;
#endif #endif
#if WASM_ENABLE_MEMORY_PROFILING != 0
option.enable_stack_estimation = true;
#endif
module->comp_ctx = aot_create_comp_context(module->comp_data, &option); module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
if (!module->comp_ctx) { if (!module->comp_ctx) {
@ -1957,6 +1962,8 @@ init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf,
module->func_ptrs[i] = (void *)func_addr; module->func_ptrs[i] = (void *)func_addr;
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
if (module->orcjit_stop_compiling) if (module->orcjit_stop_compiling)
return false; return false;
#endif #endif
@ -2047,9 +2054,9 @@ orcjit_thread_callback(void *arg)
/* Wait until init_llvm_jit_functions_stage2 finishes */ /* Wait until init_llvm_jit_functions_stage2 finishes */
os_mutex_lock(&module->tierup_wait_lock); os_mutex_lock(&module->tierup_wait_lock);
while (!module->llvm_jit_inited) { while (!(module->llvm_jit_inited && module->enable_llvm_jit_compilation)) {
os_cond_reltimedwait(&module->tierup_wait_cond, os_cond_reltimedwait(&module->tierup_wait_cond,
&module->tierup_wait_lock, 10); &module->tierup_wait_lock, 10000);
if (module->orcjit_stop_compiling) { if (module->orcjit_stop_compiling) {
/* init_llvm_jit_functions_stage2 failed */ /* init_llvm_jit_functions_stage2 failed */
os_mutex_unlock(&module->tierup_wait_lock); os_mutex_unlock(&module->tierup_wait_lock);
@ -2718,7 +2725,8 @@ create_module(char *error_buf, uint32 error_buf_size)
bh_assert(ret == BH_LIST_SUCCESS); bh_assert(ret == BH_LIST_SUCCESS);
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
if (os_mutex_init(&module->instance_list_lock) != 0) { if (os_mutex_init(&module->instance_list_lock) != 0) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"init instance list lock failed"); "init instance list lock failed");
@ -2939,7 +2947,8 @@ wasm_loader_unload(WASMModule *module)
if (!module) if (!module)
return; return;
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
module->orcjit_stop_compiling = true; module->orcjit_stop_compiling = true;
if (module->llvm_jit_init_thread) if (module->llvm_jit_init_thread)
os_thread_join(module->llvm_jit_init_thread, NULL); os_thread_join(module->llvm_jit_init_thread, NULL);
@ -2960,7 +2969,8 @@ wasm_loader_unload(WASMModule *module)
aot_destroy_comp_data(module->comp_data); aot_destroy_comp_data(module->comp_data);
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
if (module->tierup_wait_lock_inited) { if (module->tierup_wait_lock_inited) {
os_mutex_destroy(&module->tierup_wait_lock); os_mutex_destroy(&module->tierup_wait_lock);
os_cond_destroy(&module->tierup_wait_cond); os_cond_destroy(&module->tierup_wait_cond);
@ -2995,9 +3005,9 @@ wasm_loader_unload(WASMModule *module)
module->functions[i]->fast_jit_jitted_code); module->functions[i]->fast_jit_jitted_code);
} }
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
if (module->functions[i]->llvm_jit_func_ptr) { if (module->functions[i]->call_to_fast_jit_from_llvm_jit) {
jit_code_cache_free( jit_code_cache_free(
module->functions[i]->llvm_jit_func_ptr); module->functions[i]->call_to_fast_jit_from_llvm_jit);
} }
#endif #endif
#endif #endif
@ -3056,7 +3066,8 @@ wasm_loader_unload(WASMModule *module)
} }
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
os_mutex_destroy(&module->instance_list_lock); os_mutex_destroy(&module->instance_list_lock);
#endif #endif

View File

@ -677,12 +677,14 @@ typedef enum WASMAtomicEXTOpcode {
} WASMAtomicEXTOpcode; } WASMAtomicEXTOpcode;
#if WASM_ENABLE_DEBUG_INTERP != 0 #if WASM_ENABLE_DEBUG_INTERP != 0
#define DEF_DEBUG_BREAK_HANDLE(_name) \ #define DEF_DEBUG_BREAK_HANDLE() \
_name[DEBUG_OP_BREAK] = HANDLE_OPCODE(DEBUG_OP_BREAK); /* 0xd7 */ [DEBUG_OP_BREAK] = HANDLE_OPCODE(DEBUG_OP_BREAK), /* 0xd7 */
#else #else
#define DEF_DEBUG_BREAK_HANDLE(_name) #define DEF_DEBUG_BREAK_HANDLE()
#endif #endif
#define SET_GOTO_TABLE_ELEM(opcode) [opcode] = HANDLE_OPCODE(opcode)
/* /*
* Macro used to generate computed goto tables for the C interpreter. * Macro used to generate computed goto tables for the C interpreter.
*/ */
@ -905,14 +907,10 @@ typedef enum WASMAtomicEXTOpcode {
HANDLE_OPCODE(EXT_OP_LOOP), /* 0xd4 */ \ HANDLE_OPCODE(EXT_OP_LOOP), /* 0xd4 */ \
HANDLE_OPCODE(EXT_OP_IF), /* 0xd5 */ \ HANDLE_OPCODE(EXT_OP_IF), /* 0xd5 */ \
HANDLE_OPCODE(EXT_OP_BR_TABLE_CACHE), /* 0xd6 */ \ HANDLE_OPCODE(EXT_OP_BR_TABLE_CACHE), /* 0xd6 */ \
}; \ SET_GOTO_TABLE_ELEM(WASM_OP_MISC_PREFIX), /* 0xfc */ \
do { \ SET_GOTO_TABLE_ELEM(WASM_OP_ATOMIC_PREFIX), /* 0xfe */ \
_name[WASM_OP_MISC_PREFIX] = \ DEF_DEBUG_BREAK_HANDLE() \
HANDLE_OPCODE(WASM_OP_MISC_PREFIX); /* 0xfc */ \ };
_name[WASM_OP_ATOMIC_PREFIX] = \
HANDLE_OPCODE(WASM_OP_ATOMIC_PREFIX); /* 0xfe */ \
DEF_DEBUG_BREAK_HANDLE(_name) \
} while (0)
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -737,13 +737,12 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
function++; function++;
} }
bh_assert((uint32)(function - functions) == function_count);
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs; module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs;
#endif #endif
bh_assert((uint32)(function - functions) == function_count);
(void)module_inst;
return functions; return functions;
} }
@ -983,88 +982,138 @@ export_globals_instantiate(const WASMModule *module,
} }
#endif #endif
#if WASM_ENABLE_LIBC_WASI != 0 static WASMFunctionInstance *
static bool lookup_post_instantiate_func(WASMModuleInstance *module_inst,
execute_initialize_function(WASMModuleInstance *module_inst) const char *func_name)
{ {
WASMFunctionInstance *initialize = WASMFunctionInstance *func;
wasm_lookup_function(module_inst, "_initialize", NULL); WASMType *func_type;
return !initialize
|| wasm_create_exec_env_and_call_function(module_inst, initialize, 0, if (!(func = wasm_lookup_function(module_inst, func_name, NULL)))
NULL); /* Not found */
return NULL;
func_type = func->u.func->func_type;
if (!(func_type->param_count == 0 && func_type->result_count == 0))
/* Not a valid function type, ignore it */
return NULL;
return func;
} }
static bool
execute_post_instantiate_functions(WASMModuleInstance *module_inst,
bool is_sub_inst)
{
WASMFunctionInstance *start_func = module_inst->e->start_function;
WASMFunctionInstance *initialize_func = NULL;
WASMFunctionInstance *post_inst_func = NULL;
WASMFunctionInstance *call_ctors_func = NULL;
#if WASM_ENABLE_LIBC_WASI != 0
WASMModule *module = module_inst->module;
#endif
#ifdef OS_ENABLE_HW_BOUND_CHECK
WASMModuleInstanceCommon *module_inst_main = NULL;
WASMExecEnv *exec_env_tls = NULL;
#endif
WASMExecEnv *exec_env = NULL;
bool ret = false;
#if WASM_ENABLE_LIBC_WASI != 0
/*
* WASI reactor instances may assume that _initialize will be called by
* the environment at most once, and that none of their other exports
* are accessed before that call.
*/
if (!is_sub_inst && module->import_wasi_api) {
initialize_func =
lookup_post_instantiate_func(module_inst, "_initialize");
}
#endif #endif
static bool /* Execute possible "__post_instantiate" function if wasm app is
execute_post_inst_function(WASMModuleInstance *module_inst) compiled by emsdk's early version */
{ if (!is_sub_inst) {
WASMFunctionInstance *post_inst_func = NULL; post_inst_func =
WASMType *post_inst_func_type; lookup_post_instantiate_func(module_inst, "__post_instantiate");
uint32 i; }
for (i = 0; i < module_inst->export_func_count; i++)
if (!strcmp(module_inst->export_functions[i].name,
"__post_instantiate")) {
post_inst_func = module_inst->export_functions[i].function;
break;
}
if (!post_inst_func)
/* Not found */
return true;
post_inst_func_type = post_inst_func->u.func->func_type;
if (post_inst_func_type->param_count != 0
|| post_inst_func_type->result_count != 0)
/* Not a valid function type, ignore it */
return true;
return wasm_create_exec_env_and_call_function(module_inst, post_inst_func,
0, NULL);
}
#if WASM_ENABLE_BULK_MEMORY != 0 #if WASM_ENABLE_BULK_MEMORY != 0
static bool /* Only execute the memory init function for main instance since
execute_memory_init_function(WASMModuleInstance *module_inst) the data segments will be dropped once initialized */
{ if (!is_sub_inst
WASMFunctionInstance *memory_init_func = NULL; #if WASM_ENABLE_LIBC_WASI != 0
WASMType *memory_init_func_type; && !module->import_wasi_api
uint32 i; #endif
) {
for (i = 0; i < module_inst->export_func_count; i++) call_ctors_func =
if (!strcmp(module_inst->export_functions[i].name, lookup_post_instantiate_func(module_inst, "__wasm_call_ctors");
"__wasm_call_ctors")) { }
memory_init_func = module_inst->export_functions[i].function;
break;
}
if (!memory_init_func)
/* Not found */
return true;
memory_init_func_type = memory_init_func->u.func->func_type;
if (memory_init_func_type->param_count != 0
|| memory_init_func_type->result_count != 0)
/* Not a valid function type, ignore it */
return true;
return wasm_create_exec_env_and_call_function(module_inst, memory_init_func,
0, NULL);
}
#endif #endif
static bool if (!start_func && !initialize_func && !post_inst_func
execute_start_function(WASMModuleInstance *module_inst) && !call_ctors_func) {
{ /* No post instantiation functions to call */
WASMFunctionInstance *func = module_inst->e->start_function;
if (!func)
return true; return true;
}
bh_assert(!func->is_import_func && func->param_cell_num == 0 #ifdef OS_ENABLE_HW_BOUND_CHECK
&& func->ret_cell_num == 0); if (is_sub_inst) {
exec_env = exec_env_tls = wasm_runtime_get_exec_env_tls();
if (exec_env_tls) {
/* Temporarily replace exec_env_tls's module inst to current
module inst to avoid checking failure when calling the
wasm functions, and ensure that the exec_env's module inst
is the correct one. */
module_inst_main = exec_env_tls->module_inst;
exec_env_tls->module_inst = (WASMModuleInstanceCommon *)module_inst;
}
}
#endif
if (!exec_env
&& !(exec_env =
wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
module_inst->default_wasm_stack_size))) {
wasm_set_exception(module_inst, "allocate memory failed");
return false;
}
return wasm_create_exec_env_and_call_function(module_inst, func, 0, NULL); /* Execute start function for both main insance and sub instance */
if (start_func && !wasm_call_function(exec_env, start_func, 0, NULL)) {
goto fail;
}
if (initialize_func
&& !wasm_call_function(exec_env, initialize_func, 0, NULL)) {
goto fail;
}
if (post_inst_func
&& !wasm_call_function(exec_env, post_inst_func, 0, NULL)) {
goto fail;
}
if (call_ctors_func
&& !wasm_call_function(exec_env, call_ctors_func, 0, NULL)) {
goto fail;
}
ret = true;
fail:
#ifdef OS_ENABLE_HW_BOUND_CHECK
if (is_sub_inst && exec_env_tls) {
bh_assert(exec_env == exec_env_tls);
/* Restore the exec_env_tls's module inst */
exec_env_tls->module_inst = module_inst_main;
}
else
wasm_exec_env_destroy(exec_env);
#else
wasm_exec_env_destroy(exec_env);
#endif
return ret;
} }
static bool static bool
@ -1235,6 +1284,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
#if WASM_ENABLE_WAMR_COMPILER == 0 #if WASM_ENABLE_WAMR_COMPILER == 0
LOG_WARNING("warning: failed to link import function (%s, %s)", LOG_WARNING("warning: failed to link import function (%s, %s)",
func->module_name, func->field_name); func->module_name, func->field_name);
/* will throw exception only if calling */
#else #else
/* do nothing to avoid confused message */ /* do nothing to avoid confused message */
#endif /* WASM_ENABLE_WAMR_COMPILER == 0 */ #endif /* WASM_ENABLE_WAMR_COMPILER == 0 */
@ -1250,8 +1300,10 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
return false; return false;
#else #else
#if WASM_ENABLE_WAMR_COMPILER == 0 #if WASM_ENABLE_WAMR_COMPILER == 0
LOG_DEBUG("warning: failed to link import global (%s, %s)", set_error_buf_v(error_buf, error_buf_size,
global->module_name, global->field_name); "failed to link import global (%s, %s)",
global->module_name, global->field_name);
return false;
#else #else
/* do nothing to avoid confused message */ /* do nothing to avoid confused message */
#endif /* WASM_ENABLE_WAMR_COMPILER == 0 */ #endif /* WASM_ENABLE_WAMR_COMPILER == 0 */
@ -1285,9 +1337,8 @@ init_func_ptrs(WASMModuleInstance *module_inst, WASMModule *module,
*func_ptrs = import_func->func_ptr_linked; *func_ptrs = import_func->func_ptr_linked;
} }
/* Set defined function pointers */ /* The defined function pointers will be set in
bh_memcpy_s(func_ptrs, sizeof(void *) * module->function_count, wasm_runtime_set_running_mode, no need to set them here */
module->func_ptrs, sizeof(void *) * module->function_count);
return true; return true;
} }
#endif /* end of WASM_ENABLE_JIT != 0 */ #endif /* end of WASM_ENABLE_JIT != 0 */
@ -1333,6 +1384,173 @@ init_func_type_indexes(WASMModuleInstance *module_inst, char *error_buf,
} }
#endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */ #endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */
static bool
set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode,
bool first_time_set)
{
WASMModule *module = module_inst->module;
if (running_mode == Mode_Default) {
#if WASM_ENABLE_FAST_JIT == 0 && WASM_ENABLE_JIT == 0
running_mode = Mode_Interp;
#elif WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT == 0
running_mode = Mode_Fast_JIT;
#elif WASM_ENABLE_FAST_JIT == 0 && WASM_ENABLE_JIT != 0
running_mode = Mode_LLVM_JIT;
#else /* WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 */
#if WASM_ENABLE_LAZY_JIT == 0
running_mode = Mode_LLVM_JIT;
#else
running_mode = Mode_Multi_Tier_JIT;
#endif
#endif
}
if (!wasm_runtime_is_running_mode_supported(running_mode))
return false;
#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0) /* No possible multi-tier JIT */
module_inst->e->running_mode = running_mode;
if (running_mode == Mode_Interp) {
/* Do nothing for Mode_Interp */
}
else if (running_mode == Mode_Fast_JIT) {
/* Do nothing for Mode_Fast_JIT since
module_inst->fast_jit_func_ptrs is same as
module->fast_jit_func_ptrs */
}
#if WASM_ENABLE_JIT != 0
else if (running_mode == Mode_LLVM_JIT) {
/* Set defined function pointers */
bh_memcpy_s(module_inst->func_ptrs + module->import_function_count,
sizeof(void *) * module->function_count, module->func_ptrs,
sizeof(void *) * module->function_count);
}
#endif
else {
bh_assert(0);
}
#else /* Possible multi-tier JIT */
os_mutex_lock(&module->instance_list_lock);
module_inst->e->running_mode = running_mode;
if (running_mode == Mode_Interp) {
/* Do nothing for Mode_Interp */
}
#if WASM_ENABLE_FAST_JIT != 0
else if (running_mode == Mode_Fast_JIT) {
JitGlobals *jit_globals = jit_compiler_get_jit_globals();
uint32 i;
/* Allocate memory for fast_jit_func_ptrs if needed */
if (!module_inst->fast_jit_func_ptrs
|| module_inst->fast_jit_func_ptrs == module->fast_jit_func_ptrs) {
uint64 total_size = (uint64)sizeof(void *) * module->function_count;
if (!(module_inst->fast_jit_func_ptrs =
runtime_malloc(total_size, NULL, 0))) {
os_mutex_unlock(&module->instance_list_lock);
return false;
}
}
for (i = 0; i < module->function_count; i++) {
if (module->functions[i]->fast_jit_jitted_code) {
/* current fast jit function has been compiled */
module_inst->fast_jit_func_ptrs[i] =
module->functions[i]->fast_jit_jitted_code;
}
else {
module_inst->fast_jit_func_ptrs[i] =
jit_globals->compile_fast_jit_and_then_call;
}
}
}
#endif
#if WASM_ENABLE_JIT != 0
else if (running_mode == Mode_LLVM_JIT) {
void **llvm_jit_func_ptrs;
uint32 i;
/* Notify backend threads to start llvm jit compilation */
module->enable_llvm_jit_compilation = true;
/* Wait until llvm jit finishes initialization */
os_mutex_lock(&module->tierup_wait_lock);
while (!module->llvm_jit_inited) {
os_cond_reltimedwait(&module->tierup_wait_cond,
&module->tierup_wait_lock, 10);
if (module->orcjit_stop_compiling) {
/* init_llvm_jit_functions_stage2 failed */
os_mutex_unlock(&module->tierup_wait_lock);
os_mutex_unlock(&module->instance_list_lock);
return false;
}
}
os_mutex_unlock(&module->tierup_wait_lock);
llvm_jit_func_ptrs =
module_inst->func_ptrs + module->import_function_count;
for (i = 0; i < module->function_count; i++) {
llvm_jit_func_ptrs[i] = module->functions[i]->llvm_jit_func_ptr;
}
}
#endif
else if (running_mode == Mode_Multi_Tier_JIT) {
/* Notify backend threads to start llvm jit compilation */
module->enable_llvm_jit_compilation = true;
/* Free fast_jit_func_ptrs if it is allocated before */
if (module_inst->fast_jit_func_ptrs
&& module_inst->fast_jit_func_ptrs != module->fast_jit_func_ptrs) {
wasm_runtime_free(module_inst->fast_jit_func_ptrs);
}
module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs;
/* Copy all llvm jit func ptrs from the module */
bh_memcpy_s(module_inst->func_ptrs + module->import_function_count,
sizeof(void *) * module->function_count, module->func_ptrs,
sizeof(void *) * module->function_count);
}
else {
bh_assert(0);
}
/* Add module instance into module's instance list if not added */
if (first_time_set) {
bool found = false;
WASMModuleInstance *node = module->instance_list;
while (node) {
if (node == module_inst) {
found = true;
break;
}
node = node->e->next;
}
if (!found) {
module_inst->e->next = module->instance_list;
module->instance_list = module_inst;
}
}
os_mutex_unlock(&module->instance_list_lock);
#endif /* end of !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0) */
(void)module;
return true;
}
bool
wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode)
{
return set_running_mode(module_inst, running_mode, false);
}
/** /**
* Instantiate module * Instantiate module
*/ */
@ -1419,15 +1637,6 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
module_inst->e = module_inst->e =
(WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset); (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset);
#if WASM_ENABLE_SHARED_MEMORY != 0
if (os_mutex_init(&module_inst->e->mem_lock) != 0) {
set_error_buf(error_buf, error_buf_size,
"create shared memory lock failed");
goto fail;
}
module_inst->e->mem_lock_inited = true;
#endif
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
module_inst->e->sub_module_inst_list = module_inst->e->sub_module_inst_list =
&module_inst->e->sub_module_inst_list_head; &module_inst->e->sub_module_inst_list_head;
@ -1800,33 +2009,39 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
} }
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \ #if WASM_ENABLE_WASI_NN != 0
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \ if (!is_sub_inst) {
&& WASM_ENABLE_LAZY_JIT != 0) if (!(module_inst->e->wasi_nn_ctx = wasi_nn_initialize())) {
set_error_buf(error_buf, error_buf_size,
"wasi nn initialization failed");
goto fail;
}
}
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
if (!is_sub_inst) { if (!is_sub_inst) {
/* Add module instance into module's instance list */ /* Add module instance into module's instance list */
os_mutex_lock(&module->instance_list_lock); os_mutex_lock(&module->instance_list_lock);
#if WASM_ENABLE_DEBUG_INTERP != 0
if (module->instance_list) { if (module->instance_list) {
LOG_WARNING( LOG_WARNING(
"warning: multiple instances referencing to the same module " "warning: multiple instances referencing to the same module "
"may cause unexpected behaviour during debugging"); "may cause unexpected behaviour during debugging");
} }
#endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
/* Copy llvm func ptrs again in case that they were updated
after the module instance was created */
bh_memcpy_s(module_inst->func_ptrs + module->import_function_count,
sizeof(void *) * module->function_count, module->func_ptrs,
sizeof(void *) * module->function_count);
#endif
module_inst->e->next = module->instance_list; module_inst->e->next = module->instance_list;
module->instance_list = module_inst; module->instance_list = module_inst;
os_mutex_unlock(&module->instance_list_lock); os_mutex_unlock(&module->instance_list_lock);
} }
#endif #endif
/* Set running mode before executing wasm functions */
if (!set_running_mode(module_inst, wasm_runtime_get_default_running_mode(),
true)) {
set_error_buf(error_buf, error_buf_size,
"set instance running mode failed");
goto fail;
}
if (module->start_function != (uint32)-1) { if (module->start_function != (uint32)-1) {
/* TODO: fix start function can be import function issue */ /* TODO: fix start function can be import function issue */
if (module->start_function >= module->import_function_count) if (module->start_function >= module->import_function_count)
@ -1834,45 +2049,11 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
&module_inst->e->functions[module->start_function]; &module_inst->e->functions[module->start_function];
} }
if ( if (!execute_post_instantiate_functions(module_inst, is_sub_inst)) {
#if WASM_ENABLE_LIBC_WASI != 0
/*
* reactor instances may assume that _initialize will be called by
* the environment at most once, and that none of their other
* exports are accessed before that call.
*
* let the loader decide how to act if there is no _initialize
* in a reactor
*/
!execute_initialize_function(module_inst) ||
#endif
/* Execute __post_instantiate function */
!execute_post_inst_function(module_inst)
/* Execute the function in "start" section */
|| !execute_start_function(module_inst)) {
set_error_buf(error_buf, error_buf_size, module_inst->cur_exception); set_error_buf(error_buf, error_buf_size, module_inst->cur_exception);
goto fail; goto fail;
} }
#if WASM_ENABLE_BULK_MEMORY != 0
#if WASM_ENABLE_LIBC_WASI != 0
if (!module->import_wasi_api) {
#endif
/* Only execute the memory init function for main instance because
the data segments will be dropped once initialized.
*/
if (!is_sub_inst) {
if (!execute_memory_init_function(module_inst)) {
set_error_buf(error_buf, error_buf_size,
module_inst->cur_exception);
goto fail;
}
}
#if WASM_ENABLE_LIBC_WASI != 0
}
#endif
#endif
#if WASM_ENABLE_MEMORY_TRACING != 0 #if WASM_ENABLE_MEMORY_TRACING != 0
wasm_runtime_dump_module_inst_mem_consumption( wasm_runtime_dump_module_inst_mem_consumption(
(WASMModuleInstanceCommon *)module_inst); (WASMModuleInstanceCommon *)module_inst);
@ -1892,11 +2073,57 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
if (!module_inst) if (!module_inst)
return; return;
if (module_inst->exec_env_singleton) {
/* wasm_exec_env_destroy will call
wasm_cluster_wait_for_all_except_self to wait for other
threads, so as to destroy their exec_envs and module
instances first, and avoid accessing the shared resources
of current module instance after it is deinstantiated. */
wasm_exec_env_destroy(module_inst->exec_env_singleton);
}
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0)
/* Remove instance from module's instance list before freeing
func_ptrs and fast_jit_func_ptrs of the instance, to avoid
accessing the freed memory in the jit backend compilation
threads */
if (!is_sub_inst) {
WASMModule *module = module_inst->module;
WASMModuleInstance *instance_prev = NULL, *instance;
os_mutex_lock(&module->instance_list_lock);
instance = module->instance_list;
while (instance) {
if (instance == module_inst) {
if (!instance_prev)
module->instance_list = instance->e->next;
else
instance_prev->e->next = instance->e->next;
break;
}
instance_prev = instance;
instance = instance->e->next;
}
os_mutex_unlock(&module->instance_list_lock);
}
#endif
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_JIT != 0
if (module_inst->func_ptrs) if (module_inst->func_ptrs)
wasm_runtime_free(module_inst->func_ptrs); wasm_runtime_free(module_inst->func_ptrs);
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
if (module_inst->fast_jit_func_ptrs
&& module_inst->fast_jit_func_ptrs
!= module_inst->module->fast_jit_func_ptrs)
wasm_runtime_free(module_inst->fast_jit_func_ptrs);
#endif
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
if (module_inst->func_type_indexes) if (module_inst->func_type_indexes)
wasm_runtime_free(module_inst->func_type_indexes); wasm_runtime_free(module_inst->func_type_indexes);
@ -1937,9 +2164,6 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
wasm_externref_cleanup((WASMModuleInstanceCommon *)module_inst); wasm_externref_cleanup((WASMModuleInstanceCommon *)module_inst);
#endif #endif
if (module_inst->exec_env_singleton)
wasm_exec_env_destroy(module_inst->exec_env_singleton);
#if WASM_ENABLE_DUMP_CALL_STACK != 0 #if WASM_ENABLE_DUMP_CALL_STACK != 0
if (module_inst->frames) { if (module_inst->frames) {
bh_vector_destroy(module_inst->frames); bh_vector_destroy(module_inst->frames);
@ -1948,39 +2172,17 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
} }
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0)
if (!is_sub_inst) {
WASMModule *module = module_inst->module;
WASMModuleInstance *instance_prev = NULL, *instance;
os_mutex_lock(&module->instance_list_lock);
instance = module->instance_list;
while (instance) {
if (instance == module_inst) {
if (!instance_prev)
module->instance_list = instance->e->next;
else
instance_prev->e->next = instance->e->next;
break;
}
instance_prev = instance;
instance = instance->e->next;
}
os_mutex_unlock(&module->instance_list_lock);
}
#endif
#if WASM_ENABLE_SHARED_MEMORY != 0
if (module_inst->e->mem_lock_inited)
os_mutex_destroy(&module_inst->e->mem_lock);
#endif
if (module_inst->e->c_api_func_imports) if (module_inst->e->c_api_func_imports)
wasm_runtime_free(module_inst->e->c_api_func_imports); wasm_runtime_free(module_inst->e->c_api_func_imports);
#if WASM_ENABLE_WASI_NN != 0
if (!is_sub_inst) {
WASINNContext *wasi_nn_ctx = module_inst->e->wasi_nn_ctx;
if (wasi_nn_ctx)
wasi_nn_destroy(wasi_nn_ctx);
}
#endif
wasm_runtime_free(module_inst); wasm_runtime_free(module_inst);
} }
@ -2030,24 +2232,6 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name)
} }
#endif #endif
static bool
clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst)
{
#if WASM_ENABLE_LIBC_WASI != 0
const char *exception = wasm_get_exception(module_inst);
if (exception && !strcmp(exception, "Exception: wasi proc exit")) {
/* The "wasi proc exit" exception is thrown by native lib to
let wasm app exit, which is a normal behavior, we clear
the exception here. */
wasm_set_exception(module_inst, NULL);
return true;
}
return false;
#else
return false;
#endif
}
#ifdef OS_ENABLE_HW_BOUND_CHECK #ifdef OS_ENABLE_HW_BOUND_CHECK
static void static void
@ -2063,14 +2247,16 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env); WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env);
uint8 *prev_top = exec_env->wasm_stack.s.top; uint8 *prev_top = exec_env->wasm_stack.s.top;
#ifdef BH_PLATFORM_WINDOWS #ifdef BH_PLATFORM_WINDOWS
const char *exce;
int result; int result;
bool has_exception;
char exception[EXCEPTION_BUF_LEN];
#endif #endif
bool ret = true; bool ret = true;
/* Check native stack overflow firstly to ensure we have enough /* Check native stack overflow firstly to ensure we have enough
native stack to run the following codes before actually calling native stack to run the following codes before actually calling
the aot function in invokeNative function. */ the aot function in invokeNative function. */
RECORD_STACK_USAGE(exec_env, (uint8 *)&exec_env_tls);
if ((uint8 *)&exec_env_tls < exec_env->native_stack_boundary if ((uint8 *)&exec_env_tls < exec_env->native_stack_boundary
+ page_size * (guard_page_count + 1)) { + page_size * (guard_page_count + 1)) {
wasm_set_exception(module_inst, "native stack overflow"); wasm_set_exception(module_inst, "native stack overflow");
@ -2096,14 +2282,14 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
#else #else
__try { __try {
wasm_interp_call_wasm(module_inst, exec_env, function, argc, argv); wasm_interp_call_wasm(module_inst, exec_env, function, argc, argv);
} __except (wasm_get_exception(module_inst) } __except (wasm_copy_exception(module_inst, NULL)
? EXCEPTION_EXECUTE_HANDLER ? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH) { : EXCEPTION_CONTINUE_SEARCH) {
/* exception was thrown in wasm_exception_handler */ /* exception was thrown in wasm_exception_handler */
ret = false; ret = false;
} }
if ((exce = wasm_get_exception(module_inst)) has_exception = wasm_copy_exception(module_inst, exception);
&& strstr(exce, "native stack overflow")) { if (has_exception && strstr(exception, "native stack overflow")) {
/* After a stack overflow, the stack was left /* After a stack overflow, the stack was left
in a damaged state, let the CRT repair it */ in a damaged state, let the CRT repair it */
result = _resetstkoflw(); result = _resetstkoflw();
@ -2157,8 +2343,7 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
wasm_exec_env_set_thread_info(exec_env); wasm_exec_env_set_thread_info(exec_env);
interp_call_wasm(module_inst, exec_env, function, argc, argv); interp_call_wasm(module_inst, exec_env, function, argc, argv);
(void)clear_wasi_proc_exit_exception(module_inst); return !wasm_copy_exception(module_inst, NULL);
return !wasm_get_exception(module_inst) ? true : false;
} }
bool bool
@ -2185,7 +2370,7 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
} }
} }
ret = wasm_call_function(exec_env, func, argc, argv); ret = wasm_runtime_call_wasm(exec_env, func, argc, argv);
/* don't destroy the exec_env if it isn't created in this function */ /* don't destroy the exec_env if it isn't created in this function */
if (!existing_exec_env) if (!existing_exec_env)
@ -2331,6 +2516,12 @@ wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr)
return; return;
} }
#if WASM_ENABLE_SHARED_MEMORY != 0
WASMSharedMemNode *node = wasm_module_get_shared_memory(
(WASMModuleCommon *)module_inst->module);
if (node)
os_mutex_lock(&node->shared_mem_lock);
#endif
addr = memory->memory_data + ptr; addr = memory->memory_data + ptr;
if (memory->heap_handle && memory->heap_data <= addr if (memory->heap_handle && memory->heap_data <= addr
@ -2343,6 +2534,10 @@ wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr)
execute_free_function(module_inst, module_inst->e->free_function, execute_free_function(module_inst, module_inst->e->free_function,
ptr); ptr);
} }
#if WASM_ENABLE_SHARED_MEMORY != 0
if (node)
os_mutex_unlock(&node->shared_mem_lock);
#endif
} }
} }
@ -2455,8 +2650,7 @@ call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
interp_call_wasm(module_inst, exec_env, func_inst, argc, argv); interp_call_wasm(module_inst, exec_env, func_inst, argc, argv);
(void)clear_wasi_proc_exit_exception(module_inst); return !wasm_copy_exception(module_inst, NULL);
return !wasm_get_exception(module_inst) ? true : false;
got_exception: got_exception:
return false; return false;
@ -2476,14 +2670,16 @@ wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size)
WASMModuleInstance *module_inst = WASMModuleInstance *module_inst =
(WASMModuleInstance *)exec_env->module_inst; (WASMModuleInstance *)exec_env->module_inst;
uint32 stack_top_idx = module_inst->module->aux_stack_top_global_index; uint32 stack_top_idx = module_inst->module->aux_stack_top_global_index;
#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
/* Check the aux stack space */
uint32 data_end = module_inst->module->aux_data_end; uint32 data_end = module_inst->module->aux_data_end;
uint32 stack_bottom = module_inst->module->aux_stack_bottom; uint32 stack_bottom = module_inst->module->aux_stack_bottom;
bool is_stack_before_data = stack_bottom < data_end ? true : false; bool is_stack_before_data = stack_bottom < data_end ? true : false;
/* Check the aux stack space, currently we don't allocate space in heap */
if ((is_stack_before_data && (size > start_offset)) if ((is_stack_before_data && (size > start_offset))
|| ((!is_stack_before_data) && (start_offset - data_end < size))) || ((!is_stack_before_data) && (start_offset - data_end < size)))
return false; return false;
#endif
if (stack_top_idx != (uint32)-1) { if (stack_top_idx != (uint32)-1) {
/* The aux stack top is a wasm global, /* The aux stack top is a wasm global,
@ -2905,8 +3101,14 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
import_func = &module->import_functions[func_idx].u.function; import_func = &module->import_functions[func_idx].u.function;
if (import_func->call_conv_wasm_c_api) { if (import_func->call_conv_wasm_c_api) {
c_api_func_import = module_inst->e->c_api_func_imports + func_idx; if (module_inst->e->c_api_func_imports) {
func_ptr = c_api_func_import->func_ptr_linked; c_api_func_import = module_inst->e->c_api_func_imports + func_idx;
func_ptr = c_api_func_import->func_ptr_linked;
}
else {
c_api_func_import = NULL;
func_ptr = NULL;
}
} }
if (!func_ptr) { if (!func_ptr) {

View File

@ -11,10 +11,16 @@
#include "../common/wasm_runtime_common.h" #include "../common/wasm_runtime_common.h"
#include "../common/wasm_exec_env.h" #include "../common/wasm_exec_env.h"
#if WASM_ENABLE_WASI_NN != 0
#include "../libraries/wasi-nn/src/wasi_nn_private.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define EXCEPTION_BUF_LEN 128
typedef struct WASMModuleInstance WASMModuleInstance; typedef struct WASMModuleInstance WASMModuleInstance;
typedef struct WASMFunctionInstance WASMFunctionInstance; typedef struct WASMFunctionInstance WASMFunctionInstance;
typedef struct WASMMemoryInstance WASMMemoryInstance; typedef struct WASMMemoryInstance WASMMemoryInstance;
@ -59,9 +65,7 @@ typedef enum WASMExceptionID {
EXCE_AUX_STACK_UNDERFLOW, EXCE_AUX_STACK_UNDERFLOW,
EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
EXCE_OPERAND_STACK_OVERFLOW, EXCE_OPERAND_STACK_OVERFLOW,
#if WASM_ENABLE_FAST_JIT != 0
EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC, EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC,
#endif
EXCE_ALREADY_THROWN, EXCE_ALREADY_THROWN,
EXCE_NUM, EXCE_NUM,
} WASMExceptionID; } WASMExceptionID;
@ -219,12 +223,7 @@ typedef struct WASMModuleInstanceExtra {
WASMFunctionInstance *retain_function; WASMFunctionInstance *retain_function;
CApiFuncImport *c_api_func_imports; CApiFuncImport *c_api_func_imports;
RunningMode running_mode;
#if WASM_ENABLE_SHARED_MEMORY != 0
/* lock for shared memory atomic operations */
korp_mutex mem_lock;
bool mem_lock_inited;
#endif
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
bh_list sub_module_inst_list_head; bh_list sub_module_inst_list_head;
@ -237,11 +236,15 @@ typedef struct WASMModuleInstanceExtra {
uint32 max_aux_stack_used; uint32 max_aux_stack_used;
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \ #if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \ || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0) && WASM_ENABLE_LAZY_JIT != 0)
WASMModuleInstance *next; WASMModuleInstance *next;
#endif #endif
#if WASM_ENABLE_WASI_NN != 0
WASINNContext *wasi_nn_ctx;
#endif
} WASMModuleInstanceExtra; } WASMModuleInstanceExtra;
struct AOTFuncPerfProfInfo; struct AOTFuncPerfProfInfo;
@ -281,7 +284,7 @@ struct WASMModuleInstance {
DefPointer(WASMExportTabInstance *, export_tables); DefPointer(WASMExportTabInstance *, export_tables);
/* The exception buffer of wasm interpreter for current thread. */ /* The exception buffer of wasm interpreter for current thread. */
char cur_exception[128]; char cur_exception[EXCEPTION_BUF_LEN];
/* The WASM module or AOT module, for AOTModuleInstance, /* The WASM module or AOT module, for AOTModuleInstance,
it denotes `AOTModule *` */ it denotes `AOTModule *` */
@ -298,7 +301,11 @@ struct WASMModuleInstance {
not available in AOTModuleInstance */ not available in AOTModuleInstance */
DefPointer(void **, import_func_ptrs); DefPointer(void **, import_func_ptrs);
/* Array of function pointers to fast jit functions, /* Array of function pointers to fast jit functions,
not available in AOTModuleInstance */ not available in AOTModuleInstance:
Only when the multi-tier JIT macros are all enabled and the running
mode of current module instance is set to Mode_Fast_JIT, runtime
will allocate new memory for it, otherwise it always points to the
module->fast_jit_func_ptrs */
DefPointer(void **, fast_jit_func_ptrs); DefPointer(void **, fast_jit_func_ptrs);
/* The custom data that can be set/get by wasm_{get|set}_custom_data */ /* The custom data that can be set/get by wasm_{get|set}_custom_data */
DefPointer(void *, custom_data); DefPointer(void *, custom_data);
@ -402,6 +409,10 @@ wasm_dump_perf_profiling(const WASMModuleInstance *module_inst);
void void
wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst); wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst);
bool
wasm_set_running_mode(WASMModuleInstance *module_inst,
RunningMode running_mode);
WASMFunctionInstance * WASMFunctionInstance *
wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name, wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name,
const char *signature); const char *signature);
@ -435,6 +446,15 @@ wasm_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id);
const char * const char *
wasm_get_exception(WASMModuleInstance *module); wasm_get_exception(WASMModuleInstance *module);
/**
* @brief Copy exception in buffer passed as parameter. Thread-safe version of
* `wasm_get_exception()`
* @note Buffer size must be no smaller than EXCEPTION_BUF_LEN
* @return true if exception found
*/
bool
wasm_copy_exception(WASMModuleInstance *module_inst, char *exception_buf);
uint32 uint32
wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size, wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size,
void **p_native_addr); void **p_native_addr);

View File

@ -46,10 +46,6 @@
wasm_runtime_addr_native_to_app(module_inst, ptr) wasm_runtime_addr_native_to_app(module_inst, ptr)
/* clang-format on */ /* clang-format on */
extern bool
wasm_runtime_call_indirect(wasm_exec_env_t exec_env, uint32 element_indices,
uint32 argc, uint32 argv[]);
enum { enum {
T_THREAD, T_THREAD,
T_MUTEX, T_MUTEX,
@ -494,7 +490,6 @@ pthread_start_routine(void *arg)
{ {
wasm_exec_env_t exec_env = (wasm_exec_env_t)arg; wasm_exec_env_t exec_env = (wasm_exec_env_t)arg;
wasm_exec_env_t parent_exec_env; wasm_exec_env_t parent_exec_env;
wasm_module_inst_t module_inst = get_module_inst(exec_env);
ThreadRoutineArgs *routine_args = exec_env->thread_arg; ThreadRoutineArgs *routine_args = exec_env->thread_arg;
ThreadInfoNode *info_node = routine_args->info_node; ThreadInfoNode *info_node = routine_args->info_node;
uint32 argv[1]; uint32 argv[1];
@ -504,7 +499,6 @@ pthread_start_routine(void *arg)
info_node->exec_env = exec_env; info_node->exec_env = exec_env;
info_node->u.thread = exec_env->handle; info_node->u.thread = exec_env->handle;
if (!append_thread_info_node(info_node)) { if (!append_thread_info_node(info_node)) {
wasm_runtime_deinstantiate_internal(module_inst, true);
delete_thread_info_node(info_node); delete_thread_info_node(info_node);
os_cond_signal(&parent_exec_env->wait_cond); os_cond_signal(&parent_exec_env->wait_cond);
os_mutex_unlock(&parent_exec_env->wait_lock); os_mutex_unlock(&parent_exec_env->wait_lock);
@ -520,16 +514,12 @@ pthread_start_routine(void *arg)
if (!wasm_runtime_call_indirect(exec_env, routine_args->elem_index, 1, if (!wasm_runtime_call_indirect(exec_env, routine_args->elem_index, 1,
argv)) { argv)) {
if (wasm_runtime_get_exception(module_inst)) /* Exception has already been spread during throwing */
wasm_cluster_spread_exception(exec_env);
} }
/* destroy pthread key values */ /* destroy pthread key values */
call_key_destructor(exec_env); call_key_destructor(exec_env);
/* routine exit, destroy instance */
wasm_runtime_deinstantiate_internal(module_inst, true);
wasm_runtime_free(routine_args); wasm_runtime_free(routine_args);
/* if the thread is joinable, store the result in its info node, /* if the thread is joinable, store the result in its info node,
@ -571,6 +561,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
#if WASM_ENABLE_LIBC_WASI != 0 #if WASM_ENABLE_LIBC_WASI != 0
WASIContext *wasi_ctx; WASIContext *wasi_ctx;
#endif #endif
CApiFuncImport **new_c_api_func_imports = NULL;
bh_assert(module); bh_assert(module);
bh_assert(module_inst); bh_assert(module_inst);
@ -603,6 +594,46 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx); wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
#endif #endif
/* workaround about passing instantiate-linking information */
{
CApiFuncImport *c_api_func_imports;
uint32 import_func_count = 0;
uint32 size_in_bytes = 0;
#if WASM_ENABLE_INTERP != 0
if (module_inst->module_type == Wasm_Module_Bytecode) {
new_c_api_func_imports = &(
((WASMModuleInstance *)new_module_inst)->e->c_api_func_imports);
c_api_func_imports =
((WASMModuleInstance *)module_inst)->e->c_api_func_imports;
import_func_count = ((WASMModule *)module)->import_function_count;
}
#endif
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
AOTModuleInstanceExtra *e =
(AOTModuleInstanceExtra *)((AOTModuleInstance *)new_module_inst)
->e;
new_c_api_func_imports = &(e->c_api_func_imports);
e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
c_api_func_imports = e->c_api_func_imports;
import_func_count = ((AOTModule *)module)->import_func_count;
}
#endif
if (import_func_count != 0 && c_api_func_imports) {
size_in_bytes = sizeof(CApiFuncImport *) * import_func_count;
*new_c_api_func_imports = wasm_runtime_malloc(size_in_bytes);
if (!(*new_c_api_func_imports))
goto fail;
bh_memcpy_s(*new_c_api_func_imports, size_in_bytes,
c_api_func_imports, size_in_bytes);
}
}
if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode)))) if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
goto fail; goto fail;
@ -623,8 +654,9 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
routine_args->module_inst = new_module_inst; routine_args->module_inst = new_module_inst;
os_mutex_lock(&exec_env->wait_lock); os_mutex_lock(&exec_env->wait_lock);
ret = wasm_cluster_create_thread( ret =
exec_env, new_module_inst, pthread_start_routine, (void *)routine_args); wasm_cluster_create_thread(exec_env, new_module_inst, true,
pthread_start_routine, (void *)routine_args);
if (ret != 0) { if (ret != 0) {
os_mutex_unlock(&exec_env->wait_lock); os_mutex_unlock(&exec_env->wait_lock);
goto fail; goto fail;

View File

@ -0,0 +1,27 @@
#!/bin/bash
# Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set -ueo pipefail
CC="${CC:=/opt/wasi-sdk/bin/clang}"
files=("tcp_udp.c" "nslookup.c")
WASI_SYSROOT=${WASI_SYSROOT:=~/dev/wasi-libc/sysroot}
for file in "${files[@]}"
do
echo $file
$CC \
--target=wasm32-wasi-threads \
-I../inc \
--sysroot $WASI_SYSROOT \
../src/wasi/wasi_socket_ext.c -pthread -ftls-model=local-exec \
-Wl,--allow-undefined \
-Wl,--strip-all,--no-entry \
-Wl,--export=__heap_base \
-Wl,--export=__data_end \
-Wl,--shared-memory,--max-memory=10485760 \
-Wl,--export=malloc \
-Wl,--export=free \
-o "${file%.*}.wasm" "$file"
done

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <assert.h>
#include <string.h>
#ifdef __wasi__
#include <wasi/api.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <wasi_socket_ext.h>
#else
#include <netdb.h>
#endif
void
test_nslookup(int af)
{
struct addrinfo *res;
int count = 0;
struct addrinfo hints;
char *url = "google-public-dns-a.google.com";
memset(&hints, 0, sizeof(hints));
hints.ai_family = af;
hints.ai_socktype = SOCK_STREAM;
int ret = getaddrinfo(url, 0, &hints, &res);
assert(ret == 0);
struct addrinfo *address = res;
while (address) {
assert(address->ai_family == af);
assert(address->ai_socktype == SOCK_STREAM);
count++;
address = address->ai_next;
}
assert(count > 0);
freeaddrinfo(res);
}
int
main()
{
test_nslookup(AF_INET); /* for ipv4 */
test_nslookup(AF_INET6); /* for ipv6 */
return 0;
}

View File

@ -0,0 +1,193 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <unistd.h>
#include <string.h>
#include <assert.h>
#ifdef __wasi__
#include <wasi/api.h>
#include <sys/socket.h>
#include <wasi_socket_ext.h>
#endif
#include <arpa/inet.h>
#include <pthread.h>
#define SERVER_MSG "Message from server."
#define PORT 8989
pthread_mutex_t mut;
pthread_cond_t cond;
int server_init_complete = 0;
char buffer[sizeof(SERVER_MSG) + 1];
struct socket_info {
union {
struct sockaddr_in addr_ipv4;
struct sockaddr_in6 addr_ipv6;
} addr;
int sock;
};
struct thread_args {
int family;
int protocol;
};
struct socket_info
init_socket_addr(int family, int protocol)
{
int sock = socket(family, protocol, 0);
assert(sock != -1);
struct socket_info info;
if (family == AF_INET) {
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
info.addr.addr_ipv4 = addr;
}
else if (family == AF_INET6) {
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(PORT);
addr.sin6_addr = in6addr_loopback;
info.addr.addr_ipv6 = addr;
}
info.sock = sock;
return info;
}
void
assert_thread_args(struct thread_args *args)
{
assert(args->family == AF_INET || args->family == AF_INET6);
assert(args->protocol == SOCK_STREAM || args->protocol == SOCK_DGRAM);
}
void *
server(void *arg)
{
server_init_complete = 0;
struct thread_args *args = (struct thread_args *)arg;
assert_thread_args(args);
struct socket_info init_server_sock =
init_socket_addr(args->family, args->protocol);
int server_sock = init_server_sock.sock;
socklen_t addr_size;
struct sockaddr_storage client_addr;
strcpy(buffer, SERVER_MSG);
struct sockaddr *server_addr = (struct sockaddr *)&init_server_sock.addr;
int ret = bind(server_sock, server_addr,
args->family == AF_INET ? sizeof(struct sockaddr_in)
: sizeof(struct sockaddr_in6));
assert(ret == 0);
(args->protocol == SOCK_STREAM) && listen(server_sock, 1);
pthread_mutex_lock(&mut);
server_init_complete = 1;
pthread_mutex_unlock(&mut);
pthread_cond_signal(&cond);
addr_size = sizeof(client_addr);
if (args->protocol == SOCK_STREAM) {
int client_sock =
accept(server_sock, (struct sockaddr *)&client_addr, &addr_size);
assert(client_sock >= 0);
sendto(client_sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&client_addr, addr_size);
assert(close(client_sock) == 0);
}
else {
recvfrom(server_sock, buffer, sizeof(buffer), 0,
(struct sockaddr *)&client_addr, &addr_size);
sendto(server_sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&client_addr, addr_size);
assert(close(server_sock) == 0);
}
return NULL;
}
void *
client(void *arg)
{
struct thread_args *args = (struct thread_args *)arg;
assert_thread_args(args);
pthread_mutex_lock(&mut);
while (server_init_complete == 0) {
pthread_cond_wait(&cond, &mut);
}
struct socket_info init_client_sock =
init_socket_addr(args->family, args->protocol);
int sock = init_client_sock.sock;
pthread_mutex_unlock(&mut);
if (args->family == AF_INET) {
struct sockaddr_in addr = init_client_sock.addr.addr_ipv4;
if (args->protocol == SOCK_STREAM) {
assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
}
else {
assert(sendto(sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&addr, sizeof(addr))
!= -1);
}
}
else {
struct sockaddr_in6 addr = init_client_sock.addr.addr_ipv6;
if (args->protocol == SOCK_STREAM) {
assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
}
else {
assert(sendto(sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&addr, sizeof(addr))
!= -1);
}
}
recv(sock, buffer, sizeof(buffer), 0);
assert(strcmp(buffer, SERVER_MSG) == 0);
assert(close(sock) == 0);
return NULL;
}
void
test_protocol(int family, int protocol)
{
pthread_t server_thread, client_thread;
assert(pthread_cond_init(&cond, NULL) == 0);
assert(pthread_mutex_init(&mut, NULL) == 0);
struct thread_args args = { family, protocol };
assert(pthread_create(&server_thread, NULL, server, (void *)&args) == 0);
assert(pthread_create(&client_thread, NULL, client, (void *)&args) == 0);
assert(pthread_join(server_thread, NULL) == 0);
assert(pthread_join(client_thread, NULL) == 0);
assert(pthread_mutex_destroy(&mut) == 0);
assert(pthread_cond_destroy(&cond) == 0);
}
int
main(int argc, char **argv)
{
/* test tcp with ipv4 and ipv6 */
test_protocol(AF_INET, SOCK_STREAM);
test_protocol(AF_INET6, SOCK_STREAM);
/* test udp with ipv4 and ipv6 */
test_protocol(AF_INET, SOCK_DGRAM);
test_protocol(AF_INET6, SOCK_DGRAM);
return 0;
}

View File

@ -0,0 +1,12 @@
# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
set (LIB_WASI_THREADS_DIR ${CMAKE_CURRENT_LIST_DIR})
add_definitions (-DWASM_ENABLE_LIB_WASI_THREADS=1 -DWASM_ENABLE_HEAP_AUX_STACK_ALLOCATION=1)
include_directories(${LIB_WASI_THREADS_DIR})
set (LIB_WASI_THREADS_SOURCE
${LIB_WASI_THREADS_DIR}/lib_wasi_threads_wrapper.c
${LIB_WASI_THREADS_DIR}/tid_allocator.c)

View File

@ -0,0 +1,181 @@
/*
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_log.h"
#include "thread_manager.h"
#include "tid_allocator.h"
#if WASM_ENABLE_INTERP != 0
#include "wasm_runtime.h"
#endif
#if WASM_ENABLE_AOT != 0
#include "aot_runtime.h"
#endif
static const char *THREAD_START_FUNCTION = "wasi_thread_start";
static korp_mutex thread_id_lock;
static TidAllocator tid_allocator;
typedef struct {
/* app's entry function */
wasm_function_inst_t start_func;
/* arg of the app's entry function */
uint32 arg;
/* thread id passed to the app */
int32 thread_id;
} ThreadStartArg;
static int32
allocate_thread_id()
{
os_mutex_lock(&thread_id_lock);
int32 id = tid_allocator_get_tid(&tid_allocator);
os_mutex_unlock(&thread_id_lock);
return id;
}
void
deallocate_thread_id(int32 thread_id)
{
os_mutex_lock(&thread_id_lock);
tid_allocator_release_tid(&tid_allocator, thread_id);
os_mutex_unlock(&thread_id_lock);
}
static void *
thread_start(void *arg)
{
wasm_exec_env_t exec_env = (wasm_exec_env_t)arg;
ThreadStartArg *thread_arg = exec_env->thread_arg;
uint32 argv[2];
wasm_exec_env_set_thread_info(exec_env);
argv[0] = thread_arg->thread_id;
argv[1] = thread_arg->arg;
if (!wasm_runtime_call_wasm(exec_env, thread_arg->start_func, 2, argv)) {
/* Exception has already been spread during throwing */
}
// Routine exit
deallocate_thread_id(thread_arg->thread_id);
wasm_runtime_free(thread_arg);
exec_env->thread_arg = NULL;
return NULL;
}
static int32
thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
{
wasm_module_t module = wasm_exec_env_get_module(exec_env);
wasm_module_inst_t module_inst = get_module_inst(exec_env);
wasm_module_inst_t new_module_inst = NULL;
ThreadStartArg *thread_start_arg = NULL;
wasm_function_inst_t start_func;
int32 thread_id;
uint32 stack_size = 8192;
int32 ret = -1;
#if WASM_ENABLE_LIBC_WASI != 0
WASIContext *wasi_ctx;
#endif
bh_assert(module);
bh_assert(module_inst);
stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
if (!(new_module_inst = wasm_runtime_instantiate_internal(
module, true, stack_size, 0, NULL, 0)))
return -1;
wasm_runtime_set_custom_data_internal(
new_module_inst, wasm_runtime_get_custom_data(module_inst));
#if WASM_ENABLE_LIBC_WASI != 0
wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
if (wasi_ctx)
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
#endif
start_func = wasm_runtime_lookup_function(new_module_inst,
THREAD_START_FUNCTION, NULL);
if (!start_func) {
LOG_ERROR("Failed to find thread start function %s",
THREAD_START_FUNCTION);
goto thread_preparation_fail;
}
if (!(thread_start_arg = wasm_runtime_malloc(sizeof(ThreadStartArg)))) {
LOG_ERROR("Runtime args allocation failed");
goto thread_preparation_fail;
}
thread_start_arg->thread_id = thread_id = allocate_thread_id();
if (thread_id < 0) {
LOG_ERROR("Failed to get thread identifier");
goto thread_preparation_fail;
}
thread_start_arg->arg = start_arg;
thread_start_arg->start_func = start_func;
ret = wasm_cluster_create_thread(exec_env, new_module_inst, false,
thread_start, thread_start_arg);
if (ret != 0) {
LOG_ERROR("Failed to spawn a new thread");
goto thread_spawn_fail;
}
return thread_id;
thread_spawn_fail:
deallocate_thread_id(thread_id);
thread_preparation_fail:
if (new_module_inst)
wasm_runtime_deinstantiate_internal(new_module_inst, true);
if (thread_start_arg)
wasm_runtime_free(thread_start_arg);
return -1;
}
/* clang-format off */
#define REG_NATIVE_FUNC(name, func_name, signature) \
{ name, func_name##_wrapper, signature, NULL }
/* clang-format on */
static NativeSymbol native_symbols_lib_wasi_threads[] = { REG_NATIVE_FUNC(
"thread-spawn", thread_spawn, "(i)i") };
uint32
get_lib_wasi_threads_export_apis(NativeSymbol **p_lib_wasi_threads_apis)
{
*p_lib_wasi_threads_apis = native_symbols_lib_wasi_threads;
return sizeof(native_symbols_lib_wasi_threads) / sizeof(NativeSymbol);
}
bool
lib_wasi_threads_init(void)
{
if (0 != os_mutex_init(&thread_id_lock))
return false;
if (!tid_allocator_init(&tid_allocator)) {
os_mutex_destroy(&thread_id_lock);
return false;
}
return true;
}
void
lib_wasi_threads_destroy(void)
{
tid_allocator_deinit(&tid_allocator);
os_mutex_destroy(&thread_id_lock);
}

View File

@ -0,0 +1,30 @@
#!/bin/bash
#
# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
CC=${CC:=/opt/wasi-sdk/bin/clang}
WASI_SYSROOT=${WASI_SYSROOT:=~/dev/wasi-libc/sysroot}
WAMR_DIR=../../../../..
for test_c in *.c; do
test_wasm="$(basename $test_c .c).wasm"
echo "Compiling $test_c to $test_wasm"
$CC \
--sysroot $WASI_SYSROOT \
-target wasm32-wasi-threads \
-pthread -ftls-model=local-exec \
-z stack-size=32768 \
-Wl,--export=__heap_base \
-Wl,--export=__data_end \
-Wl,--shared-memory,--max-memory=1966080 \
-Wl,--export=wasi_thread_start \
-Wl,--export=malloc \
-Wl,--export=free \
-I $WAMR_DIR/samples/wasi-threads/wasm-apps \
$WAMR_DIR/samples/wasi-threads/wasm-apps/wasi_thread_start.S \
$test_c -o $test_wasm
done

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2022 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <pthread.h>
#include <stdbool.h>
#include <unistd.h>
#include "wasi_thread_start.h"
typedef enum {
BLOCKING_TASK_BUSY_WAIT,
BLOCKING_TASK_ATOMIC_WAIT,
BLOCKING_TASK_POLL_ONEOFF
} blocking_task_type_t;
/* Parameter to change test behavior */
static bool termination_by_trap;
static bool termination_in_main_thread;
static blocking_task_type_t blocking_task_type;
#define TIMEOUT_SECONDS 10ll
#define NUM_THREADS 3
static pthread_barrier_t barrier;
typedef struct {
start_args_t base;
bool throw_exception;
} shared_t;
void
run_long_task()
{
if (blocking_task_type == BLOCKING_TASK_BUSY_WAIT) {
for (int i = 0; i < TIMEOUT_SECONDS; i++)
sleep(1);
}
else if (blocking_task_type == BLOCKING_TASK_ATOMIC_WAIT) {
__builtin_wasm_memory_atomic_wait32(
0, 0, TIMEOUT_SECONDS * 1000 * 1000 * 1000);
}
else {
sleep(TIMEOUT_SECONDS);
}
}
void
start_job()
{
/* Wait for all threads (including the main thread) to be ready */
pthread_barrier_wait(&barrier);
run_long_task(); /* Task to be interrupted */
assert(false && "Thread termination test failed");
}
void
terminate_process()
{
/* Wait for all threads (including the main thread) to be ready */
pthread_barrier_wait(&barrier);
if (termination_by_trap)
__builtin_trap();
else
__wasi_proc_exit(33);
}
void
__wasi_thread_start_C(int thread_id, int *start_arg)
{
shared_t *data = (shared_t *)start_arg;
if (data->throw_exception) {
terminate_process();
}
else {
start_job();
}
}
void
test_termination(bool trap, bool main, blocking_task_type_t task_type)
{
termination_by_trap = trap;
termination_in_main_thread = main;
blocking_task_type = task_type;
int thread_id = -1, i;
shared_t data[NUM_THREADS] = { 0 };
assert(pthread_barrier_init(&barrier, NULL, NUM_THREADS + 1) == 0
&& "Failed to init barrier");
for (i = 0; i < NUM_THREADS; i++) {
/* No graceful memory free to simplify the test */
assert(start_args_init(&data[i].base)
&& "Failed to allocate thread's stack");
}
/* Create a thread that forces termination through trap or `proc_exit` */
data[0].throw_exception = !termination_in_main_thread;
thread_id = __wasi_thread_spawn(&data[0]);
assert(thread_id > 0 && "Failed to create thread");
/* Create two additional threads to test exception propagation */
data[1].throw_exception = false;
thread_id = __wasi_thread_spawn(&data[1]);
assert(thread_id > 0 && "Failed to create thread");
data[2].throw_exception = false;
thread_id = __wasi_thread_spawn(&data[2]);
assert(thread_id > 0 && "Failed to create thread");
if (termination_in_main_thread) {
terminate_process();
}
else {
start_job();
}
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
#include "wasi_thread_start.h"
enum CONSTANTS {
MAX_NUM_THREADS = 4, /* Should be the same as "--max-threads" */
NUM_RETRY = 5,
SECOND = 1000 * 1000 * 1000, /* 1 second */
TIMEOUT = 10LL * SECOND
};
int g_count = 0;
typedef struct {
start_args_t base;
int th_ready;
int th_continue;
int th_done;
bool no_ops;
} shared_t;
void
__wasi_thread_start_C(int thread_id, int *start_arg)
{
shared_t *data = (shared_t *)start_arg;
if (data->no_ops) {
__builtin_wasm_memory_atomic_wait32(NULL, 0, 2 * SECOND);
return;
}
__atomic_store_n(&data->th_ready, 1, __ATOMIC_SEQ_CST);
__builtin_wasm_memory_atomic_notify(&data->th_ready, 1);
if (__builtin_wasm_memory_atomic_wait32(&data->th_continue, 0, TIMEOUT)
== 2) {
assert(false && "Wait should not time out");
}
__atomic_fetch_add(&g_count, 1, __ATOMIC_SEQ_CST);
__atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
__builtin_wasm_memory_atomic_notify(&data->th_done, 1);
}
int
main(int argc, char **argv)
{
shared_t data[MAX_NUM_THREADS] = { 0 };
int thread_ids[MAX_NUM_THREADS];
for (int i = 0; i < MAX_NUM_THREADS; i++) {
assert(start_args_init(&data[i].base));
thread_ids[i] = __wasi_thread_spawn(&data[i]);
printf("Thread created with id=%d\n", thread_ids[i]);
assert(thread_ids[i] > 0 && "Thread creation failed");
for (int j = 0; j < i; j++) {
assert(thread_ids[i] != thread_ids[j] && "Duplicated TIDs");
}
if (__builtin_wasm_memory_atomic_wait32(&data[i].th_ready, 0, TIMEOUT)
== 2) {
assert(false && "Wait should not time out");
}
}
printf("Attempt to create thread when not possible\n");
shared_t data_fail = { 0 };
assert(start_args_init(&data_fail.base));
int thread_id = __wasi_thread_spawn(&data_fail);
start_args_deinit(&data_fail.base);
assert(thread_id < 0 && "Thread creation should fail");
printf("Unlock created threads\n");
for (int i = 0; i < MAX_NUM_THREADS; i++) {
__atomic_store_n(&data[i].th_continue, 1, __ATOMIC_SEQ_CST);
__builtin_wasm_memory_atomic_notify(&data[i].th_continue, 1);
}
printf("Wait for threads to finish\n");
for (int i = 0; i < MAX_NUM_THREADS; i++) {
if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
== 2) {
assert(false && "Wait should not time out");
}
start_args_deinit(&data[i].base);
}
printf("Value of count after update: %d\n", g_count);
assert(g_count == (MAX_NUM_THREADS)
&& "Global count not updated correctly");
/* --------------------------------------------------- */
printf("Create new threads without waiting from them to finish\n");
shared_t data_no_join[MAX_NUM_THREADS] = { 0 };
for (int i = 0; i < MAX_NUM_THREADS; i++) {
/* No graceful memory free to simplify the test */
assert(start_args_init(&data_no_join[i].base));
data_no_join[i].no_ops = true;
int thread_id = -1;
for (int j = 0; j < NUM_RETRY && thread_id < 0; j++) {
thread_id = __wasi_thread_spawn(&data_no_join[i]);
if (thread_id < 0)
__builtin_wasm_memory_atomic_wait32(NULL, 0, SECOND);
}
printf("Thread created with id=%d\n", thread_id);
assert(thread_id > 0 && "Thread creation should succeed");
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
#include "wasi_thread_start.h"
enum CONSTANTS {
NUM_THREADS = 4,
NUM_ITER = 1000,
SECOND = 1000 * 1000 * 1000, /* 1 second */
TIMEOUT = 10LL * SECOND
};
int g_count = 0;
typedef struct {
start_args_t base;
int th_done;
} shared_t;
void
__wasi_thread_start_C(int thread_id, int *start_arg)
{
shared_t *data = (shared_t *)start_arg;
for (int i = 0; i < NUM_ITER; i++)
__atomic_fetch_add(&g_count, 1, __ATOMIC_SEQ_CST);
__atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
__builtin_wasm_memory_atomic_notify(&data->th_done, 1);
}
int
main(int argc, char **argv)
{
shared_t data[NUM_THREADS] = { 0 };
int thread_ids[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
assert(start_args_init(&data[i].base));
thread_ids[i] = __wasi_thread_spawn(&data[i]);
assert(thread_ids[i] > 0 && "Thread creation failed");
}
printf("Wait for threads to finish\n");
for (int i = 0; i < NUM_THREADS; i++) {
if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
== 2) {
assert(false && "Wait should not time out");
}
start_args_deinit(&data[i].base);
}
printf("Value of count after update: %d\n", g_count);
assert(g_count == (NUM_THREADS * NUM_ITER)
&& "Global count not updated correctly");
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
#include <pthread.h>
#include "wasi_thread_start.h"
enum CONSTANTS {
NUM_THREADS = 4,
NUM_ITER = 200,
SECOND = 1000 * 1000 * 1000, /* 1 second */
TIMEOUT = 10LL * SECOND
};
pthread_mutex_t mutex;
int g_count = 0;
typedef struct {
start_args_t base;
int th_done;
} shared_t;
void
__wasi_thread_start_C(int thread_id, int *start_arg)
{
shared_t *data = (shared_t *)start_arg;
for (int i = 0; i < NUM_ITER; i++) {
pthread_mutex_lock(&mutex);
g_count++;
pthread_mutex_unlock(&mutex);
}
__atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
__builtin_wasm_memory_atomic_notify(&data->th_done, 1);
}
int
main(int argc, char **argv)
{
shared_t data[NUM_THREADS] = { 0 };
int thread_ids[NUM_THREADS];
assert(pthread_mutex_init(&mutex, NULL) == 0 && "Failed to init mutex");
for (int i = 0; i < NUM_THREADS; i++) {
assert(start_args_init(&data[i].base));
thread_ids[i] = __wasi_thread_spawn(&data[i]);
assert(thread_ids[i] > 0 && "Thread creation failed");
}
printf("Wait for threads to finish\n");
for (int i = 0; i < NUM_THREADS; i++) {
if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
== 2) {
assert(false && "Wait should not time out");
}
start_args_deinit(&data[i].base);
}
printf("Value of count after update: %d\n", g_count);
assert(g_count == (NUM_THREADS * NUM_ITER)
&& "Global count not updated correctly");
assert(pthread_mutex_destroy(&mutex) == 0 && "Failed to destroy mutex");
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(false, true, BLOCKING_TASK_BUSY_WAIT);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 33
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(false, true, BLOCKING_TASK_POLL_ONEOFF);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 33
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(false, true, BLOCKING_TASK_ATOMIC_WAIT);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 33
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(true, true, BLOCKING_TASK_BUSY_WAIT);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 1
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(true, true, BLOCKING_TASK_POLL_ONEOFF);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 1
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(true, true, BLOCKING_TASK_ATOMIC_WAIT);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 1
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(false, false, BLOCKING_TASK_BUSY_WAIT);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 33
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(false, false, BLOCKING_TASK_POLL_ONEOFF);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 33
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(false, false, BLOCKING_TASK_ATOMIC_WAIT);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 33
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(true, false, BLOCKING_TASK_BUSY_WAIT);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 1
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(true, false, BLOCKING_TASK_POLL_ONEOFF);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 1
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef __wasi__
#error This example only compiles to WASM/WASI target
#endif
#include "common.h"
int
main(int argc, char **argv)
{
test_termination(true, false, BLOCKING_TASK_ATOMIC_WAIT);
}

View File

@ -0,0 +1,3 @@
{
"exit_code": 1
}

Some files were not shown because too many files have changed in this diff Show More