From e9b9ef6d61c16914b0dbd51c8e13ea1a92311173 Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Sun, 15 Sep 2024 01:43:25 +0100 Subject: [PATCH] Extract call() and ret() into the StackFrame from VM --- src/common.cpp | 46 ++++++++++++++++++++++++++++---- src/common.hpp | 11 +++++--- src/compiler.cpp | 1 - src/vm.cpp | 69 ++++++++++++++++++------------------------------ src/vm.hpp | 45 ++++++++++++++++++------------- 5 files changed, 100 insertions(+), 72 deletions(-) diff --git a/src/common.cpp b/src/common.cpp index 4b859e9..91ad16e 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -302,8 +302,7 @@ Result Module::cmp(const Module& rhs) const { return res; } -Result StackFrame::create(const Value& parent, - const Function& fun) { +Result StackFrame::create(const Value& parent, const Value& fun) { auto pod = TRY(arena_alloc()); pod->header.tag = Tag::StackFrame; @@ -319,6 +318,10 @@ Result StackFrame::copy_value() const { return Value(StackFrame(TRY(_value.copy()))); } +Result StackFrame::copy() const { + return StackFrame(TRY(_value.copy())); +} + Result StackFrame::get(uint64_t idx) const { if (idx >= _value->size) return ERROR(KeyError); @@ -349,7 +352,7 @@ Result StackFrame::set(uint64_t idx, const Value& val) { return StackFrame(TRY(MkGcRoot(pod))); } -Result StackFrame::settop(uint64_t idx) { +Result StackFrame::settop(uint64_t idx) const { auto pod = TRY(arena_alloc(sizeof(OffPtr) * idx)); pod->header.tag = Tag::StackFrame; @@ -376,8 +379,8 @@ Result StackFrame::settop(uint64_t idx) { Result StackFrame::parent() const { return Value::create(_value->parent.get()); } -Result StackFrame::fun() const { - return Function::create((PodFunction*)_value->fun.get()); +Result StackFrame::fun() const { + return Value::create(_value->fun.get()); } uint64_t StackFrame::pc() const { return _value->pc; } @@ -400,6 +403,39 @@ Result StackFrame::setpc(uint64_t pc) { Result StackFrame::incpc() { return setpc(pc() + 1); } +Result 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()) { + uint64_t arity = fun.to()->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::ret(uint64_t regnum) const { + auto parent_frame = TRY(parent()); + if (parent_frame.is()) { + return ERROR(EndOfProgram); + } + + auto res = TRY(get(regnum)); + StackFrame& parent_stack = *parent_frame.to(); + uint64_t parent_size = TRY(parent_stack.size()); + parent_stack = TRY(parent_stack.set(parent_size, res)); + + return std::move(parent_stack); +} + Result Error::copy_value() const { return Value(Error(TRY(_value.copy()))); } diff --git a/src/common.hpp b/src/common.hpp index a922f26..cff02bd 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -1115,17 +1115,17 @@ class StackFrame : public Object { using Object::get; Result get(uint64_t idx) const; Result set(uint64_t idx, const Value& val); - Result settop(uint64_t idx); + Result settop(uint64_t idx) const; Result parent() const; - Result fun() const; + Result fun() const; uint64_t pc() const; Result setpc(uint64_t pc); Result incpc(); Result size() const { return _value->size; } - static Result create(const Value& parent, const Function& fun); + static Result create(const Value& parent, const Value& fun); - Result slice(uint64_t start, uint64_t end) { + Result slice(uint64_t start, uint64_t end) const { if (start > end || end > _value->size) return ERROR(IndexOutOfRange); uint64_t res_size = end - start; auto pod = TRY(arena_alloc(res_size * sizeof(PodObject*))); @@ -1138,6 +1138,9 @@ class StackFrame : public Object { return Array(TRY(MkGcRoot(pod))); } + Result call(const Value& fun, uint64_t start, uint64_t end) const; + Result ret(uint64_t regno) const; + virtual Result copy_value() const final; Result copy() const; diff --git a/src/compiler.cpp b/src/compiler.cpp index 91fc31c..0bf4807 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -644,7 +644,6 @@ Result Compiler::compile_syntax(Context& context, Symbol& op, Result Compiler::compile_fn(Context& context, Symbol& op, const Value& expr) { Context ctx = TRY(Context::create(context)); - ctx.maxreg = 1; // Reserve the slot for function itself auto rest = TRY(expr.rest()); diff --git a/src/vm.cpp b/src/vm.cpp index 9f1fe44..8fd05f1 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -9,7 +9,7 @@ Result VM::setreg(uint64_t idx, const Value& value) { return _stack.set(idx, value); } -Result VM::getconst(uint64_t idx) { return _constants.get(idx); } +Result VM::getconst(uint64_t idx) { return TRY(constants()).get(idx); } Result VM::get(bool is_const, uint64_t idx) { if (is_const) return getconst(idx); @@ -104,23 +104,7 @@ Result VM::vm_call_lisp(Opcode& oc, Function& fun) { uint64_t reg_start = (uint64_t)oc.arg1().arg; uint64_t reg_end = (uint64_t)oc.arg2().arg; - if (fun.arity() != (reg_end - reg_start - 1)) { - 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); + _stack = TRY(_stack.call(TRY(fun.copy_value()), reg_start, reg_end)); return Result(); } @@ -154,21 +138,14 @@ Result VM::vm_call(Opcode& oc) { } Result VM::vm_selfcall(Opcode& oc) { + auto fun = TRY(_stack.fun()); + if (!fun.is()) return ERROR(TypeMismatch); + Function& lisp_fun = *fun.to(); + uint64_t reg_start = (uint64_t)oc.arg1().arg; uint64_t reg_end = (uint64_t)oc.arg2().arg; - if (_fun.arity() != (reg_end - reg_start - 1)) { - 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); + _stack = TRY(_stack.call(fun, reg_start, reg_end)); return Result(); } @@ -180,18 +157,9 @@ Result VM::vm_ret(Opcode& oc) { return ERROR(EndOfProgram); } - auto res = TRY(getreg((uint64_t)oc.arg1().arg)); - StackFrame& parent_stack = *parent.to(); - uint64_t parent_size = TRY(parent_stack.size()); - parent_stack = TRY(parent_stack.set(parent_size, res)); + auto regnum = (uint64_t)oc.arg1().arg; - auto fun = TRY(parent_stack.fun()); - - _stack = std::move(parent_stack); - _code = TRY(fun.code()); - _constants = TRY(fun.constants()); - _closure = TRY(fun.closure()); - _fun = std::move(fun); + _stack = TRY(_stack.ret(regnum)); _stack = TRY(_stack.incpc()); return Result(); @@ -223,7 +191,7 @@ Result VM::vm_make_closure(Opcode& oc) { Result VM::vm_closure_load(Opcode& oc) { 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(_stack.incpc()); return Result(); @@ -247,8 +215,8 @@ Result VM::vm_global_store(Opcode& oc) { return Result(); } -Result VM::step() { - auto opcode = TRY(_code.get(_stack.pc())); +Result VM::step_bytecode() { + auto opcode = TRY(TRY(code()).get(_stack.pc())); if (!opcode.is()) return ERROR(TypeMismatch); Opcode& oc = *opcode.to(); @@ -310,6 +278,19 @@ Result VM::step() { return Result(); } +Result VM::step_native() { return ERROR(NotImplemented); } + +Result VM::step() { + auto fun = TRY(_stack.fun()); + if (fun.is()) { + return step_bytecode(); + } else if (fun.is()) { + return step_native(); + } else { + return ERROR(NotImplemented); + } +} + Result VM::run() { while (true) { auto rc = step(); diff --git a/src/vm.hpp b/src/vm.hpp index cba22ab..798e45f 100644 --- a/src/vm.hpp +++ b/src/vm.hpp @@ -5,44 +5,41 @@ class VM { public: VM() {} - VM(StackFrame&& stack, Function&& fun, Array&& code, Array&& constants, - Array&& closure, Dict&& globals, Value&& res) + VM(StackFrame&& stack, Dict&& globals, Value&& res) : _stack(std::move(stack)), - _fun(std::move(fun)), - _code(std::move(code)), - _constants(std::move(constants)), - _closure(std::move(closure)), _globals(std::move(globals)), _res(std::move(res)) {} + VM(VM&& vm) : _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)), _res(std::move(vm._res)) {} VM(const VM&) = delete; static Result 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 stack = TRY(StackFrame::create(nil, fun)); + auto globals_copy = TRY(globals.copy()); + + /* auto code = TRY(fun.code()); auto constants = TRY(fun.constants()); auto closure = TRY(fun.closure()); auto globals_copy = TRY(globals.copy()); + */ - return VM(std::move(stack), std::move(fun), std::move(code), - std::move(constants), std::move(closure), std::move(globals_copy), - std::move(nil)); + return VM(std::move(stack), std::move(globals_copy), std::move(nil)); } Result run(); Result step(); + Result step_bytecode(); + Result step_native(); + Result vm_mov(Opcode& oc); Result vm_add(Opcode& oc); Result vm_mul(Opcode& oc); @@ -72,12 +69,24 @@ class VM { Result globals() { return _globals.copy(); } + Result code() { + auto fun = TRY(_stack.fun()); + if (!fun.is()) return ERROR(TypeMismatch); + return fun.to()->code(); + } + Result constants() { + auto fun = TRY(_stack.fun()); + if (!fun.is()) return ERROR(TypeMismatch); + return fun.to()->constants(); + } + Result closure() { + auto fun = TRY(_stack.fun()); + if (!fun.is()) return ERROR(TypeMismatch); + return fun.to()->closure(); + } + private: StackFrame _stack; - Function _fun; - Array _code; - Array _constants; - Array _closure; Dict _globals; Value _res; };