Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions deps/v8/include/v8-initialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,13 @@ class V8_EXPORT V8 {
static size_t GetSandboxReservationSizeInBytes();
#endif // V8_ENABLE_SANDBOX

/**
* Enabling the WebAssembly trap handler requires the process to be able to
* access enough virtual address space. Returns true if the
* system requirements are met at the time of the call.
*/
static bool CanEnableWebAssemblyTrapHandler();

/**
* Activate trap-based bounds checking for WebAssembly.
*
Expand Down
60 changes: 60 additions & 0 deletions deps/v8/src/api/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,14 @@
#include "src/diagnostics/etw-jit-win.h"
#endif // V8_ENABLE_ETW_STACK_WALKING

#if V8_OS_WIN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <psapi.h>
#else
#include <sys/resource.h>
#include <unistd.h>
#endif
namespace v8 {

i::ExternalPointerTag ToExternalPointerTag(v8::EmbedderDataTypeTag api_tag) {
Expand Down Expand Up @@ -6277,6 +6285,9 @@ bool v8::V8::Initialize(const int build_config) {
bool TryHandleWebAssemblyTrapPosix(int sig_code, siginfo_t* info,
void* context) {
#if V8_ENABLE_WEBASSEMBLY && V8_TRAP_HANDLER_SUPPORTED
if (!i::trap_handler::IsTrapHandlerEnabled()) {
return false;
}
return i::trap_handler::TryHandleSignal(sig_code, info, context);
#else
return false;
Expand All @@ -6287,14 +6298,63 @@ bool TryHandleWebAssemblyTrapPosix(int sig_code, siginfo_t* info,
#if V8_OS_WIN
bool TryHandleWebAssemblyTrapWindows(EXCEPTION_POINTERS* exception) {
#if V8_ENABLE_WEBASSEMBLY && V8_TRAP_HANDLER_SUPPORTED
if (!i::trap_handler::IsTrapHandlerEnabled()) {
return false;
}
return i::trap_handler::TryHandleWasmTrap(exception);
#else
return false;
#endif
}
#endif

static uint64_t GetAddressSpaceSize() {
#if V8_OS_WIN
SYSTEM_INFO si{};
GetSystemInfo(&si);

auto lo = reinterpret_cast<uintptr_t>(si.lpMinimumApplicationAddress);
auto hi = reinterpret_cast<uintptr_t>(si.lpMaximumApplicationAddress);

// The range is inclusive, so add 1.
return static_cast<uint64_t>(hi - lo) + 1ULL;
#else
struct rlimit lim;
if (getrlimit(RLIMIT_AS, &lim) == 0 && lim.rlim_cur != RLIM_INFINITY) {
return static_cast<uint64_t>(lim.rlim_cur);
}
// Either RLIM_INFINITY or getrlimit failed — treat as "unlimited".
return std::numeric_limits<uintptr_t>::max();
#endif
}

bool V8::CanEnableWebAssemblyTrapHandler() {
#if V8_ENABLE_WEBASSEMBLY
uint64_t virtual_memory_available = GetAddressSpaceSize();
if (virtual_memory_available == 0) {
// There's no limit, assume trap handler can be enabled.
return true;
}
bool has_guard_regions = true; // Assume guard regions are enabled.
size_t byte_capacity = 1; // Check if it can reserve memory for an allocation as low as 1 byte.
size_t memory32_size = i::BackingStore::GetWasmReservationSize(has_guard_regions, byte_capacity, false);
uint64_t required_size = static_cast<uint64_t>(memory32_size);
if (i::v8_flags.wasm_memory64_trap_handling) {
uint64_t memory64_size = static_cast<uint64_t>(i::BackingStore::GetWasmReservationSize(has_guard_regions, byte_capacity, true));
required_size = std::max(memory64_size, required_size);
}

return virtual_memory_available >= required_size;
#else
return false;
#endif
}

bool V8::EnableWebAssemblyTrapHandler(bool use_v8_signal_handler) {
if (!CanEnableWebAssemblyTrapHandler()) {
return false;
}

#if V8_ENABLE_WEBASSEMBLY
return i::trap_handler::EnableTrapHandler(use_v8_signal_handler);
#else
Expand Down
38 changes: 19 additions & 19 deletions deps/v8/src/objects/backing-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,23 @@ 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);
Expand All @@ -73,21 +88,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 {
Expand Down Expand Up @@ -168,7 +168,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",
Expand Down Expand Up @@ -325,7 +325,7 @@ 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);
GetWasmReservationSize(has_guard_regions, byte_capacity, is_wasm_memory64);

//--------------------------------------------------------------------------
// Allocate pages (inaccessible by default).
Expand Down
3 changes: 3 additions & 0 deletions deps/v8/src/objects/backing-store.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ 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;

Expand Down
6 changes: 6 additions & 0 deletions test/wasm-allocation/test-wasm-allocation-works-by-default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Test that with limited virtual memory space, WASM can still allocate memory
// even without --disable-wasm-trap-handler.
'use strict';

require('../common');
new WebAssembly.Memory({ initial: 10, maximum: 100 });
Loading