mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-24 09:52:31 +00:00
LibWasm: Remove Module::functions
`Module::functions` created clones of all of the functions in the module. It provided a _slightly_ better API, but ended up costing around 40ms when instantiating spidermonkey.
This commit is contained in:
parent
2d95cc01dc
commit
dc52998341
Notes:
github-actions[bot]
2024-07-28 00:57:26 +00:00
Author: https://github.com/dzfrias
Commit: dc52998341
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/874
Reviewed-by: https://github.com/alimpfard ✅
8 changed files with 36 additions and 111 deletions
|
@ -14,14 +14,14 @@
|
|||
|
||||
namespace Wasm {
|
||||
|
||||
Optional<FunctionAddress> Store::allocate(ModuleInstance& module, Module::Function const& function)
|
||||
Optional<FunctionAddress> Store::allocate(ModuleInstance& module, CodeSection::Code const& code, TypeIndex type_index)
|
||||
{
|
||||
FunctionAddress address { m_functions.size() };
|
||||
if (function.type().value() > module.types().size())
|
||||
if (type_index.value() > module.types().size())
|
||||
return {};
|
||||
|
||||
auto& type = module.types()[function.type().value()];
|
||||
m_functions.empend(WasmFunction { type, module, function });
|
||||
auto& type = module.types()[type_index.value()];
|
||||
m_functions.empend(WasmFunction { type, module, code });
|
||||
return address;
|
||||
}
|
||||
|
||||
|
@ -223,15 +223,24 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
|
|||
auxiliary_instance.functions().append(*ptr);
|
||||
}
|
||||
|
||||
Vector<FunctionAddress> module_functions;
|
||||
module_functions.ensure_capacity(module.functions().size());
|
||||
FunctionSection const* function_section { nullptr };
|
||||
module.for_each_section_of_type<FunctionSection>([&](FunctionSection const& section) { function_section = §ion; });
|
||||
|
||||
for (auto& func : module.functions()) {
|
||||
auto address = m_store.allocate(main_module_instance, func);
|
||||
Vector<FunctionAddress> module_functions;
|
||||
if (function_section)
|
||||
module_functions.ensure_capacity(function_section->types().size());
|
||||
|
||||
module.for_each_section_of_type<CodeSection>([&](auto& code_section) {
|
||||
size_t i = 0;
|
||||
for (auto& code : code_section.functions()) {
|
||||
auto type_index = function_section->types()[i];
|
||||
auto address = m_store.allocate(main_module_instance, code, type_index);
|
||||
VERIFY(address.has_value());
|
||||
auxiliary_instance.functions().append(*address);
|
||||
module_functions.append(*address);
|
||||
++i;
|
||||
}
|
||||
});
|
||||
|
||||
BytecodeInterpreter interpreter(m_stack_info);
|
||||
|
||||
|
|
|
@ -329,7 +329,7 @@ private:
|
|||
|
||||
class WasmFunction {
|
||||
public:
|
||||
explicit WasmFunction(FunctionType const& type, ModuleInstance const& module, Module::Function const& code)
|
||||
explicit WasmFunction(FunctionType const& type, ModuleInstance const& module, CodeSection::Code const& code)
|
||||
: m_type(type)
|
||||
, m_module(module)
|
||||
, m_code(code)
|
||||
|
@ -343,7 +343,7 @@ public:
|
|||
private:
|
||||
FunctionType m_type;
|
||||
ModuleInstance const& m_module;
|
||||
Module::Function const& m_code;
|
||||
CodeSection::Code const& m_code;
|
||||
};
|
||||
|
||||
class HostFunction {
|
||||
|
@ -537,7 +537,7 @@ class Store {
|
|||
public:
|
||||
Store() = default;
|
||||
|
||||
Optional<FunctionAddress> allocate(ModuleInstance& module, Module::Function const& function);
|
||||
Optional<FunctionAddress> allocate(ModuleInstance&, CodeSection::Code const&, TypeIndex);
|
||||
Optional<FunctionAddress> allocate(HostFunction&&);
|
||||
Optional<TableAddress> allocate(TableType const&);
|
||||
Optional<MemoryAddress> allocate(MemoryType const&);
|
||||
|
|
|
@ -44,14 +44,16 @@ Result Configuration::call(Interpreter& interpreter, FunctionAddress address, Ve
|
|||
return Trap {};
|
||||
if (auto* wasm_function = function->get_pointer<WasmFunction>()) {
|
||||
Vector<Value> locals = move(arguments);
|
||||
locals.ensure_capacity(locals.size() + wasm_function->code().locals().size());
|
||||
for (auto& type : wasm_function->code().locals())
|
||||
locals.empend(type, 0ull);
|
||||
locals.ensure_capacity(locals.size() + wasm_function->code().func().locals().size());
|
||||
for (auto& local : wasm_function->code().func().locals()) {
|
||||
for (size_t i = 0; i < local.n(); ++i)
|
||||
locals.empend(local.type(), 0ull);
|
||||
}
|
||||
|
||||
set_frame(Frame {
|
||||
wasm_function->module(),
|
||||
move(locals),
|
||||
wasm_function->code().body(),
|
||||
wasm_function->code().func().body(),
|
||||
wasm_function->type().results().size(),
|
||||
});
|
||||
m_ip = 0;
|
||||
|
|
|
@ -74,9 +74,13 @@ ErrorOr<void, ValidationError> Validator::validate(Module& module)
|
|||
return result;
|
||||
}
|
||||
|
||||
module.for_each_section_of_type<FunctionSection>([this, &result](FunctionSection const& section) {
|
||||
if (result.is_error())
|
||||
CodeSection const* code_section { nullptr };
|
||||
module.for_each_section_of_type<CodeSection>([&](auto& section) { code_section = §ion; });
|
||||
module.for_each_section_of_type<FunctionSection>([&](FunctionSection const& section) {
|
||||
if ((!code_section && !section.types().is_empty()) || (code_section && code_section->functions().size() != section.types().size())) {
|
||||
result = Errors::invalid("FunctionSection"sv);
|
||||
return;
|
||||
}
|
||||
m_context.functions.ensure_capacity(section.types().size() + m_context.functions.size());
|
||||
for (auto& index : section.types()) {
|
||||
if (m_context.types.size() > index.value()) {
|
||||
|
|
|
@ -1403,42 +1403,6 @@ ParseResult<Module> Module::parse(Stream& stream)
|
|||
return Module { move(sections) };
|
||||
}
|
||||
|
||||
bool Module::populate_sections()
|
||||
{
|
||||
auto is_ok = true;
|
||||
FunctionSection const* function_section { nullptr };
|
||||
bool seen_code_section = false;
|
||||
for_each_section_of_type<FunctionSection>([&](FunctionSection const& section) { function_section = §ion; });
|
||||
for_each_section_of_type<CodeSection>([&](CodeSection const& section) {
|
||||
if (!function_section && section.functions().is_empty()) {
|
||||
return;
|
||||
}
|
||||
if (!function_section || function_section->types().size() != section.functions().size()) {
|
||||
is_ok = false;
|
||||
return;
|
||||
}
|
||||
seen_code_section = true;
|
||||
size_t index = 0;
|
||||
for (auto& entry : section.functions()) {
|
||||
if (function_section->types().size() <= index) {
|
||||
is_ok = false;
|
||||
return;
|
||||
}
|
||||
auto& type_index = function_section->types()[index];
|
||||
Vector<ValueType> locals;
|
||||
for (auto& local : entry.func().locals()) {
|
||||
for (size_t i = 0; i < local.n(); ++i)
|
||||
locals.append(local.type());
|
||||
}
|
||||
m_functions.empend(type_index, move(locals), entry.func().body());
|
||||
++index;
|
||||
}
|
||||
});
|
||||
if (!seen_code_section && function_section && !function_section->types().is_empty())
|
||||
return false;
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
ByteString parse_error_to_byte_string(ParseError error)
|
||||
{
|
||||
switch (error) {
|
||||
|
|
|
@ -541,33 +541,6 @@ void Printer::print(Wasm::Module const& module)
|
|||
print(")\n");
|
||||
}
|
||||
|
||||
void Printer::print(Wasm::Module::Function const& func)
|
||||
{
|
||||
print_indent();
|
||||
print("(function\n");
|
||||
{
|
||||
TemporaryChange change { m_indent, m_indent + 1 };
|
||||
{
|
||||
print_indent();
|
||||
print("(locals\n");
|
||||
{
|
||||
TemporaryChange change { m_indent, m_indent + 1 };
|
||||
for (auto& locals : func.locals())
|
||||
print(locals);
|
||||
}
|
||||
print_indent();
|
||||
print(")\n");
|
||||
}
|
||||
print_indent();
|
||||
print("(body\n");
|
||||
print(func.body());
|
||||
print_indent();
|
||||
print(")\n");
|
||||
}
|
||||
print_indent();
|
||||
print(")\n");
|
||||
}
|
||||
|
||||
void Printer::print(Wasm::StartSection const& section)
|
||||
{
|
||||
print_indent();
|
||||
|
|
|
@ -50,7 +50,6 @@ struct Printer {
|
|||
void print(Wasm::MemorySection::Memory const&);
|
||||
void print(Wasm::MemoryType const&);
|
||||
void print(Wasm::Module const&);
|
||||
void print(Wasm::Module::Function const&);
|
||||
void print(Wasm::Reference const&);
|
||||
void print(Wasm::StartSection const&);
|
||||
void print(Wasm::StartSection::StartFunction const&);
|
||||
|
|
|
@ -961,25 +961,6 @@ public:
|
|||
Valid,
|
||||
};
|
||||
|
||||
class Function {
|
||||
public:
|
||||
explicit Function(TypeIndex type, Vector<ValueType> local_types, Expression body)
|
||||
: m_type(type)
|
||||
, m_local_types(move(local_types))
|
||||
, m_body(move(body))
|
||||
{
|
||||
}
|
||||
|
||||
auto& type() const { return m_type; }
|
||||
auto& locals() const { return m_local_types; }
|
||||
auto& body() const { return m_body; }
|
||||
|
||||
private:
|
||||
TypeIndex m_type;
|
||||
Vector<ValueType> m_local_types;
|
||||
Expression m_body;
|
||||
};
|
||||
|
||||
using AnySection = Variant<
|
||||
CustomSection,
|
||||
TypeSection,
|
||||
|
@ -1001,14 +982,9 @@ public:
|
|||
explicit Module(Vector<AnySection> sections)
|
||||
: m_sections(move(sections))
|
||||
{
|
||||
if (!populate_sections()) {
|
||||
m_validation_status = ValidationStatus::Invalid;
|
||||
m_validation_error = "Failed to populate module sections"sv;
|
||||
}
|
||||
}
|
||||
|
||||
auto& sections() const { return m_sections; }
|
||||
auto& functions() const { return m_functions; }
|
||||
auto& type(TypeIndex index) const
|
||||
{
|
||||
FunctionType const* type = nullptr;
|
||||
|
@ -1045,11 +1021,9 @@ public:
|
|||
static ParseResult<Module> parse(Stream& stream);
|
||||
|
||||
private:
|
||||
bool populate_sections();
|
||||
void set_validation_status(ValidationStatus status) { m_validation_status = status; }
|
||||
|
||||
Vector<AnySection> m_sections;
|
||||
Vector<Function> m_functions;
|
||||
ValidationStatus m_validation_status { ValidationStatus::Unchecked };
|
||||
Optional<ByteString> m_validation_error;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue