deps: V8: backport bef0d9c1bc90

Original commit message:

    [api] Add V8::GetWasmMemoryReservationSizeInBytes()

    When the system does not have enough virtual memory for the wasm
    cage, installing the trap handler would cause any code allocating
    wasm memory to throw. Therefore it's useful for the embedder to
    know when the system doesn't have enough virtual address space
    to allocate enough wasm cages and in that case, skip the
    trap handler installation so that wasm code can at least work
    (even not at the maximal performance).

    Node.js previously has a command line option
    --disable-wasm-trap-handler to fully disable trap-based bound checks,
    this new API would allow it to adapt automatically while keeping the
    optimization in the happy path, since it's not always possible for
    end users to opt-into disabling trap-based bound checks (for example,
    when a VS Code Server is loaded in a remote server for debugging).

    Refs: https://github.com/nodejs/node/pull/62132
    Refs: https://github.com/microsoft/vscode/issues/251777
    Change-Id: I345c076af2b2b47700e5716b49c3133fdf8a0981
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7638233
    Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
    Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
    Commit-Queue: Joyee Cheung <joyee@igalia.com>
    Reviewed-by: Clemens Backes <clemensb@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#105702}

Refs: https://github.com/v8/v8/commit/bef0d9c1bc90357ef5e654b25fcb4ef9f74b591c
Co-authored-by: Joyee Cheung <joyeec9h3@gmail.com>
Refs: https://github.com/microsoft/vscode/issues/251777
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/7638233
PR-URL: https://github.com/nodejs/node/pull/61898
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
This commit is contained in:
Joyee CheungandJoyee Cheung authored and Michaël Zasso committed 2026-04-24 18:01:32 +02:00
1 parent cc5a331715
commit 13fb819110
6 files changed
+94 -21

No files matched your search

+1 -1
View File
@@ -40,7 +40,7 @@
# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.12',
'v8_embedder_string': '-node.13',
##### V8 defaults for Node.js #####
+29
View File
@@ -253,6 +253,35 @@ class V8_EXPORT V8 {
static size_t GetSandboxReservationSizeInBytes();
#endif // V8_ENABLE_SANDBOX
enum class WasmMemoryType {
kMemory32,
kMemory64,
};
/**
* Returns the virtual address space reservation size (in bytes) needed
* for one WebAssembly memory instance of the given capacity.
*
* \param type Whether this is a memory32 or memory64 instance.
* \param byte_capacity The maximum size, in bytes, of the WebAssembly
* memory. Values exceeding the engine's maximum allocatable memory
* size for the given type (determined by max_mem32_pages or
* max_mem64_pages) are clamped.
*
* When trap-based bounds checking is enabled by
* EnableWebAssemblyTrapHandler(), the amount of virtual address space
* that V8 needs to reserve for each WebAssembly memory instance can
* be much bigger than the requested size. If the process does
* not have enough virtual memory available, WebAssembly memory allocation
* would fail. During the initialization of V8, embedders can use this method
* to estimate whether the process has enough virtual memory for their
* usage of WebAssembly, and decide whether to enable the trap handler
* via EnableWebAssemblyTrapHandler(), or to skip it and reduce the amount of
* virtual memory required to keep the application running.
*/
static size_t GetWasmMemoryReservationSizeInBytes(WasmMemoryType type,
size_t byte_capacity);
/**
* Activate trap-based bounds checking for WebAssembly.
*
+21
View File
@@ -152,6 +152,7 @@
#include "src/wasm/value-type.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-result.h"
#include "src/wasm/wasm-serialization.h"
@@ -6358,6 +6359,26 @@ bool TryHandleWebAssemblyTrapWindows(EXCEPTION_POINTERS* exception) {
}
#endif
size_t V8::GetWasmMemoryReservationSizeInBytes(WasmMemoryType type,
size_t byte_capacity) {
#if V8_ENABLE_WEBASSEMBLY
bool is_memory64 = type == WasmMemoryType::kMemory64;
uint64_t max_byte_capacity =
is_memory64 ? i::wasm::max_mem64_bytes() : i::wasm::max_mem32_bytes();
if (byte_capacity > max_byte_capacity) {
byte_capacity = static_cast<size_t>(max_byte_capacity);
}
#if V8_TRAP_HANDLER_SUPPORTED
if (!is_memory64 || i::v8_flags.wasm_memory64_trap_handling) {
return i::BackingStore::GetWasmReservationSize(
/* has_guard_regions */ true, byte_capacity,
/* is_wasm_memory64 */ is_memory64);
}
#endif // V8_TRAP_HANDLER_SUPPORTED
#endif // V8_ENABLE_WEBASSEMBLY
return byte_capacity;
}
bool V8::EnableWebAssemblyTrapHandler(bool use_v8_signal_handler) {
#if V8_ENABLE_WEBASSEMBLY
return i::trap_handler::EnableTrapHandler(use_v8_signal_handler);
+22 -20
View File
@@ -51,8 +51,25 @@ enum class AllocationStatus {
kOtherFailure // Failed for an unknown reason
};
size_t GetReservationSize(bool has_guard_regions, size_t byte_capacity,
bool is_wasm_memory64) {
base::AddressRegion GetReservedRegion(bool has_guard_regions,
bool is_wasm_memory64, void* buffer_start,
size_t byte_capacity) {
return base::AddressRegion(
reinterpret_cast<Address>(buffer_start),
BackingStore::GetWasmReservationSize(has_guard_regions, byte_capacity,
is_wasm_memory64));
}
void RecordStatus(Isolate* isolate, AllocationStatus status) {
isolate->counters()->wasm_memory_allocation_result()->AddSample(
static_cast<int>(status));
}
} // namespace
size_t BackingStore::GetWasmReservationSize(bool has_guard_regions,
size_t byte_capacity,
bool is_wasm_memory64) {
#if V8_TARGET_ARCH_64_BIT && V8_ENABLE_WEBASSEMBLY
DCHECK_IMPLIES(is_wasm_memory64 && has_guard_regions,
v8_flags.wasm_memory64_trap_handling);
@@ -73,21 +90,6 @@ size_t GetReservationSize(bool has_guard_regions, size_t byte_capacity,
return byte_capacity;
}
base::AddressRegion GetReservedRegion(bool has_guard_regions,
bool is_wasm_memory64, void* buffer_start,
size_t byte_capacity) {
return base::AddressRegion(
reinterpret_cast<Address>(buffer_start),
GetReservationSize(has_guard_regions, byte_capacity, is_wasm_memory64));
}
void RecordStatus(Isolate* isolate, AllocationStatus status) {
isolate->counters()->wasm_memory_allocation_result()->AddSample(
static_cast<int>(status));
}
} // namespace
// The backing store for a Wasm shared memory remembers all the isolates
// with which it has been shared.
struct SharedWasmMemoryData {
@@ -169,7 +171,7 @@ BackingStore::~BackingStore() {
#if V8_ENABLE_WEBASSEMBLY
if (is_wasm_memory()) {
size_t reservation_size = GetReservationSize(
size_t reservation_size = GetWasmReservationSize(
has_guard_regions(), byte_capacity_, is_wasm_memory64());
TRACE_BS(
"BSw:free bs=%p mem=%p (length=%zu, capacity=%zu, reservation=%zu)\n",
@@ -319,8 +321,8 @@ std::unique_ptr<BackingStore> BackingStore::TryAllocateAndPartiallyCommitMemory(
};
size_t byte_capacity = maximum_pages * page_size;
size_t reservation_size =
GetReservationSize(has_guard_regions, byte_capacity, is_wasm_memory64);
size_t reservation_size = GetWasmReservationSize(
has_guard_regions, byte_capacity, is_wasm_memory64);
//--------------------------------------------------------------------------
// Allocate pages (inaccessible by default).
+5
View File
@@ -202,6 +202,11 @@ class V8_EXPORT_PRIVATE BackingStore : public BackingStoreBase {
uint32_t id() const { return id_; }
// Return the size of the reservation needed for a wasm backing store.
static size_t GetWasmReservationSize(bool has_guard_regions,
size_t byte_capacity,
bool is_wasm_memory64);
private:
friend class GlobalBackingStoreRegistry;
+16
View File
@@ -124,6 +124,22 @@ void WasmStreamingMoreFunctionsCanBeSerializedCallback(
streaming->SetMoreFunctionsCanBeSerializedCallback([](CompiledWasmModule) {});
}
TEST_F(ApiWasmTest, GetWasmMemoryReservationSizeInBytes) {
constexpr size_t kCapacity = 64 * 1024; // 64 KiB
size_t reservation = V8::GetWasmMemoryReservationSizeInBytes(
V8::WasmMemoryType::kMemory32, kCapacity);
size_t reservation64 = V8::GetWasmMemoryReservationSizeInBytes(
V8::WasmMemoryType::kMemory64, kCapacity);
#if V8_TRAP_HANDLER_SUPPORTED
EXPECT_GE(reservation, kCapacity);
EXPECT_GE(reservation64, kCapacity);
#else
EXPECT_EQ(reservation, kCapacity);
EXPECT_EQ(reservation64, kCapacity);
#endif // V8_TRAP_HANDLER_SUPPORTED
}
TEST_F(ApiWasmTest, WasmStreamingCallback) {
TestWasmStreaming(WasmStreamingCallbackTestCallbackIsCalled,
Promise::kPending);