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
|
// (c ; C˙)¨⌾(w⊸/) x
|
||||||
#if SINGELI_SIMD
|
#if SINGELI_SIMD
|
||||||
if (isFun(o) && TY(o)==t_md1D) {
|
if (MAY_F(isFun(o) && TY(o)==t_md1D)) {
|
||||||
u8 xe = TI(x,elType);
|
u8 xe = TI(x,elType);
|
||||||
|
|
||||||
Md1D* od = c(Md1D,o);
|
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);
|
else incByG(c, sum-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectArr r;
|
ConvArr r = toEltypeArrX(x, re);
|
||||||
void* xp;
|
assert((xe==el_B) == (r.refState!=0));
|
||||||
if (re != xe) {
|
if (r.refState != 0) {
|
||||||
assert(xe != el_B);
|
assert(re == el_B);
|
||||||
r = toEltypeArr(x, re);
|
if (r.refState == 1) decByMask(bitany_ptr(w), r.xp, ia, 0);
|
||||||
x = incG(r.obj);
|
else incByMask(bitany_ptr(w), r.xp, ia, 1);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 cv;
|
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);
|
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;
|
NOGC_E;
|
||||||
decG(w); decG(x);
|
decG(w); decG(x);
|
||||||
return r.obj;
|
return r.res;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
goto notConstEach; notConstEach:;
|
goto notConstEach; notConstEach:;
|
||||||
|
|||||||
@ -799,12 +799,14 @@ static NOINLINE DirectArr toFillArr(B x, B fill) {
|
|||||||
static void* reusableArr_ptr(Arr* t, u8 el) {
|
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);
|
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));
|
assert(isArr(x));
|
||||||
if (reusable(x) && re==reuseElType[TY(x)]) {
|
if (reusable(x) && re==reuseElType[TY(x)]) return doReuse(x, re);
|
||||||
x = REUSE(x);
|
|
||||||
return (DirectArr){x, reusableArr_ptr(a(x), re)};
|
|
||||||
}
|
|
||||||
|
|
||||||
Arr* tyarr;
|
Arr* tyarr;
|
||||||
switch (re) { default: UD;
|
switch (re) { default: UD;
|
||||||
@ -827,18 +829,15 @@ DirectArr toEltypeArr(B x, u8 re) {
|
|||||||
tyarr:
|
tyarr:
|
||||||
return (DirectArr){taga(tyarr), tyarrv_ptr((TyArr*) 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);
|
Arr* r = arr_shCopy(m_fillarrp(IA(x)), x);
|
||||||
fillarr_setFill(r, fill);
|
fillarr_setFill(r, fill);
|
||||||
return (DirectArr){taga(r), fillarrv_ptr(r)};
|
return (DirectArr){taga(r), fillarrv_ptr(r)};
|
||||||
}
|
}
|
||||||
DirectArr potentiallyReuse(B x) {
|
static DirectArr m_directarrAs(B x, u8 xe) { // doesn't consume
|
||||||
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)};
|
|
||||||
}
|
|
||||||
if (xe==el_B) {
|
if (xe==el_B) {
|
||||||
B fill = getFillR(x);
|
B fill = getFillR(x);
|
||||||
if (!noFill(fill)) return m_fillarrAs(x, fill);
|
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));
|
void* rp = m_tyarrlbc(&r, elwBitLog(xe), x, el2t(xe));
|
||||||
return (DirectArr) {r, rp};
|
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_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); }
|
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 DirectSet directSet[el_MAX];
|
||||||
extern INIT_GLOBAL DirectSetRange directSetRange[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
|
// returns an array with eltype==re, with same shape/elements/fill as x, and its data pointer
|
||||||
DirectArr toEltypeArr(B x, u8 re);
|
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.
|
// 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
|
// 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
|
// Otherwise, functionality is the same as if a regular new array was made (i.e. uninitialized elements, may start NOGC)
|
||||||
// May start NOGC
|
DirectArr potentiallyReuse(B x); // doesn't consume
|
||||||
DirectArr potentiallyReuse(B x);
|
|
||||||
|
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) \
|
#define DIRECTARR_COPY(R, RE, X) \
|
||||||
u8 R##_elt = RE; \
|
u8 R##_elt = RE; \
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user