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

View file

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

View file

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

View file

@ -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 = &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;
}
m_context.functions.ensure_capacity(section.types().size() + m_context.functions.size());
for (auto& index : section.types()) {
if (m_context.types.size() > index.value()) {

View file

@ -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 = &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)
{
switch (error) {

View file

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

View file

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

View file

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