diff --git a/src/README.md b/src/README.md index 5bb3f3a7..810f5372 100644 --- a/src/README.md +++ b/src/README.md @@ -248,6 +248,7 @@ usz* sh = HARR_FA(r, 4); // allocate shape for a rank 4 array. To get the result HArr_p r = m_harrUv(10); // 10-item vector HArr_p r = m_harrUc(10, x); // 10-item array with the same shape as x HArr_p r = m_harrUp(10); // 10-item array without any set shape. Use the arr_shWhatever(r.c, …) +// run `NOGC_E;` after filling in the items to resume allowing allocations (not necessary if item count is 0) // you can use withFill to add a fill element to a created array (or manually create a fillarr, see src/core/fillarr.h) diff --git a/src/builtins/md1.c b/src/builtins/md1.c index 4e10054e..f75a90ff 100644 --- a/src/builtins/md1.c +++ b/src/builtins/md1.c @@ -228,7 +228,7 @@ static NOINLINE B select_cells(usz n, B x, ur xr) { SGet(x) HArr_p rp = m_harrUv(cam); for (usz i = 0; i < cam; i++) rp.a[i] = Get(x, i*csz+n); - r = rp.b; + NOGC_E; r=rp.b; } else { void* rp = m_tyarrv(&r, elWidth(xe), cam, el2t(xe)); void* xp = tyany_ptr(x); diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 3704560e..6aca268f 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -932,6 +932,7 @@ B join_c2(B t, B w, B x) { HArr_p r = m_harrUv(2); r.a[0] = IGet(w,0); decG(w); r.a[1] = IGet(x,0); decG(x); + NOGC_E; return qWithFill(r.b, f); } if (c-wr > 1 || c-xr > 1) thrF("∾: Argument ranks must differ by 1 or less (%i≔=š•Ø, %i≔=š•©)", wr, xr); @@ -1115,6 +1116,7 @@ B reverse_c1(B t, B x) { B* xp = arr_bptr(x); if (xp!=NULL) for (usz i=0; iia = wsum; // Shape-setting code at end of compress expects this } @@ -456,8 +458,8 @@ static B compress(B w, B x, usz wia, u8 xl, u8 xt) { #endif break; } - #define COMPRESS_BLOCK(T) \ - usz b = bsp_max; TALLOC(i16, buf, b); \ + #define COMPRESS_BLOCK_PREP(T, PREP) \ + usz b = bsp_max; TALLOC(i16, buf, b); PREP; \ T* rp0=rp; \ for (usz i=0; i6 || (xl<3 && xl!=0) || TI(x,elType)==el_B) { - if (xr != 1) goto base; + if (xr!=1) goto base; SLOW2("š•Ø/š•©", w, x); B xf = getFillQ(x); HArr_p r0 = m_harrUv(s); @@ -767,6 +770,7 @@ B slash_c2(B t, B w, B x) { B cx = incBy(GetU(x, i), wv); for (i64 j = 0; j < wv; j++) *r0.a++ = cx; } + NOGC_E; r = withFill(r0.b, xf); goto decX_ret; } diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 157b0a4f..f05a4249 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -612,6 +612,7 @@ B reBQN_c1(B t, B x) { ptr_dec(initBlock); HArr_p d = m_harrUv(7); d.a[0] = m_f64(replVal); d.a[1] = scVal; for (usz i=2; i<7; i++) d.a[i] = bi_N; + NOGC_E; init_comp(d.a+2, prim, sys); decG(x); return m_nfn(reBQNDesc, d.b); @@ -1619,10 +1620,13 @@ void sysfn_init(void) { usz i = 0; HArr_p dsv_ns0 = m_harrUv(dsv_num); dsv_ns=dsv_ns0.b; gc_add(dsv_ns); for (usz i = 0; i < dsv_num; i++) dsv_ns0.a[i] = m_c8vec_0(dsv_strs[i]); + NOGC_E; + HArr_p dsv_vs0 = m_harrUv(dsv_num); dsv_vs=dsv_vs0.b; gc_add(dsv_vs); #define F(L,N,B) dsv_vs0.a[i] = inc(B); i++; FOR_DEFAULT_SYSVALS(F) #undef F + NOGC_E; #if CATCH_ERRORS lastErrMsg = bi_N; diff --git a/src/core/harr.c b/src/core/harr.c index e4c19c2e..846e65b9 100644 --- a/src/core/harr.c +++ b/src/core/harr.c @@ -59,6 +59,7 @@ B toKCells(B x, ur k) { NOINLINE B m_caB(usz ia, B* a) { HArr_p r = m_harrUv(ia); for (usz i = 0; i < ia; i++) r.a[i] = a[i]; + NOGC_E; return r.b; } diff --git a/src/core/harr.h b/src/core/harr.h index c327c1b0..f3c8592e 100644 --- a/src/core/harr.h +++ b/src/core/harr.h @@ -72,25 +72,25 @@ void harr_abandon_impl(HArr* p); // unsafe-ish things - don't allocate/GC anything before having written to all items -#define m_harr0v(N) ({ usz n_ = (N); HArr_p r_ = m_harrUv(n_); for(usz i=0;iuid) #else diff --git a/src/ffi.c b/src/ffi.c index f6a95781..0f8ba943 100644 --- a/src/ffi.c +++ b/src/ffi.c @@ -130,7 +130,7 @@ EXPORT BQNV bqn_makeF64Arr(size_t r0, const size_t* sh0, const f64* data) { usz EXPORT BQNV bqn_makeC8Arr (size_t r0, const size_t* sh0, const u8* data) { usz ia=calcIA(r0,sh0); u8* rp; Arr* r = m_c8arrp (&rp,ia); CPYSH(r); memcpy(rp,data,ia*1); return makeX(taga(r)); } EXPORT BQNV bqn_makeC16Arr(size_t r0, const size_t* sh0, const u16* data) { usz ia=calcIA(r0,sh0); u16* rp; Arr* r = m_c16arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*2); return makeX(taga(r)); } EXPORT BQNV bqn_makeC32Arr(size_t r0, const size_t* sh0, const u32* data) { usz ia=calcIA(r0,sh0); u32* rp; Arr* r = m_c32arrp(&rp,ia); CPYSH(r); memcpy(rp,data,ia*4); return makeX(taga(r)); } -EXPORT BQNV bqn_makeObjArr(size_t r0, const size_t* sh0, const BQNV* data) { usz ia=calcIA(r0,sh0); HArr_p r = m_harrUp(ia); CPYSH(r.c); copyBData(r.a,data,ia ); return makeX(r.b); } +EXPORT BQNV bqn_makeObjArr(size_t r0, const size_t* sh0, const BQNV* data) { usz ia=calcIA(r0,sh0); HArr_p r = m_harrUp(ia); copyBData(r.a,data,ia); NOGC_E; CPYSH(r.c); return makeX(r.b); } EXPORT BQNV bqn_makeI8Vec (size_t len, const i8* data) { i8* rp; B r = m_i8arrv (&rp,len); memcpy(rp,data,len*1); return makeX(r); } EXPORT BQNV bqn_makeI16Vec(size_t len, const i16* data) { i16* rp; B r = m_i16arrv(&rp,len); memcpy(rp,data,len*2); return makeX(r); } @@ -139,7 +139,7 @@ EXPORT BQNV bqn_makeF64Vec(size_t len, const f64* data) { f64* rp; B r = m_f64a EXPORT BQNV bqn_makeC8Vec (size_t len, const u8* data) { u8* rp; B r = m_c8arrv (&rp,len); memcpy(rp,data,len*1); return makeX(r); } EXPORT BQNV bqn_makeC16Vec(size_t len, const u16* data) { u16* rp; B r = m_c16arrv(&rp,len); memcpy(rp,data,len*2); return makeX(r); } EXPORT BQNV bqn_makeC32Vec(size_t len, const u32* data) { u32* rp; B r = m_c32arrv(&rp,len); memcpy(rp,data,len*4); return makeX(r); } -EXPORT BQNV bqn_makeObjVec(size_t len, const BQNV* data) { HArr_p r = m_harrUv(len); copyBData(r.a,data,len ); return makeX(r.b); } +EXPORT BQNV bqn_makeObjVec(size_t len, const BQNV* data) { HArr_p r = m_harrUv(len); copyBData(r.a,data,len); NOGC_E;return makeX(r.b); } EXPORT BQNV bqn_makeUTF8Str(size_t len, const char* str) { return makeX(utf8Decode(str, len)); } typedef struct BoundFn { @@ -1008,6 +1008,7 @@ void ffi_init(void) { a.a[4] = m_c8vec_0("write"); a.a[5] = m_c8vec_0("close"); a.a[6] = m_c8vec_0("poll"); + NOGC_E; names = a.b; gc_add(names); forbuildDesc = registerNFn(m_c8vec_0("(function for build)"), forbuild_c1, c2_bad); } diff --git a/src/h.h b/src/h.h index 305109f5..b068773c 100644 --- a/src/h.h +++ b/src/h.h @@ -321,11 +321,17 @@ typedef struct Arr { B VALIDATE(B x); Value* VALIDATEP(Value* x); #define UD assert(false); + extern bool cbqn_noAlloc; + NOINLINE void cbqn_NOGC_start(); // function to allow breakpointing + #define NOGC_S cbqn_NOGC_start() + #define NOGC_E cbqn_noAlloc=false #else #define assert(X) {if (!(X)) __builtin_unreachable();} #define VALIDATE(X) (X) #define VALIDATEP(X) (X) #define UD __builtin_unreachable(); + #define NOGC_S + #define NOGC_E #endif #if WARN_SLOW void warn_slow1(char* s, B x); diff --git a/src/jit/nvm_x86_64.c b/src/jit/nvm_x86_64.c index da136734..bd9540e6 100644 --- a/src/jit/nvm_x86_64.c +++ b/src/jit/nvm_x86_64.c @@ -127,7 +127,7 @@ INS B i_LST_p(B el0, i64 sz, B* cStack) { assert(sz>0); bool allNum = isNum(el0); r.a[sz-1] = el0; for (i64 i = 1; i < sz; i++) if (!isNum(r.a[sz-i-1] = GSP)) allNum = false; - GS_UPD; + NOGC_E; GS_UPD; if (allNum) return num_squeeze(r.b); return r.b; } @@ -136,7 +136,7 @@ INS B i_ARMO(B el0, i64 sz, B* cStack) { assert(sz>0); HArr_p r = m_harrUv(sz); r.a[sz-1] = el0; for (i64 i = 1; i < sz; i++) r.a[sz-i-1] = GSP; - GS_UPD; + NOGC_E; GS_UPD; return bqn_merge(r.b); } INS B i_ARMM(B el0, i64 sz, B* cStack) { assert(sz>0); @@ -144,7 +144,7 @@ INS B i_ARMM(B el0, i64 sz, B* cStack) { assert(sz>0); HArr_p r = m_harrUv(sz); // can't use harrs as gStack isn't updated r.a[sz-1] = el0; for (i64 i = 1; i < sz; i++) r.a[sz-i-1] = GSP; - GS_UPD; + NOGC_E; GS_UPD; WrappedObj* a = mm_alloc(sizeof(WrappedObj), t_arrMerge); a->obj = r.b; return tag(a,OBJ_TAG); @@ -388,6 +388,7 @@ static OptRes opt(u32* bc0) { h.a[i] = inc(c.v); RM(c.p); } + NOGC_E; B r = allNum? num_squeeze(h.b) : h.b; cact = 5; TSADD(data, r.u); diff --git a/src/load.c b/src/load.c index f383e6db..1b9a4256 100644 --- a/src/load.c +++ b/src/load.c @@ -468,6 +468,7 @@ void load_init() { // very last init function #endif runtimeH.a[i] = r; } + NOGC_E; decG(rtObjRaw); B* runtime = runtimeH.a; B rtObj = runtimeH.b; diff --git a/src/opt/mm_buddy.h b/src/opt/mm_buddy.h index 6ae248eb..48a0cd17 100644 --- a/src/opt/mm_buddy.h +++ b/src/opt/mm_buddy.h @@ -24,6 +24,9 @@ extern EmptyValue* mm_buckets[64]; ALLOC_FN void* mm_alloc(u64 sz, u8 type) { assert(sz>=16); preAlloc(sz, type); + #if DEBUG + if (cbqn_noAlloc && !gc_depth) err("allocating during noAlloc"); + #endif #if VERIFY_TAIL i64 logAlloc = LOG2(sz + VERIFY_TAIL); #else diff --git a/src/utils/bits.c b/src/utils/bits.c index 04be0330..e76238fa 100644 --- a/src/utils/bits.c +++ b/src/utils/bits.c @@ -74,6 +74,7 @@ NOINLINE B bit_sel(B b, B e0, B e1) { HArr_p ra = m_harrUc(b); SLOW3("bit_sel", e0, e1, b); for (usz i = 0; i < ia; i++) ra.a[i] = bitp_get(bp,i)? e1 : e0; + NOGC_E; u64 c1 = bit_sum(bp, ia); u64 c0 = ia-c1; diff --git a/src/utils/mut.c b/src/utils/mut.c index b0e3bfaa..3d69b8fa 100644 --- a/src/utils/mut.c +++ b/src/utils/mut.c @@ -242,15 +242,15 @@ DEF_G(void, copy, B, (void* a, usz ms, B x, usz xs, usz l), ms, x, x else cpy##T##Arr_BF(xp, rp, ia, xa); \ } \ static copy_fn copy##T##Fns[] = __VA_ARGS__; \ - T##Arr* cpy##T##Arr(B x) { \ - usz ia = IA(x); \ - MAKE; arr_shCopy(r, x); \ - if (ia>0) { \ + T##Arr* cpy##T##Arr(B x) { \ + usz ia = IA(x); \ + MAKE; arr_shCopy(r, x); \ + if (ia>0) { \ copy##T##Fns[TI(x,elType)](tyany_ptr(x), XRP, ia, a(x)); \ - } \ - if (TY) ptr_decT(a(x)); \ - else decG(x); \ - return (T##Arr*)r; \ + } \ + if (TY) ptr_decT(a(x)); \ + else decG(x); \ + NOGC_E; return (T##Arr*)r; \ } #define BIT_PUT(V) bitp_set((u64*)rp, i, o2bG(V)) #define H2T_COPY(T) copy##T##Fns[el_MAX](bxp, rp, ia, xRaw) @@ -342,6 +342,7 @@ DEF_G(void, copy, B, (void* a, usz ms, B x, usz xs, usz l), ms, x, x if (xp!=NULL) { for (usz i=0; ifns->elType!=el_MAX); + NOGC_E; Arr* a = m->val; a->sh = &a->ia; SPRNK(a, 1); return taga(a); } static B mut_fc(Mut* m, B x) { assert(m->fns->elType!=el_MAX); + NOGC_E; Arr* a = m->val; arr_shCopy(a, x); return taga(a); } static B mut_fcd(Mut* m, B x) { assert(m->fns->elType!=el_MAX); + NOGC_E; Arr* a = m->val; arr_shCopy(a, x); decG(x); return taga(a); } static Arr* mut_fp(Mut* m) { assert(m->fns->elType!=el_MAX); + NOGC_E; return m->val; } diff --git a/src/vm.c b/src/vm.c index 83964a87..93cc66d5 100644 --- a/src/vm.c +++ b/src/vm.c @@ -600,6 +600,7 @@ NOINLINE B v_getF(Scope* pscs[], B s) { B* sp = harr_ptr(s); HArr_p r = m_harrUv(ia); for (u64 i = 0; i < ia; i++) r.a[i] = v_get(pscs, sp[i], true); + NOGC_E; return r.b; } else if (isExt(s)) { Scope* sc = pscs[(u16)(s.u>>32)]; @@ -777,6 +778,7 @@ B evalBC(Body* b, Scope* sc, Block* bl) { // doesn't consume HArr_p r = m_harrUv(sz); bool allNum = true; for (i64 i = 0; i < sz; i++) if (!isNum(r.a[sz-i-1] = POP)) allNum = false; + NOGC_E; if (allNum) { GS_UPD; ADD(num_squeeze(r.b)); @@ -898,7 +900,7 @@ B evalBC(Body* b, Scope* sc, Block* bl) { // doesn't consume assert(sz>0); HArr_p r = m_harrUv(sz); for (i64 i = 0; i < sz; i++) r.a[sz-i-1] = POP; - GS_UPD; + NOGC_E; GS_UPD; ADD(bqn_merge(r.b)); break; } @@ -907,7 +909,7 @@ B evalBC(Body* b, Scope* sc, Block* bl) { // doesn't consume assert(sz>0); HArr_p r = m_harrUv(sz); for (i64 i = 0; i < sz; i++) r.a[sz-i-1] = POP; - GS_UPD; + NOGC_E; GS_UPD; WrappedObj* a = mm_alloc(sizeof(WrappedObj), t_arrMerge); a->obj = r.b; ADD(tag(a,OBJ_TAG)); @@ -1626,7 +1628,9 @@ void before_exit(void); NOINLINE NORETURN void throwImpl(bool rethrow) { // printf("gStack %p-%p:\n", gStackStart, gStack); B* c = gStack; // while (c>gStackStart) { printI(*--c); putchar('\n'); } printf("gStack printed\n"); - + #if DEBUG + if (cbqn_noAlloc && !gc_depth) err("throwing during noAlloc"); + #endif if (!rethrow) envPrevHeight = envCurr-envStart + 1; #if CATCH_ERRORS if (cf>cfStart) { // something wants to catch errors