Extract call() and ret() into the StackFrame from VM

This commit is contained in:
Konstantin Nazarov 2024-09-15 01:43:25 +01:00
parent 51de7e3547
commit e9b9ef6d61
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
5 changed files with 100 additions and 72 deletions

View file

@ -302,8 +302,7 @@ Result<short> Module::cmp(const Module& rhs) const {
return res; return res;
} }
Result<StackFrame> StackFrame::create(const Value& parent, Result<StackFrame> StackFrame::create(const Value& parent, const Value& fun) {
const Function& fun) {
auto pod = TRY(arena_alloc<PodStackFrame>()); auto pod = TRY(arena_alloc<PodStackFrame>());
pod->header.tag = Tag::StackFrame; pod->header.tag = Tag::StackFrame;
@ -319,6 +318,10 @@ Result<Value> StackFrame::copy_value() const {
return Value(StackFrame(TRY(_value.copy()))); return Value(StackFrame(TRY(_value.copy())));
} }
Result<StackFrame> StackFrame::copy() const {
return StackFrame(TRY(_value.copy()));
}
Result<Value> StackFrame::get(uint64_t idx) const { Result<Value> StackFrame::get(uint64_t idx) const {
if (idx >= _value->size) return ERROR(KeyError); if (idx >= _value->size) return ERROR(KeyError);
@ -349,7 +352,7 @@ Result<StackFrame> StackFrame::set(uint64_t idx, const Value& val) {
return StackFrame(TRY(MkGcRoot(pod))); return StackFrame(TRY(MkGcRoot(pod)));
} }
Result<StackFrame> StackFrame::settop(uint64_t idx) { Result<StackFrame> StackFrame::settop(uint64_t idx) const {
auto pod = TRY(arena_alloc<PodStackFrame>(sizeof(OffPtr<PodObject>) * idx)); auto pod = TRY(arena_alloc<PodStackFrame>(sizeof(OffPtr<PodObject>) * idx));
pod->header.tag = Tag::StackFrame; pod->header.tag = Tag::StackFrame;
@ -376,8 +379,8 @@ Result<StackFrame> StackFrame::settop(uint64_t idx) {
Result<Value> StackFrame::parent() const { Result<Value> StackFrame::parent() const {
return Value::create(_value->parent.get()); return Value::create(_value->parent.get());
} }
Result<Function> StackFrame::fun() const { Result<Value> StackFrame::fun() const {
return Function::create((PodFunction*)_value->fun.get()); return Value::create(_value->fun.get());
} }
uint64_t StackFrame::pc() const { return _value->pc; } uint64_t StackFrame::pc() const { return _value->pc; }
@ -400,6 +403,39 @@ Result<StackFrame> StackFrame::setpc(uint64_t pc) {
Result<StackFrame> StackFrame::incpc() { return setpc(pc() + 1); } Result<StackFrame> StackFrame::incpc() { return setpc(pc() + 1); }
Result<StackFrame> StackFrame::call(const Value& fun, uint64_t start,
uint64_t end) const {
auto trunc_stack = TRY(settop(start));
auto new_stack = TRY(StackFrame::create(TRY(trunc_stack.copy_value()), fun));
if (fun.is<Function>()) {
uint64_t arity = fun.to<Function>()->arity();
if (arity != (end - start - 1)) {
return ERROR(ArgumentCountMismatch);
}
}
for (uint64_t i = 0; i < end - start - 1; i++) {
new_stack = TRY(new_stack.set(i, TRY(get(start + i + 1))));
}
return new_stack;
}
Result<StackFrame> StackFrame::ret(uint64_t regnum) const {
auto parent_frame = TRY(parent());
if (parent_frame.is<Nil>()) {
return ERROR(EndOfProgram);
}
auto res = TRY(get(regnum));
StackFrame& parent_stack = *parent_frame.to<StackFrame>();
uint64_t parent_size = TRY(parent_stack.size());
parent_stack = TRY(parent_stack.set(parent_size, res));
return std::move(parent_stack);
}
Result<Value> Error::copy_value() const { Result<Value> Error::copy_value() const {
return Value(Error(TRY(_value.copy()))); return Value(Error(TRY(_value.copy())));
} }

View file

@ -1115,17 +1115,17 @@ class StackFrame : public Object {
using Object::get; using Object::get;
Result<Value> get(uint64_t idx) const; Result<Value> get(uint64_t idx) const;
Result<StackFrame> set(uint64_t idx, const Value& val); Result<StackFrame> set(uint64_t idx, const Value& val);
Result<StackFrame> settop(uint64_t idx); Result<StackFrame> settop(uint64_t idx) const;
Result<Value> parent() const; Result<Value> parent() const;
Result<Function> fun() const; Result<Value> fun() const;
uint64_t pc() const; uint64_t pc() const;
Result<StackFrame> setpc(uint64_t pc); Result<StackFrame> setpc(uint64_t pc);
Result<StackFrame> incpc(); Result<StackFrame> incpc();
Result<uint64_t> size() const { return _value->size; } Result<uint64_t> size() const { return _value->size; }
static Result<StackFrame> create(const Value& parent, const Function& fun); static Result<StackFrame> create(const Value& parent, const Value& fun);
Result<Array> slice(uint64_t start, uint64_t end) { Result<Array> slice(uint64_t start, uint64_t end) const {
if (start > end || end > _value->size) return ERROR(IndexOutOfRange); if (start > end || end > _value->size) return ERROR(IndexOutOfRange);
uint64_t res_size = end - start; uint64_t res_size = end - start;
auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(PodObject*))); auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(PodObject*)));
@ -1138,6 +1138,9 @@ class StackFrame : public Object {
return Array(TRY(MkGcRoot(pod))); return Array(TRY(MkGcRoot(pod)));
} }
Result<StackFrame> call(const Value& fun, uint64_t start, uint64_t end) const;
Result<StackFrame> ret(uint64_t regno) const;
virtual Result<Value> copy_value() const final; virtual Result<Value> copy_value() const final;
Result<StackFrame> copy() const; Result<StackFrame> copy() const;

View file

@ -644,7 +644,6 @@ Result<Expression> Compiler::compile_syntax(Context& context, Symbol& op,
Result<Expression> Compiler::compile_fn(Context& context, Symbol& op, Result<Expression> Compiler::compile_fn(Context& context, Symbol& op,
const Value& expr) { const Value& expr) {
Context ctx = TRY(Context::create(context)); Context ctx = TRY(Context::create(context));
ctx.maxreg = 1; // Reserve the slot for function itself
auto rest = TRY(expr.rest()); auto rest = TRY(expr.rest());

View file

@ -9,7 +9,7 @@ Result<StackFrame> VM::setreg(uint64_t idx, const Value& value) {
return _stack.set(idx, value); return _stack.set(idx, value);
} }
Result<Value> VM::getconst(uint64_t idx) { return _constants.get(idx); } Result<Value> VM::getconst(uint64_t idx) { return TRY(constants()).get(idx); }
Result<Value> VM::get(bool is_const, uint64_t idx) { Result<Value> VM::get(bool is_const, uint64_t idx) {
if (is_const) return getconst(idx); if (is_const) return getconst(idx);
@ -104,23 +104,7 @@ Result<void> VM::vm_call_lisp(Opcode& oc, Function& fun) {
uint64_t reg_start = (uint64_t)oc.arg1().arg; uint64_t reg_start = (uint64_t)oc.arg1().arg;
uint64_t reg_end = (uint64_t)oc.arg2().arg; uint64_t reg_end = (uint64_t)oc.arg2().arg;
if (fun.arity() != (reg_end - reg_start - 1)) { _stack = TRY(_stack.call(TRY(fun.copy_value()), reg_start, reg_end));
return ERROR(ArgumentCountMismatch);
}
auto trunc_stack = TRY(_stack.settop(reg_start));
auto new_stack = TRY(StackFrame::create(TRY(trunc_stack.copy_value()), fun));
for (uint64_t i = 0; i < reg_end - reg_start; i++) {
new_stack = TRY(new_stack.set(i, TRY(_stack.get(reg_start + i))));
}
_stack = std::move(new_stack);
_code = TRY(fun.code());
_constants = TRY(fun.constants());
_closure = TRY(fun.closure());
_fun = std::move(fun);
return Result<void>(); return Result<void>();
} }
@ -154,21 +138,14 @@ Result<void> VM::vm_call(Opcode& oc) {
} }
Result<void> VM::vm_selfcall(Opcode& oc) { Result<void> VM::vm_selfcall(Opcode& oc) {
auto fun = TRY(_stack.fun());
if (!fun.is<Function>()) return ERROR(TypeMismatch);
Function& lisp_fun = *fun.to<Function>();
uint64_t reg_start = (uint64_t)oc.arg1().arg; uint64_t reg_start = (uint64_t)oc.arg1().arg;
uint64_t reg_end = (uint64_t)oc.arg2().arg; uint64_t reg_end = (uint64_t)oc.arg2().arg;
if (_fun.arity() != (reg_end - reg_start - 1)) { _stack = TRY(_stack.call(fun, reg_start, reg_end));
return ERROR(ArgumentCountMismatch);
}
auto trunc_stack = TRY(_stack.settop(reg_start));
auto new_stack = TRY(StackFrame::create(TRY(trunc_stack.copy_value()), _fun));
for (uint64_t i = 0; i < reg_end - reg_start; i++) {
new_stack = TRY(new_stack.set(i, TRY(_stack.get(reg_start + i))));
}
_stack = std::move(new_stack);
return Result<void>(); return Result<void>();
} }
@ -180,18 +157,9 @@ Result<void> VM::vm_ret(Opcode& oc) {
return ERROR(EndOfProgram); return ERROR(EndOfProgram);
} }
auto res = TRY(getreg((uint64_t)oc.arg1().arg)); auto regnum = (uint64_t)oc.arg1().arg;
StackFrame& parent_stack = *parent.to<StackFrame>();
uint64_t parent_size = TRY(parent_stack.size());
parent_stack = TRY(parent_stack.set(parent_size, res));
auto fun = TRY(parent_stack.fun()); _stack = TRY(_stack.ret(regnum));
_stack = std::move(parent_stack);
_code = TRY(fun.code());
_constants = TRY(fun.constants());
_closure = TRY(fun.closure());
_fun = std::move(fun);
_stack = TRY(_stack.incpc()); _stack = TRY(_stack.incpc());
return Result<void>(); return Result<void>();
@ -223,7 +191,7 @@ Result<void> VM::vm_make_closure(Opcode& oc) {
Result<void> VM::vm_closure_load(Opcode& oc) { Result<void> VM::vm_closure_load(Opcode& oc) {
uint64_t acc = (uint64_t)oc.arg1().arg; uint64_t acc = (uint64_t)oc.arg1().arg;
Value val = TRY(_closure.get((uint64_t)oc.arg2().arg)); Value val = TRY(TRY(closure()).get((uint64_t)oc.arg2().arg));
_stack = TRY(setreg(acc, val)); _stack = TRY(setreg(acc, val));
_stack = TRY(_stack.incpc()); _stack = TRY(_stack.incpc());
return Result<void>(); return Result<void>();
@ -247,8 +215,8 @@ Result<void> VM::vm_global_store(Opcode& oc) {
return Result<void>(); return Result<void>();
} }
Result<void> VM::step() { Result<void> VM::step_bytecode() {
auto opcode = TRY(_code.get(_stack.pc())); auto opcode = TRY(TRY(code()).get(_stack.pc()));
if (!opcode.is<Opcode>()) return ERROR(TypeMismatch); if (!opcode.is<Opcode>()) return ERROR(TypeMismatch);
Opcode& oc = *opcode.to<Opcode>(); Opcode& oc = *opcode.to<Opcode>();
@ -310,6 +278,19 @@ Result<void> VM::step() {
return Result<void>(); return Result<void>();
} }
Result<void> VM::step_native() { return ERROR(NotImplemented); }
Result<void> VM::step() {
auto fun = TRY(_stack.fun());
if (fun.is<Function>()) {
return step_bytecode();
} else if (fun.is<StdlibFunction>()) {
return step_native();
} else {
return ERROR(NotImplemented);
}
}
Result<Value> VM::run() { Result<Value> VM::run() {
while (true) { while (true) {
auto rc = step(); auto rc = step();

View file

@ -5,44 +5,41 @@
class VM { class VM {
public: public:
VM() {} VM() {}
VM(StackFrame&& stack, Function&& fun, Array&& code, Array&& constants, VM(StackFrame&& stack, Dict&& globals, Value&& res)
Array&& closure, Dict&& globals, Value&& res)
: _stack(std::move(stack)), : _stack(std::move(stack)),
_fun(std::move(fun)),
_code(std::move(code)),
_constants(std::move(constants)),
_closure(std::move(closure)),
_globals(std::move(globals)), _globals(std::move(globals)),
_res(std::move(res)) {} _res(std::move(res)) {}
VM(VM&& vm) VM(VM&& vm)
: _stack(std::move(vm._stack)), : _stack(std::move(vm._stack)),
_fun(std::move(vm._fun)),
_code(std::move(vm._code)),
_constants(std::move(vm._constants)),
_closure(std::move(vm._closure)),
_globals(std::move(vm._globals)), _globals(std::move(vm._globals)),
_res(std::move(vm._res)) {} _res(std::move(vm._res)) {}
VM(const VM&) = delete; VM(const VM&) = delete;
static Result<VM> create(const Module& mod, const Dict& globals) { static Result<VM> create(const Module& mod, const Dict& globals) {
auto fun = TRY(mod.fun()); auto fun = Value(TRY(mod.fun()));
auto nil = Value(TRY(Nil::create())); auto nil = Value(TRY(Nil::create()));
auto stack = TRY(StackFrame::create(nil, fun)); auto stack = TRY(StackFrame::create(nil, fun));
auto globals_copy = TRY(globals.copy());
/*
auto code = TRY(fun.code()); auto code = TRY(fun.code());
auto constants = TRY(fun.constants()); auto constants = TRY(fun.constants());
auto closure = TRY(fun.closure()); auto closure = TRY(fun.closure());
auto globals_copy = TRY(globals.copy()); auto globals_copy = TRY(globals.copy());
*/
return VM(std::move(stack), std::move(fun), std::move(code), return VM(std::move(stack), std::move(globals_copy), std::move(nil));
std::move(constants), std::move(closure), std::move(globals_copy),
std::move(nil));
} }
Result<Value> run(); Result<Value> run();
Result<void> step(); Result<void> step();
Result<void> step_bytecode();
Result<void> step_native();
Result<void> vm_mov(Opcode& oc); Result<void> vm_mov(Opcode& oc);
Result<void> vm_add(Opcode& oc); Result<void> vm_add(Opcode& oc);
Result<void> vm_mul(Opcode& oc); Result<void> vm_mul(Opcode& oc);
@ -72,12 +69,24 @@ class VM {
Result<Dict> globals() { return _globals.copy(); } Result<Dict> globals() { return _globals.copy(); }
Result<Array> code() {
auto fun = TRY(_stack.fun());
if (!fun.is<Function>()) return ERROR(TypeMismatch);
return fun.to<Function>()->code();
}
Result<Array> constants() {
auto fun = TRY(_stack.fun());
if (!fun.is<Function>()) return ERROR(TypeMismatch);
return fun.to<Function>()->constants();
}
Result<Array> closure() {
auto fun = TRY(_stack.fun());
if (!fun.is<Function>()) return ERROR(TypeMismatch);
return fun.to<Function>()->closure();
}
private: private:
StackFrame _stack; StackFrame _stack;
Function _fun;
Array _code;
Array _constants;
Array _closure;
Dict _globals; Dict _globals;
Value _res; Value _res;
}; };