Switch the stack frame to store current frame PC instead of parent's

This commit is contained in:
Konstantin Nazarov 2024-09-13 21:15:57 +01:00
parent f16850d26c
commit 51de7e3547
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
6 changed files with 56 additions and 44 deletions

View file

@ -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();

View file

@ -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())));

View file

@ -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);

View file

@ -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[];
};

View file

@ -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>();

View file

@ -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;
};