ref: a633177c14382eeb647f6dc0857d255548e9ea8b
parent: e945ea00f4c0374dc61918499d8e997927b7dbcc
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Feb 11 05:21:33 EST 2025
get rid of "max stack" logic Just allocate enough to do a call. This removes a ton of logic, shaves off 4 bytes per every function and speeds up the VM a bit.
binary files a/boot/flisp.boot.builtin b/boot/flisp.boot.builtin differ
--- a/mkfile
+++ b/mkfile
@@ -65,7 +65,7 @@
`{ls `{echo $OFILES | sed 's/\.'$O'/.c/g'} >[2]/dev/null} | sort >$target
src/cvalues.$O: src/fl_arith_any.inc
-src/flisp.$O: src/maxstack.inc src/vm.inc
+src/flisp.$O: src/vm.inc
src/equalhash.$O: src/htable.inc
src/ptrhash.$O: src/htable.inc
--- a/src/compiler.lsp
+++ b/src/compiler.lsp
@@ -89,7 +89,6 @@
(bcode (buffer))
(vi nil)
(nxt nil))
- (io-write bcode #int32(-1))
(while (< i n)
(begin
(set! vi (aref v i))
--- a/src/flisp.c
+++ b/src/flisp.c
@@ -846,20 +846,9 @@
#if BYTE_ORDER == LITTLE_ENDIAN && defined(MEM_UNALIGNED_ACCESS)
#define GET_INT32(a) *(const int32_t*)(a)
#define GET_INT16(a) *(const int16_t*)(a)
-#define PUT_INT32(a, i) \
- do{ \
- *(uint32_t*)(a) = (uint32_t)(i); \
- }while(0)
#else
#define GET_INT32(a) (int32_t)((a)[0]<<0 | (a)[1]<<8 | (a)[2]<<16 | (uint32_t)(a)[3]<<24)
#define GET_INT16(a) (int16_t)((a)[0]<<0 | (a)[1]<<8)
-#define PUT_INT32(a, i) \
- do{ \
- ((uint8_t*)(a))[0] = (uint32_t)(i)>>0; \
- ((uint8_t*)(a))[1] = (uint32_t)(i)>>8; \
- ((uint8_t*)(a))[2] = (uint32_t)(i)>>16; \
- ((uint8_t*)(a))[3] = (uint32_t)(i)>>24; \
- }while(0)
#endif
/*
@@ -899,14 +888,13 @@
USED(n);
USED(v);
apply_cl_top:
+ i = FL(sp)+5+2;
+ while(i >= FL(nstack))
+ fl_grow_stack();
bp = FL(sp)-nargs;
fn = (function_t*)ptr(FL(stack)[bp-1]);
ip = cvalue_data(fn->bcode);
assert(!ismanaged((uintptr_t)ip));
- i = FL(sp)+GET_INT32(ip);
- ip += 4;
- while(i >= FL(nstack))
- fl_grow_stack();
PUSH(fn->env);
PUSH(FL(curr_frame));
@@ -948,31 +936,6 @@
#endif
}
-#define SWAP_INT32(a)
-#define SWAP_INT16(a)
-#include "maxstack.inc"
-
-#if BYTE_ORDER == BIG_ENDIAN
-#undef SWAP_INT32
-#undef SWAP_INT16
-#define SWAP_INT32(a) \
- do{ \
- uint8_t *x = (void*)a, y; \
- y = x[0]; x[0] = x[3]; x[3] = y; \
- y = x[1]; x[1] = x[2]; x[2] = y; \
- }while(0)
-#define SWAP_INT16(a) \
- do{ \
- uint8_t *x = (void*)a, y; \
- y = x[0]; x[0] = x[1]; x[1] = y; \
- }while(0)
-#define compute_maxstack compute_maxstack_swap
-#include "maxstack.inc"
-#undef compute_maxstack
-#else
-#define compute_maxstack_swap compute_maxstack
-#endif
-
// top = top frame pointer to start at
static value_t
_stacktrace(uint32_t top)
@@ -1026,19 +989,12 @@
cvalue_t *arr = ptr(args[0]);
cv_pin(arr);
uint8_t *data = cv_data(arr);
- bool printed = data[4] >= N_OPCODES; /* first is always arg count check */
- if(printed){
+ if(FL(loading)){
// read syntax, shifted 48 for compact text representation
size_t i, sz = cv_len(arr);
for(i = 0; i < sz; i++)
data[i] -= 48;
}
- int ms = GET_INT32(data);
- if(ms < 0){
- if((ms = (printed ? compute_maxstack : compute_maxstack_swap)(data, cv_len(arr))) < 0)
- lerrorf(FL_ArgError, "invalid bytecode");
- PUT_INT32(data, ms);
- }
function_t *fn = alloc_words(sizeof(function_t)/sizeof(value_t));
value_t fv = tagptr(fn, TAG_FUNCTION);
fn->bcode = args[0];
@@ -1419,6 +1375,7 @@
uint32_t saveSP;
symbol_t *sym;
+ FL(loading) = true;
PUSH(sys_image_iostream);
saveSP = FL(sp);
FL_TRY{
@@ -1453,5 +1410,6 @@
}
ios_close(value2c(ios_t*, FL(stack)[FL(sp)-1]));
POPN(1);
+ FL(loading) = false;
return 0;
}
--- a/src/flisp.h
+++ b/src/flisp.h
@@ -409,6 +409,7 @@
char gsname[2][16];
int gsnameno;
+ bool loading;
bool exiting;
bool grew;
--- a/src/maxstack.inc
+++ /dev/null
@@ -1,154 +1,0 @@
-fl_purefn
-static int
-compute_maxstack(uint8_t *code, size_t len)
-{
- uint8_t *ip = code+4, *end = code+len;
- int i, n, sp = 0, maxsp = 0;
-
- while(ip < end){
- opcode_t op = *ip++;
- if(op >= N_OPCODES)
- return -1;
- switch(op){
- case OP_LOADA: case OP_LOADI8: case OP_LOADV: case OP_LOADG:
- ip++; // fallthrough
- case OP_LOADA0: case OP_LOADA1:
- case OP_DUP: case OP_LOADT: case OP_LOADNIL: case OP_LOADVOID:
- case OP_LOAD0:
- case OP_LOAD1: case OP_LOADC0:
- case OP_LOADC1:
- sp++;
- break;
-
- case OP_POP: case OP_RET:
- case OP_CONS: case OP_SETCAR: case OP_SETCDR:
- case OP_EQ: case OP_EQV: case OP_EQUAL: case OP_ADD2: case OP_SUB2:
- case OP_IDIV: case OP_COMPARE:
- case OP_AREF2: case OP_TRYCATCH:
- sp--;
- break;
-
- case OP_AREF:
- n = 2 + *ip++;
- sp -= n;
- break;
-
- case OP_ARGC: case OP_SETG: case OP_SETA: case OP_BOX:
- ip++;
- continue;
-
- case OP_TCALL: case OP_CALL: case OP_CLOSURE: case OP_SHIFT:
- n = *ip++; // nargs
- sp -= n;
- break;
-
- case OP_LOADVL: case OP_LOADGL: case OP_LOADAL:
- sp++; // fallthrough
- case OP_SETGL: case OP_SETAL: case OP_ARGCL: case OP_BOXL:
- SWAP_INT32(ip);
- ip += 4;
- break;
-
- case OP_LOADC:
- sp++;
- ip++;
- break;
-
- case OP_VARGC:
- n = *ip++;
- sp += n+2;
- break;
- case OP_VARGCL:
- SWAP_INT32(ip);
- n = GET_INT32(ip); ip += 4;
- sp += n+2;
- break;
- case OP_OPTARGS:
- SWAP_INT32(ip);
- i = GET_INT32(ip); ip += 4;
- SWAP_INT32(ip);
- n = abs(GET_INT32(ip)); ip += 4;
- sp += n-i;
- break;
- case OP_KEYARGS:
- SWAP_INT32(ip);
- i = GET_INT32(ip); ip += 4;
- SWAP_INT32(ip);
- ip += 4;
- SWAP_INT32(ip);
- n = abs(GET_INT32(ip)); ip += 4;
- sp += n-i;
- break;
- case OP_BRBOUND:
- SWAP_INT32(ip);
- ip += 4;
- sp++;
- break;
- case OP_TCALLL: case OP_CALLL:
- SWAP_INT32(ip);
- n = GET_INT32(ip); ip+=4;
- sp -= n;
- break;
- case OP_JMP:
- SWAP_INT16(ip);
- ip += 2;
- continue;
- case OP_JMPL:
- SWAP_INT32(ip);
- ip += 4;
- continue;
- case OP_BRNE:
- SWAP_INT16(ip);
- ip += 2;
- sp -= 2;
- break;
- case OP_BRNEL:
- SWAP_INT32(ip);
- ip += 4;
- sp -= 2;
- break;
- case OP_BRNN: case OP_BRN:
- SWAP_INT16(ip);
- ip += 2;
- sp--;
- break;
- case OP_BRNNL: case OP_BRNL:
- SWAP_INT32(ip);
- ip += 4; // fallthrough
- case OP_TAPPLY: case OP_APPLY:
- case OP_LIST: case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
- case OP_VECTOR: case OP_LT: case OP_NUMEQ:
- n = *ip++;
- sp -= n-1;
- break;
-
- case OP_FOR:
- if(maxsp < sp+2)
- maxsp = sp+2; // fallthrough
- case OP_ASET:
- sp -= 2;
- break;
-
- case OP_LOADCL:
- sp++; // fallthrough
- SWAP_INT32(ip);
- ip += 4;
- break;
-
- case OP_CAR: case OP_CDR: case OP_CADR:
- case OP_NOT: case OP_NEG: case OP_NUMBERP:
- case OP_CONSP: case OP_ATOMP: case OP_SYMBOLP:
- case OP_FIXNUMP: case OP_BOUNDP: case OP_BUILTINP:
- case OP_FUNCTIONP: case OP_VECTORP: case OP_NANP:
- continue;
-
- case OP_EOF_OBJECT: case N_OPCODES:
- return -1;
- }
- if((int32_t)sp > (int32_t)maxsp)
- maxsp = sp;
- }
- assert(ip == end);
- assert(maxsp >= 0);
- return maxsp+4;
-}