From 83382cb1b46eb17f94f16fbbf05b5e471284d797 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 29 Jun 2024 13:12:34 +0100 Subject: add proper tail calls --- vm.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'vm.c') diff --git a/vm.c b/vm.c index 500b4bf..4a65832 100644 --- a/vm.c +++ b/vm.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "val.h" #include "vm.h" @@ -174,6 +175,7 @@ int runvm(State *S) { case OP_TRUE: PUSH(VAL_TRUE); break; case OP_FALSE: PUSH(VAL_FALSE); break; + case OP_TAILCALL: case OP_CALL: { // nargs + 1 = function and args uint8_t len = RBYTE(); @@ -185,14 +187,27 @@ int runvm(State *S) { CHECK(nargs == func->arity, "func needs exactly %d args, but got %d",func->arity,nargs); CHECK(th->rsp < MAXDEPTH, "rstack overflow"); - StackFrame *sf = &th->rstack[th->rsp++]; - sf->ip = th->ip; - sf->ch = th->ch; - sf->fp = th->fp; - - th->ip = 0; - th->ch = &func->ch; - th->fp = th->sp - len; + if (instr != OP_TAILCALL) { + StackFrame *sf = &th->rstack[th->rsp++]; + sf->ip = th->ip; + sf->ch = th->ch; + sf->fp = th->fp; + + th->ip = 0; + th->ch = &func->ch; + th->fp = th->sp - len; + } else { + // xxx might invalidate open upvalues + memmove(&th->stack[th->fp], &th->stack[th->sp - len], len*sizeof(Val)); + th->sp = th->fp + len; + th->ip = 0; + th->ch = &func->ch; + + StackFrame *cur_sf = &th->rstack[th->rsp]; + cur_sf->ip = th->ip; + cur_sf->ch = th->ch; + cur_sf->fp = th->fp; + } } else if (IS_CFUNC(callee)) { Val *firstarg = &th->stack[th->sp - nargs]; Val res = AS_CFUNC(callee)(S, nargs, firstarg); @@ -247,6 +262,8 @@ int runvm(State *S) { objarr_append(S, arr, v); break; } + default: + ERROR("unknown opcode"); } -- cgit v1.2.3