[wasm] [cleanup] Attach methods to the object they operate on
This CL cleans up a few things: - It removes two dead declarations: WasmMemoryObject::Grow and wasm::GrowInstanceMemory. - It removes the unneeded wasm::GetInstanceMemory function (use instance->memory_buffer() directly). - It moves wasm::GetInstanceMemorySize to WasmInstanceObject::GetMemorySize. - It moves wasm::GrowInstanceMemory to WasmInstanceObject::GrowMemory. - It moves wasm::GrowWebAssemblyMemory to WasmMemoryObject::Grow. R=ahaas@chromium.org CC=gdeepti@chromium.org Change-Id: I19781ca9784f1a8e7b60955bef82e341c4f75550 Reviewed-on: https://chromium-review.googlesource.com/463167 Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Reviewed-by: Andreas Haas <ahaas@chromium.org> Reviewed-by: Deepti Gandluri <gdeepti@chromium.org> Cr-Commit-Position: refs/heads/master@{#44293}
This commit is contained in:
parent
19f655a814
commit
c32113e7eb
@ -45,10 +45,8 @@ RUNTIME_FUNCTION(Runtime_WasmMemorySize) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(0, args.length());
|
||||
|
||||
Handle<WasmInstanceObject> instance(GetWasmInstanceOnStackTop(isolate),
|
||||
isolate);
|
||||
return *isolate->factory()->NewNumberFromInt(
|
||||
wasm::GetInstanceMemorySize(isolate, instance));
|
||||
int32_t mem_size = GetWasmInstanceOnStackTop(isolate)->GetMemorySize();
|
||||
return *isolate->factory()->NewNumberFromInt(mem_size);
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
|
||||
@ -63,7 +61,7 @@ RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
|
||||
isolate->set_context(instance->compiled_module()->ptr_to_native_context());
|
||||
|
||||
return *isolate->factory()->NewNumberFromInt(
|
||||
wasm::GrowMemory(isolate, instance, delta_pages));
|
||||
WasmInstanceObject::GrowMemory(isolate, instance, delta_pages));
|
||||
}
|
||||
|
||||
Object* ThrowRuntimeError(Isolate* isolate, int message_id, int byte_offset,
|
||||
|
@ -646,8 +646,8 @@ void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
: "maximum memory size exceeded");
|
||||
return;
|
||||
}
|
||||
int32_t ret = i::wasm::GrowWebAssemblyMemory(
|
||||
i_isolate, receiver, static_cast<uint32_t>(delta_size));
|
||||
int32_t ret = i::WasmMemoryObject::Grow(i_isolate, receiver,
|
||||
static_cast<uint32_t>(delta_size));
|
||||
if (ret == -1) {
|
||||
thrower.RangeError("Unable to grow instance memory.");
|
||||
return;
|
||||
|
@ -816,9 +816,10 @@ void RecordLazyCodeStats(Isolate* isolate, Code* code) {
|
||||
|
||||
} // namespace
|
||||
|
||||
Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* backing_store,
|
||||
size_t size, bool is_external,
|
||||
bool enable_guard_regions) {
|
||||
Handle<JSArrayBuffer> wasm::SetupArrayBuffer(Isolate* isolate,
|
||||
void* backing_store, size_t size,
|
||||
bool is_external,
|
||||
bool enable_guard_regions) {
|
||||
Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
|
||||
JSArrayBuffer::Setup(buffer, isolate, is_external, backing_store,
|
||||
static_cast<int>(size));
|
||||
@ -2237,105 +2238,6 @@ bool wasm::IsWasmCodegenAllowed(Isolate* isolate, Handle<Context> context) {
|
||||
isolate->allow_code_gen_callback()(v8::Utils::ToLocal(context));
|
||||
}
|
||||
|
||||
MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory(
|
||||
Isolate* isolate, Handle<WasmInstanceObject> object) {
|
||||
auto instance = Handle<WasmInstanceObject>::cast(object);
|
||||
if (instance->has_memory_buffer()) {
|
||||
return Handle<JSArrayBuffer>(instance->memory_buffer(), isolate);
|
||||
}
|
||||
return MaybeHandle<JSArrayBuffer>();
|
||||
}
|
||||
|
||||
// May GC, because SetSpecializationMemInfoFrom may GC
|
||||
void SetInstanceMemory(Isolate* isolate, Handle<WasmInstanceObject> instance,
|
||||
Handle<JSArrayBuffer> buffer) {
|
||||
instance->set_memory_buffer(*buffer);
|
||||
WasmCompiledModule::SetSpecializationMemInfoFrom(
|
||||
isolate->factory(), handle(instance->compiled_module()), buffer);
|
||||
}
|
||||
|
||||
int32_t wasm::GetInstanceMemorySize(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance) {
|
||||
DCHECK(IsWasmInstance(*instance));
|
||||
MaybeHandle<JSArrayBuffer> maybe_mem_buffer =
|
||||
GetInstanceMemory(isolate, instance);
|
||||
Handle<JSArrayBuffer> buffer;
|
||||
if (!maybe_mem_buffer.ToHandle(&buffer)) {
|
||||
return 0;
|
||||
} else {
|
||||
return buffer->byte_length()->Number() / WasmModule::kPageSize;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GetMaxInstanceMemoryPages(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance) {
|
||||
if (instance->has_memory_object()) {
|
||||
Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate);
|
||||
if (memory_object->has_maximum_pages()) {
|
||||
uint32_t maximum = static_cast<uint32_t>(memory_object->maximum_pages());
|
||||
if (maximum < FLAG_wasm_max_mem_pages) return maximum;
|
||||
}
|
||||
}
|
||||
WasmCompiledModule* compiled_module = instance->compiled_module();
|
||||
uint32_t compiled_max_pages = compiled_module->max_mem_pages();
|
||||
(compiled_module->module()->is_wasm()
|
||||
? isolate->counters()->wasm_wasm_max_mem_pages_count()
|
||||
: isolate->counters()->wasm_asm_max_mem_pages_count())
|
||||
->AddSample(compiled_max_pages);
|
||||
if (compiled_max_pages != 0) return compiled_max_pages;
|
||||
return FLAG_wasm_max_mem_pages;
|
||||
}
|
||||
|
||||
Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
|
||||
MaybeHandle<JSArrayBuffer> buffer,
|
||||
uint32_t pages, uint32_t max_pages) {
|
||||
Handle<JSArrayBuffer> old_buffer;
|
||||
Address old_mem_start = nullptr;
|
||||
uint32_t old_size = 0;
|
||||
if (buffer.ToHandle(&old_buffer) && old_buffer->backing_store() != nullptr &&
|
||||
old_buffer->byte_length()->IsNumber()) {
|
||||
old_mem_start = static_cast<Address>(old_buffer->backing_store());
|
||||
DCHECK_NOT_NULL(old_mem_start);
|
||||
old_size = old_buffer->byte_length()->Number();
|
||||
}
|
||||
DCHECK(old_size + pages * WasmModule::kPageSize <=
|
||||
std::numeric_limits<uint32_t>::max());
|
||||
uint32_t new_size = old_size + pages * WasmModule::kPageSize;
|
||||
if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size ||
|
||||
FLAG_wasm_max_mem_pages * WasmModule::kPageSize < new_size) {
|
||||
return Handle<JSArrayBuffer>::null();
|
||||
}
|
||||
|
||||
// TODO(gdeepti): Change the protection here instead of allocating a new
|
||||
// buffer before guard regions are turned on, see issue #5886.
|
||||
const bool enable_guard_regions =
|
||||
(old_buffer.is_null() && EnableGuardRegions()) ||
|
||||
(!old_buffer.is_null() && old_buffer->has_guard_region());
|
||||
Handle<JSArrayBuffer> new_buffer =
|
||||
NewArrayBuffer(isolate, new_size, enable_guard_regions);
|
||||
if (new_buffer.is_null()) return new_buffer;
|
||||
Address new_mem_start = static_cast<Address>(new_buffer->backing_store());
|
||||
if (old_size != 0) {
|
||||
memcpy(new_mem_start, old_mem_start, old_size);
|
||||
}
|
||||
return new_buffer;
|
||||
}
|
||||
|
||||
void UncheckedUpdateInstanceMemory(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance,
|
||||
Address old_mem_start, uint32_t old_size) {
|
||||
DCHECK(instance->has_memory_buffer());
|
||||
Handle<JSArrayBuffer> mem_buffer(instance->memory_buffer());
|
||||
uint32_t new_size = mem_buffer->byte_length()->Number();
|
||||
Address new_mem_start = static_cast<Address>(mem_buffer->backing_store());
|
||||
DCHECK_NOT_NULL(new_mem_start);
|
||||
Zone specialization_zone(isolate->allocator(), ZONE_NAME);
|
||||
CodeSpecialization code_specialization(isolate, &specialization_zone);
|
||||
code_specialization.RelocateMemoryReferences(old_mem_start, old_size,
|
||||
new_mem_start, new_size);
|
||||
code_specialization.ApplyToWholeInstance(*instance);
|
||||
}
|
||||
|
||||
void wasm::DetachWebAssemblyMemoryBuffer(Isolate* isolate,
|
||||
Handle<JSArrayBuffer> buffer) {
|
||||
int64_t byte_length =
|
||||
@ -2363,114 +2265,6 @@ void wasm::DetachWebAssemblyMemoryBuffer(Isolate* isolate,
|
||||
}
|
||||
}
|
||||
|
||||
int32_t wasm::GrowWebAssemblyMemory(Isolate* isolate,
|
||||
Handle<WasmMemoryObject> receiver,
|
||||
uint32_t pages) {
|
||||
DCHECK(WasmJs::IsWasmMemoryObject(isolate, receiver));
|
||||
Handle<WasmMemoryObject> memory_object =
|
||||
handle(WasmMemoryObject::cast(*receiver));
|
||||
MaybeHandle<JSArrayBuffer> memory_buffer = handle(memory_object->buffer());
|
||||
Handle<JSArrayBuffer> old_buffer;
|
||||
uint32_t old_size = 0;
|
||||
Address old_mem_start = nullptr;
|
||||
// Force byte_length to 0, if byte_length fails IsNumber() check.
|
||||
if (memory_buffer.ToHandle(&old_buffer) &&
|
||||
old_buffer->backing_store() != nullptr &&
|
||||
old_buffer->byte_length()->IsNumber()) {
|
||||
old_size = old_buffer->byte_length()->Number();
|
||||
old_mem_start = static_cast<Address>(old_buffer->backing_store());
|
||||
}
|
||||
Handle<JSArrayBuffer> new_buffer;
|
||||
// Return current size if grow by 0
|
||||
if (pages == 0) {
|
||||
if (!old_buffer.is_null() && old_buffer->backing_store() != nullptr) {
|
||||
new_buffer = SetupArrayBuffer(isolate, old_buffer->backing_store(),
|
||||
old_size, old_buffer->is_external(),
|
||||
old_buffer->has_guard_region());
|
||||
memory_object->set_buffer(*new_buffer);
|
||||
old_buffer->set_is_neuterable(true);
|
||||
if (!old_buffer->has_guard_region()) {
|
||||
old_buffer->set_is_external(true);
|
||||
isolate->heap()->UnregisterArrayBuffer(*old_buffer);
|
||||
}
|
||||
// Neuter but don't free the memory because it is now being used by
|
||||
// new_buffer.
|
||||
old_buffer->Neuter();
|
||||
}
|
||||
DCHECK(old_size % WasmModule::kPageSize == 0);
|
||||
return (old_size / WasmModule::kPageSize);
|
||||
}
|
||||
if (!memory_object->has_instances_link()) {
|
||||
// Memory object does not have an instance associated with it, just grow
|
||||
uint32_t max_pages;
|
||||
if (memory_object->has_maximum_pages()) {
|
||||
max_pages = static_cast<uint32_t>(memory_object->maximum_pages());
|
||||
if (FLAG_wasm_max_mem_pages < max_pages) return -1;
|
||||
} else {
|
||||
max_pages = FLAG_wasm_max_mem_pages;
|
||||
}
|
||||
new_buffer = GrowMemoryBuffer(isolate, memory_buffer, pages, max_pages);
|
||||
if (new_buffer.is_null()) return -1;
|
||||
} else {
|
||||
Handle<WasmInstanceWrapper> instance_wrapper(
|
||||
memory_object->instances_link());
|
||||
DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
|
||||
DCHECK(instance_wrapper->has_instance());
|
||||
Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
|
||||
DCHECK(IsWasmInstance(*instance));
|
||||
uint32_t max_pages = GetMaxInstanceMemoryPages(isolate, instance);
|
||||
|
||||
// Grow memory object buffer and update instances associated with it.
|
||||
new_buffer = GrowMemoryBuffer(isolate, memory_buffer, pages, max_pages);
|
||||
if (new_buffer.is_null()) return -1;
|
||||
DCHECK(!instance_wrapper->has_previous());
|
||||
SetInstanceMemory(isolate, instance, new_buffer);
|
||||
UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
|
||||
while (instance_wrapper->has_next()) {
|
||||
instance_wrapper = instance_wrapper->next_wrapper();
|
||||
DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
|
||||
Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
|
||||
DCHECK(IsWasmInstance(*instance));
|
||||
SetInstanceMemory(isolate, instance, new_buffer);
|
||||
UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
|
||||
}
|
||||
}
|
||||
memory_object->set_buffer(*new_buffer);
|
||||
DCHECK(old_size % WasmModule::kPageSize == 0);
|
||||
return (old_size / WasmModule::kPageSize);
|
||||
}
|
||||
|
||||
int32_t wasm::GrowMemory(Isolate* isolate, Handle<WasmInstanceObject> instance,
|
||||
uint32_t pages) {
|
||||
if (!IsWasmInstance(*instance)) return -1;
|
||||
if (pages == 0) return GetInstanceMemorySize(isolate, instance);
|
||||
Handle<WasmInstanceObject> instance_obj(WasmInstanceObject::cast(*instance));
|
||||
if (!instance_obj->has_memory_object()) {
|
||||
// No other instances to grow, grow just the one.
|
||||
MaybeHandle<JSArrayBuffer> instance_buffer =
|
||||
GetInstanceMemory(isolate, instance);
|
||||
Handle<JSArrayBuffer> old_buffer;
|
||||
uint32_t old_size = 0;
|
||||
Address old_mem_start = nullptr;
|
||||
if (instance_buffer.ToHandle(&old_buffer) &&
|
||||
old_buffer->backing_store() != nullptr) {
|
||||
old_size = old_buffer->byte_length()->Number();
|
||||
old_mem_start = static_cast<Address>(old_buffer->backing_store());
|
||||
}
|
||||
uint32_t max_pages = GetMaxInstanceMemoryPages(isolate, instance_obj);
|
||||
Handle<JSArrayBuffer> buffer =
|
||||
GrowMemoryBuffer(isolate, instance_buffer, pages, max_pages);
|
||||
if (buffer.is_null()) return -1;
|
||||
SetInstanceMemory(isolate, instance, buffer);
|
||||
UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
|
||||
DCHECK(old_size % WasmModule::kPageSize == 0);
|
||||
return (old_size / WasmModule::kPageSize);
|
||||
} else {
|
||||
return GrowWebAssemblyMemory(isolate, handle(instance_obj->memory_object()),
|
||||
pages);
|
||||
}
|
||||
}
|
||||
|
||||
void wasm::GrowDispatchTables(Isolate* isolate,
|
||||
Handle<FixedArray> dispatch_tables,
|
||||
uint32_t old_size, uint32_t count) {
|
||||
|
@ -419,24 +419,12 @@ int GetFunctionCodeOffset(Handle<WasmCompiledModule> compiled_module,
|
||||
// Returns nullptr on failing to get owning instance.
|
||||
WasmInstanceObject* GetOwningWasmInstance(Code* code);
|
||||
|
||||
MaybeHandle<JSArrayBuffer> GetInstanceMemory(
|
||||
Isolate* isolate, Handle<WasmInstanceObject> instance);
|
||||
|
||||
int32_t GetInstanceMemorySize(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance);
|
||||
|
||||
int32_t GrowInstanceMemory(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance, uint32_t pages);
|
||||
|
||||
Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size,
|
||||
Handle<JSArrayBuffer> NewArrayBuffer(Isolate*, size_t size,
|
||||
bool enable_guard_regions);
|
||||
|
||||
int32_t GrowWebAssemblyMemory(Isolate* isolate,
|
||||
Handle<WasmMemoryObject> receiver,
|
||||
uint32_t pages);
|
||||
|
||||
int32_t GrowMemory(Isolate* isolate, Handle<WasmInstanceObject> instance,
|
||||
uint32_t pages);
|
||||
Handle<JSArrayBuffer> SetupArrayBuffer(Isolate*, void* backing_store,
|
||||
size_t size, bool is_external,
|
||||
bool enable_guard_regions);
|
||||
|
||||
void DetachWebAssemblyMemoryBuffer(Isolate* isolate,
|
||||
Handle<JSArrayBuffer> buffer);
|
||||
|
@ -337,6 +337,64 @@ void WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table,
|
||||
table->functions()->length(), count);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
|
||||
Handle<JSArrayBuffer> old_buffer,
|
||||
uint32_t pages, uint32_t max_pages) {
|
||||
Address old_mem_start = nullptr;
|
||||
uint32_t old_size = 0;
|
||||
if (!old_buffer.is_null()) {
|
||||
DCHECK(old_buffer->byte_length()->IsNumber());
|
||||
old_mem_start = static_cast<Address>(old_buffer->backing_store());
|
||||
old_size = old_buffer->byte_length()->Number();
|
||||
}
|
||||
DCHECK_GE(std::numeric_limits<uint32_t>::max(),
|
||||
old_size + pages * WasmModule::kPageSize);
|
||||
uint32_t new_size = old_size + pages * WasmModule::kPageSize;
|
||||
if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size ||
|
||||
FLAG_wasm_max_mem_pages * WasmModule::kPageSize < new_size) {
|
||||
return Handle<JSArrayBuffer>::null();
|
||||
}
|
||||
|
||||
// TODO(gdeepti): Change the protection here instead of allocating a new
|
||||
// buffer before guard regions are turned on, see issue #5886.
|
||||
const bool enable_guard_regions =
|
||||
(old_buffer.is_null() && EnableGuardRegions()) ||
|
||||
(!old_buffer.is_null() && old_buffer->has_guard_region());
|
||||
Handle<JSArrayBuffer> new_buffer =
|
||||
NewArrayBuffer(isolate, new_size, enable_guard_regions);
|
||||
if (new_buffer.is_null()) return new_buffer;
|
||||
Address new_mem_start = static_cast<Address>(new_buffer->backing_store());
|
||||
memcpy(new_mem_start, old_mem_start, old_size);
|
||||
return new_buffer;
|
||||
}
|
||||
|
||||
// May GC, because SetSpecializationMemInfoFrom may GC
|
||||
void SetInstanceMemory(Isolate* isolate, Handle<WasmInstanceObject> instance,
|
||||
Handle<JSArrayBuffer> buffer) {
|
||||
instance->set_memory_buffer(*buffer);
|
||||
WasmCompiledModule::SetSpecializationMemInfoFrom(
|
||||
isolate->factory(), handle(instance->compiled_module()), buffer);
|
||||
}
|
||||
|
||||
void UncheckedUpdateInstanceMemory(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance,
|
||||
Address old_mem_start, uint32_t old_size) {
|
||||
DCHECK(instance->has_memory_buffer());
|
||||
Handle<JSArrayBuffer> mem_buffer(instance->memory_buffer());
|
||||
uint32_t new_size = mem_buffer->byte_length()->Number();
|
||||
Address new_mem_start = static_cast<Address>(mem_buffer->backing_store());
|
||||
DCHECK_NOT_NULL(new_mem_start);
|
||||
Zone specialization_zone(isolate->allocator(), ZONE_NAME);
|
||||
CodeSpecialization code_specialization(isolate, &specialization_zone);
|
||||
code_specialization.RelocateMemoryReferences(old_mem_start, old_size,
|
||||
new_mem_start, new_size);
|
||||
code_specialization.ApplyToWholeInstance(*instance);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Handle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate,
|
||||
Handle<JSArrayBuffer> buffer,
|
||||
int32_t maximum) {
|
||||
@ -395,6 +453,80 @@ void WasmMemoryObject::ResetInstancesLink(Isolate* isolate) {
|
||||
SetEmbedderField(kInstancesLink, *undefined);
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t WasmMemoryObject::Grow(Isolate* isolate,
|
||||
Handle<WasmMemoryObject> memory_object,
|
||||
uint32_t pages) {
|
||||
Handle<JSArrayBuffer> old_buffer(memory_object->buffer(), isolate);
|
||||
uint32_t old_size = 0;
|
||||
Address old_mem_start = nullptr;
|
||||
// Force byte_length to 0, if byte_length fails IsNumber() check.
|
||||
if (!old_buffer.is_null()) {
|
||||
old_size = old_buffer->byte_length()->Number();
|
||||
old_mem_start = static_cast<Address>(old_buffer->backing_store());
|
||||
}
|
||||
Handle<JSArrayBuffer> new_buffer;
|
||||
// Return current size if grow by 0.
|
||||
if (pages == 0) {
|
||||
// Even for pages == 0, we need to attach a new JSArrayBuffer and neuter the
|
||||
// old one to be spec compliant.
|
||||
if (!old_buffer.is_null() && old_buffer->backing_store() != nullptr) {
|
||||
new_buffer = SetupArrayBuffer(isolate, old_buffer->backing_store(),
|
||||
old_size, old_buffer->is_external(),
|
||||
old_buffer->has_guard_region());
|
||||
memory_object->set_buffer(*new_buffer);
|
||||
old_buffer->set_is_neuterable(true);
|
||||
if (!old_buffer->has_guard_region()) {
|
||||
old_buffer->set_is_external(true);
|
||||
isolate->heap()->UnregisterArrayBuffer(*old_buffer);
|
||||
}
|
||||
// Neuter but don't free the memory because it is now being used by
|
||||
// new_buffer.
|
||||
old_buffer->Neuter();
|
||||
}
|
||||
DCHECK_EQ(0, old_size % WasmModule::kPageSize);
|
||||
return old_size / WasmModule::kPageSize;
|
||||
}
|
||||
if (!memory_object->has_instances_link()) {
|
||||
// Memory object does not have an instance associated with it, just grow
|
||||
uint32_t max_pages;
|
||||
if (memory_object->has_maximum_pages()) {
|
||||
max_pages = static_cast<uint32_t>(memory_object->maximum_pages());
|
||||
if (FLAG_wasm_max_mem_pages < max_pages) return -1;
|
||||
} else {
|
||||
max_pages = FLAG_wasm_max_mem_pages;
|
||||
}
|
||||
new_buffer = GrowMemoryBuffer(isolate, old_buffer, pages, max_pages);
|
||||
if (new_buffer.is_null()) return -1;
|
||||
} else {
|
||||
Handle<WasmInstanceWrapper> instance_wrapper(
|
||||
memory_object->instances_link());
|
||||
DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
|
||||
DCHECK(instance_wrapper->has_instance());
|
||||
Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
|
||||
DCHECK(IsWasmInstance(*instance));
|
||||
uint32_t max_pages = instance->GetMaxMemoryPages();
|
||||
|
||||
// Grow memory object buffer and update instances associated with it.
|
||||
new_buffer = GrowMemoryBuffer(isolate, old_buffer, pages, max_pages);
|
||||
if (new_buffer.is_null()) return -1;
|
||||
DCHECK(!instance_wrapper->has_previous());
|
||||
SetInstanceMemory(isolate, instance, new_buffer);
|
||||
UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
|
||||
while (instance_wrapper->has_next()) {
|
||||
instance_wrapper = instance_wrapper->next_wrapper();
|
||||
DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
|
||||
Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
|
||||
DCHECK(IsWasmInstance(*instance));
|
||||
SetInstanceMemory(isolate, instance, new_buffer);
|
||||
UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
|
||||
}
|
||||
}
|
||||
memory_object->set_buffer(*new_buffer);
|
||||
DCHECK_EQ(0, old_size % WasmModule::kPageSize);
|
||||
return old_size / WasmModule::kPageSize;
|
||||
}
|
||||
|
||||
DEFINE_OBJ_ACCESSORS(WasmInstanceObject, compiled_module, kCompiledModule,
|
||||
WasmCompiledModule)
|
||||
DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, globals_buffer,
|
||||
@ -469,6 +601,59 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
|
||||
return instance;
|
||||
}
|
||||
|
||||
int32_t WasmInstanceObject::GetMemorySize() {
|
||||
if (!has_memory_buffer()) return 0;
|
||||
uint32_t bytes = memory_buffer()->byte_length()->Number();
|
||||
DCHECK_EQ(0, bytes % WasmModule::kPageSize);
|
||||
return bytes / WasmModule::kPageSize;
|
||||
}
|
||||
|
||||
int32_t WasmInstanceObject::GrowMemory(Isolate* isolate,
|
||||
Handle<WasmInstanceObject> instance,
|
||||
uint32_t pages) {
|
||||
if (pages == 0) return instance->GetMemorySize();
|
||||
if (instance->has_memory_object()) {
|
||||
return WasmMemoryObject::Grow(
|
||||
isolate, handle(instance->memory_object(), isolate), pages);
|
||||
}
|
||||
|
||||
// No other instances to grow, grow just the one.
|
||||
uint32_t old_size = 0;
|
||||
Address old_mem_start = nullptr;
|
||||
Handle<JSArrayBuffer> old_buffer;
|
||||
if (instance->has_memory_buffer()) {
|
||||
old_buffer = handle(instance->memory_buffer(), isolate);
|
||||
old_size = old_buffer->byte_length()->Number();
|
||||
old_mem_start = static_cast<Address>(old_buffer->backing_store());
|
||||
}
|
||||
uint32_t max_pages = instance->GetMaxMemoryPages();
|
||||
Handle<JSArrayBuffer> buffer =
|
||||
GrowMemoryBuffer(isolate, old_buffer, pages, max_pages);
|
||||
if (buffer.is_null()) return -1;
|
||||
SetInstanceMemory(isolate, instance, buffer);
|
||||
UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
|
||||
DCHECK_EQ(0, old_size % WasmModule::kPageSize);
|
||||
return old_size / WasmModule::kPageSize;
|
||||
}
|
||||
|
||||
uint32_t WasmInstanceObject::GetMaxMemoryPages() {
|
||||
if (has_memory_object()) {
|
||||
if (memory_object()->has_maximum_pages()) {
|
||||
uint32_t maximum =
|
||||
static_cast<uint32_t>(memory_object()->maximum_pages());
|
||||
if (maximum < FLAG_wasm_max_mem_pages) return maximum;
|
||||
}
|
||||
}
|
||||
uint32_t compiled_max_pages = compiled_module()->max_mem_pages();
|
||||
Isolate* isolate = GetIsolate();
|
||||
auto* histogram = (compiled_module()->module()->is_wasm()
|
||||
? isolate->counters()->wasm_wasm_max_mem_pages_count()
|
||||
: isolate->counters()->wasm_asm_max_mem_pages_count());
|
||||
histogram->AddSample(compiled_max_pages);
|
||||
if (compiled_max_pages != 0) return compiled_max_pages;
|
||||
return FLAG_wasm_max_mem_pages;
|
||||
}
|
||||
|
||||
WasmInstanceObject* WasmExportedFunction::instance() {
|
||||
return WasmInstanceObject::cast(GetEmbedderField(kInstance));
|
||||
}
|
||||
|
@ -115,8 +115,7 @@ class WasmMemoryObject : public JSObject {
|
||||
Handle<JSArrayBuffer> buffer,
|
||||
int32_t maximum);
|
||||
|
||||
static bool Grow(Isolate* isolate, Handle<WasmMemoryObject> memory,
|
||||
uint32_t count);
|
||||
static int32_t Grow(Isolate*, Handle<WasmMemoryObject>, uint32_t pages);
|
||||
};
|
||||
|
||||
// Representation of a WebAssembly.Instance JavaScript-level object.
|
||||
@ -149,11 +148,16 @@ class WasmInstanceObject : public JSObject {
|
||||
|
||||
// Get the debug info associated with the given wasm object.
|
||||
// If no debug info exists yet, it is created automatically.
|
||||
static Handle<WasmDebugInfo> GetOrCreateDebugInfo(
|
||||
Handle<WasmInstanceObject> instance);
|
||||
static Handle<WasmDebugInfo> GetOrCreateDebugInfo(Handle<WasmInstanceObject>);
|
||||
|
||||
static Handle<WasmInstanceObject> New(
|
||||
Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
|
||||
static Handle<WasmInstanceObject> New(Isolate*, Handle<WasmCompiledModule>);
|
||||
|
||||
int32_t GetMemorySize();
|
||||
|
||||
static int32_t GrowMemory(Isolate*, Handle<WasmInstanceObject>,
|
||||
uint32_t pages);
|
||||
|
||||
uint32_t GetMaxMemoryPages();
|
||||
};
|
||||
|
||||
// Representation of an exported WASM function.
|
||||
|
@ -700,9 +700,7 @@ TEST(TestInterruptLoop) {
|
||||
ModuleOrigin::kWasmOrigin);
|
||||
CHECK(!instance.is_null());
|
||||
|
||||
MaybeHandle<JSArrayBuffer> maybe_memory =
|
||||
GetInstanceMemory(isolate, instance);
|
||||
Handle<JSArrayBuffer> memory = maybe_memory.ToHandleChecked();
|
||||
Handle<JSArrayBuffer> memory(instance->memory_buffer(), isolate);
|
||||
int32_t* memory_array = reinterpret_cast<int32_t*>(memory->backing_store());
|
||||
|
||||
InterruptThread thread(isolate, memory_array);
|
||||
@ -1099,9 +1097,7 @@ TEST(Run_WasmModule_Buffer_Externalized_GrowMem) {
|
||||
isolate, &thrower, buffer.begin(), buffer.end(),
|
||||
ModuleOrigin::kWasmOrigin);
|
||||
CHECK(!instance.is_null());
|
||||
MaybeHandle<JSArrayBuffer> maybe_memory =
|
||||
GetInstanceMemory(isolate, instance);
|
||||
Handle<JSArrayBuffer> memory = maybe_memory.ToHandleChecked();
|
||||
Handle<JSArrayBuffer> memory(instance->memory_buffer(), isolate);
|
||||
|
||||
// Fake the Embedder flow by creating a memory object, externalize and grow.
|
||||
Handle<WasmMemoryObject> mem_obj =
|
||||
@ -1115,7 +1111,7 @@ TEST(Run_WasmModule_Buffer_Externalized_GrowMem) {
|
||||
if (!memory->has_guard_region()) v8::Utils::ToLocal(memory)->Externalize();
|
||||
void* backing_store = memory->backing_store();
|
||||
uint64_t byte_length = NumberToSize(memory->byte_length());
|
||||
uint32_t result = GrowWebAssemblyMemory(isolate, mem_obj, 4);
|
||||
uint32_t result = WasmMemoryObject::Grow(isolate, mem_obj, 4);
|
||||
CHECK_EQ(16, result);
|
||||
if (!memory->has_guard_region()) {
|
||||
isolate->array_buffer_allocator()->Free(backing_store, byte_length);
|
||||
|
Loading…
Reference in New Issue
Block a user