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:
Diego Frias 2024-07-27 16:44:36 -07:00 committed by Ali Mohammad Pur
parent 2d95cc01dc
commit dc52998341
Notes: github-actions[bot] 2024-07-28 00:57:26 +00:00
8 changed files with 36 additions and 111 deletions

View file

@ -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 = &section; });
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);

View file

@ -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&);

View file

@ -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;

View file

@ -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 = &section; });
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()) {

View file

@ -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 = &section; });
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) {

View file

@ -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();

View file

@ -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&);

View file

@ -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;
}; };