diff --git a/src/builtins/fns.c b/src/builtins/fns.c index b621973b..5521e5cd 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -80,10 +80,9 @@ B ud_c1(B t, B x) { } decG(x); - Arr* r = m_fillarrp(ria); fillarr_setFill(r, m_f64(0)); - B* rp = fillarr_ptr(r); - FILL_TO(rp, el_B, 0, m_f64(0), ria); // don't have r in undefined state if allocation errors + Arr* r = m_fillarr0p(ria); + B* rp = fillarr_ptr(r); ud_rec(rp, 0, xia, pos, sh); usz* rsh = arr_shAlloc(r, xia); @@ -135,8 +134,7 @@ B ud_c2(B t, B w, B x) { for (usz i=wr; i (i64)(USZ_MAX)) thrOOM(); - Arr* r = arr_shVec(m_fillarrp(ria)); fillarr_setFill(r, m_f64(0)); + Arr* r = m_fillarr0p(ria); B* rp = fillarr_ptr(r); - for (usz i = 0; i < ria; i++) rp[i] = m_f64(0); // don't break if allocation errors B xf = getFillQ(x); - Arr* rf = m_fillarrp(0); fillarr_setFill(rf, xf); + Arr* rf = m_fillarrpEmpty(xf); if (xr==1) arr_shVec(rf); else arr_shChangeLen(rf, xr, xsh, 0); B z = taga(rf); @@ -229,12 +228,14 @@ static B group_simple(B w, B x, ur xr, usz wia, usz xn, usz* xsh, u8 we) { Arr* c = m_fillarrp(l*csz); c->ia = 0; fillarr_setFill(c, inc(xf)); + NOGC_E; // ia=0 means that this is a "safe" array if (xr==1) arr_shVec(c); else arr_shChangeLen(c, xr, xsh, l); rp[i] = taga(c); } if (csz==0) goto done; SLOW2("𝕨⊔𝕩", w, x); SGet(x) + NOGC_S; // ia==0 of the elements means they're in a sort of invalid state; though it should be fine as `x` references all the items that may be in them, so this NOGC isn't strictly necessary if (csz == 1) { for (usz i = 0; i < xn; i++) { i32 n = wp[i]; @@ -250,6 +251,7 @@ static B group_simple(B w, B x, ur xr, usz wia, usz xn, usz* xsh, u8 we) { } } for (usz i = 0; i < ria; i++) a(rp[i])->ia = len[i]*csz; + NOGC_E; } done: @@ -294,27 +296,26 @@ B group_c2(B t, B w, B x) { for (usz i = 0; i < ria; i++) len[i] = pos[i] = 0; for (usz i = 0; i < xn; i++) len[o2i64G(GetU(w, i))]++; - Arr* r = arr_shVec(m_fillarrp(ria)); fillarr_setFill(r, m_f64(0)); - B* rp = fillarr_ptr(r); - for (usz i = 0; i < ria; i++) rp[i] = m_f64(0); // don't break if allocation errors + Arr* r = m_fillarr0p(ria); B xf = getFillQ(x); - + B* rp = fillarr_ptr(r); for (usz i = 0; i < ria; i++) { Arr* c = m_fillarrp(len[i]); c->ia = 0; fillarr_setFill(c, inc(xf)); + NOGC_E; // see comments in group_simple arr_shVec(c); rp[i] = taga(c); } - Arr* rf = m_fillarrp(0); arr_shVec(rf); - fillarr_setFill(rf, xf); - fillarr_setFill(r, taga(rf)); + fillarr_setFill(r, taga(arr_shVec(m_fillarrpEmpty(xf)))); SGet(x) + NOGC_S; for (usz i = 0; i < xn; i++) { i64 n = o2i64G(GetU(w, i)); if (n>=0) fillarr_ptr(a(rp[n]))[pos[n]++] = Get(x, i); } for (usz i = 0; i < ria; i++) a(rp[i])->ia = len[i]; + NOGC_E; decG(w); decG(x); TFREE(lenO); TFREE(pos); return taga(r); } diff --git a/src/builtins/internal.c b/src/builtins/internal.c index 3667696d..b6359854 100644 --- a/src/builtins/internal.c +++ b/src/builtins/internal.c @@ -185,18 +185,13 @@ B variation_c2(B t, B w, B x) { else if (u8_get(&wp, wpE, "f64")) res = taga(cpyF64Arr(incG(x))); else if (u8_get(&wp, wpE, "h" )) res = taga(cpyHArr (incG(x))); else if (u8_get(&wp, wpE, "f")) { - Arr* t = m_fillarrp(xia); - fillarr_setFill(t, getFillQ(x)); - arr_shCopy(t, x); - HArr* h = NULL; + Arr* r = m_fillarrp(xia); + fillarr_setFill(r, getFillQ(x)); + arr_shCopy(r, x); + COPY_TO(fillarr_ptr(r), el_B, 0, x, 0, xia); + NOGC_E; - B* xp = TO_BPTR(x); - - B* rp = fillarr_ptr(t); - for (usz i = 0; i < xia; i++) rp[i] = inc(xp[i]); - if (h) ptr_dec(h); - - res = taga(t); + res = taga(r); } else thrF("•internal.Variation: Bad type \"%R\"", taga(wc)); if (slice) { @@ -255,9 +250,10 @@ static B unshare(B x) { return unshareShape(a(HARR_FC(r, x))); } case t_fillarr: case t_fillslice: { - Arr* r = m_fillarrp(xia); arr_shCopy(r, x); + Arr* r = arr_shCopy(m_fillarr0p(xia), x); fillarr_setFill(r, unshare(getFillQ(x))); - B* rp = fillarr_ptr(r); B* xp = fillarr_ptr(a(x)); + B* rp = fillarr_ptr(r); + B* xp = fillarr_ptr(a(x)); for (usz i = 0; i < xia; i++) rp[i] = unshare(xp[i]); return unshareShape(r); } diff --git a/src/builtins/md1.c b/src/builtins/md1.c index c4fbd30a..7c82b4c5 100644 --- a/src/builtins/md1.c +++ b/src/builtins/md1.c @@ -204,9 +204,7 @@ static B to_fill_cell_1(B x) { // consumes x static B merge_fill_result_1(B rc) { u64 rr = isArr(rc)? RNK(rc)+1ULL : 1; if (rr>UR_MAX) thrM("˘: Result rank too large"); - B rf = getFillQ(rc); - Arr* r = m_fillarrp(0); - fillarr_setFill(r, rf); + Arr* r = m_fillarrpEmpty(getFillQ(rc)); usz* rsh = arr_shAlloc(r, rr); if (rr>1) { rsh[0] = 0; diff --git a/src/builtins/md2.c b/src/builtins/md2.c index e7a64bdf..38e67421 100644 --- a/src/builtins/md2.c +++ b/src/builtins/md2.c @@ -248,9 +248,7 @@ static B to_fill_cell(B x, ur k) { static B merge_fill_result(B rc, ur k, usz* sh) { u64 rr = k; if (isArr(rc)) rr += RNK(rc); if (rr>UR_MAX) thrM("⎉: Result rank too large"); - B rf = getFillQ(rc); - Arr* r = m_fillarrp(0); - fillarr_setFill(r, rf); + Arr* r = m_fillarrpEmpty(getFillQ(rc)); usz* rsh = arr_shAlloc(r, rr); if (rr>1) { shcpy(rsh, sh, k); diff --git a/src/builtins/select.c b/src/builtins/select.c index 7e23b71d..42c5af3a 100644 --- a/src/builtins/select.c +++ b/src/builtins/select.c @@ -126,6 +126,7 @@ B select_c2(B t, B w, B x) { arr_shAtm(r); fillarr_ptr(r)[0] = xv; fillarr_setFill(r, xf); + NOGC_E; rb = taga(r); } decG(x); diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index af3c092d..094ac2d1 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -15,7 +15,7 @@ NOINLINE Arr* emptyArr(B x, ur xr) { if (isF64(xf)) { u64* rp; r = m_bitarrp(&rp, 0); } else if (noFill(xf)) { r = (Arr*) m_harrUp(0).c; } else if (isC32(xf)) { u8* rp; r = m_c8arrp(&rp, 0); } - else { r = m_fillarrp(0); fillarr_setFill(r, xf); } + else { r = m_fillarrpEmpty(xf); } if (xr<=1) arr_rnk01(r, xr); return r; } @@ -53,6 +53,7 @@ B m_vec1(B a) { Arr* ra = arr_shVec(m_fillarrp(1)); fillarr_ptr(ra)[0] = a; fillarr_setFill(ra, m_f64(0)); + NOGC_E; fillarr_setFill(ra, asFill(inc(a))); return taga(ra); } @@ -86,6 +87,7 @@ FORCE_INLINE B m_vec2Base(B a, B b, bool fills) { fillarr_setFill(ra, af); fillarr_ptr(ra)[0] = a; fillarr_ptr(ra)[1] = b; + NOGC_E; return taga(ra); } noFills: @@ -325,10 +327,12 @@ B shape_c2(B t, B w, B x) { else { FILL(c32,u32,c*0x0000000100000001) } } else { incBy(x, nia); // in addition with the existing reference, this covers the filled amount & asFill + B rf = asFill(x); r = m_fillarrp(nia); if (sizeof(B)==8) fill_words(fillarr_ptr(r), x.u, (u64)nia*8); else for (usz i = 0; i < nia; i++) fillarr_ptr(r)[i] = x; - fillarr_setFill(r, asFill(x)); + fillarr_setFill(r, rf); + NOGC_E; } #undef FILL } @@ -1266,6 +1270,7 @@ B pick_ucw(B t, B o, B w, B x) { fillarr_setFill(x2, getFillQ(x)); xp = fillarr_ptr(x2); COPY_TO(xp, el_B, 0, x, 0, xia); + NOGC_E; arr_shCopy(x2, x); dec(x); x = taga(x2); diff --git a/src/builtins/slash.c b/src/builtins/slash.c index 7d2387b9..56939188 100644 --- a/src/builtins/slash.c +++ b/src/builtins/slash.c @@ -328,11 +328,11 @@ static NOINLINE B zeroCells(B x) { // doesn't consume u8 xe = TI(x,elType); B r; ur xr = RNK(x); if (xr==1) { - if (xe==el_B) { B xf = getFillR(x); r = noFill(xf)? emptyHVec() : m_emptyFVec(xf); } + if (xe==el_B) { B xf = getFillR(x); r = noFill(xf)? emptyHVec() : taga(arr_shVec(m_fillarrpEmpty(xf))); } else r = elNum(xe)? emptyIVec() : emptyCVec(); } else { Arr* ra; - if (xe==el_B) { B xf = getFillR(x); if (noFill(xf)) ra = (Arr*)m_harrUp(0).c; else { ra = m_fillarrp(0); fillarr_setFill(ra, xf); } } + if (xe==el_B) { B xf = getFillR(x); ra = noFill(xf)? (Arr*)m_harrUp(0).c : m_fillarrpEmpty(xf); } else m_tyarrp(&ra, 1, 0, elNum(xe)? t_bitarr : t_c8arr); usz* rsh = arr_shAlloc(ra, xr); shcpy(rsh+1, SH(x)+1, xr-1); diff --git a/src/core/fillarr.h b/src/core/fillarr.h index 3ea0dcff..996d474f 100644 --- a/src/core/fillarr.h +++ b/src/core/fillarr.h @@ -60,17 +60,26 @@ static B getFillE(B x) { // errors if there's no fill } -static Arr* m_fillarrp(usz ia) { +static Arr* m_fillarrp(usz ia) { // needs a NOGC_E after fill & all elements are initialized CHECK_IA(ia, sizeof(B)); - return m_arr(fsizeof(FillArr,a,B,ia), t_fillarr, ia); + Arr* r = m_arr(fsizeof(FillArr,a,B,ia), t_fillarr, ia); + NOGC_S; + return r; } static void fillarr_setFill(Arr* x, B fill) { assert(PTY(x)==t_fillarr); ((FillArr*)x)->fill = fill; } // consumes fill static B* fillarr_ptr(Arr* x) { assert(PTY(x)==t_fillarr); return ((FillArr*)x)->a; } - -static B m_emptyFVec(B f) { // consumes f - Arr* r = arr_shVec(m_fillarrp(0)); - fillarr_setFill(r, f); - return taga(r); +static Arr* m_fillarrpEmpty(B fill) { + Arr* r = m_fillarrp(0); + fillarr_setFill(r, fill); + NOGC_E; + return r; +} +static Arr* m_fillarr0p(usz ia) { // zero-initialized fillarr, with both fill & elements set to m_f64(0) + Arr* r = arr_shVec(m_fillarrp(ia)); + fillarr_setFill(r, m_f64(0)); + FILL_TO(fillarr_ptr(r), el_B, 0, m_f64(0), ia); + NOGC_E; + return r; } B m_unit(B x); // consumes diff --git a/src/core/stuff.c b/src/core/stuff.c index 5c050fa6..c5b285b7 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -631,9 +631,7 @@ B bqn_merge(B x) { B xf = getFillE(x); if (isAtm(xf)) { dec(xf); return x; } i32 xfr = RNK(xf); - B xff = getFillQ(xf); - Arr* r = m_fillarrp(0); - fillarr_setFill(r, xff); + Arr* r = m_fillarrpEmpty(getFillQ(xf)); if (xr+xfr > UR_MAX) thrM(">: Result rank too large"); usz* rsh = arr_shAlloc(r, xr+xfr); if (rsh) { diff --git a/src/core/stuff.h b/src/core/stuff.h index 311e8195..29be290c 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -136,6 +136,13 @@ static bool eqShape(B w, B x) { assert(isArr(w)); assert(isArr(x)); return eqShPart(wsh, xsh, wr); } +typedef void (*M_CopyF)(void*, usz, B, usz, usz); +typedef void (*M_FillF)(void*, usz, B, usz); +extern M_CopyF copyFns[el_MAX]; +extern M_FillF fillFns[el_MAX]; +#define COPY_TO(WHERE, ELT, MS, X, XS, LEN) copyFns[ELT](WHERE, MS, X, XS, LEN) +#define FILL_TO(WHERE, ELT, MS, X, LEN) fillFns[ELT](WHERE, MS, X, LEN) + B bit_sel(B b, B e0, B e1); // consumes b; b must be bitarr; b⊏e0‿e1 Arr* allZeroes(usz ia); Arr* allOnes(usz ia); diff --git a/src/core/tyarr.c b/src/core/tyarr.c index 74dc4c9f..5f403b32 100644 --- a/src/core/tyarr.c +++ b/src/core/tyarr.c @@ -101,7 +101,6 @@ void tyarr_init(void) { { u64* tmp; bi_emptyIVec = m_bitarrv(&tmp, 0); gc_add(bi_emptyIVec); } { u8* tmp; bi_emptyCVec = m_c8arrv (&tmp, 0); gc_add(bi_emptyCVec); } - Arr* emptySVec = arr_shVec(m_fillarrp(0)); - fillarr_setFill(emptySVec, emptyCVec()); + Arr* emptySVec = arr_shVec(m_fillarrpEmpty(emptyCVec())); bi_emptySVec = taga(emptySVec); gc_add(bi_emptySVec); } diff --git a/src/utils/calls.h b/src/utils/calls.h index 2caf5320..10a85528 100644 --- a/src/utils/calls.h +++ b/src/utils/calls.h @@ -7,14 +7,6 @@ static inline B m1c1_unsafe(D1C1 m, B f, B x) { Md1D d; d.f=f; return m(&d, x); } static inline B m1c2_unsafe(D1C2 m, B f, B w, B x) { Md1D d; d.f=f; return m(&d, w, x); } -typedef void (*M_CopyF)(void*, usz, B, usz, usz); -typedef void (*M_FillF)(void*, usz, B, usz); -extern M_CopyF copyFns[el_MAX]; -extern M_FillF fillFns[el_MAX]; -#define COPY_TO(WHERE, ELT, MS, X, XS, LEN) copyFns[ELT](WHERE, MS, X, XS, LEN) -#define FILL_TO(WHERE, ELT, MS, X, LEN) fillFns[ELT](WHERE, MS, X, LEN) - - typedef void (*CmpAAFn)(u64*, void*, void*, u64); typedef void (*CmpASFn)(u64*, void*, u64, u64); #define CMP_DEF(F, S) extern Cmp##S##Fn cmp_fns_##F##S[];