LibWeb/WebAssembly: Avoid scanning all externs when resolving references

This was very hot on a profile of ruffle.
This commit is contained in:
Ali Mohammad Pur 2025-08-03 19:33:03 +02:00 committed by Ali Mohammad Pur
commit 1ef536194d
Notes: github-actions[bot] 2025-08-08 10:55:41 +00:00
2 changed files with 11 additions and 5 deletions

View file

@ -560,10 +560,8 @@ JS::ThrowCompletionOr<Wasm::Value> to_webassembly_value(JS::VM& vm, JS::Value va
if (value.is_null())
return Wasm::Value(Wasm::ValueType { Wasm::ValueType::Kind::ExternReference });
auto& cache = get_cache(*vm.current_realm());
for (auto& entry : cache.extern_values()) {
if (entry.value == value)
return Wasm::Value { Wasm::Reference { Wasm::Reference::Extern { entry.key } } };
}
if (auto entry = cache.inverse_extern_values().get(value); entry.has_value())
return Wasm::Value { Wasm::Reference { Wasm::Reference::Extern { *entry } } };
Wasm::ExternAddress extern_addr = cache.extern_values().size();
cache.add_extern_value(extern_addr, value);
return Wasm::Value { Wasm::Reference { Wasm::Reference::Extern { extern_addr } } };

View file

@ -47,7 +47,13 @@ public:
void add_compiled_module(NonnullRefPtr<CompiledWebAssemblyModule> module) { m_compiled_modules.append(module); }
void add_function_instance(Wasm::FunctionAddress address, GC::Ptr<JS::NativeFunction> function) { m_function_instances.set(address, function); }
void add_imported_object(GC::Ptr<JS::Object> object) { m_imported_objects.set(object); }
void add_extern_value(Wasm::ExternAddress address, JS::Value value) { m_extern_values.set(address, value); }
void add_extern_value(Wasm::ExternAddress address, JS::Value value)
{
if (auto entry = m_extern_values.get(address); entry.has_value())
m_inverse_extern_values.remove(entry.value());
m_extern_values.set(address, value);
m_inverse_extern_values.set(value, address);
}
void add_global_instance(Wasm::GlobalAddress address, GC::Ptr<WebAssembly::Global> global) { m_global_instances.set(address, global); }
Optional<GC::Ptr<JS::NativeFunction>> get_function_instance(Wasm::FunctionAddress address) { return m_function_instances.get(address); }
@ -56,6 +62,7 @@ public:
HashMap<Wasm::FunctionAddress, GC::Ptr<JS::NativeFunction>> function_instances() const { return m_function_instances; }
HashMap<Wasm::ExternAddress, JS::Value> extern_values() const { return m_extern_values; }
HashMap<JS::Value, Wasm::ExternAddress> inverse_extern_values() const { return m_inverse_extern_values; }
HashMap<Wasm::GlobalAddress, GC::Ptr<WebAssembly::Global>> global_instances() const { return m_global_instances; }
HashTable<GC::Ptr<JS::Object>> imported_objects() const { return m_imported_objects; }
Wasm::AbstractMachine& abstract_machine() { return m_abstract_machine; }
@ -63,6 +70,7 @@ public:
private:
HashMap<Wasm::FunctionAddress, GC::Ptr<JS::NativeFunction>> m_function_instances;
HashMap<Wasm::ExternAddress, JS::Value> m_extern_values;
HashMap<JS::Value, Wasm::ExternAddress> m_inverse_extern_values;
HashMap<Wasm::GlobalAddress, GC::Ptr<WebAssembly::Global>> m_global_instances;
Vector<NonnullRefPtr<CompiledWebAssemblyModule>> m_compiled_modules;
HashTable<GC::Ptr<JS::Object>> m_imported_objects;