mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-06-18 02:59:21 +00:00
Merge pull request #2017 from bytecodealliance/main
Merge branch main into dev/exce_handling
This commit is contained in:
commit
9a77f1ab44
|
@ -12,7 +12,7 @@ ENV TZ=Asian/Shanghai
|
|||
# hadolint ignore=DL3008
|
||||
RUN apt-get update \
|
||||
&& 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 \
|
||||
ninja-build ocaml ocamlbuild python2.7 \
|
||||
software-properties-common tree tzdata \
|
||||
|
@ -20,6 +20,15 @@ RUN apt-get update \
|
|||
&& apt-get clean -y \
|
||||
&& 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/)
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
@ -38,18 +47,19 @@ RUN wget --progress=dot:giga -O - https://apt.kitware.com/keys/kitware-archive-l
|
|||
WORKDIR /opt
|
||||
RUN git clone https://github.com/emscripten-core/emsdk.git
|
||||
|
||||
ARG EMSDK_VER=3.0.0
|
||||
WORKDIR /opt/emsdk
|
||||
RUN git pull \
|
||||
&& ./emsdk install 2.0.26 \
|
||||
&& ./emsdk activate 2.0.26 \
|
||||
&& ./emsdk install ${EMSDK_VER} \
|
||||
&& ./emsdk activate ${EMSDK_VER} \
|
||||
&& echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc
|
||||
|
||||
#
|
||||
# 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 \
|
||||
&& 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
|
||||
|
||||
#
|
||||
|
@ -57,7 +67,7 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases
|
|||
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 \
|
||||
&& 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
|
||||
|
||||
#
|
||||
|
@ -70,6 +80,8 @@ RUN mkdir /opt/bazelisk \
|
|||
|
||||
#
|
||||
# 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
|
||||
RUN touch 99verfiy-peer.conf \
|
||||
&& echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf
|
||||
|
@ -77,9 +89,7 @@ RUN touch 99verfiy-peer.conf \
|
|||
WORKDIR /tmp
|
||||
RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
|
||||
&& chmod a+x ./llvm.sh \
|
||||
&& /tmp/llvm.sh 12 all \
|
||||
&& ln -sf /usr/bin/clang-format-12 /usr/bin/clang-format \
|
||||
&& rm -rf /tmp/*
|
||||
&& ./llvm.sh ${LLVM_VER} all
|
||||
|
||||
#
|
||||
# [Optional]
|
||||
|
@ -96,17 +106,28 @@ RUN apt-get update \
|
|||
# Install required python packages
|
||||
# hadolint ignore=DL3013
|
||||
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}"
|
||||
RUN echo "export PATH=/opt/bazelisk:/opt/clang-llvm/bin:${PATH}" >> /root/.bashrc \
|
||||
&& printf "%s\n" "PS1='\n[ \u@wamr-dev-docker \W ]\n$ '" >> /root/.bashrc \
|
||||
#
|
||||
# Install github-cli. It doens't work as a feature of devcontainer.json
|
||||
RUN cd /tmp \
|
||||
&& 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 clean -y \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm -rf /tmp/*
|
||||
|
||||
# set workdir when container run
|
||||
VOLUME /workspace
|
||||
WORKDIR /workspace
|
||||
VOLUME /workspaces
|
||||
WORKDIR /workspaces
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
// 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:
|
||||
// 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
|
||||
// Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon
|
||||
"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": [
|
||||
|
@ -27,12 +31,10 @@
|
|||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"dtsvet.vscode-wasm",
|
||||
"esbenp.prettier-vscode",
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"ms-vscode.cmake-tools",
|
||||
"ms-vscode.cpptools",
|
||||
"twxs.cmake"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
2
.github/workflows/build_iwasm_release.yml
vendored
2
.github/workflows/build_iwasm_release.yml
vendored
|
@ -36,7 +36,7 @@ jobs:
|
|||
- name: generate iwasm binary release
|
||||
run: |
|
||||
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_DEBUG_INTERP=0 \
|
||||
-DWAMR_BUILD_DEBUG_AOT=0 \
|
||||
|
|
74
.github/workflows/build_llvm_libraries.yml
vendored
74
.github/workflows/build_llvm_libraries.yml
vendored
|
@ -5,23 +5,46 @@ name: Reusable workflow-build_llvm_libraries
|
|||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
runs-on:
|
||||
os:
|
||||
required: true
|
||||
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:
|
||||
build_llvm_libraries:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: ${{ fromJson(inputs.runs-on) }}
|
||||
runs-on: ${{ inputs.os }}
|
||||
outputs:
|
||||
key: ${{ steps.create_lib_cache_key.outputs.key}}
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
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
|
||||
id: cache_llvm
|
||||
id: retrieve_llvm_libs
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
|
@ -30,10 +53,39 @@ jobs:
|
|||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-build-llvm_libraries_ex
|
||||
key: ${{ steps.create_lib_cache_key.outputs.key}}
|
||||
|
||||
- name: Build llvm
|
||||
id: build_llvm
|
||||
if: ${{ steps.cache_llvm.outputs.cache-hit != 'true' }}
|
||||
run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.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-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
|
||||
|
|
3
.github/workflows/build_wamr_vscode_ext.yml
vendored
3
.github/workflows/build_wamr_vscode_ext.yml
vendored
|
@ -32,11 +32,14 @@ jobs:
|
|||
working-directory: test-tools/wamr-ide/VSCode-Extension
|
||||
|
||||
- name: generate wamr ide vscode extension
|
||||
env:
|
||||
credentials: ${{ secrets.TOKEN }}
|
||||
run: |
|
||||
npm install -g vsce
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
vsce package
|
||||
vsce publish -p ${{ secrets.TOKEN }}
|
||||
working-directory: test-tools/wamr-ide/VSCode-Extension
|
||||
|
||||
- name: compress the vscode extension
|
||||
|
|
|
@ -15,7 +15,7 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
complinace_job:
|
||||
compliance_job:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
244
.github/workflows/compilation_on_android_ubuntu.yml
vendored
244
.github/workflows/compilation_on_android_ubuntu.yml
vendored
|
@ -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"
|
||||
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
|
||||
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
|
||||
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"
|
||||
# For Spec Test
|
||||
DEFAULT_TEST_OPTIONS: "-s spec -b -P"
|
||||
MULTI_MODULES_TEST_OPTIONS: "-s spec -b -M -P"
|
||||
SIMD_TEST_OPTIONS: "-s spec -b -S -P"
|
||||
THREADS_TEST_OPTIONS: "-s spec -b -p -P"
|
||||
X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P"
|
||||
WASI_TEST_OPTIONS: "-s wasi_certification -w"
|
||||
|
||||
jobs:
|
||||
build_llvm_libraries:
|
||||
build_llvm_libraries_on_ubuntu_2004:
|
||||
uses: ./.github/workflows/build_llvm_libraries.yml
|
||||
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:
|
||||
needs: [build_llvm_libraries]
|
||||
needs:
|
||||
[build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2204]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
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:
|
||||
- name: checkout
|
||||
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
|
||||
id: cache_llvm
|
||||
id: retrieve_llvm_libs
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
|
@ -88,10 +102,10 @@ jobs:
|
|||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
key: ${{ matrix.llvm_cache_key }}
|
||||
|
||||
- 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
|
||||
|
||||
- name: Build wamrc
|
||||
|
@ -102,7 +116,8 @@ jobs:
|
|||
working-directory: wamr-compiler
|
||||
|
||||
build_iwasm:
|
||||
needs: [build_llvm_libraries]
|
||||
needs:
|
||||
[build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2204]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -114,6 +129,7 @@ jobs:
|
|||
$FAST_JIT_BUILD_OPTIONS,
|
||||
$LLVM_LAZY_JIT_BUILD_OPTIONS,
|
||||
$LLVM_EAGER_JIT_BUILD_OPTIONS,
|
||||
$MULTI_TIER_JIT_BUILD_OPTIONS,
|
||||
]
|
||||
make_options_feature: [
|
||||
# Features
|
||||
|
@ -146,6 +162,8 @@ jobs:
|
|||
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
|
||||
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
||||
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
|
||||
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_SIMD=1"
|
||||
|
@ -162,6 +180,8 @@ jobs:
|
|||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
||||
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
|
||||
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
|
@ -174,6 +194,8 @@ jobs:
|
|||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
||||
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
|
||||
- make_options_run_mode: $AOT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
|
@ -183,16 +205,28 @@ jobs:
|
|||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
||||
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
|
||||
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:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# only download llvm cache when needed
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
id: retrieve_llvm_libs
|
||||
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
|
@ -202,10 +236,10 @@ jobs:
|
|||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
key: ${{ matrix.llvm_cache_key }}
|
||||
|
||||
- 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
|
||||
|
||||
- name: Build iwasm
|
||||
|
@ -216,7 +250,13 @@ jobs:
|
|||
working-directory: product-mini/platforms/${{ matrix.platform }}
|
||||
|
||||
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 }}
|
||||
strategy:
|
||||
matrix:
|
||||
|
@ -228,22 +268,28 @@ jobs:
|
|||
$FAST_JIT_BUILD_OPTIONS,
|
||||
$LLVM_LAZY_JIT_BUILD_OPTIONS,
|
||||
$LLVM_EAGER_JIT_BUILD_OPTIONS,
|
||||
$MULTI_TIER_JIT_BUILD_OPTIONS,
|
||||
]
|
||||
os: [ubuntu-20.04, ubuntu-22.04]
|
||||
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:
|
||||
[
|
||||
"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:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
id: retrieve_llvm_libs
|
||||
if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
|
@ -253,18 +299,18 @@ jobs:
|
|||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
key: ${{ matrix.llvm_cache_key }}
|
||||
|
||||
- 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
|
||||
|
||||
- name: download and install wabt
|
||||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wabt_release }}
|
||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
||||
sudo mv wabt-1.0.24 wabt
|
||||
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||
sudo mv wabt-1.0.31 wabt
|
||||
|
||||
- name: Build wamrc
|
||||
if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
|
||||
|
@ -276,19 +322,9 @@ jobs:
|
|||
|
||||
- name: Build Sample [wasm-c-api]
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. ${{ matrix.make_options }}
|
||||
cmake --build . --config Release --parallel 4
|
||||
./callback
|
||||
./callback_chain
|
||||
./empty_imports
|
||||
./global
|
||||
./hello
|
||||
./hostref
|
||||
./memory
|
||||
./reflect
|
||||
./table
|
||||
./trap
|
||||
cmake -S . -B build ${{ matrix.make_options }}
|
||||
cmake --build build --config Release --parallel 4
|
||||
ctest --test-dir build
|
||||
working-directory: samples/wasm-c-api
|
||||
|
||||
build_samples_others:
|
||||
|
@ -297,14 +333,13 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-22.04]
|
||||
wasi_sdk_release:
|
||||
[
|
||||
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz",
|
||||
]
|
||||
wabt_release:
|
||||
[
|
||||
"https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz",
|
||||
]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
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"
|
||||
- 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"
|
||||
wabt_release: "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz"
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
@ -313,15 +348,31 @@ jobs:
|
|||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wasi_sdk_release }}
|
||||
sudo tar -xzf wasi-sdk-12.0-*.tar.gz
|
||||
sudo mv wasi-sdk-12.0 wasi-sdk
|
||||
sudo tar -xzf wasi-sdk-*.tar.gz
|
||||
sudo mv wasi-sdk-19.0 wasi-sdk
|
||||
|
||||
- name: download and install wabt
|
||||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wabt_release }}
|
||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
||||
sudo mv wabt-1.0.24 wabt
|
||||
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||
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]
|
||||
run: |
|
||||
|
@ -376,20 +427,42 @@ jobs:
|
|||
exit $?
|
||||
working-directory: ./samples/simple
|
||||
|
||||
spec_test:
|
||||
needs: [build_iwasm, build_llvm_libraries, build_wamrc]
|
||||
- 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
|
||||
|
||||
test:
|
||||
needs: [build_iwasm, build_llvm_libraries_on_ubuntu_2004, build_wamrc]
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
running_mode:
|
||||
["classic-interp", "fast-interp", "jit", "aot", "fast-jit"]
|
||||
[
|
||||
"classic-interp",
|
||||
"fast-interp",
|
||||
"jit",
|
||||
"aot",
|
||||
"fast-jit",
|
||||
"multi-tier-jit",
|
||||
]
|
||||
test_option:
|
||||
[
|
||||
$DEFAULT_TEST_OPTIONS,
|
||||
$MULTI_MODULES_TEST_OPTIONS,
|
||||
$SIMD_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:
|
||||
# uncompatiable modes and features
|
||||
# classic-interp and fast-interp don't support simd
|
||||
|
@ -402,31 +475,68 @@ jobs:
|
|||
test_option: $MULTI_MODULES_TEST_OPTIONS
|
||||
- running_mode: "jit"
|
||||
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"
|
||||
test_option: $MULTI_MODULES_TEST_OPTIONS
|
||||
- running_mode: "fast-jit"
|
||||
test_option: $SIMD_TEST_OPTIONS
|
||||
- running_mode: "fast-jit"
|
||||
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:
|
||||
- name: checkout
|
||||
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)
|
||||
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
|
||||
|
||||
- name: set env variable(if x86_32 test needed)
|
||||
if: >
|
||||
(matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS')
|
||||
&& matrix.running_mode != 'fast-jit' && matrix.running_mode != 'jit'
|
||||
(matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS'
|
||||
|| 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
|
||||
|
||||
#only download llvm libraries in jit and aot mode
|
||||
- name: Get LLVM libraries
|
||||
if: env.USE_LLVM == 'true'
|
||||
id: cache_llvm
|
||||
id: retrieve_llvm_libs
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
|
@ -435,13 +545,28 @@ jobs:
|
|||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
key: ${{ matrix.llvm_cache_key }}
|
||||
|
||||
- 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
|
||||
|
||||
- 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 }}
|
||||
working-directory: ./tests/wamr-test-suites
|
||||
|
||||
|
@ -456,7 +581,8 @@ jobs:
|
|||
sudo apt-get update &&
|
||||
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'
|
||||
run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
|
||||
working-directory: ./tests/wamr-test-suites
|
||||
|
|
95
.github/workflows/compilation_on_macos.yml
vendored
95
.github/workflows/compilation_on_macos.yml
vendored
|
@ -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"
|
||||
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_CACHE_SUFFIX: "build-llvm_libraries_ex"
|
||||
|
||||
jobs:
|
||||
build_llvm_libraries:
|
||||
uses: ./.github/workflows/build_llvm_libraries.yml
|
||||
with:
|
||||
runs-on: "['macos-latest']"
|
||||
os: "macos-latest"
|
||||
arch: "X86"
|
||||
|
||||
build_wamrc:
|
||||
needs: [build_llvm_libraries]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
include:
|
||||
- os: macos-latest
|
||||
llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
id: retrieve_llvm_libs
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
|
@ -79,10 +81,10 @@ jobs:
|
|||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
key: ${{ matrix.llvm_cache_key }}
|
||||
|
||||
- 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
|
||||
|
||||
- name: Build wamrc
|
||||
|
@ -166,13 +168,16 @@ jobs:
|
|||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
include:
|
||||
- os: macos-latest
|
||||
llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# only download llvm cache when needed
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
id: retrieve_llvm_libs
|
||||
if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
|
@ -182,10 +187,10 @@ jobs:
|
|||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
key: ${{ matrix.llvm_cache_key }}
|
||||
|
||||
- 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
|
||||
|
||||
- name: Build iwasm
|
||||
|
@ -210,8 +215,14 @@ jobs:
|
|||
#$AOT_BUILD_OPTIONS,
|
||||
]
|
||||
os: [macos-latest]
|
||||
wasi_sdk_release: ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz"]
|
||||
wabt_release: ["https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz"]
|
||||
wasi_sdk_release:
|
||||
[
|
||||
"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:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
@ -220,24 +231,14 @@ jobs:
|
|||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wabt_release }}
|
||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
||||
sudo mv wabt-1.0.24 wabt
|
||||
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||
sudo mv wabt-1.0.31 wabt
|
||||
|
||||
- name: Build Sample [wasm-c-api]
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. ${{ matrix.make_options }}
|
||||
cmake --build . --config Release --parallel 4
|
||||
./callback
|
||||
./callback_chain
|
||||
./empty_imports
|
||||
./global
|
||||
./hello
|
||||
./hostref
|
||||
./memory
|
||||
./reflect
|
||||
./table
|
||||
./trap
|
||||
cmake -S . -B build ${{ matrix.make_options }}
|
||||
cmake --build build --config Release --parallel 4
|
||||
ctest --test-dir build
|
||||
working-directory: samples/wasm-c-api
|
||||
|
||||
build_samples_others:
|
||||
|
@ -246,8 +247,14 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
wasi_sdk_release: ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz"]
|
||||
wabt_release: ["https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz"]
|
||||
wasi_sdk_release:
|
||||
[
|
||||
"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:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
@ -256,15 +263,31 @@ jobs:
|
|||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wasi_sdk_release }}
|
||||
sudo tar -xzf wasi-sdk-12.0-*.tar.gz
|
||||
sudo mv wasi-sdk-12.0 wasi-sdk
|
||||
sudo tar -xzf wasi-sdk-*.tar.gz
|
||||
sudo mv wasi-sdk-19.0 wasi-sdk
|
||||
|
||||
- name: download and install wabt
|
||||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wabt_release }}
|
||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
||||
sudo mv wabt-1.0.24 wabt
|
||||
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||
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]
|
||||
run: |
|
||||
|
@ -311,3 +334,11 @@ jobs:
|
|||
cmake ..
|
||||
cmake --build . --config Release --parallel 4
|
||||
./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
|
||||
|
|
16
.github/workflows/compilation_on_nuttx.yml
vendored
16
.github/workflows/compilation_on_nuttx.yml
vendored
|
@ -45,6 +45,9 @@ concurrency:
|
|||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
WASI_SDK_PATH: "/opt/wasi-sdk"
|
||||
|
||||
jobs:
|
||||
build_iwasm_on_nuttx:
|
||||
runs-on: ubuntu-22.04
|
||||
|
@ -65,9 +68,12 @@ jobs:
|
|||
"boards/risc-v/k210/maix-bit/configs/nsh",
|
||||
]
|
||||
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\\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\\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\\n",
|
||||
"CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n",
|
||||
|
@ -92,6 +98,12 @@ jobs:
|
|||
tar xvf riscv.tar.gz
|
||||
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
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
|
@ -112,7 +124,7 @@ jobs:
|
|||
|
||||
- name: Enable WAMR for NuttX
|
||||
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'
|
||||
|
||||
- name: Build
|
||||
|
|
81
.github/workflows/compilation_on_sgx.yml
vendored
81
.github/workflows/compilation_on_sgx.yml
vendored
|
@ -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"
|
||||
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_CACHE_SUFFIX: "build-llvm_libraries_ex"
|
||||
|
||||
jobs:
|
||||
build_llvm_libraries:
|
||||
uses: ./.github/workflows/build_llvm_libraries.yml
|
||||
with:
|
||||
runs-on: "['ubuntu-20.04']"
|
||||
os: "ubuntu-20.04"
|
||||
arch: "X86"
|
||||
|
||||
build_iwasm:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
@ -131,7 +131,9 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
|
||||
steps:
|
||||
- name: install SGX SDK and necessary libraries
|
||||
run: |
|
||||
|
@ -150,7 +152,7 @@ jobs:
|
|||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
id: retrieve_llvm_libs
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
|
@ -159,10 +161,10 @@ jobs:
|
|||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
key: ${{ matrix.llvm_cache_key }}
|
||||
|
||||
- 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
|
||||
|
||||
- name: Build wamrc
|
||||
|
@ -189,11 +191,11 @@ jobs:
|
|||
os: [ubuntu-20.04]
|
||||
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:
|
||||
[
|
||||
"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:
|
||||
- name: checkout
|
||||
|
@ -203,8 +205,8 @@ jobs:
|
|||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wabt_release }}
|
||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
||||
sudo mv wabt-1.0.24 wabt
|
||||
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||
sudo mv wabt-1.0.31 wabt
|
||||
|
||||
- name: install SGX SDK and necessary libraries
|
||||
run: |
|
||||
|
@ -221,19 +223,9 @@ jobs:
|
|||
|
||||
- name: Build Sample [wasm-c-api]
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. ${{ matrix.make_options }}
|
||||
cmake --build . --config Release --parallel 4
|
||||
./callback
|
||||
./callback_chain
|
||||
./empty_imports
|
||||
./global
|
||||
./hello
|
||||
./hostref
|
||||
./memory
|
||||
./reflect
|
||||
./table
|
||||
./trap
|
||||
cmake -S . -B build ${{ matrix.make_options }}
|
||||
cmake --build build --config Release --parallel 4
|
||||
ctest --test-dir build
|
||||
working-directory: samples/wasm-c-api
|
||||
|
||||
build_samples_others:
|
||||
|
@ -244,11 +236,11 @@ jobs:
|
|||
os: [ubuntu-20.04]
|
||||
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:
|
||||
[
|
||||
"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:
|
||||
- name: checkout
|
||||
|
@ -258,15 +250,31 @@ jobs:
|
|||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wasi_sdk_release }}
|
||||
sudo tar -xzf wasi-sdk-12.0-*.tar.gz
|
||||
sudo mv wasi-sdk-12.0 wasi-sdk
|
||||
sudo tar -xzf wasi-sdk-*.tar.gz
|
||||
sudo mv wasi-sdk-19.0 wasi-sdk
|
||||
|
||||
- name: download and install wabt
|
||||
run: |
|
||||
cd /opt
|
||||
sudo wget ${{ matrix.wabt_release }}
|
||||
sudo tar -xzf wabt-1.0.24-*.tar.gz
|
||||
sudo mv wabt-1.0.24 wabt
|
||||
sudo tar -xzf wabt-1.0.31-*.tar.gz
|
||||
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
|
||||
run: |
|
||||
|
@ -327,6 +335,14 @@ jobs:
|
|||
cmake --build . --config Release --parallel 4
|
||||
./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:
|
||||
needs: [build_iwasm, build_llvm_libraries, build_wamrc]
|
||||
runs-on: ubuntu-20.04
|
||||
|
@ -334,6 +350,7 @@ jobs:
|
|||
matrix:
|
||||
running_mode: ["classic-interp", "fast-interp", "aot"]
|
||||
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
|
||||
exclude:
|
||||
- running_mode: "classic-interp"
|
||||
|
@ -347,7 +364,7 @@ jobs:
|
|||
|
||||
- name: Get LLVM libraries
|
||||
if: matrix.running_mode == 'aot'
|
||||
id: cache_llvm
|
||||
id: retrieve_llvm_libs
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
|
@ -356,10 +373,10 @@ jobs:
|
|||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
key: ${{ matrix.llvm_cache_key }}
|
||||
|
||||
- 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
|
||||
|
||||
- name: install SGX SDK and necessary libraries
|
||||
|
|
14
.github/workflows/compilation_on_windows.yml
vendored
14
.github/workflows/compilation_on_windows.yml
vendored
|
@ -118,3 +118,17 @@ jobs:
|
|||
cmake .. -DWAMR_BUILD_DEBUG_INTERP=1
|
||||
cmake --build . --config Release --parallel 4
|
||||
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
|
||||
|
|
7
.github/workflows/release_process.yml
vendored
7
.github/workflows/release_process.yml
vendored
|
@ -123,7 +123,7 @@ jobs:
|
|||
runner: ubuntu-20.04
|
||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
||||
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:
|
||||
needs: [create_tag, create_release]
|
||||
|
@ -133,7 +133,7 @@ jobs:
|
|||
runner: ubuntu-22.04
|
||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
||||
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:
|
||||
needs: [create_tag, create_release]
|
||||
|
@ -143,13 +143,14 @@ jobs:
|
|||
runner: macos-latest
|
||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
||||
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
|
||||
release_wamr_ide_vscode_ext:
|
||||
needs: [create_tag, create_release]
|
||||
uses: ./.github/workflows/build_wamr_vscode_ext.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
upload_url: ${{ needs.create_release.outputs.upload_url }}
|
||||
ver_num: ${{ needs.create_tag.outputs.new_ver }}
|
||||
|
|
17
.github/workflows/spec_test_on_nuttx.yml
vendored
17
.github/workflows/spec_test_on_nuttx.yml
vendored
|
@ -11,12 +11,14 @@ on:
|
|||
|
||||
env:
|
||||
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
|
||||
WASI_SDK_PATH: "/opt/wasi-sdk"
|
||||
|
||||
jobs:
|
||||
build_llvm_libraries:
|
||||
uses: ./.github/workflows/build_llvm_libraries.yml
|
||||
with:
|
||||
runs-on: "['ubuntu-22.04']"
|
||||
os: "ubuntu-22.04"
|
||||
arch: "ARM RISCV AArch64"
|
||||
|
||||
spec_test_on_qemu:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
@ -37,6 +39,7 @@ jobs:
|
|||
"-t aot",
|
||||
"-t aot -X"
|
||||
]
|
||||
llvm_cache_key: [ "${{ needs.build_llvm_libraries.outputs.cache_key }}" ]
|
||||
steps:
|
||||
- name: Install Utilities
|
||||
run: |
|
||||
|
@ -53,6 +56,12 @@ jobs:
|
|||
tar xvf riscv.tar.gz
|
||||
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
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
|
@ -72,7 +81,7 @@ jobs:
|
|||
path: apps/interpreters/wamr/wamr
|
||||
|
||||
- name: Get LLVM libraries
|
||||
id: cache_llvm
|
||||
id: retrieve_llvm_libs
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
|
@ -81,10 +90,10 @@ jobs:
|
|||
./core/deps/llvm/build/lib
|
||||
./core/deps/llvm/build/libexec
|
||||
./core/deps/llvm/build/share
|
||||
key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
|
||||
key: ${{ matrix.llvm_cache_key }}
|
||||
|
||||
- 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
|
||||
|
||||
- name: Copy LLVM
|
||||
|
|
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -13,6 +13,8 @@
|
|||
core/deps/**
|
||||
core/shared/mem-alloc/tlsf
|
||||
core/app-framework/wgl
|
||||
core/iwasm/libraries/lib-wasi-threads/test/*.wasm
|
||||
core/iwasm/libraries/lib-socket/test/*.wasm
|
||||
|
||||
wamr-sdk/out/
|
||||
wamr-sdk/runtime/build_runtime_sdk/
|
||||
|
@ -32,3 +34,8 @@ samples/socket-api/wasm-src/inc/pthread.h
|
|||
**/__pycache__
|
||||
|
||||
tests/benchmarks/coremark/coremark*
|
||||
|
||||
samples/workload/include/**
|
||||
!samples/workload/include/.gitkeep
|
||||
|
||||
# core/iwasm/libraries/wasi-threads
|
|
@ -7,7 +7,9 @@ project (iwasm)
|
|||
|
||||
set (CMAKE_VERBOSE_MAKEFILE OFF)
|
||||
|
||||
if (NOT DEFINED WAMR_BUILD_PLATFORM)
|
||||
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
|
||||
endif ()
|
||||
|
||||
# Reset default linker 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)
|
||||
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)
|
||||
# Disable wasm mini loader by default
|
||||
set (WAMR_BUILD_MINI_LOADER 0)
|
||||
|
@ -98,11 +105,6 @@ if (NOT DEFINED WAMR_BUILD_REF_TYPES)
|
|||
set (WAMR_BUILD_REF_TYPES 0)
|
||||
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})
|
||||
|
||||
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
|
@ -130,19 +132,22 @@ include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
|||
|
||||
# STATIC LIBRARY
|
||||
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)
|
||||
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)
|
||||
|
||||
# SHARED LIBRARY
|
||||
add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
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)
|
||||
target_link_libraries(iwasm_shared boringssl_crypto)
|
||||
target_link_libraries(iwasm_shared INTERFACE boringssl_crypto)
|
||||
endif ()
|
||||
|
||||
if (MINGW)
|
||||
|
@ -155,4 +160,5 @@ install (TARGETS iwasm_shared LIBRARY DESTINATION lib)
|
|||
install (FILES
|
||||
${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/lib_export.h
|
||||
DESTINATION include)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import requests
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
|
@ -21,28 +22,44 @@ def clone_llvm(dst_dir, llvm_repo, llvm_branch):
|
|||
llvm_dir = dst_dir.joinpath("llvm").resolve()
|
||||
|
||||
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"
|
||||
print(GIT_CLONE_CMD)
|
||||
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
|
||||
|
||||
|
||||
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 = [
|
||||
'-DCMAKE_BUILD_TYPE:STRING="Release"',
|
||||
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
|
||||
"-DLLVM_APPEND_VC_REV:BOOL=ON",
|
||||
"-DLLVM_BUILD_BENCHMARKS:BOOL=OFF",
|
||||
"-DLLVM_BUILD_DOCS:BOOL=OFF",
|
||||
"-DLLVM_BUILD_EXAMPLES:BOOL=OFF",
|
||||
"-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF",
|
||||
"-DLLVM_BUILD_TESTS:BOOL=OFF",
|
||||
"-DLLVM_CCACHE_BUILD:BOOL=OFF",
|
||||
"-DLLVM_CCACHE_BUILD:BOOL=ON",
|
||||
"-DLLVM_ENABLE_BINDINGS:BOOL=OFF",
|
||||
"-DLLVM_ENABLE_IDE:BOOL=OFF",
|
||||
"-DLLVM_ENABLE_LIBEDIT=OFF",
|
||||
"-DLLVM_ENABLE_TERMINFO:BOOL=OFF",
|
||||
"-DLLVM_ENABLE_ZLIB:BOOL=OFF",
|
||||
"-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF",
|
||||
|
@ -54,6 +71,18 @@ def build_llvm(llvm_dir, platform, backends, projects):
|
|||
"-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 = {
|
||||
"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()
|
||||
if lib_llvm_core_library.exists():
|
||||
print(f"Please remove {build_dir} manually and try again")
|
||||
return build_dir
|
||||
print(
|
||||
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(
|
||||
LLVM_COMPILE_OPTIONS
|
||||
|
@ -113,16 +144,17 @@ def build_llvm(llvm_dir, platform, backends, projects):
|
|||
+ LLVM_INCLUDE_TOOLS_OPTION
|
||||
)
|
||||
|
||||
CONFIG_CMD = f"cmake {compile_options} ../llvm"
|
||||
CONFIG_CMD = f"cmake {compile_options} {extra_flags} ../llvm"
|
||||
if "windows" == platform:
|
||||
if "mingw" in sysconfig.get_platform().lower():
|
||||
CONFIG_CMD += " -G'Unix Makefiles'"
|
||||
else:
|
||||
CONFIG_CMD += " -A x64"
|
||||
print(f"{CONFIG_CMD}")
|
||||
else:
|
||||
CONFIG_CMD += " -G'Ninja'"
|
||||
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 ""
|
||||
)
|
||||
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):
|
||||
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:
|
||||
raise Exception("Find more than one LLVM-13*.tar.gz")
|
||||
raise Exception("Find more than one LLVM-*.tar.gz")
|
||||
|
||||
if not packs:
|
||||
return
|
||||
|
||||
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))
|
||||
# rm -r build
|
||||
shutil.rmtree(str(build_dir))
|
||||
# mkdir build
|
||||
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}"
|
||||
subprocess.check_call(shlex.split(CMD), cwd=llvm_dir)
|
||||
# rm ./LLVM-1*.gz
|
||||
os.remove(llvm_dir.joinpath(llvm_package).resolve())
|
||||
|
||||
|
||||
def main():
|
||||
|
@ -184,8 +218,23 @@ def main():
|
|||
choices=["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()
|
||||
print(f"options={options}")
|
||||
|
||||
# if the "platform" is not identified in the command line option,
|
||||
# detect it
|
||||
|
@ -199,20 +248,21 @@ def main():
|
|||
else:
|
||||
platform = options.platform
|
||||
|
||||
print(f"========== Build LLVM for {platform} ==========\n")
|
||||
|
||||
llvm_repo_and_branch = {
|
||||
"arc": {
|
||||
"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": {
|
||||
"repo": "https://github.com/espressif/llvm-project.git",
|
||||
"repo_ssh": "git@github.com:espressif/llvm-project.git",
|
||||
"branch": "xtensa_release_15.x",
|
||||
},
|
||||
"default": {
|
||||
"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()
|
||||
|
||||
try:
|
||||
print(f"==================== CLONE LLVM ====================")
|
||||
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()
|
||||
print(f"==================== BUILD LLVM ====================")
|
||||
build_llvm(llvm_dir, platform, options.arch, options.project)
|
||||
if options.llvm_ver:
|
||||
commit_hash = query_llvm_version(llvm_info)
|
||||
print(commit_hash)
|
||||
return commit_hash is not None
|
||||
|
||||
print()
|
||||
print(f"==================== PACKAGE LLVM ====================")
|
||||
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()
|
||||
return True
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
|
|
@ -337,6 +337,11 @@ if (WAMR_BUILD_SGX_IPFS EQUAL 1)
|
|||
endif ()
|
||||
if (WAMR_BUILD_WASI_NN EQUAL 1)
|
||||
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 ()
|
||||
if (WAMR_BUILD_ALLOC_WITH_USER_DATA EQUAL 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)
|
||||
message (" Wasm files cache enabled")
|
||||
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 ()
|
||||
|
|
1
build-scripts/requirements.txt
Normal file
1
build-scripts/requirements.txt
Normal file
|
@ -0,0 +1 @@
|
|||
requests==2.28.2
|
|
@ -19,6 +19,11 @@ endif ()
|
|||
if (NOT DEFINED DEPS_DIR)
|
||||
set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps)
|
||||
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)
|
||||
message(STATUS, "EXTRA_SDK_INCLUDE_PATH = ${EXTRA_SDK_INCLUDE_PATH} ")
|
||||
|
@ -96,10 +101,21 @@ if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1)
|
|||
endif ()
|
||||
|
||||
if (WAMR_BUILD_WASI_NN EQUAL 1)
|
||||
if (NOT EXISTS "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
|
||||
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")
|
||||
|
||||
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 (${TENSORFLOW_SOURCE_DIR})
|
||||
add_subdirectory(
|
||||
|
@ -116,6 +132,14 @@ if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
|
|||
set (WAMR_BUILD_SHARED_MEMORY 1)
|
||||
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)
|
||||
set (WAMR_BUILD_THREAD_MGR 1)
|
||||
include (${IWASM_DIR}/libraries/debug-engine/debug_engine.cmake)
|
||||
|
@ -161,7 +185,7 @@ LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
|
|||
|
||||
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 (${IWASM_DIR}/common/iwasm_common.cmake)
|
||||
include (${SHARED_DIR}/utils/shared_utils.cmake)
|
||||
|
@ -182,6 +206,7 @@ set (source_all
|
|||
${WASM_APP_LIB_SOURCE_ALL}
|
||||
${NATIVE_INTERFACE_SOURCE}
|
||||
${APP_MGR_SOURCE}
|
||||
${LIB_WASI_THREADS_SOURCE}
|
||||
${LIB_PTHREAD_SOURCE}
|
||||
${THREAD_MGR_SOURCE}
|
||||
${LIBC_EMCC_SOURCE}
|
||||
|
|
|
@ -7,11 +7,14 @@
|
|||
|
||||
typedef union jvalue {
|
||||
bool z;
|
||||
int8_t b;
|
||||
uint16_t c;
|
||||
int16_t s;
|
||||
int32_t i;
|
||||
int64_t j;
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
int16_t i16;
|
||||
uint16_t u16;
|
||||
int32_t i32;
|
||||
uint32_t u32;
|
||||
int64_t i64;
|
||||
uint64_t u64;
|
||||
float f;
|
||||
double d;
|
||||
} jvalue;
|
||||
|
@ -27,7 +30,9 @@ get_int16(const char *buf)
|
|||
static inline uint16_t
|
||||
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
|
||||
|
@ -41,7 +46,9 @@ get_int32(const char *buf)
|
|||
static inline uint32_t
|
||||
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
|
||||
|
@ -55,7 +62,9 @@ get_int64(const char *buf)
|
|||
static inline uint64_t
|
||||
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
|
||||
|
@ -145,8 +154,8 @@ attr_container_get_attr_next(const char *curr_attr)
|
|||
p += sizeof(uint16_t) + get_uint16(p);
|
||||
type = *p++;
|
||||
|
||||
/* Short type to Boolean type */
|
||||
if (type >= ATTR_TYPE_SHORT && type <= ATTR_TYPE_BOOLEAN) {
|
||||
/* Byte type to Boolean type */
|
||||
if (type >= ATTR_TYPE_BYTE && type <= ATTR_TYPE_BOOLEAN) {
|
||||
p += 1 << (type & 3);
|
||||
return p;
|
||||
}
|
||||
|
@ -342,7 +351,7 @@ attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
|
|||
|
||||
/* key len + key + '\0' + type */
|
||||
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);
|
||||
else if (type == ATTR_TYPE_STRING)
|
||||
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++ = 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));
|
||||
else if (type == ATTR_TYPE_STRING) {
|
||||
set_uint16(p, value_length);
|
||||
|
@ -460,6 +469,14 @@ attr_container_set_short(attr_container_t **p_attr_cont, const char *key,
|
|||
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
|
||||
attr_container_set_int(attr_container_t **p_attr_cont, const char *key,
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
|
||||
int64_t value)
|
||||
|
@ -475,6 +508,14 @@ attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
|
|||
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
|
||||
attr_container_set_byte(attr_container_t **p_attr_cont, const char *key,
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
attr_container_set_uint16(attr_container_t **p_attr_cont, const char *key,
|
||||
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))) {
|
||||
attr_container_printf("Get attribute failed: lookup key failed.\r\n");
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* key len + key + '\0' */
|
||||
|
@ -566,14 +622,17 @@ attr_container_get_attr(const attr_container_t *attr_cont, const char *key)
|
|||
uint8_t type; \
|
||||
if (!addr) \
|
||||
return 0; \
|
||||
val.j = 0; \
|
||||
val.i64 = 0; \
|
||||
type = *(uint8_t *)addr++; \
|
||||
switch (type) { \
|
||||
case ATTR_TYPE_SHORT: \
|
||||
case ATTR_TYPE_INT: \
|
||||
case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */ \
|
||||
case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */ \
|
||||
case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */ \
|
||||
case ATTR_TYPE_INT64: \
|
||||
case ATTR_TYPE_BYTE: \
|
||||
case ATTR_TYPE_UINT8: \
|
||||
case ATTR_TYPE_UINT16: \
|
||||
case ATTR_TYPE_UINT32: \
|
||||
case ATTR_TYPE_UINT64: \
|
||||
case ATTR_TYPE_FLOAT: \
|
||||
case ATTR_TYPE_DOUBLE: \
|
||||
case ATTR_TYPE_BOOLEAN: \
|
||||
|
@ -608,31 +667,67 @@ attr_container_get_attr(const attr_container_t *attr_cont, const char *key)
|
|||
short
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
@ -671,11 +766,14 @@ attr_container_get_as_bytearray(const attr_container_t *attr_cont,
|
|||
|
||||
type = *(uint8_t *)addr++;
|
||||
switch (type) {
|
||||
case ATTR_TYPE_SHORT:
|
||||
case ATTR_TYPE_INT:
|
||||
case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */
|
||||
case ATTR_TYPE_SHORT: /* = ATTR_TYPE_INT16 */
|
||||
case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */
|
||||
case ATTR_TYPE_INT64:
|
||||
case ATTR_TYPE_BYTE:
|
||||
case ATTR_TYPE_UINT8:
|
||||
case ATTR_TYPE_UINT16:
|
||||
case ATTR_TYPE_UINT32:
|
||||
case ATTR_TYPE_UINT64:
|
||||
case ATTR_TYPE_FLOAT:
|
||||
case ATTR_TYPE_DOUBLE:
|
||||
case ATTR_TYPE_BOOLEAN:
|
||||
|
@ -807,34 +905,52 @@ attr_container_dump(const attr_container_t *attr_cont)
|
|||
attr_container_printf(" key: %s", key);
|
||||
|
||||
switch (type) {
|
||||
case ATTR_TYPE_SHORT:
|
||||
bh_memcpy_s(&value.s, sizeof(int16_t), p, sizeof(int16_t));
|
||||
case ATTR_TYPE_BYTE: /* = ATTR_TYPE_INT8 */
|
||||
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",
|
||||
value.s & 0xFFFF);
|
||||
value.i16 & 0xFFFF);
|
||||
p += 2;
|
||||
break;
|
||||
case ATTR_TYPE_INT:
|
||||
bh_memcpy_s(&value.i, sizeof(int32_t), p, sizeof(int32_t));
|
||||
attr_container_printf(", type: int, value: 0x%x\n", value.i);
|
||||
case ATTR_TYPE_INT: /* = ATTR_TYPE_INT32 */
|
||||
bh_memcpy_s(&value.i32, sizeof(int32_t), p, sizeof(int32_t));
|
||||
attr_container_printf(", type: int, value: 0x%x\n", value.i32);
|
||||
p += 4;
|
||||
break;
|
||||
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",
|
||||
(long long unsigned int)(value.j));
|
||||
(long long unsigned int)(value.i64));
|
||||
p += 8;
|
||||
break;
|
||||
case ATTR_TYPE_BYTE:
|
||||
bh_memcpy_s(&value.b, 1, p, 1);
|
||||
attr_container_printf(", type: byte, value: 0x%x\n",
|
||||
value.b & 0xFF);
|
||||
case ATTR_TYPE_UINT8:
|
||||
bh_memcpy_s(&value.u8, 1, p, 1);
|
||||
attr_container_printf(", type: uint8, value: 0x%x\n", value.u8);
|
||||
p++;
|
||||
break;
|
||||
case ATTR_TYPE_UINT16:
|
||||
bh_memcpy_s(&value.c, sizeof(uint16_t), p, sizeof(uint16_t));
|
||||
attr_container_printf(", type: uint16, value: 0x%x\n", value.c);
|
||||
bh_memcpy_s(&value.u16, sizeof(uint16_t), p, sizeof(uint16_t));
|
||||
attr_container_printf(", type: uint16, value: 0x%x\n",
|
||||
value.u16);
|
||||
p += 2;
|
||||
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:
|
||||
bh_memcpy_s(&value.f, sizeof(float), p, sizeof(float));
|
||||
attr_container_printf(", type: float, value: %f\n", value.f);
|
||||
|
|
|
@ -20,13 +20,27 @@ extern "C" {
|
|||
|
||||
/* Attribute type */
|
||||
enum {
|
||||
ATTR_TYPE_BEGIN = 1,
|
||||
ATTR_TYPE_SHORT = ATTR_TYPE_BEGIN,
|
||||
ATTR_TYPE_BEGIN = 0,
|
||||
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_INT32 = ATTR_TYPE_INT,
|
||||
ATTR_TYPE_INT64,
|
||||
ATTR_TYPE_BYTE,
|
||||
ATTR_TYPE_UINT8,
|
||||
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_BOOLEAN,
|
||||
ATTR_TYPE_STRING,
|
||||
|
@ -89,6 +103,20 @@ bool
|
|||
attr_container_set_short(attr_container_t **p_attr_cont, const char *key,
|
||||
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
|
||||
*
|
||||
|
@ -103,6 +131,34 @@ bool
|
|||
attr_container_set_int(attr_container_t **p_attr_cont, const char *key,
|
||||
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
|
||||
*
|
||||
|
@ -117,6 +173,20 @@ bool
|
|||
attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
|
||||
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
|
||||
*
|
||||
|
@ -131,6 +201,34 @@ bool
|
|||
attr_container_set_byte(attr_container_t **p_attr_cont, const char *key,
|
||||
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
|
||||
*
|
||||
|
@ -259,6 +357,18 @@ attr_container_contain_key(const attr_container_t *attr_cont, const char *key);
|
|||
short
|
||||
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,
|
||||
* 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
|
||||
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,
|
||||
* 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
|
||||
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,
|
||||
* 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
|
||||
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,
|
||||
* return 0 if attribute isn't found in attribute container.
|
||||
|
|
|
@ -993,6 +993,14 @@ wasm_app_module_uninstall(request_t *msg)
|
|||
|
||||
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
|
||||
bh_queue_exit_loop_run(get_app_manager_queue());
|
||||
#endif
|
||||
|
|
|
@ -161,6 +161,17 @@
|
|||
#define WASM_ENABLE_LIB_PTHREAD_SEMAPHORE 0
|
||||
#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
|
||||
#define WASM_ENABLE_BASE_LIB 0
|
||||
#endif
|
||||
|
|
|
@ -1226,7 +1226,10 @@ load_import_globals(const uint8 **p_buf, const uint8 *buf_end,
|
|||
}
|
||||
import_globals[i].global_data_linked =
|
||||
tmp_global.global_data_linked;
|
||||
import_globals[i].is_linked = true;
|
||||
}
|
||||
#else
|
||||
import_globals[i].is_linked = false;
|
||||
#endif
|
||||
|
||||
import_globals[i].size = wasm_value_type_size(import_globals[i].type);
|
||||
|
|
|
@ -30,6 +30,8 @@ bh_static_assert(offsetof(WASMExecEnv, aux_stack_boundary)
|
|||
bh_static_assert(offsetof(WASMExecEnv, aux_stack_bottom)
|
||||
== 7 * 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, 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);
|
||||
}
|
||||
|
||||
static bool
|
||||
clear_wasi_proc_exit_exception(AOTModuleInstance *module_inst)
|
||||
static AOTFunctionInstance *
|
||||
lookup_post_instantiate_func(AOTModuleInstance *module_inst,
|
||||
const char *func_name)
|
||||
{
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
const char *exception = aot_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. */
|
||||
aot_set_exception(module_inst, NULL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
AOTFunctionInstance *func;
|
||||
AOTFuncType *func_type;
|
||||
|
||||
static bool
|
||||
execute_post_inst_function(AOTModuleInstance *module_inst)
|
||||
{
|
||||
AOTFunctionInstance *post_inst_func =
|
||||
aot_lookup_function(module_inst, "__post_instantiate", "()");
|
||||
|
||||
if (!post_inst_func)
|
||||
if (!(func = aot_lookup_function(module_inst, func_name, NULL)))
|
||||
/* Not found */
|
||||
return true;
|
||||
return NULL;
|
||||
|
||||
return aot_create_exec_env_and_call_function(module_inst, post_inst_func, 0,
|
||||
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_start_function(AOTModuleInstance *module_inst)
|
||||
execute_post_instantiate_functions(AOTModuleInstance *module_inst,
|
||||
bool is_sub_inst)
|
||||
{
|
||||
AOTModule *module = (AOTModule *)module_inst->module;
|
||||
WASMExecEnv *exec_env;
|
||||
typedef void (*F)(WASMExecEnv *);
|
||||
union {
|
||||
F f;
|
||||
void *v;
|
||||
} u;
|
||||
AOTFunctionInstance *initialize_func = NULL;
|
||||
AOTFunctionInstance *post_inst_func = NULL;
|
||||
AOTFunctionInstance *call_ctors_func = NULL;
|
||||
#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 (!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;
|
||||
}
|
||||
|
||||
if (!(exec_env =
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
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))) {
|
||||
aot_set_exception(module_inst, "allocate memory failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
u.v = module->start_function;
|
||||
u.f(exec_env);
|
||||
/* Execute start function for both main insance and sub instance */
|
||||
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);
|
||||
(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
|
||||
|
||||
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 *
|
||||
aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_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))
|
||||
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))
|
||||
goto fail;
|
||||
|
||||
|
@ -1079,6 +1170,17 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size,
|
|||
}
|
||||
#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 */
|
||||
if (stack_size == 0)
|
||||
stack_size = DEFAULT_WASM_STACK_SIZE;
|
||||
|
@ -1104,32 +1206,11 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Execute __post_instantiate function and start function*/
|
||||
if (!execute_post_inst_function(module_inst)
|
||||
|| !execute_start_function(module_inst)) {
|
||||
if (!execute_post_instantiate_functions(module_inst, is_sub_inst)) {
|
||||
set_error_buf(error_buf, error_buf_size, module_inst->cur_exception);
|
||||
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
|
||||
wasm_runtime_dump_module_inst_mem_consumption(
|
||||
(WASMModuleInstanceCommon *)module_inst);
|
||||
|
@ -1145,6 +1226,15 @@ fail:
|
|||
void
|
||||
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
|
||||
/* Destroy wasi resource before freeing app heap, since some fields of
|
||||
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)
|
||||
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)
|
||||
wasm_runtime_free(
|
||||
((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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
native stack to run the following codes before actually calling
|
||||
the aot function in invokeNative function. */
|
||||
RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst);
|
||||
if ((uint8 *)&module_inst < exec_env->native_stack_boundary
|
||||
+ page_size * (guard_page_count + 1)) {
|
||||
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,
|
||||
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 (!ret) {
|
||||
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,
|
||||
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 (aot_get_exception(module_inst)) {
|
||||
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 */
|
||||
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->e;
|
||||
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_idx = func_type_indexes[func_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;
|
||||
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) {
|
||||
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
|
||||
it again */
|
||||
|
||||
RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst);
|
||||
if ((uint8 *)&module_inst < exec_env->native_stack_boundary) {
|
||||
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
|
||||
goto fail;
|
||||
|
@ -1980,9 +2071,6 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
|
|||
}
|
||||
|
||||
fail:
|
||||
if (clear_wasi_proc_exit_exception(module_inst))
|
||||
return true;
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
wasm_runtime_access_exce_check_guard_page();
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
#include "../interpreter/wasm_runtime.h"
|
||||
#include "../compilation/aot.h"
|
||||
|
||||
#if WASM_ENABLE_WASI_NN != 0
|
||||
#include "../libraries/wasi-nn/src/wasi_nn_private.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -75,6 +79,9 @@ typedef struct AOTFunctionInstance {
|
|||
|
||||
typedef struct AOTModuleInstanceExtra {
|
||||
CApiFuncImport *c_api_func_imports;
|
||||
#if WASM_ENABLE_WASI_NN != 0
|
||||
WASINNContext *wasi_nn_ctx;
|
||||
#endif
|
||||
} AOTModuleInstanceExtra;
|
||||
|
||||
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
|
||||
|
|
|
@ -16,9 +16,14 @@ _invokeNative:
|
|||
push %ebp
|
||||
movl %esp, %ebp
|
||||
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
|
||||
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 */
|
||||
subl %esp, %edx /* edx = edx - esp */
|
||||
1:
|
||||
|
|
|
@ -203,22 +203,12 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
|
|||
char *argv[])
|
||||
{
|
||||
bool ret;
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
WASMCluster *cluster;
|
||||
#endif
|
||||
#if WASM_ENABLE_THREAD_MGR != 0 || WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
WASMExecEnv *exec_env;
|
||||
#endif
|
||||
|
||||
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
|
||||
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
|
||||
if (exec_env) {
|
||||
|
@ -622,22 +612,12 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
|
|||
const char *name, int32 argc, char *argv[])
|
||||
{
|
||||
bool ret;
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
WASMCluster *cluster;
|
||||
#endif
|
||||
#if WASM_ENABLE_THREAD_MGR != 0 || WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
WASMExecEnv *exec_env;
|
||||
#endif
|
||||
|
||||
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
|
||||
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
|
||||
if (exec_env) {
|
||||
|
|
|
@ -276,7 +276,7 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
|
|||
WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
|
||||
|
||||
#ifndef NDEBUG
|
||||
#if WAMR_BUILD_MEMORY_PROFILING != 0
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
#define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM()
|
||||
#else
|
||||
#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 */
|
||||
static wasm_engine_t *singleton_engine = NULL;
|
||||
static wasm_engine_t *singleton_engine;
|
||||
#ifdef os_thread_local_attribute
|
||||
/* categorize wasm_store_t as threads*/
|
||||
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;
|
||||
}
|
||||
|
||||
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 *
|
||||
wasm_exporttype_new(own wasm_byte_vec_t *name,
|
||||
own wasm_externtype_t *extern_type)
|
||||
|
@ -1633,8 +1657,6 @@ wasm_val_to_rt_val(WASMModuleInstanceCommon *inst_comm_rt, uint8 val_type_rt,
|
|||
ret =
|
||||
wasm_externref_obj2ref(inst_comm_rt, v->of.ref, (uint32 *)data);
|
||||
break;
|
||||
#else
|
||||
(void)inst_comm_rt;
|
||||
#endif
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
(void)inst_comm_rt;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2537,12 +2560,12 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
|
|||
|
||||
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) {
|
||||
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) {
|
||||
goto failed;
|
||||
}
|
||||
|
@ -2622,7 +2645,7 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
|
|||
}
|
||||
|
||||
/* 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) {
|
||||
goto failed;
|
||||
}
|
||||
|
@ -3008,6 +3031,20 @@ failed:
|
|||
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
|
||||
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_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);
|
||||
wasm_byte_vec_delete(&message);
|
||||
|
||||
|
@ -3371,6 +3409,25 @@ failed:
|
|||
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 */
|
||||
wasm_global_t *
|
||||
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;
|
||||
WASMMemoryInstance *memory_inst =
|
||||
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
|
||||
|
||||
|
@ -4215,7 +4273,8 @@ wasm_memory_data_size(const wasm_memory_t *memory)
|
|||
AOTMemoryInstance *memory_inst =
|
||||
((AOTMemoryInstance **)
|
||||
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
|
||||
|
||||
|
@ -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;
|
||||
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 */
|
||||
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;
|
||||
else
|
||||
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;
|
||||
|
||||
(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;
|
||||
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),
|
||||
imported_global_interp->u.global.type))
|
||||
return false;
|
||||
|
||||
/* set init value */
|
||||
bh_assert(import->init);
|
||||
switch (wasm_valtype_kind(import->type->val_type)) {
|
||||
case WASM_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;
|
||||
}
|
||||
|
||||
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
|
||||
interp_process_export(wasm_store_t *store,
|
||||
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;
|
||||
bh_assert(import_aot_func);
|
||||
|
||||
/* it is a placeholder and let's skip it*/
|
||||
if (!import->type)
|
||||
return true;
|
||||
|
||||
/* type comparison */
|
||||
if (!wasm_functype_same_internal(import->type, import_aot_func->func_type))
|
||||
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;
|
||||
else
|
||||
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;
|
||||
|
||||
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;
|
||||
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);
|
||||
bh_assert(val_type);
|
||||
|
||||
|
@ -4537,6 +4568,7 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
|
|||
import_aot_global->type))
|
||||
return false;
|
||||
|
||||
bh_assert(import->init);
|
||||
switch (wasm_valtype_kind(val_type)) {
|
||||
case WASM_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_aot_global->is_linked = 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:
|
||||
LOG_DEBUG("%s failed", __FUNCTION__);
|
||||
return false;
|
||||
|
@ -4692,7 +4669,7 @@ aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot,
|
|||
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) {
|
||||
goto failed;
|
||||
}
|
||||
|
@ -4710,6 +4687,95 @@ failed:
|
|||
}
|
||||
#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_new(wasm_store_t *store, const wasm_module_t *module,
|
||||
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));
|
||||
}
|
||||
|
||||
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_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
||||
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 error_buf[256] = { 0 };
|
||||
wasm_instance_t *instance = NULL;
|
||||
WASMModuleInstance *inst_rt;
|
||||
CApiFuncImport *func_import = NULL, **p_func_imports = NULL;
|
||||
uint32 i = 0, import_func_count = 0;
|
||||
uint64 total_size;
|
||||
|
@ -4789,11 +4803,9 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
|||
if (!module)
|
||||
return NULL;
|
||||
|
||||
if (!compare_imports(module, imports)) {
|
||||
snprintf(sub_error_buf, sizeof(sub_error_buf),
|
||||
"Failed to match imports");
|
||||
goto failed;
|
||||
}
|
||||
/*
|
||||
* will do the check at the end of wasm_runtime_instantiate
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* link module and imports */
|
||||
if (imports && imports->num_elems) {
|
||||
bool link = false;
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if ((*module)->module_type == Wasm_Module_Bytecode) {
|
||||
if (!interp_link(instance, MODULE_INTERP(module),
|
||||
(wasm_extern_t **)imports->data)) {
|
||||
/* executes the instantiate-time linking if provided */
|
||||
if (imports) {
|
||||
if (!do_link(instance, module, imports)) {
|
||||
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
|
||||
* will do the linking result check at the end of wasm_runtime_instantiate
|
||||
*/
|
||||
if (!link) {
|
||||
snprintf(sub_error_buf, sizeof(sub_error_buf),
|
||||
"Failed to verify import count");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
instance->inst_comm_rt = wasm_runtime_instantiate(
|
||||
*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 */
|
||||
inst_rt = (WASMModuleInstance *)instance->inst_comm_rt;
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||
p_func_imports = &inst_rt->e->c_api_func_imports;
|
||||
import_func_count = inst_rt->module->import_function_count;
|
||||
WASMModuleInstanceExtra *e =
|
||||
((WASMModuleInstance *)instance->inst_comm_rt)->e;
|
||||
p_func_imports = &(e->c_api_func_imports);
|
||||
import_func_count = MODULE_INTERP(module)->import_function_count;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||
p_func_imports =
|
||||
&((AOTModuleInstanceExtra *)inst_rt->e)->c_api_func_imports;
|
||||
import_func_count = ((AOTModule *)inst_rt->module)->import_func_count;
|
||||
AOTModuleInstanceExtra *e =
|
||||
(AOTModuleInstanceExtra *)((AOTModuleInstance *)
|
||||
instance->inst_comm_rt)
|
||||
->e;
|
||||
p_func_imports = &(e->c_api_func_imports);
|
||||
import_func_count = MODULE_AOT(module)->import_func_count;
|
||||
}
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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++) {
|
||||
wasm_func_t *func_host;
|
||||
wasm_extern_t *in;
|
||||
wasm_func_t *func_host = NULL;
|
||||
wasm_extern_t *in = imports->data[i];
|
||||
bh_assert(in);
|
||||
|
||||
in = imports->data[i];
|
||||
if (wasm_extern_kind(in) != WASM_EXTERN_FUNC)
|
||||
continue;
|
||||
|
||||
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;
|
||||
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->env_arg = NULL;
|
||||
}
|
||||
bh_assert(func_import->func_ptr_linked);
|
||||
|
||||
func_import++;
|
||||
}
|
||||
|
@ -4906,6 +4902,8 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
|||
/* fill with inst */
|
||||
for (i = 0; imports && imports->data && i < imports->num_elems; ++i) {
|
||||
wasm_extern_t *import = imports->data[i];
|
||||
bh_assert(import);
|
||||
|
||||
switch (import->kind) {
|
||||
case WASM_EXTERN_FUNC:
|
||||
wasm_extern_as_func(import)->inst_comm_rt =
|
||||
|
@ -5001,7 +4999,7 @@ failed:
|
|||
sub_error_buf);
|
||||
if (trap != NULL) {
|
||||
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);
|
||||
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)
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -172,15 +172,18 @@ void
|
|||
wasm_exec_env_destroy(WASMExecEnv *exec_env)
|
||||
{
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
/* Terminate all sub-threads */
|
||||
/* Wait for all sub-threads */
|
||||
WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
|
||||
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
|
||||
/* Must fire exit event after other threads exits, otherwise
|
||||
the stopped thread will be overrided by other threads */
|
||||
wasm_cluster_thread_exited(exec_env);
|
||||
#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);
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_THREAD_MGR */
|
||||
|
@ -205,9 +208,17 @@ void
|
|||
wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
|
||||
{
|
||||
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->native_stack_boundary =
|
||||
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
|
||||
|
|
|
@ -84,6 +84,12 @@ typedef struct WASMExecEnv {
|
|||
void **native_symbol;
|
||||
#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
|
||||
/**
|
||||
* Cache for
|
||||
|
@ -165,6 +171,17 @@ typedef struct WASMExecEnv {
|
|||
} wasm_stack;
|
||||
} 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 *
|
||||
wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
|
||||
uint32 stack_size);
|
||||
|
@ -179,6 +196,13 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
|
|||
void
|
||||
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.
|
||||
*
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
#include "bh_platform.h"
|
||||
#include "mem_alloc.h"
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
#include "../common/wasm_shared_memory.h"
|
||||
#endif
|
||||
|
||||
typedef enum Memory_Mode {
|
||||
MEMORY_MODE_UNKNOWN = 0,
|
||||
MEMORY_MODE_POOL,
|
||||
|
@ -506,7 +510,7 @@ wasm_get_default_memory(WASMModuleInstance *module_inst)
|
|||
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
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);
|
||||
uint8 *memory_data_old, *memory_data_new, *heap_data_old;
|
||||
|
@ -624,7 +628,7 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
|
|||
}
|
||||
#else
|
||||
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);
|
||||
uint32 num_bytes_per_page, total_size_old;
|
||||
|
@ -697,3 +701,59 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
|
|||
return true;
|
||||
}
|
||||
#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
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "bh_common.h"
|
||||
#include "../include/wasm_export.h"
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -23,6 +24,16 @@ wasm_runtime_memory_destroy();
|
|||
unsigned
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -53,6 +53,17 @@ uint32
|
|||
get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
|
||||
#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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* allow func_type and all outputs, like p_signature, p_attachment and
|
||||
* p_call_conv_raw to be NULL
|
||||
*/
|
||||
void *
|
||||
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
||||
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;
|
||||
}
|
||||
|
||||
if (!p_signature || !p_attachment || !p_call_conv_raw)
|
||||
return func_ptr;
|
||||
|
||||
if (func_ptr) {
|
||||
if (signature && signature[0] != '\0') {
|
||||
/* 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
|
||||
/* Output warning except running aot compiler */
|
||||
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_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 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;
|
||||
uint32 n_native_symbols;
|
||||
#endif
|
||||
|
@ -438,6 +456,17 @@ wasm_native_init()
|
|||
goto fail;
|
||||
#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
|
||||
n_native_symbols = get_libc_emcc_export_apis(&native_symbols);
|
||||
if (n_native_symbols > 0
|
||||
|
@ -458,7 +487,7 @@ wasm_native_init()
|
|||
n_native_symbols = get_wasi_nn_export_apis(&native_symbols);
|
||||
if (!wasm_native_register_natives("wasi_nn", native_symbols,
|
||||
n_native_symbols))
|
||||
return false;
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -466,7 +495,7 @@ wasm_native_init()
|
|||
|| WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \
|
||||
|| WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 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:
|
||||
wasm_native_destroy();
|
||||
return false;
|
||||
|
@ -482,6 +511,10 @@ wasm_native_destroy()
|
|||
lib_pthread_destroy();
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIB_WASI_THREADS != 0
|
||||
lib_wasi_threads_destroy();
|
||||
#endif
|
||||
|
||||
node = g_native_symbols_list;
|
||||
while (node) {
|
||||
node_next = node->next;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "bh_common.h"
|
||||
#include "bh_assert.h"
|
||||
#include "bh_log.h"
|
||||
#include "wasm_native.h"
|
||||
#include "wasm_runtime_common.h"
|
||||
#include "wasm_memory.h"
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
|
@ -128,6 +129,12 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
|
|||
static JitCompOptions jit_options = { 0 };
|
||||
#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
|
||||
/* The exec_env of thread local storage, set before calling function
|
||||
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
|
||||
&& (uint8 *)sig_addr
|
||||
< 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);
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +250,7 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
|
|||
else if (exec_env_tls->exce_check_guard_page <= (uint8 *)sig_addr
|
||||
&& (uint8 *)sig_addr
|
||||
< 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) {
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
@ -514,6 +521,20 @@ wasm_runtime_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
|
||||
wasm_runtime_full_init(RuntimeInitArgs *init_args)
|
||||
{
|
||||
|
@ -521,10 +542,20 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
|
|||
&init_args->mem_alloc_option))
|
||||
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
|
||||
jit_options.code_cache_size = init_args->fast_jit_code_cache_size;
|
||||
#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()) {
|
||||
wasm_runtime_memory_destroy();
|
||||
return false;
|
||||
|
@ -554,6 +585,47 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
|
|||
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
|
||||
get_package_type(const uint8 *buf, uint32 size)
|
||||
{
|
||||
|
@ -1171,6 +1243,41 @@ wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
|
|||
#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
|
||||
wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
|
@ -1399,6 +1506,22 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env)
|
|||
else
|
||||
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);
|
||||
}
|
||||
#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
|
||||
|
@ -1743,6 +1866,33 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
|
|||
}
|
||||
#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
|
||||
wasm_runtime_call_wasm(WASMExecEnv *exec_env,
|
||||
WASMFunctionInstanceCommon *function, uint32 argc,
|
||||
|
@ -1783,11 +1933,16 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
|
|||
param_argc, new_argv);
|
||||
#endif
|
||||
if (!ret) {
|
||||
if (clear_wasi_proc_exit_exception(exec_env->module_inst)) {
|
||||
ret = true;
|
||||
}
|
||||
else {
|
||||
if (new_argv != argv) {
|
||||
wasm_runtime_free(new_argv);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
if (!wasm_runtime_finalize_call_function(exec_env, function, new_argv,
|
||||
|
@ -2150,12 +2305,42 @@ wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm)
|
|||
void
|
||||
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),
|
||||
"Exception: %s", exception);
|
||||
else
|
||||
}
|
||||
else {
|
||||
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 */
|
||||
static const char *exception_msgs[] = {
|
||||
|
@ -2176,9 +2361,7 @@ static const char *exception_msgs[] = {
|
|||
"wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
|
||||
"out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
|
||||
"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 */
|
||||
#endif
|
||||
"", /* EXCE_ALREADY_THROWN */
|
||||
};
|
||||
/* clang-format on */
|
||||
|
@ -2201,6 +2384,36 @@ wasm_get_exception(WASMModuleInstance *module_inst)
|
|||
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
|
||||
wasm_runtime_set_exception(WASMModuleInstanceCommon *module_inst_comm,
|
||||
const char *exception)
|
||||
|
@ -2222,6 +2435,17 @@ wasm_runtime_get_exception(WASMModuleInstanceCommon *module_inst_comm)
|
|||
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
|
||||
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:
|
||||
if (argv1 != argv_buf)
|
||||
|
@ -3620,7 +3844,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
|||
}
|
||||
exec_env->attachment = NULL;
|
||||
|
||||
ret = !wasm_runtime_get_exception(module) ? true : false;
|
||||
ret = !wasm_runtime_copy_exception(module, NULL);
|
||||
|
||||
fail:
|
||||
if (argv1 != argv_buf)
|
||||
|
@ -3834,7 +4058,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
|||
}
|
||||
exec_env->attachment = NULL;
|
||||
|
||||
ret = !wasm_runtime_get_exception(module) ? true : false;
|
||||
ret = !wasm_runtime_copy_exception(module, NULL);
|
||||
|
||||
fail:
|
||||
if (argv1 != argv_buf)
|
||||
|
@ -4161,7 +4385,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
|||
}
|
||||
exec_env->attachment = NULL;
|
||||
|
||||
ret = !wasm_runtime_get_exception(module) ? true : false;
|
||||
ret = !wasm_runtime_copy_exception(module, NULL);
|
||||
fail:
|
||||
if (argv1 != argv_buf)
|
||||
wasm_runtime_free(argv1);
|
||||
|
@ -4176,9 +4400,11 @@ fail:
|
|||
|| defined(BUILD_TARGET_RISCV64_LP64) */
|
||||
|
||||
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[])
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (!wasm_runtime_exec_env_check(exec_env)) {
|
||||
LOG_ERROR("Invalid exec env stack info.");
|
||||
return false;
|
||||
|
@ -4190,13 +4416,18 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_indices,
|
|||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
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
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
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
|
||||
return false;
|
||||
|
||||
if (!ret && clear_wasi_proc_exit_exception(exec_env->module_inst)) {
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -5155,3 +5386,24 @@ wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
|
|||
*minor = WAMR_VERSION_MINOR;
|
||||
*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
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Internal use for setting default running mode */
|
||||
#define Mode_Default 0
|
||||
|
||||
#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
|
||||
|
||||
#define PUT_I64_TO_ADDR(addr, value) \
|
||||
|
@ -413,6 +416,13 @@ typedef struct wasm_frame_t {
|
|||
const char *func_name_wp;
|
||||
} WASMCApiFrame;
|
||||
|
||||
#ifdef WASM_ENABLE_JIT
|
||||
typedef struct LLVMJITOptions {
|
||||
uint32 opt_level;
|
||||
uint32 size_level;
|
||||
} LLVMJITOptions;
|
||||
#endif
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
/* Signal info passing to interp/aot signal handler */
|
||||
typedef struct WASMSignalInfo {
|
||||
|
@ -437,10 +447,28 @@ wasm_runtime_get_exec_env_tls(void);
|
|||
WASM_RUNTIME_API_EXTERN bool
|
||||
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 */
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
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 */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_destroy(void);
|
||||
|
@ -484,6 +512,15 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size,
|
|||
uint32 heap_size, char *error_buf,
|
||||
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 */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
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_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
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN uint32
|
||||
|
@ -589,27 +631,6 @@ WASM_RUNTIME_API_EXTERN uint32
|
|||
wasm_runtime_start_debug_instance(WASMExecEnv *exec_env);
|
||||
#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
|
||||
wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
|
||||
|
||||
|
@ -956,6 +977,14 @@ void
|
|||
wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list);
|
||||
#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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -30,8 +30,14 @@ typedef struct AtomicWaitNode {
|
|||
korp_cond wait_cond;
|
||||
} AtomicWaitNode;
|
||||
|
||||
typedef struct AtomicWaitAddressArgs {
|
||||
uint32 index;
|
||||
void **addr;
|
||||
} AtomicWaitAddressArgs;
|
||||
|
||||
/* Atomic wait map */
|
||||
static HashMap *wait_map;
|
||||
static korp_mutex wait_map_lock;
|
||||
|
||||
static uint32
|
||||
wait_address_hash(void *address);
|
||||
|
@ -47,11 +53,18 @@ wasm_shared_memory_init()
|
|||
{
|
||||
if (os_mutex_init(&shared_memory_list_lock) != 0)
|
||||
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 */
|
||||
if (!(wait_map = bh_hash_map_create(32, true, (HashFunc)wait_address_hash,
|
||||
(KeyEqualFunc)wait_address_equal, NULL,
|
||||
destroy_wait_info))) {
|
||||
os_mutex_destroy(&shared_memory_list_lock);
|
||||
os_mutex_destroy(&wait_map_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -62,6 +75,7 @@ void
|
|||
wasm_shared_memory_destroy()
|
||||
{
|
||||
os_mutex_destroy(&shared_memory_list_lock);
|
||||
os_mutex_destroy(&wait_map_lock);
|
||||
if (wait_map) {
|
||||
bh_hash_map_destroy(wait_map);
|
||||
}
|
||||
|
@ -87,6 +101,61 @@ search_module(WASMModuleCommon *module)
|
|||
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 *
|
||||
wasm_module_get_shared_memory(WASMModuleCommon *module)
|
||||
{
|
||||
|
@ -97,13 +166,13 @@ int32
|
|||
shared_memory_inc_reference(WASMModuleCommon *module)
|
||||
{
|
||||
WASMSharedMemNode *node = search_module(module);
|
||||
uint32 ref_count = -1;
|
||||
if (node) {
|
||||
os_mutex_lock(&node->lock);
|
||||
node->ref_count++;
|
||||
ref_count = ++node->ref_count;
|
||||
os_mutex_unlock(&node->lock);
|
||||
return node->ref_count;
|
||||
}
|
||||
return -1;
|
||||
return ref_count;
|
||||
}
|
||||
|
||||
int32
|
||||
|
@ -120,6 +189,7 @@ shared_memory_dec_reference(WASMModuleCommon *module)
|
|||
bh_list_remove(shared_memory_list, node);
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
|
||||
os_mutex_destroy(&node->shared_mem_lock);
|
||||
os_mutex_destroy(&node->lock);
|
||||
wasm_runtime_free(node);
|
||||
}
|
||||
|
@ -148,7 +218,14 @@ shared_memory_set_memory_inst(WASMModuleCommon *module,
|
|||
node->module = module;
|
||||
node->memory_inst = memory;
|
||||
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) {
|
||||
os_mutex_destroy(&node->shared_mem_lock);
|
||||
wasm_runtime_free(node);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -208,9 +285,11 @@ notify_wait_list(bh_list *wait_list, uint32 count)
|
|||
bh_assert(node);
|
||||
next = bh_list_elem_next(node);
|
||||
|
||||
os_mutex_lock(&node->wait_lock);
|
||||
node->status = S_NOTIFIED;
|
||||
/* wakeup */
|
||||
os_cond_signal(&node->wait_cond);
|
||||
os_mutex_unlock(&node->wait_lock);
|
||||
|
||||
node = next;
|
||||
}
|
||||
|
@ -224,13 +303,13 @@ acquire_wait_info(void *address, bool create)
|
|||
AtomicWaitInfo *wait_info = NULL;
|
||||
bh_list_status ret;
|
||||
|
||||
os_mutex_lock(&shared_memory_list_lock);
|
||||
os_mutex_lock(&wait_map_lock); /* Make find + insert atomic */
|
||||
|
||||
if (address)
|
||||
wait_info = (AtomicWaitInfo *)bh_hash_map_find(wait_map, address);
|
||||
|
||||
if (!create) {
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
os_mutex_unlock(&wait_map_lock);
|
||||
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);
|
||||
(void)ret;
|
||||
|
@ -270,7 +349,7 @@ fail2:
|
|||
wasm_runtime_free(wait_info);
|
||||
|
||||
fail1:
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
os_mutex_unlock(&wait_map_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -297,17 +376,16 @@ destroy_wait_info(void *wait_info)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
release_wait_info(HashMap *wait_map_, AtomicWaitInfo *wait_info, void *address)
|
||||
static bool
|
||||
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) {
|
||||
bh_hash_map_remove(wait_map_, address, NULL, NULL);
|
||||
destroy_wait_info(wait_info);
|
||||
if (wait_info->wait_list->len > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
os_mutex_unlock(&shared_memory_list_lock);
|
||||
bh_hash_map_remove(wait_map_, address, NULL, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32
|
||||
|
@ -317,11 +395,16 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
|||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
|
||||
AtomicWaitInfo *wait_info;
|
||||
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
|
||||
|| module->module_type == Wasm_Module_AoT);
|
||||
|
||||
if (wasm_copy_exception(module_inst, NULL)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Currently we have only one memory instance */
|
||||
if (!module_inst->memories[0]->is_shared) {
|
||||
wasm_runtime_set_exception(module, "expected shared memory");
|
||||
|
@ -343,11 +426,13 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
|||
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)
|
||||
|| (wait64 && *(uint64 *)address != expect)) {
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
if (no_wait) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
|
@ -355,33 +440,29 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
|||
|
||||
if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) {
|
||||
wasm_runtime_set_exception(module, "failed to create wait node");
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
return -1;
|
||||
}
|
||||
memset(wait_node, 0, sizeof(AtomicWaitNode));
|
||||
|
||||
if (0 != os_mutex_init(&wait_node->wait_lock)) {
|
||||
wasm_runtime_free(wait_node);
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != os_cond_init(&wait_node->wait_cond)) {
|
||||
os_mutex_destroy(&wait_node->wait_lock);
|
||||
wasm_runtime_free(wait_node);
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wait_node->status = S_WAITING;
|
||||
|
||||
os_mutex_lock(&wait_info->wait_list_lock);
|
||||
ret = bh_list_insert(wait_info->wait_list, wait_node);
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
bh_assert(ret == BH_LIST_SUCCESS);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
|
||||
/* condition wait start */
|
||||
os_mutex_lock(&wait_node->wait_lock);
|
||||
|
||||
|
@ -389,22 +470,27 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
|||
timeout < 0 ? BHT_WAIT_FOREVER
|
||||
: (uint64)timeout / 1000);
|
||||
|
||||
is_timeout = wait_node->status == S_WAITING ? true : false;
|
||||
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);
|
||||
|
||||
check_ret = is_wait_node_exists(wait_info->wait_list, wait_node);
|
||||
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);
|
||||
os_mutex_destroy(&wait_node->wait_lock);
|
||||
os_cond_destroy(&wait_node->wait_cond);
|
||||
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;
|
||||
return is_timeout ? 2 : 0;
|
||||
|
@ -417,12 +503,22 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
|
|||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
|
||||
uint32 notify_result;
|
||||
AtomicWaitInfo *wait_info;
|
||||
WASMSharedMemNode *node;
|
||||
bool out_of_bounds;
|
||||
|
||||
bh_assert(module->module_type == Wasm_Module_Bytecode
|
||||
|| module->module_type == Wasm_Module_AoT);
|
||||
|
||||
if ((uint8 *)address < module_inst->memories[0]->memory_data
|
||||
|| (uint8 *)address + 4 > module_inst->memories[0]->memory_data_end) {
|
||||
node = search_module((WASMModuleCommon *)module_inst->module);
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
|
@ -430,12 +526,18 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
|
|||
wait_info = acquire_wait_info(address, false);
|
||||
|
||||
/* Nobody wait on this address */
|
||||
if (!wait_info)
|
||||
if (!wait_info) {
|
||||
if (node)
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
os_mutex_lock(&wait_info->wait_list_lock);
|
||||
notify_result = notify_wait_list(wait_info->wait_list, count);
|
||||
os_mutex_unlock(&wait_info->wait_list_lock);
|
||||
|
||||
if (node)
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
|
||||
return notify_result;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ typedef struct WASMSharedMemNode {
|
|||
WASMModuleCommon *module;
|
||||
/* The memory information */
|
||||
WASMMemoryInstanceCommon *memory_inst;
|
||||
/* Lock used for atomic operations */
|
||||
korp_mutex shared_mem_lock;
|
||||
|
||||
/* reference count */
|
||||
uint32 ref_count;
|
||||
|
@ -37,6 +39,9 @@ wasm_shared_memory_init();
|
|||
void
|
||||
wasm_shared_memory_destroy();
|
||||
|
||||
void
|
||||
notify_stale_threads_on_exception(WASMModuleInstanceCommon *module);
|
||||
|
||||
WASMSharedMemNode *
|
||||
wasm_module_get_shared_memory(WASMModuleCommon *module);
|
||||
|
||||
|
|
|
@ -149,6 +149,7 @@ typedef struct AOTImportGlobal {
|
|||
uint32 data_offset;
|
||||
/* global data after linked */
|
||||
WASMValue global_data_linked;
|
||||
bool is_linked;
|
||||
} AOTImportGlobal;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1240,6 +1240,8 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
|||
case WASM_OP_ATOMIC_FENCE:
|
||||
/* Skip memory index */
|
||||
frame_ip++;
|
||||
if (!aot_compiler_op_atomic_fence(comp_ctx, func_ctx))
|
||||
return false;
|
||||
break;
|
||||
case WASM_OP_ATOMIC_I32_LOAD:
|
||||
bytes = 4;
|
||||
|
|
|
@ -259,6 +259,7 @@ check_type_compatible(uint8 src_type, uint8 dst_type)
|
|||
#define I32_SIX LLVM_CONST(i32_six)
|
||||
#define I32_SEVEN LLVM_CONST(i32_seven)
|
||||
#define I32_EIGHT LLVM_CONST(i32_eight)
|
||||
#define I32_NINE LLVM_CONST(i32_nine)
|
||||
#define I32_NEG_ONE LLVM_CONST(i32_neg_one)
|
||||
#define I64_NEG_ONE LLVM_CONST(i64_neg_one)
|
||||
#define I32_MIN LLVM_CONST(i32_min)
|
||||
|
|
|
@ -9,6 +9,36 @@
|
|||
#include "../aot/aot_intrinsic.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
|
||||
trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
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;
|
||||
LLVMValueRef is_less, is_greater, res;
|
||||
|
||||
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, 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");
|
||||
}
|
||||
res = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_UNO, LLVMRealUNO,
|
||||
operand, operand, src_type, "fcmp_is_nan");
|
||||
|
||||
if (!res) {
|
||||
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)))
|
||||
goto fail;
|
||||
|
||||
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, 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");
|
||||
}
|
||||
call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_LE, LLVMRealOLE, operand,
|
||||
min_value, src_type, "fcmp_min_value");
|
||||
|
||||
if (!is_less) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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, 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");
|
||||
}
|
||||
is_greater =
|
||||
call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_GE, LLVMRealOGE, operand,
|
||||
max_value, src_type, "fcmp_min_value");
|
||||
|
||||
if (!is_greater) {
|
||||
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 vmin, vmax;
|
||||
|
||||
if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, operand, operand,
|
||||
"fcmp_is_nan"))) {
|
||||
if (!(res =
|
||||
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.");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -212,8 +189,9 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* Start to translate check_nan_succ block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_nan_succ);
|
||||
if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand,
|
||||
min_value, "fcmp_min_value"))) {
|
||||
if (!(is_less = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_LE,
|
||||
LLVMRealOLE, operand, min_value,
|
||||
src_type, "fcmp_min_value"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -232,8 +210,9 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* Start to translate check_less_succ block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_less_succ);
|
||||
if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand,
|
||||
max_value, "fcmp_max_value"))) {
|
||||
if (!(is_greater = call_fcmp_intrinsic(comp_ctx, func_ctx, FLOAT_GE,
|
||||
LLVMRealOGE, operand, max_value,
|
||||
src_type, "fcmp_max_value"))) {
|
||||
aot_set_last_error("llvm build fcmp failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -366,6 +366,87 @@ fail:
|
|||
#endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 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
|
||||
check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
uint32 callee_cell_num)
|
||||
|
@ -409,6 +490,19 @@ check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
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,
|
||||
* if no, throw exception
|
||||
|
@ -852,8 +946,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
callee_cell_num =
|
||||
aot_func->param_cell_num + aot_func->local_cell_num + 1;
|
||||
|
||||
if (comp_ctx->enable_stack_bound_check
|
||||
&& !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
|
||||
if (!check_stack(comp_ctx, func_ctx, callee_cell_num))
|
||||
goto fail;
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 14
|
||||
|
@ -906,6 +999,14 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
#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;
|
||||
fail:
|
||||
if (param_types)
|
||||
|
@ -1467,8 +1568,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
/* Translate call non-import block */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import);
|
||||
|
||||
if (comp_ctx->enable_stack_bound_check
|
||||
&& !check_stack_boundary(comp_ctx, func_ctx,
|
||||
if (!check_stack(comp_ctx, func_ctx,
|
||||
param_cell_num + ext_cell_num
|
||||
+ 1
|
||||
/* Reserve some local variables */
|
||||
|
@ -1553,6 +1653,14 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
#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;
|
||||
|
||||
fail:
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "aot_emit_exception.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
#include "aot_intrinsic.h"
|
||||
#include "aot_emit_control.h"
|
||||
|
||||
#define BUILD_ICMP(op, left, right, res, name) \
|
||||
do { \
|
||||
|
@ -1344,7 +1345,7 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
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_success, "wait_success");
|
||||
|
@ -1368,6 +1369,14 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
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;
|
||||
fail:
|
||||
return false;
|
||||
|
@ -1414,4 +1423,13 @@ fail:
|
|||
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 */
|
||||
|
|
|
@ -97,6 +97,10 @@ bool
|
|||
aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx, uint32 align,
|
||||
uint32 offset, uint32 bytes);
|
||||
|
||||
bool
|
||||
aot_compiler_op_atomic_fence(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -286,6 +286,21 @@ create_native_stack_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
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
|
||||
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) {
|
||||
func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count
|
||||
+ 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)) {
|
||||
goto fail;
|
||||
}
|
||||
if (comp_ctx->enable_stack_estimation
|
||||
&& !create_native_stack_top_min(comp_ctx, func_ctx)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Get auxiliary stack info */
|
||||
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)
|
||||
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->size_level = option->size_level;
|
||||
|
||||
|
|
|
@ -163,6 +163,7 @@ typedef struct AOTFuncContext {
|
|||
LLVMValueRef aot_inst;
|
||||
LLVMValueRef argv_buf;
|
||||
LLVMValueRef native_stack_bound;
|
||||
LLVMValueRef native_stack_top_min_addr;
|
||||
LLVMValueRef aux_stack_bound;
|
||||
LLVMValueRef aux_stack_bottom;
|
||||
LLVMValueRef native_symbol;
|
||||
|
@ -313,6 +314,9 @@ typedef struct AOTCompContext {
|
|||
/* Native stack bounday Check */
|
||||
bool enable_stack_bound_check;
|
||||
|
||||
/* Native stack usage estimation */
|
||||
bool enable_stack_estimation;
|
||||
|
||||
/* 128-bit SIMD */
|
||||
bool enable_simd;
|
||||
|
||||
|
@ -403,6 +407,7 @@ typedef struct AOTCompOption {
|
|||
bool enable_aux_stack_frame;
|
||||
bool disable_llvm_intrinsics;
|
||||
bool disable_llvm_lto;
|
||||
bool enable_stack_estimation;
|
||||
uint32 opt_level;
|
||||
uint32 size_level;
|
||||
uint32 output_format;
|
||||
|
|
|
@ -135,7 +135,8 @@ check_and_seek(JitCompContext *cc, JitReg addr, uint32 offset, uint32 bytes)
|
|||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
/* ---------- check ---------- */
|
||||
/* 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;
|
||||
uint32 cur_page_count_offset =
|
||||
(uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
|
||||
|
@ -176,6 +177,18 @@ fail:
|
|||
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
|
||||
jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset,
|
||||
uint32 bytes, bool sign, bool atomic)
|
||||
|
@ -779,6 +792,51 @@ bool
|
|||
jit_compile_op_atomic_wait(JitCompContext *cc, uint8 op_type, uint32 align,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -786,6 +844,39 @@ bool
|
|||
jit_compiler_op_atomic_notify(JitCompContext *cc, uint32 align, uint32 offset,
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -56,9 +56,31 @@ jit_code_cache_free(void *ptr)
|
|||
bool
|
||||
jit_pass_register_jitted_code(JitCompContext *cc)
|
||||
{
|
||||
uint32 jit_func_idx =
|
||||
cc->cur_wasm_func_idx - cc->cur_wasm_module->import_function_count;
|
||||
cc->cur_wasm_module->fast_jit_func_ptrs[jit_func_idx] =
|
||||
cc->cur_wasm_func->fast_jit_jitted_code = cc->jitted_addr_begin;
|
||||
WASMModuleInstance *instance;
|
||||
WASMModule *module = cc->cur_wasm_module;
|
||||
WASMFunction *func = cc->cur_wasm_func;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -157,8 +157,16 @@ jit_compiler_compile(WASMModule *module, uint32 func_idx)
|
|||
/* Apply compiler passes */
|
||||
if (!apply_compiler_passes(cc) || 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",
|
||||
last_error ? last_error : "unknown error");
|
||||
#endif
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -259,11 +269,13 @@ jit_compiler_set_llvm_jit_func_ptr(WASMModule *module, uint32 func_idx,
|
|||
WASMModuleInstance *instance;
|
||||
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);
|
||||
|
||||
module->func_ptrs[i] = func_ptr;
|
||||
|
||||
instance = module->instance_list;
|
||||
while (instance) {
|
||||
if (instance->e->running_mode == Mode_Multi_Tier_JIT)
|
||||
instance->func_ptrs[func_idx] = func_ptr;
|
||||
instance = instance->e->next;
|
||||
}
|
||||
|
|
|
@ -841,7 +841,7 @@ init_func_translation(JitCompContext *cc)
|
|||
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
|
||||
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->jitted_return_address_offset =
|
||||
offsetof(WASMInterpFrame, jitted_return_addr);
|
||||
|
|
|
@ -560,6 +560,7 @@ address_of_const(JitCompContext *cc, JitReg reg, unsigned size)
|
|||
unsigned no = jit_reg_no(reg);
|
||||
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]);
|
||||
|
||||
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 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]);
|
||||
|
||||
return cc->_const_val._next[kind][idx];
|
||||
|
|
|
@ -1688,6 +1688,7 @@ jit_cc_is_hreg(JitCompContext *cc, JitReg reg)
|
|||
unsigned kind = jit_reg_kind(reg);
|
||||
unsigned no = jit_reg_no(reg);
|
||||
bh_assert(jit_reg_is_variable(reg));
|
||||
bh_assert(kind < JIT_REG_KIND_L32);
|
||||
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 no = jit_reg_no(reg);
|
||||
bh_assert(jit_cc_is_hreg(cc, reg));
|
||||
bh_assert(kind < JIT_REG_KIND_L32);
|
||||
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 no = jit_reg_no(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];
|
||||
}
|
||||
|
||||
|
@ -1739,6 +1742,7 @@ jit_cc_is_hreg_caller_saved_jitted(JitCompContext *cc, JitReg reg)
|
|||
unsigned kind = jit_reg_kind(reg);
|
||||
unsigned no = jit_reg_no(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];
|
||||
}
|
||||
|
||||
|
|
|
@ -156,6 +156,7 @@ rc_get_vr(RegallocContext *rc, JitReg vreg)
|
|||
unsigned no = jit_reg_no(vreg);
|
||||
|
||||
bh_assert(jit_reg_is_variable(vreg));
|
||||
bh_assert(kind < JIT_REG_KIND_L32);
|
||||
|
||||
return &rc->vregs[kind][no];
|
||||
}
|
||||
|
@ -175,6 +176,7 @@ rc_get_hr(RegallocContext *rc, JitReg hreg)
|
|||
unsigned no = jit_reg_no(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];
|
||||
}
|
||||
|
@ -208,7 +210,9 @@ static unsigned
|
|||
get_reg_stride(JitReg reg)
|
||||
{
|
||||
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)
|
||||
{
|
||||
const int kind = jit_reg_kind(vreg);
|
||||
const HardReg *hregs = rc->hregs[kind];
|
||||
const unsigned hreg_num = jit_cc_hreg_num(rc->cc, kind);
|
||||
const HardReg *hregs;
|
||||
unsigned hreg_num;
|
||||
JitReg hreg, vreg_to_reload = 0;
|
||||
int min_distance = distance, vr_distance;
|
||||
VirtualReg *vr = rc_get_vr(rc, vreg);
|
||||
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)
|
||||
/* Unsupported hard register kind. */
|
||||
{
|
||||
|
|
|
@ -55,6 +55,7 @@ typedef struct AOTCompOption {
|
|||
bool enable_aux_stack_frame;
|
||||
bool disable_llvm_intrinsics;
|
||||
bool disable_llvm_lto;
|
||||
bool enable_stack_estimation;
|
||||
uint32_t opt_level;
|
||||
uint32_t size_level;
|
||||
uint32_t output_format;
|
||||
|
|
|
@ -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_name(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
|
||||
|
@ -797,6 +798,9 @@ static inline void* wasm_val_ptr(const wasm_val_t* val) {
|
|||
|
||||
#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
|
||||
|
|
|
@ -131,6 +131,14 @@ typedef struct mem_alloc_info_t {
|
|||
uint32_t highmark_size;
|
||||
} 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 */
|
||||
typedef struct RuntimeInitArgs {
|
||||
mem_alloc_type_t mem_alloc_type;
|
||||
|
@ -152,6 +160,13 @@ typedef struct RuntimeInitArgs {
|
|||
|
||||
/* 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;
|
||||
|
||||
#ifndef WASM_VALKIND_T_DEFINED
|
||||
|
@ -195,9 +210,9 @@ WASM_RUNTIME_API_EXTERN bool
|
|||
wasm_runtime_init(void);
|
||||
|
||||
/**
|
||||
* Initialize the WASM runtime environment, and also initialize
|
||||
* the memory allocator and register native symbols, which are specified
|
||||
* with init arguments
|
||||
* Initialize the WASM runtime environment, WASM running mode,
|
||||
* and also initialize the memory allocator and register native symbols,
|
||||
* which are specified with init arguments
|
||||
*
|
||||
* @param init_args specifies the init arguments
|
||||
*
|
||||
|
@ -206,6 +221,28 @@ wasm_runtime_init(void);
|
|||
WASM_RUNTIME_API_EXTERN bool
|
||||
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.
|
||||
*/
|
||||
|
@ -450,6 +487,34 @@ wasm_runtime_instantiate(const wasm_module_t module,
|
|||
uint32_t stack_size, uint32_t heap_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.
|
||||
*
|
||||
|
@ -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_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
|
||||
* 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_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 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -278,9 +278,14 @@ struct WASMFunction {
|
|||
#endif
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
/* The compiled fast jit jitted code block of this function */
|
||||
void *fast_jit_jitted_code;
|
||||
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
|
||||
/* The compiled llvm jit func ptr of this function */
|
||||
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
|
||||
};
|
||||
|
@ -506,14 +511,13 @@ struct WASMModule {
|
|||
#endif
|
||||
|
||||
#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)
|
||||
/**
|
||||
* List of instances referred to this module. When source debugging
|
||||
* feature is enabled, the debugger may modify the code section of
|
||||
* the module, so we need to report a warning if user create several
|
||||
* instances based on the same module. Sub instances created by
|
||||
* lib-pthread or spawn API won't be added into the list.
|
||||
* instances based on the same module.
|
||||
*
|
||||
* 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
|
||||
|
@ -533,7 +537,22 @@ struct WASMModule {
|
|||
#endif
|
||||
|
||||
#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;
|
||||
/* locks for Fast JIT lazy compilation */
|
||||
korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM];
|
||||
|
@ -543,7 +562,16 @@ struct WASMModule {
|
|||
#if WASM_ENABLE_JIT != 0
|
||||
struct AOTCompData *comp_data;
|
||||
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;
|
||||
/* whether the func pointers are compiled */
|
||||
bool *func_ptrs_compiled;
|
||||
|
@ -568,6 +596,12 @@ struct WASMModule {
|
|||
korp_tid llvm_jit_init_thread;
|
||||
/* whether the llvm jit is initialized */
|
||||
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
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "wasm_runtime.h"
|
||||
#include "wasm_opcode.h"
|
||||
#include "wasm_loader.h"
|
||||
#include "wasm_memory.h"
|
||||
#include "../common/wasm_exec_env.h"
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
#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_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint32)(*(uint8 *)maddr); \
|
||||
*(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) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint32)LOAD_U16(maddr); \
|
||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
} \
|
||||
else { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = LOAD_I32(maddr); \
|
||||
STORE_U32(maddr, readv op sval); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
} \
|
||||
PUSH_I32(readv); \
|
||||
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_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint64)(*(uint8 *)maddr); \
|
||||
*(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) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint64)LOAD_U16(maddr); \
|
||||
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) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint64)LOAD_U32(maddr); \
|
||||
STORE_U32(maddr, (uint32)(readv op sval)); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
} \
|
||||
else { \
|
||||
uint64 op_result; \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint64)LOAD_I64(maddr); \
|
||||
op_result = readv op sval; \
|
||||
STORE_I64(maddr, op_result); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
} \
|
||||
PUSH_I64(readv); \
|
||||
break; \
|
||||
|
@ -891,7 +892,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
|||
if (!func_import->call_conv_wasm_c_api) {
|
||||
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;
|
||||
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;
|
||||
|
||||
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
|
||||
|
||||
|
@ -1023,7 +1024,7 @@ wasm_interp_call_func_import(WASMModuleInstance *module_inst,
|
|||
exec_env->module_inst = (WASMModuleInstanceCommon *)module_inst;
|
||||
|
||||
/* 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,
|
||||
sizeof(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
|
||||
#define CHECK_SUSPEND_FLAGS() \
|
||||
do { \
|
||||
os_mutex_lock(&exec_env->wait_lock); \
|
||||
if (IS_WAMR_TERM_SIG(exec_env->current_status->signal_flag)) { \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
return; \
|
||||
} \
|
||||
if (IS_WAMR_STOP_SIG(exec_env->current_status->signal_flag)) { \
|
||||
SYNC_ALL_TO_FRAME(); \
|
||||
wasm_cluster_thread_stopped(exec_env); \
|
||||
wasm_cluster_thread_waiting_run(exec_env); \
|
||||
} \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
} while (0)
|
||||
#else
|
||||
#define CHECK_SUSPEND_FLAGS() \
|
||||
do { \
|
||||
os_mutex_lock(&exec_env->wait_lock); \
|
||||
if (exec_env->suspend_flags.flags != 0) { \
|
||||
if (exec_env->suspend_flags.flags & 0x01) { \
|
||||
/* terminate current thread */ \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
return; \
|
||||
} \
|
||||
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_mutex_unlock(&exec_env->wait_lock); \
|
||||
} while (0)
|
||||
#endif /* WASM_ENABLE_DEBUG_INTERP */
|
||||
#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 = 0; \
|
||||
SYNC_ALL_TO_FRAME(); \
|
||||
wasm_cluster_thread_stopped(exec_env); \
|
||||
wasm_cluster_thread_waiting_run(exec_env); \
|
||||
} \
|
||||
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 = 0; \
|
||||
SYNC_ALL_TO_FRAME(); \
|
||||
wasm_cluster_thread_stopped(exec_env); \
|
||||
wasm_cluster_thread_waiting_run(exec_env); \
|
||||
} \
|
||||
continue
|
||||
|
@ -1123,14 +1127,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
WASMFunctionInstance *cur_func,
|
||||
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);
|
||||
uint8 *global_data = module->global_data;
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 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 =
|
||||
memory ? num_bytes_per_page * memory->cur_page_count : 0;
|
||||
memory ? wasm_get_linear_memory_size(memory, node) : 0;
|
||||
#endif
|
||||
WASMType **wasm_types = module->module->types;
|
||||
WASMGlobalInstance *globals = module->e->globals, *global;
|
||||
|
@ -1365,7 +1377,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
|
||||
HANDLE_OP(EXT_OP_BR_TABLE_CACHE)
|
||||
{
|
||||
BrTableCache *node =
|
||||
BrTableCache *node_cache =
|
||||
bh_list_first_elem(module->module->br_table_cache_list);
|
||||
BrTableCache *node_next;
|
||||
|
||||
|
@ -1374,13 +1386,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#endif
|
||||
lidx = POP_I32();
|
||||
|
||||
while (node) {
|
||||
node_next = bh_list_elem_next(node);
|
||||
if (node->br_table_op_addr == frame_ip - 1) {
|
||||
depth = node->br_depths[lidx];
|
||||
while (node_cache) {
|
||||
node_next = bh_list_elem_next(node_cache);
|
||||
if (node_cache->br_table_op_addr == frame_ip - 1) {
|
||||
depth = node_cache->br_depths[lidx];
|
||||
goto label_pop_csp_n;
|
||||
}
|
||||
node = node_next;
|
||||
node_cache = node_next;
|
||||
}
|
||||
bh_assert(0);
|
||||
HANDLE_OP_END();
|
||||
|
@ -3434,6 +3446,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (ret == (uint32)-1)
|
||||
goto got_exception;
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
CHECK_SUSPEND_FLAGS();
|
||||
#endif
|
||||
|
||||
PUSH_I32(ret);
|
||||
break;
|
||||
}
|
||||
|
@ -3454,6 +3470,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (ret == (uint32)-1)
|
||||
goto got_exception;
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
CHECK_SUSPEND_FLAGS();
|
||||
#endif
|
||||
|
||||
PUSH_I32(ret);
|
||||
break;
|
||||
}
|
||||
|
@ -3461,6 +3481,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
{
|
||||
/* Skip the memory index */
|
||||
frame_ip++;
|
||||
os_atomic_thread_fence(os_memory_order_release);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3475,23 +3496,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = LOAD_I32(maddr);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
|
||||
PUSH_I32(readv);
|
||||
|
@ -3510,30 +3531,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = LOAD_I64(maddr);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
|
||||
PUSH_I64(readv);
|
||||
|
@ -3552,23 +3573,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
*(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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
STORE_U32(maddr, frame_sp[1]);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3586,31 +3607,31 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
*(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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
STORE_U32(maddr, (uint32)sval);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
PUT_I64_TO_ADDR((uint32 *)maddr,
|
||||
GET_I64_FROM_ADDR(frame_sp + 1));
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3630,32 +3651,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint32)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U16(maddr, (uint16)(sval));
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = LOAD_I32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, sval);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
PUSH_I32(readv);
|
||||
break;
|
||||
|
@ -3676,44 +3697,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint64)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint64)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint32)expect;
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, (uint32)(sval));
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint64)LOAD_I64(maddr);
|
||||
if (readv == expect) {
|
||||
STORE_I64(maddr, sval);
|
||||
}
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
PUSH_I64(readv);
|
||||
break;
|
||||
|
@ -3859,7 +3880,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (memory)
|
||||
linear_mem_size = num_bytes_per_page * memory->cur_page_count;
|
||||
#endif
|
||||
if (wasm_get_exception(module))
|
||||
if (wasm_copy_exception(module, NULL))
|
||||
goto got_exception;
|
||||
}
|
||||
else {
|
||||
|
@ -3908,10 +3929,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
PUSH_CSP(LABEL_TYPE_FUNCTION, 0, cell_num, frame_ip_end - 1);
|
||||
|
||||
wasm_exec_env_set_cur_frame(exec_env, frame);
|
||||
}
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
CHECK_SUSPEND_FLAGS();
|
||||
#endif
|
||||
}
|
||||
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]);
|
||||
bh_assert(action == JIT_INTERP_ACTION_NORMAL
|
||||
|| (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 */
|
||||
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 */
|
||||
|
||||
#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
|
||||
llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
|
||||
WASMExecEnv *exec_env,
|
||||
|
@ -4111,14 +4115,6 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
|
|||
ret = wasm_runtime_invoke_native(
|
||||
exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL,
|
||||
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 (argv1 != argv1_buf)
|
||||
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,
|
||||
argv, argc, argv);
|
||||
|
||||
if (clear_wasi_proc_exit_exception(module_inst))
|
||||
ret = true;
|
||||
|
||||
return ret && !wasm_get_exception(module_inst) ? true : false;
|
||||
return ret && !wasm_copy_exception(module_inst, NULL) ? true : false;
|
||||
}
|
||||
}
|
||||
#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 i;
|
||||
bool copy_argv_from_frame = true;
|
||||
char exception[EXCEPTION_BUF_LEN];
|
||||
|
||||
if (argc < function->param_cell_num) {
|
||||
char buf[128];
|
||||
|
@ -4198,6 +4192,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
|||
}
|
||||
argc = function->param_cell_num;
|
||||
|
||||
RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame);
|
||||
#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
&& WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
|
||||
if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
|
||||
|
@ -4242,58 +4237,51 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
|||
}
|
||||
}
|
||||
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 WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0
|
||||
/* Fast JIT and LLVM JIT are both enabled, call llvm jit function
|
||||
if (running_mode == Mode_Interp) {
|
||||
wasm_interp_call_func_bytecode(module_inst, exec_env, function,
|
||||
frame);
|
||||
}
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
else if (running_mode == Mode_Fast_JIT) {
|
||||
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,
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
#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);
|
||||
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);
|
||||
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
|
||||
|
||||
#else /* else of WASM_ENABLE_LAZY_JIT != 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 */
|
||||
else {
|
||||
/* There should always be a supported running mode selected */
|
||||
bh_assert(0);
|
||||
}
|
||||
|
||||
(void)wasm_interp_call_func_bytecode;
|
||||
#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 */
|
||||
if (!wasm_get_exception(module_inst)) {
|
||||
if (!wasm_copy_exception(module_inst, NULL)) {
|
||||
if (copy_argv_from_frame) {
|
||||
for (i = 0; i < function->ret_cell_num; i++) {
|
||||
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);
|
||||
}
|
||||
#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);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "wasm_runtime.h"
|
||||
#include "wasm_opcode.h"
|
||||
#include "wasm_loader.h"
|
||||
#include "wasm_memory.h"
|
||||
#include "../common/wasm_exec_env.h"
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
#include "../common/wasm_shared_memory.h"
|
||||
|
@ -469,28 +470,28 @@ LOAD_PTR(void *addr)
|
|||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint32)(*(uint8 *)maddr); \
|
||||
*(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) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint32)LOAD_U16(maddr); \
|
||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
} \
|
||||
else { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = LOAD_I32(maddr); \
|
||||
STORE_U32(maddr, readv op sval); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
} \
|
||||
PUSH_I32(readv); \
|
||||
break; \
|
||||
|
@ -509,39 +510,39 @@ LOAD_PTR(void *addr)
|
|||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint64)(*(uint8 *)maddr); \
|
||||
*(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) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint64)LOAD_U16(maddr); \
|
||||
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) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint64)LOAD_U32(maddr); \
|
||||
STORE_U32(maddr, (uint32)(readv op sval)); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
} \
|
||||
else { \
|
||||
uint64 op_result; \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8); \
|
||||
\
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
os_mutex_lock(&node->shared_mem_lock); \
|
||||
readv = (uint64)LOAD_I64(maddr); \
|
||||
op_result = readv op sval; \
|
||||
STORE_I64(maddr, op_result); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
os_mutex_unlock(&node->shared_mem_lock); \
|
||||
} \
|
||||
PUSH_I64(readv); \
|
||||
break; \
|
||||
|
@ -925,7 +926,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
|||
if (!func_import->call_conv_wasm_c_api) {
|
||||
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;
|
||||
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;
|
||||
|
||||
/* 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,
|
||||
sizeof(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
|
||||
#define CHECK_SUSPEND_FLAGS() \
|
||||
do { \
|
||||
os_mutex_lock(&exec_env->wait_lock); \
|
||||
if (exec_env->suspend_flags.flags != 0) { \
|
||||
if (exec_env->suspend_flags.flags & 0x01) { \
|
||||
/* terminate current thread */ \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
return; \
|
||||
} \
|
||||
/* TODO: support suspend and breakpoint */ \
|
||||
} \
|
||||
os_mutex_unlock(&exec_env->wait_lock); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
@ -1151,13 +1155,22 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
WASMFunctionInstance *cur_func,
|
||||
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);
|
||||
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 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 =
|
||||
memory ? num_bytes_per_page * memory->cur_page_count : 0;
|
||||
memory ? wasm_get_linear_memory_size(memory, node) : 0;
|
||||
#endif
|
||||
uint8 *global_data = module->global_data;
|
||||
WASMGlobalInstance *globals = module->e ? module->e->globals : NULL;
|
||||
|
@ -3275,6 +3288,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (ret == (uint32)-1)
|
||||
goto got_exception;
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
CHECK_SUSPEND_FLAGS();
|
||||
#endif
|
||||
|
||||
PUSH_I32(ret);
|
||||
break;
|
||||
}
|
||||
|
@ -3295,9 +3312,18 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (ret == (uint32)-1)
|
||||
goto got_exception;
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
CHECK_SUSPEND_FLAGS();
|
||||
#endif
|
||||
|
||||
PUSH_I32(ret);
|
||||
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_LOAD8_U:
|
||||
|
@ -3310,23 +3336,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = LOAD_I32(maddr);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
|
||||
PUSH_I32(readv);
|
||||
|
@ -3345,30 +3371,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = LOAD_I64(maddr);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
|
||||
PUSH_I64(readv);
|
||||
|
@ -3386,23 +3412,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
*(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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
STORE_U32(maddr, sval);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3420,30 +3446,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
*(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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
STORE_U32(maddr, (uint32)sval);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
STORE_I64(maddr, sval);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3463,32 +3489,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint32)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U16(maddr, (uint16)(sval));
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = LOAD_I32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, sval);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
PUSH_I32(readv);
|
||||
break;
|
||||
|
@ -3509,44 +3535,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint64)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint64)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
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) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
|
||||
expect = (uint32)expect;
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, (uint32)(sval));
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
os_mutex_lock(&node->shared_mem_lock);
|
||||
readv = (uint64)LOAD_I64(maddr);
|
||||
if (readv == expect) {
|
||||
STORE_I64(maddr, sval);
|
||||
}
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
os_mutex_unlock(&node->shared_mem_lock);
|
||||
}
|
||||
PUSH_I64(readv);
|
||||
break;
|
||||
|
@ -3797,7 +3823,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (memory)
|
||||
linear_mem_size = num_bytes_per_page * memory->cur_page_count;
|
||||
#endif
|
||||
if (wasm_get_exception(module))
|
||||
if (wasm_copy_exception(module, NULL))
|
||||
goto got_exception;
|
||||
}
|
||||
else {
|
||||
|
@ -3837,6 +3863,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
|
||||
wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)frame);
|
||||
}
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
CHECK_SUSPEND_FLAGS();
|
||||
#endif
|
||||
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
|
||||
frame here. */
|
||||
unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
|
||||
char exception[EXCEPTION_BUF_LEN];
|
||||
|
||||
if (argc < function->param_cell_num) {
|
||||
char buf[128];
|
||||
|
@ -3917,6 +3947,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
|||
}
|
||||
argc = function->param_cell_num;
|
||||
|
||||
RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame);
|
||||
#if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
&& WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
|
||||
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 */
|
||||
if (!wasm_get_exception(module_inst)) {
|
||||
if (!wasm_copy_exception(module_inst, NULL)) {
|
||||
for (i = 0; i < function->ret_cell_num; 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);
|
||||
}
|
||||
#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);
|
||||
|
|
|
@ -1399,6 +1399,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
|
|||
WASMModule *sub_module = NULL;
|
||||
WASMGlobal *linked_global = NULL;
|
||||
#endif
|
||||
bool ret = false;
|
||||
|
||||
CHECK_BUF(p, p_end, 2);
|
||||
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
|
||||
global->is_linked = wasm_native_lookup_libc_builtin_global(
|
||||
sub_module_name, global_name, global);
|
||||
if (global->is_linked) {
|
||||
ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name,
|
||||
global);
|
||||
if (ret) {
|
||||
if (global->type != declare_type
|
||||
|| global->is_mutable != declare_mutable) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"incompatible import type");
|
||||
return false;
|
||||
}
|
||||
global->is_linked = true;
|
||||
}
|
||||
#endif
|
||||
#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);
|
||||
|
||||
(void)parent_module;
|
||||
(void)ret;
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
|
@ -2989,6 +2992,7 @@ static bool
|
|||
init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
|
||||
AOTCompOption option = { 0 };
|
||||
char *aot_last_error;
|
||||
uint64 size;
|
||||
|
@ -3027,8 +3031,11 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
|||
}
|
||||
|
||||
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
|
||||
option.enable_bulk_memory = true;
|
||||
#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)
|
||||
option.enable_aux_stack_frame = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
option.enable_stack_estimation = true;
|
||||
#endif
|
||||
|
||||
module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
|
||||
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;
|
||||
|
||||
#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)
|
||||
return false;
|
||||
#endif
|
||||
|
@ -3199,9 +3211,9 @@ orcjit_thread_callback(void *arg)
|
|||
|
||||
/* Wait until init_llvm_jit_functions_stage2 finishes */
|
||||
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,
|
||||
&module->tierup_wait_lock, 10);
|
||||
&module->tierup_wait_lock, 10000);
|
||||
if (module->orcjit_stop_compiling) {
|
||||
/* init_llvm_jit_functions_stage2 failed */
|
||||
os_mutex_unlock(&module->tierup_wait_lock);
|
||||
|
@ -3853,7 +3865,7 @@ create_module(char *error_buf, uint32 error_buf_size)
|
|||
#endif
|
||||
|
||||
#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)
|
||||
if (os_mutex_init(&module->instance_list_lock) != 0) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
|
@ -4148,10 +4160,8 @@ check_wasi_abi_compatibility(const WASMModule *module,
|
|||
|
||||
/* should have one at least */
|
||||
if (module->import_wasi_api && !start && !initialize) {
|
||||
set_error_buf(
|
||||
error_buf, error_buf_size,
|
||||
"a module with WASI apis must be either a command or a reactor");
|
||||
return false;
|
||||
LOG_WARNING("warning: a module with WASI apis should be either "
|
||||
"a command or a reactor");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4185,7 +4195,20 @@ check_wasi_abi_compatibility(const WASMModule *module,
|
|||
|
||||
memory = wasm_loader_find_export(module, "", "memory", EXPORT_KIND_MEMORY,
|
||||
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,
|
||||
"a module with WASI apis must export memory by default");
|
||||
return false;
|
||||
|
@ -4243,7 +4266,8 @@ wasm_loader_unload(WASMModule *module)
|
|||
if (!module)
|
||||
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;
|
||||
if (module->llvm_jit_init_thread)
|
||||
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);
|
||||
#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) {
|
||||
os_mutex_destroy(&module->tierup_wait_lock);
|
||||
os_cond_destroy(&module->tierup_wait_cond);
|
||||
|
@ -4299,9 +4324,9 @@ wasm_loader_unload(WASMModule *module)
|
|||
module->functions[i]->fast_jit_jitted_code);
|
||||
}
|
||||
#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(
|
||||
module->functions[i]->llvm_jit_func_ptr);
|
||||
module->functions[i]->call_to_fast_jit_from_llvm_jit);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -4394,7 +4419,7 @@ wasm_loader_unload(WASMModule *module)
|
|||
#endif
|
||||
|
||||
#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)
|
||||
os_mutex_destroy(&module->instance_list_lock);
|
||||
#endif
|
||||
|
|
|
@ -1835,6 +1835,7 @@ static bool
|
|||
init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
|
||||
AOTCompOption option = { 0 };
|
||||
char *aot_last_error;
|
||||
uint64 size;
|
||||
|
@ -1873,8 +1874,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
|
|||
}
|
||||
|
||||
option.is_jit_mode = true;
|
||||
option.opt_level = 3;
|
||||
option.size_level = 3;
|
||||
option.opt_level = llvm_jit_options.opt_level;
|
||||
option.size_level = llvm_jit_options.size_level;
|
||||
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
option.enable_bulk_memory = true;
|
||||
#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)
|
||||
option.enable_aux_stack_frame = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
option.enable_stack_estimation = true;
|
||||
#endif
|
||||
|
||||
module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
|
||||
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;
|
||||
|
||||
#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)
|
||||
return false;
|
||||
#endif
|
||||
|
@ -2047,9 +2054,9 @@ orcjit_thread_callback(void *arg)
|
|||
|
||||
/* Wait until init_llvm_jit_functions_stage2 finishes */
|
||||
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,
|
||||
&module->tierup_wait_lock, 10);
|
||||
&module->tierup_wait_lock, 10000);
|
||||
if (module->orcjit_stop_compiling) {
|
||||
/* init_llvm_jit_functions_stage2 failed */
|
||||
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);
|
||||
#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) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"init instance list lock failed");
|
||||
|
@ -2939,7 +2947,8 @@ wasm_loader_unload(WASMModule *module)
|
|||
if (!module)
|
||||
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;
|
||||
if (module->llvm_jit_init_thread)
|
||||
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);
|
||||
#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) {
|
||||
os_mutex_destroy(&module->tierup_wait_lock);
|
||||
os_cond_destroy(&module->tierup_wait_cond);
|
||||
|
@ -2995,9 +3005,9 @@ wasm_loader_unload(WASMModule *module)
|
|||
module->functions[i]->fast_jit_jitted_code);
|
||||
}
|
||||
#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(
|
||||
module->functions[i]->llvm_jit_func_ptr);
|
||||
module->functions[i]->call_to_fast_jit_from_llvm_jit);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -3056,7 +3066,8 @@ wasm_loader_unload(WASMModule *module)
|
|||
}
|
||||
#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);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -677,12 +677,14 @@ typedef enum WASMAtomicEXTOpcode {
|
|||
} WASMAtomicEXTOpcode;
|
||||
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
#define DEF_DEBUG_BREAK_HANDLE(_name) \
|
||||
_name[DEBUG_OP_BREAK] = HANDLE_OPCODE(DEBUG_OP_BREAK); /* 0xd7 */
|
||||
#define DEF_DEBUG_BREAK_HANDLE() \
|
||||
[DEBUG_OP_BREAK] = HANDLE_OPCODE(DEBUG_OP_BREAK), /* 0xd7 */
|
||||
#else
|
||||
#define DEF_DEBUG_BREAK_HANDLE(_name)
|
||||
#define DEF_DEBUG_BREAK_HANDLE()
|
||||
#endif
|
||||
|
||||
#define SET_GOTO_TABLE_ELEM(opcode) [opcode] = HANDLE_OPCODE(opcode)
|
||||
|
||||
/*
|
||||
* 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_IF), /* 0xd5 */ \
|
||||
HANDLE_OPCODE(EXT_OP_BR_TABLE_CACHE), /* 0xd6 */ \
|
||||
}; \
|
||||
do { \
|
||||
_name[WASM_OP_MISC_PREFIX] = \
|
||||
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)
|
||||
SET_GOTO_TABLE_ELEM(WASM_OP_MISC_PREFIX), /* 0xfc */ \
|
||||
SET_GOTO_TABLE_ELEM(WASM_OP_ATOMIC_PREFIX), /* 0xfe */ \
|
||||
DEF_DEBUG_BREAK_HANDLE() \
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -737,13 +737,12 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
|
|||
|
||||
function++;
|
||||
}
|
||||
bh_assert((uint32)(function - functions) == function_count);
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs;
|
||||
#endif
|
||||
|
||||
bh_assert((uint32)(function - functions) == function_count);
|
||||
(void)module_inst;
|
||||
return functions;
|
||||
}
|
||||
|
||||
|
@ -983,88 +982,138 @@ export_globals_instantiate(const WASMModule *module,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
static bool
|
||||
execute_initialize_function(WASMModuleInstance *module_inst)
|
||||
static WASMFunctionInstance *
|
||||
lookup_post_instantiate_func(WASMModuleInstance *module_inst,
|
||||
const char *func_name)
|
||||
{
|
||||
WASMFunctionInstance *initialize =
|
||||
wasm_lookup_function(module_inst, "_initialize", NULL);
|
||||
return !initialize
|
||||
|| wasm_create_exec_env_and_call_function(module_inst, initialize, 0,
|
||||
NULL);
|
||||
WASMFunctionInstance *func;
|
||||
WASMType *func_type;
|
||||
|
||||
if (!(func = wasm_lookup_function(module_inst, func_name, 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
|
||||
|
||||
static bool
|
||||
execute_post_inst_function(WASMModuleInstance *module_inst)
|
||||
{
|
||||
WASMFunctionInstance *post_inst_func = NULL;
|
||||
WASMType *post_inst_func_type;
|
||||
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);
|
||||
/* 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
|
||||
static bool
|
||||
execute_memory_init_function(WASMModuleInstance *module_inst)
|
||||
{
|
||||
WASMFunctionInstance *memory_init_func = NULL;
|
||||
WASMType *memory_init_func_type;
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < module_inst->export_func_count; i++)
|
||||
if (!strcmp(module_inst->export_functions[i].name,
|
||||
"__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);
|
||||
/* 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
|
||||
|
||||
static bool
|
||||
execute_start_function(WASMModuleInstance *module_inst)
|
||||
{
|
||||
WASMFunctionInstance *func = module_inst->e->start_function;
|
||||
|
||||
if (!func)
|
||||
if (!start_func && !initialize_func && !post_inst_func
|
||||
&& !call_ctors_func) {
|
||||
/* No post instantiation functions to call */
|
||||
return true;
|
||||
}
|
||||
|
||||
bh_assert(!func->is_import_func && func->param_cell_num == 0
|
||||
&& func->ret_cell_num == 0);
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
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
|
||||
|
@ -1235,6 +1284,7 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
|
|||
#if WASM_ENABLE_WAMR_COMPILER == 0
|
||||
LOG_WARNING("warning: failed to link import function (%s, %s)",
|
||||
func->module_name, func->field_name);
|
||||
/* will throw exception only if calling */
|
||||
#else
|
||||
/* do nothing to avoid confused message */
|
||||
#endif /* WASM_ENABLE_WAMR_COMPILER == 0 */
|
||||
|
@ -1250,8 +1300,10 @@ check_linked_symbol(WASMModuleInstance *module_inst, char *error_buf,
|
|||
return false;
|
||||
#else
|
||||
#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,
|
||||
"failed to link import global (%s, %s)",
|
||||
global->module_name, global->field_name);
|
||||
return false;
|
||||
#else
|
||||
/* do nothing to avoid confused message */
|
||||
#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;
|
||||
}
|
||||
|
||||
/* Set defined function pointers */
|
||||
bh_memcpy_s(func_ptrs, sizeof(void *) * module->function_count,
|
||||
module->func_ptrs, sizeof(void *) * module->function_count);
|
||||
/* The defined function pointers will be set in
|
||||
wasm_runtime_set_running_mode, no need to set them here */
|
||||
return true;
|
||||
}
|
||||
#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 */
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -1419,15 +1637,6 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
|
|||
module_inst->e =
|
||||
(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
|
||||
module_inst->e->sub_module_inst_list =
|
||||
&module_inst->e->sub_module_inst_list_head;
|
||||
|
@ -1800,33 +2009,39 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|
||||
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
|
||||
&& WASM_ENABLE_LAZY_JIT != 0)
|
||||
#if WASM_ENABLE_WASI_NN != 0
|
||||
if (!is_sub_inst) {
|
||||
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) {
|
||||
/* Add module instance into module's instance list */
|
||||
os_mutex_lock(&module->instance_list_lock);
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
if (module->instance_list) {
|
||||
LOG_WARNING(
|
||||
"warning: multiple instances referencing to the same module "
|
||||
"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->instance_list = module_inst;
|
||||
os_mutex_unlock(&module->instance_list_lock);
|
||||
}
|
||||
#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) {
|
||||
/* TODO: fix start function can be import function issue */
|
||||
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];
|
||||
}
|
||||
|
||||
if (
|
||||
#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)) {
|
||||
if (!execute_post_instantiate_functions(module_inst, is_sub_inst)) {
|
||||
set_error_buf(error_buf, error_buf_size, module_inst->cur_exception);
|
||||
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
|
||||
wasm_runtime_dump_module_inst_mem_consumption(
|
||||
(WASMModuleInstanceCommon *)module_inst);
|
||||
|
@ -1892,11 +2073,57 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
|||
if (!module_inst)
|
||||
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 (module_inst->func_ptrs)
|
||||
wasm_runtime_free(module_inst->func_ptrs);
|
||||
#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 (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);
|
||||
#endif
|
||||
|
||||
if (module_inst->exec_env_singleton)
|
||||
wasm_exec_env_destroy(module_inst->exec_env_singleton);
|
||||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||
if (module_inst->frames) {
|
||||
bh_vector_destroy(module_inst->frames);
|
||||
|
@ -1948,39 +2172,17 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
|||
}
|
||||
#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)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2030,24 +2232,6 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name)
|
|||
}
|
||||
#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
|
||||
|
||||
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);
|
||||
uint8 *prev_top = exec_env->wasm_stack.s.top;
|
||||
#ifdef BH_PLATFORM_WINDOWS
|
||||
const char *exce;
|
||||
int result;
|
||||
bool has_exception;
|
||||
char exception[EXCEPTION_BUF_LEN];
|
||||
#endif
|
||||
bool ret = true;
|
||||
|
||||
/* Check native stack overflow firstly to ensure we have enough
|
||||
native stack to run the following codes before actually calling
|
||||
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
|
||||
+ page_size * (guard_page_count + 1)) {
|
||||
wasm_set_exception(module_inst, "native stack overflow");
|
||||
|
@ -2096,14 +2282,14 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
|
|||
#else
|
||||
__try {
|
||||
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_CONTINUE_SEARCH) {
|
||||
/* exception was thrown in wasm_exception_handler */
|
||||
ret = false;
|
||||
}
|
||||
if ((exce = wasm_get_exception(module_inst))
|
||||
&& strstr(exce, "native stack overflow")) {
|
||||
has_exception = wasm_copy_exception(module_inst, exception);
|
||||
if (has_exception && strstr(exception, "native stack overflow")) {
|
||||
/* After a stack overflow, the stack was left
|
||||
in a damaged state, let the CRT repair it */
|
||||
result = _resetstkoflw();
|
||||
|
@ -2157,8 +2343,7 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
|
|||
wasm_exec_env_set_thread_info(exec_env);
|
||||
|
||||
interp_call_wasm(module_inst, exec_env, function, argc, argv);
|
||||
(void)clear_wasi_proc_exit_exception(module_inst);
|
||||
return !wasm_get_exception(module_inst) ? true : false;
|
||||
return !wasm_copy_exception(module_inst, NULL);
|
||||
}
|
||||
|
||||
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 */
|
||||
if (!existing_exec_env)
|
||||
|
@ -2331,6 +2516,12 @@ wasm_module_free(WASMModuleInstance *module_inst, uint32 ptr)
|
|||
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;
|
||||
|
||||
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,
|
||||
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);
|
||||
|
||||
(void)clear_wasi_proc_exit_exception(module_inst);
|
||||
return !wasm_get_exception(module_inst) ? true : false;
|
||||
return !wasm_copy_exception(module_inst, NULL);
|
||||
|
||||
got_exception:
|
||||
return false;
|
||||
|
@ -2476,14 +2670,16 @@ wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size)
|
|||
WASMModuleInstance *module_inst =
|
||||
(WASMModuleInstance *)exec_env->module_inst;
|
||||
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 stack_bottom = module_inst->module->aux_stack_bottom;
|
||||
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))
|
||||
|| ((!is_stack_before_data) && (start_offset - data_end < size)))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (stack_top_idx != (uint32)-1) {
|
||||
/* The aux stack top is a wasm global,
|
||||
|
@ -2905,9 +3101,15 @@ llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
|
|||
|
||||
import_func = &module->import_functions[func_idx].u.function;
|
||||
if (import_func->call_conv_wasm_c_api) {
|
||||
if (module_inst->e->c_api_func_imports) {
|
||||
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) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
|
|
|
@ -11,10 +11,16 @@
|
|||
#include "../common/wasm_runtime_common.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
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EXCEPTION_BUF_LEN 128
|
||||
|
||||
typedef struct WASMModuleInstance WASMModuleInstance;
|
||||
typedef struct WASMFunctionInstance WASMFunctionInstance;
|
||||
typedef struct WASMMemoryInstance WASMMemoryInstance;
|
||||
|
@ -59,9 +65,7 @@ typedef enum WASMExceptionID {
|
|||
EXCE_AUX_STACK_UNDERFLOW,
|
||||
EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
|
||||
EXCE_OPERAND_STACK_OVERFLOW,
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC,
|
||||
#endif
|
||||
EXCE_ALREADY_THROWN,
|
||||
EXCE_NUM,
|
||||
} WASMExceptionID;
|
||||
|
@ -219,12 +223,7 @@ typedef struct WASMModuleInstanceExtra {
|
|||
WASMFunctionInstance *retain_function;
|
||||
|
||||
CApiFuncImport *c_api_func_imports;
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
/* lock for shared memory atomic operations */
|
||||
korp_mutex mem_lock;
|
||||
bool mem_lock_inited;
|
||||
#endif
|
||||
RunningMode running_mode;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
bh_list sub_module_inst_list_head;
|
||||
|
@ -238,10 +237,14 @@ typedef struct WASMModuleInstanceExtra {
|
|||
#endif
|
||||
|
||||
#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)
|
||||
WASMModuleInstance *next;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_WASI_NN != 0
|
||||
WASINNContext *wasi_nn_ctx;
|
||||
#endif
|
||||
} WASMModuleInstanceExtra;
|
||||
|
||||
struct AOTFuncPerfProfInfo;
|
||||
|
@ -281,7 +284,7 @@ struct WASMModuleInstance {
|
|||
DefPointer(WASMExportTabInstance *, export_tables);
|
||||
|
||||
/* 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,
|
||||
it denotes `AOTModule *` */
|
||||
|
@ -298,7 +301,11 @@ struct WASMModuleInstance {
|
|||
not available in AOTModuleInstance */
|
||||
DefPointer(void **, import_func_ptrs);
|
||||
/* 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);
|
||||
/* The custom data that can be set/get by wasm_{get|set}_custom_data */
|
||||
DefPointer(void *, custom_data);
|
||||
|
@ -402,6 +409,10 @@ wasm_dump_perf_profiling(const WASMModuleInstance *module_inst);
|
|||
void
|
||||
wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst);
|
||||
|
||||
bool
|
||||
wasm_set_running_mode(WASMModuleInstance *module_inst,
|
||||
RunningMode running_mode);
|
||||
|
||||
WASMFunctionInstance *
|
||||
wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name,
|
||||
const char *signature);
|
||||
|
@ -435,6 +446,15 @@ wasm_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id);
|
|||
const char *
|
||||
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
|
||||
wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size,
|
||||
void **p_native_addr);
|
||||
|
|
|
@ -46,10 +46,6 @@
|
|||
wasm_runtime_addr_native_to_app(module_inst, ptr)
|
||||
/* clang-format on */
|
||||
|
||||
extern bool
|
||||
wasm_runtime_call_indirect(wasm_exec_env_t exec_env, uint32 element_indices,
|
||||
uint32 argc, uint32 argv[]);
|
||||
|
||||
enum {
|
||||
T_THREAD,
|
||||
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 parent_exec_env;
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
ThreadRoutineArgs *routine_args = exec_env->thread_arg;
|
||||
ThreadInfoNode *info_node = routine_args->info_node;
|
||||
uint32 argv[1];
|
||||
|
@ -504,7 +499,6 @@ pthread_start_routine(void *arg)
|
|||
info_node->exec_env = exec_env;
|
||||
info_node->u.thread = exec_env->handle;
|
||||
if (!append_thread_info_node(info_node)) {
|
||||
wasm_runtime_deinstantiate_internal(module_inst, true);
|
||||
delete_thread_info_node(info_node);
|
||||
os_cond_signal(&parent_exec_env->wait_cond);
|
||||
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,
|
||||
argv)) {
|
||||
if (wasm_runtime_get_exception(module_inst))
|
||||
wasm_cluster_spread_exception(exec_env);
|
||||
/* Exception has already been spread during throwing */
|
||||
}
|
||||
|
||||
/* destroy pthread key values */
|
||||
call_key_destructor(exec_env);
|
||||
|
||||
/* routine exit, destroy instance */
|
||||
wasm_runtime_deinstantiate_internal(module_inst, true);
|
||||
|
||||
wasm_runtime_free(routine_args);
|
||||
|
||||
/* 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
|
||||
WASIContext *wasi_ctx;
|
||||
#endif
|
||||
CApiFuncImport **new_c_api_func_imports = NULL;
|
||||
|
||||
bh_assert(module);
|
||||
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);
|
||||
#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))))
|
||||
goto fail;
|
||||
|
||||
|
@ -623,8 +654,9 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
|
|||
routine_args->module_inst = new_module_inst;
|
||||
|
||||
os_mutex_lock(&exec_env->wait_lock);
|
||||
ret = wasm_cluster_create_thread(
|
||||
exec_env, new_module_inst, pthread_start_routine, (void *)routine_args);
|
||||
ret =
|
||||
wasm_cluster_create_thread(exec_env, new_module_inst, true,
|
||||
pthread_start_routine, (void *)routine_args);
|
||||
if (ret != 0) {
|
||||
os_mutex_unlock(&exec_env->wait_lock);
|
||||
goto fail;
|
||||
|
|
27
core/iwasm/libraries/lib-socket/test/build.sh
Executable file
27
core/iwasm/libraries/lib-socket/test/build.sh
Executable 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
|
49
core/iwasm/libraries/lib-socket/test/nslookup.c
Normal file
49
core/iwasm/libraries/lib-socket/test/nslookup.c
Normal 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;
|
||||
}
|
193
core/iwasm/libraries/lib-socket/test/tcp_udp.c
Normal file
193
core/iwasm/libraries/lib-socket/test/tcp_udp.c
Normal 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;
|
||||
}
|
12
core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake
Normal file
12
core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake
Normal 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)
|
181
core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
Normal file
181
core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
Normal 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);
|
||||
}
|
30
core/iwasm/libraries/lib-wasi-threads/test/build.sh
Normal file
30
core/iwasm/libraries/lib-wasi-threads/test/build.sh
Normal 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
|
122
core/iwasm/libraries/lib-wasi-threads/test/common.h
Normal file
122
core/iwasm/libraries/lib-wasi-threads/test/common.h
Normal 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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
70
core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c
Normal file
70
core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c
Normal 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;
|
||||
}
|
78
core/iwasm/libraries/lib-wasi-threads/test/global_lock.c
Normal file
78
core/iwasm/libraries/lib-wasi-threads/test/global_lock.c
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 33
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 33
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 33
|
||||
}
|
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c
Normal file
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c
Normal 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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 1
|
||||
}
|
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c
Normal file
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c
Normal 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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 1
|
||||
}
|
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c
Normal file
16
core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c
Normal 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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 1
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 33
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 33
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 33
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 1
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 1
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"exit_code": 1
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user