static Type *julia_type_to_llvm(jl_value_t *jt, jl_codectx_t *ctx) { if (jt == (jl_value_t*)jl_bool_type) return T_int1; if (jt == (jl_value_t*)jl_float32_type) return T_float32; if (jt == (jl_value_t*)jl_float64_type) return T_float64; //if (jt == (jl_value_t*)jl_null) return T_void; if (jl_is_cpointer_type(jt)) { Type *lt = julia_type_to_llvm(jl_tparam0(jt), ctx); if (lt == NULL) return NULL; if (lt == T_void) lt = T_int8; return PointerType::get(lt, 0); } if (jl_is_bits_type(jt)) { int nb = jl_bitstype_nbits(jt); if (nb == 8) return T_int8; if (nb == 16) return T_int16; if (nb == 32) return T_int32; if (nb == 64) return T_int64; else return Type::getIntNTy(getGlobalContext(), nb); } if (jt == (jl_value_t*)jl_bottom_type) return T_void; //if (jt == (jl_value_t*)jl_any_type) // return jl_pvalue_llvmt; return jl_pvalue_llvmt; //emit_type_error(literal_pointer_val(jt), (jl_value_t*)jl_bits_kind, // "conversion to native type", ctx); //return NULL; }
void jl_compute_struct_offsets(jl_struct_type_t *st) { size_t sz = 0, alignm = 0; for(size_t i=0; i < st->types->length; i++) { jl_value_t *ty = jl_tupleref(st->types, i); size_t fsz, al; if (jl_is_bits_type(ty)) { fsz = jl_bitstype_nbits(ty)/8; al = fsz; // alignment == size for bits types st->fields[i].isptr = 0; } else { fsz = sizeof(void*); al = fsz; st->fields[i].isptr = 1; } sz = LLT_ALIGN(sz, al); if (al > alignm) alignm = al; st->fields[i].offset = sz; st->fields[i].size = fsz; sz += fsz; } st->alignment = alignm; st->size = LLT_ALIGN(sz, alignm); }
int jl_egal(jl_value_t *a, jl_value_t *b) { if (a == b) return 1; jl_value_t *ta = (jl_value_t*)jl_typeof(a); if (ta != (jl_value_t*)jl_typeof(b)) return 0; if (jl_is_bits_type(ta)) { size_t nb = jl_bitstype_nbits(ta)/8; switch (nb) { case 1: return *(int8_t*)jl_bits_data(a) == *(int8_t*)jl_bits_data(b); case 2: return *(int16_t*)jl_bits_data(a) == *(int16_t*)jl_bits_data(b); case 4: return *(int32_t*)jl_bits_data(a) == *(int32_t*)jl_bits_data(b); case 8: return *(int64_t*)jl_bits_data(a) == *(int64_t*)jl_bits_data(b); default: return memcmp(jl_bits_data(a), jl_bits_data(b), nb)==0; } } if (jl_is_tuple(a)) { size_t l = jl_tuple_len(a); if (l != jl_tuple_len(b)) return 0; for(size_t i=0; i < l; i++) { if (!jl_egal(jl_tupleref(a,i),jl_tupleref(b,i))) return 0; } return 1; } return 0; }
// this is a run-time function // warning: cannot allocate memory except using alloc_temp_arg_space extern "C" void *jl_value_to_pointer(jl_value_t *jt, jl_value_t *v, int argn, int addressof) { jl_value_t *jvt = (jl_value_t*)jl_typeof(v); if (addressof) { if (jvt == jt) { if (jl_is_bits_type(jvt)) { size_t osz = jl_bitstype_nbits(jt)/8; return alloc_temp_arg_copy(jl_bits_data(v), osz); } else if (jl_is_struct_type(jvt) && jl_is_leaf_type(jvt) && !jl_is_array_type(jvt)) { return v + 1; } } goto value_to_pointer_error; } else { if (jl_is_cpointer_type(jvt) && jl_tparam0(jvt) == jt) { return (void*)jl_unbox_voidpointer(v); } } if (((jl_value_t*)jl_uint8_type == jt || (jl_value_t*)jl_int8_type == jt) && jl_is_byte_string(v)) { return jl_string_data(v); } if (jl_is_array_type(jvt)) { if (jl_tparam0(jl_typeof(v)) == jt || jt==(jl_value_t*)jl_bottom_type) return ((jl_array_t*)v)->data; if (jl_is_cpointer_type(jt)) { jl_array_t *ar = (jl_array_t*)v; void **temp=(void**)alloc_temp_arg_space(jl_array_len(ar)*sizeof(void*)); size_t i; for(i=0; i < jl_array_len(ar); i++) { temp[i] = jl_value_to_pointer(jl_tparam0(jt), jl_arrayref(ar, i), argn, 0); } return temp; } } value_to_pointer_error: std::map<int, std::string>::iterator it = argNumberStrings.find(argn); if (it == argNumberStrings.end()) { std::stringstream msg; msg << "argument "; msg << argn; argNumberStrings[argn] = msg.str(); it = argNumberStrings.find(argn); } jl_value_t *targ=NULL, *pty=NULL; JL_GC_PUSH(&targ, &pty); targ = (jl_value_t*)jl_tuple1(jt); pty = (jl_value_t*)jl_apply_type((jl_value_t*)jl_pointer_type, (jl_tuple_t*)targ); jl_type_error_rt("ccall", (*it).second.c_str(), pty, v); // doesn't return return (jl_value_t*)jl_null; }
static jl_value_t *new_scalar(jl_bits_type_t *bt) { size_t nb = jl_bitstype_nbits(bt)/8; jl_value_t *v = (jl_value_t*)allocobj((NWORDS(LLT_ALIGN(nb,sizeof(void*)))+1)* sizeof(void*)); v->type = (jl_type_t*)bt; return v; }
// this is used to wrap values for generic contexts, where a // dynamically-typed value is required (e.g. argument to unknown function). // if it's already a pointer it's left alone. static Value *boxed(Value *v) { Type *t = v->getType(); if (t == jl_pvalue_llvmt) return v; if (t == T_void) return literal_pointer_val((jl_value_t*)jl_nothing); if (t == T_int1) return julia_bool(v); jl_value_t *jt = julia_type_of(v); jl_bits_type_t *jb = (jl_bits_type_t*)jt; if (jb == jl_int8_type) return builder.CreateCall(box_int8_func, builder.CreateSExt(v, T_int32)); if (jb == jl_int16_type) return builder.CreateCall(box_int16_func, v); if (jb == jl_int32_type) return builder.CreateCall(box_int32_func, v); if (jb == jl_int64_type) return builder.CreateCall(box_int64_func, v); if (jb == jl_float32_type) return builder.CreateCall(box_float32_func, v); //if (jb == jl_float64_type) return builder.CreateCall(box_float64_func, v); if (jb == jl_float64_type) { // manually inline alloc & init of Float64 box. cheap, I know. #ifdef __LP64__ Value *newv = builder.CreateCall(jlalloc2w_func); #else Value *newv = builder.CreateCall(jlalloc3w_func); #endif return init_bits_value(newv, jt, t, v); } if (jb == jl_uint8_type) return builder.CreateCall(box_uint8_func, builder.CreateZExt(v, T_int32)); if (jb == jl_uint16_type) return builder.CreateCall(box_uint16_func, v); if (jb == jl_uint32_type) return builder.CreateCall(box_uint32_func, v); if (jb == jl_uint64_type) return builder.CreateCall(box_uint64_func, v); if (jb == jl_char_type) return builder.CreateCall(box_char_func, v); // TODO: skip the call for constant arguments if (jl_is_bits_type(jt)) { if (v->getType()->isPointerTy()) { v = builder.CreatePtrToInt(v, T_size); } int nb = jl_bitstype_nbits(jt); if (nb == 8) return builder.CreateCall2(box8_func, literal_pointer_val(jt), v); if (nb == 16) return builder.CreateCall2(box16_func, literal_pointer_val(jt), v); if (nb == 32) return builder.CreateCall2(box32_func, literal_pointer_val(jt), v); if (nb == 64) return builder.CreateCall2(box64_func, literal_pointer_val(jt), v); size_t sz = sizeof(void*) + (nb+7)/8; Value *newv = builder.CreateCall(jlallocobj_func, ConstantInt::get(T_size, sz)); // TODO: make sure this is rooted. I think it is. return init_bits_value(newv, jt, t, v); } assert("Don't know how to box this type" && false); return NULL; }
jl_array_t *jl_ptr_to_array(jl_type_t *atype, void *data, jl_tuple_t *dims, int julia_mallocated) { 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 = (ndims > 2 ? (ndims-2) : 0); #ifndef __LP64__ // on 32-bit, ndimwords must be odd to preserve 8-byte alignment ndimwords += (~ndimwords)&1; #endif a = allocobj(sizeof(jl_array_t) + ndimwords*sizeof(size_t)); a->type = atype; a->data = data; a->length = nel; a->elsize = elsz; a->ptrarray = !isunboxed; a->ndims = ndims; if (julia_mallocated) { a->reshaped = 0; jl_gc_acquire_buffer(data); } else { // this marks the array as not owning its buffer a->reshaped = 1; *((jl_array_t**)(&a->_space[0] + ndimwords*sizeof(size_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; }
// this is used to wrap values for generic contexts, where a // dynamically-typed value is required (e.g. argument to unknown function). // if it's already a pointer it's left alone. static Value *boxed(Value *v) { Type *t = v->getType(); if (t == jl_pvalue_llvmt) return v; if (t == T_void) return literal_pointer_val((jl_value_t*)jl_nothing); if (t == T_int1) return julia_bool(v); jl_value_t *jt = julia_type_of(v); jl_bits_type_t *jb = (jl_bits_type_t*)jt; if (jb == jl_int8_type) return builder.CreateCall(box_int8_func, builder.CreateSExt(v, T_int32)); if (jb == jl_int16_type) return builder.CreateCall(box_int16_func, v); if (jb == jl_int32_type) return builder.CreateCall(box_int32_func, v); if (jb == jl_int64_type) return builder.CreateCall(box_int64_func, v); if (jb == jl_float32_type) return builder.CreateCall(box_float32_func, v); if (jb == jl_float64_type) return builder.CreateCall(box_float64_func, v); if (jb == jl_uint8_type) return builder.CreateCall(box_uint8_func, builder.CreateZExt(v, T_int32)); if (jb == jl_uint16_type) return builder.CreateCall(box_uint16_func, v); if (jb == jl_uint32_type) return builder.CreateCall(box_uint32_func, v); if (jb == jl_uint64_type) return builder.CreateCall(box_uint64_func, v); if (jb == jl_char_type) return builder.CreateCall(box_char_func, v); // TODO: skip the call for constant arguments if (jl_is_bits_type(jt)) { if (v->getType()->isPointerTy()) { v = builder.CreatePtrToInt(v, T_size); } int nb = jl_bitstype_nbits(jt); if (nb == 8) return builder.CreateCall2(box8_func, literal_pointer_val(jt), v); if (nb == 16) return builder.CreateCall2(box16_func, literal_pointer_val(jt), v); if (nb == 32) return builder.CreateCall2(box32_func, literal_pointer_val(jt), v); if (nb == 64) return builder.CreateCall2(box64_func, literal_pointer_val(jt), v); size_t sz = sizeof(void*) + (nb+7)/8; Value *newv = builder.CreateCall(jlallocobj_func, ConstantInt::get(T_size, sz)); builder.CreateStore(literal_pointer_val(jt), builder.CreateBitCast(newv, jl_ppvalue_llvmt)); builder.CreateStore(v, builder.CreateBitCast(bitstype_pointer(newv), PointerType::get(t,0))); // TODO: make sure this is rooted. I think it is. return builder.CreateBitCast(newv, jl_pvalue_llvmt); } assert("Don't know how to box this type" && false); return NULL; }
void jl_assign_bits(void *dest, jl_value_t *bits) { size_t nb = jl_bitstype_nbits(jl_typeof(bits))/8; switch (nb) { case 1: *(int8_t*)dest = *(int8_t*)jl_bits_data(bits); break; case 2: *(int16_t*)dest = *(int16_t*)jl_bits_data(bits); break; case 4: *(int32_t*)dest = *(int32_t*)jl_bits_data(bits); break; case 8: *(int64_t*)dest = *(int64_t*)jl_bits_data(bits); break; case 16: *(bits128_t*)dest = *(bits128_t*)jl_bits_data(bits); break; default: memcpy(dest, jl_bits_data(bits), nb); } }
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; }
DLLEXPORT void jl_show_any(jl_value_t *str, jl_value_t *v) { ios_t *s = (ios_t*)jl_iostr_data(str); // fallback for printing some other builtin types if (jl_is_tuple(v)) { jl_show_tuple(str, (jl_tuple_t*)v, '(', ')', 1); } else if (jl_is_type(v)) { show_type(str, v); } else if (jl_is_func(v)) { show_function(s, v); } else if (jl_typeis(v,jl_intrinsic_type)) { JL_PRINTF(s, "#<intrinsic-function %d>", *(uint32_t*)jl_bits_data(v)); } else { jl_value_t *t = (jl_value_t*)jl_typeof(v); assert(jl_is_struct_type(t) || jl_is_bits_type(t)); jl_tag_type_t *tt = (jl_tag_type_t*)t; JL_PUTS(tt->name->name->name, s); if (tt->parameters != jl_null) { jl_show_tuple(str, tt->parameters, '{', '}', 0); } JL_PUTC('(', s); if (jl_is_struct_type(tt)) { jl_struct_type_t *st = (jl_struct_type_t*)tt; size_t i; size_t n = jl_tuple_len(st->names); for(i=0; i < n; i++) { jl_value_t *fval = jl_get_nth_field(v, i); if (fval == NULL) JL_PUTS("#undef", s); else jl_show(str, fval); if (i < n-1) JL_PUTC(',', s); } } else { size_t nb = jl_bitstype_nbits(tt)/8; char *data = (char*)jl_bits_data(v); JL_PUTS("0x", s); for(int i=nb-1; i >= 0; --i) ios_printf(s, "%02hhx", data[i]); } JL_PUTC(')', s); } }
// this is used to wrap values for generic contexts, where a // dynamically-typed value is required (e.g. argument to unknown function). // if it's already a pointer it's left alone. static Value *boxed(Value *v, jl_value_t *jt) { Type *t = v->getType(); if (t == jl_pvalue_llvmt) return v; if (t == T_void) return literal_pointer_val((jl_value_t*)jl_nothing); if (t == T_int1) return julia_bool(v); if (jt == NULL) jt = julia_type_of(v); jl_bits_type_t *jb = (jl_bits_type_t*)jt; if (jb == jl_int8_type) return builder.CreateCall(box_int8_func, builder.CreateSExt(v, T_int32)); if (jb == jl_int16_type) return builder.CreateCall(box_int16_func, v); if (jb == jl_int32_type) return builder.CreateCall(box_int32_func, v); if (jb == jl_int64_type) return builder.CreateCall(box_int64_func, v); if (jb == jl_float32_type) return builder.CreateCall(box_float32_func, v); //if (jb == jl_float64_type) return builder.CreateCall(box_float64_func, v); if (jb == jl_float64_type) { // manually inline alloc & init of Float64 box. cheap, I know. #ifdef __LP64__ Value *newv = builder.CreateCall(jlalloc2w_func); #else Value *newv = builder.CreateCall(jlalloc3w_func); #endif return init_bits_value(newv, literal_pointer_val(jt), t, v); } if (jb == jl_uint8_type) return builder.CreateCall(box_uint8_func, builder.CreateZExt(v, T_int32)); if (jb == jl_uint16_type) return builder.CreateCall(box_uint16_func, v); if (jb == jl_uint32_type) return builder.CreateCall(box_uint32_func, v); if (jb == jl_uint64_type) return builder.CreateCall(box_uint64_func, v); if (jb == jl_char_type) return builder.CreateCall(box_char_func, v); // TODO: skip the call for constant arguments if (!jl_is_bits_type(jt)) { assert("Don't know how to box this type" && false); return NULL; } int nb = jl_bitstype_nbits(jt); return allocate_box_dynamic(literal_pointer_val(jt), nb, v); }
DLLEXPORT uptrint_t jl_object_id(jl_value_t *v) { if (jl_is_symbol(v)) return ((jl_sym_t*)v)->hash; jl_value_t *tv = (jl_value_t*)jl_typeof(v); if (jl_is_bits_type(tv)) { size_t nb = jl_bitstype_nbits(tv)/8; uptrint_t h = inthash((uptrint_t)tv); switch (nb) { case 1: return int32hash(*(int8_t*)jl_bits_data(v) ^ h); case 2: return int32hash(*(int16_t*)jl_bits_data(v) ^ h); case 4: return int32hash(*(int32_t*)jl_bits_data(v) ^ h); case 8: return hash64(*(int64_t*)jl_bits_data(v) ^ h); default: #ifdef __LP64__ return h ^ memhash((char*)jl_bits_data(v), nb); #else return h ^ memhash32((char*)jl_bits_data(v), nb); #endif } } if (tv == (jl_value_t*)jl_union_kind) { #ifdef __LP64__ return jl_object_id(jl_fieldref(v,0))^0xA5A5A5A5A5A5A5A5L; #else return jl_object_id(jl_fieldref(v,0))^0xA5A5A5A5; #endif } if (jl_is_struct_type(tv)) return inthash((uptrint_t)v); assert(jl_is_tuple(v)); uptrint_t h = 0; size_t l = jl_tuple_len(v); for(size_t i = 0; i < l; i++) { uptrint_t u = jl_object_id(jl_tupleref(v,i)); h = bitmix(h, u); } return h; }
jl_value_t *jl_new_bits(jl_bits_type_t *bt, void *data) { if (bt == jl_uint8_type) return jl_box_uint8(*(uint8_t*)data); else if (bt == jl_int64_type) return jl_box_int64(*(int64_t*)data); else if (bt == jl_bool_type) return (*(int8_t*)data) ? jl_true:jl_false; else if (bt == jl_int32_type) return jl_box_int32(*(int32_t*)data); else if (bt == jl_float64_type) return jl_box_float64(*(double*)data); size_t nb = jl_bitstype_nbits(bt)/8; jl_value_t *v = (jl_value_t*)allocobj((NWORDS(LLT_ALIGN(nb,sizeof(void*)))+1)* sizeof(void*)); v->type = (jl_type_t*)bt; switch (nb) { case 1: *(int8_t*) jl_bits_data(v) = *(int8_t*)data; break; case 2: *(int16_t*) jl_bits_data(v) = *(int16_t*)data; break; case 4: *(int32_t*) jl_bits_data(v) = *(int32_t*)data; break; case 8: *(int64_t*) jl_bits_data(v) = *(int64_t*)data; break; case 16: *(bits128_t*)jl_bits_data(v) = *(bits128_t*)data; break; default: memcpy(jl_bits_data(v), data, nb); } return v; }
// ** NOTE: julia_mallocated means buffer was allocated using julia_malloc. // using the address of another array does not work!! jl_array_t *jl_ptr_to_array_1d(jl_type_t *atype, void *data, size_t nel, int julia_mallocated) { 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)); a->type = atype; a->data = data; a->length = nel; a->elsize = elsz; a->ptrarray = !isunboxed; a->ndims = 1; if (julia_mallocated) { a->reshaped = 0; jl_gc_acquire_buffer(data); } else { // this marks the array as not owning its buffer a->reshaped = 1; *((jl_array_t**)(&a->_space[0])) = a; } a->nrows = a->length; a->maxsize = a->length; 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; }
static Type *julia_type_to_llvm(jl_value_t *jt) { if (jt == (jl_value_t*)jl_bool_type) return T_int1; if (jt == (jl_value_t*)jl_float32_type) return T_float32; if (jt == (jl_value_t*)jl_float64_type) return T_float64; if (jl_is_cpointer_type(jt)) { Type *lt = julia_type_to_llvm(jl_tparam0(jt)); if (lt == NULL) return NULL; if (lt == T_void) lt = T_int8; return PointerType::get(lt, 0); } if (jl_is_bits_type(jt)) { int nb = jl_bitstype_nbits(jt); if (nb == 8) return T_int8; if (nb == 16) return T_int16; if (nb == 32) return T_int32; if (nb == 64) return T_int64; else return Type::getIntNTy(getGlobalContext(), nb); } if (jt == (jl_value_t*)jl_bottom_type) return T_void; return jl_pvalue_llvmt; }
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_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 = (ndims > 2 ? (ndims-2) : 0); #ifndef __LP64__ // on 32-bit, ndimwords must be odd to preserve 8-byte alignment ndimwords += (~ndimwords)&1; #endif if (tot <= ARRAY_INLINE_NBYTES) { a = allocobj(sizeof(jl_array_t) + tot + (ndimwords-1)*sizeof(size_t)); a->type = atype; data = (&a->_space[0] + ndimwords*sizeof(size_t)); if (tot > 0 && !isunboxed) { memset(data, 0, tot); } } else { a = allocobj(sizeof(jl_array_t) + (ndimwords-1)*sizeof(size_t)); JL_GC_PUSH(&a); a->type = atype; // temporarily initialize to make gc-safe a->data = NULL; a->length = 0; a->reshaped = 0; data = allocb(tot); 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->reshaped = 0; 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; }