Commit 5f3af52a authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm] Internalize strings used for property lookups

During the property lookup, the strings will be internalized anyway.
Doing it early will save the creation of duplicate strings by using the
internalized object right away.
This might fix the GC overhead we see for huge numbers of imports.

R=ahaas@chromium.org

Bug: chromium:1036737
Change-Id: I9c968a0652f394e977c6d061ef157037ebb0f7f9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1993289
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65691}
parent f7771e5b
...@@ -2730,7 +2730,7 @@ Handle<Script> CreateWasmScript(Isolate* isolate, ...@@ -2730,7 +2730,7 @@ Handle<Script> CreateWasmScript(Isolate* isolate,
.ToHandleChecked(); .ToHandleChecked();
Handle<String> module_name = Handle<String> module_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes( WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, wire_bytes.module_bytes(), name); isolate, wire_bytes.module_bytes(), name, kNoInternalize);
name_str = isolate->factory() name_str = isolate->factory()
->NewConsString(module_name, name_hash) ->NewConsString(module_name, name_hash)
.ToHandleChecked(); .ToHandleChecked();
......
...@@ -583,7 +583,6 @@ bool InstanceBuilder::ExecuteStartFunction() { ...@@ -583,7 +583,6 @@ bool InstanceBuilder::ExecuteStartFunction() {
// Look up an import value in the {ffi_} object. // Look up an import value in the {ffi_} object.
MaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index, MaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index,
Handle<String> module_name, Handle<String> module_name,
Handle<String> import_name) { Handle<String> import_name) {
// We pre-validated in the js-api layer that the ffi object is present, and // We pre-validated in the js-api layer that the ffi object is present, and
// a JSObject, if the module has imports. // a JSObject, if the module has imports.
...@@ -777,12 +776,12 @@ void InstanceBuilder::SanitizeImports() { ...@@ -777,12 +776,12 @@ void InstanceBuilder::SanitizeImports() {
const WasmImport& import = module_->import_table[index]; const WasmImport& import = module_->import_table[index];
Handle<String> module_name = Handle<String> module_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes, WasmModuleObject::ExtractUtf8StringFromModuleBytes(
import.module_name); isolate_, wire_bytes, import.module_name, kInternalize);
Handle<String> import_name = Handle<String> import_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes, WasmModuleObject::ExtractUtf8StringFromModuleBytes(
import.field_name); isolate_, wire_bytes, import.field_name, kInternalize);
int int_index = static_cast<int>(index); int int_index = static_cast<int>(index);
MaybeHandle<Object> result = MaybeHandle<Object> result =
...@@ -1481,7 +1480,7 @@ void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) { ...@@ -1481,7 +1480,7 @@ void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
// Process each export in the export table. // Process each export in the export table.
for (const WasmExport& exp : module_->export_table) { for (const WasmExport& exp : module_->export_table) {
Handle<String> name = WasmModuleObject::ExtractUtf8StringFromModuleBytes( Handle<String> name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate_, module_object_, exp.name); isolate_, module_object_, exp.name, kInternalize);
Handle<JSObject> export_to = exports_object; Handle<JSObject> export_to = exports_object;
switch (exp.kind) { switch (exp.kind) {
case kExternalFunction: { case kExternalFunction: {
......
...@@ -401,11 +401,11 @@ Handle<JSArray> GetImports(Isolate* isolate, ...@@ -401,11 +401,11 @@ Handle<JSArray> GetImports(Isolate* isolate,
Handle<String> import_module = Handle<String> import_module =
WasmModuleObject::ExtractUtf8StringFromModuleBytes( WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, module_object, import.module_name); isolate, module_object, import.module_name, kInternalize);
Handle<String> import_name = Handle<String> import_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes( WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, module_object, import.field_name); isolate, module_object, import.field_name, kInternalize);
JSObject::AddProperty(isolate, entry, module_string, import_module, NONE); JSObject::AddProperty(isolate, entry, module_string, import_module, NONE);
JSObject::AddProperty(isolate, entry, name_string, import_name, NONE); JSObject::AddProperty(isolate, entry, name_string, import_name, NONE);
...@@ -501,7 +501,7 @@ Handle<JSArray> GetExports(Isolate* isolate, ...@@ -501,7 +501,7 @@ Handle<JSArray> GetExports(Isolate* isolate,
Handle<String> export_name = Handle<String> export_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes( WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, module_object, exp.name); isolate, module_object, exp.name, kNoInternalize);
JSObject::AddProperty(isolate, entry, name_string, export_name, NONE); JSObject::AddProperty(isolate, entry, name_string, export_name, NONE);
JSObject::AddProperty(isolate, entry, kind_string, export_kind, NONE); JSObject::AddProperty(isolate, entry, kind_string, export_kind, NONE);
...@@ -531,7 +531,7 @@ Handle<JSArray> GetCustomSections(Isolate* isolate, ...@@ -531,7 +531,7 @@ Handle<JSArray> GetCustomSections(Isolate* isolate,
for (auto& section : custom_sections) { for (auto& section : custom_sections) {
Handle<String> section_name = Handle<String> section_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes( WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, module_object, section.name); isolate, module_object, section.name, kNoInternalize);
if (!name->Equals(*section_name)) continue; if (!name->Equals(*section_name)) continue;
...@@ -580,7 +580,7 @@ Handle<FixedArray> DecodeLocalNames(Isolate* isolate, ...@@ -580,7 +580,7 @@ Handle<FixedArray> DecodeLocalNames(Isolate* isolate,
for (LocalName& name : func.names) { for (LocalName& name : func.names) {
Handle<String> name_str = Handle<String> name_str =
WasmModuleObject::ExtractUtf8StringFromModuleBytes( WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, module_object, name.name); isolate, module_object, name.name, kNoInternalize);
func_locals_names->set(name.local_index, *name_str); func_locals_names->set(name.local_index, *name_str);
} }
} }
......
...@@ -326,22 +326,25 @@ int WasmModuleObject::GetSourcePosition(Handle<WasmModuleObject> module_object, ...@@ -326,22 +326,25 @@ int WasmModuleObject::GetSourcePosition(Handle<WasmModuleObject> module_object,
Handle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes( Handle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes(
Isolate* isolate, Handle<WasmModuleObject> module_object, Isolate* isolate, Handle<WasmModuleObject> module_object,
wasm::WireBytesRef ref) { wasm::WireBytesRef ref, InternalizeString internalize) {
// TODO(wasm): cache strings from modules if it's a performance win.
Vector<const uint8_t> wire_bytes = Vector<const uint8_t> wire_bytes =
module_object->native_module()->wire_bytes(); module_object->native_module()->wire_bytes();
return ExtractUtf8StringFromModuleBytes(isolate, wire_bytes, ref); return ExtractUtf8StringFromModuleBytes(isolate, wire_bytes, ref,
internalize);
} }
Handle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes( Handle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes(
Isolate* isolate, Vector<const uint8_t> wire_bytes, Isolate* isolate, Vector<const uint8_t> wire_bytes, wasm::WireBytesRef ref,
wasm::WireBytesRef ref) { InternalizeString internalize) {
Vector<const uint8_t> name_vec = Vector<const uint8_t> name_vec =
wire_bytes.SubVector(ref.offset(), ref.end_offset()); wire_bytes.SubVector(ref.offset(), ref.end_offset());
// UTF8 validation happens at decode time. // UTF8 validation happens at decode time.
DCHECK(unibrow::Utf8::ValidateEncoding(name_vec.begin(), name_vec.length())); DCHECK(unibrow::Utf8::ValidateEncoding(name_vec.begin(), name_vec.length()));
return isolate->factory() auto* factory = isolate->factory();
->NewStringFromUtf8(Vector<const char>::cast(name_vec)) return internalize
? factory->InternalizeUtf8String(
Vector<const char>::cast(name_vec))
: factory->NewStringFromUtf8(Vector<const char>::cast(name_vec))
.ToHandleChecked(); .ToHandleChecked();
} }
...@@ -349,7 +352,8 @@ MaybeHandle<String> WasmModuleObject::GetModuleNameOrNull( ...@@ -349,7 +352,8 @@ MaybeHandle<String> WasmModuleObject::GetModuleNameOrNull(
Isolate* isolate, Handle<WasmModuleObject> module_object) { Isolate* isolate, Handle<WasmModuleObject> module_object) {
const WasmModule* module = module_object->module(); const WasmModule* module = module_object->module();
if (!module->name.is_set()) return {}; if (!module->name.is_set()) return {};
return ExtractUtf8StringFromModuleBytes(isolate, module_object, module->name); return ExtractUtf8StringFromModuleBytes(isolate, module_object, module->name,
kNoInternalize);
} }
MaybeHandle<String> WasmModuleObject::GetFunctionNameOrNull( MaybeHandle<String> WasmModuleObject::GetFunctionNameOrNull(
...@@ -360,7 +364,8 @@ MaybeHandle<String> WasmModuleObject::GetFunctionNameOrNull( ...@@ -360,7 +364,8 @@ MaybeHandle<String> WasmModuleObject::GetFunctionNameOrNull(
wasm::ModuleWireBytes(module_object->native_module()->wire_bytes()), wasm::ModuleWireBytes(module_object->native_module()->wire_bytes()),
func_index); func_index);
if (!name.is_set()) return {}; if (!name.is_set()) return {};
return ExtractUtf8StringFromModuleBytes(isolate, module_object, name); return ExtractUtf8StringFromModuleBytes(isolate, module_object, name,
kNoInternalize);
} }
Handle<String> WasmModuleObject::GetFunctionName( Handle<String> WasmModuleObject::GetFunctionName(
......
...@@ -120,6 +120,8 @@ class ImportedFunctionEntry { ...@@ -120,6 +120,8 @@ class ImportedFunctionEntry {
int const index_; int const index_;
}; };
enum InternalizeString : bool { kInternalize = true, kNoInternalize = false };
// Representation of a WebAssembly.Module JavaScript-level object. // Representation of a WebAssembly.Module JavaScript-level object.
class WasmModuleObject : public JSObject { class WasmModuleObject : public JSObject {
public: public:
...@@ -186,11 +188,15 @@ class WasmModuleObject : public JSObject { ...@@ -186,11 +188,15 @@ class WasmModuleObject : public JSObject {
uint32_t byte_offset, uint32_t byte_offset,
bool is_at_number_conversion); bool is_at_number_conversion);
// Extract a portion of the wire bytes as UTF-8 string. // Extract a portion of the wire bytes as UTF-8 string, optionally
// internalized. (Prefer to internalize early if the string will be used for a
// property lookup anyway.)
static Handle<String> ExtractUtf8StringFromModuleBytes( static Handle<String> ExtractUtf8StringFromModuleBytes(
Isolate*, Handle<WasmModuleObject>, wasm::WireBytesRef); Isolate*, Handle<WasmModuleObject>, wasm::WireBytesRef,
InternalizeString);
static Handle<String> ExtractUtf8StringFromModuleBytes( static Handle<String> ExtractUtf8StringFromModuleBytes(
Isolate*, Vector<const uint8_t> wire_byte, wasm::WireBytesRef); Isolate*, Vector<const uint8_t> wire_byte, wasm::WireBytesRef,
InternalizeString);
OBJECT_CONSTRUCTORS(WasmModuleObject, JSObject); OBJECT_CONSTRUCTORS(WasmModuleObject, JSObject);
}; };
......
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