fix bugs when GC changes refcounts

This commit is contained in:
dzaima 2025-06-13 01:40:23 +03:00
parent e8f5595536
commit 932f388cdf

View File

@ -1487,11 +1487,12 @@ static B set_bit_result(B r, u8 rt, ur rr, usz rl, usz *sh) {
a->ia = rl; a->ia = rl;
a->sh = &a->ia; a->sh = &a->ia;
} else { } else {
if (shObj(r)->refc>1) { ShArr* old = shObj(r);
shObj(r)->refc--; // won't go to zero as refc>1; preparation for being overwritten by new shape if (old->refc>1) {
usz* rsh = a->sh = m_shArr(rr)->a; usz* rsh = a->sh = m_shArr(rr)->a;
shcpy(rsh, sh, rr-1); shcpy(rsh, sh, rr-1);
sh = rsh; sh = rsh;
ptr_decR(old); // shouldn't typically go to zero as refc>1 was just checked above, but can still happen if GC happens curing m_shArr; must be delayed to after m_shArr as sh==old->a for bitcast_impl
SPRNK(a, rr); SPRNK(a, rr);
} }
sh[rr-1] = rl; sh[rr-1] = rl;
@ -1515,9 +1516,10 @@ B bitcast_impl(B el0, B el1, B x) {
if (rt==t_bitarr && (!reusable(r) || IS_SLICE(TY(r)))) { if (rt==t_bitarr && (!reusable(r) || IS_SLICE(TY(r)))) {
r = taga(copy(xct, r)); r = taga(copy(xct, r));
} else if (!reusable(r)) { } else if (!reusable(r)) {
B pr = r; B r0 = incG(r);
Arr* r2 = TI(r,slice)(r, 0, IA(r)); Arr* r2 = TI(r,slice)(r, 0, IA(r));
r = taga(arr_shSetI(r2, xr, shObj(pr))); // safe to use pr because r has refcount>1 and slice only consumes one, leaving some behind r = taga(arr_shSetI(r2, xr, shObj(r0)));
decG(r0);
} else { } else {
REUSE(r); REUSE(r);
#if VERIFY_TAIL #if VERIFY_TAIL