summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2021-05-23 21:42:19 +0430
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2021-05-27 17:28:41 +0430
commitbc936a5fac14165a1d75ccd16ecae22dfd25582d (patch)
tree3a86f00cc3462321d9b2bf729a2afe3b45d4bae6 /Userland
parent73eb0785e0f791d535c803907f347ecb81f929b5 (diff)
downloadserenity-bc936a5fac14165a1d75ccd16ecae22dfd25582d.zip
LibWasm: Make Frame a value type as well
This means stack operations will no longer do extra allocations.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp24
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h7
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp17
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/Configuration.h13
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp36
-rw-r--r--Userland/Utilities/wasm.cpp10
6 files changed, 53 insertions, 54 deletions
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp
index 49704fddd4..210d73e487 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp
+++ b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp
@@ -107,15 +107,15 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
module.for_each_section_of_type<GlobalSection>([&](auto& global_section) {
for (auto& entry : global_section.entries()) {
- auto frame = make<Frame>(
- auxiliary_instance,
- Vector<Value> {},
- entry.expression(),
- 1);
Configuration config { m_store };
config.pre_interpret_hook = &pre_interpret_hook;
config.post_interpret_hook = &post_interpret_hook;
- config.set_frame(move(frame));
+ config.set_frame(Frame {
+ auxiliary_instance,
+ Vector<Value> {},
+ entry.expression(),
+ 1,
+ });
auto result = config.execute();
// What if this traps?
if (result.is_trap())
@@ -139,15 +139,15 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
for (auto& segment : data_section.data()) {
segment.value().visit(
[&](const DataSection::Data::Active& data) {
- auto frame = make<Frame>(
- main_module_instance,
- Vector<Value> {},
- data.offset,
- 1);
Configuration config { m_store };
config.pre_interpret_hook = &pre_interpret_hook;
config.post_interpret_hook = &post_interpret_hook;
- config.set_frame(move(frame));
+ config.set_frame(Frame {
+ main_module_instance,
+ Vector<Value> {},
+ data.offset,
+ 1,
+ });
auto result = config.execute();
size_t offset = 0;
result.values().first().value().visit(
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h
index 346f93dee9..0b786c457c 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h
+++ b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h
@@ -392,8 +392,6 @@ private:
};
class Frame {
- AK_MAKE_NONCOPYABLE(Frame);
-
public:
explicit Frame(const ModuleInstance& module, Vector<Value> locals, const Expression& expression, size_t arity)
: m_module(module)
@@ -418,7 +416,7 @@ private:
class Stack {
public:
- using EntryType = Variant<Value, Label, NonnullOwnPtr<Frame>>;
+ using EntryType = Variant<Value, Label, Frame>;
Stack() = default;
[[nodiscard]] bool is_empty() const { return m_data.is_empty(); }
@@ -428,9 +426,10 @@ public:
auto size() const { return m_data.size(); }
auto& entries() const { return m_data; }
+ auto& entries() { return m_data; }
private:
- Vector<EntryType> m_data;
+ Vector<EntryType, 64> m_data;
};
using InstantiationResult = AK::Result<NonnullOwnPtr<ModuleInstance>, InstantiationError>;
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp
index 5bc8628008..b73f25261e 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp
+++ b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp
@@ -35,13 +35,12 @@ Result Configuration::call(FunctionAddress address, Vector<Value> arguments)
for (auto& type : wasm_function->code().locals())
locals.empend(type, 0ull);
- auto frame = make<Frame>(
+ set_frame(Frame {
wasm_function->module(),
move(locals),
wasm_function->code().body(),
- wasm_function->type().results().size());
-
- set_frame(move(frame));
+ wasm_function->type().results().size(),
+ });
return execute();
}
@@ -61,8 +60,8 @@ Result Configuration::execute()
return Trap {};
Vector<Value> results;
- results.ensure_capacity(m_current_frame->arity());
- for (size_t i = 0; i < m_current_frame->arity(); ++i)
+ results.ensure_capacity(frame().arity());
+ for (size_t i = 0; i < frame().arity(); ++i)
results.append(move(stack().pop().get<Value>()));
auto label = stack().pop();
// ASSERT: label == current frame
@@ -83,9 +82,9 @@ void Configuration::dump_stack()
dbgln(" *{}", v.value());
});
},
- [](const NonnullOwnPtr<Frame>& f) {
- dbgln(" frame({})", f->arity());
- for (auto& local : f->locals()) {
+ [](const Frame& f) {
+ dbgln(" frame({})", f.arity());
+ for (auto& local : f.locals()) {
local.value().visit([]<typename T>(const T& v) {
if constexpr (IsIntegral<T> || IsFloatingPoint<T>)
dbgln(" {}", v);
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h
index 8b792c1535..70658c447b 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h
+++ b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h
@@ -18,14 +18,15 @@ public:
}
Optional<Label> nth_label(size_t);
- void set_frame(NonnullOwnPtr<Frame> frame)
+ void set_frame(Frame&& frame)
{
- m_current_frame = frame.ptr();
+ m_current_frame_index = m_stack.size();
+ Label label(frame.arity(), frame.expression().instructions().size());
m_stack.push(move(frame));
- m_stack.push(Label(m_current_frame->arity(), m_current_frame->expression().instructions().size()));
+ m_stack.push(label);
}
- auto& frame() const { return m_current_frame; }
- auto& frame() { return m_current_frame; }
+ auto& frame() const { return m_stack.entries()[m_current_frame_index].get<Frame>(); }
+ auto& frame() { return m_stack.entries()[m_current_frame_index].get<Frame>(); }
auto& ip() const { return m_ip; }
auto& ip() { return m_ip; }
auto& depth() const { return m_depth; }
@@ -45,7 +46,7 @@ public:
private:
Store& m_store;
- Frame* m_current_frame { nullptr };
+ size_t m_current_frame_index { 0 };
Stack m_stack;
size_t m_depth { 0 };
InstructionPointer m_ip;
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp b/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp
index c557610054..5d5eb1a0be 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp
+++ b/Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp
@@ -31,7 +31,7 @@ namespace Wasm {
void Interpreter::interpret(Configuration& configuration)
{
- auto& instructions = configuration.frame()->expression().instructions();
+ auto& instructions = configuration.frame().expression().instructions();
auto max_ip_value = InstructionPointer { instructions.size() };
auto& current_ip_value = configuration.ip();
@@ -73,7 +73,7 @@ void Interpreter::branch_to_label(Configuration& configuration, LabelIndex index
ReadonlyBytes Interpreter::load_from_memory(Configuration& configuration, const Instruction& instruction, size_t size)
{
- auto& address = configuration.frame()->module().memories().first();
+ auto& address = configuration.frame().module().memories().first();
auto memory = configuration.store().get(address);
if (!memory) {
m_do_trap = true;
@@ -97,7 +97,7 @@ ReadonlyBytes Interpreter::load_from_memory(Configuration& configuration, const
void Interpreter::store_to_memory(Configuration& configuration, const Instruction& instruction, ReadonlyBytes data)
{
- auto& address = configuration.frame()->module().memories().first();
+ auto& address = configuration.frame().module().memories().first();
auto memory = configuration.store().get(address);
TRAP_IF_NOT(memory);
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
@@ -366,11 +366,11 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
case Instructions::nop.value():
return;
case Instructions::local_get.value():
- configuration.stack().push(Value(configuration.frame()->locals()[instruction.arguments().get<LocalIndex>().value()]));
+ configuration.stack().push(Value(configuration.frame().locals()[instruction.arguments().get<LocalIndex>().value()]));
return;
case Instructions::local_set.value(): {
auto entry = configuration.stack().pop();
- configuration.frame()->locals()[instruction.arguments().get<LocalIndex>().value()] = move(entry.get<Value>());
+ configuration.frame().locals()[instruction.arguments().get<LocalIndex>().value()] = move(entry.get<Value>());
return;
}
case Instructions::i32_const.value():
@@ -448,7 +448,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
}
case Instructions::return_.value(): {
Vector<Stack::EntryType> results;
- auto& frame = *configuration.frame();
+ auto& frame = configuration.frame();
results.ensure_capacity(frame.arity());
for (size_t i = 0; i < frame.arity(); ++i)
results.prepend(configuration.stack().pop());
@@ -460,7 +460,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
last_label = entry.get<Label>();
continue;
}
- if (entry.has<NonnullOwnPtr<Frame>>()) {
+ if (entry.has<Frame>()) {
// Push the frame back
configuration.stack().push(move(entry));
// Push its label back (if there is one)
@@ -475,7 +475,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
configuration.stack().push(move(result));
// Jump past the call/indirect instruction
- configuration.ip() = configuration.frame()->expression().instructions().size() - 1;
+ configuration.ip() = configuration.frame().expression().instructions().size() - 1;
return;
}
case Instructions::br.value():
@@ -489,14 +489,14 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
goto unimplemented;
case Instructions::call.value(): {
auto index = instruction.arguments().get<FunctionIndex>();
- auto address = configuration.frame()->module().functions()[index.value()];
+ auto address = configuration.frame().module().functions()[index.value()];
dbgln_if(WASM_TRACE_DEBUG, "call({})", address.value());
call_address(configuration, address);
return;
}
case Instructions::call_indirect.value(): {
auto& args = instruction.arguments().get<Instruction::IndirectCallArgs>();
- auto table_address = configuration.frame()->module().tables()[args.table.value()];
+ auto table_address = configuration.frame().module().tables()[args.table.value()];
auto table_instance = configuration.store().get(table_address);
auto index = configuration.stack().pop().get<Value>().to<i32>();
TRAP_IF_NOT(index.has_value());
@@ -565,15 +565,15 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
case Instructions::local_tee.value(): {
auto value = configuration.stack().peek().get<Value>();
auto local_index = instruction.arguments().get<LocalIndex>();
- TRAP_IF_NOT(configuration.frame()->locals().size() > local_index.value());
+ TRAP_IF_NOT(configuration.frame().locals().size() > local_index.value());
dbgln_if(WASM_TRACE_DEBUG, "stack:peek -> locals({})", local_index.value());
- configuration.frame()->locals()[local_index.value()] = move(value);
+ configuration.frame().locals()[local_index.value()] = move(value);
return;
}
case Instructions::global_get.value(): {
auto global_index = instruction.arguments().get<GlobalIndex>();
- TRAP_IF_NOT(configuration.frame()->module().globals().size() > global_index.value());
- auto address = configuration.frame()->module().globals()[global_index.value()];
+ TRAP_IF_NOT(configuration.frame().module().globals().size() > global_index.value());
+ auto address = configuration.frame().module().globals()[global_index.value()];
dbgln_if(WASM_TRACE_DEBUG, "global({}) -> stack", address.value());
auto global = configuration.store().get(address);
configuration.stack().push(Value(global->value()));
@@ -581,8 +581,8 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
}
case Instructions::global_set.value(): {
auto global_index = instruction.arguments().get<GlobalIndex>();
- TRAP_IF_NOT(configuration.frame()->module().globals().size() > global_index.value());
- auto address = configuration.frame()->module().globals()[global_index.value()];
+ TRAP_IF_NOT(configuration.frame().module().globals().size() > global_index.value());
+ auto address = configuration.frame().module().globals()[global_index.value()];
auto value = configuration.stack().pop().get<Value>();
dbgln_if(WASM_TRACE_DEBUG, "stack -> global({})", address.value());
auto global = configuration.store().get(address);
@@ -590,7 +590,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
return;
}
case Instructions::memory_size.value(): {
- auto address = configuration.frame()->module().memories()[0];
+ auto address = configuration.frame().module().memories()[0];
auto instance = configuration.store().get(address);
auto pages = instance->size() / Constants::page_size;
dbgln_if(WASM_TRACE_DEBUG, "memory.size -> stack({})", pages);
@@ -598,7 +598,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
return;
}
case Instructions::memory_grow.value(): {
- auto address = configuration.frame()->module().memories()[0];
+ auto address = configuration.frame().module().memories()[0];
auto instance = configuration.store().get(address);
i32 old_pages = instance->size() / Constants::page_size;
auto new_pages = configuration.stack().pop().get<Value>().to<i32>();
diff --git a/Userland/Utilities/wasm.cpp b/Userland/Utilities/wasm.cpp
index ed814b5548..ed0199671a 100644
--- a/Userland/Utilities/wasm.cpp
+++ b/Userland/Utilities/wasm.cpp
@@ -155,10 +155,10 @@ static bool pre_interpret_hook(Wasm::Configuration& config, Wasm::InstructionPoi
Optional<Wasm::FunctionAddress> address;
auto index = args[1].to_uint<u64>();
if (index.has_value()) {
- address = config.frame()->module().functions()[index.value()];
+ address = config.frame().module().functions()[index.value()];
} else {
auto& name = args[1];
- for (auto& export_ : config.frame()->module().exports()) {
+ for (auto& export_ : config.frame().module().exports()) {
if (export_.name() == name) {
if (auto addr = export_.value().get_pointer<Wasm::FunctionAddress>()) {
address = *addr;
@@ -437,12 +437,12 @@ int main(int argc, char* argv[])
if (debug) {
Wasm::Configuration config { machine.store() };
- auto frame = make<Wasm::Frame>(
+ config.set_frame(Wasm::Frame {
*module_instance,
Vector<Wasm::Value> {},
instance->get<Wasm::WasmFunction>().code().body(),
- 1);
- config.set_frame(move(frame));
+ 1,
+ });
const Wasm::Instruction instr { Wasm::Instructions::nop };
Wasm::InstructionPointer ip { 0 };
g_continue = false;