Switch the stack frame to store current frame PC instead of parent's
This commit is contained in:
parent
f16850d26c
commit
51de7e3547
6 changed files with 56 additions and 44 deletions
|
@ -258,7 +258,7 @@ Result<PodObject*> 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();
|
||||
|
|
|
@ -302,14 +302,14 @@ Result<short> Module::cmp(const Module& rhs) const {
|
|||
return res;
|
||||
}
|
||||
|
||||
Result<StackFrame> StackFrame::create(const Value& parent, const Function& fun,
|
||||
uint64_t parent_pc) {
|
||||
Result<StackFrame> StackFrame::create(const Value& parent,
|
||||
const Function& fun) {
|
||||
auto pod = TRY(arena_alloc<PodStackFrame>());
|
||||
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> 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> 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<Value> StackFrame::parent() const {
|
|||
Result<Function> 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> StackFrame::setpc(uint64_t pc) {
|
||||
auto pod =
|
||||
TRY(arena_alloc<PodStackFrame>(sizeof(OffPtr<PodObject>) * _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> StackFrame::incpc() { return setpc(pc() + 1); }
|
||||
|
||||
Result<Value> Error::copy_value() const {
|
||||
return Value(Error(TRY(_value.copy())));
|
||||
|
|
|
@ -1118,11 +1118,12 @@ class StackFrame : public Object {
|
|||
Result<StackFrame> settop(uint64_t idx);
|
||||
Result<Value> parent() const;
|
||||
Result<Function> fun() const;
|
||||
uint64_t parent_pc() const;
|
||||
uint64_t pc() const;
|
||||
Result<StackFrame> setpc(uint64_t pc);
|
||||
Result<StackFrame> incpc();
|
||||
Result<uint64_t> size() const { return _value->size; }
|
||||
|
||||
static Result<StackFrame> create(const Value& parent, const Function& fun,
|
||||
uint64_t parent_pc);
|
||||
static Result<StackFrame> create(const Value& parent, const Function& fun);
|
||||
|
||||
Result<Array> slice(uint64_t start, uint64_t end) {
|
||||
if (start > end || end > _value->size) return ERROR(IndexOutOfRange);
|
||||
|
|
|
@ -198,7 +198,7 @@ class PodStackFrame final : public PodObject {
|
|||
|
||||
OffPtr<PodObject> parent;
|
||||
OffPtr<PodObject> fun;
|
||||
uint64_t parent_pc;
|
||||
uint64_t pc;
|
||||
uint64_t size;
|
||||
OffPtr<PodObject> data[];
|
||||
};
|
||||
|
|
48
src/vm.cpp
48
src/vm.cpp
|
@ -20,7 +20,7 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
||||
|
@ -69,9 +69,9 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
@ -81,9 +81,9 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
@ -93,9 +93,9 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
@ -109,8 +109,7 @@ Result<void> 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<void> VM::vm_call_lisp(Opcode& oc, Function& fun) {
|
|||
_constants = TRY(fun.constants());
|
||||
_closure = TRY(fun.closure());
|
||||
_fun = std::move(fun);
|
||||
_pc = 0;
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
@ -136,7 +134,7 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
||||
|
@ -164,15 +162,13 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
@ -190,20 +186,20 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
||||
Result<void> VM::vm_jump(Opcode& oc) {
|
||||
_pc += oc.arg1().arg;
|
||||
auto offset = oc.arg1().arg;
|
||||
_stack = TRY(_stack.setpc(_stack.pc() + offset));
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
|
@ -220,7 +216,7 @@ Result<void> VM::vm_make_closure(Opcode& oc) {
|
|||
|
||||
_stack = TRY(setreg(oc.arg1().arg, fun));
|
||||
|
||||
_pc++;
|
||||
_stack = TRY(_stack.incpc());
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
@ -229,7 +225,7 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
||||
|
@ -238,7 +234,7 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
||||
|
@ -247,12 +243,12 @@ Result<void> 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<void>();
|
||||
}
|
||||
|
||||
Result<void> VM::step() {
|
||||
auto opcode = TRY(_code.get(_pc));
|
||||
auto opcode = TRY(_code.get(_stack.pc()));
|
||||
if (!opcode.is<Opcode>()) return ERROR(TypeMismatch);
|
||||
Opcode& oc = *opcode.to<Opcode>();
|
||||
|
||||
|
|
10
src/vm.hpp
10
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<VM> 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<Value> run();
|
||||
|
@ -82,6 +79,5 @@ class VM {
|
|||
Array _constants;
|
||||
Array _closure;
|
||||
Dict _globals;
|
||||
uint64_t _pc;
|
||||
Value _res;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue