// Resize the buffer to a max size of `newlen` // The buffer can either be newly allocated or realloc'd, the return // value is 1 if a new buffer is allocated and 0 if it is realloc'd. // the caller needs to take care of moving the data from the old buffer // to the new one if necessary. // When this function returns, the `->data` pointer always points to // the **beginning** of the new buffer. static int NOINLINE array_resize_buffer(jl_array_t *a, size_t newlen) { jl_ptls_t ptls = jl_get_ptls_states(); assert(!a->flags.isshared || a->flags.how == 3); size_t elsz = a->elsize; size_t nbytes = newlen * elsz; size_t oldnbytes = a->maxsize * elsz; size_t oldoffsnb = a->offset * elsz; size_t oldlen = a->nrows; assert(nbytes >= oldnbytes); if (elsz == 1) { nbytes++; oldnbytes++; } int newbuf = 0; if (a->flags.how == 2) { // already malloc'd - use realloc char *olddata = (char*)a->data - oldoffsnb; a->data = jl_gc_managed_realloc(olddata, nbytes, oldnbytes, a->flags.isaligned, (jl_value_t*)a); } else { newbuf = 1; if ( #ifdef _P64 nbytes >= MALLOC_THRESH #else elsz > 4 #endif ) { a->data = jl_gc_managed_malloc(nbytes); jl_gc_track_malloced_array(ptls, a); a->flags.how = 2; a->flags.isaligned = 1; } else { a->data = jl_gc_alloc_buf(ptls, nbytes); a->flags.how = 1; jl_gc_wb_buf(a, a->data, nbytes); } } if (JL_ARRAY_IMPL_NUL && elsz == 1) memset((char*)a->data + oldnbytes - 1, 0, nbytes - oldnbytes + 1); (void)oldlen; assert(oldlen == a->nrows && "Race condition detected: recursive resizing on the same array."); a->flags.isshared = 0; a->maxsize = newlen; return newbuf; }
// allocate buffer of newlen elements, placing old data at given offset (in #elts) // newlen: new length (#elts), including offset // oldlen: old length (#elts), excluding offset // offs: new offset static void array_resize_buffer(jl_array_t *a, size_t newlen, size_t oldlen, size_t offs) { size_t es = a->elsize; size_t nbytes = newlen * es; size_t offsnb = offs * es; size_t oldnbytes = oldlen * es; size_t oldoffsnb = a->offset * es; if (es == 1) nbytes++; assert(!a->isshared || a->how==3); char *newdata; if (a->how == 2) { // already malloc'd - use realloc newdata = (char*)jl_gc_managed_realloc((char*)a->data - oldoffsnb, nbytes, oldnbytes+oldoffsnb, a->isaligned, (jl_value_t*)a); if (offs != a->offset) { memmove(&newdata[offsnb], &newdata[oldoffsnb], oldnbytes); } } else { if ( #ifdef _P64 nbytes >= MALLOC_THRESH #else es > 4 #endif ) { newdata = (char*)jl_gc_managed_malloc(nbytes); jl_gc_track_malloced_array(a); a->how = 2; a->isaligned = 1; } else { newdata = (char*)allocb(nbytes); a->how = 1; } memcpy(newdata + offsnb, (char*)a->data, oldnbytes); } a->data = newdata + offsnb; a->isshared = 0; if (a->ptrarray || es==1) memset(newdata+offsnb+oldnbytes, 0, nbytes-oldnbytes-offsnb); if (a->how == 1) jl_gc_wb_buf(a, newdata); a->maxsize = newlen; }