diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 3ef6223b..bcd56ff9 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -1326,7 +1326,7 @@ B transp_c1(B t, B x) { void* xp = tyany_ptr(x); switch(xe) { default: UD; #if __BMI2__ - case el_bit: + case el_bit:; u64* r0 = rp; TALLOC(u64, r1, BIT_N(h)); for (usz i=0; ia; mm_visit(((FillArr*)x)->fill); for (usz i = 0; i < ia; i++) mm_visit(p[i]); @@ -60,7 +61,7 @@ static bool fillarr_canStore(B x) { return true; } static void fillarr_freeT(Value* x) { FillArr* s=(void*)x; dec(s->fill); decSh(x); mm_free(x); } -static void fillslice_visit(Value* x) { FillSlice* s=(void*)x; mm_visitP(s->p); mm_visit(s->fill); } +static void fillslice_visit(Value* x) { FillSlice* s=(void*)x; mm_visitP(s->p); mm_visit(s->fill); VISIT_SHAPE(x); } static void fillslice_freeO(Value* x) { FillSlice* s=(void*)x; ptr_dec(s->p); dec(s->fill); decSh(x); } static void fillslice_freeF(Value* x) { fillslice_freeO(x); mm_free(x); } diff --git a/src/core/heap.c b/src/core/heap.c index 0d40634e..92bf188b 100644 --- a/src/core/heap.c +++ b/src/core/heap.c @@ -19,33 +19,14 @@ void heapVerify_checkFn(Value* v) { -void heapVerify_callVisit(Value* v) { - if (TIv(v,isArr) && PRNK(v)>1) heapVerify_visitP(shObjP(v)); - TIv(v,visit)(v); -} - -void heap_getReferents(Value* v) { - heap_curr = v; - if (TIv(v,isArr) && PRNK(v)>1) heapVerify_visitP(shObjP(v)); - TIv(v,visit)(v); -} void gc_visitRoots(void); void gcv2_runHeapverify(i32); -void heapVerify() { +void cbqn_heapVerify() { heap_observed = 0; - #if GC_VISIT_V2 - gcv2_runHeapverify(0); - mm_forHeap(heapVerify_checkFn); - gcv2_runHeapverify(1); - #else - heapVerify_mode=0; mm_forHeap(heapVerify_callVisit); gc_visitRoots(); - mm_forHeap(heapVerify_checkFn); - heapVerify_mode=1; mm_forHeap(heapVerify_callVisit); gc_visitRoots(); - #endif - if (heap_observed) { - printf("refc of last: %d\n", heap_observed->refc); - // heapVerify_mode=2; mm_forHeap(heap_getReferents); - } + gcv2_runHeapverify(0); + mm_forHeap(heapVerify_checkFn); + gcv2_runHeapverify(1); + if (heap_observed) printf("refc of last: %d\n", heap_observed->refc); heapVerify_mode=-1; } @@ -97,7 +78,7 @@ void heap_printInfo(bool sizes, bool types, bool freed, bool chain) { for (i32 i = 2; i < 64; i++) { for (i32 j = 0; j < MM; j++) { i32 o = i-j; - ux cf=0, cc=0; + u64 cf=0, cc=0; if (freed) { cf = heap_PIFreed[o + j*64]; } diff --git a/src/core/heap.h b/src/core/heap.h deleted file mode 100644 index 19113886..00000000 --- a/src/core/heap.h +++ /dev/null @@ -1,23 +0,0 @@ -u64 mm_heapUsed(void); - -#ifdef HEAP_VERIFY - -extern u32 heapVerify_mode; -extern Value* heap_observed; -extern Value* heap_curr; -static bool heapVerify_visit(B x) { - if (heapVerify_mode==-1) return false; - if (isVal(x)) mm_visitP(v(x)); - return true; -} -static bool heapVerify_visitP(void* x) { - if(heapVerify_mode==-1) return false; - Value* v = x; - if (heapVerify_mode==0) v->refc--; - else if(heapVerify_mode==1) v->refc++; - else if(heapVerify_mode==2) if (x==heap_observed) { printf("referee: %p ", heap_curr); printI(tag(heap_curr,OBJ_TAG)); putchar('\n'); } - return true; -} -void heapVerify(void); - -#endif diff --git a/src/core/stuff.c b/src/core/stuff.c index e49723e4..5c050fa6 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -44,7 +44,7 @@ NOINLINE B c2F(B f, B w, B x) { dec(w); dec(x); NOINLINE void value_freeF(Value* x) { value_free(x); } NOINLINE void decA_F(B x) { dec(x); } void noop_visit(Value* x) { } -#if HEAP_VERIFY && GC_VISIT_V2 +#if HEAP_VERIFY void arr_visit(Value* x) { VISIT_SHAPE(x); } #endif NOINLINE B c1_bad(B f, B x) { thrM("This function can't be called monadically"); } @@ -666,7 +666,7 @@ B bqn_merge(B x) { usz* rsh = arr_shAlloc(ra, xr+elR); if (rsh) { shcpy (rsh , SH(x), xr); - if (elSh)shcpy(rsh+xr, elSh, elR); + if (elSh)shcpy(rsh+xr, elSh, elR); } decG(x); return withFill(taga(ra),fill); diff --git a/src/core/stuff.h b/src/core/stuff.h index 319d3206..4b4c2c53 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -222,7 +222,7 @@ B def_fn_ix(B t, B w, B x); B def_decompose(B x); void noop_visit(Value* x); -#if HEAP_VERIFY && GC_VISIT_V2 +#if HEAP_VERIFY void arr_visit(Value* x); #define VISIT_SHAPE(X) ({ if (PRNK(X)>1) mm_visitP(shObjP(X)); }) #else diff --git a/src/ffi.c b/src/ffi.c index 0f8ba943..d7b7f320 100644 --- a/src/ffi.c +++ b/src/ffi.c @@ -939,6 +939,7 @@ void ffi_init(void) { switch (id) { default: err("bad id"); case 0: { char* s = toCStr(x); + decG(x); i32 r = chdir(s); freeCStr(s); return m_f64(r); @@ -954,30 +955,34 @@ void ffi_init(void) { return m_vec2(m_f64(r), m_vec2(m_f64(vs[0]), m_f64(vs[1]))); } case 3: { - SGetU(x) - int fd = o2i(GetU(x,0)); - I8Arr* buf = cpyI8Arr(GetU(x,1)); - usz maxlen = o2s(GetU(x,2)); + SGet(x) + int fd = o2i(Get(x,0)); + I8Arr* buf = cpyI8Arr(Get(x,1)); + usz maxlen = o2s(Get(x,2)); + decG(x); assert(PIA(buf)==maxlen); int res = read(fd, buf->a, maxlen); return m_vec2(m_f64(res), taga(buf)); } case 4: { - SGetU(x) - int fd = o2i(GetU(x,0)); - I8Arr* buf = cpyI8Arr(GetU(x,1)); - usz maxlen = o2s(GetU(x,2)); + SGet(x) + int fd = o2i(Get(x,0)); + I8Arr* buf = cpyI8Arr(Get(x,1)); + usz maxlen = o2s(Get(x,2)); + decG(x); int res = write(fd, buf->a, maxlen); + ptr_dec(buf); return m_f64(res); } case 5: { return m_f64(close(o2i(x))); } case 6: { - SGetU(x) - I16Arr* buf = cpyI16Arr(GetU(x,0)); i16* a = (i16*)buf->a; - int nfds = o2i(GetU(x,1)); - int timeout = o2s(GetU(x,2)); + SGet(x) + I16Arr* buf = cpyI16Arr(Get(x,0)); i16* a = (i16*)buf->a; + int nfds = o2i(Get(x,1)); + int timeout = o2s(Get(x,2)); + decG(x); TALLOC(pollfd, ps, nfds) for (i32 i = 0; i < nfds; i++) ps[i] = (pollfd){.fd = a[i*4+0]|a[i*4+1]<<16, .events=a[i*4+2]}; diff --git a/src/h.h b/src/h.h index 9d0c25dc..335cd0eb 100644 --- a/src/h.h +++ b/src/h.h @@ -46,7 +46,6 @@ #endif #endif -// #define HEAP_VERIFY // enable usage of heapVerify() // #define ALLOC_STAT // store basic allocation statistics // #define ALLOC_SIZES // store per-type allocation size statistics // #define USE_VALGRIND // whether to mark freed memory for valgrind @@ -357,6 +356,10 @@ void gc_addFn(vfn f); // add function that calls mm_visit/mm_visitP for dynamic void gc_add_ref(B* x); // add x as a root reference bool gc_maybeGC(bool toplevel); // gc if that seems necessary; returns if did gc void gc_forceGC(bool toplevel); // force a gc; who knows what happens if gc is disabled (probably should error) +u64 mm_heapUsed(void); +#if HEAP_VERIFY + void cbqn_heapVerify(void); +#endif // some primitive actions static const B bi_N = b((u64)0x7FF2000000000000ull); // tag(0,TAG_TAG); // make gcc happy diff --git a/src/load.c b/src/load.c index 108bf9e6..d3bc1cdc 100644 --- a/src/load.c +++ b/src/load.c @@ -512,8 +512,8 @@ void load_init() { // very last init function printI(interp); printf("\n"); dec(interp); - #ifdef HEAP_VERIFY - heapVerify(); + #if HEAP_VERIFY + cbqn_heapVerify(); #endif rtWrap_print(); CTR_FOR(CTR_PRINT) @@ -551,7 +551,6 @@ void load_init() { // very last init function decG(fmtR); #endif - gc_enable(); #endif // PRECOMP } @@ -806,6 +805,7 @@ void cbqn_init() { #define F(X) X##_init(); FOR_INIT(F) #undef F - cbqn_initialized = true; + cbqn_initialized = true; + gc_enable(); } #undef FOR_INIT diff --git a/src/main.c b/src/main.c index a0ca35b4..50e0121d 100644 --- a/src/main.c +++ b/src/main.c @@ -825,16 +825,16 @@ void cbqn_runLine(char* ln, i64 len) { fprintf(stderr, "Error: "); printErrMsg(thrownMsg); fputc('\n', stderr); vm_pst(envCurr+1, envStart+envPrevHeight); freeThrown(); - #ifdef HEAP_VERIFY - heapVerify(); + #if HEAP_VERIFY + cbqn_heapVerify(); #endif gc_maybeGC(true); return; } cbqn_takeInterrupts(true); cbqn_runLine0(ln, len); - #ifdef HEAP_VERIFY - heapVerify(); + #if HEAP_VERIFY + cbqn_heapVerify(); #endif gc_maybeGC(true); cbqn_takeInterrupts(false); @@ -983,8 +983,8 @@ int main(int argc, char* argv[]) { execRes = bqn_execFile(src, args); } dec(execRes); - #ifdef HEAP_VERIFY - heapVerify(); + #if HEAP_VERIFY + cbqn_heapVerify(); #endif gc_forceGC(true); } @@ -1045,8 +1045,8 @@ int main(int argc, char* argv[]) { } } } - #ifdef HEAP_VERIFY - heapVerify(); + #if HEAP_VERIFY + cbqn_heapVerify(); #endif bqn_exit(0); #undef INIT diff --git a/src/opt/gc.c b/src/opt/gc.c index 2b8c03b3..90733ffe 100644 --- a/src/opt/gc.c +++ b/src/opt/gc.c @@ -1,8 +1,11 @@ #include "gc.h" -void mm_freeFreedAndMerge(void); +#if ENABLE_GC + static void mm_freeFreedAndMerge(void); +#endif + #ifdef LOG_GC -#include "../utils/time.h" + #include "../utils/time.h" #endif u64 gc_depth = 1; @@ -73,41 +76,45 @@ static void gc_tryFree(Value* v) { u64 gc_visitBytes, gc_visitCount, gc_freedBytes, gc_freedCount, gc_unkRefsBytes, gc_unkRefsCount; #endif -#if GC_VISIT_V2 - i32 visit_mode; - enum { - GC_DEC_REFC, // decrement refcount - GC_INC_REFC, // increment refcount - GC_MARK, // if unmarked, mark & visit - GC_LISTBAD, // - }; - - void gc_onVisit(Value* x) { - switch (visit_mode) { default: UD; - case GC_DEC_REFC: x->refc--; return; - case GC_INC_REFC: x->refc++; return; - case GC_MARK: { - if (x->mmInfo&0x80) return; - x->mmInfo|= 0x80; - #ifdef LOG_GC - gc_visitBytes+= mm_size(x); gc_visitCount++; - #endif - TIv(x,visit)(x); - return; - } +i32 visit_mode; +enum { + GC_DEC_REFC, // decrement refcount + GC_INC_REFC, // increment refcount + GC_MARK, // if unmarked, mark & visit +}; + +void gc_onVisit(Value* x) { + switch (visit_mode) { default: UD; + case GC_DEC_REFC: + #if DEBUG + if(x->refc==0) err("decrementing refc 0"); + #endif + x->refc--; + return; + case GC_INC_REFC: x->refc++; return; + case GC_MARK: { + if (x->mmInfo&0x80) return; + x->mmInfo|= 0x80; + #ifdef LOG_GC + gc_visitBytes+= mm_size(x); gc_visitCount++; + #endif + TIv(x,visit)(x); + return; } } - - static void gcv2_visit(Value* x) { TIv(x,visit)(x); } - - #if HEAP_VERIFY +} + +static void gcv2_visit(Value* x) { TIv(x,visit)(x); } + +#if HEAP_VERIFY void gcv2_runHeapverify(i32 mode) { visit_mode = mode==0? GC_DEC_REFC : GC_INC_REFC; mm_forHeap(gcv2_visit); gc_visitRoots(); } - #endif - +#endif + +#if ENABLE_GC static Value** gcv2_bufS; static Value** gcv2_bufC; static Value** gcv2_bufE; @@ -132,7 +139,7 @@ static void gc_tryFree(Value* v) { if (gcv2_bufC == gcv2_bufE) return gcv2_storeRemainingR(x); gcv2_storeRemainingEnd(x); } - + static void gc_run(bool toplevel) { if (toplevel) { mm_forHeap(gc_resetTag); @@ -157,13 +164,6 @@ static void gc_tryFree(Value* v) { free(gcv2_bufS); } - mm_forHeap(gc_tryFree); - mm_freeFreedAndMerge(); - } -#else - static void gc_run(bool toplevel) { - mm_forHeap(gc_resetTag); - gc_visitRoots(); mm_forHeap(gc_tryFree); mm_freeFreedAndMerge(); } @@ -183,9 +183,7 @@ void gc_forceGC(bool toplevel) { u64 endSize = mm_heapUsed(); #ifdef LOG_GC fprintf(stderr, "GC kept "N64d"B/"N64d" objs, freed "N64d"B, incl. directly "N64d"B/"N64d" objs", gc_visitBytes, gc_visitCount, startSize-endSize, gc_freedBytes, gc_freedCount); - #if GC_VISIT_V2 - fprintf(stderr, "; unknown refs: "N64d"B/"N64d" objs", gc_unkRefsBytes, gc_unkRefsCount); - #endif + fprintf(stderr, "; unknown refs: "N64d"B/"N64d" objs", gc_unkRefsBytes, gc_unkRefsCount); fprintf(stderr, "; took %.3fms\n", (nsTime()-start)/1e6); #endif gc_lastAlloc = endSize; diff --git a/src/opt/gc.h b/src/opt/gc.h index e88cb6c3..0f0c0e35 100644 --- a/src/opt/gc.h +++ b/src/opt/gc.h @@ -8,40 +8,10 @@ static void gc_enable() { gc_depth--; } extern u64 gc_visitBytes, gc_visitCount, gc_freedBytes, gc_freedCount; #endif -#if GC_VISIT_V2 - extern void gc_onVisit(Value*); - static void mm_visit(B x) { - if (isVal(x)) gc_onVisit(v(x)); - } - static void mm_visitP(void* xp) { - gc_onVisit(xp); - } -#else - static void mm_visit(B x) { - #ifdef HEAP_VERIFY - if(heapVerify_visit(x)) return; - #endif - - if (!isVal(x)) return; - Value* vx = v(x); - if (vx->mmInfo&0x80) return; - vx->mmInfo|= 0x80; - #ifdef LOG_GC - gc_visitBytes+= mm_size(vx); gc_visitCount++; - #endif - TI(x,visit)(vx); - } - static void mm_visitP(void* xp) { - #ifdef HEAP_VERIFY - if(heapVerify_visitP(xp)) return; - #endif - - Value* x = (Value*)xp; - if (x->mmInfo&0x80) return; - x->mmInfo|= 0x80; - #ifdef LOG_GC - gc_visitBytes+= mm_size(x); gc_visitCount++; - #endif - TIv(x,visit)(x); - } -#endif \ No newline at end of file +extern void gc_onVisit(Value*); +static void mm_visit(B x) { + if (isVal(x)) gc_onVisit(v(x)); +} +static void mm_visitP(void* xp) { + gc_onVisit(xp); +} diff --git a/src/opt/mm_2buddy.c b/src/opt/mm_2buddy.c index 18070b4a..29d88630 100644 --- a/src/opt/mm_2buddy.c +++ b/src/opt/mm_2buddy.c @@ -47,7 +47,7 @@ void mm_forFreedHeap(V2v f) { b1_forFreedHeap(f); b3_forFreedHeap(f); } -void mm_freeFreedAndMerge() { +static void mm_freeFreedAndMerge() { b1_freeFreedAndMerge(); b3_freeFreedAndMerge(); } diff --git a/src/opt/mm_buddyTemplate.c b/src/opt/mm_buddyTemplate.c index 4a30cb19..8f39598f 100644 --- a/src/opt/mm_buddyTemplate.c +++ b/src/opt/mm_buddyTemplate.c @@ -36,7 +36,7 @@ FORCE_INLINE void BN(splitTo)(EmptyValue* c, i64 from, i64 to, bool notEqual) { buckets[from] = c; } -#if GC_VISIT_V2 && !BUDDY_NO_GC +#if !BUDDY_NO_GC && ENABLE_GC static bool BN(allocMore_rec); #endif @@ -44,12 +44,12 @@ static NOINLINE void* BN(allocateMore)(i64 bucket, u8 type, i64 from, i64 to) { u64 sz = BSZ(from); CHECK_INTERRUPT; - #if GC_VISIT_V2 && !BUDDY_NO_GC + #if !BUDDY_NO_GC && ENABLE_GC if (gc_maybeGC(false)) goto alloc_rec; #endif if (mm_heapAlloc+sz >= mm_heapMax) { - #if GC_VISIT_V2 && !BUDDY_NO_GC + #if !BUDDY_NO_GC && ENABLE_GC if (!BN(allocMore_rec)) { gc_forceGC(false); BN(allocMore_rec) = true; @@ -130,6 +130,7 @@ void BN(forFreedHeap)(V2v f) { } } } +#if !BUDDY_NO_GC && ENABLE_GC static void BN(freeFreedAndMerge)() { for (u64 i = 0; i < 64; i++) buckets[i] = NULL; @@ -140,7 +141,7 @@ static void BN(freeFreedAndMerge)() { Value* e = (Value*)(ci.sz + (u8*)ci.p); assert(c!=e); while (true) { - if (vg_def_v(c->type)==t_freed) BN(freeLink)(c, false); + if (vg_def_v(c->type)==t_freed) mm_freeLink(c, false); Value* next = (Value*)(BSZ(vg_def_v(c->mmInfo)&63) + (u8*)c); if (vg_def_v(c->type)==t_empty) { @@ -159,6 +160,7 @@ static void BN(freeFreedAndMerge)() { .mmInfo = MMI(b), .next = buckets[b] }; + vg_undef_p(cv, sizeof(EmptyValue)); buckets[b] = cv; emptyStart+= curr*MUL; @@ -175,6 +177,7 @@ static void BN(freeFreedAndMerge)() { } } } +#endif void writeNum(FILE* f, u64 v, i32 len); void BN(dumpHeap)(FILE* f) { diff --git a/src/opt/mm_malloc.h b/src/opt/mm_malloc.h index 29d8a370..edadcf0a 100644 --- a/src/opt/mm_malloc.h +++ b/src/opt/mm_malloc.h @@ -23,7 +23,7 @@ static void gc_enable() { } static void mm_visit(B x) { } static void mm_visitP(void* x) { } -void gc_maybeGC(bool); +bool gc_maybeGC(bool); void gc_forceGC(bool); void mm_forHeap(V2v f); void mm_dumpHeap(FILE* f); diff --git a/src/vm.c b/src/vm.c index 88eb7f00..b46875c3 100644 --- a/src/vm.c +++ b/src/vm.c @@ -690,7 +690,7 @@ B evalBC(Body* b, Scope* sc, Block* bl) { // doesn't consume if (!vmStack) vmStack = malloc(400); i32 stackNum = bcDepth>>1; vmStack[stackNum] = -1; - printf("new eval\n"); + fprintf(stderr,"new eval\n"); B* origStack = gStack; #endif u32* bc = b->bc; @@ -728,9 +728,9 @@ B evalBC(Body* b, Scope* sc, Block* bl) { // doesn't consume u32* sbc = bc; i32 bcPos = BCPOS(b,sbc); vmStack[stackNum] = bcPos; - for(i32 i = 0; i < bcDepth; i++) printf(" "); - print_BC(sbc,20); printf("@%d in: ", bcPos); - for (i32 i = 0; i < lgStack-origStack; i++) { if(i)printf("; "); printI(origStack[i]); } putchar('\n'); fflush(stdout); + for(i32 i = 0; i < bcDepth; i++) fprintf(stderr," "); + print_BC(stderr,sbc,20); fprintf(stderr,"@%d in: ",bcPos); + for (i32 i = 0; i < lgStack-origStack; i++) { if(i)fprintf(stderr,"; "); fprintI(stderr,origStack[i]); } fputc('\n',stderr); fflush(stderr); bcCtr++; for (i32 i = 0; i < sc->varAm; i++) VALIDATE(sc->vars[i]); #endif @@ -930,9 +930,9 @@ B evalBC(Body* b, Scope* sc, Block* bl) { // doesn't consume #endif } #ifdef DEBUG_VM - for(i32 i = 0; i < bcDepth; i++) printf(" "); - print_BC(sbc,20); printf("@%d out: ", BCPOS(b, sbc)); - for (i32 i = 0; i < lgStack-origStack; i++) { if(i)printf("; "); printI(origStack[i]); } putchar('\n'); fflush(stdout); + for(i32 i = 0; i < bcDepth; i++) fprintf(stderr," "); + print_BC(stderr,sbc,20); fprintf(stderr,"@%d out: ",BCPOS(b, sbc)); + for (i32 i = 0; i < lgStack-origStack; i++) { if(i)fprintf(stderr,"; "); fprintI(stderr,origStack[i]); } fputc('\n',stderr); fflush(stderr); #endif } end:; diff --git a/test/moreCfgs.sh b/test/moreCfgs.sh index 35981810..bf08a179 100755 --- a/test/moreCfgs.sh +++ b/test/moreCfgs.sh @@ -3,13 +3,13 @@ if [ "$#" -ne 1 ]; then echo "Usage: $0 path/to/mlochbaum/BQN" exit fi -make && ./BQN -p 2+2 || exit -make single-debug && ./BQN -p 2+2 || exit -make heapverify && ./BQN -p 2+2 || exit -make rtverify && ./BQN -p 2+2 || exit -make rtperf && ./BQN -p 2+2 | head -2 || exit -make f='-DDEBUG -DDEBUG_VM' c && ./BQN -p 2+2 | tail -2 || exit -make f='-DWARN_SLOW' c && ./BQN -p 2+2 2> /dev/null || exit +make && ./BQN -p 2+2 || exit +make single-debug && ./BQN -p 2+2 || exit +make heapverify && ./BQN -p 2+2 || exit +make rtverify && ./BQN -p 2+2 || exit +make rtperf && ./BQN -p 2+2 | head -2 || exit +make f='-DDEBUG -DDEBUG_VM' c && ./BQN -p 2+2 2>&1 | tail -2 || exit +make f='-DWARN_SLOW' c && ./BQN -p 2+2 2> /dev/null || exit make f='-DMM=0 -DENABLE_GC=0' c && ./BQN -p 2+2 || exit make f='-DMM=1' c && ./BQN -p 2+2 || exit make f='-DMM=2' c && ./BQN -p 2+2 || exit