more proper eltype copying helper
fixes c¨⌾(m⊸/)genericlist arr_bptr==NULL path copying input during noAlloc
This commit is contained in:
parent
7e3e4a031f
commit
9e47ce066a
@ -1084,7 +1084,7 @@ B slash_ucw(B t, B o, B w, B x) {
|
||||
|
||||
// (c ; C˙)¨⌾(w⊸/) x
|
||||
#if SINGELI_SIMD
|
||||
if (isFun(o) && TY(o)==t_md1D) {
|
||||
if (MAY_F(isFun(o) && TY(o)==t_md1D)) {
|
||||
u8 xe = TI(x,elType);
|
||||
|
||||
Md1D* od = c(Md1D,o);
|
||||
@ -1109,28 +1109,12 @@ B slash_ucw(B t, B o, B w, B x) {
|
||||
else incByG(c, sum-1);
|
||||
}
|
||||
|
||||
DirectArr r;
|
||||
void* xp;
|
||||
if (re != xe) {
|
||||
assert(xe != el_B);
|
||||
r = toEltypeArr(x, re);
|
||||
x = incG(r.obj);
|
||||
xp = r.data;
|
||||
} else {
|
||||
if (xe==el_B) {
|
||||
r = potentiallyReuse(x);
|
||||
if (r.obj.u == x.u) {
|
||||
xp = r.data;
|
||||
decByMask(bitany_ptr(w), xp, ia, 0);
|
||||
} else {
|
||||
TO_BPTR(x);
|
||||
xp = arr_bptrG(x);
|
||||
incByMask(bitany_ptr(w), xp, ia, 1);
|
||||
}
|
||||
} else {
|
||||
r = potentiallyReuse(x);
|
||||
xp = tyany_ptr(x);
|
||||
}
|
||||
ConvArr r = toEltypeArrX(x, re);
|
||||
assert((xe==el_B) == (r.refState!=0));
|
||||
if (r.refState != 0) {
|
||||
assert(re == el_B);
|
||||
if (r.refState == 1) decByMask(bitany_ptr(w), r.xp, ia, 0);
|
||||
else incByMask(bitany_ptr(w), r.xp, ia, 1);
|
||||
}
|
||||
|
||||
u64 cv;
|
||||
@ -1141,10 +1125,10 @@ B slash_ucw(B t, B o, B w, B x) {
|
||||
cv = re==el_f64? r_f64u(o2fG(c)) : r_Bu(c);
|
||||
}
|
||||
|
||||
blendArrScalarFns[elwBitLog(re)](r.data, xp, cv, bitany_ptr(w), ia);
|
||||
blendArrScalarFns[elwBitLog(re)](r.rp, r.xp, cv, bitany_ptr(w), ia);
|
||||
NOGC_E;
|
||||
decG(w); decG(x);
|
||||
return r.obj;
|
||||
return r.res;
|
||||
}
|
||||
#endif
|
||||
goto notConstEach; notConstEach:;
|
||||
|
||||
@ -799,12 +799,14 @@ static NOINLINE DirectArr toFillArr(B x, B fill) {
|
||||
static void* reusableArr_ptr(Arr* t, u8 el) {
|
||||
return el==el_B? (void*)(PTY(t)==t_fillarr? fillarrv_ptr(t) : harrv_ptr(t)) : tyarrv_ptr((TyArr*)t);
|
||||
}
|
||||
DirectArr toEltypeArr(B x, u8 re) {
|
||||
static DirectArr doReuse(B x, u8 xe) { // consumes (i.e. transfers x to result)
|
||||
assert(TI(x,elType)==xe);
|
||||
x = REUSE(x);
|
||||
return (DirectArr){x, reusableArr_ptr(a(x), xe)};
|
||||
}
|
||||
DirectArr toEltypeArr(B x, u8 re) { // consumes
|
||||
assert(isArr(x));
|
||||
if (reusable(x) && re==reuseElType[TY(x)]) {
|
||||
x = REUSE(x);
|
||||
return (DirectArr){x, reusableArr_ptr(a(x), re)};
|
||||
}
|
||||
if (reusable(x) && re==reuseElType[TY(x)]) return doReuse(x, re);
|
||||
|
||||
Arr* tyarr;
|
||||
switch (re) { default: UD;
|
||||
@ -827,18 +829,15 @@ DirectArr toEltypeArr(B x, u8 re) {
|
||||
tyarr:
|
||||
return (DirectArr){taga(tyarr), tyarrv_ptr((TyArr*) tyarr)};
|
||||
}
|
||||
static NOINLINE DirectArr m_fillarrAs(B x, B fill) {
|
||||
|
||||
|
||||
|
||||
static NOINLINE DirectArr m_fillarrAs(B x, B fill) { // doesn't consume
|
||||
Arr* r = arr_shCopy(m_fillarrp(IA(x)), x);
|
||||
fillarr_setFill(r, fill);
|
||||
return (DirectArr){taga(r), fillarrv_ptr(r)};
|
||||
}
|
||||
DirectArr potentiallyReuse(B x) {
|
||||
assert(isArr(x));
|
||||
u8 xe = TI(x,elType);
|
||||
if (reusable(x) && xe == reuseElType[TY(x)]) {
|
||||
x = REUSE(x);
|
||||
return (DirectArr){incG(x), reusableArr_ptr(a(x), xe)};
|
||||
}
|
||||
static DirectArr m_directarrAs(B x, u8 xe) { // doesn't consume
|
||||
if (xe==el_B) {
|
||||
B fill = getFillR(x);
|
||||
if (!noFill(fill)) return m_fillarrAs(x, fill);
|
||||
@ -850,6 +849,48 @@ DirectArr potentiallyReuse(B x) {
|
||||
void* rp = m_tyarrlbc(&r, elwBitLog(xe), x, el2t(xe));
|
||||
return (DirectArr) {r, rp};
|
||||
}
|
||||
static bool canReuse(B x, u8 xe) {
|
||||
return reusable(x) && xe == reuseElType[TY(x)];
|
||||
}
|
||||
DirectArr potentiallyReuse(B x) { // doesn't consume
|
||||
assert(isArr(x));
|
||||
u8 xe = TI(x,elType);
|
||||
return canReuse(x, xe)? doReuse(incG(x), xe) : m_directarrAs(x, xe);
|
||||
}
|
||||
|
||||
ConvArr toEltypeArrX(B x, u8 re) { // doesn't consume
|
||||
debug_assert(isArr(x) && el_or(re,TI(x,elType))==re);
|
||||
u8 xe = TI(x,elType);
|
||||
u8 refState = 0;
|
||||
DirectArr dr;
|
||||
if (re == xe) {
|
||||
if (canReuse(x, xe)) {
|
||||
refState = xe==el_B? 1 : 0;
|
||||
dr = doReuse(incG(x), xe);
|
||||
goto ret_dr;
|
||||
} else {
|
||||
void* xp;
|
||||
if (xe == el_B) {
|
||||
xp = arr_bptr(x);
|
||||
if (xp == NULL) {
|
||||
refState = 1;
|
||||
goto toEltype;
|
||||
}
|
||||
refState = 2;
|
||||
} else {
|
||||
xp = tyany_ptr(x);
|
||||
}
|
||||
DirectArr r = m_directarrAs(x, re);
|
||||
return (ConvArr){r.obj, r.data, xp, refState};
|
||||
}
|
||||
} else {
|
||||
assert(xe != el_B);
|
||||
toEltype:;
|
||||
dr = toEltypeArr(incG(x), re);
|
||||
ret_dr:
|
||||
return (ConvArr){dr.obj, dr.data, dr.data, refState};
|
||||
}
|
||||
}
|
||||
|
||||
B directGetU_bit(void* data, ux i) { return m_f64(bitp_get(data,i));} void directSet_bit(void* data, ux i, B v) { bitp_set(data, i, o2bG(v)); }
|
||||
B directGetU_i8 (void* data, ux i) { return m_f64((( i8*)data)[i]); } void directSet_i8 (void* data, ux i, B v) { (( i8*)data)[i] = o2iG(v); }
|
||||
|
||||
@ -288,15 +288,28 @@ extern INIT_GLOBAL DirectGet directGetU[el_MAX];
|
||||
extern INIT_GLOBAL DirectSet directSet[el_MAX];
|
||||
extern INIT_GLOBAL DirectSetRange directSetRange[el_MAX];
|
||||
|
||||
// consumes x; returns an array with eltype==re, with same shape/elements/fill as x, and its data pointer
|
||||
DirectArr toEltypeArr(B x, u8 re);
|
||||
// returns an array with eltype==re, with same shape/elements/fill as x, and its data pointer
|
||||
DirectArr toEltypeArr(B x, u8 re); // consumes
|
||||
|
||||
// doesn't consume; returns array with same shape & fill as x, returning x itself if possible (iif so, x.u==obj.u).
|
||||
// returns array with same shape & fill as x, returning x itself if possible (iif so, x.u==obj.u).
|
||||
// If reused, the object is untouched besides having its refcount incremented and flags cleared.
|
||||
// As such, if an el_B array is reused, all elements effectively have 1 more refcount than they should as x's elements never get freed
|
||||
// Otherwise, functionality is the same as if a regular new array was made
|
||||
// May start NOGC
|
||||
DirectArr potentiallyReuse(B x);
|
||||
// Otherwise, functionality is the same as if a regular new array was made (i.e. uninitialized elements, may start NOGC)
|
||||
DirectArr potentiallyReuse(B x); // doesn't consume
|
||||
|
||||
typedef struct {
|
||||
B res;
|
||||
void* rp;
|
||||
void* xp;
|
||||
u8 refState;
|
||||
} ConvArr;
|
||||
|
||||
// gives TI(res,elType)==re to write in via rp, and a pointer to x's data in eltype==re representation, from either x, or rp
|
||||
// TI(x,elType)==el_B needs special handling based on result.refState:
|
||||
// 0: elements aren't reference-counted (is so iif TI(x,elType)!=el_B)
|
||||
// 1: xp==rp, elements not desired to be copied from x must be decremented
|
||||
// 2: result is a fresh array, so elements desired to be copied from x must be incremented
|
||||
ConvArr toEltypeArrX(B x, u8 re); // doesn't consume; x must stay alive for xp to remain valid
|
||||
|
||||
#define DIRECTARR_COPY(R, RE, X) \
|
||||
u8 R##_elt = RE; \
|
||||
|
||||
Loading…
Reference in New Issue
Block a user