diff --git a/src/arena.cpp b/src/arena.cpp index e8569dd..3b4fd81 100644 --- a/src/arena.cpp +++ b/src/arena.cpp @@ -258,7 +258,7 @@ Result Arena::gc_stack(PodStackFrame* obj) { nobj->header.tag = Tag::StackFrame; nobj->parent = TRY(gc_pod(obj->parent.get())); nobj->fun = TRY(gc_pod(obj->fun.get())); - nobj->parent_pc = obj->parent_pc; + nobj->pc = obj->pc; nobj->size = obj->size; for (uint64_t i = 0; i < obj->size; i++) { PodObject* val = obj->data[i].get(); diff --git a/src/common.cpp b/src/common.cpp index 8a3276f..4b859e9 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -302,14 +302,14 @@ Result Module::cmp(const Module& rhs) const { return res; } -Result StackFrame::create(const Value& parent, const Function& fun, - uint64_t parent_pc) { +Result StackFrame::create(const Value& parent, + const Function& fun) { auto pod = TRY(arena_alloc()); pod->header.tag = Tag::StackFrame; pod->parent = parent.pod(); pod->fun = fun.pod(); - pod->parent_pc = parent_pc; + pod->pc = 0; pod->size = 0; return StackFrame(TRY(MkGcRoot(pod))); @@ -332,7 +332,7 @@ Result StackFrame::set(uint64_t idx, const Value& val) { pod->parent = _value->parent; pod->fun = _value->fun; - pod->parent_pc = _value->parent_pc; + pod->pc = _value->pc; pod->size = size; for (uint64_t i = 0; i < _value->size; i++) { @@ -355,7 +355,7 @@ Result StackFrame::settop(uint64_t idx) { pod->parent = _value->parent; pod->fun = _value->fun; - pod->parent_pc = _value->parent_pc; + pod->pc = _value->pc; pod->size = idx; auto min_idx = std::min(_value->size, idx); @@ -379,7 +379,26 @@ Result StackFrame::parent() const { Result StackFrame::fun() const { return Function::create((PodFunction*)_value->fun.get()); } -uint64_t StackFrame::parent_pc() const { return _value->parent_pc; } +uint64_t StackFrame::pc() const { return _value->pc; } + +Result StackFrame::setpc(uint64_t pc) { + auto pod = + TRY(arena_alloc(sizeof(OffPtr) * _value->size)); + pod->header.tag = Tag::StackFrame; + + pod->parent = _value->parent; + pod->fun = _value->fun; + pod->pc = pc; + pod->size = _value->size; + + for (uint64_t i = 0; i < _value->size; i++) { + pod->data[i] = _value->data[i]; + } + + return StackFrame(TRY(MkGcRoot(pod))); +} + +Result StackFrame::incpc() { return setpc(pc() + 1); } Result Error::copy_value() const { return Value(Error(TRY(_value.copy()))); diff --git a/src/common.hpp b/src/common.hpp index 1ca263d..a922f26 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -1118,11 +1118,12 @@ class StackFrame : public Object { Result settop(uint64_t idx); Result parent() const; Result fun() const; - uint64_t parent_pc() 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, - uint64_t parent_pc); + static Result create(const Value& parent, const Function& fun); Result slice(uint64_t start, uint64_t end) { if (start > end || end > _value->size) return ERROR(IndexOutOfRange); diff --git a/src/pod.hpp b/src/pod.hpp index 4c11009..6456489 100644 --- a/src/pod.hpp +++ b/src/pod.hpp @@ -198,7 +198,7 @@ class PodStackFrame final : public PodObject { OffPtr parent; OffPtr fun; - uint64_t parent_pc; + uint64_t pc; uint64_t size; OffPtr data[]; }; diff --git a/src/vm.cpp b/src/vm.cpp index e167d2e..9f1fe44 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -20,7 +20,7 @@ Result VM::vm_mov(Opcode& oc) { uint64_t acc = (uint64_t)oc.arg1().arg; Value val = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg)); _stack = TRY(setreg(acc, val)); - _pc++; + _stack = TRY(_stack.incpc()); return Result(); } @@ -30,7 +30,7 @@ Result VM::vm_add(Opcode& oc) { Value val2 = TRY(get(oc.arg3().is_const, (uint64_t)oc.arg3().arg)); Value res = TRY(val1.add(val2)); _stack = TRY(setreg(acc, res)); - _pc++; + _stack = TRY(_stack.incpc()); return Result(); } @@ -40,7 +40,7 @@ Result VM::vm_mul(Opcode& oc) { Value val2 = TRY(get(oc.arg3().is_const, (uint64_t)oc.arg3().arg)); Value res = TRY(val1.mul(val2)); _stack = TRY(setreg(acc, res)); - _pc++; + _stack = TRY(_stack.incpc()); return Result(); } @@ -50,7 +50,7 @@ Result VM::vm_sub(Opcode& oc) { Value val2 = TRY(get(oc.arg3().is_const, (uint64_t)oc.arg3().arg)); Value res = TRY(val1.sub(val2)); _stack = TRY(setreg(acc, res)); - _pc++; + _stack = TRY(_stack.incpc()); return Result(); } @@ -60,7 +60,7 @@ Result VM::vm_div(Opcode& oc) { Value val2 = TRY(get(oc.arg3().is_const, (uint64_t)oc.arg3().arg)); Value res = TRY(val1.div(val2)); _stack = TRY(setreg(acc, res)); - _pc++; + _stack = TRY(_stack.incpc()); return Result(); } @@ -69,9 +69,9 @@ Result VM::vm_equal(Opcode& oc) { Value val2 = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg)); int64_t expected = oc.arg3().arg; if ((TRY(val1.cmp(val2)) == 0) != expected) { - _pc += 2; + _stack = TRY(_stack.setpc(_stack.pc() + 2)); } else { - _pc += 1; + _stack = TRY(_stack.incpc()); } return Result(); } @@ -81,9 +81,9 @@ Result VM::vm_less(Opcode& oc) { Value val2 = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg)); int64_t expected = oc.arg3().arg; if ((TRY(val1.cmp(val2)) == -1) != expected) { - _pc += 2; + _stack = TRY(_stack.setpc(_stack.pc() + 2)); } else { - _pc += 1; + _stack = TRY(_stack.incpc()); } return Result(); } @@ -93,9 +93,9 @@ Result VM::vm_less_equal(Opcode& oc) { Value val2 = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg)); int64_t expected = oc.arg3().arg; if ((TRY(val1.cmp(val2)) <= 0) != expected) { - _pc += 2; + _stack = TRY(_stack.setpc(_stack.pc() + 2)); } else { - _pc += 1; + _stack = TRY(_stack.incpc()); } return Result(); } @@ -109,8 +109,7 @@ Result VM::vm_call_lisp(Opcode& oc, Function& fun) { } auto trunc_stack = TRY(_stack.settop(reg_start)); - auto new_stack = - TRY(StackFrame::create(TRY(trunc_stack.copy_value()), fun, _pc)); + 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)))); @@ -122,7 +121,6 @@ Result VM::vm_call_lisp(Opcode& oc, Function& fun) { _constants = TRY(fun.constants()); _closure = TRY(fun.closure()); _fun = std::move(fun); - _pc = 0; return Result(); } @@ -136,7 +134,7 @@ Result VM::vm_call_stdlib(Opcode& oc, StdlibFunction& fun) { auto res = TRY(call_stdlib_function(fun.fun_id(), params)); _stack = TRY(setreg(oc.arg1().arg, res)); - _pc++; + _stack = TRY(_stack.incpc()); return Result(); } @@ -164,15 +162,13 @@ Result VM::vm_selfcall(Opcode& oc) { } auto trunc_stack = TRY(_stack.settop(reg_start)); - auto new_stack = - TRY(StackFrame::create(TRY(trunc_stack.copy_value()), _fun, _pc)); + 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); - _pc = 0; return Result(); } @@ -190,20 +186,20 @@ Result VM::vm_ret(Opcode& oc) { parent_stack = TRY(parent_stack.set(parent_size, res)); auto fun = TRY(parent_stack.fun()); - uint64_t pc = _stack.parent_pc(); _stack = std::move(parent_stack); _code = TRY(fun.code()); _constants = TRY(fun.constants()); _closure = TRY(fun.closure()); _fun = std::move(fun); - _pc = pc + 1; + _stack = TRY(_stack.incpc()); return Result(); } Result VM::vm_jump(Opcode& oc) { - _pc += oc.arg1().arg; + auto offset = oc.arg1().arg; + _stack = TRY(_stack.setpc(_stack.pc() + offset)); return Result(); } @@ -220,7 +216,7 @@ Result VM::vm_make_closure(Opcode& oc) { _stack = TRY(setreg(oc.arg1().arg, fun)); - _pc++; + _stack = TRY(_stack.incpc()); return Result(); } @@ -229,7 +225,7 @@ 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)); _stack = TRY(setreg(acc, val)); - _pc++; + _stack = TRY(_stack.incpc()); return Result(); } @@ -238,7 +234,7 @@ Result VM::vm_global_load(Opcode& oc) { Value sym = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg)); Value val = TRY(_globals.get(sym)); _stack = TRY(setreg(acc, val)); - _pc++; + _stack = TRY(_stack.incpc()); return Result(); } @@ -247,12 +243,12 @@ Result VM::vm_global_store(Opcode& oc) { Value val = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg)); _globals = TRY(_globals.insert(sym, val)); - _pc++; + _stack = TRY(_stack.incpc()); return Result(); } Result VM::step() { - auto opcode = TRY(_code.get(_pc)); + auto opcode = TRY(_code.get(_stack.pc())); if (!opcode.is()) return ERROR(TypeMismatch); Opcode& oc = *opcode.to(); diff --git a/src/vm.hpp b/src/vm.hpp index daa7ae8..cba22ab 100644 --- a/src/vm.hpp +++ b/src/vm.hpp @@ -6,14 +6,13 @@ class VM { public: VM() {} VM(StackFrame&& stack, Function&& fun, Array&& code, Array&& constants, - Array&& closure, Dict&& globals, uint64_t pc, Value&& res) + Array&& closure, 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)), - _pc(pc), _res(std::move(res)) {} VM(VM&& vm) : _stack(std::move(vm._stack)), @@ -22,7 +21,6 @@ class VM { _constants(std::move(vm._constants)), _closure(std::move(vm._closure)), _globals(std::move(vm._globals)), - _pc(vm._pc), _res(std::move(vm._res)) {} VM(const VM&) = delete; @@ -30,9 +28,8 @@ class VM { static Result create(const Module& mod, const Dict& globals) { auto fun = TRY(mod.fun()); auto nil = Value(TRY(Nil::create())); - auto stack = TRY(StackFrame::create(nil, fun, 0)); + auto stack = TRY(StackFrame::create(nil, fun)); - uint64_t pc = 0; auto code = TRY(fun.code()); auto constants = TRY(fun.constants()); auto closure = TRY(fun.closure()); @@ -40,7 +37,7 @@ class VM { return VM(std::move(stack), std::move(fun), std::move(code), std::move(constants), std::move(closure), std::move(globals_copy), - pc, std::move(nil)); + std::move(nil)); } Result run(); @@ -82,6 +79,5 @@ class VM { Array _constants; Array _closure; Dict _globals; - uint64_t _pc; Value _res; };