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;
}
Result<StackFrame> StackFrame::create(const Value& parent,
const Function& fun) {
Result<StackFrame> StackFrame::create(const Value& parent, const Value& fun) {
auto pod = TRY(arena_alloc<PodStackFrame>());
pod->header.tag = Tag::StackFrame;
@ -319,6 +318,10 @@ Result<Value> StackFrame::copy_value() const {
return Value(StackFrame(TRY(_value.copy())));
}
Result<StackFrame> StackFrame::copy() const {
return StackFrame(TRY(_value.copy()));
}
Result<Value> StackFrame::get(uint64_t idx) const {
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)));
}
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));
pod->header.tag = Tag::StackFrame;
@ -376,8 +379,8 @@ Result<StackFrame> StackFrame::settop(uint64_t idx) {
Result<Value> StackFrame::parent() const {
return Value::create(_value->parent.get());
}
Result<Function> StackFrame::fun() const {
return Function::create((PodFunction*)_value->fun.get());
Result<Value> StackFrame::fun() const {
return Value::create(_value->fun.get());
}
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::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 {
return Value(Error(TRY(_value.copy())));
}

View file

@ -1115,17 +1115,17 @@ class StackFrame : public Object {
using Object::get;
Result<Value> get(uint64_t idx) const;
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<Function> fun() const;
Result<Value> fun() 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);
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);
uint64_t res_size = end - start;
auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(PodObject*)));
@ -1138,6 +1138,9 @@ class StackFrame : public Object {
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;
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,
const Value& expr) {
Context ctx = TRY(Context::create(context));
ctx.maxreg = 1; // Reserve the slot for function itself
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);
}
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) {
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_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<void>();
}
@ -154,21 +138,14 @@ Result<void> VM::vm_call(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_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<void>();
}
@ -180,18 +157,9 @@ Result<void> VM::vm_ret(Opcode& oc) {
return ERROR(EndOfProgram);
}
auto res = TRY(getreg((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 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<void>();
@ -223,7 +191,7 @@ Result<void> VM::vm_make_closure(Opcode& oc) {
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));
Value val = TRY(TRY(closure()).get((uint64_t)oc.arg2().arg));
_stack = TRY(setreg(acc, val));
_stack = TRY(_stack.incpc());
return Result<void>();
@ -247,8 +215,8 @@ Result<void> VM::vm_global_store(Opcode& oc) {
return Result<void>();
}
Result<void> VM::step() {
auto opcode = TRY(_code.get(_stack.pc()));
Result<void> VM::step_bytecode() {
auto opcode = TRY(TRY(code()).get(_stack.pc()));
if (!opcode.is<Opcode>()) return ERROR(TypeMismatch);
Opcode& oc = *opcode.to<Opcode>();
@ -310,6 +278,19 @@ Result<void> VM::step() {
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() {
while (true) {
auto rc = step();

View file

@ -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<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 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<Value> run();
Result<void> step();
Result<void> step_bytecode();
Result<void> step_native();
Result<void> vm_mov(Opcode& oc);
Result<void> vm_add(Opcode& oc);
Result<void> vm_mul(Opcode& oc);
@ -72,12 +69,24 @@ class VM {
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:
StackFrame _stack;
Function _fun;
Array _code;
Array _constants;
Array _closure;
Dict _globals;
Value _res;
};