Skip to content

Commit bc936a5

Browse files
committed
LibWasm: Make Frame a value type as well
This means stack operations will no longer do extra allocations.
1 parent 73eb078 commit bc936a5

File tree

6 files changed

+53
-54
lines changed

6 files changed

+53
-54
lines changed

Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,15 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
107107

108108
module.for_each_section_of_type<GlobalSection>([&](auto& global_section) {
109109
for (auto& entry : global_section.entries()) {
110-
auto frame = make<Frame>(
111-
auxiliary_instance,
112-
Vector<Value> {},
113-
entry.expression(),
114-
1);
115110
Configuration config { m_store };
116111
config.pre_interpret_hook = &pre_interpret_hook;
117112
config.post_interpret_hook = &post_interpret_hook;
118-
config.set_frame(move(frame));
113+
config.set_frame(Frame {
114+
auxiliary_instance,
115+
Vector<Value> {},
116+
entry.expression(),
117+
1,
118+
});
119119
auto result = config.execute();
120120
// What if this traps?
121121
if (result.is_trap())
@@ -139,15 +139,15 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
139139
for (auto& segment : data_section.data()) {
140140
segment.value().visit(
141141
[&](const DataSection::Data::Active& data) {
142-
auto frame = make<Frame>(
143-
main_module_instance,
144-
Vector<Value> {},
145-
data.offset,
146-
1);
147142
Configuration config { m_store };
148143
config.pre_interpret_hook = &pre_interpret_hook;
149144
config.post_interpret_hook = &post_interpret_hook;
150-
config.set_frame(move(frame));
145+
config.set_frame(Frame {
146+
main_module_instance,
147+
Vector<Value> {},
148+
data.offset,
149+
1,
150+
});
151151
auto result = config.execute();
152152
size_t offset = 0;
153153
result.values().first().value().visit(

Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,6 @@ class Label {
392392
};
393393

394394
class Frame {
395-
AK_MAKE_NONCOPYABLE(Frame);
396-
397395
public:
398396
explicit Frame(const ModuleInstance& module, Vector<Value> locals, const Expression& expression, size_t arity)
399397
: m_module(module)
@@ -418,7 +416,7 @@ class Frame {
418416

419417
class Stack {
420418
public:
421-
using EntryType = Variant<Value, Label, NonnullOwnPtr<Frame>>;
419+
using EntryType = Variant<Value, Label, Frame>;
422420
Stack() = default;
423421

424422
[[nodiscard]] bool is_empty() const { return m_data.is_empty(); }
@@ -428,9 +426,10 @@ class Stack {
428426

429427
auto size() const { return m_data.size(); }
430428
auto& entries() const { return m_data; }
429+
auto& entries() { return m_data; }
431430

432431
private:
433-
Vector<EntryType> m_data;
432+
Vector<EntryType, 64> m_data;
434433
};
435434

436435
using InstantiationResult = AK::Result<NonnullOwnPtr<ModuleInstance>, InstantiationError>;

Userland/Libraries/LibWasm/AbstractMachine/Configuration.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,12 @@ Result Configuration::call(FunctionAddress address, Vector<Value> arguments)
3535
for (auto& type : wasm_function->code().locals())
3636
locals.empend(type, 0ull);
3737

38-
auto frame = make<Frame>(
38+
set_frame(Frame {
3939
wasm_function->module(),
4040
move(locals),
4141
wasm_function->code().body(),
42-
wasm_function->type().results().size());
43-
44-
set_frame(move(frame));
42+
wasm_function->type().results().size(),
43+
});
4544
return execute();
4645
}
4746

@@ -61,8 +60,8 @@ Result Configuration::execute()
6160
return Trap {};
6261

6362
Vector<Value> results;
64-
results.ensure_capacity(m_current_frame->arity());
65-
for (size_t i = 0; i < m_current_frame->arity(); ++i)
63+
results.ensure_capacity(frame().arity());
64+
for (size_t i = 0; i < frame().arity(); ++i)
6665
results.append(move(stack().pop().get<Value>()));
6766
auto label = stack().pop();
6867
// ASSERT: label == current frame
@@ -83,9 +82,9 @@ void Configuration::dump_stack()
8382
dbgln(" *{}", v.value());
8483
});
8584
},
86-
[](const NonnullOwnPtr<Frame>& f) {
87-
dbgln(" frame({})", f->arity());
88-
for (auto& local : f->locals()) {
85+
[](const Frame& f) {
86+
dbgln(" frame({})", f.arity());
87+
for (auto& local : f.locals()) {
8988
local.value().visit([]<typename T>(const T& v) {
9089
if constexpr (IsIntegral<T> || IsFloatingPoint<T>)
9190
dbgln(" {}", v);

Userland/Libraries/LibWasm/AbstractMachine/Configuration.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@ class Configuration {
1818
}
1919

2020
Optional<Label> nth_label(size_t);
21-
void set_frame(NonnullOwnPtr<Frame> frame)
21+
void set_frame(Frame&& frame)
2222
{
23-
m_current_frame = frame.ptr();
23+
m_current_frame_index = m_stack.size();
24+
Label label(frame.arity(), frame.expression().instructions().size());
2425
m_stack.push(move(frame));
25-
m_stack.push(Label(m_current_frame->arity(), m_current_frame->expression().instructions().size()));
26+
m_stack.push(label);
2627
}
27-
auto& frame() const { return m_current_frame; }
28-
auto& frame() { return m_current_frame; }
28+
auto& frame() const { return m_stack.entries()[m_current_frame_index].get<Frame>(); }
29+
auto& frame() { return m_stack.entries()[m_current_frame_index].get<Frame>(); }
2930
auto& ip() const { return m_ip; }
3031
auto& ip() { return m_ip; }
3132
auto& depth() const { return m_depth; }
@@ -45,7 +46,7 @@ class Configuration {
4546

4647
private:
4748
Store& m_store;
48-
Frame* m_current_frame { nullptr };
49+
size_t m_current_frame_index { 0 };
4950
Stack m_stack;
5051
size_t m_depth { 0 };
5152
InstructionPointer m_ip;

Userland/Libraries/LibWasm/AbstractMachine/Interpreter.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace Wasm {
3131

3232
void Interpreter::interpret(Configuration& configuration)
3333
{
34-
auto& instructions = configuration.frame()->expression().instructions();
34+
auto& instructions = configuration.frame().expression().instructions();
3535
auto max_ip_value = InstructionPointer { instructions.size() };
3636
auto& current_ip_value = configuration.ip();
3737

@@ -73,7 +73,7 @@ void Interpreter::branch_to_label(Configuration& configuration, LabelIndex index
7373

7474
ReadonlyBytes Interpreter::load_from_memory(Configuration& configuration, const Instruction& instruction, size_t size)
7575
{
76-
auto& address = configuration.frame()->module().memories().first();
76+
auto& address = configuration.frame().module().memories().first();
7777
auto memory = configuration.store().get(address);
7878
if (!memory) {
7979
m_do_trap = true;
@@ -97,7 +97,7 @@ ReadonlyBytes Interpreter::load_from_memory(Configuration& configuration, const
9797

9898
void Interpreter::store_to_memory(Configuration& configuration, const Instruction& instruction, ReadonlyBytes data)
9999
{
100-
auto& address = configuration.frame()->module().memories().first();
100+
auto& address = configuration.frame().module().memories().first();
101101
auto memory = configuration.store().get(address);
102102
TRAP_IF_NOT(memory);
103103
auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
@@ -366,11 +366,11 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
366366
case Instructions::nop.value():
367367
return;
368368
case Instructions::local_get.value():
369-
configuration.stack().push(Value(configuration.frame()->locals()[instruction.arguments().get<LocalIndex>().value()]));
369+
configuration.stack().push(Value(configuration.frame().locals()[instruction.arguments().get<LocalIndex>().value()]));
370370
return;
371371
case Instructions::local_set.value(): {
372372
auto entry = configuration.stack().pop();
373-
configuration.frame()->locals()[instruction.arguments().get<LocalIndex>().value()] = move(entry.get<Value>());
373+
configuration.frame().locals()[instruction.arguments().get<LocalIndex>().value()] = move(entry.get<Value>());
374374
return;
375375
}
376376
case Instructions::i32_const.value():
@@ -448,7 +448,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
448448
}
449449
case Instructions::return_.value(): {
450450
Vector<Stack::EntryType> results;
451-
auto& frame = *configuration.frame();
451+
auto& frame = configuration.frame();
452452
results.ensure_capacity(frame.arity());
453453
for (size_t i = 0; i < frame.arity(); ++i)
454454
results.prepend(configuration.stack().pop());
@@ -460,7 +460,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
460460
last_label = entry.get<Label>();
461461
continue;
462462
}
463-
if (entry.has<NonnullOwnPtr<Frame>>()) {
463+
if (entry.has<Frame>()) {
464464
// Push the frame back
465465
configuration.stack().push(move(entry));
466466
// Push its label back (if there is one)
@@ -475,7 +475,7 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
475475
configuration.stack().push(move(result));
476476

477477
// Jump past the call/indirect instruction
478-
configuration.ip() = configuration.frame()->expression().instructions().size() - 1;
478+
configuration.ip() = configuration.frame().expression().instructions().size() - 1;
479479
return;
480480
}
481481
case Instructions::br.value():
@@ -489,14 +489,14 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
489489
goto unimplemented;
490490
case Instructions::call.value(): {
491491
auto index = instruction.arguments().get<FunctionIndex>();
492-
auto address = configuration.frame()->module().functions()[index.value()];
492+
auto address = configuration.frame().module().functions()[index.value()];
493493
dbgln_if(WASM_TRACE_DEBUG, "call({})", address.value());
494494
call_address(configuration, address);
495495
return;
496496
}
497497
case Instructions::call_indirect.value(): {
498498
auto& args = instruction.arguments().get<Instruction::IndirectCallArgs>();
499-
auto table_address = configuration.frame()->module().tables()[args.table.value()];
499+
auto table_address = configuration.frame().module().tables()[args.table.value()];
500500
auto table_instance = configuration.store().get(table_address);
501501
auto index = configuration.stack().pop().get<Value>().to<i32>();
502502
TRAP_IF_NOT(index.has_value());
@@ -565,40 +565,40 @@ void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip
565565
case Instructions::local_tee.value(): {
566566
auto value = configuration.stack().peek().get<Value>();
567567
auto local_index = instruction.arguments().get<LocalIndex>();
568-
TRAP_IF_NOT(configuration.frame()->locals().size() > local_index.value());
568+
TRAP_IF_NOT(configuration.frame().locals().size() > local_index.value());
569569
dbgln_if(WASM_TRACE_DEBUG, "stack:peek -> locals({})", local_index.value());
570-
configuration.frame()->locals()[local_index.value()] = move(value);
570+
configuration.frame().locals()[local_index.value()] = move(value);
571571
return;
572572
}
573573
case Instructions::global_get.value(): {
574574
auto global_index = instruction.arguments().get<GlobalIndex>();
575-
TRAP_IF_NOT(configuration.frame()->module().globals().size() > global_index.value());
576-
auto address = configuration.frame()->module().globals()[global_index.value()];
575+
TRAP_IF_NOT(configuration.frame().module().globals().size() > global_index.value());
576+
auto address = configuration.frame().module().globals()[global_index.value()];
577577
dbgln_if(WASM_TRACE_DEBUG, "global({}) -> stack", address.value());
578578
auto global = configuration.store().get(address);
579579
configuration.stack().push(Value(global->value()));
580580
return;
581581
}
582582
case Instructions::global_set.value(): {
583583
auto global_index = instruction.arguments().get<GlobalIndex>();
584-
TRAP_IF_NOT(configuration.frame()->module().globals().size() > global_index.value());
585-
auto address = configuration.frame()->module().globals()[global_index.value()];
584+
TRAP_IF_NOT(configuration.frame().module().globals().size() > global_index.value());
585+
auto address = configuration.frame().module().globals()[global_index.value()];
586586
auto value = configuration.stack().pop().get<Value>();
587587
dbgln_if(WASM_TRACE_DEBUG, "stack -> global({})", address.value());
588588
auto global = configuration.store().get(address);
589589
global->set_value(move(value));
590590
return;
591591
}
592592
case Instructions::memory_size.value(): {
593-
auto address = configuration.frame()->module().memories()[0];
593+
auto address = configuration.frame().module().memories()[0];
594594
auto instance = configuration.store().get(address);
595595
auto pages = instance->size() / Constants::page_size;
596596
dbgln_if(WASM_TRACE_DEBUG, "memory.size -> stack({})", pages);
597597
configuration.stack().push(Value((i32)pages));
598598
return;
599599
}
600600
case Instructions::memory_grow.value(): {
601-
auto address = configuration.frame()->module().memories()[0];
601+
auto address = configuration.frame().module().memories()[0];
602602
auto instance = configuration.store().get(address);
603603
i32 old_pages = instance->size() / Constants::page_size;
604604
auto new_pages = configuration.stack().pop().get<Value>().to<i32>();

Userland/Utilities/wasm.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,10 @@ static bool pre_interpret_hook(Wasm::Configuration& config, Wasm::InstructionPoi
155155
Optional<Wasm::FunctionAddress> address;
156156
auto index = args[1].to_uint<u64>();
157157
if (index.has_value()) {
158-
address = config.frame()->module().functions()[index.value()];
158+
address = config.frame().module().functions()[index.value()];
159159
} else {
160160
auto& name = args[1];
161-
for (auto& export_ : config.frame()->module().exports()) {
161+
for (auto& export_ : config.frame().module().exports()) {
162162
if (export_.name() == name) {
163163
if (auto addr = export_.value().get_pointer<Wasm::FunctionAddress>()) {
164164
address = *addr;
@@ -437,12 +437,12 @@ int main(int argc, char* argv[])
437437

438438
if (debug) {
439439
Wasm::Configuration config { machine.store() };
440-
auto frame = make<Wasm::Frame>(
440+
config.set_frame(Wasm::Frame {
441441
*module_instance,
442442
Vector<Wasm::Value> {},
443443
instance->get<Wasm::WasmFunction>().code().body(),
444-
1);
445-
config.set_frame(move(frame));
444+
1,
445+
});
446446
const Wasm::Instruction instr { Wasm::Instructions::nop };
447447
Wasm::InstructionPointer ip { 0 };
448448
g_continue = false;

0 commit comments

Comments
 (0)