Commit cd7539e1 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Fix memory estimates for NativeModule

1) For the code space estimate, exclude everything except code.
2) Add some static code size per function.
3) Add some static code size per module.
4) Include signature zone memory.

R=mstarzinger@chromium.org

Change-Id: Ifa9ac347edf98c2e63ab3201a64ac2e0a3de28e5
Reviewed-on: https://chromium-review.googlesource.com/c/1118263Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57436}
parent 3b64603d
......@@ -931,27 +931,39 @@ void WasmCodeManager::InstallSamplingGCCallback(Isolate* isolate) {
}
// static
size_t WasmCodeManager::EstimateNativeModuleSize(const WasmModule* module) {
size_t WasmCodeManager::EstimateNativeModuleCodeSize(const WasmModule* module) {
constexpr size_t kCodeSizeMultiplier = 4;
constexpr size_t kImportSize = 32 * kPointerSize;
uint32_t num_wasm_functions = module->num_declared_functions;
size_t estimate =
AllocatePageSize() /* TODO(titzer): 1 page spot bonus */ +
sizeof(NativeModule) +
(sizeof(WasmCode*) * num_wasm_functions /* code table size */) +
(sizeof(WasmCode) * num_wasm_functions /* code object size */) +
(kImportSize * module->num_imported_functions /* import size */) +
(JumpTableAssembler::SizeForNumberOfSlots(num_wasm_functions));
constexpr size_t kCodeOverhead = 32; // for prologue, stack check, ...
constexpr size_t kStaticCodeSize = 512; // runtime stubs, ...
constexpr size_t kImportSize = 64 * kPointerSize;
size_t estimate = kStaticCodeSize;
for (auto& function : module->functions) {
estimate += kCodeSizeMultiplier * function.code.length();
estimate += kCodeOverhead + kCodeSizeMultiplier * function.code.length();
}
estimate +=
JumpTableAssembler::SizeForNumberOfSlots(module->num_declared_functions);
estimate += kImportSize * module->num_imported_functions;
return estimate;
}
// static
size_t WasmCodeManager::EstimateNativeModuleNonCodeSize(
const WasmModule* module) {
size_t wasm_module_estimate = EstimateStoredSize(module);
uint32_t num_wasm_functions = module->num_declared_functions;
// TODO(wasm): Include wire bytes size.
size_t native_module_estimate =
sizeof(NativeModule) + /* NativeModule struct */
(sizeof(WasmCode*) * num_wasm_functions) + /* code table size */
(sizeof(WasmCode) * num_wasm_functions); /* code object size */
return wasm_module_estimate + native_module_estimate;
}
bool WasmCodeManager::ShouldForceCriticalMemoryPressureNotification() {
base::MutexGuard lock(&native_modules_mutex_);
// TODO(titzer): we force a critical memory pressure notification
......
......@@ -330,6 +330,7 @@ class V8_EXPORT_PRIVATE NativeModule final {
bool lazy_compile_frozen() const { return lazy_compile_frozen_; }
Vector<const byte> wire_bytes() const { return wire_bytes_.as_vector(); }
const WasmModule* module() const { return module_.get(); }
size_t committed_code_space() const { return committed_code_space_.load(); }
void SetWireBytes(OwnedVector<const byte> wire_bytes);
......@@ -492,7 +493,8 @@ class V8_EXPORT_PRIVATE WasmCodeManager final {
// using sampling based on regular intervals independent of the GC.
static void InstallSamplingGCCallback(Isolate* isolate);
static size_t EstimateNativeModuleSize(const WasmModule* module);
static size_t EstimateNativeModuleCodeSize(const WasmModule* module);
static size_t EstimateNativeModuleNonCodeSize(const WasmModule* module);
private:
friend class NativeModule;
......
......@@ -191,8 +191,9 @@ Handle<WasmModuleObject> WasmEngine::ImportNativeModule(
const WasmModule* module = shared_module->module();
Handle<Script> script =
CreateWasmScript(isolate, wire_bytes, module->source_map_url);
Handle<WasmModuleObject> module_object =
WasmModuleObject::New(isolate, std::move(shared_module), script);
size_t code_size = shared_module->committed_code_space();
Handle<WasmModuleObject> module_object = WasmModuleObject::New(
isolate, std::move(shared_module), script, code_size);
// TODO(6792): Wrappers below might be cloned using {Factory::CopyCode}.
// This requires unlocking the code space here. This should eventually be
......
......@@ -74,8 +74,8 @@ std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name) {
return os;
}
WasmModule::WasmModule(std::unique_ptr<Zone> owned)
: signature_zone(std::move(owned)) {}
WasmModule::WasmModule(std::unique_ptr<Zone> signature_zone)
: signature_zone(std::move(signature_zone)) {}
bool IsWasmCodegenAllowed(Isolate* isolate, Handle<Context> context) {
// TODO(wasm): Once wasm has its own CSP policy, we should introduce a
......@@ -312,15 +312,15 @@ inline size_t VectorSize(const std::vector<T>& vector) {
}
} // namespace
size_t EstimateWasmModuleSize(const WasmModule* module) {
size_t estimate =
sizeof(WasmModule) + VectorSize(module->signatures) +
VectorSize(module->signature_ids) + VectorSize(module->functions) +
VectorSize(module->data_segments) + VectorSize(module->tables) +
VectorSize(module->import_table) + VectorSize(module->export_table) +
VectorSize(module->exceptions) + VectorSize(module->table_inits);
// TODO(wasm): include names table and wire bytes in size estimate
return estimate;
size_t EstimateStoredSize(const WasmModule* module) {
return sizeof(WasmModule) + VectorSize(module->globals) +
(module->signature_zone ? module->signature_zone->allocation_size()
: 0) +
VectorSize(module->signatures) + VectorSize(module->signature_ids) +
VectorSize(module->functions) + VectorSize(module->data_segments) +
VectorSize(module->tables) + VectorSize(module->import_table) +
VectorSize(module->export_table) + VectorSize(module->exceptions) +
VectorSize(module->table_inits);
}
} // namespace wasm
} // namespace internal
......
......@@ -174,14 +174,14 @@ struct V8_EXPORT_PRIVATE WasmModule {
function_names;
std::string source_map_url;
explicit WasmModule(std::unique_ptr<Zone> owned = nullptr);
explicit WasmModule(std::unique_ptr<Zone> signature_zone = nullptr);
WireBytesRef LookupFunctionName(const ModuleWireBytes& wire_bytes,
uint32_t function_index) const;
void AddFunctionNameForTesting(int function_index, WireBytesRef name);
};
size_t EstimateWasmModuleSize(const WasmModule* module);
size_t EstimateStoredSize(const WasmModule* module);
// Interface to the storage (wire bytes) of a wasm module.
// It is illegal for anyone receiving a ModuleWireBytes to store pointers based
......
......@@ -179,18 +179,17 @@ Handle<WasmModuleObject> WasmModuleObject::New(
OwnedVector<const uint8_t> wire_bytes, Handle<Script> script,
Handle<ByteArray> asm_js_offset_table) {
// Create a new {NativeModule} first.
size_t native_memory_estimate =
isolate->wasm_engine()->code_manager()->EstimateNativeModuleSize(
shared_module.get());
size_t code_size_estimate =
wasm::WasmCodeManager::EstimateNativeModuleCodeSize(shared_module.get());
auto native_module = isolate->wasm_engine()->code_manager()->NewNativeModule(
isolate, enabled, native_memory_estimate,
isolate, enabled, code_size_estimate,
wasm::NativeModule::kCanAllocateMoreMemory, std::move(shared_module));
native_module->SetWireBytes(std::move(wire_bytes));
native_module->SetRuntimeStubs(isolate);
// Delegate to the shared {WasmModuleObject::New} allocator.
Handle<WasmModuleObject> module_object =
New(isolate, std::move(native_module), script);
New(isolate, std::move(native_module), script, code_size_estimate);
if (!asm_js_offset_table.is_null()) {
module_object->set_asm_js_offset_table(*asm_js_offset_table);
}
......@@ -200,19 +199,17 @@ Handle<WasmModuleObject> WasmModuleObject::New(
// static
Handle<WasmModuleObject> WasmModuleObject::New(
Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
Handle<Script> script) {
int export_wrapper_size =
static_cast<int>(native_module->module()->num_exported_functions);
Handle<Script> script, size_t code_size_estimate) {
const WasmModule* module = native_module->module();
int export_wrapper_size = static_cast<int>(module->num_exported_functions);
Handle<FixedArray> export_wrappers =
isolate->factory()->NewFixedArray(export_wrapper_size, TENURED);
// Use the given shared {NativeModule}, but increase its reference count by
// allocating a new {Managed<T>} that the {WasmModuleObject} references.
size_t native_memory_estimate =
isolate->wasm_engine()->code_manager()->EstimateNativeModuleSize(
native_module->module());
size_t memory_estimate =
EstimateWasmModuleSize(native_module->module()) + native_memory_estimate;
code_size_estimate +
wasm::WasmCodeManager::EstimateNativeModuleNonCodeSize(module);
Handle<Managed<wasm::NativeModule>> managed_native_module =
Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
std::move(native_module));
......
......@@ -145,7 +145,7 @@ class WasmModuleObject : public JSObject {
// reference counted and might be shared between multiple Isolates.
static Handle<WasmModuleObject> New(
Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
Handle<Script> script);
Handle<Script> script, size_t code_size_estimate);
// Set a breakpoint on the given byte position inside the given module.
// This will affect all live and future instances of the module.
......
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