Skip to content

Commit c1eb17e

Browse files
committed
deps: V8: cherry-pick 253e9aaa672a
Original commit message: [api] add V8::CanEnableWebAssemblyTrapHandler() 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 emebdder to know when the system require is not met 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 for this, this patch would allow it to adapt automatically without requiring the use of a command line flag, which is not always under end-user's control. Refs: #52766 Refs: #60788 Refs: microsoft/vscode#251777 Bug: 40644005 Change-Id: Ie0608970daabe370db4616b875a8f098711c80e2
1 parent 40c57ed commit c1eb17e

File tree

4 files changed

+89
-19
lines changed

4 files changed

+89
-19
lines changed

deps/v8/include/v8-initialization.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,13 @@ class V8_EXPORT V8 {
253253
static size_t GetSandboxReservationSizeInBytes();
254254
#endif // V8_ENABLE_SANDBOX
255255

256+
/**
257+
* Enabling the WebAssembly trap handler requires the process to be able to
258+
* access enough virtual address space. Returns true if the
259+
* system requirements are met at the time of the call.
260+
*/
261+
static bool CanEnableWebAssemblyTrapHandler();
262+
256263
/**
257264
* Activate trap-based bounds checking for WebAssembly.
258265
*

deps/v8/src/api/api.cc

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,14 @@
183183
#include "src/diagnostics/etw-jit-win.h"
184184
#endif // V8_ENABLE_ETW_STACK_WALKING
185185

186+
#if V8_OS_WIN
187+
#define WIN32_LEAN_AND_MEAN
188+
#include <windows.h>
189+
#include <psapi.h>
190+
#else
191+
#include <sys/resource.h>
192+
#include <unistd.h>
193+
#endif
186194
namespace v8 {
187195

188196
i::ExternalPointerTag ToExternalPointerTag(v8::EmbedderDataTypeTag api_tag) {
@@ -6277,6 +6285,9 @@ bool v8::V8::Initialize(const int build_config) {
62776285
bool TryHandleWebAssemblyTrapPosix(int sig_code, siginfo_t* info,
62786286
void* context) {
62796287
#if V8_ENABLE_WEBASSEMBLY && V8_TRAP_HANDLER_SUPPORTED
6288+
if (!i::trap_handler::IsTrapHandlerEnabled()) {
6289+
return false;
6290+
}
62806291
return i::trap_handler::TryHandleSignal(sig_code, info, context);
62816292
#else
62826293
return false;
@@ -6287,13 +6298,62 @@ bool TryHandleWebAssemblyTrapPosix(int sig_code, siginfo_t* info,
62876298
#if V8_OS_WIN
62886299
bool TryHandleWebAssemblyTrapWindows(EXCEPTION_POINTERS* exception) {
62896300
#if V8_ENABLE_WEBASSEMBLY && V8_TRAP_HANDLER_SUPPORTED
6301+
if (!i::trap_handler::IsTrapHandlerEnabled()) {
6302+
return false;
6303+
}
62906304
return i::trap_handler::TryHandleWasmTrap(exception);
62916305
#else
62926306
return false;
62936307
#endif
62946308
}
62956309
#endif
62966310

6311+
static uint64_t GetAddressSpaceSize() {
6312+
#if V8_OS_WIN
6313+
SYSTEM_INFO si{};
6314+
GetSystemInfo(&si);
6315+
6316+
auto lo = reinterpret_cast<uintptr_t>(si.lpMinimumApplicationAddress);
6317+
auto hi = reinterpret_cast<uintptr_t>(si.lpMaximumApplicationAddress);
6318+
6319+
// The range is inclusive, so add 1.
6320+
return static_cast<uint64_t>(hi - lo) + 1ULL;
6321+
#else
6322+
struct rlimit lim;
6323+
if (getrlimit(RLIMIT_AS, &lim) == 0 && lim.rlim_cur != RLIM_INFINITY) {
6324+
return static_cast<uint64_t>(lim.rlim_cur);
6325+
}
6326+
// Either RLIM_INFINITY or getrlimit failed — treat as "unlimited".
6327+
return std::numeric_limits<uintptr_t>::max();
6328+
#endif
6329+
}
6330+
6331+
bool V8::CanEnableWebAssemblyTrapHandler() {
6332+
#if V8_ENABLE_WEBASSEMBLY && V8_TRAP_HANDLER_SUPPORTED
6333+
uint64_t virtual_memory_available = GetAddressSpaceSize();
6334+
if (virtual_memory_available == 0) {
6335+
// There's no limit, assume trap handler can be enabled.
6336+
return true;
6337+
}
6338+
bool has_guard_regions = true; // Assume guard regions are enabled.
6339+
// Check if it can reserve memory for an allocation as low as 1 byte.
6340+
size_t byte_capacity = 1;
6341+
size_t memory32_size = i::BackingStore::GetWasmReservationSize(
6342+
has_guard_regions, byte_capacity, false);
6343+
uint64_t required_size = static_cast<uint64_t>(memory32_size);
6344+
if (i::v8_flags.wasm_memory64_trap_handling) {
6345+
uint64_t memory64_size =
6346+
static_cast<uint64_t>(i::BackingStore::GetWasmReservationSize(
6347+
has_guard_regions, byte_capacity, true));
6348+
required_size = std::max(memory64_size, required_size);
6349+
}
6350+
6351+
return virtual_memory_available >= required_size;
6352+
#else
6353+
return false;
6354+
#endif
6355+
}
6356+
62976357
bool V8::EnableWebAssemblyTrapHandler(bool use_v8_signal_handler) {
62986358
#if V8_ENABLE_WEBASSEMBLY
62996359
return i::trap_handler::EnableTrapHandler(use_v8_signal_handler);

deps/v8/src/objects/backing-store.cc

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,23 @@ enum class AllocationStatus {
5151
kOtherFailure // Failed for an unknown reason
5252
};
5353

54-
size_t GetReservationSize(bool has_guard_regions, size_t byte_capacity,
55-
bool is_wasm_memory64) {
54+
base::AddressRegion GetReservedRegion(bool has_guard_regions,
55+
bool is_wasm_memory64, void* buffer_start,
56+
size_t byte_capacity) {
57+
return base::AddressRegion(
58+
reinterpret_cast<Address>(buffer_start),
59+
BackingStore::GetWasmReservationSize(has_guard_regions, byte_capacity, is_wasm_memory64));
60+
}
61+
62+
void RecordStatus(Isolate* isolate, AllocationStatus status) {
63+
isolate->counters()->wasm_memory_allocation_result()->AddSample(
64+
static_cast<int>(status));
65+
}
66+
67+
} // namespace
68+
69+
size_t BackingStore::GetWasmReservationSize(bool has_guard_regions, size_t byte_capacity,
70+
bool is_wasm_memory64) {
5671
#if V8_TARGET_ARCH_64_BIT && V8_ENABLE_WEBASSEMBLY
5772
DCHECK_IMPLIES(is_wasm_memory64 && has_guard_regions,
5873
v8_flags.wasm_memory64_trap_handling);
@@ -73,21 +88,6 @@ size_t GetReservationSize(bool has_guard_regions, size_t byte_capacity,
7388
return byte_capacity;
7489
}
7590

76-
base::AddressRegion GetReservedRegion(bool has_guard_regions,
77-
bool is_wasm_memory64, void* buffer_start,
78-
size_t byte_capacity) {
79-
return base::AddressRegion(
80-
reinterpret_cast<Address>(buffer_start),
81-
GetReservationSize(has_guard_regions, byte_capacity, is_wasm_memory64));
82-
}
83-
84-
void RecordStatus(Isolate* isolate, AllocationStatus status) {
85-
isolate->counters()->wasm_memory_allocation_result()->AddSample(
86-
static_cast<int>(status));
87-
}
88-
89-
} // namespace
90-
9191
// The backing store for a Wasm shared memory remembers all the isolates
9292
// with which it has been shared.
9393
struct SharedWasmMemoryData {
@@ -168,7 +168,7 @@ BackingStore::~BackingStore() {
168168

169169
#if V8_ENABLE_WEBASSEMBLY
170170
if (is_wasm_memory()) {
171-
size_t reservation_size = GetReservationSize(
171+
size_t reservation_size = GetWasmReservationSize(
172172
has_guard_regions(), byte_capacity_, is_wasm_memory64());
173173
TRACE_BS(
174174
"BSw:free bs=%p mem=%p (length=%zu, capacity=%zu, reservation=%zu)\n",
@@ -325,7 +325,7 @@ std::unique_ptr<BackingStore> BackingStore::TryAllocateAndPartiallyCommitMemory(
325325

326326
size_t byte_capacity = maximum_pages * page_size;
327327
size_t reservation_size =
328-
GetReservationSize(has_guard_regions, byte_capacity, is_wasm_memory64);
328+
GetWasmReservationSize(has_guard_regions, byte_capacity, is_wasm_memory64);
329329

330330
//--------------------------------------------------------------------------
331331
// Allocate pages (inaccessible by default).

deps/v8/src/objects/backing-store.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ class V8_EXPORT_PRIVATE BackingStore : public BackingStoreBase {
183183

184184
uint32_t id() const { return id_; }
185185

186+
// Return the size of the reservation needed for a wasm backing store.
187+
static size_t GetWasmReservationSize(bool has_guard_regions, size_t byte_capacity,
188+
bool is_wasm_memory64);
186189
private:
187190
friend class GlobalBackingStoreRegistry;
188191

0 commit comments

Comments
 (0)