diff --git a/src/h.h b/src/h.h index 8cad8f13..31b2ccf0 100644 --- a/src/h.h +++ b/src/h.h @@ -118,6 +118,7 @@ typedef struct Arr { void* mm_allocN(usz sz, u8 type); void mm_free(Value* x); void mm_visit(B x); +u64 mm_round(usz x); B mm_alloc(usz sz, u8 type, u64 tag) { assert(tag>1LL<<16 || tag==0); // make sure it's `ftag`ged :| return b((u64)mm_allocN(sz,type) | tag); diff --git a/src/mm_buddy.c b/src/mm_buddy.c index a19cd27d..ea6d4fe4 100644 --- a/src/mm_buddy.c +++ b/src/mm_buddy.c @@ -14,6 +14,7 @@ struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else ca EmptyValue* buckets[64]; #define BSZ(x) (1ull<<(x)) +#define BSZI(x) (64-__builtin_clzl((x)-1ull)) EmptyValue* makeEmpty(u8 bucket) { // result->next is garbage u8 cb = bucket; @@ -38,15 +39,15 @@ EmptyValue* makeEmpty(u8 bucket) { // result->next is garbage break; } } + c->mmInfo = bucket; while (cb != bucket) { cb--; - EmptyValue* b = (EmptyValue*) (((char*)c)+BSZ(cb)); + EmptyValue* b = (EmptyValue*) (BSZ(cb) + (char*)c); b->type = t_empty; b->mmInfo = cb; b->next = 0; assert(buckets[cb]==0); buckets[cb] = b; } - c->mmInfo = bucket; return c; } @@ -61,7 +62,7 @@ void mm_free(Value* x) { void* mm_allocN(usz sz, u8 type) { assert(sz>8); - u8 bucket = 64-__builtin_clzl(sz-1ull); // inverse of BSZ + u8 bucket = BSZI(sz); // inverse of BSZ EmptyValue* x = buckets[bucket]; if (x==NULL) x = makeEmpty(bucket); else buckets[bucket] = x->next; @@ -72,6 +73,10 @@ void* mm_allocN(usz sz, u8 type) { return x; } +u64 mm_round(usz sz) { + return BSZ(BSZI(sz)); +} + void mm_visit(B x) { } diff --git a/src/mm_malloc.c b/src/mm_malloc.c index eb5c3046..7964bffb 100644 --- a/src/mm_malloc.c +++ b/src/mm_malloc.c @@ -14,6 +14,11 @@ void* mm_allocN(usz sz, u8 type) { x->type = type; return x; } + +u64 mm_round(usz sz) { + return sz; +} + void mm_visit(B x) { } diff --git a/src/vm.c b/src/vm.c index 5c29d19d..e1e03fe5 100644 --- a/src/vm.c +++ b/src/vm.c @@ -249,6 +249,23 @@ i32 bcDepth=-2; i32* vmStack; i32 bcCtr = 0; #endif + +B* gStack; +B* gStackStart; +B* gStackEnd; + +void allocStack(u64 am) { + u64 left = gStackEnd-gStack; + if (am>left) { + u64 n = gStackEnd-gStackStart + am + 500; + u64 d = gStackStart-gStack; + if (gStack==NULL) gStackStart = malloc(n*sizeof(B)); + else gStackStart = realloc(gStackStart, n*sizeof(B)); + gStack = gStackStart+d; + gStackEnd = gStackStart+n; + } +} + B evalBC(Body* b, Scope* sc) { #ifdef DEBUG_VM bcDepth+= 2; @@ -260,11 +277,11 @@ B evalBC(Body* b, Scope* sc) { B* objs = b->comp->objs->a; Block** blocks = b->comp->blocks; i32* bc = b->bc; - B stack[b->maxStack]; - i32 sh = 0; - #define POP stack[--sh] + allocStack(b->maxStack); + #define POP (*--gStack) #define P(N) B N=POP; - #define ADD stack[sh++] = + #define ADD(X) { B tr=X; *(gStack++) = tr; } // if ordering is needed + // #define ADD(X) *(gStack++) = X; } // if ordering is not needed while(true) { #ifdef DEBUG_VM i32* sbc = bc; @@ -279,24 +296,24 @@ B evalBC(Body* b, Scope* sc) { switch(*bc++) { case POPS: dec(POP); break; case PUSH: { - ADD inci(objs[*bc++]); + ADD(inci(objs[*bc++])); break; } case FN1C: { P(f)P(x) - ADD c1(f, x); dec(f); + ADD(c1(f, x); dec(f)); break; } case FN1O: { P(f)P(x) - ADD isNothing(x)? x : c1(f, x); dec(f); + ADD(isNothing(x)? x : c1(f, x); dec(f)); break; } case FN2C: { P(w)P(f)P(x) - ADD c2(f, w, x); dec(f); + ADD(c2(f, w, x); dec(f)); break; } case FN2O: { P(w)P(f)P(x) - if (isNothing(x)) { dec(w); ADD x; } - else ADD isNothing(w)? c1(f, x) : c2(f, w, x); + if (isNothing(x)) { dec(w); ADD(x); } + else ADD(isNothing(w)? c1(f, x) : c2(f, w, x)); dec(f); break; } @@ -304,43 +321,43 @@ B evalBC(Body* b, Scope* sc) { i32 sz = *bc++; HArr_p r = m_harrv(sz); for (i32 i = 0; i < sz; i++) r.a[sz-i-1] = POP; - ADD r.b; + ADD(r.b); break; } case DFND: { Block* bl = blocks[*bc++]; switch(bl->ty) { default: UD; - case 0: ADD m_funBlock(bl, sc); break; - case 1: ADD m_md1Block(bl, sc); break; - case 2: ADD m_md2Block(bl, sc); break; + case 0: ADD(m_funBlock(bl, sc)); break; + case 1: ADD(m_md1Block(bl, sc)); break; + case 2: ADD(m_md2Block(bl, sc)); break; } break; } - case OP1D: { P(f)P(m) ADD m1_d (m,f ); break; } - case OP2D: { P(f)P(m)P(g) ADD m2_d (m,f,g); break; } - case OP2H: { P(m)P(g) ADD m2_h (m, g); break; } - case TR2D: { P(g)P(h) ADD m_atop( g,h); break; } - case TR3D: { P(f)P(g)P(h) ADD m_fork(f,g,h); break; } + case OP1D: { P(f)P(m) ADD(m1_d (m,f )); break; } + case OP2D: { P(f)P(m)P(g) ADD(m2_d (m,f,g)); break; } + case OP2H: { P(m)P(g) ADD(m2_h (m, g)); break; } + case TR2D: { P(g)P(h) ADD(m_atop( g,h)); break; } + case TR3D: { P(f)P(g)P(h) ADD(m_fork(f,g,h)); break; } case TR3O: { P(f)P(g)P(h) - if (isNothing(f)) { ADD m_atop(g,h); dec(f); } - else ADD m_fork(f,g,h); + if (isNothing(f)) { ADD(m_atop(g,h)); dec(f); } + else ADD(m_fork(f,g,h)); break; } case LOCM: { i32 d = *bc++; i32 p = *bc++; - ADD tag((u64)d<<32 | p, VAR_TAG); + ADD(tag((u64)d<<32 | p, VAR_TAG)); break; } case LOCO: { i32 d = *bc++; i32 p = *bc++; - ADD inci(scd(sc,d)->vars[p]); + ADD(inci(scd(sc,d)->vars[p])); break; } - case SETN: { P(s) P(x) v_set(sc, s, inci(x), false); ADD x; break; } - case SETU: { P(s) P(x) v_set(sc, s, inci(x), true ); ADD x; break; } + case SETN: { P(s) P(x) v_set(sc, s, inci(x), false); ADD(x); break; } + case SETU: { P(s) P(x) v_set(sc, s, inci(x), true ); ADD(x); break; } case SETM: { P(s)P(f)P(x) B w = v_get(sc, s); B r = c2(f,w,x); dec(f); v_set(sc, s, inci(r), true); - ADD r; + ADD(r); break; } // not implemented: VARO VARM CHKV VFYM SETH FLDO FLDM NSPM RETD SYSV @@ -358,15 +375,14 @@ B evalBC(Body* b, Scope* sc) { for (i32 i = 0; i < sh; i++) { if(i)printf(" ⋄ "); print(stack[i]); } puts(""); fflush(stdout); #endif } - #undef P - #undef ADD - #undef POP end:; #ifdef DEBUG_VM bcDepth-= 2; #endif - assert(sh==1); - return stack[0]; + return POP; + #undef P + #undef ADD + #undef POP } B actualExec(Block* bl, Scope* psc, u32 ga, B* svar) {