diff --git a/build b/build index 2c8c67e1..10e38096 100755 --- a/build +++ b/build @@ -1,3 +1,3 @@ #!/usr/bin/env bash -clang -std=gnu11 -O3 -Wall -Wno-microsoft-anon-tag -Wno-unused-function -fms-extensions $@ -o BQN src/opt/single.c -lm -# gcc -std=gnu11 -O3 -Wall -Wno-parentheses -Wno-misleading-indentation -Wno-unused-function -fms-extensions $@ -o BQN src/opt/single.c -lm +clang -std=gnu11 -O3 -Wall -Wno-microsoft-anon-tag -Wno-unused-function -fms-extensions -no-pie $@ -o BQN src/opt/single.c -lm +# gcc -std=gnu11 -O3 -Wall -Wno-parentheses -Wno-misleading-indentation -Wno-unused-function -fms-extensions -no-pie $@ -o BQN src/opt/single.c -lm diff --git a/buildg b/buildg index 3460e8b0..52db7890 100755 --- a/buildg +++ b/buildg @@ -1,3 +1,3 @@ #!/usr/bin/env bash -clang -std=gnu11 -O3 -g -Wall -Wno-microsoft-anon-tag -fms-extensions -Wno-unused-function -fno-omit-frame-pointer $@ -o BQN src/opt/single.c -lm -# gcc -std=gnu11 -O3 -g -Wall -Wno-parentheses -Wno-misleading-indentation -Wno-unused-function -fms-extensions -fno-omit-frame-pointer $@ -o BQN src/opt/single.c -lm +clang -std=gnu11 -O3 -g -Wall -Wno-microsoft-anon-tag -fms-extensions -no-pie -Wno-unused-function -fno-omit-frame-pointer $@ -o BQN src/opt/single.c -lm +# gcc -std=gnu11 -O3 -g -Wall -Wno-parentheses -Wno-misleading-indentation -Wno-unused-function -fms-extensions -no-pie -fno-omit-frame-pointer $@ -o BQN src/opt/single.c -lm diff --git a/debugBuild b/debugBuild index 75891ecf..ed2370fb 100755 --- a/debugBuild +++ b/debugBuild @@ -1,3 +1,3 @@ #!/usr/bin/env bash -clang -DDEBUG -std=gnu11 -g -Wall -Wno-microsoft-anon-tag -Wno-unused-function -fms-extensions $@ -o BQN src/opt/single.c -lm -# gcc -DDEBUG -std=gnu11 -g -Wall -Wno-parentheses -Wno-misleading-indentation -Wno-unused-function -fms-extensions $@ -o BQN src/opt/single.c -lm +clang -DDEBUG -std=gnu11 -g -Wall -Wno-microsoft-anon-tag -Wno-unused-function -fms-extensions -no-pie $@ -o BQN src/opt/single.c -lm +# gcc -DDEBUG -std=gnu11 -g -Wall -Wno-parentheses -Wno-misleading-indentation -Wno-unused-function -fms-extensions -no-pie $@ -o BQN src/opt/single.c -lm diff --git a/src/h.h b/src/h.h index e81478b2..32554936 100644 --- a/src/h.h +++ b/src/h.h @@ -101,8 +101,9 @@ #define CHR_MAX 1114111 #define U16_MAX ((u16)~(u16)0) #define U32_MAX ((u32)~(u32)0) -#define NOINLINE __attribute__ ((noinline)) -#define NORETURN __attribute__ ((noreturn)) +#define NOINLINE __attribute__((noinline)) +#define FORCE_INLINE __attribute__((always_inline)) static inline +#define NORETURN __attribute__((noreturn)) #define AUTO __auto_type #define LIKELY(X) __builtin_expect(X,1) #define RARE(X) __builtin_expect(X,0) @@ -125,22 +126,22 @@ CTR_FOR(F) #define fsizeof(T,F,E,N) (offsetof(T, F) + sizeof(E)*(N)) // type, flexible array member name, flexible array member type, item amount #define ftag(x) ((u64)(x) << 48) #define tag(v, t) b(((u64)(v)) | ftag(t)) - // .111111111110000000000000000000000000000000000000000000000000000 infinity - // .111111111111000000000000000000000000000000000000000000000000000 qNaN - // .111111111110nnn................................................ sNaN aka tagged aka not f64, if nnn≠0 - // 0111111111110................................................... direct value with no need of refcounting -static const u16 C32_TAG = 0b0111111111110001; // 0111111111110001................00000000000ccccccccccccccccccccc char -static const u16 TAG_TAG = 0b0111111111110010; // 0111111111110010................nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn special value (0=nothing, 1=undefined var, 2=bad header; 3=optimized out; 4=error?; 5=no fill) -static const u16 VAR_TAG = 0b0111111111110011; // 0111111111110011ddddddddddddddddnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn variable reference -static const u16 EXT_TAG = 0b0111111111110100; // 0111111111110100ddddddddddddddddnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn extended variable reference -static const u16 I32_TAG = 0b0111111111110111; // 0111111111110111................nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 32-bit int; unused -static const u16 MD1_TAG = 0b1111111111110010; // 1111111111110010ppppppppppppppppppppppppppppppppppppppppppppp000 1-modifier -static const u16 MD2_TAG = 0b1111111111110011; // 1111111111110011ppppppppppppppppppppppppppppppppppppppppppppp000 2-modifier -static const u16 FUN_TAG = 0b1111111111110100; // 1111111111110100ppppppppppppppppppppppppppppppppppppppppppppp000 function -static const u16 NSP_TAG = 0b1111111111110101; // 1111111111110101ppppppppppppppppppppppppppppppppppppppppppppp000 namespace maybe? -static const u16 OBJ_TAG = 0b1111111111110110; // 1111111111110110ppppppppppppppppppppppppppppppppppppppppppppp000 custom object (e.g. bigints) -static const u16 ARR_TAG = 0b1111111111110111; // 1111111111110111ppppppppppppppppppppppppppppppppppppppppppppp000 array (everything else is an atom) -static const u16 VAL_TAG = 0b1111111111110 ; // 1111111111110................................................... pointer to Value, needs refcounting + // .FF0 .111111111110000000000000000000000000000000000000000000000000000 infinity + // .FF8 .111111111111000000000000000000000000000000000000000000000000000 qNaN + // .FF. .111111111110nnn................................................ sNaN aka tagged aka not f64, if nnn≠0 + // 7FF. 0111111111110................................................... direct value with no need of refcounting +static const u16 C32_TAG = 0b0111111111110001; // 7FF1 0111111111110001................00000000000ccccccccccccccccccccc char +static const u16 TAG_TAG = 0b0111111111110010; // 7FF2 0111111111110010................nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn special value (0=nothing, 1=undefined var, 2=bad header; 3=optimized out; 4=error?; 5=no fill) +static const u16 VAR_TAG = 0b0111111111110011; // 7FF3 0111111111110011ddddddddddddddddnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn variable reference +static const u16 EXT_TAG = 0b0111111111110100; // 7FF4 0111111111110100ddddddddddddddddnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn extended variable reference +static const u16 I32_TAG = 0b0111111111110111; // 7FF7 0111111111110111................nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 32-bit int; unused +static const u16 MD1_TAG = 0b1111111111110010; // FFF2 1111111111110010ppppppppppppppppppppppppppppppppppppppppppppp000 1-modifier +static const u16 MD2_TAG = 0b1111111111110011; // FFF3 1111111111110011ppppppppppppppppppppppppppppppppppppppppppppp000 2-modifier +static const u16 FUN_TAG = 0b1111111111110100; // FFF4 1111111111110100ppppppppppppppppppppppppppppppppppppppppppppp000 function +static const u16 NSP_TAG = 0b1111111111110101; // FFF5 1111111111110101ppppppppppppppppppppppppppppppppppppppppppppp000 namespace maybe? +static const u16 OBJ_TAG = 0b1111111111110110; // FFF6 1111111111110110ppppppppppppppppppppppppppppppppppppppppppppp000 custom object (e.g. bigints) +static const u16 ARR_TAG = 0b1111111111110111; // FFF7 1111111111110111ppppppppppppppppppppppppppppppppppppppppppppp000 array (everything else is an atom) +static const u16 VAL_TAG = 0b1111111111110 ; // FFF. 1111111111110................................................... pointer to Value, needs refcounting void cbqn_init(); diff --git a/src/main.c b/src/main.c index 4cd8a130..f5e696e5 100644 --- a/src/main.c +++ b/src/main.c @@ -11,7 +11,7 @@ static void repl_init() { cbqn_init(); replPath = m_str32(U"REPL"); gc_add(replPath); Block* initBlock = bqn_comp(m_str32(U"\"(REPL initializer)\""), inc(replPath), m_f64(0)); - gsc = m_scope(initBlock->body, NULL, 0); gc_add(tag(gsc,OBJ_TAG)); + gsc = m_scope(initBlock->body, NULL, 0, 0, NULL); gc_add(tag(gsc,OBJ_TAG)); ptr_dec(initBlock); init = true; } diff --git a/src/vm.c b/src/vm.c index 9031775c..0f23cbc3 100644 --- a/src/vm.c +++ b/src/vm.c @@ -564,39 +564,22 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume #undef GS_UPD } -Scope* m_scope(Body* body, Scope* psc, u16 varAm) { // doesn't consume +Scope* m_scope(Body* body, Scope* psc, u16 varAm, i32 initVarAm, B* initVars) { // doesn't consume Scope* sc = mm_allocN(fsizeof(Scope, vars, B, varAm), t_scope); sc->body = body; ptr_inc(body); sc->psc = psc; if(psc) ptr_inc(psc); sc->varAm = varAm; sc->ext = NULL; + i32 i = 0; + while (ivars[i] = initVars[i]; i++; } + while (ivars[i++] = bi_noVar; return sc; } - -B actualExec(Block* bl, Scope* psc, i32 ga, B* svar) { // consumes svar contents - Body* body = bl->body; - u16 varAm = body->varAm; - assert(varAm>=ga); - Scope* sc = m_scope(body, psc, varAm); - i32 i = 0; - while (ivars[i] = svar[i]; i++; } - while (ivars[i++] = bi_noVar; - bool jit = USE_JIT; - // jit = body->bc[2]==m_f64(123456).u>>32; // enable JIT just for blocks starting with `123456⋄` - B r; - if (jit) { - if (!body->nvm) { - Nvm_res r = m_nvm(body); - body->nvm = r.p; - body->nvmRefs = r.refs; - } - r = evalJIT(body, sc, body->nvm); - } else { - r = evalBC(body, sc); - } +static void scope_dec(Scope* sc) { + i32 varAm = sc->varAm; if (sc->refc>1) { usz innerRef = 1; - for (i = 0; i < varAm; i++) { + for (i32 i = 0; i < varAm; i++) { B c = sc->vars[i]; if (isVal(c) && v(c)->refc==1) { u8 t = v(c)->type; @@ -608,21 +591,45 @@ B actualExec(Block* bl, Scope* psc, i32 ga, B* svar) { // consumes svar contents assert(innerRef<=sc->refc); if (innerRef==sc->refc) { value_free((Value*)sc); - return r; + return; } } ptr_dec(sc); +} + +B execBodyInline(Body* body, Scope* sc) { + bool jit = USE_JIT; + // jit = body->bc[2]==m_f64(123456).u>>32; // enable JIT just for blocks starting with `123456⋄` + if (jit) { + if (!body->nvm) { + Nvm_res r = m_nvm(body); + body->nvm = r.p; + body->nvmRefs = r.refs; + } + return evalJIT(body, sc, body->nvm); + } else { + return evalBC(body, sc); + } +} + +FORCE_INLINE B execBlock(Block* bl, Scope* psc, i32 ga, B* svar) { // consumes svar contents + Body* body = bl->body; + u16 varAm = body->varAm; + assert(varAm>=ga); + Scope* sc = m_scope(body, psc, varAm, ga, svar); + B r = execBodyInline(body, sc); + scope_dec(sc); return r; } -B funBl_c1(B t, B x) { FunBlock* b=c(FunBlock, t ); ptr_inc(b); return actualExec(b->bl, b->sc, 3, (B[]){t, x, bi_N }); } -B funBl_c2(B t, B w, B x) { FunBlock* b=c(FunBlock, t ); ptr_inc(b); return actualExec(b->bl, b->sc, 3, (B[]){t, x, w }); } -B md1Bl_c1(B D, B x) { Md1D* d=c(Md1D,D); Md1Block* b=c(Md1Block, d->m1); ptr_inc(d); return actualExec(b->bl, b->sc, 5, (B[]){D, x, bi_N, inc(d->m1), inc(d->f) }); } -B md1Bl_c2(B D, B w, B x) { Md1D* d=c(Md1D,D); Md1Block* b=c(Md1Block, d->m1); ptr_inc(d); return actualExec(b->bl, b->sc, 5, (B[]){D, x, w , inc(d->m1), inc(d->f) }); } -B md2Bl_c1(B D, B x) { Md2D* d=c(Md2D,D); Md2Block* b=c(Md2Block, d->m2); ptr_inc(d); return actualExec(b->bl, b->sc, 6, (B[]){D, x, bi_N, inc(d->m2), inc(d->f), inc(d->g)}); } -B md2Bl_c2(B D, B w, B x) { Md2D* d=c(Md2D,D); Md2Block* b=c(Md2Block, d->m2); ptr_inc(d); return actualExec(b->bl, b->sc, 6, (B[]){D, x, w , inc(d->m2), inc(d->f), inc(d->g)}); } +B funBl_c1(B t, B x) { FunBlock* b=c(FunBlock, t ); ptr_inc(b); return execBlock(b->bl, b->sc, 3, (B[]){t, x, bi_N }); } +B funBl_c2(B t, B w, B x) { FunBlock* b=c(FunBlock, t ); ptr_inc(b); return execBlock(b->bl, b->sc, 3, (B[]){t, x, w }); } +B md1Bl_c1(B D, B x) { Md1D* d=c(Md1D,D); Md1Block* b=c(Md1Block, d->m1); ptr_inc(d); return execBlock(b->bl, b->sc, 5, (B[]){D, x, bi_N, inc(d->m1), inc(d->f) }); } +B md1Bl_c2(B D, B w, B x) { Md1D* d=c(Md1D,D); Md1Block* b=c(Md1Block, d->m1); ptr_inc(d); return execBlock(b->bl, b->sc, 5, (B[]){D, x, w , inc(d->m1), inc(d->f) }); } +B md2Bl_c1(B D, B x) { Md2D* d=c(Md2D,D); Md2Block* b=c(Md2Block, d->m2); ptr_inc(d); return execBlock(b->bl, b->sc, 6, (B[]){D, x, bi_N, inc(d->m2), inc(d->f), inc(d->g)}); } +B md2Bl_c2(B D, B w, B x) { Md2D* d=c(Md2D,D); Md2Block* b=c(Md2Block, d->m2); ptr_inc(d); return execBlock(b->bl, b->sc, 6, (B[]){D, x, w , inc(d->m2), inc(d->f), inc(d->g)}); } B m_funBlock(Block* bl, Scope* psc) { // doesn't consume anything - if (bl->imm) return actualExec(bl, psc, 0, NULL); + if (bl->imm) return execBlock(bl, psc, 0, NULL); B r = mm_alloc(sizeof(FunBlock), t_fun_block, ftag(FUN_TAG)); c(FunBlock, r)->bl = bl; ptr_inc(bl); c(FunBlock, r)->sc = psc; ptr_inc(psc); @@ -720,8 +727,8 @@ void md2Bl_print(B x) { printf("{2-modifier block}"); } B block_decompose(B x) { return m_v2(m_i32(1), x); } -B bl_m1d(B m, B f ) { Md1Block* c = c(Md1Block,m); return c->bl->imm? actualExec(c(Md1Block, m)->bl, c(Md1Block, m)->sc, 2, (B[]){m, f }) : m_md1D(m,f ); } -B bl_m2d(B m, B f, B g) { Md2Block* c = c(Md2Block,m); return c->bl->imm? actualExec(c(Md2Block, m)->bl, c(Md2Block, m)->sc, 3, (B[]){m, f, g}) : m_md2D(m,f,g); } +B bl_m1d(B m, B f ) { Md1Block* c = c(Md1Block,m); return c->bl->imm? execBlock(c(Md1Block, m)->bl, c(Md1Block, m)->sc, 2, (B[]){m, f }) : m_md1D(m,f ); } +B bl_m2d(B m, B f, B g) { Md2Block* c = c(Md2Block,m); return c->bl->imm? execBlock(c(Md2Block, m)->bl, c(Md2Block, m)->sc, 3, (B[]){m, f, g}) : m_md2D(m,f,g); } void allocStack(void** curr, void** start, void** end, i32 elSize, i32 count) { usz pageSize = sysconf(_SC_PAGESIZE); diff --git a/src/vm.h b/src/vm.h index e99b9804..a1af45a8 100644 --- a/src/vm.h +++ b/src/vm.h @@ -104,7 +104,7 @@ struct Scope { Block* bqn_comp(B str, B path, B args); Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl); Block* compile(B bcq, B objs, B blocksq, B indices, B tokenInfo, B src, Scope* sc); -Scope* m_scope(Body* body, Scope* psc, u16 varAm); +Scope* m_scope(Body* body, Scope* psc, u16 varAm, i32 initVarAm, B* initVars); B evalBC(Body* b, Scope* sc); // doesn't consume; executes bytecode of the body directly in the scope u32* nextBC(u32* p);