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,
.ToHandleChecked();
Handle<String> module_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, wire_bytes.module_bytes(), name);
isolate, wire_bytes.module_bytes(), name, kNoInternalize);
name_str = isolate->factory()
->NewConsString(module_name, name_hash)
.ToHandleChecked();
......
......@@ -583,7 +583,6 @@ bool InstanceBuilder::ExecuteStartFunction() {
// Look up an import value in the {ffi_} object.
MaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index,
Handle<String> module_name,
Handle<String> import_name) {
// We pre-validated in the js-api layer that the ffi object is present, and
// a JSObject, if the module has imports.
......@@ -777,12 +776,12 @@ void InstanceBuilder::SanitizeImports() {
const WasmImport& import = module_->import_table[index];
Handle<String> module_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
import.module_name);
WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate_, wire_bytes, import.module_name, kInternalize);
Handle<String> import_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
import.field_name);
WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate_, wire_bytes, import.field_name, kInternalize);
int int_index = static_cast<int>(index);
MaybeHandle<Object> result =
......@@ -1481,7 +1480,7 @@ void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
// Process each export in the export table.
for (const WasmExport& exp : module_->export_table) {
Handle<String> name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate_, module_object_, exp.name);
isolate_, module_object_, exp.name, kInternalize);
Handle<JSObject> export_to = exports_object;
switch (exp.kind) {
case kExternalFunction: {
......
......@@ -401,11 +401,11 @@ Handle<JSArray> GetImports(Isolate* isolate,
Handle<String> import_module =
WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, module_object, import.module_name);
isolate, module_object, import.module_name, kInternalize);
Handle<String> import_name =
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, name_string, import_name, NONE);
......@@ -501,7 +501,7 @@ Handle<JSArray> GetExports(Isolate* isolate,
Handle<String> export_name =
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, kind_string, export_kind, NONE);
......@@ -531,7 +531,7 @@ Handle<JSArray> GetCustomSections(Isolate* isolate,
for (auto& section : custom_sections) {
Handle<String> section_name =
WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, module_object, section.name);
isolate, module_object, section.name, kNoInternalize);
if (!name->Equals(*section_name)) continue;
......@@ -580,7 +580,7 @@ Handle<FixedArray> DecodeLocalNames(Isolate* isolate,
for (LocalName& name : func.names) {
Handle<String> name_str =
WasmModuleObject::ExtractUtf8StringFromModuleBytes(
isolate, module_object, name.name);
isolate, module_object, name.name, kNoInternalize);
func_locals_names->set(name.local_index, *name_str);
}
}
......
......@@ -326,30 +326,34 @@ int WasmModuleObject::GetSourcePosition(Handle<WasmModuleObject> module_object,
Handle<String> WasmModuleObject::ExtractUtf8StringFromModuleBytes(
Isolate* isolate, Handle<WasmModuleObject> module_object,
wasm::WireBytesRef ref) {
// TODO(wasm): cache strings from modules if it's a performance win.
wasm::WireBytesRef ref, InternalizeString internalize) {
Vector<const uint8_t> 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(
Isolate* isolate, Vector<const uint8_t> wire_bytes,
wasm::WireBytesRef ref) {
Isolate* isolate, Vector<const uint8_t> wire_bytes, wasm::WireBytesRef ref,
InternalizeString internalize) {
Vector<const uint8_t> name_vec =
wire_bytes.SubVector(ref.offset(), ref.end_offset());
// UTF8 validation happens at decode time.
DCHECK(unibrow::Utf8::ValidateEncoding(name_vec.begin(), name_vec.length()));
return isolate->factory()
->NewStringFromUtf8(Vector<const char>::cast(name_vec))
.ToHandleChecked();
auto* factory = isolate->factory();
return internalize
? factory->InternalizeUtf8String(
Vector<const char>::cast(name_vec))
: factory->NewStringFromUtf8(Vector<const char>::cast(name_vec))
.ToHandleChecked();
}
MaybeHandle<String> WasmModuleObject::GetModuleNameOrNull(
Isolate* isolate, Handle<WasmModuleObject> module_object) {
const WasmModule* module = module_object->module();
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(
......@@ -360,7 +364,8 @@ MaybeHandle<String> WasmModuleObject::GetFunctionNameOrNull(
wasm::ModuleWireBytes(module_object->native_module()->wire_bytes()),
func_index);
if (!name.is_set()) return {};
return ExtractUtf8StringFromModuleBytes(isolate, module_object, name);
return ExtractUtf8StringFromModuleBytes(isolate, module_object, name,
kNoInternalize);
}
Handle<String> WasmModuleObject::GetFunctionName(
......
......@@ -120,6 +120,8 @@ class ImportedFunctionEntry {
int const index_;
};
enum InternalizeString : bool { kInternalize = true, kNoInternalize = false };
// Representation of a WebAssembly.Module JavaScript-level object.
class WasmModuleObject : public JSObject {
public:
......@@ -186,11 +188,15 @@ class WasmModuleObject : public JSObject {
uint32_t byte_offset,
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(
Isolate*, Handle<WasmModuleObject>, wasm::WireBytesRef);
Isolate*, Handle<WasmModuleObject>, wasm::WireBytesRef,
InternalizeString);
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);
};
......
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