JL_DLLEXPORT jl_array_t *jl_string_to_array(jl_value_t *str) { jl_ptls_t ptls = jl_get_ptls_states(); jl_array_t *a; int ndimwords = jl_array_ndimwords(1); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t) + sizeof(void*), JL_SMALL_BYTE_ALIGNMENT); a = (jl_array_t*)jl_gc_alloc(ptls, tsz, jl_array_uint8_type); a->flags.pooled = tsz <= GC_MAX_SZCLASS; a->flags.ndims = 1; a->offset = 0; a->data = jl_string_data(str); a->flags.isaligned = 0; a->elsize = 1; a->flags.ptrarray = 0; jl_array_data_owner(a) = str; a->flags.how = 3; a->flags.isshared = 1; size_t l = jl_string_len(str); #ifdef STORE_ARRAY_LEN a->length = l; #endif a->nrows = a->maxsize = l; return a; }
jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data, jl_tuple_t *dims) { size_t i; jl_array_t *a; size_t ndims = jl_tuple_len(dims); int ndimwords = jl_array_ndimwords(ndims); a = allocobj((sizeof(jl_array_t) + sizeof(void*) + ndimwords*sizeof(size_t) + 15)&-16); a->type = atype; a->ndims = ndims; a->offset = 0; a->data = NULL; a->isaligned = data->isaligned; jl_value_t *el_type = jl_tparam0(atype); if (store_unboxed(el_type)) { a->elsize = jl_datatype_size(el_type); a->ptrarray = 0; } else { a->elsize = sizeof(void*); a->ptrarray = 1; } JL_GC_PUSH1(&a); jl_array_data_owner(a) = (jl_value_t*)data; a->how = 3; a->data = data->data; a->isshared = 1; data->isshared = 1; if (ndims == 1) { size_t l = jl_unbox_long(jl_tupleref(dims,0)); #ifdef STORE_ARRAY_LEN a->length = l; #endif a->nrows = l; a->maxsize = l; } else { size_t *adims = &a->nrows; size_t l=1; wideint_t prod; for(i=0; i < ndims; i++) { adims[i] = jl_unbox_long(jl_tupleref(dims, i)); prod = (wideint_t)l * (wideint_t)adims[i]; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array dimensions"); l = prod; } #ifdef STORE_ARRAY_LEN a->length = l; #endif } JL_GC_POP(); return a; }
JL_DLLEXPORT jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data, jl_value_t *_dims, int own_buffer) { jl_ptls_t ptls = jl_get_ptls_states(); size_t elsz, nel = 1; jl_array_t *a; size_t ndims = jl_nfields(_dims); wideint_t prod; assert(is_ntuple_long(_dims)); size_t *dims = (size_t*)_dims; for (size_t i = 0; i < ndims; i++) { prod = (wideint_t)nel * (wideint_t)dims[i]; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array dimensions"); nel = prod; } if (__unlikely(ndims == 1)) return jl_ptr_to_array_1d(atype, data, nel, own_buffer); jl_value_t *el_type = jl_tparam0(atype); int isunboxed = store_unboxed(el_type); if (isunboxed) elsz = jl_datatype_size(el_type); else elsz = sizeof(void*); int ndimwords = jl_array_ndimwords(ndims); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t), JL_CACHE_BYTE_ALIGNMENT); a = (jl_array_t*)jl_gc_alloc(ptls, tsz, atype); // No allocation or safepoint allowed after this a->flags.pooled = tsz <= GC_MAX_SZCLASS; a->data = data; #ifdef STORE_ARRAY_LEN a->length = nel; #endif a->elsize = elsz; a->flags.ptrarray = !isunboxed; a->flags.ndims = ndims; a->offset = 0; a->flags.isshared = 1; a->flags.isaligned = 0; if (own_buffer) { a->flags.how = 2; jl_gc_track_malloced_array(ptls, a); jl_gc_count_allocd(nel*elsz + (elsz == 1 ? 1 : 0)); } else { a->flags.how = 0; } assert(ndims != 1); // handled above memcpy(&a->nrows, dims, ndims * sizeof(size_t)); return a; }
jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data, jl_tuple_t *dims, int own_buffer) { size_t i, elsz, nel=1; jl_array_t *a; size_t ndims = jl_tuple_len(dims); wideint_t prod; for(i=0; i < ndims; i++) { prod = (wideint_t)nel * (wideint_t)jl_unbox_long(jl_tupleref(dims, i)); if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array dimensions"); nel = prod; } jl_value_t *el_type = jl_tparam0(atype); int isunboxed = store_unboxed(el_type); if (isunboxed) elsz = jl_datatype_size(el_type); else elsz = sizeof(void*); int ndimwords = jl_array_ndimwords(ndims); a = allocobj((sizeof(jl_array_t) + ndimwords*sizeof(size_t)+15)&-16); a->type = atype; a->data = data; #ifdef STORE_ARRAY_LEN a->length = nel; #endif a->elsize = elsz; a->ptrarray = !isunboxed; a->ndims = ndims; a->offset = 0; a->isshared = 1; a->isaligned = 0; if (own_buffer) { a->how = 2; jl_gc_track_malloced_array(a); } else { a->how = 0; } if (ndims == 1) { a->nrows = nel; a->maxsize = nel; } else { size_t *adims = &a->nrows; for(i=0; i < ndims; i++) { adims[i] = jl_unbox_long(jl_tupleref(dims, i)); } } return a; }
// own_buffer != 0 iff GC should call free() on this pointer eventually JL_DLLEXPORT jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data, size_t nel, int own_buffer) { jl_ptls_t ptls = jl_get_ptls_states(); jl_array_t *a; jl_value_t *eltype = jl_tparam0(atype); int isunboxed = jl_array_store_unboxed(eltype); size_t elsz; unsigned align; if (isunboxed && jl_is_uniontype(eltype)) jl_exceptionf(jl_argumenterror_type, "unsafe_wrap: unspecified layout for union element type"); if (isunboxed) { elsz = jl_datatype_size(eltype); align = jl_datatype_align(eltype); } else { align = elsz = sizeof(void*); } if (((uintptr_t)data) & (align - 1)) jl_exceptionf(jl_argumenterror_type, "unsafe_wrap: pointer %p is not properly aligned to %u bytes", data, align); int ndimwords = jl_array_ndimwords(1); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t), JL_CACHE_BYTE_ALIGNMENT); a = (jl_array_t*)jl_gc_alloc(ptls, tsz, atype); // No allocation or safepoint allowed after this a->flags.pooled = tsz <= GC_MAX_SZCLASS; a->data = data; #ifdef STORE_ARRAY_LEN a->length = nel; #endif a->elsize = elsz; a->flags.ptrarray = !isunboxed; a->flags.ndims = 1; a->flags.isshared = 1; a->flags.isaligned = 0; // TODO: allow passing memalign'd buffers if (own_buffer) { a->flags.how = 2; jl_gc_track_malloced_array(ptls, a); jl_gc_count_allocd(nel*elsz + (elsz == 1 ? 1 : 0)); } else { a->flags.how = 0; } a->nrows = nel; a->maxsize = nel; a->offset = 0; return a; }
jl_array_t *jl_ptr_to_array(jl_type_t *atype, void *data, jl_tuple_t *dims, int own_buffer) { size_t i, elsz, nel=1; jl_array_t *a; size_t ndims = jl_tuple_len(dims); for(i=0; i < ndims; i++) { nel *= jl_unbox_long(jl_tupleref(dims, i)); } jl_type_t *el_type = (jl_type_t*)jl_tparam0(atype); int isunboxed = jl_is_bits_type(el_type); if (isunboxed) elsz = jl_bitstype_nbits(el_type)/8; else elsz = sizeof(void*); int ndimwords = jl_array_ndimwords(ndims); a = allocobj((sizeof(jl_array_t) + ndimwords*sizeof(size_t)+15)&-16); a->type = atype; a->data = data; a->length = nel; a->elsize = elsz; a->ptrarray = !isunboxed; a->ndims = ndims; if (own_buffer) { a->ismalloc = 1; jl_array_data_owner(a) = (jl_value_t*)jl_gc_acquire_buffer(data,nel*elsz); } else { a->ismalloc = 0; jl_array_data_owner(a) = (jl_value_t*)a; } if (ndims == 1) { a->nrows = a->length; a->maxsize = a->length; a->offset = 0; } else { size_t *adims = &a->nrows; for(i=0; i < ndims; i++) { adims[i] = jl_unbox_long(jl_tupleref(dims, i)); } } return a; }
// own_buffer != 0 iff GC should call free() on this pointer eventually JL_DLLEXPORT jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data, size_t nel, int own_buffer) { jl_ptls_t ptls = jl_get_ptls_states(); size_t elsz; jl_array_t *a; jl_value_t *el_type = jl_tparam0(atype); int isunboxed = store_unboxed(el_type); if (isunboxed) elsz = jl_datatype_size(el_type); else elsz = sizeof(void*); int ndimwords = jl_array_ndimwords(1); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t), JL_CACHE_BYTE_ALIGNMENT); a = (jl_array_t*)jl_gc_alloc(ptls, tsz, atype); // No allocation or safepoint allowed after this a->flags.pooled = tsz <= GC_MAX_SZCLASS; a->data = data; #ifdef STORE_ARRAY_LEN a->length = nel; #endif a->elsize = elsz; a->flags.ptrarray = !isunboxed; a->flags.ndims = 1; a->flags.isshared = 1; a->flags.isaligned = 0; // TODO: allow passing memalign'd buffers if (own_buffer) { a->flags.how = 2; jl_gc_track_malloced_array(ptls, a); jl_gc_count_allocd(nel*elsz + (elsz == 1 ? 1 : 0)); } else { a->flags.how = 0; } a->nrows = nel; a->maxsize = nel; a->offset = 0; return a; }
// own_buffer != 0 iff GC should call free() on this pointer eventually jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data, size_t nel, int own_buffer) { size_t elsz; jl_array_t *a; jl_value_t *el_type = jl_tparam0(atype); int isunboxed = store_unboxed(el_type); if (isunboxed) elsz = jl_datatype_size(el_type); else elsz = sizeof(void*); int ndimwords = jl_array_ndimwords(1); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t), 16); a = (jl_array_t*)jl_gc_allocobj(tsz); jl_set_typeof(a, atype); a->pooled = tsz <= GC_MAX_SZCLASS; a->data = data; #ifdef STORE_ARRAY_LEN a->length = nel; #endif a->elsize = elsz; a->ptrarray = !isunboxed; a->ndims = 1; a->isshared = 1; a->isaligned = 0; // TODO: allow passing memalign'd buffers if (own_buffer) { a->how = 2; jl_gc_track_malloced_array(a); jl_gc_count_allocd(nel*elsz + (elsz == 1 ? 1 : 0)); } else { a->how = 0; } a->nrows = nel; a->maxsize = nel; a->offset = 0; return a; }
// own_buffer != 0 iff GC should call free() on this pointer eventually jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data, size_t nel, int own_buffer) { size_t elsz; jl_array_t *a; jl_value_t *el_type = jl_tparam0(atype); int isunboxed = store_unboxed(el_type); if (isunboxed) elsz = jl_datatype_size(el_type); else elsz = sizeof(void*); a = allocobj((sizeof(jl_array_t)+jl_array_ndimwords(1)*sizeof(size_t)+15)&-16); a->type = atype; a->data = data; #ifdef STORE_ARRAY_LEN a->length = nel; #endif a->elsize = elsz; a->ptrarray = !isunboxed; a->ndims = 1; a->isshared = 1; a->isaligned = 0; // TODO: allow passing memalign'd buffers if (own_buffer) { a->how = 2; jl_gc_track_malloced_array(a); } else { a->how = 0; } a->nrows = nel; a->maxsize = nel; a->offset = 0; return a; }
// own_buffer != 0 iff GC should call free() on this pointer eventually jl_array_t *jl_ptr_to_array_1d(jl_type_t *atype, void *data, size_t nel, int own_buffer) { size_t elsz; jl_array_t *a; jl_type_t *el_type = (jl_type_t*)jl_tparam0(atype); int isunboxed = jl_is_bits_type(el_type); if (isunboxed) elsz = jl_bitstype_nbits(el_type)/8; else elsz = sizeof(void*); a = allocobj((sizeof(jl_array_t)+jl_array_ndimwords(1)*sizeof(size_t)+15)&-16); a->type = atype; a->data = data; a->length = nel; a->elsize = elsz; a->ptrarray = !isunboxed; a->ndims = 1; if (own_buffer) { a->ismalloc = 1; jl_array_data_owner(a) = (jl_value_t*)jl_gc_acquire_buffer(data,nel*elsz); } else { a->ismalloc = 0; jl_array_data_owner(a) = (jl_value_t*)a; } a->nrows = a->length; a->maxsize = a->length; a->offset = 0; return a; }
JL_DLLEXPORT jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data, jl_value_t *_dims) { jl_ptls_t ptls = jl_get_ptls_states(); jl_array_t *a; size_t ndims = jl_nfields(_dims); assert(is_ntuple_long(_dims)); size_t *dims = (size_t*)_dims; int ndimwords = jl_array_ndimwords(ndims); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t) + sizeof(void*), JL_SMALL_BYTE_ALIGNMENT); a = (jl_array_t*)jl_gc_alloc(ptls, tsz, atype); // No allocation or safepoint allowed after this a->flags.pooled = tsz <= GC_MAX_SZCLASS; a->flags.ndims = ndims; a->offset = 0; a->data = NULL; a->flags.isaligned = data->flags.isaligned; jl_value_t *el_type = jl_tparam0(atype); assert(store_unboxed(el_type) == !data->flags.ptrarray); if (!data->flags.ptrarray) { a->elsize = jl_datatype_size(el_type); a->flags.ptrarray = 0; } else { a->elsize = sizeof(void*); a->flags.ptrarray = 1; } // if data is itself a shared wrapper, // owner should point back to the original array jl_array_data_owner(a) = jl_array_owner(data); a->flags.how = 3; a->data = data->data; a->flags.isshared = 1; data->flags.isshared = 1; if (ndims == 1) { size_t l = dims[0]; #ifdef STORE_ARRAY_LEN a->length = l; #endif a->nrows = l; a->maxsize = l; } else { size_t *adims = &a->nrows; size_t l = 1; wideint_t prod; for (size_t i = 0; i < ndims; i++) { adims[i] = dims[i]; prod = (wideint_t)l * (wideint_t)adims[i]; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array dimensions"); l = prod; } #ifdef STORE_ARRAY_LEN a->length = l; #endif } return a; }
jl_array_t *jl_reshape_array(jl_type_t *atype, jl_array_t *data, jl_tuple_t *dims) { size_t i; jl_array_t *a; size_t ndims = jl_tuple_len(dims); int ndimwords = jl_array_ndimwords(ndims); a = allocobj((sizeof(jl_array_t) + ndimwords*sizeof(size_t) + 15)&-16); a->type = atype; a->ndims = ndims; a->data = NULL; JL_GC_PUSH(&a); char *d = data->data; if (data->ndims == 1) d -= data->offset*data->elsize; if (d == jl_array_inline_data_area(data)) { if (data->ndims == 1) { // data might resize, so switch it to shared representation. // problem: we'd like to do that, but it might not be valid, // since the buffer might be used from C in a way that it's // assumed not to move. for now, just copy the data (note this // case only happens for sizes <= ARRAY_INLINE_NBYTES) jl_mallocptr_t *mp = array_new_buffer(data, data->length); memcpy(mp->ptr, data->data, data->length * data->elsize); a->data = mp->ptr; jl_array_data_owner(a) = (jl_value_t*)mp; a->ismalloc = 1; //data->data = mp->ptr; //data->offset = 0; //data->maxsize = data->length; //jl_array_data_owner(data) = (jl_value_t*)mp; } else { a->ismalloc = 0; jl_array_data_owner(a) = (jl_value_t*)data; } } else { a->ismalloc = data->ismalloc; jl_array_data_owner(a) = jl_array_data_owner(data); } if (a->data == NULL) a->data = data->data; jl_type_t *el_type = (jl_type_t*)jl_tparam0(atype); if (jl_is_bits_type(el_type)) { a->elsize = jl_bitstype_nbits(el_type)/8; a->ptrarray = 0; } else { a->elsize = sizeof(void*); a->ptrarray = 1; } if (ndims == 1) { a->length = jl_unbox_long(jl_tupleref(dims,0)); a->nrows = a->length; a->maxsize = a->length; a->offset = 0; } else { size_t *adims = &a->nrows; size_t l=1; for(i=0; i < ndims; i++) { adims[i] = jl_unbox_long(jl_tupleref(dims, i)); l *= adims[i]; } a->length = l; } JL_GC_POP(); return a; }
static jl_array_t *_new_array(jl_type_t *atype, uint32_t ndims, size_t *dims) { size_t i, tot, nel=1; int isunboxed=0, elsz; void *data; jl_array_t *a; for(i=0; i < ndims; i++) { nel *= dims[i]; } jl_type_t *el_type = (jl_type_t*)jl_tparam0(atype); isunboxed = jl_is_bits_type(el_type); if (isunboxed) { elsz = jl_bitstype_nbits(el_type)/8; tot = elsz * nel; if (elsz == 1) { // hidden 0 terminator for all byte arrays tot++; } } else { elsz = sizeof(void*); tot = sizeof(void*) * nel; } int ndimwords = jl_array_ndimwords(ndims); if (tot <= ARRAY_INLINE_NBYTES) { size_t tsz = tot>sizeof(size_t) ? tot-sizeof(size_t) : tot; a = allocobj((sizeof(jl_array_t)+tsz+ndimwords*sizeof(size_t)+15)&-16); a->type = atype; a->ismalloc = 0; data = (&a->_space[0] + ndimwords*sizeof(size_t)); if (tot > 0 && !isunboxed) { memset(data, 0, tot); } } else { a = allocobj((sizeof(jl_array_t)+ndimwords*sizeof(size_t)+15)&-16); JL_GC_PUSH(&a); a->type = atype; a->ismalloc = 1; // temporarily initialize to make gc-safe a->data = NULL; jl_value_t **powner = (jl_value_t**)(&a->_space[0] + ndimwords*sizeof(size_t)); *powner = (jl_value_t*)jl_gc_managed_malloc(tot); data = ((jl_mallocptr_t*)*powner)->ptr; if (!isunboxed) memset(data, 0, tot); JL_GC_POP(); } a->data = data; if (elsz == 1) ((char*)data)[tot-1] = '\0'; a->length = nel; a->ndims = ndims; a->ptrarray = !isunboxed; a->elsize = elsz; if (ndims == 1) { a->nrows = nel; a->maxsize = nel; a->offset = 0; } else { size_t *adims = &a->nrows; for(i=0; i < ndims; i++) adims[i] = dims[i]; } return a; }
static jl_array_t *_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims, int isunboxed, int elsz) { size_t i, tot, nel=1; wideint_t prod; void *data; jl_array_t *a; for(i=0; i < ndims; i++) { prod = (wideint_t)nel * (wideint_t)dims[i]; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array dimensions"); nel = prod; } if (isunboxed) { prod = (wideint_t)elsz * (wideint_t)nel; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array size"); tot = prod; if (elsz == 1) { // hidden 0 terminator for all byte arrays tot++; } } else { prod = (wideint_t)sizeof(void*) * (wideint_t)nel; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array size"); tot = prod; } int ndimwords = jl_array_ndimwords(ndims); size_t tsz = sizeof(jl_array_t); tsz += ndimwords*sizeof(size_t); if (tot <= ARRAY_INLINE_NBYTES) { if (isunboxed && elsz >= 4) tsz = (tsz+15)&-16; // align data area 16 size_t doffs = tsz; tsz += tot; tsz = (tsz+15)&-16; // align whole object 16 a = allocobj(tsz); a->type = atype; a->how = 0; data = (char*)a + doffs; if (tot > 0 && !isunboxed) { memset(data, 0, tot); } } else { tsz = (tsz+15)&-16; // align whole object size 16 a = allocobj(tsz); JL_GC_PUSH1(&a); a->type = atype; // temporarily initialize to make gc-safe a->data = NULL; a->how = 2; data = jl_gc_managed_malloc(tot); jl_gc_track_malloced_array(a); if (!isunboxed) memset(data, 0, tot); JL_GC_POP(); } a->data = data; if (elsz == 1) ((char*)data)[tot-1] = '\0'; #ifdef STORE_ARRAY_LEN a->length = nel; #endif a->ndims = ndims; a->ptrarray = !isunboxed; a->elsize = elsz; a->isshared = 0; a->isaligned = 1; a->offset = 0; if (ndims == 1) { a->nrows = nel; a->maxsize = nel; } else { size_t *adims = &a->nrows; for(i=0; i < ndims; i++) adims[i] = dims[i]; } return a; }
jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data, jl_value_t *dims) { size_t i; jl_array_t *a; size_t ndims = jl_nfields(dims); int ndimwords = jl_array_ndimwords(ndims); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t) + sizeof(void*), 16); a = (jl_array_t*)jl_gc_allocobj(tsz); jl_set_typeof(a, atype); a->pooled = tsz <= GC_MAX_SZCLASS; a->ndims = ndims; a->offset = 0; a->data = NULL; a->isaligned = data->isaligned; jl_value_t *el_type = jl_tparam0(atype); if (store_unboxed(el_type)) { a->elsize = jl_datatype_size(el_type); a->ptrarray = 0; } else { a->elsize = sizeof(void*); a->ptrarray = 1; } JL_GC_PUSH1(&a); jl_array_t *owner = data; // if data is itself a shared wrapper, // owner should point back to the original array if (owner->how == 3) { owner = (jl_array_t*)jl_array_data_owner(owner); } assert(owner->how != 3); jl_array_data_owner(a) = (jl_value_t*)owner; a->how = 3; a->data = data->data; a->isshared = 1; data->isshared = 1; if (ndims == 1) { size_t l = ((size_t*)jl_data_ptr(dims))[0]; #ifdef STORE_ARRAY_LEN a->length = l; #endif a->nrows = l; a->maxsize = l; } else { size_t *adims = &a->nrows; size_t l=1; wideint_t prod; for(i=0; i < ndims; i++) { adims[i] = ((size_t*)jl_data_ptr(dims))[i]; prod = (wideint_t)l * (wideint_t)adims[i]; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array dimensions"); l = prod; } #ifdef STORE_ARRAY_LEN a->length = l; #endif } JL_GC_POP(); return a; }
jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data, jl_value_t *dims, int own_buffer) { size_t i, elsz, nel=1; jl_array_t *a; size_t ndims = jl_nfields(dims); wideint_t prod; for(i=0; i < ndims; i++) { prod = (wideint_t)nel * (wideint_t)jl_unbox_long(jl_fieldref(dims, i)); if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array dimensions"); nel = prod; } jl_value_t *el_type = jl_tparam0(atype); int isunboxed = store_unboxed(el_type); if (isunboxed) elsz = jl_datatype_size(el_type); else elsz = sizeof(void*); int ndimwords = jl_array_ndimwords(ndims); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t), 16); a = (jl_array_t*)jl_gc_allocobj(tsz); jl_set_typeof(a, atype); a->pooled = tsz <= GC_MAX_SZCLASS; a->data = data; #ifdef STORE_ARRAY_LEN a->length = nel; #endif a->elsize = elsz; a->ptrarray = !isunboxed; a->ndims = ndims; a->offset = 0; a->isshared = 1; a->isaligned = 0; if (own_buffer) { a->how = 2; jl_gc_track_malloced_array(a); jl_gc_count_allocd(nel*elsz + (elsz == 1 ? 1 : 0)); } else { a->how = 0; } if (ndims == 1) { a->nrows = nel; a->maxsize = nel; } else { size_t *adims = &a->nrows; // jl_fieldref can allocate JL_GC_PUSH1(&a); for(i=0; i < ndims; i++) { adims[i] = jl_unbox_long(jl_fieldref(dims, i)); } JL_GC_POP(); } return a; }
JL_DLLEXPORT jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data, jl_value_t *_dims) { jl_ptls_t ptls = jl_get_ptls_states(); jl_array_t *a; size_t ndims = jl_nfields(_dims); assert(is_ntuple_long(_dims)); size_t *dims = (size_t*)_dims; assert(jl_types_equal(jl_tparam0(jl_typeof(data)), jl_tparam0(atype))); int ndimwords = jl_array_ndimwords(ndims); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords * sizeof(size_t) + sizeof(void*), JL_SMALL_BYTE_ALIGNMENT); a = (jl_array_t*)jl_gc_alloc(ptls, tsz, atype); // No allocation or safepoint allowed after this a->flags.pooled = tsz <= GC_MAX_SZCLASS; a->flags.ndims = ndims; a->offset = 0; a->data = NULL; a->flags.isaligned = data->flags.isaligned; jl_array_t *owner = (jl_array_t*)jl_array_owner(data); jl_value_t *eltype = jl_tparam0(atype); size_t elsz = 0, align = 0; int isboxed = !jl_islayout_inline(eltype, &elsz, &align); assert(isboxed == data->flags.ptrarray); if (!isboxed) { a->elsize = elsz; jl_value_t *ownerty = jl_typeof(owner); size_t oldelsz = 0, oldalign = 0; if (ownerty == (jl_value_t*)jl_string_type) { oldalign = 1; } else { jl_islayout_inline(jl_tparam0(ownerty), &oldelsz, &oldalign); } if (oldalign < align) jl_exceptionf(jl_argumenterror_type, "reinterpret from alignment %d bytes to alignment %d bytes not allowed", (int) oldalign, (int) align); a->flags.ptrarray = 0; } else { a->elsize = sizeof(void*); a->flags.ptrarray = 1; } // if data is itself a shared wrapper, // owner should point back to the original array jl_array_data_owner(a) = (jl_value_t*)owner; a->flags.how = 3; a->data = data->data; a->flags.isshared = 1; data->flags.isshared = 1; if (ndims == 1) { size_t l = dims[0]; #ifdef STORE_ARRAY_LEN a->length = l; #endif a->nrows = l; a->maxsize = l; } else { size_t *adims = &a->nrows; size_t l = 1; wideint_t prod; for (size_t i = 0; i < ndims; i++) { adims[i] = dims[i]; prod = (wideint_t)l * (wideint_t)adims[i]; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array dimensions"); l = prod; } #ifdef STORE_ARRAY_LEN a->length = l; #endif } return a; }
static jl_array_t *_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims, int isunboxed, int elsz) { jl_ptls_t ptls = jl_get_ptls_states(); size_t i, tot, nel=1; void *data; jl_array_t *a; for(i=0; i < ndims; i++) { wideint_t prod = (wideint_t)nel * (wideint_t)dims[i]; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array dimensions"); nel = prod; } if (isunboxed) { wideint_t prod = (wideint_t)elsz * (wideint_t)nel; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array size"); tot = prod; if (elsz == 1) { // extra byte for all julia allocated byte arrays tot++; } } else { wideint_t prod = (wideint_t)sizeof(void*) * (wideint_t)nel; if (prod > (wideint_t) MAXINTVAL) jl_error("invalid Array size"); tot = prod; } int ndimwords = jl_array_ndimwords(ndims); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t), JL_CACHE_BYTE_ALIGNMENT); if (tot <= ARRAY_INLINE_NBYTES) { if (isunboxed && elsz >= 4) tsz = JL_ARRAY_ALIGN(tsz, JL_SMALL_BYTE_ALIGNMENT); // align data area size_t doffs = tsz; tsz += tot; tsz = JL_ARRAY_ALIGN(tsz, JL_SMALL_BYTE_ALIGNMENT); // align whole object a = (jl_array_t*)jl_gc_alloc(ptls, tsz, atype); // No allocation or safepoint allowed after this a->flags.how = 0; data = (char*)a + doffs; if (tot > 0 && !isunboxed) { memset(data, 0, tot); } } else { tsz = JL_ARRAY_ALIGN(tsz, JL_CACHE_BYTE_ALIGNMENT); // align whole object data = jl_gc_managed_malloc(tot); // Allocate the Array **after** allocating the data // to make sure the array is still young a = (jl_array_t*)jl_gc_alloc(ptls, tsz, atype); // No allocation or safepoint allowed after this a->flags.how = 2; jl_gc_track_malloced_array(ptls, a); if (!isunboxed) memset(data, 0, tot); } a->flags.pooled = tsz <= GC_MAX_SZCLASS; a->data = data; if (JL_ARRAY_IMPL_NUL && elsz == 1) ((char*)data)[tot - 1] = '\0'; #ifdef STORE_ARRAY_LEN a->length = nel; #endif a->flags.ndims = ndims; a->flags.ptrarray = !isunboxed; a->elsize = elsz; a->flags.isshared = 0; a->flags.isaligned = 1; a->offset = 0; if (ndims == 1) { a->nrows = nel; a->maxsize = nel; } else { size_t *adims = &a->nrows; for(i=0; i < ndims; i++) adims[i] = dims[i]; } return a; }
static void gc_markval_(jl_value_t *v) { gc_markval_top: assert(v != NULL); //assert(v != lookforme); if (gc_marked_obj(v)) return; jl_value_t *vt = (jl_value_t*)jl_typeof(v); #ifdef OBJPROFILE void **bp = ptrhash_bp(&obj_counts, vt); if (*bp == HT_NOTFOUND) *bp = (void*)2; else (*((ptrint_t*)bp))++; #endif gc_setmark_obj(v); if (gc_typeof(vt) == (jl_value_t*)jl_bits_kind) return; // some values have special representations if (vt == (jl_value_t*)jl_tuple_type) { size_t l = jl_tuple_len(v); for(size_t i=0; i < l; i++) { jl_value_t *elt = ((jl_tuple_t*)v)->data[i]; if (elt != NULL) GC_Markval(elt); } } else if (((jl_struct_type_t*)(vt))->name == jl_array_typename) { jl_array_t *a = (jl_array_t*)v; int ndims = jl_array_ndims(a); int ndimwords = jl_array_ndimwords(ndims); void *data_area = &a->_space[0] + ndimwords*sizeof(size_t); if (a->reshaped) { GC_Markval(*((jl_value_t**)data_area)); } else if (a->data) { char *data = a->data; if (ndims == 1) data -= a->offset*a->elsize; if (data != data_area) { gc_setmark(data); } } if (a->ptrarray) { size_t l = a->length; if (l > 0) { for(size_t i=0; i < l-1; i++) { jl_value_t *elt = ((jl_value_t**)a->data)[i]; if (elt != NULL) GC_Markval(elt); } v = ((jl_value_t**)a->data)[l-1]; if (v != NULL) goto gc_markval_top; } } } else if (vt == (jl_value_t*)jl_module_type) { gc_mark_module((jl_module_t*)v); } else if (vt == (jl_value_t*)jl_task_type) { jl_task_t *ta = (jl_task_t*)v; GC_Markval(ta->on_exit); GC_Markval(ta->tls); if (ta->start) GC_Markval(ta->start); if (ta->result) GC_Markval(ta->result); GC_Markval(ta->state.eh_task); if (ta->stkbuf != NULL) gc_setmark(ta->stkbuf); #ifdef COPY_STACKS ptrint_t offset; if (ta == jl_current_task) { offset = 0; gc_mark_stack(jl_pgcstack, offset); } else { offset = ta->stkbuf - (ta->stackbase-ta->ssize); gc_mark_stack(ta->state.gcstack, offset); } jl_savestate_t *ss = &ta->state; while (ss != NULL) { GC_Markval(ss->ostream_obj); ss = ss->prev; if (ss != NULL) ss = (jl_savestate_t*)((char*)ss + offset); } #else gc_mark_stack(ta->state.gcstack, 0); jl_savestate_t *ss = &ta->state; while (ss != NULL) { GC_Markval(ss->ostream_obj); ss = ss->prev; } #endif } else if (vt == (jl_value_t*)jl_weakref_type) { // don't mark contents } else { int nf = (int)jl_tuple_len(((jl_struct_type_t*)vt)->names); if (nf > 0) { int i = 0; if (vt == (jl_value_t*)jl_struct_kind || vt == (jl_value_t*)jl_function_type) { i++; // skip fptr field } for(; i < nf-1; i++) { jl_value_t *fld = ((jl_value_t**)v)[i+1]; if (fld) GC_Markval(fld); } v = ((jl_value_t**)v)[i+1]; if (v) goto gc_markval_top; } } }