mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-23 09:22:30 +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 {
|
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() };
|
FunctionAddress address { m_functions.size() };
|
||||||
if (function.type().value() > module.types().size())
|
if (type_index.value() > module.types().size())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto& type = module.types()[function.type().value()];
|
auto& type = module.types()[type_index.value()];
|
||||||
m_functions.empend(WasmFunction { type, module, function });
|
m_functions.empend(WasmFunction { type, module, code });
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,15 +223,24 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
|
||||||
auxiliary_instance.functions().append(*ptr);
|
auxiliary_instance.functions().append(*ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<FunctionAddress> module_functions;
|
FunctionSection const* function_section { nullptr };
|
||||||
module_functions.ensure_capacity(module.functions().size());
|
module.for_each_section_of_type<FunctionSection>([&](FunctionSection const& section) { function_section = §ion; });
|
||||||
|
|
||||||
for (auto& func : module.functions()) {
|
Vector<FunctionAddress> module_functions;
|
||||||
auto address = m_store.allocate(main_module_instance, func);
|
if (function_section)
|
||||||
VERIFY(address.has_value());
|
module_functions.ensure_capacity(function_section->types().size());
|
||||||
auxiliary_instance.functions().append(*address);
|
|
||||||
module_functions.append(*address);
|
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);
|
BytecodeInterpreter interpreter(m_stack_info);
|
||||||
|
|
||||||
|
|
|
@ -329,7 +329,7 @@ private:
|
||||||
|
|
||||||
class WasmFunction {
|
class WasmFunction {
|
||||||
public:
|
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_type(type)
|
||||||
, m_module(module)
|
, m_module(module)
|
||||||
, m_code(code)
|
, m_code(code)
|
||||||
|
@ -343,7 +343,7 @@ public:
|
||||||
private:
|
private:
|
||||||
FunctionType m_type;
|
FunctionType m_type;
|
||||||
ModuleInstance const& m_module;
|
ModuleInstance const& m_module;
|
||||||
Module::Function const& m_code;
|
CodeSection::Code const& m_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
class HostFunction {
|
class HostFunction {
|
||||||
|
@ -537,7 +537,7 @@ class Store {
|
||||||
public:
|
public:
|
||||||
Store() = default;
|
Store() = default;
|
||||||
|
|
||||||
Optional<FunctionAddress> allocate(ModuleInstance& module, Module::Function const& function);
|
Optional<FunctionAddress> allocate(ModuleInstance&, CodeSection::Code const&, TypeIndex);
|
||||||
Optional<FunctionAddress> allocate(HostFunction&&);
|
Optional<FunctionAddress> allocate(HostFunction&&);
|
||||||
Optional<TableAddress> allocate(TableType const&);
|
Optional<TableAddress> allocate(TableType const&);
|
||||||
Optional<MemoryAddress> allocate(MemoryType const&);
|
Optional<MemoryAddress> allocate(MemoryType const&);
|
||||||
|
|
|
@ -44,14 +44,16 @@ Result Configuration::call(Interpreter& interpreter, FunctionAddress address, Ve
|
||||||
return Trap {};
|
return Trap {};
|
||||||
if (auto* wasm_function = function->get_pointer<WasmFunction>()) {
|
if (auto* wasm_function = function->get_pointer<WasmFunction>()) {
|
||||||
Vector<Value> locals = move(arguments);
|
Vector<Value> locals = move(arguments);
|
||||||
locals.ensure_capacity(locals.size() + wasm_function->code().locals().size());
|
locals.ensure_capacity(locals.size() + wasm_function->code().func().locals().size());
|
||||||
for (auto& type : wasm_function->code().locals())
|
for (auto& local : wasm_function->code().func().locals()) {
|
||||||
locals.empend(type, 0ull);
|
for (size_t i = 0; i < local.n(); ++i)
|
||||||
|
locals.empend(local.type(), 0ull);
|
||||||
|
}
|
||||||
|
|
||||||
set_frame(Frame {
|
set_frame(Frame {
|
||||||
wasm_function->module(),
|
wasm_function->module(),
|
||||||
move(locals),
|
move(locals),
|
||||||
wasm_function->code().body(),
|
wasm_function->code().func().body(),
|
||||||
wasm_function->type().results().size(),
|
wasm_function->type().results().size(),
|
||||||
});
|
});
|
||||||
m_ip = 0;
|
m_ip = 0;
|
||||||
|
|
|
@ -74,9 +74,13 @@ ErrorOr<void, ValidationError> Validator::validate(Module& module)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.for_each_section_of_type<FunctionSection>([this, &result](FunctionSection const& section) {
|
CodeSection const* code_section { nullptr };
|
||||||
if (result.is_error())
|
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;
|
return;
|
||||||
|
}
|
||||||
m_context.functions.ensure_capacity(section.types().size() + m_context.functions.size());
|
m_context.functions.ensure_capacity(section.types().size() + m_context.functions.size());
|
||||||
for (auto& index : section.types()) {
|
for (auto& index : section.types()) {
|
||||||
if (m_context.types.size() > index.value()) {
|
if (m_context.types.size() > index.value()) {
|
||||||
|
|
|
@ -1403,42 +1403,6 @@ ParseResult<Module> Module::parse(Stream& stream)
|
||||||
return Module { move(sections) };
|
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)
|
ByteString parse_error_to_byte_string(ParseError error)
|
||||||
{
|
{
|
||||||
switch (error) {
|
switch (error) {
|
||||||
|
|
|
@ -541,33 +541,6 @@ void Printer::print(Wasm::Module const& module)
|
||||||
print(")\n");
|
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)
|
void Printer::print(Wasm::StartSection const& section)
|
||||||
{
|
{
|
||||||
print_indent();
|
print_indent();
|
||||||
|
|
|
@ -50,7 +50,6 @@ struct Printer {
|
||||||
void print(Wasm::MemorySection::Memory const&);
|
void print(Wasm::MemorySection::Memory const&);
|
||||||
void print(Wasm::MemoryType const&);
|
void print(Wasm::MemoryType const&);
|
||||||
void print(Wasm::Module const&);
|
void print(Wasm::Module const&);
|
||||||
void print(Wasm::Module::Function const&);
|
|
||||||
void print(Wasm::Reference const&);
|
void print(Wasm::Reference const&);
|
||||||
void print(Wasm::StartSection const&);
|
void print(Wasm::StartSection const&);
|
||||||
void print(Wasm::StartSection::StartFunction const&);
|
void print(Wasm::StartSection::StartFunction const&);
|
||||||
|
|
|
@ -961,25 +961,6 @@ public:
|
||||||
Valid,
|
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<
|
using AnySection = Variant<
|
||||||
CustomSection,
|
CustomSection,
|
||||||
TypeSection,
|
TypeSection,
|
||||||
|
@ -1001,14 +982,9 @@ public:
|
||||||
explicit Module(Vector<AnySection> sections)
|
explicit Module(Vector<AnySection> sections)
|
||||||
: m_sections(move(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& sections() const { return m_sections; }
|
||||||
auto& functions() const { return m_functions; }
|
|
||||||
auto& type(TypeIndex index) const
|
auto& type(TypeIndex index) const
|
||||||
{
|
{
|
||||||
FunctionType const* type = nullptr;
|
FunctionType const* type = nullptr;
|
||||||
|
@ -1045,11 +1021,9 @@ public:
|
||||||
static ParseResult<Module> parse(Stream& stream);
|
static ParseResult<Module> parse(Stream& stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool populate_sections();
|
|
||||||
void set_validation_status(ValidationStatus status) { m_validation_status = status; }
|
void set_validation_status(ValidationStatus status) { m_validation_status = status; }
|
||||||
|
|
||||||
Vector<AnySection> m_sections;
|
Vector<AnySection> m_sections;
|
||||||
Vector<Function> m_functions;
|
|
||||||
ValidationStatus m_validation_status { ValidationStatus::Unchecked };
|
ValidationStatus m_validation_status { ValidationStatus::Unchecked };
|
||||||
Optional<ByteString> m_validation_error;
|
Optional<ByteString> m_validation_error;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue