MAKE_MUT_INIT, move mut_init to mut.c

This commit is contained in:
dzaima 2023-03-06 22:22:33 +02:00
parent 3f0bc57503
commit 8194f51b30
10 changed files with 103 additions and 102 deletions

View File

@ -137,7 +137,7 @@ B ud_c2(B t, B w, B x) {
usz ria=cia; usz ria=cia;
for (usz i=0; i<fr; i++) if (mulOn(ria, rsh[i])) thrM("↕: result shape too large"); for (usz i=0; i<fr; i++) if (mulOn(ria, rsh[i])) thrM("↕: result shape too large");
TALLOC(usz, ri, fr-1); TALLOC(usz, ri, fr-1);
MAKE_MUT(r, ria); mut_init(r, TI(x,elType)); MAKE_MUT_INIT(r, ria, TI(x,elType));
MUTG_INIT(r); MUTG_INIT(r);
usz k = cia*rsh[fr-1]; usz k = cia*rsh[fr-1];
if (wr==1) { if (wr==1) {

View File

@ -256,7 +256,7 @@ static NOINLINE B select_cells(usz n, B x, ur xr) {
} else { } else {
usz rs = shProd(xsh, 2, xr); usz rs = shProd(xsh, 2, xr);
usz xs = rs*xsh[1]; // aka csz usz xs = rs*xsh[1]; // aka csz
MAKE_MUT(rm, cam*rs); mut_init(rm, TI(x,elType)); MUTG_INIT(rm); MAKE_MUT_INIT(rm, cam*rs, TI(x,elType)); MUTG_INIT(rm);
usz xi = rs*n; usz xi = rs*n;
usz ri = 0; usz ri = 0;
for (usz i = 0; i < cam; i++) { for (usz i = 0; i < cam; i++) {
@ -276,7 +276,7 @@ static NOINLINE B select_cells(usz n, B x, ur xr) {
} }
static NOINLINE B shift_cells(B f, B x, u8 e, u8 rtid) { static NOINLINE B shift_cells(B f, B x, u8 e, u8 rtid) {
MAKE_MUT(r, IA(x)); mut_init(r, e); MUTG_INIT(r); MAKE_MUT_INIT(r, IA(x), e); MUTG_INIT(r);
usz cam = SH(x)[0]; usz cam = SH(x)[0];
usz csz = SH(x)[1]; usz csz = SH(x)[1];
assert(cam!=0 && csz!=0); assert(cam!=0 && csz!=0);

View File

@ -64,7 +64,7 @@ B scan_add_bool(B x, u64 ia) { // consumes x
u8 re = xs<=I8_MAX? el_i8 : xs<=I16_MAX? el_i16 : xs<=I32_MAX? el_i32 : el_f64; u8 re = xs<=I8_MAX? el_i8 : xs<=I16_MAX? el_i16 : xs<=I32_MAX? el_i32 : el_f64;
if (xs < ia/128) { if (xs < ia/128) {
B ones = C1(slash, x); B ones = C1(slash, x);
MAKE_MUT(r0, ia) mut_init(r0, re); MUTG_INIT(r0); MAKE_MUT_INIT(r0, ia, re); MUTG_INIT(r0);
SGetU(ones) SGetU(ones)
usz ri = 0; usz ri = 0;
for (usz i = 0; i < xs; i++) { for (usz i = 0; i < xs; i++) {

View File

@ -311,7 +311,7 @@ B select_c2(B t, B w, B x) {
usz csz = arr_csz(x); usz csz = arr_csz(x);
CFRes f = cf_get(1, csz<<elWidthLogBits(xe)); CFRes f = cf_get(1, csz<<elWidthLogBits(xe));
MAKE_MUT(rm, ria); mut_init(rm, xe); MAKE_MUT_INIT(rm, ria, xe);
usz i = 0; f64 badw; usz i = 0; f64 badw;
if (xe<el_B && elInt(we)) { if (xe<el_B && elInt(we)) {
void* wp = tyany_ptr(w); void* wp = tyany_ptr(w);
@ -472,7 +472,7 @@ B select_ucw(B t, B o, B w, B x) {
return x; return x;
} }
} }
MAKE_MUT(r, xia); mut_init(r, el_or(xe, re)); MAKE_MUT_INIT(r, xia, el_or(xe, re));
MUTG_INIT(r); MUTG_INIT(r);
mut_copyG(r, 0, x, 0, xia); mut_copyG(r, 0, x, 0, xia);
SGet(rep) SGet(rep)
@ -486,7 +486,7 @@ B select_ucw(B t, B o, B w, B x) {
decG(w); decG(rep); FREE_CHECK; decG(w); decG(rep); FREE_CHECK;
return mut_fcd(r, x); return mut_fcd(r, x);
} }
MAKE_MUT(r, xia); mut_init(r, el_or(xe, re)); MAKE_MUT_INIT(r, xia, el_or(xe, re));
MUTG_INIT(r); MUTG_INIT(r);
mut_copyG(r, 0, x, 0, xia); mut_copyG(r, 0, x, 0, xia);
SGet(rep) SGet(rep)

View File

@ -24,8 +24,7 @@ static Arr* take_impl(usz ria, B x) { // consumes x; returns v↑⥊𝕩 without
usz xia = IA(x); usz xia = IA(x);
if (ria>xia) { if (ria>xia) {
B xf = getFillE(x); B xf = getFillE(x);
MAKE_MUT(r, ria); mut_init(r, el_or(TI(x,elType), selfElType(xf))); MAKE_MUT_INIT(r, ria, el_or(TI(x,elType), selfElType(xf))); MUTG_INIT(r);
MUTG_INIT(r);
mut_copyG(r, 0, x, 0, xia); mut_copyG(r, 0, x, 0, xia);
mut_fillG(r, xia, xf, ria-xia); mut_fillG(r, xia, xf, ria-xia);
decG(x); decG(x);
@ -273,8 +272,7 @@ B shape_c2(B t, B w, B x) {
} else { } else {
if (TI(x,elType) == el_B) { if (TI(x,elType) == el_B) {
B xf = getFillQ(x); B xf = getFillQ(x);
MAKE_MUT(m, nia); mut_init(m, el_B); MAKE_MUT_INIT(m, nia, el_B); MUTG_INIT(m);
MUTG_INIT(m);
i64 div = nia/xia; i64 div = nia/xia;
i64 mod = nia%xia; i64 mod = nia%xia;
for (i64 i = 0; i < div; i++) mut_copyG(m, i*xia, x, 0, xia); for (i64 i = 0; i < div; i++) mut_copyG(m, i*xia, x, 0, xia);
@ -526,7 +524,6 @@ NOINLINE B takedrop_highrank(bool take, B w, B x) {
} else if (ria==0) { // printf("empty result\n"); } else if (ria==0) { // printf("empty result\n");
r = taga(arr_shSetU(emptyArr(x, rr), rr, rsh)); r = taga(arr_shSetU(emptyArr(x, rr), rr, rsh));
} else { // printf("generic\n"); } else { // printf("generic\n");
MAKE_MUT(rm, ria); mut_init(rm, TI(x,elType));
B xf = getFillR(x); B xf = getFillR(x);
if (anyFill && noFill(xf)) { if (anyFill && noFill(xf)) {
#if PROPER_FILLS #if PROPER_FILLS
@ -536,7 +533,7 @@ NOINLINE B takedrop_highrank(bool take, B w, B x) {
#endif #endif
} }
MUTG_INIT(rm); MAKE_MUT_INIT(rm, ria, TI(x,elType)); MUTG_INIT(rm);
if (IA(x)==0) { if (IA(x)==0) {
mut_fillG(rm, 0, xf, ria); mut_fillG(rm, 0, xf, ria);
} else { // actual generic copying code } else { // actual generic copying code
@ -657,8 +654,7 @@ B take_c2(B t, B w, B x) {
usz xia = IA(x); usz xia = IA(x);
if (n>xia) { if (n>xia) {
B xf = getFillE(x); B xf = getFillE(x);
MAKE_MUT(r, n); mut_init(r, el_or(TI(x,elType), selfElType(xf))); MAKE_MUT_INIT(r, n, el_or(TI(x,elType), selfElType(xf))); MUTG_INIT(r);
MUTG_INIT(r);
mut_fillG(r, 0, xf, n-xia); mut_fillG(r, 0, xf, n-xia);
mut_copyG(r, n-xia, x, 0, xia); mut_copyG(r, n-xia, x, 0, xia);
decG(x); decG(x);
@ -997,8 +993,7 @@ B couple_c2(B t, B w, B x) {
if (!eqShape(w, x)) thrF("≍: 𝕨 and 𝕩 must have equal shapes (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x); if (!eqShape(w, x)) thrF("≍: 𝕨 and 𝕩 must have equal shapes (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x);
usz ia = IA(w); usz ia = IA(w);
ur wr = RNK(w); ur wr = RNK(w);
MAKE_MUT(r, ia*2); mut_init(r, el_or(TI(w,elType), TI(x,elType))); MAKE_MUT_INIT(r, ia*2, el_or(TI(w,elType), TI(x,elType))); MUTG_INIT(r);
MUTG_INIT(r);
mut_copyG(r, 0, w, 0, ia); mut_copyG(r, 0, w, 0, ia);
mut_copyG(r, ia, x, 0, ia); mut_copyG(r, ia, x, 0, ia);
Arr* ra = mut_fp(r); Arr* ra = mut_fp(r);
@ -1025,8 +1020,7 @@ B shiftb_c1(B t, B x) {
B xf = getFillE(x); B xf = getFillE(x);
usz csz = arr_csz(x); usz csz = arr_csz(x);
MAKE_MUT(r, ia); mut_init(r, el_or(TI(x,elType), selfElType(xf))); MAKE_MUT_INIT(r, ia, el_or(TI(x,elType), selfElType(xf))); MUTG_INIT(r);
MUTG_INIT(r);
mut_copyG(r, csz, x, 0, ia-csz); mut_copyG(r, csz, x, 0, ia-csz);
mut_fillG(r, 0, xf, csz); mut_fillG(r, 0, xf, csz);
return qWithFill(mut_fcd(r, x), xf); return qWithFill(mut_fcd(r, x), xf);
@ -1038,8 +1032,7 @@ B shiftb_c2(B t, B w, B x) {
B f = fill_both(w, x); B f = fill_both(w, x);
usz wia = IA(w); usz wia = IA(w);
usz xia = IA(x); usz xia = IA(x);
MAKE_MUT(r, xia); mut_init(r, el_or(TI(w,elType), TI(x,elType))); MAKE_MUT_INIT(r, xia, el_or(TI(w,elType), TI(x,elType))); MUTG_INIT(r);
MUTG_INIT(r);
int mid = wia<xia? wia : xia; int mid = wia<xia? wia : xia;
mut_copyG(r, 0 , w, 0, mid); mut_copyG(r, 0 , w, 0, mid);
mut_copyG(r, mid, x, 0, xia-mid); mut_copyG(r, mid, x, 0, xia-mid);
@ -1053,8 +1046,7 @@ B shifta_c1(B t, B x) {
if (ia==0) return x; if (ia==0) return x;
B xf = getFillE(x); B xf = getFillE(x);
usz csz = arr_csz(x); usz csz = arr_csz(x);
MAKE_MUT(r, ia); mut_init(r, el_or(TI(x,elType), selfElType(xf))); MAKE_MUT_INIT(r, ia, el_or(TI(x,elType), selfElType(xf))); MUTG_INIT(r);
MUTG_INIT(r);
mut_copyG(r, 0, x, csz, ia-csz); mut_copyG(r, 0, x, csz, ia-csz);
mut_fillG(r, ia-csz, xf, csz); mut_fillG(r, ia-csz, xf, csz);
return qWithFill(mut_fcd(r, x), xf); return qWithFill(mut_fcd(r, x), xf);
@ -1066,8 +1058,7 @@ B shifta_c2(B t, B w, B x) {
B f = fill_both(w, x); B f = fill_both(w, x);
usz wia = IA(w); usz wia = IA(w);
usz xia = IA(x); usz xia = IA(x);
MAKE_MUT(r, xia); mut_init(r, el_or(TI(w,elType), TI(x,elType))); MAKE_MUT_INIT(r, xia, el_or(TI(w,elType), TI(x,elType))); MUTG_INIT(r);
MUTG_INIT(r);
if (wia < xia) { if (wia < xia) {
usz m = xia-wia; usz m = xia-wia;
mut_copyG(r, 0, x, wia, m); mut_copyG(r, 0, x, wia, m);
@ -1132,8 +1123,7 @@ B reverse_c1(B t, B x) {
usz cam = SH(x)[0]; usz cam = SH(x)[0];
usz rp = 0; usz rp = 0;
usz ip = IA(x); usz ip = IA(x);
MAKE_MUT(r, ip); mut_init(r, TI(x,elType)); MAKE_MUT_INIT(r, ip, TI(x,elType)); MUTG_INIT(r);
MUTG_INIT(r);
for (usz i = 0; i < cam; i++) { for (usz i = 0; i < cam; i++) {
ip-= csz; ip-= csz;
mut_copyG(r, rp, x, ip, csz); mut_copyG(r, rp, x, ip, csz);
@ -1200,8 +1190,7 @@ static NOINLINE B rotate_highrank(bool inv, B w, B x) {
ccsz*= xshc; ccsz*= xshc;
} }
MAKE_MUT(rm, IA(x)); mut_init(rm, TI(x,elType)); MAKE_MUT_INIT(rm, IA(x), TI(x,elType)); MUTG_INIT(rm);
MUTG_INIT(rm);
usz n0 = csz*rot0; usz n0 = csz*rot0;
usz n1 = csz*(l0-rot0); usz n1 = csz*(l0-rot0);
@ -1239,8 +1228,7 @@ B reverse_c2(B t, B w, B x) {
i64 am = WRAP_ROT(o2i64(w), cam); i64 am = WRAP_ROT(o2i64(w), cam);
if (am==0) return x; if (am==0) return x;
am*= csz; am*= csz;
MAKE_MUT(r, xia); mut_init(r, TI(x,elType)); MAKE_MUT_INIT(r, xia, TI(x,elType)); MUTG_INIT(r);
MUTG_INIT(r);
mut_copyG(r, 0, x, am, xia-am); mut_copyG(r, 0, x, am, xia-am);
mut_copyG(r, xia-am, x, 0, am); mut_copyG(r, xia-am, x, 0, am);
B xf = getFillQ(x); B xf = getFillQ(x);
@ -1398,8 +1386,7 @@ B pick_uc1(B t, B o, B x) { // TODO do in-place like pick_ucw; maybe just call i
usz ia = IA(x); usz ia = IA(x);
B arg = IGet(x, 0); B arg = IGet(x, 0);
B rep = c1(o, arg); B rep = c1(o, arg);
MAKE_MUT(r, ia); mut_init(r, el_or(TI(x,elType), selfElType(rep))); MAKE_MUT_INIT(r, ia, el_or(TI(x,elType), selfElType(rep))); MUTG_INIT(r);
MUTG_INIT(r);
mut_setG(r, 0, rep); mut_setG(r, 0, rep);
mut_copyG(r, 1, x, 1, ia-1); mut_copyG(r, 1, x, 1, ia-1);
return qWithFill(mut_fcd(r, x), xf); return qWithFill(mut_fcd(r, x), xf);
@ -1442,8 +1429,7 @@ B pick_ucw(B t, B o, B w, B x) {
else if (xt==t_c16arr) { u16* xp = c16any_ptr(x); xp[wi] = o2cG(rep); return x; } else if (xt==t_c16arr) { u16* xp = c16any_ptr(x); xp[wi] = o2cG(rep); return x; }
else if (xt==t_c32arr) { u32* xp = c32any_ptr(x); xp[wi] = o2cG(rep); return x; } else if (xt==t_c32arr) { u32* xp = c32any_ptr(x); xp[wi] = o2cG(rep); return x; }
} }
MAKE_MUT(r, xia); mut_init(r, el_or(TI(x,elType), selfElType(rep))); MAKE_MUT_INIT(r, xia, el_or(TI(x,elType), selfElType(rep))); MUTG_INIT(r);
MUTG_INIT(r);
mut_setG(r, wi, rep); mut_setG(r, wi, rep);
mut_copyG(r, 0, x, 0, wi); mut_copyG(r, 0, x, 0, wi);
mut_copyG(r, wi+1, x, wi+1, xia-wi-1); mut_copyG(r, wi+1, x, wi+1, xia-wi-1);
@ -1466,8 +1452,7 @@ static B takedrop_ucw(i64 wi, B o, u64 am, B x, ux xr) {
usz* repsh = SH(rep); usz* repsh = SH(rep);
if (RNK(rep)==0 || !eqShPart(repsh+1, SH(x)+1, xr-1) || repsh[0]!=am) thrM("𝔽⌾(n⊸↑)𝕩: 𝔽 returned an array with a different shape than n↑𝕩"); if (RNK(rep)==0 || !eqShPart(repsh+1, SH(x)+1, xr-1) || repsh[0]!=am) thrM("𝔽⌾(n⊸↑)𝕩: 𝔽 returned an array with a different shape than n↑𝕩");
MAKE_MUT(r, xia); MAKE_MUT_INIT(r, xia, el_or(TI(x,elType), TI(rep,elType))); MUTG_INIT(r);
mut_init(r, el_or(TI(x,elType), TI(rep,elType))); MUTG_INIT(r);
if (wi<0) { if (wi<0) {
mut_copyG(r, 0, x, 0, lv); mut_copyG(r, 0, x, 0, lv);
mut_copyG(r, lv, rep, 0, tk); mut_copyG(r, lv, rep, 0, tk);

View File

@ -687,7 +687,7 @@ B slash_c2(B t, B w, B x) {
SLOW2("𝕨/𝕩", w, x); SLOW2("𝕨/𝕩", w, x);
B xf = getFillQ(x); B xf = getFillQ(x);
usz csz = arr_csz(x); usz csz = arr_csz(x);
MAKE_MUT(r0, s*csz) mut_init(r0, TI(x,elType)); MUTG_INIT(r0); MAKE_MUT_INIT(r0, s*csz, TI(x,elType)); MUTG_INIT(r0);
SGetU(w) SGetU(w)
if (csz!=1) { usz ri=0; for (ux i=0; i<wia; i++) { usz c=o2s(GetU(w, i)); for(ux j=0;j<c;j++) { mut_copyG(r0, ri, x, i*csz, csz); ri+= csz; } } } if (csz!=1) { usz ri=0; for (ux i=0; i<wia; i++) { usz c=o2s(GetU(w, i)); for(ux j=0;j<c;j++) { mut_copyG(r0, ri, x, i*csz, csz); ri+= csz; } } }
else { SGetU(x) usz ri=0; for (ux i=0; i<wia; i++) { usz c=o2s(GetU(w, i)); if (c) { mut_fillG(r0, ri, GetU(x, i), c); ri+= c; } } } else { SGetU(x) usz ri=0; for (ux i=0; i<wia; i++) { usz c=o2s(GetU(w, i)); if (c) { mut_fillG(r0, ri, GetU(x, i), c); ri+= c; } } }
@ -768,7 +768,7 @@ B slash_c2(B t, B w, B x) {
if (xl>6 || (xl<3 && xl!=0) || TI(x,elType)==el_B) { if (xl>6 || (xl<3 && xl!=0) || TI(x,elType)==el_B) {
B xf = getFillQ(x); B xf = getFillQ(x);
if (xr!=1) { if (xr!=1) {
MAKE_MUT(r0, IA(x) * wv) mut_init(r0, TI(x,elType)); MUTG_INIT(r0); MAKE_MUT_INIT(r0, IA(x) * wv, TI(x,elType)); MUTG_INIT(r0);
usz csz = arr_csz(x); usz csz = arr_csz(x);
ux ri = 0; ux ri = 0;
for (ux i = 0; i < xlen; i++) for (ux j = 0; j < wv; j++) { for (ux i = 0; i < xlen; i++) for (ux j = 0; j < wv; j++) {
@ -971,7 +971,7 @@ B slash_ucw(B t, B o, B w, B x) {
usz argIA = IA(arg); usz argIA = IA(arg);
B rep = c1(o, arg); B rep = c1(o, arg);
if (isAtm(rep) || RNK(rep)!=1 || IA(rep) != argIA) thrF("𝔽⌾(a⊸/)𝕩: Result of 𝔽 must have the same shape as a/𝕩 (expected ⟨%s⟩, got %H)", argIA, rep); if (isAtm(rep) || RNK(rep)!=1 || IA(rep) != argIA) thrF("𝔽⌾(a⊸/)𝕩: Result of 𝔽 must have the same shape as a/𝕩 (expected ⟨%s⟩, got %H)", argIA, rep);
MAKE_MUT(r, ia); mut_init(r, el_or(TI(x,elType), TI(rep,elType))); MAKE_MUT_INIT(r, ia, el_or(TI(x,elType), TI(rep,elType)));
SGet(x) SGet(x)
SGet(rep) SGet(rep)
usz repI = 0; usz repI = 0;
@ -979,7 +979,7 @@ B slash_ucw(B t, B o, B w, B x) {
u64* d = bitarr_ptr(w); u64* d = bitarr_ptr(w);
if (elInt(TI(x,elType)) && elInt(TI(rep,elType))) { if (elInt(TI(x,elType)) && elInt(TI(rep,elType))) {
if (r->fns->elType!=el_i32) mut_to(r, el_i32); if (r->fns->elType!=el_i32) mut_to(r, el_i32);
i32* rp = r->ai32; i32* rp = r->a;
x = toI32Any(x); i32* xp = i32any_ptr(x); x = toI32Any(x); i32* xp = i32any_ptr(x);
rep = toI32Any(rep); i32* np = i32any_ptr(rep); rep = toI32Any(rep); i32* np = i32any_ptr(rep);
for (usz i = 0; i < ia; i++) { for (usz i = 0; i < ia; i++) {

View File

@ -408,10 +408,10 @@ BQNFFIEnt ffi_parseType(B arg, bool forRes) { // doesn't consume; parse argument
} }
arg = chr_squeezeChk(inc(arg)); arg = chr_squeezeChk(inc(arg));
MAKE_MUT(tmp, ia+1); mut_init(tmp, el_c32); MUTG_INIT(tmp); MAKE_MUT_INIT(tmp, ia+1, el_c32); MUTG_INIT(tmp);
mut_copyG(tmp, 0, arg, 0, ia); mut_copyG(tmp, 0, arg, 0, ia);
mut_setG(tmp, ia, m_c32(0)); mut_setG(tmp, ia, m_c32(0));
u32* xp = tmp->ac32; u32* xp = tmp->a;
u32* xpN = xp + ia; u32* xpN = xp + ia;
BQNFFIEnt t; BQNFFIEnt t;

View File

@ -419,7 +419,7 @@ B nativeComp_c2(B t, B w, B x) {
B tokens = nc_tokenize(prims, sysvs, xBuf, xia, &fnBlock); B tokens = nc_tokenize(prims, sysvs, xBuf, xia, &fnBlock);
decG(xBufO); decG(xBufO);
// // parse // parse
B objs = emptyHVec(); B objs = emptyHVec();
i32* bc0; i32* bc0;
B bytecode = m_i32arrv(&bc0, fnBlock? 3 : 0); B bytecode = m_i32arrv(&bc0, fnBlock? 3 : 0);

View File

@ -1,6 +1,42 @@
#include "../core.h" #include "../core.h"
#include "mut.h" #include "mut.h"
FORCE_INLINE void mut_init(Mut* m, u8 n) {
m->fns = &mutFns[n];
usz ia = m->ia;
u64 sz;
// hack around inlining of the allocator too many times
switch(n) { default: UD;
case el_bit: sz = BITARR_SZ( ia); break;
case el_i8: case el_c8: sz = TYARR_SZ(I8, ia); break;
case el_i16: case el_c16: sz = TYARR_SZ(I16,ia); break;
case el_i32: case el_c32: sz = TYARR_SZ(I32,ia); break;
case el_f64: sz = TYARR_SZ(F64,ia); break;
case el_B:;
HArr_p t = m_harrUp(ia);
m->val = (Arr*)t.c;
m->a = t.c->a;
return;
}
Arr* a = m_arr(sz, m->fns->valType, ia);
m->val = a;
m->a = ((TyArr*)a)->a;
}
#if __clang__
NOINLINE void make_mut_init(Mut* rp, ux ia, u8 el) {
MAKE_MUT(r, ia)
mut_init(r, el);
*rp = r_val;
}
#else
NOINLINE Mut make_mut_init(ux ia, u8 el) {
MAKE_MUT(r, ia)
mut_init(r, el);
return r_val;
}
#endif
static Arr* (*cpyFns[])(B) = { static Arr* (*cpyFns[])(B) = {
[el_bit] = cpyBitArr, [el_bit] = cpyBitArr,
[el_i8] = cpyI8Arr, [el_c8] = cpyC8Arr, [el_i8] = cpyI8Arr, [el_c8] = cpyC8Arr,
@ -35,8 +71,7 @@ NOINLINE void mut_to(Mut* m, u8 n) {
NOINLINE B vec_addF(B w, B x) { NOINLINE B vec_addF(B w, B x) {
usz wia = IA(w); usz wia = IA(w);
MAKE_MUT(r, wia+1); mut_init(r, el_or(TI(w,elType), selfElType(x))); MAKE_MUT_INIT(r, wia+1, el_or(TI(w,elType), selfElType(x))); MUTG_INIT(r);
MUTG_INIT(r);
mut_copyG(r, 0, w, 0, wia); mut_copyG(r, 0, w, 0, wia);
mut_setG(r, wia, x); mut_setG(r, wia, x);
dec(w); dec(w);
@ -383,16 +418,16 @@ MAKE_CCPY(C32, c32)
static B m_getU_MAX(Mut* m, usz ms) { err("m_setG_MAX"); } static B m_getU_MAX(void* a, usz ms) { err("m_setG_MAX"); }
static B m_getU_bit(Mut* m, usz ms) { return m_i32(bitp_get(m->abit, ms)); } static B m_getU_bit(void* a, usz ms) { return m_i32(bitp_get(((u64*) a), ms)); }
static B m_getU_i8 (Mut* m, usz ms) { return m_i32(m->ai8 [ms]); } static B m_getU_i8 (void* a, usz ms) { return m_i32(((i8* ) a)[ms]); }
static B m_getU_i16(Mut* m, usz ms) { return m_i32(m->ai16[ms]); } static B m_getU_i16(void* a, usz ms) { return m_i32(((i16*) a)[ms]); }
static B m_getU_i32(Mut* m, usz ms) { return m_i32(m->ai32[ms]); } static B m_getU_i32(void* a, usz ms) { return m_i32(((i32*) a)[ms]); }
static B m_getU_c8 (Mut* m, usz ms) { return m_c32(m->ac8 [ms]); } static B m_getU_c8 (void* a, usz ms) { return m_c32(((u8* ) a)[ms]); }
static B m_getU_c16(Mut* m, usz ms) { return m_c32(m->ac16[ms]); } static B m_getU_c16(void* a, usz ms) { return m_c32(((u16*) a)[ms]); }
static B m_getU_c32(Mut* m, usz ms) { return m_c32(m->ac32[ms]); } static B m_getU_c32(void* a, usz ms) { return m_c32(((u32*) a)[ms]); }
static B m_getU_f64(Mut* m, usz ms) { return m_f64(m->af64[ms]); } static B m_getU_f64(void* a, usz ms) { return m_f64(((f64*) a)[ms]); }
static B m_getU_B (Mut* m, usz ms) { return m->aB[ms]; } static B m_getU_B (void* a, usz ms) { return ((B*) a)[ms]; }
M_CopyF copyFns[el_MAX]; M_CopyF copyFns[el_MAX];
M_FillF fillFns[el_MAX]; M_FillF fillFns[el_MAX];

View File

@ -3,20 +3,21 @@
/* Usage: /* Usage:
Start with MAKE_MUT(name, itemAmount); Start with MAKE_MUT(name, itemAmount) or MAKE_MUT_INIT(name, itemAmount, elType).
MAKE_MUT allocates the object on the stack, so everything must happen within the scope of it. Those allocate the Mut instance on the stack, so it must be finished before the scope ends.
Optionally, call mut_init(name, el_something) with an appropriate ElType. MAKE_MUT doesn't allocate any backing array, and will do so during mut_(set|fill|copy) (one of which must be the next operation on the Mut).
End with mut_f(v|c|cd|p); MAKE_MUT_INIT makes a backing array with the specified element type; mut_(set|fill|copy) can still widen it, but the primary use-case is for the G-postfixed functions.
There must be no allocations while a mut object is being built so GC doesn't do bad things. End with mut_f(v|c|cd|p);.
mut_pfree must be used to free a partially finished `mut` instance safely (e.g. before throwing an error).
Methods ending with G expect that mut_init has been called with a type that can fit the elements that it'll set, and MUTG_INIT afterwards in the same scope. There must be no allocations while a mut object is being built so GC doesn't read the partially-initialized object.
mut_pfree must be used to free a partially filled `mut` instance safely (e.g. before throwing an error).
*/ */
typedef struct Mut Mut; typedef struct Mut Mut;
typedef struct MutFns MutFns; typedef struct MutFns MutFns;
typedef void (*M_SetF)(void*, usz, B); typedef void (*M_SetF)(void*, usz, B);
typedef B (*M_GetF)(Mut*, usz); typedef B (*M_GetF)(void*, usz);
struct MutFns { struct MutFns {
u8 elType; u8 elType;
u8 valType; u8 valType;
@ -31,37 +32,18 @@ struct Mut {
MutFns* fns; MutFns* fns;
usz ia; usz ia;
Arr* val; Arr* val;
union { void* a;
void* a; B* aB;
i8* ai8; i16* ai16; i32* ai32;
u8* ac8; u16* ac16; u32* ac32;
f64* af64; u64* abit;
};
}; };
#define MAKE_MUT(N, IA) Mut N##_val; N##_val.fns = &mutFns[el_MAX]; N##_val.ia = (IA); Mut* N = &N##_val;
static void mut_init(Mut* m, u8 n) {
m->fns = &mutFns[n];
usz ia = PIA(m);
u64 sz;
// hack around inlining of the allocator too many times
switch(n) { default: UD;
case el_bit: sz = BITARR_SZ( ia); break;
case el_i8: case el_c8: sz = TYARR_SZ(I8, ia); break;
case el_i16: case el_c16: sz = TYARR_SZ(I16,ia); break;
case el_i32: case el_c32: sz = TYARR_SZ(I32,ia); break;
case el_f64: sz = TYARR_SZ(F64,ia); break;
case el_B:;
HArr_p t = m_harrUp(ia);
m->val = (Arr*)t.c;
m->aB = t.c->a;
return;
}
Arr* a = m_arr(sz, m->fns->valType, ia);
m->val = a;
m->a = ((TyArr*)a)->a;
}
void mut_to(Mut* m, u8 n); void mut_to(Mut* m, u8 n);
#if __clang__ && __has_attribute(noescape) // workaround for clang not realizing that stack-returned structs aren't captured
void make_mut_init(__attribute__((noescape)) Mut* rp, ux ia, u8 el);
#define MAKE_MUT_INIT(N, IA, EL) Mut N##_val; Mut* N = &N##_val; make_mut_init(N, IA, EL);
#else
Mut make_mut_init(ux ia, u8 el);
#define MAKE_MUT_INIT(N, IA, EL) Mut N##_val = make_mut_init(IA, EL); Mut* N = &N##_val;
#endif
#define MAKE_MUT(N, IA) Mut N##_val; N##_val.fns = &mutFns[el_MAX]; N##_val.ia = (IA); Mut* N = &N##_val;
static B mut_fv(Mut* m) { assert(m->fns->elType!=el_MAX); static B mut_fv(Mut* m) { assert(m->fns->elType!=el_MAX);
NOGC_E; NOGC_E;
@ -70,13 +52,13 @@ static B mut_fv(Mut* m) { assert(m->fns->elType!=el_MAX);
SPRNK(a, 1); SPRNK(a, 1);
return taga(a); return taga(a);
} }
static B mut_fc(Mut* m, B x) { assert(m->fns->elType!=el_MAX); static B mut_fc(Mut* m, B x) { assert(m->fns->elType!=el_MAX); // doesn't consume x
NOGC_E; NOGC_E;
Arr* a = m->val; Arr* a = m->val;
arr_shCopy(a, x); arr_shCopy(a, x);
return taga(a); return taga(a);
} }
static B mut_fcd(Mut* m, B x) { assert(m->fns->elType!=el_MAX); static B mut_fcd(Mut* m, B x) { assert(m->fns->elType!=el_MAX); // consumes x
NOGC_E; NOGC_E;
Arr* a = m->val; Arr* a = m->val;
arr_shCopy(a, x); arr_shCopy(a, x);
@ -100,25 +82,24 @@ static void mut_set(Mut* m, usz ms, B x) { m->fns->m_set(m, ms, x); }
// clears the object (decrements its refcount) at position ms // clears the object (decrements its refcount) at position ms
static void mut_rm(Mut* m, usz ms) { if (m->fns->elType == el_B) dec(m->aB[ms]); } static void mut_rm(Mut* m, usz ms) { if (m->fns->elType == el_B) dec(((B*)m->a)[ms]); }
// gets object at position ms, without increasing refcount // gets object at position ms, without increasing refcount
static B mut_getU(Mut* m, usz ms) { return m->fns->m_getU(m, ms); } static B mut_getU(Mut* m, usz ms) { return m->fns->m_getU(m->a, ms); }
// doesn't consume; fills m[ms…ms+l] with x // doesn't consume; fills m[ms…ms+l] with x
static void mut_fill(Mut* m, usz ms, B x, usz l) { m->fns->m_fill(m, ms, x, l); } static void mut_fill(Mut* m, usz ms, B x, usz l) { m->fns->m_fill(m, ms, x, l); }
// expects x to be an array, each position must be written to precisely once // doesn't consume; expects x to be an array, each position must be written to precisely once
// doesn't consume
static void mut_copy(Mut* m, usz ms, B x, usz xs, usz l) { assert(isArr(x)); m->fns->m_copy(m, ms, x, xs, l); } static void mut_copy(Mut* m, usz ms, B x, usz xs, usz l) { assert(isArr(x)); m->fns->m_copy(m, ms, x, xs, l); }
#define MUTG_INIT(N) MutFns N##_mutfns = *N->fns; void* N##_mutarr = N->a #define MUTG_INIT(N) MutFns N##_mutfns = *N->fns; void* N##_mutarr = N->a
// // mut_set but assumes the type of x already fits in m // these methods function as the non-G-postfixed ones, except that
// the MAKE_MUT_INIT must have been used, MUTG_INIT called, and x must fit into the array type initialized to
#define mut_setG(N, ms, x) N##_mutfns.m_setG(N##_mutarr, ms, x) #define mut_setG(N, ms, x) N##_mutfns.m_setG(N##_mutarr, ms, x)
// // mut_fill but assumes the type of x already fits in m
#define mut_fillG(N, ms, x, l) N##_mutfns.m_fillG(N##_mutarr, ms, x, l) #define mut_fillG(N, ms, x, l) N##_mutfns.m_fillG(N##_mutarr, ms, x, l)
// // mut_copy but assumes the type of x already fits in m
#define mut_copyG(N, ms, x, xs, l) N##_mutfns.m_copyG(N##_mutarr, ms, x, xs, l) #define mut_copyG(N, ms, x, xs, l) N##_mutfns.m_copyG(N##_mutarr, ms, x, xs, l)
@ -187,7 +168,7 @@ FORCE_INLINE B arr_join_inline(B w, B x, bool consume, bool* reusedW) {
case t_harr: if (fsizeof(HArr,a,B,ria)<wsz) { rp = harr_ptr(w); goto yes; } break; case t_harr: if (fsizeof(HArr,a,B,ria)<wsz) { rp = harr_ptr(w); goto yes; } break;
} }
no:; // failed to reuse no:; // failed to reuse
MAKE_MUT(r, ria); mut_init(r, el_or(TI(w,elType), TI(x,elType))); MAKE_MUT_INIT(r, ria, el_or(TI(w,elType), TI(x,elType)));
MUTG_INIT(r); MUTG_INIT(r);
mut_copyG(r, 0, w, 0, wia); mut_copyG(r, 0, w, 0, wia);
mut_copyG(r, wia, x, 0, xia); mut_copyG(r, wia, x, 0, xia);