ref: db710d46c1f43cf7e23ea8ed278454b772a2cea3
parent: 3f9ca6ff8e3a23a7912e4ccc879025bd6feb2b95
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Mar 21 19:16:57 EDT 2023
vm: reduce branching a bit
--- a/flisp.c
+++ b/flisp.c
@@ -895,8 +895,6 @@
#define GET_INT16(a) (*(int16_t*)a)
#define PUT_INT32(a,i) (*(int32_t*)(a) = (int32_t)(i))
#endif
-#define SWAP_INT32(a) (*(int32_t*)(a) = bswap_32(*(int32_t*)(a)))
-#define SWAP_INT16(a) (*(int16_t*)(a) = bswap_16(*(int16_t*)(a)))
#define OP(x) case x:
#define NEXT_OP goto next_op
@@ -960,7 +958,10 @@
switch (op) {
OP(OP_ARGC)
n = *ip++;
- do_argc:
+ if (0) {
+ OP(OP_LARGC)
+ n = GET_INT32(ip); ip+=4;
+ }
if (nargs != n) {
if (nargs > n)
lerrorf(ArgError, "apply: too many arguments");
@@ -970,7 +971,10 @@
NEXT_OP;
OP(OP_VARGC)
i = *ip++;
- do_vargc:
+ if (0) {
+ OP(OP_LVARGC)
+ i = GET_INT32(ip); ip+=4;
+ }
s = (fixnum_t)nargs - (fixnum_t)i;
if (s > 0) {
v = list(&Stack[bp+i], s);
@@ -998,12 +1002,6 @@
}
nargs = i+1;
NEXT_OP;
- OP(OP_LARGC)
- n = GET_INT32(ip); ip+=4;
- goto do_argc;
- OP(OP_LVARGC)
- i = GET_INT32(ip); ip+=4;
- goto do_vargc;
OP(OP_BRBOUND)
i = GET_INT32(ip); ip+=4;
if (captured)
@@ -1015,8 +1013,13 @@
NEXT_OP;
OP(OP_DUP) SP++; Stack[SP-1] = Stack[SP-2]; NEXT_OP;
OP(OP_POP) POPN(1); NEXT_OP;
+ OP(OP_TCALLL)
+ n = GET_INT32(ip);
+ ip+=4;
+ if (0) {
OP(OP_TCALL)
- n = *ip++; // nargs
+ n = *ip++; // nargs
+ }
do_tcall:
func = Stack[SP-n-1];
if (tag(func) == TAG_FUNCTION) {
@@ -1064,8 +1067,13 @@
}
type_error("apply", "function", func);
// WARNING: repeated code ahead
+ OP(OP_CALLL)
+ n = GET_INT32(ip);
+ ip+=4;
+ if (0) {
OP(OP_CALL)
- n = *ip++; // nargs
+ n = *ip++; // nargs
+ }
do_call:
func = Stack[SP-n-1];
if (tag(func) == TAG_FUNCTION) {
@@ -1109,8 +1117,6 @@
NEXT_OP;
}
type_error("apply", "function", func);
- OP(OP_TCALLL) n = GET_INT32(ip); ip+=4; goto do_tcall;
- OP(OP_CALLL) n = GET_INT32(ip); ip+=4; goto do_call;
OP(OP_JMP) ip += GET_INT16(ip); NEXT_OP;
OP(OP_BRF)
v = POP();
@@ -1759,182 +1765,21 @@
}
}
-static uint32_t compute_maxstack(uint8_t *code, size_t len, int bswap)
-{
- uint8_t *ip = code+4, *end = code+len;
- uint8_t op;
- uint32_t i, n, sp = 0, maxsp = 0;
+#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) (*(int32_t*)(a) = bswap_32(*(int32_t*)(a)))
+#define SWAP_INT16(a) (*(int16_t*)(a) = bswap_16(*(int16_t*)(a)))
+#define compute_maxstack compute_maxstack_swap
+#include "maxstack.inc"
+#undef compute_maxstack
+#else
+#endif
- while (1) {
- if ((int32_t)sp > (int32_t)maxsp) maxsp = sp;
- if (ip >= end) break;
- op = *ip++;
- switch (op) {
- case OP_ARGC:
- n = *ip++;
- USED(n);
- break;
- case OP_VARGC:
- n = *ip++;
- sp += (n+2);
- break;
- case OP_LARGC:
- if (bswap) SWAP_INT32(ip);
- n = GET_INT32(ip); ip+=4;
- USED(n);
- break;
- case OP_LVARGC:
- if (bswap) SWAP_INT32(ip);
- n = GET_INT32(ip); ip+=4;
- sp += (n+2);
- break;
- case OP_OPTARGS:
- if (bswap) SWAP_INT32(ip);
- i = GET_INT32(ip); ip+=4;
- if (bswap) SWAP_INT32(ip);
- n = abs(GET_INT32(ip)); ip+=4;
- sp += (n-i);
- break;
- case OP_KEYARGS:
- if (bswap) SWAP_INT32(ip);
- i = GET_INT32(ip); ip+=4;
- if (bswap) SWAP_INT32(ip);
- n = GET_INT32(ip); ip+=4;
- USED(n);
- if (bswap) SWAP_INT32(ip);
- n = abs(GET_INT32(ip)); ip+=4;
- sp += (n-i);
- break;
- case OP_BRBOUND:
- if (bswap) SWAP_INT32(ip);
- ip+=4;
- sp++;
- break;
-
- case OP_TCALL: case OP_CALL:
- n = *ip++; // nargs
- sp -= n;
- break;
- case OP_TCALLL: case OP_CALLL:
- if (bswap) SWAP_INT32(ip);
- n = GET_INT32(ip); ip+=4;
- sp -= n;
- break;
- case OP_JMP:
- if (bswap) SWAP_INT16(ip);
- ip += 2; break;
- case OP_JMPL:
- if (bswap) SWAP_INT32(ip);
- ip += 4; break;
- case OP_BRF: case OP_BRT:
- if (bswap) SWAP_INT16(ip);
- ip+=2;
- sp--;
- break;
- case OP_BRFL: case OP_BRTL:
- if (bswap) SWAP_INT32(ip);
- ip += 4;
- sp--;
- break;
- case OP_BRNE:
- if (bswap) SWAP_INT16(ip);
- ip += 2;
- sp -= 2;
- break;
- case OP_BRNEL:
- if (bswap) SWAP_INT32(ip);
- ip += 4;
- sp -= 2;
- break;
- case OP_BRNN: case OP_BRN:
- if (bswap) SWAP_INT16(ip);
- ip += 2;
- sp--;
- break;
- case OP_BRNNL: case OP_BRNL:
- if (bswap) SWAP_INT32(ip);
- ip += 4;
- sp--;
- break;
- case OP_RET: sp--; break;
-
- case OP_CONS: case OP_SETCAR: case OP_SETCDR: case OP_POP:
- case OP_EQ: case OP_EQV: case OP_EQUAL: case OP_ADD2: case OP_SUB2:
- case OP_IDIV: case OP_NUMEQ: case OP_LT: case OP_COMPARE:
- case OP_AREF: case OP_TRYCATCH:
- sp--;
- break;
-
- case OP_PAIRP: case OP_ATOMP: case OP_NOT: case OP_NULLP:
- case OP_BOOLEANP: case OP_SYMBOLP: case OP_NUMBERP: case OP_FIXNUMP:
- case OP_BOUNDP: case OP_BUILTINP: case OP_FUNCTIONP: case OP_VECTORP:
- case OP_NOP: case OP_CAR: case OP_CDR: case OP_NEG: case OP_CLOSURE:
- break;
-
- case OP_TAPPLY: case OP_APPLY:
- n = *ip++;
- sp -= (n-1);
- break;
-
- case OP_LIST: case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
- case OP_VECTOR:
- n = *ip++;
- sp -= (n-1);
- break;
-
- case OP_ASET:
- sp -= 2;
- break;
- case OP_FOR:
- if (sp+2 > maxsp) maxsp = sp+2;
- sp -=2;
- break;
-
- case OP_LOADT: case OP_LOADF: case OP_LOADNIL: case OP_LOAD0:
- case OP_LOAD1: case OP_LOADA0: case OP_LOADA1: case OP_LOADC00:
- case OP_LOADC01: case OP_DUP:
- sp++;
- break;
-
- case OP_LOADI8: case OP_LOADV: case OP_LOADG: case OP_LOADA:
- ip++;
- sp++;
- break;
- case OP_LOADVL: case OP_LOADGL: case OP_LOADAL:
- if (bswap) SWAP_INT32(ip);
- ip+=4;
- sp++;
- break;
-
- case OP_SETG: case OP_SETA:
- ip++;
- break;
- case OP_SETGL: case OP_SETAL:
- if (bswap) SWAP_INT32(ip);
- ip+=4;
- break;
-
- case OP_LOADC: ip+=2; sp++; break;
- case OP_SETC:
- ip+=2;
- break;
- case OP_LOADCL:
- if (bswap) SWAP_INT32(ip);
- ip+=4;
- if (bswap) SWAP_INT32(ip);
- ip+=4;
- sp++; break;
- case OP_SETCL:
- if (bswap) SWAP_INT32(ip);
- ip+=4;
- if (bswap) SWAP_INT32(ip);
- ip+=4;
- break;
- }
- }
- return maxsp+5;
-}
-
// top = top frame pointer to start at
static value_t _stacktrace(uint32_t top)
{
@@ -1989,19 +1834,21 @@
cvalue_t *arr = (cvalue_t*)ptr(args[0]);
cv_pin(arr);
char *data = cv_data(arr);
- int swap = 0;
+ uint32_t ms;
if ((uint8_t)data[4] >= N_OPCODES) {
// read syntax, shifted 48 for compact text representation
size_t i, sz = cv_len(arr);
for(i=0; i < sz; i++)
data[i] -= 48;
- }
- else {
#if BYTE_ORDER == BIG_ENDIAN
- swap = 1;
-#endif
+ ms = compute_maxstack((uint8_t*)data, cv_len(arr));
+ } else {
+ ms = compute_maxstack_swap((uint8_t*)data, cv_len(arr));
}
- uint32_t ms = compute_maxstack((uint8_t*)data, cv_len(arr), swap);
+#else
+ }
+ ms = compute_maxstack((uint8_t*)data, cv_len(arr));
+#endif
PUT_INT32(data, ms);
function_t *fn = (function_t*)alloc_words(4);
value_t fv = tagptr(fn, TAG_FUNCTION);
--- /dev/null
+++ b/maxstack.inc
@@ -1,0 +1,175 @@
+static uint32_t compute_maxstack(uint8_t *code, size_t len)
+{
+ uint8_t *ip = code+4, *end = code+len;
+ uint8_t op;
+ uint32_t i, n, sp = 0, maxsp = 0;
+
+ while (1) {
+ if ((int32_t)sp > (int32_t)maxsp) maxsp = sp;
+ if (ip >= end) break;
+ op = *ip++;
+ switch (op) {
+ case OP_ARGC:
+ n = *ip++;
+ USED(n);
+ break;
+ case OP_VARGC:
+ n = *ip++;
+ sp += (n+2);
+ break;
+ case OP_LARGC:
+ SWAP_INT32(ip);
+ n = GET_INT32(ip); ip+=4;
+ USED(n);
+ break;
+ case OP_LVARGC:
+ 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);
+ n = GET_INT32(ip); ip+=4;
+ USED(n);
+ 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_TCALL: case OP_CALL:
+ n = *ip++; // nargs
+ sp -= n;
+ 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; break;
+ case OP_JMPL:
+ SWAP_INT32(ip);
+ ip += 4; break;
+ case OP_BRF: case OP_BRT:
+ SWAP_INT16(ip);
+ ip+=2;
+ sp--;
+ break;
+ case OP_BRFL: case OP_BRTL:
+ SWAP_INT32(ip);
+ ip += 4;
+ sp--;
+ break;
+ 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;
+ sp--;
+ break;
+ case OP_RET: sp--; break;
+
+ case OP_CONS: case OP_SETCAR: case OP_SETCDR: case OP_POP:
+ case OP_EQ: case OP_EQV: case OP_EQUAL: case OP_ADD2: case OP_SUB2:
+ case OP_IDIV: case OP_NUMEQ: case OP_LT: case OP_COMPARE:
+ case OP_AREF: case OP_TRYCATCH:
+ sp--;
+ break;
+
+ case OP_PAIRP: case OP_ATOMP: case OP_NOT: case OP_NULLP:
+ case OP_BOOLEANP: case OP_SYMBOLP: case OP_NUMBERP: case OP_FIXNUMP:
+ case OP_BOUNDP: case OP_BUILTINP: case OP_FUNCTIONP: case OP_VECTORP:
+ case OP_NOP: case OP_CAR: case OP_CDR: case OP_NEG: case OP_CLOSURE:
+ break;
+
+ case OP_TAPPLY: case OP_APPLY:
+ n = *ip++;
+ sp -= (n-1);
+ break;
+
+ case OP_LIST: case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
+ case OP_VECTOR:
+ n = *ip++;
+ sp -= (n-1);
+ break;
+
+ case OP_ASET:
+ sp -= 2;
+ break;
+ case OP_FOR:
+ if (sp+2 > maxsp) maxsp = sp+2;
+ sp -=2;
+ break;
+
+ case OP_LOADT: case OP_LOADF: case OP_LOADNIL: case OP_LOAD0:
+ case OP_LOAD1: case OP_LOADA0: case OP_LOADA1: case OP_LOADC00:
+ case OP_LOADC01: case OP_DUP:
+ sp++;
+ break;
+
+ case OP_LOADI8: case OP_LOADV: case OP_LOADG: case OP_LOADA:
+ ip++;
+ sp++;
+ break;
+ case OP_LOADVL: case OP_LOADGL: case OP_LOADAL:
+ SWAP_INT32(ip);
+ ip+=4;
+ sp++;
+ break;
+
+ case OP_SETG: case OP_SETA:
+ ip++;
+ break;
+ case OP_SETGL: case OP_SETAL:
+ SWAP_INT32(ip);
+ ip+=4;
+ break;
+
+ case OP_LOADC: ip+=2; sp++; break;
+ case OP_SETC:
+ ip+=2;
+ break;
+ case OP_LOADCL:
+ SWAP_INT32(ip);
+ ip+=4;
+ SWAP_INT32(ip);
+ ip+=4;
+ sp++; break;
+ case OP_SETCL:
+ SWAP_INT32(ip);
+ ip+=4;
+ SWAP_INT32(ip);
+ ip+=4;
+ break;
+ }
+ }
+ return maxsp+5;
+}