shithub: sl

Download patch

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