STATIC_INLINE void jl_array_grow_at_end(jl_array_t *a, size_t idx, size_t inc, size_t n) { // optimized for the case of only growing and shrinking at the end if (__unlikely(a->flags.isshared)) { if (a->flags.how != 3) jl_error("cannot resize array with shared data"); if (inc == 0) { // If inc > 0, it will always trigger the slow path and unshare the // buffer array_try_unshare(a); return; } } size_t elsz = a->elsize; char *data = (char*)a->data; int has_gap = n > idx; if (__unlikely((n + inc) > a->maxsize - a->offset)) { size_t nb1 = idx * elsz; size_t nbinc = inc * elsz; size_t newlen = a->maxsize == 0 ? (inc < 4 ? 4 : inc) : a->maxsize * 2; while ((n + inc) > newlen - a->offset) newlen *= 2; newlen = limit_overallocation(a, n, newlen, inc); int newbuf = array_resize_buffer(a, newlen); char *newdata = (char*)a->data + a->offset * elsz; if (newbuf) { memcpy(newdata, data, nb1); if (has_gap) { memcpy(newdata + nb1 + nbinc, data + nb1, n * elsz - nb1); } } else if (has_gap) { memmove(newdata + nb1 + nbinc, newdata + nb1, n * elsz - nb1); } a->data = data = newdata; } else if (has_gap) { size_t nb1 = idx * elsz; memmove(data + nb1 + inc * elsz, data + nb1, n * elsz - nb1); } size_t newnrows = n + inc; #ifdef STORE_ARRAY_LEN a->length = newnrows; #endif a->nrows = newnrows; if (a->flags.ptrarray) { memset(data + idx * elsz, 0, inc * elsz); } }
void jl_array_grow_end(jl_array_t *a, size_t inc) { if (a->isshared && a->how!=3) jl_error("cannot resize array with shared data"); // optimized for the case of only growing and shrinking at the end size_t alen = jl_array_nrows(a); if ((alen + inc) > a->maxsize - a->offset) { size_t newlen = a->maxsize==0 ? (inc<4?4:inc) : a->maxsize*2; while ((alen + inc) > newlen - a->offset) newlen *= 2; newlen = limit_overallocation(a, alen, newlen, inc); array_resize_buffer(a, newlen, alen, a->offset); } #ifdef STORE_ARRAY_LEN a->length += inc; #endif a->nrows += inc; }
void jl_array_grow_beg(jl_array_t *a, size_t inc) { if (inc == 0) return; // designed to handle the case of growing and shrinking at both ends if (a->isshared) array_try_unshare(a); size_t es = a->elsize; size_t incnb = inc*es; if (a->offset >= inc) { a->data = (char*)a->data - incnb; a->offset -= inc; } else { size_t alen = a->nrows; size_t anb = alen*es; if (inc > (a->maxsize-alen)/2 - (a->maxsize-alen)/20) { size_t newlen = a->maxsize==0 ? inc*2 : a->maxsize*2; while (alen+2*inc > newlen-a->offset) newlen *= 2; newlen = limit_overallocation(a, alen, newlen, 2*inc); size_t center = (newlen - (alen + inc))/2; array_resize_buffer(a, newlen, alen, center+inc); char *newdata = (char*)a->data - (center+inc)*es; if (a->ptrarray) { memset(newdata, 0, (center+inc)*es); } a->offset = center; a->data = newdata + center*es; } else { size_t center = (a->maxsize - (alen + inc))/2; char *newdata = (char*)a->data - es*a->offset + es*center; memmove(&newdata[incnb], a->data, anb); a->data = newdata; a->offset = center; } } #ifdef STORE_ARRAY_LEN a->length += inc; #endif a->nrows += inc; }
STATIC_INLINE void jl_array_grow_at_beg(jl_array_t *a, size_t idx, size_t inc, size_t n) { // designed to handle the case of growing and shrinking at both ends if (__unlikely(a->flags.isshared)) { if (a->flags.how != 3) jl_error("cannot resize array with shared data"); if (inc == 0) { // If inc > 0, it will always trigger the slow path and unshare the // buffer array_try_unshare(a); return; } } size_t newnrows = n + inc; size_t elsz = a->elsize; size_t nbinc = inc * elsz; char *data = (char*)a->data; char *newdata; if (a->offset >= inc) { assert(!a->flags.isshared); newdata = data - nbinc; a->offset -= inc; if (idx > 0) { memmove(newdata, data, idx * elsz); } } else { size_t oldoffsnb = a->offset * elsz; size_t nb1 = idx * elsz; if (inc > (a->maxsize - n) / 2 - (a->maxsize - n) / 20) { size_t newlen = a->maxsize == 0 ? inc * 2 : a->maxsize * 2; while (n + 2 * inc > newlen - a->offset) newlen *= 2; newlen = limit_overallocation(a, n, newlen, 2 * inc); size_t newoffset = (newlen - newnrows) / 2; if (!array_resize_buffer(a, newlen)) data = (char*)a->data + oldoffsnb; newdata = (char*)a->data + newoffset * elsz; // We could use memcpy if resizing allocates a new buffer, // hopefully it's not a particularly important optimization. if (idx > 0 && newdata < data) memmove(newdata, data, nb1); memmove(newdata + nbinc + nb1, data + nb1, n * elsz - nb1); if (idx > 0 && newdata > data) memmove(newdata, data, nb1); a->offset = newoffset; } else { assert(!a->flags.isshared); a->offset = (a->maxsize - newnrows) / 2; newdata = data - oldoffsnb + a->offset * elsz; // We could use memcpy if resizing allocates a new buffer, // hopefully it's not a particularly important optimization. if (idx > 0 && newdata < data) memmove(newdata, data, nb1); memmove(newdata + nbinc + nb1, data + nb1, n * elsz - nb1); if (idx > 0 && newdata > data) memmove(newdata, data, nb1); } } #ifdef STORE_ARRAY_LEN a->length = newnrows; #endif a->nrows = newnrows; a->data = newdata; if (a->flags.ptrarray) { memset(newdata + idx * elsz, 0, nbinc); } }