diff --git a/.bazelrc b/.bazelrc index ab9a27f84..6e1301594 100644 --- a/.bazelrc +++ b/.bazelrc @@ -80,10 +80,10 @@ build:zig-cc-linux-aarch64 --test_env=QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ build --enable_platform_specific_config -# Use C++17. -build:linux --cxxopt=-std=c++17 -build:macos --cxxopt=-std=c++17 -build:windows --cxxopt="/std:c++17" +# Use C++20. +build:linux --cxxopt=-std=c++20 --host_cxxopt=-std=c++20 +build:macos --cxxopt=-std=c++20 --host_cxxopt=-std=c++20 +build:windows --cxxopt="/std:c++20" --host_cxxopt="/std:c++20" # Enable symlinks and runfiles on Windows (enabled by default on other platforms). startup --windows_enable_symlinks diff --git a/.clang-tidy b/.clang-tidy index ceab9ad4a..ea657db54 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -19,5 +19,6 @@ Checks: clang-*, -readability-magic-numbers, -readability-make-member-function-const, -readability-simplify-boolean-expr, + -clang-diagnostic-builtin-macro-redefined, WarningsAsErrors: '*' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5a6dd8f49..58bbb97eb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -120,7 +120,7 @@ jobs: os: ubuntu-22.04 arch: x86_64 action: test - flags: --config=clang-asan-strict --define=crypto=system + flags: --config=clang-asan --define=crypto=system - name: 'NullVM on Linux/x86_64 with TSan' engine: 'null' os: ubuntu-22.04 @@ -237,7 +237,7 @@ jobs: os: ubuntu-22.04 arch: x86_64 action: test - flags: --config=clang-asan-strict --define=crypto=system + flags: --config=clang-asan --define=crypto=system - name: 'Wasmtime on Linux/aarch64' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' @@ -262,14 +262,6 @@ jobs: os: macos-13 arch: x86_64 action: test - - name: 'WAVM on Linux/x86_64' - engine: 'wavm' - repo: 'com_github_wavm_wavm' - os: ubuntu-22.04 - arch: x86_64 - action: test - flags: --config=clang - cache: true steps: - uses: actions/checkout@v2 diff --git a/BUILD b/BUILD index 215459eb2..6db5fd903 100644 --- a/BUILD +++ b/BUILD @@ -19,7 +19,6 @@ load( "proxy_wasm_select_engine_wamr", "proxy_wasm_select_engine_wasmedge", "proxy_wasm_select_engine_wasmtime", - "proxy_wasm_select_engine_wavm", ) load("@rules_cc//cc:defs.bzl", "cc_library") @@ -281,34 +280,6 @@ cc_library( ], ) -cc_library( - name = "wavm_lib", - srcs = [ - "src/wavm/wavm.cc", - ], - hdrs = ["include/proxy-wasm/wavm.h"], - copts = [ - "-DWAVM_API=", - "-Wno-non-virtual-dtor", - "-Wno-old-style-cast", - ], - defines = [ - "PROXY_WASM_HAS_RUNTIME_WAVM", - "PROXY_WASM_HOST_ENGINE_WAVM", - ], - linkopts = select({ - "@platforms//os:macos": [], - "@platforms//os:windows": [], - "//conditions:default": [ - "-ldl", - ], - }), - deps = [ - ":wasm_vm_headers", - "//external:wavm", - ], -) - cc_library( name = "lib", deps = [ @@ -324,7 +295,5 @@ cc_library( ) + proxy_wasm_select_engine_wasmtime( [":wasmtime_lib"], [":prefixed_wasmtime_lib"], - ) + proxy_wasm_select_engine_wavm( - [":wavm_lib"], ), ) diff --git a/bazel/BUILD b/bazel/BUILD index 650fa29d8..a3487f891 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -46,11 +46,6 @@ config_setting( values = {"define": "engine=wasmtime"}, ) -config_setting( - name = "engine_wavm", - values = {"define": "engine=wavm"}, -) - config_setting( name = "multiengine", values = {"define": "engine=multi"}, diff --git a/bazel/external/v8.patch b/bazel/external/v8.patch index 58e7f9ba0..33f817cf7 100644 --- a/bazel/external/v8.patch +++ b/bazel/external/v8.patch @@ -1,13 +1,14 @@ # 1. Disable pointer compression (limits the maximum number of WasmVMs). # 2. Don't expose Wasm C API (only Wasm C++ API). -# 3. Fix gcc build error by disabling nonnull warning. -# 4. Allow compiling v8 on macOS 10.15 to 13.0. TODO(dio): Will remove this patch when https://bugs.chromium.org/p/v8/issues/detail?id=13428 is fixed. +# 3. Revert v8 commit b26554ec368e9553782012c96aa5e99b163eaff2, which removed +# use of _allowlist_function_transition from v8 bazel/defs.bzl, since it is +# still required by the version of Bazel we currently use (6.5.0). diff --git a/BUILD.bazel b/BUILD.bazel -index 4e89f90e7e..3fcb38b3f3 100644 +index 3f5a87d054e..0a693b7ee10 100644 --- a/BUILD.bazel +++ b/BUILD.bazel -@@ -157,7 +157,7 @@ v8_int( +@@ -292,7 +292,7 @@ v8_int( # If no explicit value for v8_enable_pointer_compression, we set it to 'none'. v8_string( name = "v8_enable_pointer_compression", @@ -17,41 +18,46 @@ index 4e89f90e7e..3fcb38b3f3 100644 # Default setting for v8_enable_pointer_compression. diff --git a/bazel/defs.bzl b/bazel/defs.bzl -index e957c0fad3..063627b72b 100644 +index 0539ea176ac..14d7ace5e59 100644 --- a/bazel/defs.bzl +++ b/bazel/defs.bzl -@@ -131,6 +131,7 @@ def _default_args(): - "-Wno-redundant-move", - "-Wno-return-type", - "-Wno-stringop-overflow", -+ "-Wno-nonnull", - # Use GNU dialect, because GCC doesn't allow using - # ##__VA_ARGS__ when in standards-conforming mode. - "-std=gnu++17", -@@ -151,6 +152,18 @@ def _default_args(): - "-fno-integrated-as", - ], - "//conditions:default": [], -+ }) + select({ -+ "@v8//bazel/config:is_macos": [ -+ # The clang available on macOS catalina has a warning that isn't clean on v8 code. -+ "-Wno-range-loop-analysis", -+ -+ # To supress warning on deprecated declaration on v8 code. For example: -+ # external/v8/src/base/platform/platform-darwin.cc:56:22: 'getsectdatafromheader_64' -+ # is deprecated: first deprecated in macOS 13.0. -+ # https://bugs.chromium.org/p/v8/issues/detail?id=13428. -+ "-Wno-deprecated-declarations", -+ ], -+ "//conditions:default": [], - }), - includes = ["include"], - linkopts = select({ +@@ -485,6 +485,9 @@ _v8_mksnapshot = rule( + cfg = "exec", + ), + "target_os": attr.string(mandatory = True), ++ "_allowlist_function_transition": attr.label( ++ default = "@bazel_tools//tools/allowlists/function_transition_allowlist", ++ ), + "prefix": attr.string(mandatory = True), + "suffix": attr.string(mandatory = True), + }, +diff --git a/bazel/v8-non-pointer-compression.bzl b/bazel/v8-non-pointer-compression.bzl +index 8c929454840..57336154cf7 100644 +--- a/bazel/v8-non-pointer-compression.bzl ++++ b/bazel/v8-non-pointer-compression.bzl +@@ -47,6 +47,17 @@ v8_binary_non_pointer_compression = rule( + # Note specificaly how it's configured with v8_target_cpu_transition, which + # ensures that setting propagates down the graph. + "binary": attr.label(cfg = v8_disable_pointer_compression), ++ # This is a stock Bazel requirement for any rule that uses Starlark ++ # transitions. It's okay to copy the below verbatim for all such rules. ++ # ++ # The purpose of this requirement is to give the ability to restrict ++ # which packages can invoke these rules, since Starlark transitions ++ # make much larger graphs possible that can have memory and performance ++ # consequences for your build. The whitelist defaults to "everything". ++ # But you can redefine it more strictly if you feel that's prudent. ++ "_allowlist_function_transition": attr.label( ++ default = "@bazel_tools//tools/allowlists/function_transition_allowlist", ++ ), + }, + # Making this executable means it works with "$ bazel run". + executable = True, diff --git a/src/wasm/c-api.cc b/src/wasm/c-api.cc -index 4473e205c0..65a6ec7e1d 100644 +index 05e4029f183..d705be96a16 100644 --- a/src/wasm/c-api.cc +++ b/src/wasm/c-api.cc -@@ -2247,6 +2247,8 @@ auto Instance::exports() const -> ownvec { +@@ -2472,6 +2472,8 @@ WASM_EXPORT auto Instance::exports() const -> ownvec { } // namespace wasm @@ -60,7 +66,7 @@ index 4473e205c0..65a6ec7e1d 100644 // BEGIN FILE wasm-c.cc extern "C" { -@@ -3274,3 +3276,5 @@ wasm_instance_t* wasm_frame_instance(const wasm_frame_t* frame) { +@@ -3518,3 +3520,5 @@ wasm_instance_t* wasm_frame_instance(const wasm_frame_t* frame) { #undef WASM_DEFINE_SHARABLE_REF } // extern "C" diff --git a/bazel/external/v8_include.patch b/bazel/external/v8_include.patch deleted file mode 100644 index 0d0fe210c..000000000 --- a/bazel/external/v8_include.patch +++ /dev/null @@ -1,41 +0,0 @@ -# fix include types for late clang (15.0.7) / gcc (13.2.1) -# for Arch linux / Fedora, like in -# In file included from external/v8/src/torque/torque.cc:5: -# In file included from external/v8/src/torque/source-positions.h:10: -# In file included from external/v8/src/torque/contextual.h:10: -# In file included from external/v8/src/base/macros.h:12: -# external/v8/src/base/logging.h:154:26: error: use of undeclared identifier 'uint16_t' - -diff --git a/src/base/logging.h b/src/base/logging.h ---- a/src/base/logging.h -+++ b/src/base/logging.h -@@ -5,6 +5,7 @@ - #ifndef V8_BASE_LOGGING_H_ - #define V8_BASE_LOGGING_H_ - -+#include - #include - #include - #include -diff --git a/src/base/macros.h b/src/base/macros.h ---- a/src/base/macros.h -+++ b/src/base/macros.h -@@ -5,6 +5,7 @@ - #ifndef V8_BASE_MACROS_H_ - #define V8_BASE_MACROS_H_ - -+#include - #include - #include - -diff --git a/src/inspector/v8-string-conversions.h b/src/inspector/v8-string-conversions.h ---- a/src/inspector/v8-string-conversions.h -+++ b/src/inspector/v8-string-conversions.h -@@ -5,6 +5,7 @@ - #ifndef V8_INSPECTOR_V8_STRING_CONVERSIONS_H_ - #define V8_INSPECTOR_V8_STRING_CONVERSIONS_H_ - -+#include - #include - - // Conversion routines between UT8 and UTF16, used by string-16.{h,cc}. You may diff --git a/bazel/external/wavm.BUILD b/bazel/external/wavm.BUILD deleted file mode 100644 index b315efdea..000000000 --- a/bazel/external/wavm.BUILD +++ /dev/null @@ -1,28 +0,0 @@ -load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake") - -licenses(["notice"]) # Apache 2 - -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "srcs", - srcs = glob(["**"]), -) - -cmake( - name = "wavm_lib", - cache_entries = { - "LLVM_DIR": "$EXT_BUILD_DEPS/copy_llvm/llvm/lib/cmake/llvm", - "WAVM_ENABLE_STATIC_LINKING": "on", - "WAVM_ENABLE_RELEASE_ASSERTS": "on", - "WAVM_ENABLE_UNWIND": "on", - "CMAKE_CXX_FLAGS": "-Wno-unused-command-line-argument", - }, - generate_args = ["-GNinja"], - lib_source = ":srcs", - out_static_libs = [ - "libWAVM.a", - "libWAVMUnwind.a", - ], - deps = ["@llvm//:llvm_lib"], -) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 908ffe492..985ff65a2 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -130,9 +130,9 @@ def proxy_wasm_cpp_host_repositories(): maybe( http_archive, name = "proxy_wasm_cpp_sdk", - sha256 = "89792fc1abca331f29f99870476a04146de5e82ff903bdffca90e6729c1f2470", - strip_prefix = "proxy-wasm-cpp-sdk-95bb82ce45c41d9100fd1ec15d2ffc67f7f3ceee", - urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/archive/95bb82ce45c41d9100fd1ec15d2ffc67f7f3ceee.tar.gz"], + sha256 = "26c4c0f9f645de7e789dc92f113d7352ee54ac43bb93ae3a8a22945f1ce71590", + strip_prefix = "proxy-wasm-cpp-sdk-7465dee8b2953beebff99f6dc3720ad0c79bab99", + urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/archive/7465dee8b2953beebff99f6dc3720ad0c79bab99.tar.gz"], ) # Compile DB dependencies. @@ -149,11 +149,9 @@ def proxy_wasm_cpp_host_repositories(): maybe( http_archive, name = "com_google_googletest", - sha256 = "9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb", - strip_prefix = "googletest-release-1.10.0", - urls = ["https://github.com/google/googletest/archive/release-1.10.0.tar.gz"], - patches = ["@proxy_wasm_cpp_host//bazel/external:googletest.patch"], - patch_args = ["-p1"], + sha256 = "65fab701d9829d38cb77c14acdc431d2108bfdbf8979e40eb8ae567edf10b27c", + strip_prefix = "googletest-1.17.0", + urls = ["https://github.com/google/googletest/releases/download/v1.17.0/googletest-1.17.0.tar.gz"], ) # NullVM dependencies. @@ -171,13 +169,12 @@ def proxy_wasm_cpp_host_repositories(): maybe( git_repository, name = "v8", - # 10.7.193.13 - commit = "6c8b357a84847a479cd329478522feefc1c3195a", + # 13.8.258.26 + commit = "de9d0f8b56ae61896e4d2ac577fc589efb14f87d", remote = "https://chromium.googlesource.com/v8/v8", - shallow_since = "1664374400 +0000", + shallow_since = "1752074621 -0400", patches = [ "@proxy_wasm_cpp_host//bazel/external:v8.patch", - "@proxy_wasm_cpp_host//bazel/external:v8_include.patch", ], patch_args = ["-p1"], ) @@ -187,20 +184,6 @@ def proxy_wasm_cpp_host_repositories(): actual = "@v8//:wee8", ) - maybe( - new_git_repository, - name = "com_googlesource_chromium_base_trace_event_common", - build_file = "@v8//:bazel/BUILD.trace_event_common", - commit = "521ac34ebd795939c7e16b37d9d3ddb40e8ed556", - remote = "https://chromium.googlesource.com/chromium/src/base/trace_event/common.git", - shallow_since = "1662508800 +0000", - ) - - native.bind( - name = "base_trace_event_common", - actual = "@com_googlesource_chromium_base_trace_event_common//:trace_event_common", - ) - # WAMR with dependencies. maybe( @@ -263,30 +246,3 @@ def proxy_wasm_cpp_host_repositories(): name = "prefixed_wasmtime", actual = "@com_github_bytecodealliance_wasmtime//:prefixed_wasmtime_lib", ) - - # WAVM with dependencies. - - maybe( - http_archive, - name = "com_github_wavm_wavm", - build_file = "@proxy_wasm_cpp_host//bazel/external:wavm.BUILD", - sha256 = "7cfa3d7334c96f89553bb44eeee736a192826a78b4db114042d38d6882748f5b", - strip_prefix = "WAVM-nightly-2022-05-14", - url = "https://github.com/WAVM/WAVM/archive/refs/tags/nightly/2022-05-14.tar.gz", - ) - - native.bind( - name = "wavm", - actual = "@com_github_wavm_wavm//:wavm_lib", - ) - - maybe( - http_archive, - name = "llvm", - build_file = "@proxy_wasm_cpp_host//bazel/external:llvm.BUILD", - sha256 = "7d9a8405f557cefc5a21bf5672af73903b64749d9bc3a50322239f56f34ffddf", - strip_prefix = "llvm-12.0.1.src", - url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-12.0.1/llvm-12.0.1.src.tar.xz", - patches = ["@proxy_wasm_cpp_host//bazel/external:llvm.patch"], - patch_args = ["-p1"], - ) diff --git a/bazel/select.bzl b/bazel/select.bzl index 747aef33c..cc4da38d1 100644 --- a/bazel/select.bzl +++ b/bazel/select.bzl @@ -47,10 +47,3 @@ def proxy_wasm_select_engine_wasmedge(xs): "@proxy_wasm_cpp_host//bazel:multiengine": xs, "//conditions:default": [], }) - -def proxy_wasm_select_engine_wavm(xs): - return select({ - "@proxy_wasm_cpp_host//bazel:engine_wavm": xs, - "@proxy_wasm_cpp_host//bazel:multiengine": xs, - "//conditions:default": [], - }) diff --git a/include/proxy-wasm/wasm.h b/include/proxy-wasm/wasm.h index 9fa2bda1f..3ab64b243 100644 --- a/include/proxy-wasm/wasm.h +++ b/include/proxy-wasm/wasm.h @@ -373,7 +373,7 @@ class PluginHandleBase : public std::enable_shared_from_this { using PluginHandleFactory = std::function( std::shared_ptr base_wasm, std::shared_ptr plugin)>; -// Get an existing ThreadLocal VM matching 'vm_id' or create one using 'base_wavm' by cloning or by +// Get an existing ThreadLocal VM matching 'vm_id' or create one using 'base_wasm' by cloning or by // using it it as a template. std::shared_ptr getOrCreateThreadLocalPlugin( const std::shared_ptr &base_handle, const std::shared_ptr &plugin, diff --git a/include/proxy-wasm/wasm_vm.h b/include/proxy-wasm/wasm_vm.h index a573212e0..db54ebd86 100644 --- a/include/proxy-wasm/wasm_vm.h +++ b/include/proxy-wasm/wasm_vm.h @@ -189,10 +189,9 @@ class WasmVm { /** * Whether or not the VM implementation supports cloning. Cloning is VM system dependent. * When a VM is configured a single VM is instantiated to check that the .wasm file is valid and - * to do VM system specific initialization. In the case of WAVM this is potentially ahead-of-time - * compilation. Then, if cloning is supported, we clone that VM for each worker, potentially - * copying and sharing the initialized data structures for efficiency. Otherwise we create an new - * VM from scratch for each worker. + * to do VM system specific initialization. Then, if cloning is supported, we clone that VM for + * each worker, potentially copying and sharing the initialized data structures for efficiency. + * Otherwise we create an new VM from scratch for each worker. * @return one of enum Cloneable with the VMs cloneability. */ virtual Cloneable cloneable() = 0; diff --git a/include/proxy-wasm/wavm.h b/include/proxy-wasm/wavm.h deleted file mode 100644 index 1ebbe8397..000000000 --- a/include/proxy-wasm/wavm.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2016-2019 Envoy Project Authors -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once - -#include - -#include "include/proxy-wasm/wasm_vm.h" - -namespace proxy_wasm { - -std::unique_ptr createWavmVm(); - -} // namespace proxy_wasm diff --git a/src/wavm/wavm.cc b/src/wavm/wavm.cc deleted file mode 100644 index 670eb7c41..000000000 --- a/src/wavm/wavm.cc +++ /dev/null @@ -1,492 +0,0 @@ -// Copyright 2016-2019 Envoy Project Authors -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "include/proxy-wasm/wavm.h" -#include "include/proxy-wasm/wasm_vm.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "WAVM/IR/Module.h" -#include "WAVM/IR/Operators.h" -#include "WAVM/IR/Types.h" -#include "WAVM/IR/Validate.h" -#include "WAVM/IR/Value.h" -#include "WAVM/Inline/Assert.h" -#include "WAVM/Inline/BasicTypes.h" -#include "WAVM/Inline/Errors.h" -#include "WAVM/Inline/Hash.h" -#include "WAVM/Inline/HashMap.h" -#include "WAVM/Inline/IndexMap.h" -#include "WAVM/Inline/IntrusiveSharedPtr.h" -#include "WAVM/Platform/Mutex.h" -#include "WAVM/Platform/Thread.h" -#include "WAVM/Runtime/Intrinsics.h" -#include "WAVM/Runtime/Linker.h" -#include "WAVM/Runtime/Runtime.h" -#include "WAVM/RuntimeABI/RuntimeABI.h" -#include "WAVM/WASM/WASM.h" -#include "WAVM/WASTParse/WASTParse.h" - -#ifdef NDEBUG -#define ASSERT(_x) _x -#else -#define ASSERT(_x) \ - do { \ - if (!_x) \ - ::exit(1); \ - } while (0) -#endif - -using namespace WAVM; -using namespace WAVM::IR; - -namespace WAVM::IR { -template <> constexpr ValueType inferValueType() { return ValueType::i32; } -} // namespace WAVM::IR - -namespace proxy_wasm { - -// Forward declarations. -template -void getFunctionWavm(WasmVm *vm, std::string_view function_name, - std::function *function); -template -void getFunctionWavm(WasmVm *vm, std::string_view function_name, - std::function *function); -template -void registerCallbackWavm(WasmVm *vm, std::string_view module_name, std::string_view function_name, - R (*function)(Args...)); - -namespace Wavm { - -struct Wavm; - -namespace { - -#define CALL_WITH_CONTEXT(_x, _context, _wavm) \ - do { \ - try { \ - SaveRestoreContext _saved_context(static_cast(_context)); \ - WAVM::Runtime::catchRuntimeExceptions( \ - [&] { _x; }, \ - [&](WAVM::Runtime::Exception *exception) { \ - _wavm->fail(FailState::RuntimeError, getFailMessage(function_name, exception)); \ - throw std::exception(); \ - }); \ - } catch (...) { \ - } \ - } while (0) - -std::string getFailMessage(std::string_view function_name, WAVM::Runtime::Exception *exception) { - std::string message = "Function: " + std::string(function_name) + - " failed: " + WAVM::Runtime::describeExceptionType(exception->type) + - "\nProxy-Wasm plugin in-VM backtrace:\n"; - std::vector callstack_descriptions = - WAVM::Runtime::describeCallStack(exception->callStack); - - // Since the first frame is on host and useless for developers, e.g.: `host!envoy+112901013` - // we start with index 1 here - for (size_t i = 1; i < callstack_descriptions.size(); i++) { - std::ostringstream oss; - std::string description = callstack_descriptions[i]; - if (description.find("wasm!") == std::string::npos) { - // end of WASM's call stack - break; - } - oss << std::setw(3) << std::setfill(' ') << std::to_string(i); - message += oss.str() + ": " + description + "\n"; - } - - WAVM::Runtime::destroyException(exception); - return message; -} - -struct WasmUntaggedValue : public WAVM::IR::UntaggedValue { - WasmUntaggedValue() = default; - WasmUntaggedValue(I32 inI32) { i32 = inI32; } - WasmUntaggedValue(I64 inI64) { i64 = inI64; } - WasmUntaggedValue(U32 inU32) { u32 = inU32; } - WasmUntaggedValue(Word w) { u32 = static_cast(w.u64_); } - WasmUntaggedValue(U64 inU64) { u64 = inU64; } - WasmUntaggedValue(F32 inF32) { f32 = inF32; } - WasmUntaggedValue(F64 inF64) { f64 = inF64; } -}; - -class RootResolver : public WAVM::Runtime::Resolver { -public: - RootResolver(WAVM::Runtime::Compartment * /*compartment*/, WasmVm *vm) : vm_(vm) {} - - ~RootResolver() override { module_name_to_instance_map_.clear(); } - - bool resolve(const std::string &module_name, const std::string &export_name, ExternType type, - WAVM::Runtime::Object *&out_object) override { - auto *named_instance = module_name_to_instance_map_.get(module_name); - if (named_instance != nullptr) { - out_object = getInstanceExport(*named_instance, export_name); - if (out_object != nullptr) { - if (!isA(out_object, type)) { - vm_->fail(FailState::UnableToInitializeCode, - "Failed to load WASM module due to a type mismatch in an import: " + - std::string(module_name) + "." + export_name + " " + - asString(WAVM::Runtime::getExternType(out_object)) + - " but was expecting type: " + asString(type)); - return false; - } - return true; - } - } - for (auto *r : resolvers_) { - if (r->resolve(module_name, export_name, type, out_object)) { - return true; - } - } - vm_->fail(FailState::MissingFunction, - "Failed to load Wasm module due to a missing import: " + std::string(module_name) + - "." + std::string(export_name) + " " + asString(type)); - return false; - } - - HashMap &moduleNameToInstanceMap() { - return module_name_to_instance_map_; - } - - void addResolver(WAVM::Runtime::Resolver *r) { resolvers_.push_back(r); } - -private: - WasmVm *vm_; - HashMap module_name_to_instance_map_{}; - std::vector resolvers_{}; -}; - -const uint64_t WasmPageSize = 1 << 16; - -} // namespace - -template struct NativeWord { using type = T; }; -template <> struct NativeWord { using type = uint32_t; }; - -template typename NativeWord::type ToNative(const T &t) { return t; } -template <> typename NativeWord::type ToNative(const Word &t) { return t.u32(); } - -struct PairHash { - template std::size_t operator()(const std::pair &x) const { - return std::hash()(x.first) + std::hash()(x.second); - } -}; - -struct Wavm : public WasmVm { - Wavm() = default; - ~Wavm() override; - - // WasmVm - std::string_view getEngineName() override { return "wavm"; } - Cloneable cloneable() override { return Cloneable::InstantiatedModule; }; - std::unique_ptr clone() override; - bool load(std::string_view bytecode, std::string_view precompiled, - const std::unordered_map &function_names) override; - bool link(std::string_view debug_name) override; - uint64_t getMemorySize() override; - std::optional getMemory(uint64_t pointer, uint64_t size) override; - bool setMemory(uint64_t pointer, uint64_t size, const void *data) override; - bool getWord(uint64_t pointer, Word *data) override; - bool setWord(uint64_t pointer, Word data) override; - size_t getWordSize() override { return sizeof(uint32_t); }; - std::string_view getPrecompiledSectionName() override; - -#define _GET_FUNCTION(_T) \ - void getFunction(std::string_view function_name, _T *f) override { \ - getFunctionWavm(this, function_name, f); \ - }; - FOR_ALL_WASM_VM_EXPORTS(_GET_FUNCTION) -#undef _GET_FUNCTION - -#define _REGISTER_CALLBACK(_T) \ - void registerCallback(std::string_view module_name, std::string_view function_name, _T, \ - typename ConvertFunctionTypeWordToUint32<_T>::type f) override { \ - registerCallbackWavm(this, module_name, function_name, f); \ - }; - FOR_ALL_WASM_VM_IMPORTS(_REGISTER_CALLBACK) -#undef _REGISTER_CALLBACK - - void terminate() override {} - bool usesWasmByteOrder() override { return true; } - - IR::Module ir_module_; - WAVM::Runtime::ModuleRef module_ = nullptr; - WAVM::Runtime::GCPointer module_instance_; - WAVM::Runtime::Memory *memory_{}; - WAVM::Runtime::GCPointer compartment_; - WAVM::Runtime::GCPointer context_; - std::map intrinsic_modules_{}; - std::map> - intrinsic_module_instances_{}; - std::vector> host_functions_{}; - uint8_t *memory_base_ = nullptr; -}; - -Wavm::~Wavm() { - module_instance_ = nullptr; - context_ = nullptr; - intrinsic_module_instances_.clear(); - intrinsic_modules_.clear(); - host_functions_.clear(); - if (compartment_ != nullptr) { - ASSERT(tryCollectCompartment(std::move(compartment_))); - } -} - -std::unique_ptr Wavm::clone() { - auto wavm = std::make_unique(); - if (wavm == nullptr) { - return nullptr; - } - - wavm->compartment_ = WAVM::Runtime::cloneCompartment(compartment_); - if (wavm->compartment_ == nullptr) { - return nullptr; - } - - wavm->context_ = WAVM::Runtime::cloneContext(context_, wavm->compartment_); - if (wavm->context_ == nullptr) { - return nullptr; - } - - wavm->memory_ = WAVM::Runtime::remapToClonedCompartment(memory_, wavm->compartment_); - wavm->memory_base_ = WAVM::Runtime::getMemoryBaseAddress(wavm->memory_); - wavm->module_instance_ = - WAVM::Runtime::remapToClonedCompartment(module_instance_, wavm->compartment_); - - for (auto &p : intrinsic_module_instances_) { - wavm->intrinsic_module_instances_.emplace( - p.first, WAVM::Runtime::remapToClonedCompartment(p.second, wavm->compartment_)); - } - - auto *integration_clone = integration()->clone(); - if (integration_clone == nullptr) { - return nullptr; - } - wavm->integration().reset(integration_clone); - - return wavm; -} - -bool Wavm::load(std::string_view bytecode, std::string_view precompiled, - const std::unordered_map & /*function_names*/) { - compartment_ = WAVM::Runtime::createCompartment(); - if (compartment_ == nullptr) { - return false; - } - - context_ = WAVM::Runtime::createContext(compartment_); - if (context_ == nullptr) { - return false; - } - - if (!WASM::loadBinaryModule(reinterpret_cast(bytecode.data()), - bytecode.size(), ir_module_)) { - return false; - } - - if (!precompiled.empty()) { - module_ = WAVM::Runtime::loadPrecompiledModule( - ir_module_, {precompiled.data(), precompiled.data() + precompiled.size()}); - if (module_ == nullptr) { - return false; - } - - } else { - module_ = WAVM::Runtime::compileModule(ir_module_); - if (module_ == nullptr) { - return false; - } - } - - return true; -} - -bool Wavm::link(std::string_view debug_name) { - RootResolver rootResolver(compartment_, this); - for (auto &p : intrinsic_modules_) { - auto *instance = Intrinsics::instantiateModule(compartment_, {&intrinsic_modules_[p.first]}, - std::string(p.first)); - if (instance == nullptr) { - return false; - } - intrinsic_module_instances_.emplace(p.first, instance); - rootResolver.moduleNameToInstanceMap().set(p.first, instance); - } - - WAVM::Runtime::LinkResult link_result = linkModule(ir_module_, rootResolver); - if (!link_result.missingImports.empty()) { - for (auto &i : link_result.missingImports) { - integration()->error("Missing Wasm import " + i.moduleName + " " + i.exportName); - } - fail(FailState::MissingFunction, "Failed to load Wasm module due to a missing import(s)"); - return false; - } - - module_instance_ = instantiateModule( - compartment_, module_, std::move(link_result.resolvedImports), std::string(debug_name)); - if (module_instance_ == nullptr) { - return false; - } - - memory_ = getDefaultMemory(module_instance_); - if (memory_ == nullptr) { - return false; - } - - memory_base_ = WAVM::Runtime::getMemoryBaseAddress(memory_); - - return true; -} - -uint64_t Wavm::getMemorySize() { return WAVM::Runtime::getMemoryNumPages(memory_) * WasmPageSize; } - -std::optional Wavm::getMemory(uint64_t pointer, uint64_t size) { - auto memory_num_bytes = WAVM::Runtime::getMemoryNumPages(memory_) * WasmPageSize; - if (pointer + size > memory_num_bytes) { - return std::nullopt; - } - return std::string_view(reinterpret_cast(memory_base_ + pointer), size); -} - -bool Wavm::setMemory(uint64_t pointer, uint64_t size, const void *data) { - auto memory_num_bytes = WAVM::Runtime::getMemoryNumPages(memory_) * WasmPageSize; - if (pointer + size > memory_num_bytes) { - return false; - } - auto *p = reinterpret_cast(memory_base_ + pointer); - memcpy(p, data, size); - return true; -} - -bool Wavm::getWord(uint64_t pointer, Word *data) { - auto memory_num_bytes = WAVM::Runtime::getMemoryNumPages(memory_) * WasmPageSize; - if (pointer + sizeof(uint32_t) > memory_num_bytes) { - return false; - } - auto *p = reinterpret_cast(memory_base_ + pointer); - uint32_t data32; - memcpy(&data32, p, sizeof(uint32_t)); - data->u64_ = wasmtoh(data32, true); - return true; -} - -bool Wavm::setWord(uint64_t pointer, Word data) { - uint32_t data32 = htowasm(data.u32(), true); - return setMemory(pointer, sizeof(uint32_t), &data32); -} - -std::string_view Wavm::getPrecompiledSectionName() { return "wavm.precompiled_object"; } - -} // namespace Wavm - -std::unique_ptr createWavmVm() { return std::make_unique(); } - -template -IR::FunctionType inferHostFunctionType(R (*/*func*/)(Args...)) { - return IR::FunctionType(IR::inferResultType(), IR::TypeTuple({IR::inferValueType()...}), - IR::CallingConvention::c); -} - -using namespace Wavm; - -template -void registerCallbackWavm(WasmVm *vm, std::string_view module_name, std::string_view function_name, - R (*f)(Args...)) { - auto *wavm = dynamic_cast(vm); - wavm->host_functions_.emplace_back(new Intrinsics::Function( - &wavm->intrinsic_modules_[std::string(module_name)], function_name.data(), - reinterpret_cast(f), inferHostFunctionType(f))); -} - -template -IR::FunctionType inferStdFunctionType(std::function * /*func*/) { - return IR::FunctionType(IR::inferResultType(), IR::TypeTuple({IR::inferValueType()...})); -} - -static bool checkFunctionType(WAVM::Runtime::Function *f, IR::FunctionType t) { - return getFunctionType(f) == t; -} - -template -void getFunctionWavm(WasmVm *vm, std::string_view function_name, - std::function *function) { - auto *wavm = dynamic_cast(vm); - auto *f = - asFunctionNullable(getInstanceExport(wavm->module_instance_, std::string(function_name))); - if (!f) { - f = asFunctionNullable(getInstanceExport(wavm->module_instance_, std::string(function_name))); - } - if (!f) { - *function = nullptr; - return; - } - if (!checkFunctionType(f, inferStdFunctionType(function))) { - *function = nullptr; - wavm->fail(FailState::UnableToInitializeCode, - "Bad function signature for: " + std::string(function_name)); - return; - } - *function = [wavm, f, function_name](ContextBase *context, Args... args) -> R { - WasmUntaggedValue values[] = {args...}; - WasmUntaggedValue return_value; - CALL_WITH_CONTEXT( - invokeFunction(wavm->context_, f, getFunctionType(f), &values[0], &return_value), context, - wavm); - if (wavm->isFailed()) { - return 0; - } - return static_cast(return_value.i32); - }; -} - -template -void getFunctionWavm(WasmVm *vm, std::string_view function_name, - std::function *function) { - auto *wavm = dynamic_cast(vm); - auto *f = - asFunctionNullable(getInstanceExport(wavm->module_instance_, std::string(function_name))); - if (!f) { - f = asFunctionNullable(getInstanceExport(wavm->module_instance_, std::string(function_name))); - } - if (!f) { - *function = nullptr; - return; - } - if (!checkFunctionType(f, inferStdFunctionType(function))) { - *function = nullptr; - wavm->fail(FailState::UnableToInitializeCode, - "Bad function signature for: " + std::string(function_name)); - return; - } - *function = [wavm, f, function_name](ContextBase *context, Args... args) { - WasmUntaggedValue values[] = {args...}; - CALL_WITH_CONTEXT(invokeFunction(wavm->context_, f, getFunctionType(f), &values[0]), context, - wavm); - }; -} - -} // namespace proxy_wasm diff --git a/test/runtime_test.cc b/test/runtime_test.cc index 16b4f763a..41e3946f1 100644 --- a/test/runtime_test.cc +++ b/test/runtime_test.cc @@ -53,12 +53,6 @@ TEST_P(TestVm, BadSignature) { } TEST_P(TestVm, StraceLogLevel) { - if (engine_ == "wavm") { - // TODO(mathetake): strace is yet to be implemented for WAVM. - // See https://github.com/proxy-wasm/proxy-wasm-cpp-host/issues/120. - return; - } - auto source = readTestWasmFile("clock.wasm"); ASSERT_FALSE(source.empty()); auto wasm = TestWasm(std::move(vm_)); @@ -134,11 +128,7 @@ TEST_P(TestVm, WasmMemoryLimit) { auto *host = dynamic_cast(wasm.wasm_vm()->integration().get()); EXPECT_TRUE(host->isErrorLogged("Function: infinite_memory failed")); // Trap message - if (engine_ == "wavm") { - EXPECT_TRUE(host->isErrorLogged("wavm.reachedUnreachable")); - } else { - EXPECT_TRUE(host->isErrorLogged("unreachable")); - } + EXPECT_TRUE(host->isErrorLogged("unreachable")); // Backtrace if (engine_ == "v8") { EXPECT_TRUE(host->isErrorLogged("Proxy-Wasm plugin in-VM backtrace:")); @@ -163,11 +153,7 @@ TEST_P(TestVm, Trap) { auto *host = dynamic_cast(wasm.wasm_vm()->integration().get()); EXPECT_TRUE(host->isErrorLogged("Function: trigger failed")); // Trap message - if (engine_ == "wavm") { - EXPECT_TRUE(host->isErrorLogged("wavm.reachedUnreachable")); - } else { - EXPECT_TRUE(host->isErrorLogged("unreachable")); - } + EXPECT_TRUE(host->isErrorLogged("unreachable")); // Backtrace if (engine_ == "v8") { EXPECT_TRUE(host->isErrorLogged("Proxy-Wasm plugin in-VM backtrace:")); @@ -192,11 +178,7 @@ TEST_P(TestVm, Trap2) { auto *host = dynamic_cast(wasm.wasm_vm()->integration().get()); EXPECT_TRUE(host->isErrorLogged("Function: trigger2 failed")); // Trap message - if (engine_ == "wavm") { - EXPECT_TRUE(host->isErrorLogged("wavm.reachedUnreachable")); - } else { - EXPECT_TRUE(host->isErrorLogged("unreachable")); - } + EXPECT_TRUE(host->isErrorLogged("unreachable")); // Backtrace if (engine_ == "v8") { EXPECT_TRUE(host->isErrorLogged("Proxy-Wasm plugin in-VM backtrace:")); diff --git a/test/utility.cc b/test/utility.cc index ee6f2b951..b4c10053f 100644 --- a/test/utility.cc +++ b/test/utility.cc @@ -31,9 +31,6 @@ std::vector getWasmEngines() { #endif #if defined(PROXY_WASM_HOST_ENGINE_WASMTIME) "wasmtime", -#endif -#if defined(PROXY_WASM_HOST_ENGINE_WAVM) - "wavm", #endif "" }; diff --git a/test/utility.h b/test/utility.h index ccd2a59b6..0eb743037 100644 --- a/test/utility.h +++ b/test/utility.h @@ -27,9 +27,6 @@ #if defined(PROXY_WASM_HOST_ENGINE_V8) #include "include/proxy-wasm/v8.h" #endif -#if defined(PROXY_WASM_HOST_ENGINE_WAVM) -#include "include/proxy-wasm/wavm.h" -#endif #if defined(PROXY_WASM_HOST_ENGINE_WASMTIME) #include "include/proxy-wasm/wasmtime.h" #endif @@ -172,10 +169,6 @@ class TestVm : public testing::TestWithParam { } else if (engine == "v8") { vm = proxy_wasm::createV8Vm(); #endif -#if defined(PROXY_WASM_HOST_ENGINE_WAVM) - } else if (engine == "wavm") { - vm = proxy_wasm::createWavmVm(); -#endif #if defined(PROXY_WASM_HOST_ENGINE_WASMTIME) } else if (engine == "wasmtime") { vm = proxy_wasm::createWasmtimeVm(); @@ -199,4 +192,7 @@ class TestVm : public testing::TestWithParam { std::string engine_; }; +// TODO: remove when #412 is fixed. +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TestVm); + } // namespace proxy_wasm diff --git a/test/wasm_vm_test.cc b/test/wasm_vm_test.cc index 6b4ece60f..d6f9d280a 100644 --- a/test/wasm_vm_test.cc +++ b/test/wasm_vm_test.cc @@ -35,8 +35,6 @@ TEST_P(TestVm, Basic) { EXPECT_EQ(vm_->cloneable(), proxy_wasm::Cloneable::NotCloneable); } else if (engine_ == "wasmtime" || engine_ == "v8" || engine_ == "wamr") { EXPECT_EQ(vm_->cloneable(), proxy_wasm::Cloneable::CompiledBytecode); - } else if (engine_ == "wavm") { - EXPECT_EQ(vm_->cloneable(), proxy_wasm::Cloneable::InstantiatedModule); } else { FAIL(); } @@ -95,10 +93,6 @@ TEST_P(TestVm, CloneUntilOutOfMemory) { if (vm_->cloneable() == proxy_wasm::Cloneable::NotCloneable) { return; } - if (engine_ == "wavm") { - // TODO(PiotrSikora): Figure out why this fails on the CI. - return; - } auto source = readTestWasmFile("abi_export.wasm"); ASSERT_TRUE(vm_->load(source, {}, {}));