Commit b5fcbda3 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm][32-bit] Only reserve maximum memory size if it was defined

With a recent change we reserve the maximum memory size also on 32-bit
platforms, up to 1GB. This change, however, caused failing tests in the
cases where no maximum memory size was defined and where WebAssembly
defines an implicit maximum memory size of 4GB. With this CL we do not
reserve more memory than the initial size if no maximum memory size is
defined.

R=clemensb@chromium.org

Bug: v8:11493
Change-Id: I62b62fd4faa7a480275b75421a98f73539646eab
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2712756
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72977}
parent d1552fa7
......@@ -465,9 +465,9 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
// The maximum number of pages isn't strictly necessary for memory
// objects used for asm.js, as they are never visible, but we might
// as well make it accurate.
auto maximum_pages = static_cast<uint32_t>(
RoundUp(buffer->byte_length(), wasm::kWasmPageSize) /
wasm::kWasmPageSize);
auto maximum_pages =
static_cast<int>(RoundUp(buffer->byte_length(), wasm::kWasmPageSize) /
wasm::kWasmPageSize);
memory_object_ =
WasmMemoryObject::New(isolate_, memory_buffer_, maximum_pages);
} else {
......@@ -1632,10 +1632,11 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) {
// Allocate memory for a module instance as a new JSArrayBuffer.
bool InstanceBuilder::AllocateMemory() {
uint32_t initial_pages = module_->initial_pages;
uint32_t maximum_pages =
module_->has_maximum_pages ? module_->maximum_pages : max_mem_pages();
if (initial_pages > max_mem_pages()) {
int initial_pages = static_cast<int>(module_->initial_pages);
int maximum_pages = module_->has_maximum_pages
? static_cast<int>(module_->maximum_pages)
: WasmMemoryObject::kNoMaximum;
if (initial_pages > static_cast<int>(max_mem_pages())) {
thrower_->RangeError("Out of memory: wasm memory too large");
return false;
}
......
......@@ -1144,7 +1144,7 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
// The descriptor's 'maximum'.
int64_t maximum = -1;
int64_t maximum = i::WasmMemoryObject::kNoMaximum;
if (!GetOptionalIntegerProperty(isolate, &thrower, context, descriptor,
v8_str(isolate, "maximum"), nullptr, &maximum,
initial, i::wasm::max_mem_pages())) {
......@@ -1176,8 +1176,8 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
i::Handle<i::JSObject> memory_obj;
if (!i::WasmMemoryObject::New(i_isolate, static_cast<uint32_t>(initial),
static_cast<uint32_t>(maximum), shared)
if (!i::WasmMemoryObject::New(i_isolate, static_cast<int>(initial),
static_cast<int>(maximum), shared)
.ToHandle(&memory_obj)) {
thrower.RangeError("could not allocate memory");
return;
......
......@@ -816,8 +816,7 @@ void SetInstanceMemory(Handle<WasmInstanceObject> instance,
} // namespace
Handle<WasmMemoryObject> WasmMemoryObject::New(
Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_buffer,
uint32_t maximum) {
Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_buffer, int maximum) {
Handle<JSArrayBuffer> buffer;
if (!maybe_buffer.ToHandle(&buffer)) {
// If no buffer was provided, create a zero-length one.
......@@ -848,21 +847,29 @@ Handle<WasmMemoryObject> WasmMemoryObject::New(
}
MaybeHandle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate,
uint32_t initial,
uint32_t maximum,
int initial, int maximum,
SharedFlag shared) {
auto heuristic_maximum = maximum;
bool has_maximum = maximum != kNoMaximum;
int heuristic_maximum = maximum;
if (!has_maximum) {
heuristic_maximum = static_cast<int>(wasm::max_mem_pages());
}
#ifdef V8_TARGET_ARCH_32_BIT
// TODO(wasm): use a better heuristic for reserving more than the initial
// number of pages on 32-bit systems. Being too greedy in reserving capacity
// limits the number of memories that can be allocated, causing OOMs in many
// tests. For now, on 32-bit we never reserve more than initial, unless the
// memory is shared.
if (shared == SharedFlag::kNotShared) {
// On 32-bit systems we reserve a maximum of 1GB.
constexpr uint32_t kGB = 1024 * 1024 * 1024;
heuristic_maximum = std::min(maximum, kGB / wasm::kWasmPageSize);
heuristic_maximum = std::max(heuristic_maximum, initial);
// On 32-bit platforms we need a heuristic here to balance overall memory
// and address space consumption. If a maximum memory size is defined, then
// we reserve that maximum size up to 1GB. If no maximum memory size is
// defined, we just allocate the initial size and grow with a realloc.
constexpr int kGBPages = 1024 * 1024 * 1024 / wasm::kWasmPageSize;
if (initial > kGBPages || !has_maximum) {
// We allocate at least the initial size. If no maximum is specified we
// also start with the initial size.
heuristic_maximum = initial;
} else {
// We reserve the maximum size, but at most 1GB.
heuristic_maximum = std::min(maximum, kGBPages);
}
}
#endif
......
......@@ -309,13 +309,15 @@ class WasmMemoryObject : public JSObject {
inline bool has_maximum_pages();
V8_EXPORT_PRIVATE static Handle<WasmMemoryObject> New(
Isolate* isolate, MaybeHandle<JSArrayBuffer> buffer, uint32_t maximum);
Isolate* isolate, MaybeHandle<JSArrayBuffer> buffer, int maximum);
V8_EXPORT_PRIVATE static MaybeHandle<WasmMemoryObject> New(Isolate* isolate,
uint32_t initial,
uint32_t maximum,
int initial,
int maximum,
SharedFlag shared);
static constexpr int kNoMaximum = -1;
void update_instances(Isolate* isolate, Handle<JSArrayBuffer> buffer);
V8_EXPORT_PRIVATE static int32_t Grow(Isolate*, Handle<WasmMemoryObject>,
......
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