move TAlloc/TStack around, immediate functions

This commit is contained in:
dzaima 2021-06-15 01:20:32 +03:00
parent d2a1d7c329
commit 1afe46b393
15 changed files with 236 additions and 78 deletions

View File

@ -1,6 +1,7 @@
#include "../core.h"
#include "../utils/hash.h"
#include "../utils/mut.h"
#include "../utils/talloc.h"
#include "../nfns.h"

View File

@ -1,5 +1,6 @@
#include "../core.h"
#include "../utils/builtins.h"
#include "../utils/talloc.h"
B md2BI_uc1(B t, B o, B f, B g, B x) { return c(BMd2,t)->uc1(t, o, f, g, x); }
B md2BI_ucw(B t, B o, B f, B g, B w, B x) { return c(BMd2,t)->ucw(t, o, f, g, w, x); }

View File

@ -2,6 +2,7 @@
#include "../utils/each.h"
#include "../utils/mut.h"
#include "../utils/builtins.h"
#include "../utils/talloc.h"
B shape_c1(B t, B x) {

View File

@ -1,4 +1,5 @@
#include "../core.h"
#include "../utils/talloc.h"

View File

@ -1,5 +1,7 @@
#include "../core.h"
u64 allocB; // currently allocated number of bytes
#if MM==0
#include "../opt/mm_malloc.c"
#elif MM==1

View File

@ -1,17 +1,22 @@
#include "../core.h"
#include "../utils/mut.h"
#include "../utils/utf.h"
#include "../utils/talloc.h"
u64 allocB; // currently allocated number of bytes
B bi_emptyHVec, bi_emptyIVec, bi_emptyCVec, bi_emptySVec;
NOINLINE TStack* tstack_ext(TStack* o, u32 elsz) {
usz ncap = o->cap*2;
TStack* n = (TStack*)mm_allocN(sizeof(TStack) + elsz*ncap, t_temp);
memcpy(n->data, o->data, o->cap*elsz);
n->cap = ncap;
n->size = o->size;
mm_free((Value*)o);
NOINLINE TStack* ts_e(TStack* o, u32 elsz, u64 am) { u64 size = o->size;
u64 alsz = mm_round(fsizeof(TStack, data, u8, (size+am)*elsz));
TStack* n;
if (alsz==mm_size((Value*)o)) {
n = o;
} else {
n = (TStack*)mm_allocN(alsz, t_temp);
memcpy(n->data, o->data, o->cap*elsz);
mm_free((Value*)o);
n->size = size;
}
n->cap = (mm_size((Value*)n)-offsetof(TStack,data))/elsz;
return n;
}

View File

@ -21,39 +21,6 @@ static B mm_alloc(usz sz, u8 type, u64 tag) {
#define MAP_NORESERVE 0 // apparently needed for freebsd or something
#endif
typedef struct TAlloc {
struct Value;
u8 data[];
} TAlloc;
#define TOFF offsetof(TAlloc, data)
#define TALLOC(T,N,AM) T* N = (T*) ((TAlloc*)mm_allocN(TOFF + (AM)*sizeof(T) + 8, t_temp))->data; // +8 so mm is happy
#define TOBJ(N) (void*)((u8*)(N) - TOFF)
#define TFREE(N) mm_free((Value*)TOBJ(N));
#define TREALLOC(N, AM) talloc_realloc(TOBJ(N), AM)
#define TSIZE(N) (mm_size(TOBJ(N))-TOFF)
static inline void* talloc_realloc(TAlloc* t, u64 am) { // TODO maybe shouldn't be inline?
u64 stored = mm_size((Value*)t)-TOFF;
if (stored > am) return t->data;
TALLOC(u8,r,am);
memcpy(r, t->data, stored);
mm_free((Value*)t);
return r;
}
typedef struct TStack {
struct Value;
usz size;
usz cap;
u8 data[];
} TStack;
#define TSALLOC(T,N,I) usz N##_dc=(I); u32 N##_e=sizeof(T); TStack* N##_o = (TStack*)mm_allocN(sizeof(TStack)+N##_e*N##_dc, t_temp); N##_o->size=0; N##_o->cap=N##_dc; T* N = (T*)N##_o->data;
#define TSFREE(N) mm_free((Value*)N##_o);
#define TSDBL(N) { N##_o = tstack_ext(N##_o, N##_e); N = (void*)N##_o->data; }
#define TSADD(N,X) { if (N##_o->size==N##_o->cap) TSDBL(N); N[N##_o->size++] = X; }
#define TSADDA(N,P,AM) { u64 n=AM; while(N##_o->size+n>N##_o->cap) TSDBL(N); memcpy(N+N##_o->size,P,n*N##_e); N##_o->size+= AM; }
#define TSSIZE(N) (N##_o->size)
TStack* tstack_ext(TStack* o, u32 elsz);
// shape mess
typedef struct ShArr {

View File

@ -106,7 +106,7 @@
#define AUTO __auto_type
#define LIKELY(X) __builtin_expect(X,1)
#define RARE(X) __builtin_expect(X,0)
#define RFLD(X,T,F) ((T*)((char*)(X) - offsetof(T,F))) // reverse-read field: `T* x = …; E v = x->f; x == RFLD(v, T, f)`
#define RFLD(X,T,F) ((T*)((char*)(X) - offsetof(T,F))) // value, result type, field name; reverse-read field: `T* x = …; E v = x->f; x == RFLD(v, T, f)`
#define N64x "%"SCNx64
#define N64d "%"SCNd64
#define N64u "%"SCNu64
@ -122,7 +122,7 @@ typedef u8 ur;
CTR_FOR(F)
#undef 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 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

View File

@ -2,6 +2,7 @@
#include "../core/gstack.h"
#include "../ns.h"
#include "../utils/file.h"
#include "../utils/talloc.h"
#ifndef USE_PERF
#define USE_PERF 0 // enable writing symbols to /tmp/perf-<pid>.map
@ -45,7 +46,7 @@ static void* mmX_allocN(usz sz, u8 type) { assert(sz>=16); return mmX_allocL(BSZ
#endif
#define P(N) B N=GSP;
#if VM_POS
#define POS_UPD (envCurr-1)->bcL = bc-1;
#define POS_UPD (envCurr-1)->bcL = bc;
#else
#define POS_UPD
#endif
@ -61,28 +62,39 @@ INS B i_ADDI(u64 v) {
INS B i_ADDU(u64 v) {
return b(v);
}
INS B i_FN1C(B f, u32* bc GA1) { P(x) // TODO figure out a way to instead pass an offset in bc, so that shorter `mov`s can be used to pass it
GS_UPD;POS_UPD;
INS B i_FN1C(B f, u32* bc GA1) { P(x) GS_UPD;POS_UPD; // TODO figure out a way to instead pass an offset in bc, so that shorter `mov`s can be used to pass it
B r = c1(f, x);
dec(f); return r;
}
INS B i_FN1O(B f, u32* bc GA1) { P(x)
GS_UPD;POS_UPD;
INS B i_FN1O(B f, u32* bc GA1) { P(x) GS_UPD;POS_UPD;
B r = isNothing(x)? x : c1(f, x);
dec(f); return r;
}
INS B i_FN2C(B w, u32* bc GA1) { P(f)P(x)
GS_UPD;POS_UPD;
INS B i_FN2C(B w, u32* bc GA1) { P(f)P(x) GS_UPD;POS_UPD;
B r = c2(f, w, x);
dec(f); return r;
}
INS B i_FN2O(B w, u32* bc GA1) { P(f)P(x)
GS_UPD;POS_UPD; B r;
INS B i_FN2O(B w, u32* bc GA1) { P(f)P(x) GS_UPD;POS_UPD;
B r;
if (isNothing(x)) { dec(w); r = x; }
else r = isNothing(w)? c1(f, x) : c2(f, w, x);
dec(f);
return r;
}
INS B i_FN1Ci(B x, BB2B fi, u32* bc GA1) { GS_UPD;POS_UPD;
return fi(b((u64)0), x);
}
INS B i_FN2Ci(B w, BBB2B fi, u32* bc GA1) { P(x) GS_UPD;POS_UPD;
return fi(b((u64)0), w, x);
}
INS B i_FN1Oi(B x, BB2B fm, u32* bc GA1) { GS_UPD;POS_UPD;
B r = isNothing(x)? x : fm(b((u64)0), x);
return r;
}
INS B i_FN2Oi(B w, BB2B fm, BBB2B fd, u32* bc GA1) { P(x) GS_UPD;POS_UPD;
if (isNothing(x)) { dec(w); return x; }
else return isNothing(w)? fm(b((u64)0), x) : fd(b((u64)0), w, x);
}
INS B i_ARR_0() { // TODO combine with ADDI
return inc(bi_emptyHVec);
}
@ -151,12 +163,11 @@ INS B i_NSPM(B o, u32 l) {
c(FldAlias,a)->p = l;
return a;
}
INS B i_RETD(Scope** pscs GA1) {
INS B i_RETD(Scope** pscs GA1) { GS_UPD;
Scope* sc = pscs[0];
Body* b = sc->body;
ptr_inc(sc);
ptr_inc(b->nsDesc);
GS_UPD;
return m_ns(sc, b->nsDesc);
}
@ -171,8 +182,6 @@ INS B i_RETD(Scope** pscs GA1) {
#include "x86_64.h"
#if USE_PERF
@ -204,6 +213,110 @@ static void write_asm(u8* p, u64 sz) { // for debugging; view with objdump -b bi
}
typedef struct SRef { B v; i32 p; } SRef;
#define SREF(V,P) ((SRef){.v=V, .p=P})
typedef struct OptRes { u32* bc; u32* offset; } OptRes;
static OptRes opt(u32* bc0) {
TSALLOC(SRef, stk, 8);
TSALLOC(u8, actions, 64); // 1 per instruction; 0: nothing; 1: indicates return; 2: remove; 3: FN1_/FN2C; 4: FN2O
TSALLOC(u64, data, 64); // variable length; whatever things are needed for the specific action
u32* bc = bc0; usz pos = 0;
while (true) {
u32* sbc = bc;
#define L64 ({ u64 r = bc[0] | ((u64)bc[1])<<32; bc+= 2; r; })
bool ret = false;
u8 cact = 0;
switch (*bc++) { case FN1Ci: case FN1Oi: case FN2Ci: case FN2Oi: thrM("JIT optimization: didn't already expect immediate FN__");
case ADDU: case ADDI: cact = 0; TSADD(stk,SREF(b(L64), pos)); break;
case FN1C: case FN1O: { SRef f = stk[TSSIZE(stk)-1];
if (!isFun(f.v) || v(f.v)->type!=t_funBI) goto defIns;
actions[f.p] = 2; cact = 3;
TSADD(data, (u64) c(Fun, f.v)->c1);
goto defStk;
break;
}
case FN2C: { SRef f = stk[TSSIZE(stk)-2];
if (!isFun(f.v) || v(f.v)->type!=t_funBI) goto defIns;
actions[f.p] = 2; cact = 3;
TSADD(data, (u64) c(Fun, f.v)->c2);
goto defStk;
break;
}
case FN2O: { SRef f = stk[TSSIZE(stk)-2];
if (!isFun(f.v) || v(f.v)->type!=t_funBI) goto defIns;
actions[f.p] = 2; cact = 4;
TSADD(data, (u64) c(Fun, f.v)->c1);
TSADD(data, (u64) c(Fun, f.v)->c2);
goto defStk;
break;
}
case RETN: case RETD:
ret = true;
cact = 1;
goto defIns;
default: defIns:;
defStk:
TSSIZE(stk)-= stackConsumed(sbc);
i32 added = stackAdded(sbc);
for (i32 i = 0; i < added; i++) TSADD(stk, SREF(bi_optOut, -1))
}
TSADD(actions, cact);
#undef L64
if (ret) break;
bc = nextBC(sbc);
pos++;
}
TSFREE(stk);
TSALLOC(u32, rbc, TSSIZE(actions));
TSALLOC(u32, roff, TSSIZE(actions));
bc = bc0;
u64 tpos = 0, dpos = 0;
while (true) {
u32* sbc = bc;
u32* ebc = nextBC(sbc);
#define L64 ({ u64 r = bc[0] | ((u64)bc[1])<<32; bc+= 2; r; })
u32 ctype = actions[tpos++];
bool ret = false;
u32 v = *bc++;
u64 psz = TSSIZE(rbc);
#define A64(X) { u64 a64=(X); TSADD(rbc, (u32)a64); TSADD(rbc, a64>>32); }
switch (ctype) { default: UD;
case 3: assert(v==FN1C|v==FN1O|v==FN2C);
TSADD(rbc, v==FN1C? FN1Ci : v==FN1O? FN1Oi : FN2Ci);
A64(data[dpos++]);
break;
case 4: assert(v==FN2O);
TSADD(rbc, FN2Oi);
A64(data[dpos++]);
A64(data[dpos++]);
break;
case 2: break; // remove
case 1: ret = true; goto def2; // return
case 0: def2:; // do nothing
TSADDA(rbc, sbc, ebc-sbc);
}
u64 added = TSSIZE(rbc)-psz;
for (i32 i = 0; i < added; i++) TSADD(roff, sbc-bc0);
#undef A64
if (ret) break;
bc = ebc;
}
bc = bc0; pos = 0;
TSFREE(data);
TSFREE(actions);
return (OptRes){.bc = rbc, .offset = roff};
}
#undef SREF
void freeOpt(OptRes o) {
TSFREEP(o.bc);
TSFREEP(o.offset);
}
static u32 readBytes4(u8* d) {
return d[0] | d[1]<<8 | d[2]<<16 | d[3]<<24;
}
@ -224,12 +337,15 @@ u8* m_nvm(Body* body) {
if ((u64)i_SETN != (u32)(u64)i_SETN) thrM("JIT: Refusing to run with CBQN code outside of the 32-bit address range");
// #define CCALL(F) { IMM(r_TMP, F); ASM(CALL, r_TMP, -); }
#define CCALL(F) { TSADD(rel, ASM_SIZE); ASM(CALLI, (u32)(u64)F, -); }
u32* bc = body->bc;
u32* origBC = body->bc;
OptRes optRes = opt(origBC);
Block** blocks = body->blocks->a;
i32 depth = 0;
u32* bc = optRes.bc;
while (true) {
u32* s = bc;
u32* n = nextBC(bc);
u32* off = origBC + optRes.offset[s-optRes.bc];
bool ret = false;
#define L64 ({ u64 r = bc[0] | ((u64)bc[1])<<32; bc+= 2; r; })
// #define LEA0(O,I,OFF) { ASM(MOV,O,I); ADDI(O,OFF); }
@ -256,10 +372,14 @@ u8* m_nvm(Body* body) {
IMM(REG_ARG0, L64); CCALL(i_ADDU);
#endif
break;
case FN1C: TOPp; IMM(REG_ARG1, s); INV(2,0,i_FN1C); break; // (B, u32* bc, S)
case FN2C: TOPp; IMM(REG_ARG1, s); INV(2,0,i_FN2C); break; // (B, u32* bc, S)
case FN1O: TOPp; IMM(REG_ARG1, s); INV(2,0,i_FN1O); break; // (B, u32* bc, S)
case FN2O: TOPp; IMM(REG_ARG1, s); INV(2,0,i_FN2O); break; // (B, u32* bc, S)
case FN1C: TOPp; IMM(REG_ARG1,off); INV(2,0,i_FN1C); break; // (B, u32* bc, S)
case FN2C: TOPp; IMM(REG_ARG1,off); INV(2,0,i_FN2C); break; // (B, u32* bc, S)
case FN1O: TOPp; IMM(REG_ARG1,off); INV(2,0,i_FN1O); break; // (B, u32* bc, S)
case FN2O: TOPp; IMM(REG_ARG1,off); INV(2,0,i_FN2O); break; // (B, u32* bc, S)
case FN1Ci:TOPp; IMM(REG_ARG1,L64); IMM(REG_ARG2,off); INV(3,0,i_FN1Ci); break; // (B, BB2B fm, u32* bc, S)
case FN2Ci:TOPp; IMM(REG_ARG1,L64); IMM(REG_ARG2,off); INV(3,0,i_FN2Ci); break; // (B, BBB2B fd, u32* bc, S)
case FN1Oi:TOPp; IMM(REG_ARG1,L64); IMM(REG_ARG2,off); INV(3,0,i_FN1Oi); break; // (B, BB2B fm, u32* bc, S)
case FN2Oi:TOPp; IMM(REG_ARG1,L64); IMM(REG_ARG2, L64); IMM(REG_ARG3,off); INV(4,0,i_FN2Oi); break; // (B, BB2B fm, BBB2B fd, u32* bc, S)
case ARRM: case ARRO:;
u32 sz = *bc++;
if (sz) { TOPp; IMM(REG_ARG1, sz); INV(2,0,i_ARR_p); } // (B, i64 sz, S)
@ -269,23 +389,23 @@ u8* m_nvm(Body* body) {
Block* bl = blocks[*bc++];
u64 fn = (u64)(bl->ty==0? i_DFND_0 : bl->ty==1? i_DFND_1 : bl->ty==2? i_DFND_2 : NULL);
if (fn==0) thrM("JIT: Bad DFND argument");
IMM(REG_ARG0,s); ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,bl); INV(3,1,fn);
IMM(REG_ARG0,off); ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,bl); INV(3,1,fn);
break;
case OP1D: TOPp; IMM(REG_ARG1,s); INV(2,0,i_OP1D); break; // (B, u32* bc, S)
case OP2D: TOPp; IMM(REG_ARG1,s); INV(2,0,i_OP2D); break; // (B, u32* bc, S)
case OP1D: TOPp; IMM(REG_ARG1,off); INV(2,0,i_OP1D); break; // (B, u32* bc, S)
case OP2D: TOPp; IMM(REG_ARG1,off); INV(2,0,i_OP2D); break; // (B, u32* bc, S)
case OP2H: TOPp; INV(1,0,i_OP2H); break; // (B, S)
case TR2D: TOPp; INV(1,0,i_TR2D); break; // (B, S)
case TR3D: TOPp; INV(1,0,i_TR3D); break; // (B, S)
case TR3O: TOPp; INV(1,0,i_TR3O); break; // (B, S)
case LOCM: TOPs; { u64 d=*bc++; u64 p=*bc++; IMM(REG_RES, tag((u64)d<<32 | (u32)p, VAR_TAG).u); } break;
case EXTM: TOPs; { u64 d=*bc++; u64 p=*bc++; IMM(REG_RES, tag((u64)d<<32 | (u32)p, EXT_TAG).u); } break;
case LOCO: TOPs; IMM(REG_ARG0,*bc++); IMM(REG_ARG1,*bc++); ASM(MOV,REG_ARG2,r_PSCS); IMM(REG_ARG3,s); INV(4,1,i_LOCO); break; // (u32 d, u32 p, Scope** pscs, u32* bc, S)
case EXTO: TOPs; IMM(REG_ARG0,*bc++); IMM(REG_ARG1,*bc++); ASM(MOV,REG_ARG2,r_PSCS); IMM(REG_ARG3,s); INV(4,1,i_EXTO); break; // (u32 d, u32 p, Scope** pscs, u32* bc, S)
case LOCO: TOPs; IMM(REG_ARG0,*bc++); IMM(REG_ARG1,*bc++); ASM(MOV,REG_ARG2,r_PSCS); IMM(REG_ARG3,off); INV(4,1,i_LOCO); break; // (u32 d, u32 p, Scope** pscs, u32* bc, S)
case EXTO: TOPs; IMM(REG_ARG0,*bc++); IMM(REG_ARG1,*bc++); ASM(MOV,REG_ARG2,r_PSCS); IMM(REG_ARG3,off); INV(4,1,i_EXTO); break; // (u32 d, u32 p, Scope** pscs, u32* bc, S)
case LOCU: TOPs; IMM(REG_ARG0,*bc++); IMM(REG_ARG1,*bc++); ASM(MOV,REG_ARG2,r_PSCS); CCALL(i_LOCU); break; // (u32 d, u32 p, Scope** pscs, S)
case EXTU: TOPs; IMM(REG_ARG0,*bc++); IMM(REG_ARG1,*bc++); ASM(MOV,REG_ARG2,r_PSCS); CCALL(i_EXTU); break; // (u32 d, u32 p, Scope** pscs, S)
case SETN: TOPp; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,s); INV(3,0,i_SETN); break; // (B, Scope** pscs, u32* bc, S)
case SETU: TOPp; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,s); INV(3,0,i_SETU); break; // (B, Scope** pscs, u32* bc, S)
case SETM: TOPp; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,s); INV(3,0,i_SETM); break; // (B, Scope** pscs, u32* bc, S)
case SETN: TOPp; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,off); INV(3,0,i_SETN); break; // (B, Scope** pscs, u32* bc, S)
case SETU: TOPp; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,off); INV(3,0,i_SETU); break; // (B, Scope** pscs, u32* bc, S)
case SETM: TOPp; ASM(MOV,REG_ARG1,r_PSCS); IMM(REG_ARG2,off); INV(3,0,i_SETM); break; // (B, Scope** pscs, u32* bc, S)
case FLDO: TOPp; IMM(REG_ARG1,*bc++); ASM(MOV,REG_ARG2,r_PSCS); INV(3,0,i_FLDO); break; // (B, u32 p, Scope** pscs, S)
case NSPM: TOPp; IMM(REG_ARG1,*bc++); CCALL(i_NSPM); break; // (B, u32 l, S)
case RETD: ASM(MOV,REG_ARG0,r_PSCS); INV(1,1,i_RETD); ret=true; break; // (Scope** pscs, S); stack diff 0 is wrong, but updating it is useless
@ -301,6 +421,7 @@ u8* m_nvm(Body* body) {
depth+= stackDiff(s);
if (ret) break;
}
freeOpt(optRes);
ASM(POP, r_CS, -);
ASM(POP, r_PSCS, -);
ASM(POP, r_TMP, -);

View File

@ -17,6 +17,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "../core.h"
#include "../utils/talloc.h"
// 16 integer registers:
// 0 1 2 (0: not saved, 1: callee saves, 2: caller saves)

View File

@ -2,6 +2,7 @@
#include "../core.h"
#include "file.h"
#include "mut.h"
#include "talloc.h"
FILE* file_open(B path, char* desc, char* mode) { // doesn't consume
u64 plen = utf8lenB(path);

View File

@ -1,5 +1,6 @@
#pragma once
#include "wyhash.h"
#include "talloc.h"
extern u64 wy_secret[4];

35
src/utils/talloc.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
typedef struct TAlloc {
struct Value;
u8 data[];
} TAlloc;
#define TOFF offsetof(TAlloc, data)
#define TALLOC(T,N,AM) T* N = (T*) ((TAlloc*)mm_allocN(TOFF + (AM)*sizeof(T) + 8, t_temp))->data; // +8 so mm is happy
#define TOBJ(N) (void*)((u8*)(N) - TOFF)
#define TFREE(N) mm_free((Value*)TOBJ(N));
#define TREALLOC(N, AM) talloc_realloc(TOBJ(N), AM)
#define TSIZE(N) (mm_size(TOBJ(N))-TOFF)
static inline void* talloc_realloc(TAlloc* t, u64 am) { // TODO maybe shouldn't be inline?
u64 stored = mm_size((Value*)t)-TOFF;
if (stored > am) return t->data;
TALLOC(u8,r,am);
memcpy(r, t->data, stored);
mm_free((Value*)t);
return r;
}
typedef struct TStack {
struct Value;
usz size;
usz cap;
u8 data[];
} TStack;
#define TSALLOC(T,N,I) usz N##_dc=(I); u32 N##_e=sizeof(T); TStack* N##_o = (TStack*)mm_allocN(sizeof(TStack)+N##_e*N##_dc, t_temp); N##_o->size=0; N##_o->cap=N##_dc; T* N = (T*)N##_o->data;
#define TSFREE(N) mm_free((Value*)N##_o);
#define TSUPD(N,AM) { N##_o = ts_e(N##_o, N##_e, AM); N = (void*)N##_o->data; }
#define TSADD(N,X) { if (N##_o->size==N##_o->cap) TSUPD(N, 1); N[N##_o->size++] = X; }
#define TSADDA(N,P,AM) { u64 n=AM; if(N##_o->size+n>N##_o->cap) TSUPD(N, n); memcpy(N+N##_o->size,P,n*N##_e); N##_o->size+= n; }
#define TSFREEP(N) mm_free((void*)RFLD(N, TStack, data));
#define TSSIZE(N) (N##_o->size)
TStack* ts_e(TStack* o, u32 elsz, u64 am);

View File

@ -4,6 +4,7 @@
#include "jit/nvm.h"
#include "ns.h"
#include "utils/utf.h"
#include "utils/talloc.h"
#ifndef USE_JIT
#define USE_JIT 0 // enable the extremely basic x86-64 JIT that mostly just generates MOVs and CALLs
@ -13,7 +14,7 @@
#define FOR_BC(F) F(PUSH) F(VARO) F(VARM) F(ARRO) F(ARRM) F(FN1C) F(FN2C) F(OP1D) F(OP2D) F(TR2D) \
F(TR3D) F(SETN) F(SETU) F(SETM) F(POPS) F(DFND) F(FN1O) F(FN2O) F(CHKV) F(TR3O) \
F(OP2H) F(LOCO) F(LOCM) F(VFYM) F(SETH) F(RETN) F(FLDO) F(FLDM) F(NSPM) F(RETD) F(SYSV) F(LOCU) \
F(EXTO) F(EXTM) F(EXTU)
F(EXTO) F(EXTM) F(EXTU) F(ADDI) F(ADDU) F(FN1Ci)F(FN1Oi)F(FN2Ci)F(FN2Oi)
u32* nextBC(u32* p) {
switch(*p) {
@ -29,21 +30,36 @@ u32* nextBC(u32* p) {
return p+2;
case LOCO: case LOCM: case LOCU:
case EXTO: case EXTM: case EXTU:
case ADDI: case ADDU:
case ADDI: case ADDU: case FN1Ci: case FN1Oi: case FN2Ci:
return p+3;
case FN2Oi:
return p+5;
default: return 0;
}
}
i32 stackDiff(u32* p) {
switch(*p) {
if (*p==ARRO|*p==ARRM) return 1-p[1];
switch(*p) { default: UD; // case ARRO: case ARRM: return 1-p[1];
case PUSH: case VARO: case VARM: case DFND: case LOCO: case LOCM: case LOCU: case EXTO: case EXTM: case EXTU: case SYSV: case ADDI: case ADDU: return 1;
case CHKV: case VFYM: case FLDO: case FLDM: case RETD: case NSPM: return 0;
case FN1C: case OP1D: case TR2D: case SETN: case SETU: case POPS: case FN1O: case OP2H: case SETH: case RETN: return -1;
case FN2C: case OP2D: case TR3D: case SETM: case FN2O: case TR3O: return -2;
case ARRO: case ARRM: return 1-p[1];
default: return 9999999;
case FN1Ci:case FN1Oi:case CHKV: case VFYM: case FLDO: case FLDM: case RETD: case NSPM: return 0;
case FN2Ci:case FN2Oi:case FN1C: case FN1O: case OP1D: case TR2D: case SETN: case SETU: case POPS: case OP2H: case SETH: case RETN: return -1;
case OP2D: case TR3D: case FN2C: case FN2O: case SETM: case TR3O: return -2;
}
}
i32 stackConsumed(u32* p) {
if (*p==ARRO|*p==ARRM) return p[1];
switch(*p) { default: UD; // case ARRO: case ARRM: return -p[1];
case PUSH: case VARO: case VARM: case DFND: case LOCO: case LOCM: case LOCU: case EXTO: case EXTM: case EXTU: case SYSV: case ADDI: case ADDU: return 0;
case CHKV: case VFYM: case RETD: return 0;
case FN1Ci:case FN1Oi:case FLDO: case FLDM: case NSPM: case RETN: case POPS: return 1;
case FN2Ci:case FN2Oi:case FN1C: case FN1O: case OP1D: case TR2D: case SETN: case SETU: case OP2H: case SETH: return 2;
case OP2D: case TR3D: case FN2C: case FN2O: case SETM: case TR3O: return 3;
}
}
i32 stackAdded(u32* p) {
if (*p==ARRO|*p==ARRM) return 1;
return stackDiff(p)+stackConsumed(p);
}
char* nameBC(u32* p) {
switch(*p) { default: return "(unknown)";
#define F(X) case X: return #X;
@ -184,6 +200,7 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B block
break;
}
}
#undef A64
usz nlen = TSSIZE(nBCT)-TSSIZE(mapT);
for (usz i = 0; i < nlen; i++) TSADD(mapT, c-bc);
h+= stackDiff(c);

View File

@ -34,7 +34,8 @@ enum {
SYSV = 30, // N; get system function N
LOCU = 31, // N0,N1; like LOCO but overrides the slot with bi_optOut
EXTO, EXTM, EXTU, // alternate versions of LOC_ for extended variables
ADDI, ADDU, // separate PUSH for refcounting needed/not needed (stores the object inline, instead of reading from `objs`)
ADDI, ADDU, // separate PUSH for refcounting needed/not needed (stores the object inline as 2 u32s, instead of reading from `objs`)
FN1Ci, FN1Oi, FN2Ci, FN2Oi, // FN__ alternatives that don't take the function from the stack, but instead as an 2×u32 immediate in the bytecode
BC_SIZE
};
@ -106,6 +107,9 @@ B evalBC(Body* b, Scope* sc); // doesn't consume; executes bytecode of the body
u32* nextBC(u32* p);
i32 stackDiff(u32* p);
i32 stackConsumed(u32* p);
i32 stackAdded(u32* p);
char* nameBC(u32* p);
typedef struct FunBlock { struct Fun; Scope* sc; Block* bl; } FunBlock;