From 3212034ee6e75d54cbf91b65cc659772166442f4 Mon Sep 17 00:00:00 2001 From: code Date: Mon, 30 Sep 2024 03:08:03 +0800 Subject: [PATCH 01/21] compdb add the compdb support to the proxy_wasm_cpp_host (#419) * compdb add the compdb support to the proxy_wasm_cpp_host Signed-off-by: wangbaiping --- .gitignore | 3 ++ CONTRIBUTING.md | 4 ++ DEVELOPMENT.md | 11 +++++ README.md | 4 ++ bazel/repositories.bzl | 9 ++++ tools/gen_compilation_database.py | 79 +++++++++++++++++++++++++++++++ 6 files changed, 110 insertions(+) create mode 100644 DEVELOPMENT.md create mode 100755 tools/gen_compilation_database.py diff --git a/.gitignore b/.gitignore index a6ef824c1..54c8a3b00 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ /bazel-* +/external +/compile_commands.json +/.cache/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 654a07164..d3f60f57a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,3 +26,7 @@ information on using pull requests. This project follows [Google's Open Source Community Guidelines](https://opensource.google/conduct/). + +## Development + +See the [Development Guidelines](DEVELOPMENT.md). diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 000000000..791fe23a1 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,11 @@ +# Development guidelines + +## Generate compilation database + +[JSON Compilation Database](https://clang.llvm.org/docs/JSONCompilationDatabase.html) files can be used by [clangd](https://clangd.llvm.org/) or similar tools to add source code cross-references and code completion functionality to editors. + +The following command can be used to generate the `compile_commands.json` file: + +``` +BAZEL_BUILD_OPTION_LIST="--define=engine=multi" ./tools/gen_compilation_database.py --include_all //test/... //:lib +``` diff --git a/README.md b/README.md index 8cb5694ee..bd198e723 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ # WebAssembly for Proxies (C++ host implementation) + +## How to Contribute + +See [CONTRIBUTING](CONTRIBUTING.md). diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 0bede2208..908ffe492 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -135,6 +135,15 @@ def proxy_wasm_cpp_host_repositories(): urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/archive/95bb82ce45c41d9100fd1ec15d2ffc67f7f3ceee.tar.gz"], ) + # Compile DB dependencies. + maybe( + http_archive, + name = "bazel_compdb", + sha256 = "acd2a9eaf49272bb1480c67d99b82662f005b596a8c11739046a4220ec73c4da", + strip_prefix = "bazel-compilation-database-40864791135333e1446a04553b63cbe744d358d0", + url = "https://github.com/grailbio/bazel-compilation-database/archive/40864791135333e1446a04553b63cbe744d358d0.tar.gz", + ) + # Test dependencies. maybe( diff --git a/tools/gen_compilation_database.py b/tools/gen_compilation_database.py new file mode 100755 index 000000000..bff3d82d5 --- /dev/null +++ b/tools/gen_compilation_database.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 + +# 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. + +import argparse +import json +import os +import shlex +import subprocess +from pathlib import Path + +# This is copied from https://github.com/envoyproxy/envoy and remove unnecessary code. + +# This method is equivalent to https://github.com/grailbio/bazel-compilation-database/blob/master/generate.py +def generate_compilation_database(args): + # We need to download all remote outputs for generated source code. This option lives here to override those + # specified in bazelrc. + bazel_startup_options = shlex.split(os.environ.get("BAZEL_STARTUP_OPTION_LIST", "")) + bazel_options = shlex.split(os.environ.get("BAZEL_BUILD_OPTION_LIST", "")) + [ + "--remote_download_outputs=all", + ] + + source_dir_targets = args.bazel_targets + + subprocess.check_call(["bazel", *bazel_startup_options, "build"] + bazel_options + [ + "--aspects=@bazel_compdb//:aspects.bzl%compilation_database_aspect", + "--output_groups=compdb_files,header_files" + ] + source_dir_targets) + + execroot = subprocess.check_output( + ["bazel", *bazel_startup_options, "info", *bazel_options, + "execution_root"]).decode().strip() + + db_entries = [] + for db in Path(execroot).glob('**/*.compile_commands.json'): + db_entries.extend(json.loads(db.read_text())) + + def replace_execroot_marker(db_entry): + if 'directory' in db_entry and db_entry['directory'] == '__EXEC_ROOT__': + db_entry['directory'] = execroot + if 'command' in db_entry: + db_entry['command'] = ( + db_entry['command'].replace('-isysroot __BAZEL_XCODE_SDKROOT__', '')) + return db_entry + + return list(map(replace_execroot_marker, db_entries)) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Generate JSON compilation database') + parser.add_argument('--include_external', action='https://github.com/store_true') + parser.add_argument('--include_genfiles', action='https://github.com/store_true') + parser.add_argument('--include_headers', action='https://github.com/store_true') + parser.add_argument('--include_all', action='https://github.com/store_true') + parser.add_argument( + '--system-clang', + action='https://github.com/store_true', + help= + 'Use `clang++` instead of the bazel wrapper for commands. This may help if `clangd` cannot find/run the tools.' + ) + parser.add_argument('bazel_targets', nargs='*', default=[]) + + args = parser.parse_args() + db = generate_compilation_database(args) + + with open("compile_commands.json", "w") as db_file: + json.dump(db, db_file, indent=2) From 63cb9c1a40d8e6382d3f302721e09b8c45466661 Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Fri, 13 Dec 2024 13:01:25 -0600 Subject: [PATCH 02/21] Fix references to prefix_wasm_api (#420) Signed-off-by: Keith Mattix II --- bazel/external/wasmtime.BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazel/external/wasmtime.BUILD b/bazel/external/wasmtime.BUILD index 79a331f18..27da86e46 100644 --- a/bazel/external/wasmtime.BUILD +++ b/bazel/external/wasmtime.BUILD @@ -21,7 +21,7 @@ genrule( "crates/c-api/include/wasm.h", ], outs = [ - "include/prefixed_wasm.h", + "crates/c-api/include/prefixed_wasm.h", ], cmd = """ sed -e 's/\\ wasm_/\\ wasmtime_wasm_/g' \ From c4d7bb0fda912e24c64daf2aa749ec54cec99412 Mon Sep 17 00:00:00 2001 From: Matt Leon Date: Thu, 19 Dec 2024 13:59:36 -0500 Subject: [PATCH 03/21] feat(go-sdk): add wasi hostcalls used by the Go SDK (#427) The full Go sdk imports hostcalls not currently exported to the wasm module, making the wasm module fail on instantiation. Per discussion with the Go core maintainers, these functions do not need to be implemented, but they must be present. Signed-off-by: Matt Leon --- include/proxy-wasm/exports.h | 10 +++++++--- src/exports.cc | 25 +++++++++++++++++++++++++ src/wasm.cc | 5 ++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/include/proxy-wasm/exports.h b/include/proxy-wasm/exports.h index 376a4d3b6..91c51150c 100644 --- a/include/proxy-wasm/exports.h +++ b/include/proxy-wasm/exports.h @@ -139,10 +139,13 @@ Word wasi_unstable_fd_read(Word, Word, Word, Word); Word wasi_unstable_fd_seek(Word, int64_t, Word, Word); Word wasi_unstable_fd_close(Word); Word wasi_unstable_fd_fdstat_get(Word fd, Word statOut); +Word wasi_unstable_fd_fdstat_set_flags(Word fd, Word flags); Word wasi_unstable_environ_get(Word, Word); Word wasi_unstable_environ_sizes_get(Word count_ptr, Word buf_size_ptr); Word wasi_unstable_args_get(Word argc_ptr, Word argv_buf_size_ptr); Word wasi_unstable_args_sizes_get(Word argc_ptr, Word argv_buf_size_ptr); +Word wasi_unstable_sched_yield(); +Word wasi_unstable_poll_oneoff(Word in, Word out, Word nsubscriptions, Word nevents); void wasi_unstable_proc_exit(Word); Word wasi_unstable_clock_time_get(Word, uint64_t, Word); Word wasi_unstable_random_get(Word, Word); @@ -170,9 +173,10 @@ void emscripten_notify_memory_growth(Word); _f(continue_stream) _f(close_stream) _f(get_log_level) #define FOR_ALL_WASI_FUNCTIONS(_f) \ - _f(fd_write) _f(fd_read) _f(fd_seek) _f(fd_close) _f(fd_fdstat_get) _f(environ_get) \ - _f(environ_sizes_get) _f(args_get) _f(args_sizes_get) _f(clock_time_get) _f(random_get) \ - _f(proc_exit) _f(path_open) _f(fd_prestat_get) _f(fd_prestat_dir_name) + _f(fd_write) _f(fd_read) _f(fd_seek) _f(fd_close) _f(fd_fdstat_get) _f(fd_fdstat_set_flags) \ + _f(environ_get) _f(environ_sizes_get) _f(args_get) _f(args_sizes_get) _f(clock_time_get) \ + _f(random_get) _f(sched_yield) _f(poll_oneoff) _f(proc_exit) _f(path_open) \ + _f(fd_prestat_get) _f(fd_prestat_dir_name) // Helpers to generate a stub to pass to VM, in place of a restricted proxy-wasm capability. #define _CREATE_PROXY_WASM_STUB(_fn) \ diff --git a/src/exports.cc b/src/exports.cc index 0290dcf0f..25ca06c9d 100644 --- a/src/exports.cc +++ b/src/exports.cc @@ -646,6 +646,9 @@ Word grpc_send(Word token, Word message_ptr, Word message_size, Word end_stream) return context->grpcSend(token, message.value(), end_stream != 0U); } +// WASIp1 typings in comments sourced from +// https://github.com/WebAssembly/wasi-libc/blob/446cb3f1aa21f9b1a1eab372f82d65d19003e924/libc-bottom-half/headers/public/wasi/api.h + // __wasi_errno_t path_open(__wasi_fd_t fd, __wasi_lookupflags_t dirflags, const char *path, // size_t path_len, __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base, __wasi_rights_t // fs_rights_inheriting, __wasi_fdflags_t fdflags, __wasi_fd_t *retptr0) @@ -776,6 +779,13 @@ Word wasi_unstable_fd_fdstat_get(Word fd, Word statOut) { return 0; // __WASI_ESUCCESS } +// __wasi_errno_t __wasi_fd_fdstat_set_flags(__wasi_fd_t fd, __wasi_fdflags_t flags) +Word wasi_unstable_fd_fdstat_set_flags(Word /*fd*/, Word /*flags*/) { + // Flags that can be specified: append, dsync, nonblock, rsync, and sync. Proxy-wasm only supports + // STDOUT and STDERR, but none of these flags have any effect in Proxy-Wasm. + return 52; // __WASI_ERRNO_ENOSYS +} + // __wasi_errno_t __wasi_environ_get(char **environ, char *environ_buf); Word wasi_unstable_environ_get(Word environ_array_ptr, Word environ_buf) { auto *context = contextOrEffectiveContext(); @@ -879,6 +889,21 @@ Word wasi_unstable_random_get(Word result_buf_ptr, Word buf_len) { return 0; // __WASI_ESUCCESS } +// __wasi_errno_t __wasi_sched_yield() +Word wasi_unstable_sched_yield() { + // Per POSIX man pages, it is valid to return success if the calling thread is the only thread in + // the highest priority list. This is vacuously true for wasm without threads. There are no valid + // error cases defined. + return 0; // __WASI_ESUCCESS +} + +// __wasi_errno_t __wasi_poll_oneoff(const __wasi_subscription_t *in, __wasi_event_t *out, +// __wasi_size_t nsubscriptions, __wasi_size_t *nevents) +Word wasi_unstable_poll_oneoff(Word /*in*/, Word /*out*/, Word /*nsubscriptions*/, + Word /*nevents_ptr*/) { + return 52; // __WASI_ERRNO_ENOSYS +} + // void __wasi_proc_exit(__wasi_exitcode_t rval); void wasi_unstable_proc_exit(Word /*exit_code*/) { auto *context = contextOrEffectiveContext(); diff --git a/src/wasm.cc b/src/wasm.cc index cb1dd9b3a..e8a7ce436 100644 --- a/src/wasm.cc +++ b/src/wasm.cc @@ -394,7 +394,10 @@ void WasmBase::startVm(ContextBase *root_context) { // time "wasi_unstable.clock_time_get", "wasi_snapshot_preview1.clock_time_get", // random - "wasi_unstable.random_get", "wasi_snapshot_preview1.random_get"}); + "wasi_unstable.random_get", "wasi_snapshot_preview1.random_get", + // Go runtime initialization + "wasi_unstable.fd_fdstat_get", "wasi_snapshot_preview1.fd_fdstat_get", + "wasi_unstable.fd_fdstat_set_flags", "wasi_snapshot_preview1.fd_fdstat_set_flags"}); if (_initialize_) { // WASI reactor. _initialize_(root_context); From 3095c6822328749f078f104d9b90cfd66eb80924 Mon Sep 17 00:00:00 2001 From: Michael Warres Date: Sat, 12 Jul 2025 19:01:05 -0400 Subject: [PATCH 04/21] chore: workflow runner fixes (#436) Assorted changes to get workflows working again: - Update format workflows to use ubuntu-22.04 - Update windows-2019 to windows-2022 and add a missing include needed to build with that - Enable manual triggering of workflows Fixes #435 --------- Signed-off-by: Michael Warres --- .github/workflows/format.yml | 10 ++++++---- .github/workflows/test.yml | 4 +++- include/proxy-wasm/signature_util.h | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index de71b24cc..1004f123f 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -31,6 +31,8 @@ on: schedule: - cron: '0 0 * * *' + workflow_dispatch: + concurrency: group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} @@ -41,7 +43,7 @@ jobs: addlicense: name: verify licenses - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 @@ -61,7 +63,7 @@ jobs: buildifier: name: check format with buildifier - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 @@ -99,7 +101,7 @@ jobs: clang_format: name: check format with clang-format - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 @@ -115,7 +117,7 @@ jobs: clang_tidy: name: check format with clang-tidy - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 811c6a369..5a6dd8f49 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,6 +31,8 @@ on: schedule: - cron: '0 0 * * *' + workflow_dispatch: + concurrency: group: ${{ github.head_ref || github.run_id }}-${{ github.workflow }} @@ -127,7 +129,7 @@ jobs: flags: --config=clang-tsan - name: 'NullVM on Windows/x86_64' engine: 'null' - os: windows-2019 + os: windows-2022 arch: x86_64 action: test targets: -//test/fuzz/... diff --git a/include/proxy-wasm/signature_util.h b/include/proxy-wasm/signature_util.h index 68579dcd1..a5c9c39df 100644 --- a/include/proxy-wasm/signature_util.h +++ b/include/proxy-wasm/signature_util.h @@ -14,6 +14,7 @@ #pragma once +#include #include namespace proxy_wasm { From 7a212bcaa2b68716e71bd6b8d7206acd53bb1ab1 Mon Sep 17 00:00:00 2001 From: Michael Warres Date: Sat, 12 Jul 2025 23:58:32 -0400 Subject: [PATCH 05/21] feat: add knob to customise on{Request,Response}Headers StopIteration behavior (#434) Add protected ContextBase::allow_on_headers_stop_iteration_ field that can be used by host implementations to control whether or not ContextBase propagates FilterHeaderStatus::StopIteration returned by onRequestHeaders() or onResponseHeaders() without modification. Follow-on envoyproxy/envoy#40213 adds an option in Envoy WasmFilter PluginConfig that sets the value of this field. For details, see [Envoy Wasm / Proxy-Wasm support for FilterHeadersStatus::StopIteration](https://docs.google.com/document/d/1Whd1C0k-H2NHrPOmlAqqauFz6ObSTP017juJIYyciB0/edit?usp=sharing). This PR is one part of implementing [Option B: WasmFilter config knob](https://docs.google.com/document/d/1Whd1C0k-H2NHrPOmlAqqauFz6ObSTP017juJIYyciB0/edit?tab=t.0#bookmark=id.5wxldlapsp54). Note that default behavior of proxy-wasm-cpp-host and ContextBase is unchanged. --------- Signed-off-by: Michael Warres --- include/proxy-wasm/context.h | 7 +++ src/context.cc | 10 ++-- test/BUILD | 15 ++++++ test/stop_iteration_test.cc | 81 ++++++++++++++++++++++++++++++++ test/test_data/BUILD | 5 ++ test/test_data/stop_iteration.cc | 31 ++++++++++++ test/utility.h | 2 + 7 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 test/stop_iteration_test.cc create mode 100644 test/test_data/stop_iteration.cc diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index 12937041f..7f675525c 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -397,6 +397,13 @@ class ContextBase : public RootInterface, bool destroyed_ = false; bool stream_failed_ = false; // Set true after failStream is called in case of VM failure. + // If true, convertVmCallResultToFilterHeadersStatus() propagates + // FilterHeadersStatus::StopIteration unmodified to callers. If false, it + // translates FilterHeaderStatus::StopIteration to + // FilterHeadersStatus::StopAllIterationAndWatermark, which is the default + // behavior for v0.2.* of the Proxy-Wasm ABI. + bool allow_on_headers_stop_iteration_ = false; + private: // helper functions FilterHeadersStatus convertVmCallResultToFilterHeadersStatus(uint64_t result); diff --git a/src/context.cc b/src/context.cc index 5353a52a5..d8dbc9a2a 100644 --- a/src/context.cc +++ b/src/context.cc @@ -493,10 +493,12 @@ FilterHeadersStatus ContextBase::convertVmCallResultToFilterHeadersStatus(uint64 result > static_cast(FilterHeadersStatus::StopAllIterationAndWatermark)) { return FilterHeadersStatus::StopAllIterationAndWatermark; } - if (result == static_cast(FilterHeadersStatus::StopIteration)) { - // Always convert StopIteration (pause processing headers, but continue processing body) - // to StopAllIterationAndWatermark (pause all processing), since the former breaks all - // assumptions about HTTP processing. + if (result == static_cast(FilterHeadersStatus::StopIteration) && + !allow_on_headers_stop_iteration_) { + // Default behavior for Proxy-Wasm 0.2.* ABI is to translate StopIteration + // (pause processing headers, but continue processing body) to + // StopAllIterationAndWatermark (pause all processing), as described in + // https://github.com/proxy-wasm/proxy-wasm-cpp-host/issues/143. return FilterHeadersStatus::StopAllIterationAndWatermark; } return static_cast(result); diff --git a/test/BUILD b/test/BUILD index 61973ce17..73787e4b0 100644 --- a/test/BUILD +++ b/test/BUILD @@ -132,6 +132,21 @@ cc_test( ], ) +cc_test( + name = "stop_iteration_test", + srcs = ["stop_iteration_test.cc"], + data = [ + "//test/test_data:stop_iteration.wasm", + ], + linkstatic = 1, + deps = [ + ":utility_lib", + "//:lib", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "security_test", srcs = ["security_test.cc"], diff --git a/test/stop_iteration_test.cc b/test/stop_iteration_test.cc new file mode 100644 index 000000000..9ff443f24 --- /dev/null +++ b/test/stop_iteration_test.cc @@ -0,0 +1,81 @@ +// Copyright 2025 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 "gtest/gtest.h" +#include "include/proxy-wasm/wasm.h" +#include "test/utility.h" + +namespace proxy_wasm { + +INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines()), + [](const testing::TestParamInfo &info) { + return info.param; + }); + +// TestVm is parameterized for each engine and creates a VM on construction. +TEST_P(TestVm, AllowOnHeadersStopIteration) { + // Read the wasm source. + auto source = readTestWasmFile("stop_iteration.wasm"); + ASSERT_FALSE(source.empty()); + + // Create a WasmBase and load the plugin. + auto wasm = std::make_shared(std::move(vm_)); + ASSERT_TRUE(wasm->load(source, /*allow_precompiled=*/false)); + ASSERT_TRUE(wasm->initialize()); + + // Create a plugin. + const auto plugin = std::make_shared( + /*name=*/"test", /*root_id=*/"", /*vm_id=*/"", + /*engine=*/wasm->wasm_vm()->getEngineName(), /*plugin_config=*/"", + /*fail_open=*/false, /*key=*/""); + + // Create root context, call onStart() and onConfigure() + ContextBase *root_context = wasm->start(plugin); + ASSERT_TRUE(root_context != nullptr); + ASSERT_TRUE(wasm->configure(root_context, plugin)); + + auto wasm_handle = std::make_shared(wasm); + auto plugin_handle = std::make_shared(wasm_handle, plugin); + + // By default, stream context onRequestHeaders and onResponseHeaders + // translates FilterHeadersStatus::StopIteration to + // FilterHeadersStatus::StopAllIterationAndWatermark. + { + auto stream_context = TestContext(wasm.get(), root_context->id(), plugin_handle); + stream_context.onCreate(); + EXPECT_EQ(stream_context.onRequestHeaders(/*headers=*/0, /*end_of_stream=*/false), + FilterHeadersStatus::StopAllIterationAndWatermark); + EXPECT_EQ(stream_context.onResponseHeaders(/*headers=*/0, /*end_of_stream=*/false), + FilterHeadersStatus::StopAllIterationAndWatermark); + stream_context.onDone(); + stream_context.onDelete(); + } + ASSERT_FALSE(wasm->isFailed()); + + // Create a stream context that propagates FilterHeadersStatus::StopIteration. + { + auto stream_context = TestContext(wasm.get(), root_context->id(), plugin_handle); + stream_context.set_allow_on_headers_stop_iteration(true); + stream_context.onCreate(); + EXPECT_EQ(stream_context.onRequestHeaders(/*headers=*/0, /*end_of_stream=*/false), + FilterHeadersStatus::StopIteration); + EXPECT_EQ(stream_context.onResponseHeaders(/*headers=*/0, /*end_of_stream=*/false), + FilterHeadersStatus::StopIteration); + stream_context.onDone(); + stream_context.onDelete(); + } + ASSERT_FALSE(wasm->isFailed()); +} + +} // namespace proxy_wasm diff --git a/test/test_data/BUILD b/test/test_data/BUILD index bd70b8eb9..e5ecd439e 100644 --- a/test/test_data/BUILD +++ b/test/test_data/BUILD @@ -89,3 +89,8 @@ proxy_wasm_cc_binary( name = "http_logging.wasm", srcs = ["http_logging.cc"], ) + +proxy_wasm_cc_binary( + name = "stop_iteration.wasm", + srcs = ["stop_iteration.cc"], +) diff --git a/test/test_data/stop_iteration.cc b/test/test_data/stop_iteration.cc new file mode 100644 index 000000000..55594285f --- /dev/null +++ b/test/test_data/stop_iteration.cc @@ -0,0 +1,31 @@ +// Copyright 2025 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 "proxy_wasm_intrinsics.h" + +class StopIterationContext : public Context { +public: + explicit StopIterationContext(uint32_t id, RootContext *root) : Context(id, root) {} + + FilterHeadersStatus onRequestHeaders(uint32_t headers, bool end_of_stream) override { + return FilterHeadersStatus::StopIteration; + } + + FilterHeadersStatus onResponseHeaders(uint32_t headers, bool end_of_stream) override { + return FilterHeadersStatus::StopIteration; + } +}; + +static RegisterContextFactory register_StaticContext(CONTEXT_FACTORY(StopIterationContext), + ROOT_FACTORY(RootContext)); diff --git a/test/utility.h b/test/utility.h index 27b3b0493..ccd2a59b6 100644 --- a/test/utility.h +++ b/test/utility.h @@ -133,6 +133,8 @@ class TestContext : public ContextBase { .count(); } + void set_allow_on_headers_stop_iteration(bool allow) { allow_on_headers_stop_iteration_ = allow; } + private: std::string log_; static std::string global_log_; From 65bb78fbf8beb6d3670701d35711e691c0c4c4ce Mon Sep 17 00:00:00 2001 From: Michael Warres Date: Sat, 12 Jul 2025 23:59:47 -0400 Subject: [PATCH 06/21] add leonm1@ to CODEOWNERS (#437) Signed-off-by: Michael Warres --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index e0a504f38..e4190bb47 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @PiotrSikora @martijneken @mpwarres +* @PiotrSikora @martijneken @mpwarres @leonm1 From ad8303f41070c1689ebdba69935ca360d17dba8a Mon Sep 17 00:00:00 2001 From: Michael Warres Date: Tue, 15 Jul 2025 10:52:58 -0400 Subject: [PATCH 07/21] chore!:remove support for wavm (#438) * remove support for wavm Signed-off-by: Michael Warres * apply clang-format Signed-off-by: Michael Warres --------- Signed-off-by: Michael Warres Signed-off-by: Matt Leon --- .github/workflows/test.yml | 8 - BUILD | 31 --- bazel/BUILD | 5 - bazel/external/wavm.BUILD | 28 -- bazel/repositories.bzl | 27 -- bazel/select.bzl | 7 - include/proxy-wasm/wasm.h | 2 +- include/proxy-wasm/wasm_vm.h | 7 +- include/proxy-wasm/wavm.h | 26 -- src/wavm/wavm.cc | 492 ----------------------------------- test/runtime_test.cc | 24 +- test/utility.cc | 3 - test/utility.h | 7 - test/wasm_vm_test.cc | 6 - 14 files changed, 7 insertions(+), 666 deletions(-) delete mode 100644 bazel/external/wavm.BUILD delete mode 100644 include/proxy-wasm/wavm.h delete mode 100644 src/wavm/wavm.cc diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5a6dd8f49..5f33c3316 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -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/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..38108bd81 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -263,30 +263,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..eaaaa3197 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(); 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, {}, {})); From 497e4ef09659a9ffe2e88c28a053528c8b9e0fd7 Mon Sep 17 00:00:00 2001 From: Matt Leon Date: Thu, 17 Jul 2025 09:29:11 -0400 Subject: [PATCH 08/21] build: compile with C++20 (#441) * build using c++20 std=c++20 is used by both v8 and Envoy. Switching to use it is necessary to build with more recent versions of v8, and will also reduce overall build surprises when importing proxy-wasm-cpp-host into Envoy. Signed-off-by: Michael Warres * change --config=clang-asan-strict to --config=clang-asan Signed-off-by: Michael Warres * chore: support clang-18 and ubuntu-24.04 These changes make Proxy-Wasm build cleanly with clang-18 and pass clang-tidy-18 checks. Signed-off-by: Matt Leon * chore: ignore c++20 + clang-18 + gcc-14 findings Signed-off-by: Matt Leon --------- Signed-off-by: Michael Warres Signed-off-by: Matt Leon Co-authored-by: Michael Warres --- .bazelrc | 9 ++++--- .clang-tidy | 15 +++++++++++ .github/workflows/format.yml | 14 +++++----- .github/workflows/test.yml | 38 +++++++++++++-------------- bazel/external/bazel_clang_tidy.patch | 11 -------- bazel/external/v8.patch | 5 +++- bazel/external/wasmedge.BUILD | 3 +++ bazel/repositories.bzl | 14 +++++----- src/null/null_plugin.cc | 1 - src/wasmedge/wasmedge.cc | 1 + test/utility.cc | 11 ++++---- test/utility.h | 3 +++ 12 files changed, 68 insertions(+), 57 deletions(-) diff --git a/.bazelrc b/.bazelrc index ab9a27f84..97009c8a9 100644 --- a/.bazelrc +++ b/.bazelrc @@ -10,6 +10,7 @@ build --action_env=PATH build:clang --action_env=BAZEL_COMPILER=clang build:clang --action_env=CC=clang build:clang --action_env=CXX=clang++ +build:clang --copt -Wno-pragma-once-outside-header --cxxopt -Wno-pragma-once-outside-header # Common flags for Clang sanitizers. build:clang-xsan --config=clang @@ -80,10 +81,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..df9f5c944 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,17 +1,28 @@ Checks: clang-*, + -clang-analyzer-core.CallAndMessage, -clang-analyzer-optin.portability.UnixAPI, -clang-analyzer-unix.Malloc, -clang-diagnostic-pragma-once-outside-header, + -clang-diagnostic-builtin-macro-redefined, cppcoreguidelines-pro-type-member-init, cppcoreguidelines-pro-type-static-cast-downcast, misc-*, -misc-non-private-member-variables-in-classes, + -misc-use-anonymous-namespace, + -misc-const-correctness, + -misc-include-cleaner, + -misc-unused-parameters, modernize-*, -modernize-avoid-c-arrays, -modernize-use-trailing-return-type, + -modernize-return-braced-init-list, + -modernize-use-default-member-init, + -modernize-type-traits, + -modernize-use-emplace, llvm-include-order, performance-*, -performance-no-int-to-ptr, + -performance-avoid-endl, portability-*, readability-*, -readability-convert-member-functions-to-static, @@ -19,5 +30,9 @@ Checks: clang-*, -readability-magic-numbers, -readability-make-member-function-const, -readability-simplify-boolean-expr, + -readability-identifier-length, + -readability-container-data-pointer, + -readability-redundant-casting, + -readability-avoid-return-with-void-value, WarningsAsErrors: '*' diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 1004f123f..fa4ba153c 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -43,7 +43,7 @@ jobs: addlicense: name: verify licenses - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v2 @@ -63,7 +63,7 @@ jobs: buildifier: name: check format with buildifier - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v2 @@ -101,29 +101,29 @@ jobs: clang_format: name: check format with clang-format - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v2 - name: Install dependencies (Linux) - run: sudo apt update -y && sudo apt install -y clang-format-12 + run: sudo apt update -y && sudo apt install -y clang-format-18 - name: Format (clang-format) run: | - find . -name "*.h" -o -name "*.cc" -o -name "*.proto" | grep -v ".pb." | xargs -n1 clang-format-12 -i + find . -name "*.h" -o -name "*.cc" -o -name "*.proto" | grep -v ".pb." | xargs -n1 clang-format-18 -i git diff --exit-code clang_tidy: name: check format with clang-tidy - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v2 - name: Install dependencies (Linux) - run: sudo apt update -y && sudo apt install -y clang-tidy-12 lld-12 && sudo ln -sf /usr/bin/lld-12 /usr/bin/lld + run: sudo apt update -y && sudo apt install -y clang-tidy-18 lld-18 && sudo ln -sf /usr/bin/lld-18 /usr/bin/lld - name: Bazel cache uses: PiotrSikora/cache@v2.1.7-with-skip-cache diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5f33c3316..dbb3eed27 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,7 +43,7 @@ jobs: test_data: name: build test data - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v2 @@ -111,19 +111,19 @@ jobs: include: - name: 'NullVM on Linux/x86_64' engine: 'null' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: x86_64 action: test flags: --config=gcc - name: 'NullVM on Linux/x86_64 with ASan' engine: 'null' - os: ubuntu-22.04 + os: ubuntu-24.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 + os: ubuntu-24.04 arch: x86_64 action: test flags: --config=clang-tsan @@ -136,7 +136,7 @@ jobs: - name: 'V8 on Linux/x86_64' engine: 'v8' repo: 'v8' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: x86_64 action: test flags: --config=clang --define=crypto=system @@ -144,7 +144,7 @@ jobs: - name: 'V8 on Linux/x86_64 with ASan' engine: 'v8' repo: 'v8' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: x86_64 action: test flags: --config=clang-asan @@ -152,7 +152,7 @@ jobs: - name: 'V8 on Linux/x86_64 with TSan' engine: 'v8' repo: 'v8' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: x86_64 action: test flags: --config=clang-tsan @@ -160,7 +160,7 @@ jobs: - name: 'V8 on Linux/x86_64 with GCC' engine: 'v8' repo: 'v8' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: x86_64 action: test flags: --config=gcc @@ -168,7 +168,7 @@ jobs: - name: 'V8 on Linux/aarch64' engine: 'v8' repo: 'v8' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: aarch64 action: test targets: -//test/fuzz/... @@ -185,7 +185,7 @@ jobs: - name: 'WAMR interp on Linux/x86_64' engine: 'wamr-interp' repo: 'com_github_bytecodealliance_wasm_micro_runtime' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: x86_64 action: test flags: --config=clang @@ -198,11 +198,11 @@ jobs: - name: 'WAMR jit on Linux/x86_64' engine: 'wamr-jit' repo: 'com_github_bytecodealliance_wasm_micro_runtime' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: x86_64 action: test flags: --config=clang - deps: lld-12 + deps: lld-18 cache: true - name: 'WAMR jit on macOS/x86_64' engine: 'wamr-jit' @@ -214,7 +214,7 @@ jobs: - name: 'WasmEdge on Linux/x86_64' engine: 'wasmedge' repo: 'com_github_wasmedge_wasmedge' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: x86_64 action: test flags: --config=clang @@ -227,21 +227,21 @@ jobs: - name: 'Wasmtime on Linux/x86_64' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: x86_64 action: test flags: --config=clang -c opt - name: 'Wasmtime on Linux/x86_64 with ASan' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' - os: ubuntu-22.04 + os: ubuntu-24.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' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: aarch64 action: build flags: --config=zig-cc-linux-aarch64 @@ -249,7 +249,7 @@ jobs: - name: 'Wasmtime on Linux/s390x' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' - os: ubuntu-22.04 + os: ubuntu-24.04 arch: s390x action: test flags: --config=clang --test_timeout=1800 diff --git a/bazel/external/bazel_clang_tidy.patch b/bazel/external/bazel_clang_tidy.patch index 9c84b3c7f..82711d83e 100644 --- a/bazel/external/bazel_clang_tidy.patch +++ b/bazel/external/bazel_clang_tidy.patch @@ -1,5 +1,4 @@ # 1. Treat .h files as C++ headers. -# 2. Hardcode clang-tidy-12. diff --git a/clang_tidy/clang_tidy.bzl b/clang_tidy/clang_tidy.bzl index 3a5ed07..5db5c6c 100644 @@ -15,13 +14,3 @@ index 3a5ed07..5db5c6c 100644 # start args passed to the compiler args.add("--") -diff --git a/clang_tidy/run_clang_tidy.sh b/clang_tidy/run_clang_tidy.sh -index 582bab1..b9ebb94 100755 ---- a/clang_tidy/run_clang_tidy.sh -+++ b/clang_tidy/run_clang_tidy.sh -@@ -11,4 +11,4 @@ shift - touch $OUTPUT - truncate -s 0 $OUTPUT - --clang-tidy "$@" -+clang-tidy-12 "$@" diff --git a/bazel/external/v8.patch b/bazel/external/v8.patch index 58e7f9ba0..ba1ae19dd 100644 --- a/bazel/external/v8.patch +++ b/bazel/external/v8.patch @@ -20,11 +20,14 @@ diff --git a/bazel/defs.bzl b/bazel/defs.bzl index e957c0fad3..063627b72b 100644 --- a/bazel/defs.bzl +++ b/bazel/defs.bzl -@@ -131,6 +131,7 @@ def _default_args(): +@@ -131,6 +131,10 @@ def _default_args(): "-Wno-redundant-move", "-Wno-return-type", "-Wno-stringop-overflow", + "-Wno-nonnull", ++ "-Wno-error=pessimizing-move", ++ "-Wno-error=dangling-reference", ++ "-Wno-error=dangling-pointer=", # Use GNU dialect, because GCC doesn't allow using # ##__VA_ARGS__ when in standards-conforming mode. "-std=gnu++17", diff --git a/bazel/external/wasmedge.BUILD b/bazel/external/wasmedge.BUILD index 1869bf969..2c6e89204 100644 --- a/bazel/external/wasmedge.BUILD +++ b/bazel/external/wasmedge.BUILD @@ -18,6 +18,9 @@ cmake( "WASMEDGE_BUILD_TOOLS": "Off", "WASMEDGE_FORCE_DISABLE_LTO": "On", }, + env = { + "CXXFLAGS": "-Wno-error=dangling-reference -Wno-error=maybe-uninitialized -Wno-error=array-bounds= -Wno-error=deprecated-declarations -std=c++20", + }, generate_args = ["-GNinja"], lib_source = ":srcs", out_static_libs = ["libwasmedge.a"], diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 38108bd81..94e9fc5f3 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. diff --git a/src/null/null_plugin.cc b/src/null/null_plugin.cc index 0f74496a2..689225687 100644 --- a/src/null/null_plugin.cc +++ b/src/null/null_plugin.cc @@ -26,7 +26,6 @@ #include #include -#include "include/proxy-wasm/null_plugin.h" #include "include/proxy-wasm/null_vm.h" #include "include/proxy-wasm/wasm.h" diff --git a/src/wasmedge/wasmedge.cc b/src/wasmedge/wasmedge.cc index 38b8a9c9c..596af0c9e 100644 --- a/src/wasmedge/wasmedge.cc +++ b/src/wasmedge/wasmedge.cc @@ -19,6 +19,7 @@ #include "wasmedge/wasmedge.h" +#include #include #include #include diff --git a/test/utility.cc b/test/utility.cc index b4c10053f..7bdf9d2ad 100644 --- a/test/utility.cc +++ b/test/utility.cc @@ -21,19 +21,18 @@ std::string TestContext::global_log_; std::vector getWasmEngines() { std::vector engines = { #if defined(PROXY_WASM_HOST_ENGINE_V8) - "v8", + "v8", #endif #if defined(PROXY_WASM_HOST_ENGINE_WAMR) - "wamr", + "wamr", #endif #if defined(PROXY_WASM_HOST_ENGINE_WASMEDGE) - "wasmedge", + "wasmedge", #endif #if defined(PROXY_WASM_HOST_ENGINE_WASMTIME) - "wasmtime", + "wasmtime", #endif - "" - }; + ""}; engines.pop_back(); return engines; } diff --git a/test/utility.h b/test/utility.h index eaaaa3197..0eb743037 100644 --- a/test/utility.h +++ b/test/utility.h @@ -192,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 From 1000bc25c77aee28383fc66648dad00b31e460aa Mon Sep 17 00:00:00 2001 From: Matt Leon Date: Sat, 26 Jul 2025 12:56:23 -0400 Subject: [PATCH 09/21] chore: update V8 to 13.8.258.26 (#442) * update V8 to 13.8.258.26 Signed-off-by: Michael Warres * add missing files to v8.patch Signed-off-by: Michael Warres * chore: Update v8 to use 13.8 interface Signed-off-by: Matt Leon * chore: use bazel repos for missing v8 dependencies Signed-off-by: Matt Leon * chore: fix test expectation Signed-off-by: Matt Leon * chore: disable failing test This test fails with the new V8 version Signed-off-by: Matt Leon * chore: fix sed to work on darwin BSD sed requires an extension to create a backup file when used with in-place editing. Signed-off-by: Matt Leon * fix: remove racy call to isolate->IsExecutionTerminating() Signed-off-by: Matt Leon * fix: remove V8's libatomic dependency Signed-off-by: Matt Leon * chore: use toolchains_llvm with clang 19.1.0 Fixes macos build Signed-off-by: Matt Leon * chore: update aarch64 build to run on native aarch64 runner Signed-off-by: Matt Leon * chore: update hermetic-llvm to be platform-agnostic and use in CI Signed-off-by: Matt Leon * chore: Silence tsan warnings inside V8 These warnings flag a Join() function protected by a mutex. Such a function marks that the racy operation has ended. Signed-off-by: Matt Leon --------- Signed-off-by: Michael Warres Signed-off-by: Matt Leon Co-authored-by: Michael Warres --- .bazelrc | 19 +- .github/workflows/test.yml | 17 +- bazel/BUILD | 2 + bazel/cc_defs.bzl | 22 ++ bazel/dependencies.bzl | 45 +++- bazel/dependencies_import.bzl | 3 + bazel/external/dragonbox.BUILD | 12 + bazel/external/fp16.BUILD | 15 ++ bazel/external/intel_ittapi.BUILD | 21 ++ bazel/external/simdutf.BUILD | 11 + bazel/external/v8.patch | 355 ++++++++++++++++++++++++++---- bazel/external/v8_include.patch | 41 ---- bazel/repositories.bzl | 101 +++++++-- bazel/tsan_suppressions.txt | 3 + src/v8/v8.cc | 87 ++++---- test/BUILD | 3 +- test/fuzz/BUILD | 2 +- test/runtime_test.cc | 2 +- test/wasm_vm_test.cc | 2 +- 19 files changed, 586 insertions(+), 177 deletions(-) create mode 100644 bazel/cc_defs.bzl create mode 100644 bazel/external/dragonbox.BUILD create mode 100644 bazel/external/fp16.BUILD create mode 100644 bazel/external/intel_ittapi.BUILD create mode 100644 bazel/external/simdutf.BUILD delete mode 100644 bazel/external/v8_include.patch create mode 100644 bazel/tsan_suppressions.txt diff --git a/.bazelrc b/.bazelrc index 97009c8a9..5a0373356 100644 --- a/.bazelrc +++ b/.bazelrc @@ -55,6 +55,7 @@ build:clang-tsan --config=clang-xsan build:clang-tsan --copt -DTHREAD_SANITIZER=1 build:clang-tsan --copt -fsanitize=thread build:clang-tsan --linkopt -fsanitize=thread +build:clang-tsan --test_env=TSAN_OPTIONS=suppressions=bazel/tsan_suppressions.txt # Use Clang-Tidy tool. build:clang-tidy --config=clang @@ -67,17 +68,14 @@ build:gcc --action_env=BAZEL_COMPILER=gcc build:gcc --action_env=CC=gcc build:gcc --action_env=CXX=g++ -# Use Zig C/C++ compiler. -build:zig-cc --incompatible_enable_cc_toolchain_resolution -build:zig-cc --extra_toolchains @zig_sdk//:aarch64-linux-gnu.2.28_toolchain -build:zig-cc --extra_toolchains @zig_sdk//:x86_64-linux-gnu.2.28_toolchain -build:zig-cc --host_copt=-fno-sanitize=undefined +build:hermetic-llvm --incompatible_enable_cc_toolchain_resolution +build:hermetic-llvm --action_env BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 +build:hermetic-llvm --extra_toolchains @emsdk//emscripten_toolchain:cc-toolchain-wasm -# Use Zig C/C++ compiler (cross-compile to Linux/aarch64). -build:zig-cc-linux-aarch64 --config=zig-cc -build:zig-cc-linux-aarch64 --platforms @zig_sdk//:linux_aarch64_platform -build:zig-cc-linux-aarch64 --run_under=qemu-aarch64-static -build:zig-cc-linux-aarch64 --test_env=QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ +build:hermetic-llvm-macos --config=hermetic-llvm +# Below flags mitigate https://github.com/bazel-contrib/toolchains_llvm/pull/229. +build:hermetic-llvm-macos --features=-libtool +build:hermetic-llvm-macos --features=-supports_dynamic_linker build --enable_platform_specific_config @@ -86,6 +84,7 @@ 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 build:windows --enable_runfiles diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dbb3eed27..7cb78e3b5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -139,7 +139,7 @@ jobs: os: ubuntu-24.04 arch: x86_64 action: test - flags: --config=clang --define=crypto=system + flags: --config=hermetic-llvm --define=crypto=system cache: true - name: 'V8 on Linux/x86_64 with ASan' engine: 'v8' @@ -147,7 +147,7 @@ jobs: os: ubuntu-24.04 arch: x86_64 action: test - flags: --config=clang-asan + flags: --config=hermetic-llvm --config=clang-asan cache: true - name: 'V8 on Linux/x86_64 with TSan' engine: 'v8' @@ -155,7 +155,7 @@ jobs: os: ubuntu-24.04 arch: x86_64 action: test - flags: --config=clang-tsan + flags: --config=hermetic-llvm --config=clang-tsan cache: true - name: 'V8 on Linux/x86_64 with GCC' engine: 'v8' @@ -168,12 +168,11 @@ jobs: - name: 'V8 on Linux/aarch64' engine: 'v8' repo: 'v8' - os: ubuntu-24.04 + os: ubuntu-24.04-arm arch: aarch64 action: test targets: -//test/fuzz/... - flags: --config=zig-cc-linux-aarch64 --@v8//bazel/config:v8_target_cpu=arm64 - deps: qemu-user-static libc6-arm64-cross + flags: --config=hermetic-llvm --@v8//bazel/config:v8_target_cpu=arm64 cache: true - name: 'V8 on macOS/x86_64' engine: 'v8' @@ -181,6 +180,7 @@ jobs: os: macos-13 arch: x86_64 action: test + flags: --config=hermetic-llvm-macos cache: true - name: 'WAMR interp on Linux/x86_64' engine: 'wamr-interp' @@ -241,11 +241,10 @@ jobs: - name: 'Wasmtime on Linux/aarch64' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' - os: ubuntu-24.04 + os: ubuntu-24.04-arm arch: aarch64 action: build - flags: --config=zig-cc-linux-aarch64 - deps: qemu-user-static libc6-arm64-cross + flags: --config=hermetic-llvm - name: 'Wasmtime on Linux/s390x' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' diff --git a/bazel/BUILD b/bazel/BUILD index a3487f891..15f323fa7 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -68,3 +68,5 @@ selects.config_setting_group( ":linux_s390x", ], ) + +exports_files(["tsan_suppressions.txt"]) diff --git a/bazel/cc_defs.bzl b/bazel/cc_defs.bzl new file mode 100644 index 000000000..5951de438 --- /dev/null +++ b/bazel/cc_defs.bzl @@ -0,0 +1,22 @@ +# Copyright 2025 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. + +load("@rules_cc//cc:defs.bzl", _cc_test = "cc_test") +load("@rules_fuzzing//fuzzing:cc_defs.bzl", _cc_fuzz_test = "cc_fuzz_test") + +def cc_test(data = [], **kwargs): + _cc_test(data = data + ["//bazel:tsan_suppressions.txt"], **kwargs) + +def cc_fuzz_test(data = [], **kwargs): + _cc_fuzz_test(data = data + ["//bazel:tsan_suppressions.txt"], **kwargs) diff --git a/bazel/dependencies.bzl b/bazel/dependencies.bzl index 7b5c5fcbd..683fb9964 100644 --- a/bazel/dependencies.bzl +++ b/bazel/dependencies.bzl @@ -12,13 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@bazel-zig-cc//toolchain:defs.bzl", zig_register_toolchains = "register_toolchains") load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") +load("@envoy_toolshed//sysroot:sysroot.bzl", "setup_sysroots") load("@proxy_wasm_cpp_host//bazel/cargo/wasmsign/remote:crates.bzl", wasmsign_crate_repositories = "crate_repositories") load("@proxy_wasm_cpp_host//bazel/cargo/wasmtime/remote:crates.bzl", wasmtime_crate_repositories = "crate_repositories") load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") load("@rules_rust//crate_universe:repositories.bzl", "crate_universe_dependencies") load("@rules_rust//rust:repositories.bzl", "rust_repositories", "rust_repository_set") +load("@toolchains_llvm//toolchain:deps.bzl", "bazel_toolchain_dependencies") +load("@toolchains_llvm//toolchain:rules.bzl", "llvm_toolchain") def proxy_wasm_cpp_host_dependencies(): # Bazel extensions. @@ -52,14 +54,39 @@ def proxy_wasm_cpp_host_dependencies(): ) crate_universe_dependencies(bootstrap = True) - zig_register_toolchains( - version = "0.9.1", - url_format = "https://ziglang.org/download/%7Bversion%7D/zig-%7Bhost_platform%7D-%7Bversion%7D.tar.xz", - host_platform_sha256 = { - "linux-aarch64": "5d99a39cded1870a3fa95d4de4ce68ac2610cca440336cfd252ffdddc2b90e66", - "linux-x86_64": "be8da632c1d3273f766b69244d80669fe4f5e27798654681d77c992f17c237d7", - "macos-aarch64": "8c473082b4f0f819f1da05de2dbd0c1e891dff7d85d2c12b6ee876887d438287", - "macos-x86_64": "2d94984972d67292b55c1eb1c00de46580e9916575d083003546e9a01166754c", + setup_sysroots() + bazel_toolchain_dependencies() + llvm_toolchain( + name = "llvm_toolchain", + llvm_version = "19.1.0", + sha256 = { + "linux-x86_64": "cee77d641690466a193d9b88c89705de1c02bbad46bde6a3b126793c0a0f2923", + "linux-aarch64": "7bb54afd330fe1a1c2d4c593fa1e2dbe2abd9bf34fb3597994ff41e443cf144b", + "darwin-aarch64": "9da86f64a99f5ce9b679caf54e938736ca269c5e069d0c94ad08b995c5f25c16", + "darwin-x86_64": "264f2f1e8b67f066749349ae8b4943d346cd44e099464164ef21b42a57663540", + }, + strip_prefix = { + "linux-x86_64": "LLVM-19.1.0-Linux-X64", + "linux-aarch64": "clang+llvm-19.1.0-aarch64-linux-gnu", + "darwin-aarch64": "LLVM-19.1.0-macOS-ARM64", + "darwin-x86_64": "LLVM-19.1.0-macOS-X64", + }, + urls = { + "linux-x86_64": ["https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.0/LLVM-19.1.0-Linux-X64.tar.xz"], + "linux-aarch64": ["https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.0/clang+llvm-19.1.0-aarch64-linux-gnu.tar.xz"], + "darwin-aarch64": ["https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.0/LLVM-19.1.0-macOS-ARM64.tar.xz"], + "darwin-x86_64": ["https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.0/LLVM-19.1.0-macOS-X64.tar.xz"], + }, + ) + + llvm_toolchain( + name = "llvm_aarch64", + llvm_version = "19.1.0", + toolchain_roots = { + "": "@llvm_toolchain_llvm//", + }, + sysroot = { + "linux-aarch64": "@sysroot_linux_arm64//:sysroot", }, ) diff --git a/bazel/dependencies_import.bzl b/bazel/dependencies_import.bzl index 1f23f7d0b..e4cf5e879 100644 --- a/bazel/dependencies_import.bzl +++ b/bazel/dependencies_import.bzl @@ -13,11 +13,14 @@ # limitations under the License. load("@fuzzing_py_deps//:requirements.bzl", pip_fuzzing_dependencies = "install_deps") +load("@llvm_toolchain//:toolchains.bzl", "llvm_register_toolchains") load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies") load("@v8_python_deps//:requirements.bzl", pip_v8_dependencies = "install_deps") def proxy_wasm_cpp_host_dependencies_import(): + llvm_register_toolchains() + rules_foreign_cc_dependencies() rules_fuzzing_dependencies() diff --git a/bazel/external/dragonbox.BUILD b/bazel/external/dragonbox.BUILD new file mode 100644 index 000000000..d0bdf231e --- /dev/null +++ b/bazel/external/dragonbox.BUILD @@ -0,0 +1,12 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +licenses(["notice"]) # Apache 2 + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "dragonbox", + srcs = [], + hdrs = ["include/dragonbox/dragonbox.h"], + includes = ["include/"], +) diff --git a/bazel/external/fp16.BUILD b/bazel/external/fp16.BUILD new file mode 100644 index 000000000..f3fbfda1f --- /dev/null +++ b/bazel/external/fp16.BUILD @@ -0,0 +1,15 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +licenses(["notice"]) # MIT + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "FP16", + hdrs = [ + "include/fp16.h", + "include/fp16/bitcasts.h", + "include/fp16/fp16.h", + ], + includes = ["include/"], +) diff --git a/bazel/external/intel_ittapi.BUILD b/bazel/external/intel_ittapi.BUILD new file mode 100644 index 000000000..13351d38a --- /dev/null +++ b/bazel/external/intel_ittapi.BUILD @@ -0,0 +1,21 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +licenses(["notice"]) + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "lib_ittapi", + srcs = [ + "include/ittnotify.h", + "include/jitprofiling.h", + "src/ittnotify/ittnotify_config.h", + "src/ittnotify/jitprofiling.c", + ], + hdrs = [ + "include/ittnotify.h", + "src/ittnotify/ittnotify_types.h", + ], + includes = ["include/"], + visibility = ["//visibility:public"], +) diff --git a/bazel/external/simdutf.BUILD b/bazel/external/simdutf.BUILD new file mode 100644 index 000000000..ee4896494 --- /dev/null +++ b/bazel/external/simdutf.BUILD @@ -0,0 +1,11 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +licenses(["notice"]) # Apache 2 + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "simdutf", + srcs = ["simdutf.cpp"], + hdrs = ["simdutf.h"], +) diff --git a/bazel/external/v8.patch b/bazel/external/v8.patch index ba1ae19dd..a124cf9a5 100644 --- a/bazel/external/v8.patch +++ b/bazel/external/v8.patch @@ -1,13 +1,20 @@ -# 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. +From bc2a85e39fd55879b9baed51429c08b27d5514c8 Mon Sep 17 00:00:00 2001 +From: Matt Leon +Date: Wed, 16 Jul 2025 16:55:02 -0400 +Subject: [PATCH 1/7] Disable pointer compression + +Pointer compression limits the maximum number of WasmVMs. + +Signed-off-by: Matt Leon +--- + BUILD.bazel | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) 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", @@ -16,45 +23,80 @@ index 4e89f90e7e..3fcb38b3f3 100644 ) # Default setting for v8_enable_pointer_compression. +-- +2.50.0.727.gbf7dc18ff4-goog + + +From 61898e9a63ac89a37261c081b84714cfc400a4b1 Mon Sep 17 00:00:00 2001 +From: Matt Leon +Date: Wed, 16 Jul 2025 16:56:31 -0400 +Subject: [PATCH 2/7] Restore _allowlist_function_transition + +Reverts 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). + +Signed-off-by: Matt Leon +--- + bazel/defs.bzl | 3 +++ + bazel/v8-non-pointer-compression.bzl | 11 +++++++++++ + 2 files changed, 14 insertions(+) + 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,10 @@ def _default_args(): - "-Wno-redundant-move", - "-Wno-return-type", - "-Wno-stringop-overflow", -+ "-Wno-nonnull", -+ "-Wno-error=pessimizing-move", -+ "-Wno-error=dangling-reference", -+ "-Wno-error=dangling-pointer=", - # 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, +-- +2.50.0.727.gbf7dc18ff4-goog + + +From 4a6e7158fd4ca48c75c8e33ea15760c9beea1d2f Mon Sep 17 00:00:00 2001 +From: Matt Leon +Date: Wed, 16 Jul 2025 16:56:52 -0400 +Subject: [PATCH 3/7] Don't expose Wasm C API (only Wasm C++ API). + +Signed-off-by: Matt Leon +--- + src/wasm/c-api.cc | 4 ++++ + 1 file changed, 4 insertions(+) + 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 @@ -63,9 +105,242 @@ 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" + +#endif +-- +2.50.0.727.gbf7dc18ff4-goog + + +From 7b593eb8086dcfe9012d4fa694d622f21dadb731 Mon Sep 17 00:00:00 2001 +From: Matt Leon +Date: Wed, 16 Jul 2025 16:58:02 -0400 +Subject: [PATCH 4/7] Stub out fast_float for bazel-supplied version + +Signed-off-by: Matt Leon +--- + BUILD.bazel | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/BUILD.bazel b/BUILD.bazel +index 0a693b7ee10..eafd9dad20c 100644 +--- a/BUILD.bazel ++++ b/BUILD.bazel +@@ -4438,7 +4438,7 @@ v8_library( + ], + deps = [ + ":lib_dragonbox", +- "//third_party/fast_float/src:fast_float", ++ "@fast_float//:fast_float", + ":lib_fp16", + ":simdutf", + ":v8_libbase", +-- +2.50.0.727.gbf7dc18ff4-goog + + +From b442d34b12dd513946f509d9db86839ce8aa4d7f Mon Sep 17 00:00:00 2001 +From: Matt Leon +Date: Wed, 16 Jul 2025 20:04:05 -0400 +Subject: [PATCH 5/7] Stub out vendored dependencies for bazel-sourced versions + +Signed-off-by: Matt Leon +--- + BUILD.bazel | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/BUILD.bazel b/BUILD.bazel +index eafd9dad20c..ce36666e36e 100644 +--- a/BUILD.bazel ++++ b/BUILD.bazel +@@ -4437,10 +4437,10 @@ v8_library( + ":noicu/generated_torque_definitions", + ], + deps = [ +- ":lib_dragonbox", ++ "@dragonbox//:dragonbox", + "@fast_float//:fast_float", +- ":lib_fp16", +- ":simdutf", ++ "@fp16//:FP16", ++ "@simdutf//:simdutf", + ":v8_libbase", + "@abseil-cpp//absl/container:btree", + "@abseil-cpp//absl/container:flat_hash_map", +-- +2.50.0.727.gbf7dc18ff4-goog + + +From e0b8f32cc057a3c0875437d5d54d012cabcab458 Mon Sep 17 00:00:00 2001 +From: Matt Leon +Date: Wed, 16 Jul 2025 20:29:10 -0400 +Subject: [PATCH 6/7] Add build flags to make V8 compile with GCC + +Signed-off-by: Matt Leon +--- + bazel/defs.bzl | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/bazel/defs.bzl b/bazel/defs.bzl +index 14d7ace5e59..c7a48d4e805 100644 +--- a/bazel/defs.bzl ++++ b/bazel/defs.bzl +@@ -117,6 +117,9 @@ def _default_args(): + "-Wno-implicit-int-float-conversion", + "-Wno-deprecated-copy", + "-Wno-non-virtual-dtor", ++ "-Wno-invalid-offsetof", ++ "-Wno-dangling-pointer", ++ "-Wno-dangling-reference", + "-isystem .", + ], + "//conditions:default": [], +-- +2.50.0.727.gbf7dc18ff4-goog + + +From 7ce2d6bd14b338ab91a8636a8694b9ef180b2f90 Mon Sep 17 00:00:00 2001 +From: Matt Leon +Date: Fri, 18 Jul 2025 17:28:42 -0400 +Subject: [PATCH 7/7] Hack out atomic simd support in V8. + +Atomic simdutf requires __cpp_lib_atomic_ref >= 201806, which is only +supported in clang libc++ 19+. The version of LLVM used in Envoy as of +2025-07-18 is libc++ 18, so this is not supported. + +The simdutf documentation indicates this atomic form is not tested and +is not recommended for use: +https://github.com/simdutf/simdutf/blob/5d1b6248f29a8ed0eb90f79be268be41730e39f8/include/simdutf/implementation.h#L3066-L3068 + +In addition, this is in the implementation of a JS array buffer. Since +proxy-wasm-cpp-host does not make use of JS array buffers or shared +memory between web workers, we're stubbing it out. + +Mostly reverts +https://github.com/v8/v8/commit/6d6c1e680c7b8ea5f62a76e9c3d88d3fb0a88df0. + +Signed-off-by: Matt Leon +--- + bazel/defs.bzl | 2 +- + src/builtins/builtins-typed-array.cc | 8 ++++++++ + src/objects/simd.cc | 10 ++++++++++ + 3 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/bazel/defs.bzl b/bazel/defs.bzl +index c7a48d4e805..a73b3812882 100644 +--- a/bazel/defs.bzl ++++ b/bazel/defs.bzl +@@ -180,7 +180,7 @@ def _default_args(): + "Advapi32.lib", + ], + "@v8//bazel/config:is_macos": ["-pthread"], +- "//conditions:default": ["-Wl,--no-as-needed -ldl -latomic -pthread"], ++ "//conditions:default": ["-Wl,--no-as-needed -ldl -pthread"], + }) + select({ + ":should_add_rdynamic": ["-rdynamic"], + "//conditions:default": [], +diff --git a/src/builtins/builtins-typed-array.cc b/src/builtins/builtins-typed-array.cc +index 918cb873481..bc933e8dc1d 100644 +--- a/src/builtins/builtins-typed-array.cc ++++ b/src/builtins/builtins-typed-array.cc +@@ -520,17 +520,21 @@ simdutf::result ArrayBufferSetFromBase64( + DirectHandle typed_array, size_t& output_length) { + output_length = array_length; + simdutf::result simd_result; ++#ifdef WANT_ATOMIC_REF + if (typed_array->buffer()->is_shared()) { + simd_result = simdutf::atomic_base64_to_binary_safe( + reinterpret_cast(input_vector), input_length, + reinterpret_cast(typed_array->DataPtr()), output_length, + alphabet, last_chunk_handling, /*decode_up_to_bad_char*/ true); + } else { ++#endif + simd_result = simdutf::base64_to_binary_safe( + reinterpret_cast(input_vector), input_length, + reinterpret_cast(typed_array->DataPtr()), output_length, + alphabet, last_chunk_handling, /*decode_up_to_bad_char*/ true); ++#ifdef WANT_ATOMIC_REF + } ++#endif + + return simd_result; + } +@@ -833,15 +837,19 @@ BUILTIN(Uint8ArrayPrototypeToBase64) { + // 11. Return CodePointsToString(outAscii). + + size_t simd_result_size; ++#ifdef WANT_ATOMIC_REF + if (uint8array->buffer()->is_shared()) { + simd_result_size = simdutf::atomic_binary_to_base64( + std::bit_cast(uint8array->DataPtr()), length, + reinterpret_cast(output->GetChars(no_gc)), alphabet); + } else { ++#endif + simd_result_size = simdutf::binary_to_base64( + std::bit_cast(uint8array->DataPtr()), length, + reinterpret_cast(output->GetChars(no_gc)), alphabet); ++#ifdef WANT_ATOMIC_REF + } ++#endif + DCHECK_EQ(simd_result_size, output_length); + USE(simd_result_size); + } +diff --git a/src/objects/simd.cc b/src/objects/simd.cc +index 0ef570ceb7d..9217fa76072 100644 +--- a/src/objects/simd.cc ++++ b/src/objects/simd.cc +@@ -477,6 +477,7 @@ void Uint8ArrayToHexSlow(const char* bytes, size_t length, + } + } + ++#ifdef WANT_ATOMIC_REF + void AtomicUint8ArrayToHexSlow(const char* bytes, size_t length, + DirectHandle string_output) { + int index = 0; +@@ -492,6 +493,7 @@ void AtomicUint8ArrayToHexSlow(const char* bytes, size_t length, + index += 2; + } + } ++#endif + + inline uint16_t ByteToHex(uint8_t byte) { + const uint16_t correction = (('a' - '0' - 10) << 8) + ('a' - '0' - 10); +@@ -645,11 +647,15 @@ Tagged Uint8ArrayToHex(const char* bytes, size_t length, bool is_shared, + } + #endif + ++#ifdef WANT_ATOMIC_REF + if (is_shared) { + AtomicUint8ArrayToHexSlow(bytes, length, string_output); + } else { ++#endif + Uint8ArrayToHexSlow(bytes, length, string_output); ++#ifdef WANT_ATOMIC_REF + } ++#endif + return *string_output; + } + +@@ -1082,12 +1088,16 @@ bool ArrayBufferFromHex(const base::Vector& input_vector, bool is_shared, + for (uint32_t i = 0; i < output_length * 2; i += 2) { + result = HandleRemainingHexValues(input_vector, i); + if (result.has_value()) { ++#ifdef WANT_ATOMIC_REF + if (is_shared) { + std::atomic_ref(buffer[index++]) + .store(result.value(), std::memory_order_relaxed); + } else { ++#endif + buffer[index++] = result.value(); ++#ifdef WANT_ATOMIC_REF + } ++#endif + } else { + return false; + } +-- +2.50.0.727.gbf7dc18ff4-goog + 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/repositories.bzl b/bazel/repositories.bzl index 94e9fc5f3..159244263 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -60,10 +60,18 @@ def proxy_wasm_cpp_host_repositories(): maybe( http_archive, - name = "bazel-zig-cc", - sha256 = "ff89e0220c72cdc774e451a35e5c3b9f1593d0df71341844b2108c181ac0eef9", - strip_prefix = "hermetic_cc_toolchain-0.4.4", - url = "https://github.com/uber/hermetic_cc_toolchain/archive/refs/tags/v0.4.4.tar.gz", + name = "envoy_toolshed", + sha256 = "e2252e46e64417d5cedd9f1eb34a622bce5e13b43837e5fe051c83066b0a400b", + strip_prefix = "toolshed-bazel-bins-v0.1.13/bazel", + url = "https://github.com/envoyproxy/toolshed/archive/refs/tags/bazel-bins-v0.1.13.tar.gz", + ) + maybe( + http_archive, + name = "toolchains_llvm", + sha256 = "b7cd301ef7b0ece28d20d3e778697a5e3b81828393150bed04838c0c52963a01", + strip_prefix = "toolchains_llvm-0.10.3", + canonical_id = "v0.10.3", + url = "https://github.com/grailbio/bazel-toolchain/releases/download/0.10.3/toolchains_llvm-0.10.3.tar.gz", ) maybe( @@ -169,34 +177,89 @@ 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"], + patch_cmds = [ + "find ./src ./include -type f -exec sed -i.bak -e 's!#include \"third_party/simdutf/simdutf.h\"!#include \"simdutf.h\"!' {} \\;", + "find ./src ./include -type f -exec sed -i.bak -e 's!#include \"third_party/fp16/src/include/fp16.h\"!#include \"fp16.h\"!' {} \\;", + "find ./src ./include -type f -exec sed -i.bak -e 's!#include \"third_party/dragonbox/src/include/dragonbox/dragonbox.h\"!#include \"dragonbox/dragonbox.h\"!' {} \\;", + "find ./src ./include -type f -exec sed -i.bak -e 's!#include \"third_party/fast_float/src/include/fast_float/!#include \"fast_float/!' {} \\;", + ], + repo_mapping = { + "@abseil-cpp": "@com_google_absl", + }, ) - native.bind( - name = "wee8", - actual = "@v8//:wee8", + maybe( + http_archive, + name = "highway", + sha256 = "7e0be78b8318e8bdbf6fa545d2ecb4c90f947df03f7aadc42c1967f019e63343", + urls = [ + "https://github.com/google/highway/archive/refs/tags/1.2.0.tar.gz", + ], + strip_prefix = "highway-1.2.0", + ) + + maybe( + http_archive, + name = "fast_float", + sha256 = "d2a08e722f461fe699ba61392cd29e6b23be013d0f56e50c7786d0954bffcb17", + urls = [ + "https://github.com/fastfloat/fast_float/archive/refs/tags/v7.0.0.tar.gz", + ], + strip_prefix = "fast_float-7.0.0", + ) + + maybe( + http_archive, + name = "dragonbox", + urls = [ + "https://github.com/jk-jeon/dragonbox/archive/6c7c925b571d54486b9ffae8d9d18a822801cbda.zip", + ], + strip_prefix = "dragonbox-6c7c925b571d54486b9ffae8d9d18a822801cbda", + sha256 = "2f10448d665355b41f599e869ac78803f82f13b070ce7ef5ae7b5cceb8a178f3", + build_file = "@proxy_wasm_cpp_host//bazel/external:dragonbox.BUILD", ) 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", + http_archive, + name = "fp16", + urls = [ + "https://github.com/Maratyszcza/FP16/archive/0a92994d729ff76a58f692d3028ca1b64b145d91.zip", + ], + strip_prefix = "FP16-0a92994d729ff76a58f692d3028ca1b64b145d91", + sha256 = "e66e65515fa09927b348d3d584c68be4215cfe664100d01c9dbc7655a5716d70", + build_file = "@proxy_wasm_cpp_host//bazel/external:fp16.BUILD", + ) + + maybe( + http_archive, + name = "simdutf", + sha256 = "512374f8291d3daf102ccd0ad223b1a8318358f7c1295efd4d9a3abbb8e4b6ff", + urls = [ + "https://github.com/simdutf/simdutf/releases/download/v7.3.0/singleheader.zip", + ], + build_file = "@proxy_wasm_cpp_host//bazel/external:simdutf.BUILD", + ) + + maybe( + http_archive, + name = "intel_ittapi", + strip_prefix = "ittapi-a3911fff01a775023a06af8754f9ec1e5977dd97", + sha256 = "1d0dddfc5abb786f2340565c82c6edd1cff10c917616a18ce62ee0b94dbc2ed4", + urls = ["https://github.com/intel/ittapi/archive/a3911fff01a775023a06af8754f9ec1e5977dd97.tar.gz"], + build_file = "@proxy_wasm_cpp_host//bazel/external:intel_ittapi.BUILD", ) native.bind( - name = "base_trace_event_common", - actual = "@com_googlesource_chromium_base_trace_event_common//:trace_event_common", + name = "wee8", + actual = "@v8//:wee8", ) # WAMR with dependencies. diff --git a/bazel/tsan_suppressions.txt b/bazel/tsan_suppressions.txt new file mode 100644 index 000000000..8754c04f3 --- /dev/null +++ b/bazel/tsan_suppressions.txt @@ -0,0 +1,3 @@ +# False positive in V8 worker shutdown +race:v8::platform::DefaultJobHandle::Join +race:v8::platform::DefaultJobHandle::Cancel diff --git a/src/v8/v8.cc b/src/v8/v8.cc index 61779c1d5..bc5b82850 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -140,20 +140,20 @@ class V8 : public WasmVm { static std::string printValue(const wasm::Val &value) { switch (value.kind()) { - case wasm::I32: + case wasm::ValKind::I32: return std::to_string(value.get()); - case wasm::I64: + case wasm::ValKind::I64: return std::to_string(value.get()); - case wasm::F32: + case wasm::ValKind::F32: return std::to_string(value.get()); - case wasm::F64: + case wasm::ValKind::F64: return std::to_string(value.get()); default: return "unknown"; } } -static std::string printValues(const wasm::Val values[], size_t size) { +static std::string printValues(const wasm::vec &values, size_t size) { if (size == 0) { return ""; } @@ -170,17 +170,17 @@ static std::string printValues(const wasm::Val values[], size_t size) { static const char *printValKind(wasm::ValKind kind) { switch (kind) { - case wasm::I32: + case wasm::ValKind::I32: return "i32"; - case wasm::I64: + case wasm::ValKind::I64: return "i64"; - case wasm::F32: + case wasm::ValKind::F32: return "f32"; - case wasm::F64: + case wasm::ValKind::F64: return "f64"; - case wasm::ANYREF: - return "anyref"; - case wasm::FUNCREF: + case wasm::ValKind::EXTERNREF: + return "externref"; + case wasm::ValKind::FUNCREF: return "funcref"; default: return "unknown"; @@ -229,11 +229,11 @@ template wasm::Val makeVal(T t) { return wasm::Val::make(t); } template <> wasm::Val makeVal(Word t) { return wasm::Val::make(static_cast(t.u64_)); } template constexpr auto convertArgToValKind(); -template <> constexpr auto convertArgToValKind() { return wasm::I32; }; -template <> constexpr auto convertArgToValKind() { return wasm::I32; }; -template <> constexpr auto convertArgToValKind() { return wasm::I64; }; -template <> constexpr auto convertArgToValKind() { return wasm::I64; }; -template <> constexpr auto convertArgToValKind() { return wasm::F64; }; +template <> constexpr auto convertArgToValKind() { return wasm::ValKind::I32; }; +template <> constexpr auto convertArgToValKind() { return wasm::ValKind::I32; }; +template <> constexpr auto convertArgToValKind() { return wasm::ValKind::I64; }; +template <> constexpr auto convertArgToValKind() { return wasm::ValKind::I64; }; +template <> constexpr auto convertArgToValKind() { return wasm::ValKind::F64; }; template constexpr auto convertArgsTupleToValTypesImpl(std::index_sequence /*comptime*/) { @@ -343,7 +343,8 @@ bool V8::link(std::string_view /*debug_name*/) { assert(module_ != nullptr); const auto import_types = module_.get()->imports(); - std::vector imports; + wasm::vec imports = + wasm::vec::make_uninitialized(import_types.size()); for (size_t i = 0; i < import_types.size(); i++) { std::string_view module(import_types[i]->module().get(), import_types[i]->module().size()); @@ -352,7 +353,7 @@ bool V8::link(std::string_view /*debug_name*/) { switch (import_type->kind()) { - case wasm::EXTERN_FUNC: { + case wasm::ExternKind::FUNC: { auto it = host_functions_.find(std::string(module) + "." + std::string(name)); if (it == host_functions_.end()) { fail(FailState::UnableToInitializeCode, @@ -372,10 +373,10 @@ bool V8::link(std::string_view /*debug_name*/) { printValTypes(func->type()->results())); return false; } - imports.push_back(func); + imports[i] = func; } break; - case wasm::EXTERN_GLOBAL: { + case wasm::ExternKind::GLOBAL: { // TODO(PiotrSikora): add support when/if needed. fail(FailState::UnableToInitializeCode, "Failed to load Wasm module due to a missing import: " + std::string(module) + "." + @@ -383,7 +384,7 @@ bool V8::link(std::string_view /*debug_name*/) { return false; } break; - case wasm::EXTERN_MEMORY: { + case wasm::ExternKind::MEMORY: { assert(memory_ == nullptr); auto type = wasm::MemoryType::make(import_type->memory()->limits()); if (type == nullptr) { @@ -393,10 +394,10 @@ bool V8::link(std::string_view /*debug_name*/) { if (memory_ == nullptr) { return false; } - imports.push_back(memory_.get()); + imports[i] = memory_.get(); } break; - case wasm::EXTERN_TABLE: { + case wasm::ExternKind::TABLE: { assert(table_ == nullptr); auto type = wasm::TableType::make(wasm::ValType::make(import_type->table()->element()->kind()), @@ -408,16 +409,12 @@ bool V8::link(std::string_view /*debug_name*/) { if (table_ == nullptr) { return false; } - imports.push_back(table_.get()); + imports[i] = table_.get(); } break; } } - if (import_types.size() != imports.size()) { - return false; - } - - instance_ = wasm::Instance::make(store_.get(), module_.get(), imports.data()); + instance_ = wasm::Instance::make(store_.get(), module_.get(), imports); if (instance_ == nullptr) { fail(FailState::UnableToInitializeCode, "Failed to create new Wasm instance"); return false; @@ -435,16 +432,16 @@ bool V8::link(std::string_view /*debug_name*/) { switch (export_type->kind()) { - case wasm::EXTERN_FUNC: { + case wasm::ExternKind::FUNC: { assert(export_item->func() != nullptr); module_functions_.insert_or_assign(std::string(name), export_item->func()->copy()); } break; - case wasm::EXTERN_GLOBAL: { + case wasm::ExternKind::GLOBAL: { // TODO(PiotrSikora): add support when/if needed. } break; - case wasm::EXTERN_MEMORY: { + case wasm::ExternKind::MEMORY: { assert(export_item->memory() != nullptr); assert(memory_ == nullptr); memory_ = exports[i]->memory()->copy(); @@ -453,7 +450,7 @@ bool V8::link(std::string_view /*debug_name*/) { } } break; - case wasm::EXTERN_TABLE: { + case wasm::ExternKind::TABLE: { // TODO(PiotrSikora): add support when/if needed. } break; } @@ -531,7 +528,8 @@ void V8::registerHostFunctionImpl(std::string_view module_name, std::string_view convertArgsTupleToValTypes>()); auto func = wasm::Func::make( store_.get(), type.get(), - [](void *data, const wasm::Val params[], wasm::Val /*results*/[]) -> wasm::own { + [](void *data, const wasm::vec ¶ms, + wasm::vec & /*results*/) -> wasm::own { auto *func_data = reinterpret_cast(data); const bool log = func_data->vm_->cmpLogLevel(LogLevel::trace); if (log) { @@ -567,7 +565,8 @@ void V8::registerHostFunctionImpl(std::string_view module_name, std::string_view convertArgsTupleToValTypes>()); auto func = wasm::Func::make( store_.get(), type.get(), - [](void *data, const wasm::Val params[], wasm::Val results[]) -> wasm::own { + [](void *data, const wasm::vec ¶ms, + wasm::vec &results) -> wasm::own { auto *func_data = reinterpret_cast(data); const bool log = func_data->vm_->cmpLogLevel(LogLevel::trace); if (log) { @@ -621,20 +620,21 @@ void V8::getModuleFunctionImpl(std::string_view function_name, const bool log = cmpLogLevel(LogLevel::trace); SaveRestoreContext saved_context(context); wasm::own trap = nullptr; + wasm::vec results = wasm::vec::make_uninitialized(); // Workaround for MSVC++ not supporting zero-sized arrays. if constexpr (sizeof...(args) > 0) { - wasm::Val params[] = {makeVal(args)...}; + wasm::vec params = wasm::vec::make(makeVal(args)...); if (log) { integration()->trace("[host->vm] " + std::string(function_name) + "(" + printValues(params, sizeof...(Args)) + ")"); } - trap = func->call(params, nullptr); + trap = func->call(params, results); } else { if (log) { integration()->trace("[host->vm] " + std::string(function_name) + "()"); } - trap = func->call(nullptr, nullptr); + trap = func->call(wasm::vec::make_uninitialized(), results); } if (trap) { @@ -671,12 +671,12 @@ void V8::getModuleFunctionImpl(std::string_view function_name, *function = [func, function_name, this](ContextBase *context, Args... args) -> R { const bool log = cmpLogLevel(LogLevel::trace); SaveRestoreContext saved_context(context); - wasm::Val results[1]; + wasm::vec results = wasm::vec::make_uninitialized(1); wasm::own trap = nullptr; // Workaround for MSVC++ not supporting zero-sized arrays. if constexpr (sizeof...(args) > 0) { - wasm::Val params[] = {makeVal(args)...}; + wasm::vec params = wasm::vec::make(makeVal(args)...); if (log) { integration()->trace("[host->vm] " + std::string(function_name) + "(" + printValues(params, sizeof...(Args)) + ")"); @@ -686,7 +686,7 @@ void V8::getModuleFunctionImpl(std::string_view function_name, if (log) { integration()->trace("[host->vm] " + std::string(function_name) + "()"); } - trap = func->call(nullptr, results); + trap = func->call(wasm::vec::make_uninitialized(), results); } if (trap) { @@ -706,9 +706,6 @@ void V8::terminate() { auto *store_impl = reinterpret_cast(store_.get()); auto *isolate = store_impl->isolate(); isolate->TerminateExecution(); - while (isolate->IsExecutionTerminating()) { - std::this_thread::yield(); - } } std::string V8::getFailMessage(std::string_view function_name, wasm::own trap) { diff --git a/test/BUILD b/test/BUILD index 73787e4b0..97e70558a 100644 --- a/test/BUILD +++ b/test/BUILD @@ -13,7 +13,8 @@ # limitations under the License. load("@proxy_wasm_cpp_host//bazel:select.bzl", "proxy_wasm_select_engine_null") -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") +load("@rules_cc//cc:defs.bzl", "cc_library") +load("//bazel:cc_defs.bzl", "cc_test") licenses(["notice"]) # Apache 2 diff --git a/test/fuzz/BUILD b/test/fuzz/BUILD index 71b099007..2221f6367 100644 --- a/test/fuzz/BUILD +++ b/test/fuzz/BUILD @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test") +load("//bazel:cc_defs.bzl", "cc_fuzz_test") licenses(["notice"]) # Apache 2 diff --git a/test/runtime_test.cc b/test/runtime_test.cc index 41e3946f1..2e9080978 100644 --- a/test/runtime_test.cc +++ b/test/runtime_test.cc @@ -102,7 +102,7 @@ TEST_P(TestVm, TerminateExecution) { // Check integration logs. auto *host = dynamic_cast(wasm.wasm_vm()->integration().get()); EXPECT_TRUE(host->isErrorLogged("Function: infinite_loop failed")); - EXPECT_TRUE(host->isErrorLogged("termination_exception")); + EXPECT_TRUE(host->isErrorLogged("TerminationException")); } TEST_P(TestVm, WasmMemoryLimit) { diff --git a/test/wasm_vm_test.cc b/test/wasm_vm_test.cc index d6f9d280a..4d084cc75 100644 --- a/test/wasm_vm_test.cc +++ b/test/wasm_vm_test.cc @@ -89,7 +89,7 @@ TEST_P(TestVm, Clone) { #if defined(__linux__) && defined(__x86_64__) -TEST_P(TestVm, CloneUntilOutOfMemory) { +TEST_P(TestVm, DISABLED_CloneUntilOutOfMemory) { if (vm_->cloneable() == proxy_wasm::Cloneable::NotCloneable) { return; } From 74f8572f45633cccb48239c5ecaca10d16490729 Mon Sep 17 00:00:00 2001 From: Matt Leon Date: Tue, 29 Jul 2025 15:51:01 -0400 Subject: [PATCH 10/21] chore: fix github bazel cache (#445) GitHub's actions cache appears to be empty, even with recent pushes to main. This config has been working well in Google's github.com/GoogleCloudPlatform/service-extensions repo, which should be building all the same things as this repo. Using --disk_cache avoids putting a bunch of junk in the cache that the previous xdg cache dir entry had to manually strip out. Signed-off-by: Matt Leon --- .github/workflows/format.yml | 63 +++++++++---------- .github/workflows/test.yml | 114 ++++++++++++++++------------------- 2 files changed, 80 insertions(+), 97 deletions(-) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index fa4ba153c..051459d7c 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -125,49 +125,40 @@ jobs: - name: Install dependencies (Linux) run: sudo apt update -y && sudo apt install -y clang-tidy-18 lld-18 && sudo ln -sf /usr/bin/lld-18 /usr/bin/lld - - name: Bazel cache - uses: PiotrSikora/cache@v2.1.7-with-skip-cache + - name: set cache name + id: vars + # The cache tag consists of the following parts: + # * clang-tidy- prefix + # * matrix.name, which separates the cache for each build type. + # * hash of WORKSPACE, .bazelrc, and .bazelversion, which is + # purely to differentiate caches for substantial changes in bazel. + # * github.sha, which is the commit hash of the commit used to generate + # the cache entry. + run: echo "CACHE_TAG=clang-tidy-${{ matrix.name }}-${{ hashFiles('WORKSPACE', '.bazelrc', '.bazelversion') }}" >> "$GITHUB_OUTPUT" + + - name: bazel cache + uses: actions/cache/restore@v3 with: - path: | - ~/.cache/bazel - key: clang_tidy-${{ hashFiles('WORKSPACE', '.bazelrc', '.bazelversion', 'bazel/dependencies.bzl', 'bazel/repositories.bzl', 'bazel/cargo/wasmsign/remote/crates.bzl') }} + path: /tmp/bazel/cache + key: ${{ steps.vars.outputs.CACHE_TAG }}-${{ github.sha }} + restore-keys: | + ${{ steps.vars.outputs.CACHE_TAG }}-${{ github.sha }} + ${{ steps.vars.outputs.CACHE_TAG }}- + clang-tidy-${{ matrix.name }}- + clang-tidy- - name: Bazel build run: > bazel build --config clang-tidy --define engine=multi + --disk_cache /tmp/bazel/cache --copt=-DPROXY_WASM_VERIFY_WITH_ED25519_PUBKEY=\"$(xxd -p -c 256 test/test_data/signature_key1.pub | cut -b9-)\" //... - - name: Skip Bazel cache update - if: ${{ github.ref != 'refs/heads/main' }} - run: echo "CACHE_SKIP_SAVE=true" >> $GITHUB_ENV - - - name: Cleanup Bazel cache - if: ${{ github.ref == 'refs/heads/main' }} - run: | - export OUTPUT=$(${{ matrix.run_under }} bazel info output_base) - echo "===== BEFORE =====" - du -s ${OUTPUT}/external/* $(dirname ${OUTPUT})/* | sort -rn | head -20 - # BoringSSL's test data (90 MiB). - rm -rf ${OUTPUT}/external/boringssl/crypto_test_data.cc - rm -rf ${OUTPUT}/external/boringssl/src/crypto/*/test/ - rm -rf ${OUTPUT}/external/boringssl/src/third_party/wycheproof_testvectors/ - # LLVM's tests (500 MiB). - rm -rf ${OUTPUT}/external/llvm*/test/ - # V8's tests (100 MiB). - if [ -d "${OUTPUT}/external/v8/test/torque" ]; then - mv ${OUTPUT}/external/v8/test/torque ${OUTPUT}/external/v8/test_torque - rm -rf ${OUTPUT}/external/v8/test/* - mv ${OUTPUT}/external/v8/test_torque ${OUTPUT}/external/v8/test/torque - fi - # Unnecessary CMake tools (65 MiB). - rm -rf ${OUTPUT}/external/cmake-*/bin/{ccmake,cmake-gui,cpack,ctest} - # Distfiles for Rust toolchains (350 MiB). - rm -rf ${OUTPUT}/external/rust_*/*.tar.gz - # Bazel's repository cache (650-800 MiB) and install base (155 MiB). - rm -rf ${OUTPUT}/../cache - rm -rf ${OUTPUT}/../install - echo "===== AFTER =====" - du -s ${OUTPUT}/external/* $(dirname ${OUTPUT})/* | sort -rn | head -20 + - name: save bazel cache + uses: actions/cache/save@v3 + if: always() + with: + path: /tmp/bazel/cache + key: ${{ steps.vars.outputs.CACHE_TAG }}-${{ github.sha }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7cb78e3b5..9ec572f34 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,12 +48,26 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Bazel cache - uses: PiotrSikora/cache@v2.1.7-with-skip-cache + - name: set cache name + id: vars + # The cache tag consists of the following parts: + # * test-deps-bazel-cache- prefix + # * hash of WORKSPACE, .bazelrc, and .bazelversion, which is + # purely to differentiate caches for substantial changes in bazel. + # * github.sha, which is the commit hash of the commit used to generate + # the cache entry. + run: echo "CACHE_TAG=test-deps-bazel-cache-${{ hashFiles('WORKSPACE', '.bazelrc', '.bazelversion') }}" >> "$GITHUB_OUTPUT" + + - name: bazel cache + uses: actions/cache/restore@v3 with: - path: | - ~/.cache/bazel - key: test_data-${{ hashFiles('WORKSPACE', '.bazelrc', '.bazelversion', 'bazel/dependencies.bzl', 'bazel/repositories.bzl', 'bazel/cargo/wasmsign/crates.bzl') }} + path: /tmp/bazel/cache + key: ${{ steps.vars.outputs.CACHE_TAG }}-${{ github.sha }} + restore-keys: | + ${{ steps.vars.outputs.CACHE_TAG }}-${{ github.sha }} + ${{ steps.vars.outputs.CACHE_TAG }}- + test-deps-bazel-cache-${{ matrix.name }}- + test-deps-bazel-cache- - name: Bazel build run: > @@ -61,6 +75,7 @@ jobs: --verbose_failures --test_output=errors --config=clang + --disk_cache /tmp/bazel/cache -c opt $(bazel query 'kind(was.*_rust_binary, //test/test_data/...)') $(bazel query 'kind(_optimized_wasm_cc_binary, //test/test_data/...)') @@ -84,19 +99,12 @@ jobs: if-no-files-found: error retention-days: 3 - - name: Skip Bazel cache update - if: ${{ github.ref != 'refs/heads/main' }} - run: echo "CACHE_SKIP_SAVE=true" >> $GITHUB_ENV - - - name: Cleanup Bazel cache - if: ${{ github.ref == 'refs/heads/main' }} - run: | - export OUTPUT=$(bazel info output_base) - # Distfiles for Rust toolchains (350 MiB). - rm -rf ${OUTPUT}/external/rust_*/*.tar.gz - # Bazel's repository cache (650-800 MiB) and install base (155 MiB). - rm -rf $(bazel info repository_cache) - rm -rf $(bazel info install_base) + - name: save bazel cache + uses: actions/cache/save@v3 + if: always() + with: + path: /tmp/bazel/cache + key: ${{ steps.vars.outputs.CACHE_TAG }}-${{ github.sha }} build: name: ${{ matrix.action }} with ${{ matrix.name }} @@ -282,21 +290,27 @@ jobs: if: startsWith(matrix.run_under, 'docker') run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - - name: Set cache key - if: ${{ matrix.cache }} - run: echo "::set-output name=uniq::$(bazel query --output build //external:${{ matrix.repo }} | grep -E 'sha256|commit' | cut -d\" -f2)-$(echo ${{ matrix.flags }} | sha256sum)" - id: cache-key - - - name: Bazel cache - if: ${{ matrix.cache }} - uses: PiotrSikora/cache@v2.1.7-with-skip-cache + - name: set cache name + id: vars + # The cache tag consists of the following parts: + # * bazel-cache- prefix + # * matrix.name, which separates the cache for each build type. + # * hash of WORKSPACE, .bazelrc, and .bazelversion, which is + # purely to differentiate caches for substantial changes in bazel. + # * github.sha, which is the commit hash of the commit used to generate + # the cache entry. + run: echo "CACHE_TAG=bazel-cache-${{ matrix.name }}-${{ hashFiles('WORKSPACE', '.bazelrc', '.bazelversion') }}" >> "$GITHUB_OUTPUT" + + - name: bazel cache + uses: actions/cache/restore@v3 with: - path: | - ~/.cache/bazel - /private/var/tmp/_bazel_runner/ - key: ${{ matrix.arch }}-${{ matrix.os }}-${{ matrix.engine }}-${{ steps.cache-key.outputs.uniq }}-${{ hashFiles('WORKSPACE', '.bazelrc', '.bazelversion', 'bazel/dependencies.bzl', 'bazel/repositories.bzl') }} + path: /tmp/bazel/cache + key: ${{ steps.vars.outputs.CACHE_TAG }}-${{ github.sha }} restore-keys: | - ${{ matrix.arch }}-${{ matrix.os }}-${{ matrix.engine }}-${{ steps.cache-key.outputs.uniq }}- + ${{ steps.vars.outputs.CACHE_TAG }}-${{ github.sha }} + ${{ steps.vars.outputs.CACHE_TAG }}- + bazel-cache-${{ matrix.name }}- + bazel-cache- - name: Download test data uses: actions/download-artifact@v4 @@ -321,6 +335,7 @@ jobs: --verbose_failures --test_output=errors --define engine=${{ matrix.engine }} + --disk_cache /tmp/bazel/cache ${{ matrix.flags }} -- //test/... ${{ matrix.targets }} @@ -332,38 +347,15 @@ jobs: --verbose_failures --test_output=errors --define engine=${{ matrix.engine }} + --disk_cache /tmp/bazel/cache ${{ matrix.flags }} --per_file_copt=src/signature_util.cc,test/signature_util_test.cc@-DPROXY_WASM_VERIFY_WITH_ED25519_PUBKEY=\"$(xxd -p -c 256 test/test_data/signature_key1.pub | cut -b9-)\" //test:signature_util_test - - name: Skip Bazel cache update - if: ${{ matrix.cache && github.ref != 'refs/heads/main' }} - run: echo "CACHE_SKIP_SAVE=true" >> $GITHUB_ENV + - name: save bazel cache + uses: actions/cache/save@v3 + if: always() + with: + path: /tmp/bazel/cache + key: ${{ steps.vars.outputs.CACHE_TAG }}-${{ github.sha }} - - name: Cleanup Bazel cache - if: ${{ matrix.cache && github.ref == 'refs/heads/main' }} - run: | - export OUTPUT=$(${{ matrix.run_under }} bazel info output_base) - echo "===== BEFORE =====" - du -s ${OUTPUT}/external/* $(dirname ${OUTPUT})/* | sort -rn | head -20 - # BoringSSL's test data (90 MiB). - rm -rf ${OUTPUT}/external/boringssl/crypto_test_data.cc - rm -rf ${OUTPUT}/external/boringssl/src/crypto/*/test/ - rm -rf ${OUTPUT}/external/boringssl/src/third_party/wycheproof_testvectors/ - # LLVM's tests (500 MiB). - rm -rf ${OUTPUT}/external/llvm*/test/ - # V8's tests (100 MiB). - if [ -d "${OUTPUT}/external/v8/test/torque" ]; then - mv ${OUTPUT}/external/v8/test/torque ${OUTPUT}/external/v8/test_torque - rm -rf ${OUTPUT}/external/v8/test/* - mv ${OUTPUT}/external/v8/test_torque ${OUTPUT}/external/v8/test/torque - fi - # Unnecessary CMake tools (65 MiB). - rm -rf ${OUTPUT}/external/cmake-*/bin/{ccmake,cmake-gui,cpack,ctest} - # Distfiles for Rust toolchains (350 MiB). - rm -rf ${OUTPUT}/external/rust_*/*.tar.gz - # Bazel's repository cache (650-800 MiB) and install base (155 MiB). - rm -rf ${OUTPUT}/../cache - rm -rf ${OUTPUT}/../install - echo "===== AFTER =====" - du -s ${OUTPUT}/external/* $(dirname ${OUTPUT})/* | sort -rn | head -20 From a374efd1f0295c6da6825f55795dab6495215035 Mon Sep 17 00:00:00 2001 From: rachgreen33 Date: Thu, 31 Jul 2025 13:43:05 -0400 Subject: [PATCH 11/21] Feat: Add additional virtual keywords to wasm base. (#444) * Feat: Add additional virtual keywords to wasm base. Signed-off-by: Rachel Green --- include/proxy-wasm/context.h | 8 ++++---- include/proxy-wasm/wasm.h | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/proxy-wasm/context.h b/include/proxy-wasm/context.h index 7f675525c..208633acc 100644 --- a/include/proxy-wasm/context.h +++ b/include/proxy-wasm/context.h @@ -150,14 +150,14 @@ class ContextBase : public RootInterface, const std::shared_ptr &plugin_handle); // Stream context. virtual ~ContextBase(); - WasmBase *wasm() const { return wasm_; } + virtual WasmBase *wasm() const { return wasm_; } uint32_t id() const { return id_; } // The VM Context used for calling "malloc" has an id_ == 0. bool isVmContext() const { return id_ == 0; } // Root Contexts have the VM Context as a parent. bool isRootContext() const { return parent_context_id_ == 0; } - ContextBase *parent_context() const { return parent_context_; } - ContextBase *root_context() const { + virtual ContextBase *parent_context() const { return parent_context_; } + virtual ContextBase *root_context() const { const ContextBase *previous = this; ContextBase *parent = parent_context_; while (parent != previous) { @@ -170,7 +170,7 @@ class ContextBase : public RootInterface, std::string_view log_prefix() const { return isRootContext() ? root_log_prefix_ : plugin_->log_prefix(); } - WasmVm *wasmVm() const; + virtual WasmVm *wasmVm() const; // Called before deleting the context. virtual void destroy(); diff --git a/include/proxy-wasm/wasm.h b/include/proxy-wasm/wasm.h index 3ab64b243..9b85710bd 100644 --- a/include/proxy-wasm/wasm.h +++ b/include/proxy-wasm/wasm.h @@ -54,18 +54,18 @@ class WasmBase : public std::enable_shared_from_this { WasmBase(const std::shared_ptr &base_wasm_handle, const WasmVmFactory &factory); virtual ~WasmBase(); - bool load(const std::string &code, bool allow_precompiled = false); - bool initialize(); - void startVm(ContextBase *root_context); - bool configure(ContextBase *root_context, std::shared_ptr plugin); + virtual bool load(const std::string &code, bool allow_precompiled = false); + virtual bool initialize(); + virtual void startVm(ContextBase *root_context); + virtual bool configure(ContextBase *root_context, std::shared_ptr plugin); // Returns the root ContextBase or nullptr if onStart returns false. - ContextBase *start(const std::shared_ptr &plugin); + virtual ContextBase *start(const std::shared_ptr &plugin); std::string_view vm_id() const { return vm_id_; } std::string_view vm_key() const { return vm_key_; } WasmVm *wasm_vm() const { return wasm_vm_.get(); } - ContextBase *vm_context() const { return vm_context_.get(); } - ContextBase *getRootContext(const std::shared_ptr &plugin, bool allow_closed); + virtual ContextBase *vm_context() const { return vm_context_.get(); } + virtual ContextBase *getRootContext(const std::shared_ptr &plugin, bool allow_closed); ContextBase *getContext(uint32_t id) { auto it = contexts_.find(id); if (it != contexts_.end()) @@ -321,14 +321,14 @@ using WasmHandleCloneFactory = class WasmHandleBase : public std::enable_shared_from_this { public: explicit WasmHandleBase(std::shared_ptr wasm_base) : wasm_base_(wasm_base) {} - ~WasmHandleBase() { + virtual ~WasmHandleBase() { if (wasm_base_) { wasm_base_->startShutdown(); } } - bool canary(const std::shared_ptr &plugin, - const WasmHandleCloneFactory &clone_factory); + virtual bool canary(const std::shared_ptr &plugin, + const WasmHandleCloneFactory &clone_factory); void kill() { wasm_base_ = nullptr; } @@ -356,7 +356,7 @@ class PluginHandleBase : public std::enable_shared_from_this { explicit PluginHandleBase(std::shared_ptr wasm_handle, std::shared_ptr plugin) : plugin_(plugin), wasm_handle_(wasm_handle) {} - ~PluginHandleBase() { + virtual ~PluginHandleBase() { if (wasm_handle_) { wasm_handle_->wasm()->startShutdown(plugin_->key()); } From 4fbf3127cafe2038546f6a65e5624ab297e007d7 Mon Sep 17 00:00:00 2001 From: Matt Leon Date: Fri, 22 Aug 2025 15:36:25 -0400 Subject: [PATCH 12/21] chore: Add license headers to BUILD files (#451) addlicense v1.2.0 supports linting .BUILD files, so the verify licenses check will fail for all future PRs without this commit. https://github.com/google/addlicense/releases/tag/v1.2.0 Signed-off-by: Matt Leon --- bazel/cargo/wasmsign/Cargo.toml | 14 ++++++++++++++ bazel/cargo/wasmtime/Cargo.toml | 14 ++++++++++++++ bazel/external/Dockerfile.bazel | 14 ++++++++++++++ bazel/external/dragonbox.BUILD | 14 ++++++++++++++ bazel/external/fp16.BUILD | 14 ++++++++++++++ bazel/external/intel_ittapi.BUILD | 14 ++++++++++++++ bazel/external/llvm.BUILD | 14 ++++++++++++++ bazel/external/simdutf.BUILD | 14 ++++++++++++++ bazel/external/wamr.BUILD | 14 ++++++++++++++ bazel/external/wamr_llvm.BUILD | 14 ++++++++++++++ bazel/external/wasmedge.BUILD | 14 ++++++++++++++ bazel/external/wasmtime.BUILD | 14 ++++++++++++++ 12 files changed, 168 insertions(+) diff --git a/bazel/cargo/wasmsign/Cargo.toml b/bazel/cargo/wasmsign/Cargo.toml index 815f8b03a..5267cb2d1 100644 --- a/bazel/cargo/wasmsign/Cargo.toml +++ b/bazel/cargo/wasmsign/Cargo.toml @@ -1,3 +1,17 @@ +# Copyright 2025 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. + [package] edition = "2018" name = "wasmsign-bazel" diff --git a/bazel/cargo/wasmtime/Cargo.toml b/bazel/cargo/wasmtime/Cargo.toml index 8abf88812..b038be7fd 100644 --- a/bazel/cargo/wasmtime/Cargo.toml +++ b/bazel/cargo/wasmtime/Cargo.toml @@ -1,3 +1,17 @@ +# Copyright 2025 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. + [package] edition = "2021" name = "wasmtime-c-api-bazel" diff --git a/bazel/external/Dockerfile.bazel b/bazel/external/Dockerfile.bazel index 2c4bfbbfa..9b16abeb3 100644 --- a/bazel/external/Dockerfile.bazel +++ b/bazel/external/Dockerfile.bazel @@ -1,4 +1,18 @@ # syntax=docker/dockerfile:1 +# Copyright 2025 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. + # Prep: # docker run --rm --privileged tonistiigi/binfmt --install all diff --git a/bazel/external/dragonbox.BUILD b/bazel/external/dragonbox.BUILD index d0bdf231e..00f3ee074 100644 --- a/bazel/external/dragonbox.BUILD +++ b/bazel/external/dragonbox.BUILD @@ -1,3 +1,17 @@ +# Copyright 2025 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. + load("@rules_cc//cc:defs.bzl", "cc_library") licenses(["notice"]) # Apache 2 diff --git a/bazel/external/fp16.BUILD b/bazel/external/fp16.BUILD index f3fbfda1f..f82146cff 100644 --- a/bazel/external/fp16.BUILD +++ b/bazel/external/fp16.BUILD @@ -1,3 +1,17 @@ +# Copyright 2025 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. + load("@rules_cc//cc:defs.bzl", "cc_library") licenses(["notice"]) # MIT diff --git a/bazel/external/intel_ittapi.BUILD b/bazel/external/intel_ittapi.BUILD index 13351d38a..cc867842f 100644 --- a/bazel/external/intel_ittapi.BUILD +++ b/bazel/external/intel_ittapi.BUILD @@ -1,3 +1,17 @@ +# Copyright 2025 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. + load("@rules_cc//cc:defs.bzl", "cc_library") licenses(["notice"]) diff --git a/bazel/external/llvm.BUILD b/bazel/external/llvm.BUILD index 38909ee9a..9dccf5c98 100644 --- a/bazel/external/llvm.BUILD +++ b/bazel/external/llvm.BUILD @@ -1,3 +1,17 @@ +# Copyright 2025 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. + load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake") licenses(["notice"]) # Apache 2 diff --git a/bazel/external/simdutf.BUILD b/bazel/external/simdutf.BUILD index ee4896494..834467e35 100644 --- a/bazel/external/simdutf.BUILD +++ b/bazel/external/simdutf.BUILD @@ -1,3 +1,17 @@ +# Copyright 2025 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. + load("@rules_cc//cc:defs.bzl", "cc_library") licenses(["notice"]) # Apache 2 diff --git a/bazel/external/wamr.BUILD b/bazel/external/wamr.BUILD index dcf8d87ef..d0f10b226 100644 --- a/bazel/external/wamr.BUILD +++ b/bazel/external/wamr.BUILD @@ -1,3 +1,17 @@ +# Copyright 2025 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. + load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake") licenses(["notice"]) # Apache 2 diff --git a/bazel/external/wamr_llvm.BUILD b/bazel/external/wamr_llvm.BUILD index 789e5a442..6fe496145 100644 --- a/bazel/external/wamr_llvm.BUILD +++ b/bazel/external/wamr_llvm.BUILD @@ -1,3 +1,17 @@ +# Copyright 2025 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. + load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake") licenses(["notice"]) # Apache 2 diff --git a/bazel/external/wasmedge.BUILD b/bazel/external/wasmedge.BUILD index 2c6e89204..e8fba783e 100644 --- a/bazel/external/wasmedge.BUILD +++ b/bazel/external/wasmedge.BUILD @@ -1,3 +1,17 @@ +# Copyright 2025 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. + load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake") licenses(["notice"]) # Apache 2 diff --git a/bazel/external/wasmtime.BUILD b/bazel/external/wasmtime.BUILD index 27da86e46..f359d9361 100644 --- a/bazel/external/wasmtime.BUILD +++ b/bazel/external/wasmtime.BUILD @@ -1,3 +1,17 @@ +# Copyright 2025 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. + load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_rust//rust:defs.bzl", "rust_static_library") From cbc2dd9924fd05abcdc14b7a325f7630858a8eea Mon Sep 17 00:00:00 2001 From: Matt Leon Date: Fri, 22 Aug 2025 15:38:32 -0400 Subject: [PATCH 13/21] workflows: remove unaccessed files from cache before saving (#452) Caches are growing organically (started around 400MiB, now at 2+GiB). This strategy is used by github.com/GoogleCloudPlatform/service-extensions to evict unneeded cached entries. Signed-off-by: Matt Leon --- .github/workflows/test.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9ec572f34..8c42a546e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -99,6 +99,15 @@ jobs: if-no-files-found: error retention-days: 3 + - name: remove unaccessed files from cache + shell: bash + run: > + find /tmp/bazel/cache + -type f + -name '*' + -amin +360 + -exec rm {} \; + - name: save bazel cache uses: actions/cache/save@v3 if: always() @@ -352,6 +361,15 @@ jobs: --per_file_copt=src/signature_util.cc,test/signature_util_test.cc@-DPROXY_WASM_VERIFY_WITH_ED25519_PUBKEY=\"$(xxd -p -c 256 test/test_data/signature_key1.pub | cut -b9-)\" //test:signature_util_test + - name: remove unaccessed files from cache + shell: bash + run: > + find /tmp/bazel/cache + -type f + -name '*' + -amin +360 + -exec rm {} \; + - name: save bazel cache uses: actions/cache/save@v3 if: always() From ee4dfe6204f1e0b9d93fcd7ae3a817806ea8ab7b Mon Sep 17 00:00:00 2001 From: rachgreen33 Date: Sat, 30 Aug 2025 13:53:58 -0400 Subject: [PATCH 14/21] Feat: Support creating warmed VM in the proxy wasm V8 VM API. (#447) * Support creating warmed VM in the proxy wasm V8 VM API. Signed-off-by: Rachel Green --- include/proxy-wasm/null_vm.h | 2 ++ include/proxy-wasm/v8.h | 1 + include/proxy-wasm/wamr.h | 1 + include/proxy-wasm/wasm_vm.h | 5 ++++ include/proxy-wasm/wasmtime.h | 1 + src/v8/v8.cc | 18 ++++++++++++- src/wamr/wamr.cc | 18 ++++++++++++- src/wasmedge/wasmedge.cc | 19 +++++++++++--- src/wasmtime/wasmtime.cc | 19 +++++++++++++- test/wasm_vm_test.cc | 48 +++++++++++++++++++++++++++++++++++ 10 files changed, 126 insertions(+), 6 deletions(-) diff --git a/include/proxy-wasm/null_vm.h b/include/proxy-wasm/null_vm.h index a0a3798ff..703266df3 100644 --- a/include/proxy-wasm/null_vm.h +++ b/include/proxy-wasm/null_vm.h @@ -63,6 +63,8 @@ struct NullVm : public WasmVm { void terminate() override {} bool usesWasmByteOrder() override { return false; } + void warm() override {} + std::string plugin_name_; std::unique_ptr plugin_; }; diff --git a/include/proxy-wasm/v8.h b/include/proxy-wasm/v8.h index 73c91b956..5531f52cb 100644 --- a/include/proxy-wasm/v8.h +++ b/include/proxy-wasm/v8.h @@ -21,6 +21,7 @@ namespace proxy_wasm { +bool initV8Engine(); std::unique_ptr createV8Vm(); } // namespace proxy_wasm diff --git a/include/proxy-wasm/wamr.h b/include/proxy-wasm/wamr.h index 98ff72e31..32a05e94a 100644 --- a/include/proxy-wasm/wamr.h +++ b/include/proxy-wasm/wamr.h @@ -21,6 +21,7 @@ namespace proxy_wasm { +bool initWamrEngine(); std::unique_ptr createWamrVm(); } // namespace proxy_wasm diff --git a/include/proxy-wasm/wasm_vm.h b/include/proxy-wasm/wasm_vm.h index db54ebd86..c14624ac0 100644 --- a/include/proxy-wasm/wasm_vm.h +++ b/include/proxy-wasm/wasm_vm.h @@ -308,6 +308,11 @@ class WasmVm { */ virtual bool usesWasmByteOrder() = 0; + /** + * Warm the VM such as engine and runtime. + */ + virtual void warm() = 0; + bool isFailed() { return failed_ != FailState::Ok; } void fail(FailState fail_state, std::string_view message) { integration()->error(message); diff --git a/include/proxy-wasm/wasmtime.h b/include/proxy-wasm/wasmtime.h index e3fe4b48c..11c4ae7a3 100644 --- a/include/proxy-wasm/wasmtime.h +++ b/include/proxy-wasm/wasmtime.h @@ -18,6 +18,7 @@ namespace proxy_wasm { +bool initWasmtimeEngine(); std::unique_ptr createWasmtimeVm(); } // namespace proxy_wasm diff --git a/src/v8/v8.cc b/src/v8/v8.cc index bc5b82850..9e184f292 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -103,6 +103,8 @@ class V8 : public WasmVm { void terminate() override; bool usesWasmByteOrder() override { return true; } + void warm() override; + private: wasm::own trap(std::string message); @@ -124,6 +126,9 @@ class V8 : public WasmVm { void getModuleFunctionImpl(std::string_view function_name, std::function *function); + // Initialize the V8 engine and store if necessary. + void initStore(); + wasm::own store_; wasm::own module_; wasm::own> shared_module_; @@ -260,9 +265,16 @@ template constexpr T convertValTypesToArgsTuple(const U // V8 implementation. +void V8::initStore() { + if (store_ != nullptr) { + return; + } + store_ = wasm::Store::make(engine()); +} + bool V8::load(std::string_view bytecode, std::string_view precompiled, const std::unordered_map &function_names) { - store_ = wasm::Store::make(engine()); + initStore(); if (store_ == nullptr) { return false; } @@ -708,6 +720,8 @@ void V8::terminate() { isolate->TerminateExecution(); } +void V8::warm() { initStore(); } + std::string V8::getFailMessage(std::string_view function_name, wasm::own trap) { auto message = "Function: " + std::string(function_name) + " failed: "; message += std::string(trap->message().get(), trap->message().size()); @@ -741,6 +755,8 @@ std::string V8::getFailMessage(std::string_view function_name, wasm::own createV8Vm() { return std::make_unique(); } } // namespace proxy_wasm diff --git a/src/wamr/wamr.cc b/src/wamr/wamr.cc index 482a59bf1..88dc9f007 100644 --- a/src/wamr/wamr.cc +++ b/src/wamr/wamr.cc @@ -90,6 +90,8 @@ class Wamr : public WasmVm { void terminate() override {} bool usesWasmByteOrder() override { return true; } + void warm() override; + private: template void registerHostFunctionImpl(std::string_view module_name, std::string_view function_name, @@ -107,6 +109,9 @@ class Wamr : public WasmVm { void getModuleFunctionImpl(std::string_view function_name, std::function *function); + // Initialize the Wamr store if necessary. + void initStore(); + WasmStorePtr store_; WasmModulePtr module_; WasmSharedModulePtr shared_module_; @@ -119,9 +124,16 @@ class Wamr : public WasmVm { std::unordered_map module_functions_; }; +void Wamr::initStore() { + if (store_ != nullptr) { + return; + } + store_ = wasm_store_new(engine()); +} + bool Wamr::load(std::string_view bytecode, std::string_view precompiled, const std::unordered_map & /*function_names*/) { - store_ = wasm_store_new(engine()); + initStore(); if (store_ == nullptr) { return false; } @@ -697,8 +709,12 @@ void Wamr::getModuleFunctionImpl(std::string_view function_name, }; }; +void Wamr::warm() { initStore(); } + } // namespace wamr +bool initWamrEngine() { return wamr::engine() != nullptr; } + std::unique_ptr createWamrVm() { return std::make_unique(); } } // namespace proxy_wasm diff --git a/src/wasmedge/wasmedge.cc b/src/wasmedge/wasmedge.cc index 596af0c9e..263ed1883 100644 --- a/src/wasmedge/wasmedge.cc +++ b/src/wasmedge/wasmedge.cc @@ -264,6 +264,9 @@ class WasmEdge : public WasmVm { }; FOR_ALL_WASM_VM_EXPORTS(_GET_MODULE_FUNCTION) #undef _GET_MODULE_FUNCTION + + void warm() override; + private: template void registerHostFunctionImpl(std::string_view module_name, std::string_view function_name, @@ -284,6 +287,9 @@ class WasmEdge : public WasmVm { void terminate() override {} bool usesWasmByteOrder() override { return true; } + // Initialize the WasmEdge store if necessary. + void initStore(); + WasmEdgeLoaderPtr loader_; WasmEdgeValidatorPtr validator_; WasmEdgeExecutorPtr executor_; @@ -314,13 +320,18 @@ bool WasmEdge::load(std::string_view bytecode, std::string_view /*precompiled*/, return true; } +void WasmEdge::initStore() { + if (store_ != nullptr) { + return; + } + store_ = WasmEdge_StoreCreate(); +} + bool WasmEdge::link(std::string_view /*debug_name*/) { assert(ast_module_ != nullptr); // Create store and register imports. - if (store_ == nullptr) { - store_ = WasmEdge_StoreCreate(); - } + initStore(); if (store_ == nullptr) { return false; } @@ -609,6 +620,8 @@ void WasmEdge::getModuleFunctionImpl(std::string_view function_name, }; } +void WasmEdge::warm() { initStore(); } + } // namespace WasmEdge std::unique_ptr createWasmEdgeVm() { return std::make_unique(); } diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index c4a7646f0..ac0361623 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -80,6 +80,9 @@ class Wasmtime : public WasmVm { }; FOR_ALL_WASM_VM_EXPORTS(_GET_MODULE_FUNCTION) #undef _GET_MODULE_FUNCTION + + void warm() override; + private: template void registerHostFunctionImpl(std::string_view module_name, std::string_view function_name, @@ -100,6 +103,9 @@ class Wasmtime : public WasmVm { void terminate() override {} bool usesWasmByteOrder() override { return true; } + // Initialize the Wasmtime store if necessary. + void initStore(); + WasmStorePtr store_; WasmModulePtr module_; WasmSharedModulePtr shared_module_; @@ -111,9 +117,16 @@ class Wasmtime : public WasmVm { std::unordered_map module_functions_; }; +void Wasmtime::initStore() { + if (store_ != nullptr) { + return; + } + store_ = wasm_store_new(engine()); +} + bool Wasmtime::load(std::string_view bytecode, std::string_view /*precompiled*/, const std::unordered_map & /*function_names*/) { - store_ = wasm_store_new(engine()); + initStore(); if (store_ == nullptr) { return false; } @@ -693,8 +706,12 @@ void Wasmtime::getModuleFunctionImpl(std::string_view function_name, }; }; +void Wasmtime::warm() { initStore(); } + } // namespace wasmtime +bool initWasmtimeEngine() { return wasmtime::engine() != nullptr; } + std::unique_ptr createWasmtimeVm() { return std::make_unique(); } } // namespace proxy_wasm diff --git a/test/wasm_vm_test.cc b/test/wasm_vm_test.cc index 4d084cc75..bb2bab193 100644 --- a/test/wasm_vm_test.cc +++ b/test/wasm_vm_test.cc @@ -30,6 +30,54 @@ INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines() return info.param; }); +TEST_P(TestVm, Init) { + std::chrono::time_point time2; + + auto time1 = std::chrono::steady_clock::now(); + if (engine_ == "v8") { +#if defined(PROXY_WASM_HOST_ENGINE_V8) + EXPECT_TRUE(proxy_wasm::initV8Engine()); + time2 = std::chrono::steady_clock::now(); + EXPECT_TRUE(proxy_wasm::initV8Engine()); +#endif + } else if (engine_ == "wamr") { +#if defined(PROXY_WASM_HOST_ENGINE_WAMR) + EXPECT_TRUE(proxy_wasm::initWamrEngine()); + time2 = std::chrono::steady_clock::now(); + EXPECT_TRUE(proxy_wasm::initWamrEngine()); +#endif + } else if (engine_ == "wasmtime") { +#if defined(PROXY_WASM_HOST_ENGINE_WASMTIME) + EXPECT_TRUE(proxy_wasm::initWasmtimeEngine()); + time2 = std::chrono::steady_clock::now(); + EXPECT_TRUE(proxy_wasm::initWasmtimeEngine()); +#endif + } else { + return; + } + auto time3 = std::chrono::steady_clock::now(); + + auto cold = std::chrono::duration_cast(time2 - time1).count(); + auto warm = std::chrono::duration_cast(time3 - time2).count(); + + std::cout << "\"cold\" engine time: " << cold << "ns" << std::endl; + std::cout << "\"warm\" engine time: " << warm << "ns" << std::endl; + + // Default warm time in nanoseconds. + int warm_time_ns_limit = 10000; + +#if defined(__linux__) && defined(__s390x__) + // Linux 390x is significantly slower, so we use a more lenient limit. + warm_time_ns_limit = 75000; +#endif + + // Verify that getting a "warm" engine takes less than 10us. + EXPECT_LE(warm, warm_time_ns_limit); + + // Verify that getting a "warm" engine takes at least 50x less time than getting a "cold" one. + EXPECT_LE(warm * 50, cold); +} + TEST_P(TestVm, Basic) { if (engine_ == "wasmedge") { EXPECT_EQ(vm_->cloneable(), proxy_wasm::Cloneable::NotCloneable); From 26969ea51f5f6cc7652f18c26d95ff5feb465f9f Mon Sep 17 00:00:00 2001 From: Michael Warres Date: Thu, 4 Sep 2025 09:32:28 -0400 Subject: [PATCH 15/21] chore: update WAMR to 2.4.1 (#453) Signed-off-by: Michael Warres --- bazel/external/wamr.BUILD | 2 +- bazel/repositories.bzl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bazel/external/wamr.BUILD b/bazel/external/wamr.BUILD index d0f10b226..a3375e2cb 100644 --- a/bazel/external/wamr.BUILD +++ b/bazel/external/wamr.BUILD @@ -69,7 +69,7 @@ cmake( "@proxy_wasm_cpp_host//bazel:engine_wamr_jit": ["-ldl"], "//conditions:default": [], }), - out_static_libs = ["libvmlib.a"], + out_static_libs = ["libiwasm.a"], deps = select({ "@proxy_wasm_cpp_host//bazel:engine_wamr_jit": ["@llvm-15_0_7//:llvm_wamr_lib"], "//conditions:default": [], diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 159244263..09939a706 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -268,10 +268,10 @@ def proxy_wasm_cpp_host_repositories(): http_archive, name = "com_github_bytecodealliance_wasm_micro_runtime", build_file = "@proxy_wasm_cpp_host//bazel/external:wamr.BUILD", - # WAMR-2.1.1 - sha256 = "a0824762abbcbb3dd6b7bb07530f198ece5d792a12a879bc2a99100590fdb151", - strip_prefix = "wasm-micro-runtime-WAMR-2.1.1", - url = "https://github.com/bytecodealliance/wasm-micro-runtime/archive/refs/tags/WAMR-2.1.1.zip", + # WAMR-2.4.1 + sha256 = "ca18bbf304f47287bf43707564db63b8908dd6d0d6ac40bb39271a7144def4cc", + strip_prefix = "wasm-micro-runtime-WAMR-2.4.1", + url = "https://github.com/bytecodealliance/wasm-micro-runtime/archive/refs/tags/WAMR-2.4.1.zip", ) native.bind( From 8b2e6535d929ed7092693e429f6bb81575a818a5 Mon Sep 17 00:00:00 2001 From: Michael Warres Date: Sun, 14 Sep 2025 23:09:07 -0400 Subject: [PATCH 16/21] fix: avoid potential unaligned loads, found by fuzzer (#456) Signed-off-by: Michael Warres --- src/pairs_util.cc | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src/pairs_util.cc b/src/pairs_util.cc index d21135788..b8121882f 100644 --- a/src/pairs_util.cc +++ b/src/pairs_util.cc @@ -15,6 +15,7 @@ #include "include/proxy-wasm/pairs_util.h" +#include #include #include #include @@ -25,6 +26,23 @@ namespace proxy_wasm { +namespace { + +// Read trivially copyable type from char buffer and return value. Does not +// check if char buffer is large enough to contain instance of `T`. +template inline T unalignedLoad(const char *buffer) { + // Checking for undefined behaviour wrt std::memcpy. + static_assert(std::is_trivially_copyable_v, + "type must be trivially copyable to use std::memcpy"); + T result; + // Use std::memcpy to get around strict type aliasing rules. + std::memcpy(&result, buffer, sizeof(T)); + + return result; +} + +} // namespace + using Sizes = std::vector>; size_t PairsUtil::pairsSize(const Pairs &pairs) { @@ -113,10 +131,13 @@ Pairs PairsUtil::toPairs(std::string_view buffer) { if (pos + sizeof(uint32_t) > end) { return {}; } - uint32_t num_pairs = wasmtoh(*reinterpret_cast(pos), - contextOrEffectiveContext() != nullptr - ? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder() - : false); + + // clang complains that this is unused when the wasmtoh macro drops its + // second argument on non-big-endian platforms. + [[maybe_unused]] const bool uses_wasm_byte_order = + contextOrEffectiveContext() != nullptr && + contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder(); + uint32_t num_pairs = wasmtoh(unalignedLoad(pos), uses_wasm_byte_order); pos += sizeof(uint32_t); // Check if we're not going to exceed the limit. @@ -135,20 +156,14 @@ Pairs PairsUtil::toPairs(std::string_view buffer) { if (pos + sizeof(uint32_t) > end) { return {}; } - s.first = wasmtoh(*reinterpret_cast(pos), - contextOrEffectiveContext() != nullptr - ? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder() - : false); + s.first = wasmtoh(unalignedLoad(pos), uses_wasm_byte_order); pos += sizeof(uint32_t); // Read value length. if (pos + sizeof(uint32_t) > end) { return {}; } - s.second = wasmtoh(*reinterpret_cast(pos), - contextOrEffectiveContext() != nullptr - ? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder() - : false); + s.second = wasmtoh(unalignedLoad(pos), uses_wasm_byte_order); pos += sizeof(uint32_t); } From 3025566375cd8d7f8cc6e2d6899fa9d6da03aca8 Mon Sep 17 00:00:00 2001 From: Michael Warres Date: Mon, 6 Oct 2025 22:51:30 -0400 Subject: [PATCH 17/21] Execute proxy-wasm-cpp-host ubuntu-24.04 actions on larger runner (#460) Signed-off-by: Michael Warres --- .github/workflows/format.yml | 8 ++++---- .github/workflows/test.yml | 28 ++++++++++++++-------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 051459d7c..8f61d3582 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -43,7 +43,7 @@ jobs: addlicense: name: verify licenses - runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-16core steps: - uses: actions/checkout@v2 @@ -63,7 +63,7 @@ jobs: buildifier: name: check format with buildifier - runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-16core steps: - uses: actions/checkout@v2 @@ -101,7 +101,7 @@ jobs: clang_format: name: check format with clang-format - runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-16core steps: - uses: actions/checkout@v2 @@ -117,7 +117,7 @@ jobs: clang_tidy: name: check format with clang-tidy - runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-16core steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c42a546e..cc6ddbc5f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,7 +43,7 @@ jobs: test_data: name: build test data - runs-on: ubuntu-24.04 + runs-on: ubuntu-24.04-16core steps: - uses: actions/checkout@v2 @@ -128,19 +128,19 @@ jobs: include: - name: 'NullVM on Linux/x86_64' engine: 'null' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=gcc - name: 'NullVM on Linux/x86_64 with ASan' engine: 'null' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang-asan --define=crypto=system - name: 'NullVM on Linux/x86_64 with TSan' engine: 'null' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang-tsan @@ -153,7 +153,7 @@ jobs: - name: 'V8 on Linux/x86_64' engine: 'v8' repo: 'v8' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=hermetic-llvm --define=crypto=system @@ -161,7 +161,7 @@ jobs: - name: 'V8 on Linux/x86_64 with ASan' engine: 'v8' repo: 'v8' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=hermetic-llvm --config=clang-asan @@ -169,7 +169,7 @@ jobs: - name: 'V8 on Linux/x86_64 with TSan' engine: 'v8' repo: 'v8' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=hermetic-llvm --config=clang-tsan @@ -177,7 +177,7 @@ jobs: - name: 'V8 on Linux/x86_64 with GCC' engine: 'v8' repo: 'v8' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=gcc @@ -202,7 +202,7 @@ jobs: - name: 'WAMR interp on Linux/x86_64' engine: 'wamr-interp' repo: 'com_github_bytecodealliance_wasm_micro_runtime' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang @@ -215,7 +215,7 @@ jobs: - name: 'WAMR jit on Linux/x86_64' engine: 'wamr-jit' repo: 'com_github_bytecodealliance_wasm_micro_runtime' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang @@ -231,7 +231,7 @@ jobs: - name: 'WasmEdge on Linux/x86_64' engine: 'wasmedge' repo: 'com_github_wasmedge_wasmedge' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang @@ -244,14 +244,14 @@ jobs: - name: 'Wasmtime on Linux/x86_64' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang -c opt - name: 'Wasmtime on Linux/x86_64 with ASan' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: x86_64 action: test flags: --config=clang-asan --define=crypto=system @@ -265,7 +265,7 @@ jobs: - name: 'Wasmtime on Linux/s390x' engine: 'wasmtime' repo: 'com_github_bytecodealliance_wasmtime' - os: ubuntu-24.04 + os: ubuntu-24.04-16core arch: s390x action: test flags: --config=clang --test_timeout=1800 From f3f9969a3f52bb512b5f1d20120ddd33871150c3 Mon Sep 17 00:00:00 2001 From: rachgreen33 Date: Mon, 20 Oct 2025 15:00:04 -0400 Subject: [PATCH 18/21] chore: Update V8 flag initialization to use V8 API (#458) * Set flags via the v8 API, instead of directly modifying them --------- Signed-off-by: Rachel Green --- src/v8/v8.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/v8/v8.cc b/src/v8/v8.cc index 9e184f292..932a60043 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -28,9 +28,10 @@ #include "include/proxy-wasm/limits.h" +#include "absl/strings/str_format.h" +#include "include/v8-initialization.h" #include "include/v8-version.h" #include "include/v8.h" -#include "src/flags/flags.h" #include "src/wasm/c-api.h" #include "wasm-api/wasm.hh" @@ -42,10 +43,13 @@ wasm::Engine *engine() { static wasm::own engine; std::call_once(init, []() { - ::v8::internal::v8_flags.liftoff = false; - ::v8::internal::v8_flags.wasm_max_mem_pages = - PROXY_WASM_HOST_MAX_WASM_MEMORY_SIZE_BYTES / PROXY_WASM_HOST_WASM_MEMORY_PAGE_SIZE_BYTES; + // Disable the Liftoff compiler to force optimized JIT up-front. + std::string args = absl::StrFormat("--wasm_max_mem_pages=%u --no-liftoff", + PROXY_WASM_HOST_MAX_WASM_MEMORY_SIZE_BYTES / + PROXY_WASM_HOST_WASM_MEMORY_PAGE_SIZE_BYTES); + ::v8::V8::SetFlagsFromString(args.c_str(), args.size()); ::v8::V8::EnableWebAssemblyTrapHandler(true); + engine = wasm::Engine::make(); }); From 14fa83a43bddadef6da8a37135f1dee57f8b29a3 Mon Sep 17 00:00:00 2001 From: rachgreen33 Date: Thu, 20 Nov 2025 14:30:27 -0500 Subject: [PATCH 19/21] Feat: Allow invocation of the emscripten_notify_memory_growth hostcall. (#461) * Feat: Allow invocation of the emscripten_notify_memory_growth hostcall. Signed-off-by: Rachel Green --- src/wasm.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/wasm.cc b/src/wasm.cc index e8a7ce436..a1b4c1836 100644 --- a/src/wasm.cc +++ b/src/wasm.cc @@ -378,7 +378,9 @@ ContextBase *WasmBase::getRootContext(const std::shared_ptr &plugin, void WasmBase::startVm(ContextBase *root_context) { // wasi_snapshot_preview1.clock_time_get wasm_vm_->setRestrictedCallback( - true, {// logging (Proxy-Wasm) + true, {// emscripten + "env.emscripten_notify_memory_growth", + // logging (Proxy-Wasm) "env.proxy_log", // logging (stdout/stderr) "wasi_unstable.fd_write", "wasi_snapshot_preview1.fd_write", From 44be7b18175b362f81bc821e6e23882518d7295a Mon Sep 17 00:00:00 2001 From: rachgreen33 Date: Fri, 21 Nov 2025 14:03:50 -0500 Subject: [PATCH 20/21] Chore: Remove the initEngine methods, and update Warm test. (#459) * Remove the init*engine methods from runtimes, and update warm() test. Signed-off-by: Rachel Green --- include/proxy-wasm/v8.h | 1 - include/proxy-wasm/wamr.h | 1 - include/proxy-wasm/wasmtime.h | 1 - src/v8/v8.cc | 2 -- src/wamr/wamr.cc | 2 -- src/wasmedge/wasmedge.cc | 7 ++++--- src/wasmtime/wasmtime.cc | 2 -- test/wasm_vm_test.cc | 35 ++++++++++------------------------- 8 files changed, 14 insertions(+), 37 deletions(-) diff --git a/include/proxy-wasm/v8.h b/include/proxy-wasm/v8.h index 5531f52cb..73c91b956 100644 --- a/include/proxy-wasm/v8.h +++ b/include/proxy-wasm/v8.h @@ -21,7 +21,6 @@ namespace proxy_wasm { -bool initV8Engine(); std::unique_ptr createV8Vm(); } // namespace proxy_wasm diff --git a/include/proxy-wasm/wamr.h b/include/proxy-wasm/wamr.h index 32a05e94a..98ff72e31 100644 --- a/include/proxy-wasm/wamr.h +++ b/include/proxy-wasm/wamr.h @@ -21,7 +21,6 @@ namespace proxy_wasm { -bool initWamrEngine(); std::unique_ptr createWamrVm(); } // namespace proxy_wasm diff --git a/include/proxy-wasm/wasmtime.h b/include/proxy-wasm/wasmtime.h index 11c4ae7a3..e3fe4b48c 100644 --- a/include/proxy-wasm/wasmtime.h +++ b/include/proxy-wasm/wasmtime.h @@ -18,7 +18,6 @@ namespace proxy_wasm { -bool initWasmtimeEngine(); std::unique_ptr createWasmtimeVm(); } // namespace proxy_wasm diff --git a/src/v8/v8.cc b/src/v8/v8.cc index 932a60043..f5a73b130 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -759,8 +759,6 @@ std::string V8::getFailMessage(std::string_view function_name, wasm::own createV8Vm() { return std::make_unique(); } } // namespace proxy_wasm diff --git a/src/wamr/wamr.cc b/src/wamr/wamr.cc index 88dc9f007..8eef73590 100644 --- a/src/wamr/wamr.cc +++ b/src/wamr/wamr.cc @@ -713,8 +713,6 @@ void Wamr::warm() { initStore(); } } // namespace wamr -bool initWamrEngine() { return wamr::engine() != nullptr; } - std::unique_ptr createWamrVm() { return std::make_unique(); } } // namespace proxy_wasm diff --git a/src/wasmedge/wasmedge.cc b/src/wasmedge/wasmedge.cc index 263ed1883..30fe78f5e 100644 --- a/src/wasmedge/wasmedge.cc +++ b/src/wasmedge/wasmedge.cc @@ -225,9 +225,6 @@ using HostModuleDataPtr = std::unique_ptr; class WasmEdge : public WasmVm { public: WasmEdge() { - loader_ = WasmEdge_LoaderCreate(nullptr); - validator_ = WasmEdge_ValidatorCreate(nullptr); - executor_ = WasmEdge_ExecutorCreate(nullptr, nullptr); store_ = nullptr; ast_module_ = nullptr; module_ = nullptr; @@ -305,6 +302,7 @@ class WasmEdge : public WasmVm { bool WasmEdge::load(std::string_view bytecode, std::string_view /*precompiled*/, const std::unordered_map & /*function_names*/) { + initStore(); WasmEdge_ASTModuleContext *mod = nullptr; WasmEdge_Result res = WasmEdge_LoaderParseFromBuffer( loader_.get(), &mod, reinterpret_cast(bytecode.data()), bytecode.size()); @@ -324,6 +322,9 @@ void WasmEdge::initStore() { if (store_ != nullptr) { return; } + loader_ = WasmEdge_LoaderCreate(nullptr); + validator_ = WasmEdge_ValidatorCreate(nullptr); + executor_ = WasmEdge_ExecutorCreate(nullptr, nullptr); store_ = WasmEdge_StoreCreate(); } diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index ac0361623..a72a0361d 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -710,8 +710,6 @@ void Wasmtime::warm() { initStore(); } } // namespace wasmtime -bool initWasmtimeEngine() { return wasmtime::engine() != nullptr; } - std::unique_ptr createWasmtimeVm() { return std::make_unique(); } } // namespace proxy_wasm diff --git a/test/wasm_vm_test.cc b/test/wasm_vm_test.cc index bb2bab193..346fe2a07 100644 --- a/test/wasm_vm_test.cc +++ b/test/wasm_vm_test.cc @@ -31,37 +31,17 @@ INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines() }); TEST_P(TestVm, Init) { - std::chrono::time_point time2; - auto time1 = std::chrono::steady_clock::now(); - if (engine_ == "v8") { -#if defined(PROXY_WASM_HOST_ENGINE_V8) - EXPECT_TRUE(proxy_wasm::initV8Engine()); - time2 = std::chrono::steady_clock::now(); - EXPECT_TRUE(proxy_wasm::initV8Engine()); -#endif - } else if (engine_ == "wamr") { -#if defined(PROXY_WASM_HOST_ENGINE_WAMR) - EXPECT_TRUE(proxy_wasm::initWamrEngine()); - time2 = std::chrono::steady_clock::now(); - EXPECT_TRUE(proxy_wasm::initWamrEngine()); -#endif - } else if (engine_ == "wasmtime") { -#if defined(PROXY_WASM_HOST_ENGINE_WASMTIME) - EXPECT_TRUE(proxy_wasm::initWasmtimeEngine()); - time2 = std::chrono::steady_clock::now(); - EXPECT_TRUE(proxy_wasm::initWasmtimeEngine()); -#endif - } else { - return; - } + vm_->warm(); + auto time2 = std::chrono::steady_clock::now(); + vm_->warm(); auto time3 = std::chrono::steady_clock::now(); auto cold = std::chrono::duration_cast(time2 - time1).count(); auto warm = std::chrono::duration_cast(time3 - time2).count(); - std::cout << "\"cold\" engine time: " << cold << "ns" << std::endl; - std::cout << "\"warm\" engine time: " << warm << "ns" << std::endl; + std::cout << "[" << engine_ << "] \"cold\" engine time: " << cold << "ns" << std::endl; + std::cout << "[" << engine_ << "] \"warm\" engine time: " << warm << "ns" << std::endl; // Default warm time in nanoseconds. int warm_time_ns_limit = 10000; @@ -75,6 +55,11 @@ TEST_P(TestVm, Init) { EXPECT_LE(warm, warm_time_ns_limit); // Verify that getting a "warm" engine takes at least 50x less time than getting a "cold" one. + // We skip NullVM because warm() is a noop. + if (engine_ == "null") { + std::cout << "Skipping warm() performance assertions for NullVM." << std::endl; + return; + } EXPECT_LE(warm * 50, cold); } From c8868da77499d414f3dcd07e4fbe584dc9a1c30d Mon Sep 17 00:00:00 2001 From: rachgreen33 Date: Mon, 24 Nov 2025 11:13:10 -0500 Subject: [PATCH 21/21] feat: pass FailState value to WasmVmIntegration::error() (#450) * pass FailState value to WasmVmIntegration::error() Signed-off-by: Rachel Green --- include/proxy-wasm/wasm_vm.h | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/include/proxy-wasm/wasm_vm.h b/include/proxy-wasm/wasm_vm.h index c14624ac0..9a2f0a6a0 100644 --- a/include/proxy-wasm/wasm_vm.h +++ b/include/proxy-wasm/wasm_vm.h @@ -143,12 +143,25 @@ enum class AbiVersion { ProxyWasm_0_1_0, ProxyWasm_0_2_0, ProxyWasm_0_2_1, Unkno class NullPlugin; +enum class FailState : int { + Ok = 0, + UnableToCreateVm = 1, + UnableToCloneVm = 2, + MissingFunction = 3, + UnableToInitializeCode = 4, + StartFailed = 5, + ConfigureFailed = 6, + RuntimeError = 7, +}; + // Integrator specific WasmVm operations. struct WasmVmIntegration { virtual ~WasmVmIntegration() {} virtual WasmVmIntegration *clone() = 0; virtual proxy_wasm::LogLevel getLogLevel() = 0; virtual void error(std::string_view message) = 0; + // Allow integrations to handle specific FailStates differently. + virtual void error(FailState fail_state, std::string_view message) { error(message); } virtual void trace(std::string_view message) = 0; // Get a NullVm implementation of a function. // @param function_name is the name of the function with the implementation specific prefix. @@ -165,17 +178,6 @@ struct WasmVmIntegration { void *ptr_to_function_return) = 0; }; -enum class FailState : int { - Ok = 0, - UnableToCreateVm = 1, - UnableToCloneVm = 2, - MissingFunction = 3, - UnableToInitializeCode = 4, - StartFailed = 5, - ConfigureFailed = 6, - RuntimeError = 7, -}; - // Wasm VM instance. Provides the low level WASM interface. class WasmVm { public: @@ -308,14 +310,11 @@ class WasmVm { */ virtual bool usesWasmByteOrder() = 0; - /** - * Warm the VM such as engine and runtime. - */ - virtual void warm() = 0; + virtual void warm() {} bool isFailed() { return failed_ != FailState::Ok; } void fail(FailState fail_state, std::string_view message) { - integration()->error(message); + integration()->error(fail_state, message); failed_ = fail_state; for (auto &callback : fail_callbacks_) { callback(fail_state);