Commit b10bff90 authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[wasm] Introduce separate limits for memory64

This breaks up the existing {max_mem_pages()} method and the
{kSpecMaxMemoryPages} and {kV8MaxWasmMemoryPages} constants into two
versions for memory32 and memory64, respectively.

For now, the limits are still the same.

Some checks and clamping is moved to earlier places where we still have
the information whether a memory is 32 or 64 bit.
We also store that information in the WasmMemoryObject and use this for
knowing the maximum for growing.

This CL is not supposed to change any observable behaviour.

R=jkummerow@chromium.org

Bug: v8:10949
Change-Id: Ieaca0596d1a24ef2746842954a75188494103eb2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3782677Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81960}
parent 4cdc220d
...@@ -300,7 +300,7 @@ inline bool IsValidAsmjsMemorySize(size_t size) { ...@@ -300,7 +300,7 @@ inline bool IsValidAsmjsMemorySize(size_t size) {
// Enforce asm.js spec minimum size. // Enforce asm.js spec minimum size.
if (size < (1u << 12u)) return false; if (size < (1u << 12u)) return false;
// Enforce engine-limited and flag-limited maximum allocation size. // Enforce engine-limited and flag-limited maximum allocation size.
if (size > wasm::max_mem_bytes()) return false; if (size > wasm::max_mem32_bytes()) return false;
// Enforce power-of-2 sizes for 2^12 - 2^24. // Enforce power-of-2 sizes for 2^12 - 2^24.
if (size < (1u << 24u)) { if (size < (1u << 24u)) {
uint32_t size32 = static_cast<uint32_t>(size); uint32_t size32 = static_cast<uint32_t>(size);
......
...@@ -1010,7 +1010,8 @@ DEFINE_BOOL(wasm_test_streaming, false, ...@@ -1010,7 +1010,8 @@ DEFINE_BOOL(wasm_test_streaming, false,
"use streaming compilation instead of async compilation for tests") "use streaming compilation instead of async compilation for tests")
DEFINE_BOOL(wasm_native_module_cache_enabled, true, DEFINE_BOOL(wasm_native_module_cache_enabled, true,
"enable the native module cache") "enable the native module cache")
DEFINE_UINT(wasm_max_mem_pages, wasm::kV8MaxWasmMemoryPages, // The actual value used at runtime is clamped to kV8MaxWasmMemory{32,64}Pages.
DEFINE_UINT(wasm_max_mem_pages, kMaxUInt32,
"maximum number of 64KiB memory pages per wasm memory") "maximum number of 64KiB memory pages per wasm memory")
DEFINE_UINT(wasm_max_table_size, wasm::kV8MaxWasmTableSize, DEFINE_UINT(wasm_max_table_size, wasm::kV8MaxWasmTableSize,
"maximum table size of a wasm instance") "maximum table size of a wasm instance")
......
...@@ -315,10 +315,6 @@ void BackingStore::SetAllocatorFromIsolate(Isolate* isolate) { ...@@ -315,10 +315,6 @@ void BackingStore::SetAllocatorFromIsolate(Isolate* isolate) {
std::unique_ptr<BackingStore> BackingStore::TryAllocateWasmMemory( std::unique_ptr<BackingStore> BackingStore::TryAllocateWasmMemory(
Isolate* isolate, size_t initial_pages, size_t maximum_pages, Isolate* isolate, size_t initial_pages, size_t maximum_pages,
SharedFlag shared) { SharedFlag shared) {
// Compute size of reserved memory.
size_t engine_max_pages = wasm::max_mem_pages();
maximum_pages = std::min(engine_max_pages, maximum_pages);
auto result = TryAllocateAndPartiallyCommitMemory( auto result = TryAllocateAndPartiallyCommitMemory(
isolate, initial_pages * wasm::kWasmPageSize, isolate, initial_pages * wasm::kWasmPageSize,
maximum_pages * wasm::kWasmPageSize, wasm::kWasmPageSize, initial_pages, maximum_pages * wasm::kWasmPageSize, wasm::kWasmPageSize, initial_pages,
...@@ -454,9 +450,7 @@ std::unique_ptr<BackingStore> BackingStore::AllocateWasmMemory( ...@@ -454,9 +450,7 @@ std::unique_ptr<BackingStore> BackingStore::AllocateWasmMemory(
SharedFlag shared) { SharedFlag shared) {
// Wasm pages must be a multiple of the allocation page size. // Wasm pages must be a multiple of the allocation page size.
DCHECK_EQ(0, wasm::kWasmPageSize % AllocatePageSize()); DCHECK_EQ(0, wasm::kWasmPageSize % AllocatePageSize());
DCHECK_LE(initial_pages, maximum_pages);
// Enforce engine limitation on the maximum number of pages.
if (initial_pages > wasm::max_mem_pages()) return nullptr;
auto backing_store = auto backing_store =
TryAllocateWasmMemory(isolate, initial_pages, maximum_pages, shared); TryAllocateWasmMemory(isolate, initial_pages, maximum_pages, shared);
......
...@@ -2059,11 +2059,11 @@ auto Memory::make(Store* store_abs, const MemoryType* type) -> own<Memory> { ...@@ -2059,11 +2059,11 @@ auto Memory::make(Store* store_abs, const MemoryType* type) -> own<Memory> {
uint32_t minimum = limits.min; uint32_t minimum = limits.min;
// The max_mem_pages limit is only spec'ed for JS embeddings, so we'll // The max_mem_pages limit is only spec'ed for JS embeddings, so we'll
// directly use the maximum pages limit here. // directly use the maximum pages limit here.
if (minimum > i::wasm::kSpecMaxMemoryPages) return nullptr; if (minimum > i::wasm::kSpecMaxMemory32Pages) return nullptr;
uint32_t maximum = limits.max; uint32_t maximum = limits.max;
if (maximum != Limits(0).max) { if (maximum != Limits(0).max) {
if (maximum < minimum) return nullptr; if (maximum < minimum) return nullptr;
if (maximum > i::wasm::kSpecMaxMemoryPages) return nullptr; if (maximum > i::wasm::kSpecMaxMemory32Pages) return nullptr;
} }
// TODO(wasm+): Support shared memory. // TODO(wasm+): Support shared memory.
i::SharedFlag shared = i::SharedFlag::kNotShared; i::SharedFlag shared = i::SharedFlag::kNotShared;
......
...@@ -85,19 +85,25 @@ struct CompilationEnv { ...@@ -85,19 +85,25 @@ struct CompilationEnv {
: module(module), : module(module),
bounds_checks(bounds_checks), bounds_checks(bounds_checks),
runtime_exception_support(runtime_exception_support), runtime_exception_support(runtime_exception_support),
// During execution, the memory can never be bigger than what fits in a min_memory_size(MinPages(module) * kWasmPageSize),
// uintptr_t. max_memory_size(MaxPages(module) * kWasmPageSize),
min_memory_size(
std::min(kV8MaxWasmMemoryPages,
uintptr_t{module ? module->initial_pages : 0}) *
kWasmPageSize),
max_memory_size((module && module->has_maximum_pages
? std::min(kV8MaxWasmMemoryPages,
uintptr_t{module->maximum_pages})
: kV8MaxWasmMemoryPages) *
kWasmPageSize),
enabled_features(enabled_features), enabled_features(enabled_features),
dynamic_tiering(dynamic_tiering) {} dynamic_tiering(dynamic_tiering) {}
static constexpr uintptr_t MinPages(const WasmModule* module) {
if (!module) return 0;
const uintptr_t platform_max_pages =
module->is_memory64 ? kV8MaxWasmMemory64Pages : kV8MaxWasmMemory32Pages;
return std::min(platform_max_pages, uintptr_t{module->initial_pages});
}
static constexpr uintptr_t MaxPages(const WasmModule* module) {
if (!module) return kV8MaxWasmMemory32Pages;
const uintptr_t platform_max_pages =
module->is_memory64 ? kV8MaxWasmMemory64Pages : kV8MaxWasmMemory32Pages;
if (!module->has_maximum_pages) return platform_max_pages;
return std::min(platform_max_pages, uintptr_t{module->maximum_pages});
}
}; };
// The wire bytes are either owned by the StreamingDecoder, or (after streaming) // The wire bytes are either owned by the StreamingDecoder, or (after streaming)
......
...@@ -827,10 +827,12 @@ class ModuleDecoderTemplate : public Decoder { ...@@ -827,10 +827,12 @@ class ModuleDecoderTemplate : public Decoder {
if (!AddMemory(module_.get())) break; if (!AddMemory(module_.get())) break;
uint8_t flags = validate_memory_flags(&module_->has_shared_memory, uint8_t flags = validate_memory_flags(&module_->has_shared_memory,
&module_->is_memory64); &module_->is_memory64);
consume_resizable_limits( uint32_t max_pages = module_->is_memory64 ? kSpecMaxMemory64Pages
"memory", "pages", kSpecMaxMemoryPages, &module_->initial_pages, : kSpecMaxMemory32Pages;
&module_->has_maximum_pages, kSpecMaxMemoryPages, consume_resizable_limits("memory", "pages", max_pages,
&module_->maximum_pages, flags); &module_->initial_pages,
&module_->has_maximum_pages, max_pages,
&module_->maximum_pages, flags);
break; break;
} }
case kExternalGlobal: { case kExternalGlobal: {
...@@ -949,9 +951,11 @@ class ModuleDecoderTemplate : public Decoder { ...@@ -949,9 +951,11 @@ class ModuleDecoderTemplate : public Decoder {
if (!AddMemory(module_.get())) break; if (!AddMemory(module_.get())) break;
uint8_t flags = validate_memory_flags(&module_->has_shared_memory, uint8_t flags = validate_memory_flags(&module_->has_shared_memory,
&module_->is_memory64); &module_->is_memory64);
consume_resizable_limits("memory", "pages", kSpecMaxMemoryPages, uint32_t max_pages =
module_->is_memory64 ? kSpecMaxMemory64Pages : kSpecMaxMemory32Pages;
consume_resizable_limits("memory", "pages", max_pages,
&module_->initial_pages, &module_->initial_pages,
&module_->has_maximum_pages, kSpecMaxMemoryPages, &module_->has_maximum_pages, max_pages,
&module_->maximum_pages, flags); &module_->maximum_pages, flags);
} }
} }
......
...@@ -1686,9 +1686,12 @@ bool InstanceBuilder::AllocateMemory() { ...@@ -1686,9 +1686,12 @@ bool InstanceBuilder::AllocateMemory() {
? SharedFlag::kShared ? SharedFlag::kShared
: SharedFlag::kNotShared; : SharedFlag::kNotShared;
if (!WasmMemoryObject::New(isolate_, initial_pages, maximum_pages, shared) if (!WasmMemoryObject::New(isolate_, initial_pages, maximum_pages, shared,
module_->is_memory64 ? WasmMemoryObject::kMemory64
: WasmMemoryObject::kMemory32)
.ToHandle(&memory_object_)) { .ToHandle(&memory_object_)) {
thrower_->RangeError("Out of memory: wasm memory"); thrower_->RangeError(
"Out of memory: Cannot allocate Wasm memory for new instance");
return false; return false;
} }
memory_buffer_ = memory_buffer_ =
......
...@@ -1645,12 +1645,21 @@ WasmCodeManager* GetWasmCodeManager() { ...@@ -1645,12 +1645,21 @@ WasmCodeManager* GetWasmCodeManager() {
} }
// {max_mem_pages} is declared in wasm-limits.h. // {max_mem_pages} is declared in wasm-limits.h.
uint32_t max_mem_pages() { uint32_t max_mem32_pages() {
static_assert( static_assert(
kV8MaxWasmMemoryPages * kWasmPageSize <= JSArrayBuffer::kMaxByteLength, kV8MaxWasmMemory32Pages * kWasmPageSize <= JSArrayBuffer::kMaxByteLength,
"Wasm memories must not be bigger than JSArrayBuffers"); "Wasm memories must not be bigger than JSArrayBuffers");
static_assert(kV8MaxWasmMemoryPages <= kMaxUInt32); static_assert(kV8MaxWasmMemory32Pages <= kMaxUInt32);
return std::min(uint32_t{kV8MaxWasmMemoryPages}, return std::min(uint32_t{kV8MaxWasmMemory32Pages},
FLAG_wasm_max_mem_pages.value());
}
uint32_t max_mem64_pages() {
static_assert(
kV8MaxWasmMemory64Pages * kWasmPageSize <= JSArrayBuffer::kMaxByteLength,
"Wasm memories must not be bigger than JSArrayBuffers");
static_assert(kV8MaxWasmMemory64Pages <= kMaxUInt32);
return std::min(uint32_t{kV8MaxWasmMemory64Pages},
FLAG_wasm_max_mem_pages.value()); FLAG_wasm_max_mem_pages.value());
} }
......
...@@ -1291,16 +1291,19 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -1291,16 +1291,19 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
Local<Context> context = isolate->GetCurrentContext(); Local<Context> context = isolate->GetCurrentContext();
Local<v8::Object> descriptor = Local<Object>::Cast(args[0]); Local<v8::Object> descriptor = Local<Object>::Cast(args[0]);
// TODO(clemensb): The JS API spec is not updated for memory64 yet; fix this
// code once it is.
int64_t initial = 0; int64_t initial = 0;
if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor, if (!GetInitialOrMinimumProperty(isolate, &thrower, context, descriptor,
&initial, 0, i::wasm::kSpecMaxMemoryPages)) { &initial, 0,
i::wasm::kSpecMaxMemory32Pages)) {
return; return;
} }
// The descriptor's 'maximum'. // The descriptor's 'maximum'.
int64_t maximum = i::WasmMemoryObject::kNoMaximum; int64_t maximum = i::WasmMemoryObject::kNoMaximum;
if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor, if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor,
v8_str(isolate, "maximum"), nullptr, &maximum, v8_str(isolate, "maximum"), nullptr, &maximum,
initial, i::wasm::kSpecMaxMemoryPages)) { initial, i::wasm::kSpecMaxMemory32Pages)) {
return; return;
} }
......
...@@ -20,9 +20,11 @@ namespace v8 { ...@@ -20,9 +20,11 @@ namespace v8 {
namespace internal { namespace internal {
namespace wasm { namespace wasm {
// This constant limits the amount of *declared* memory. At runtime, memory can // These constants limit the amount of *declared* memory. At runtime, memory can
// only grow up to kV8MaxWasmMemoryPages. // only grow up to kV8MaxWasmMemory{32,64}Pages.
constexpr size_t kSpecMaxMemoryPages = 65536; constexpr size_t kSpecMaxMemory32Pages = 65536; // 4GB
// TODO(clemensb): Increase the maximum for memory64.
constexpr size_t kSpecMaxMemory64Pages = 65536; // 4GB
// The following limits are imposed by V8 on WebAssembly modules. // The following limits are imposed by V8 on WebAssembly modules.
// The limits are agreed upon with other engines for consistency. // The limits are agreed upon with other engines for consistency.
...@@ -35,13 +37,17 @@ constexpr size_t kV8MaxWasmTags = 1000000; ...@@ -35,13 +37,17 @@ constexpr size_t kV8MaxWasmTags = 1000000;
constexpr size_t kV8MaxWasmExceptionTypes = 1000000; constexpr size_t kV8MaxWasmExceptionTypes = 1000000;
constexpr size_t kV8MaxWasmDataSegments = 100000; constexpr size_t kV8MaxWasmDataSegments = 100000;
// This indicates the maximum memory size our implementation supports. // This indicates the maximum memory size our implementation supports.
// Do not use this limit directly; use {max_mem_pages()} instead to take the // Do not use this limit directly; use {max_mem{32,64}_pages()} instead to take
// spec'ed limit as well as command line flag into account. // the spec'ed limit as well as command line flag into account.
// Also, do not use this limit to validate declared memory, use // Also, do not use this limit to validate declared memory, use
// kSpecMaxMemoryPages for that. // kSpecMaxMemory{32,64}Pages for that.
constexpr size_t kV8MaxWasmMemoryPages = kSystemPointerSize == 4 constexpr size_t kV8MaxWasmMemory32Pages = kSystemPointerSize == 4
? 32767 // = 2 GiB - 64Kib ? 32767 // = 2 GiB - 64Kib
: 65536; // = 4 GiB : 65536; // = 4 GiB
// TODO(clemensb): Increase the maximum for memory64.
constexpr size_t kV8MaxWasmMemory64Pages = kSystemPointerSize == 4
? 32767 // = 2 GiB - 64Kib
: 65536; // = 4 GiB
constexpr size_t kV8MaxWasmStringSize = 100000; constexpr size_t kV8MaxWasmStringSize = 100000;
constexpr size_t kV8MaxWasmModuleSize = 1024 * 1024 * 1024; // = 1 GiB constexpr size_t kV8MaxWasmModuleSize = 1024 * 1024 * 1024; // = 1 GiB
constexpr size_t kV8MaxWasmFunctionSize = 7654321; constexpr size_t kV8MaxWasmFunctionSize = 7654321;
...@@ -75,14 +81,21 @@ constexpr uint64_t kWasmMaxHeapOffset = ...@@ -75,14 +81,21 @@ constexpr uint64_t kWasmMaxHeapOffset =
// The following functions are defined in wasm-engine.cc. // The following functions are defined in wasm-engine.cc.
// Maximum number of pages we can allocate. This might be lower than the number // Maximum number of pages we can allocate, for memory32 and memory64. This
// of pages that can be declared (e.g. as maximum): kSpecMaxMemoryPages. // might be lower than the number of pages that can be declared (e.g. as
// TODO(wasm): Make this size_t for wasm64. Currently the --wasm-max-mem-pages // maximum): kSpecMaxMemory{32,64}Pages.
// flag is only uint32_t. // Even for 64-bit memory, the number of pages is still a 32-bit number for now,
V8_EXPORT_PRIVATE uint32_t max_mem_pages(); // which allows for up to 128 TB memories (2**31 * 64k).
static_assert(kV8MaxWasmMemory64Pages <= kMaxUInt32);
V8_EXPORT_PRIVATE uint32_t max_mem32_pages();
V8_EXPORT_PRIVATE uint32_t max_mem64_pages();
inline uint64_t max_mem32_bytes() {
return uint64_t{max_mem32_pages()} * kWasmPageSize;
}
inline uint64_t max_mem_bytes() { inline uint64_t max_mem64_bytes() {
return uint64_t{max_mem_pages()} * kWasmPageSize; return uint64_t{max_mem64_pages()} * kWasmPageSize;
} }
V8_EXPORT_PRIVATE uint32_t max_table_init_entries(); V8_EXPORT_PRIVATE uint32_t max_table_init_entries();
......
...@@ -814,7 +814,8 @@ void SetInstanceMemory(Handle<WasmInstanceObject> instance, ...@@ -814,7 +814,8 @@ void SetInstanceMemory(Handle<WasmInstanceObject> instance,
} // namespace } // namespace
MaybeHandle<WasmMemoryObject> WasmMemoryObject::New( MaybeHandle<WasmMemoryObject> WasmMemoryObject::New(
Isolate* isolate, Handle<JSArrayBuffer> buffer, int maximum) { Isolate* isolate, Handle<JSArrayBuffer> buffer, int maximum,
MemoryIndexType index_type) {
Handle<JSFunction> memory_ctor( Handle<JSFunction> memory_ctor(
isolate->native_context()->wasm_memory_constructor(), isolate); isolate->native_context()->wasm_memory_constructor(), isolate);
...@@ -822,6 +823,7 @@ MaybeHandle<WasmMemoryObject> WasmMemoryObject::New( ...@@ -822,6 +823,7 @@ MaybeHandle<WasmMemoryObject> WasmMemoryObject::New(
isolate->factory()->NewJSObject(memory_ctor, AllocationType::kOld)); isolate->factory()->NewJSObject(memory_ctor, AllocationType::kOld));
memory_object->set_array_buffer(*buffer); memory_object->set_array_buffer(*buffer);
memory_object->set_maximum_pages(maximum); memory_object->set_maximum_pages(maximum);
memory_object->set_is_memory64(index_type == MemoryIndexType::kMemory64);
if (buffer->is_shared()) { if (buffer->is_shared()) {
auto backing_store = buffer->GetBackingStore(); auto backing_store = buffer->GetBackingStore();
...@@ -836,19 +838,22 @@ MaybeHandle<WasmMemoryObject> WasmMemoryObject::New( ...@@ -836,19 +838,22 @@ MaybeHandle<WasmMemoryObject> WasmMemoryObject::New(
return memory_object; return memory_object;
} }
MaybeHandle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate, MaybeHandle<WasmMemoryObject> WasmMemoryObject::New(
int initial, int maximum, Isolate* isolate, int initial, int maximum, SharedFlag shared,
SharedFlag shared) { MemoryIndexType index_type) {
bool has_maximum = maximum != kNoMaximum; bool has_maximum = maximum != kNoMaximum;
int heuristic_maximum = maximum;
if (!has_maximum) { int engine_maximum = index_type == MemoryIndexType::kMemory64
heuristic_maximum = static_cast<int>(wasm::max_mem_pages()); ? static_cast<int>(wasm::max_mem64_pages())
} : static_cast<int>(wasm::max_mem32_pages());
if (initial > engine_maximum) return {};
#ifdef V8_TARGET_ARCH_32_BIT #ifdef V8_TARGET_ARCH_32_BIT
// On 32-bit platforms we need an heuristic here to balance overall memory // On 32-bit platforms we need an heuristic here to balance overall memory
// and address space consumption. // and address space consumption.
constexpr int kGBPages = 1024 * 1024 * 1024 / wasm::kWasmPageSize; constexpr int kGBPages = 1024 * 1024 * 1024 / wasm::kWasmPageSize;
int heuristic_maximum;
if (initial > kGBPages) { if (initial > kGBPages) {
// We always allocate at least the initial size. // We always allocate at least the initial size.
heuristic_maximum = initial; heuristic_maximum = initial;
...@@ -863,6 +868,9 @@ MaybeHandle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate, ...@@ -863,6 +868,9 @@ MaybeHandle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate,
// and then grow with realloc. // and then grow with realloc.
heuristic_maximum = initial; heuristic_maximum = initial;
} }
#else
int heuristic_maximum =
has_maximum ? std::min(engine_maximum, maximum) : engine_maximum;
#endif #endif
auto backing_store = BackingStore::AllocateWasmMemory( auto backing_store = BackingStore::AllocateWasmMemory(
...@@ -933,10 +941,11 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate, ...@@ -933,10 +941,11 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
size_t old_size = old_buffer->byte_length(); size_t old_size = old_buffer->byte_length();
DCHECK_EQ(0, old_size % wasm::kWasmPageSize); DCHECK_EQ(0, old_size % wasm::kWasmPageSize);
size_t old_pages = old_size / wasm::kWasmPageSize; size_t old_pages = old_size / wasm::kWasmPageSize;
uint32_t max_pages = wasm::kSpecMaxMemoryPages; size_t max_pages = memory_object->is_memory64() ? wasm::max_mem64_pages()
: wasm::max_mem32_pages();
if (memory_object->has_maximum_pages()) { if (memory_object->has_maximum_pages()) {
DCHECK_GE(max_pages, memory_object->maximum_pages()); max_pages = std::min(max_pages,
max_pages = static_cast<uint32_t>(memory_object->maximum_pages()); static_cast<size_t>(memory_object->maximum_pages()));
} }
DCHECK_GE(max_pages, old_pages); DCHECK_GE(max_pages, old_pages);
if (pages > max_pages - old_pages) return -1; if (pages > max_pages - old_pages) return -1;
...@@ -997,7 +1006,7 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate, ...@@ -997,7 +1006,7 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
// These numbers are kept small because we must be careful about address // These numbers are kept small because we must be careful about address
// space consumption on 32-bit platforms. // space consumption on 32-bit platforms.
size_t min_growth = old_pages + 8 + (old_pages >> 3); size_t min_growth = old_pages + 8 + (old_pages >> 3);
size_t new_capacity = std::max(new_pages, min_growth); size_t new_capacity = std::clamp(new_pages, min_growth, max_pages);
std::unique_ptr<BackingStore> new_backing_store = std::unique_ptr<BackingStore> new_backing_store =
backing_store->CopyWasmMemory(isolate, new_pages, new_capacity); backing_store->CopyWasmMemory(isolate, new_pages, new_capacity);
if (!new_backing_store) { if (!new_backing_store) {
...@@ -1152,7 +1161,8 @@ bool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize( ...@@ -1152,7 +1161,8 @@ bool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
} }
void WasmInstanceObject::SetRawMemory(byte* mem_start, size_t mem_size) { void WasmInstanceObject::SetRawMemory(byte* mem_start, size_t mem_size) {
CHECK_LE(mem_size, wasm::max_mem_bytes()); CHECK_LE(mem_size, module()->is_memory64 ? wasm::max_mem64_bytes()
: wasm::max_mem32_bytes());
set_memory_start(mem_start); set_memory_start(mem_start);
set_memory_size(mem_size); set_memory_size(mem_size);
} }
...@@ -1188,7 +1198,6 @@ Handle<WasmInstanceObject> WasmInstanceObject::New( ...@@ -1188,7 +1198,6 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
isolate->factory()->NewFixedArray(num_imported_functions); isolate->factory()->NewFixedArray(num_imported_functions);
instance->set_imported_function_refs(*imported_function_refs); instance->set_imported_function_refs(*imported_function_refs);
instance->SetRawMemory(reinterpret_cast<byte*>(EmptyBackingStoreBuffer()), 0);
instance->set_isolate_root(isolate->isolate_root()); instance->set_isolate_root(isolate->isolate_root());
instance->set_stack_limit_address( instance->set_stack_limit_address(
isolate->stack_guard()->address_of_jslimit()); isolate->stack_guard()->address_of_jslimit());
...@@ -1220,6 +1229,7 @@ Handle<WasmInstanceObject> WasmInstanceObject::New( ...@@ -1220,6 +1229,7 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
instance->set_tiering_budget_array( instance->set_tiering_budget_array(
module_object->native_module()->tiering_budget_array()); module_object->native_module()->tiering_budget_array());
instance->set_break_on_entry(module_object->script().break_on_entry()); instance->set_break_on_entry(module_object->script().break_on_entry());
instance->SetRawMemory(reinterpret_cast<byte*>(EmptyBackingStoreBuffer()), 0);
// Insert the new instance into the scripts weak list of instances. This list // Insert the new instance into the scripts weak list of instances. This list
// is used for breakpoints affecting all instances belonging to the script. // is used for breakpoints affecting all instances belonging to the script.
......
...@@ -253,6 +253,9 @@ class WasmTableObject ...@@ -253,6 +253,9 @@ class WasmTableObject
class WasmMemoryObject class WasmMemoryObject
: public TorqueGeneratedWasmMemoryObject<WasmMemoryObject, JSObject> { : public TorqueGeneratedWasmMemoryObject<WasmMemoryObject, JSObject> {
public: public:
// Whether this memory object is a 64-bit memory.
enum MemoryIndexType { kMemory32, kMemory64 };
DECL_OPTIONAL_ACCESSORS(instances, WeakArrayList) DECL_OPTIONAL_ACCESSORS(instances, WeakArrayList)
// Add an instance to the internal (weak) list. // Add an instance to the internal (weak) list.
...@@ -262,12 +265,13 @@ class WasmMemoryObject ...@@ -262,12 +265,13 @@ class WasmMemoryObject
inline bool has_maximum_pages(); inline bool has_maximum_pages();
V8_EXPORT_PRIVATE static MaybeHandle<WasmMemoryObject> New( V8_EXPORT_PRIVATE static MaybeHandle<WasmMemoryObject> New(
Isolate* isolate, Handle<JSArrayBuffer> buffer, int maximum); Isolate* isolate, Handle<JSArrayBuffer> buffer, int maximum,
MemoryIndexType index_type = MemoryIndexType::kMemory32);
V8_EXPORT_PRIVATE static MaybeHandle<WasmMemoryObject> New(Isolate* isolate, V8_EXPORT_PRIVATE static MaybeHandle<WasmMemoryObject> New(
int initial, Isolate* isolate, int initial, int maximum,
int maximum, SharedFlag shared = SharedFlag::kNotShared,
SharedFlag shared); MemoryIndexType index_type = MemoryIndexType::kMemory32);
static constexpr int kNoMaximum = -1; static constexpr int kNoMaximum = -1;
......
...@@ -151,6 +151,7 @@ extern class WasmTableObject extends JSObject { ...@@ -151,6 +151,7 @@ extern class WasmTableObject extends JSObject {
extern class WasmMemoryObject extends JSObject { extern class WasmMemoryObject extends JSObject {
array_buffer: JSArrayBuffer; array_buffer: JSArrayBuffer;
maximum_pages: Smi; maximum_pages: Smi;
is_memory64: Smi; // Boolean
instances: WeakArrayList|Undefined; instances: WeakArrayList|Undefined;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment