@@ -3321,7 +3321,7 @@ static Value *emit_genericmemoryptr(jl_codectx_t &ctx, Value *mem, const jl_data
33213321 LoadInst *LI = ctx.builder .CreateAlignedLoad (PPT, addr, Align (sizeof (char *)));
33223322 LI->setOrdering (AtomicOrdering::NotAtomic);
33233323 LI->setMetadata (LLVMContext::MD_nonnull, MDNode::get (ctx.builder .getContext (), None));
3324- jl_aliasinfo_t aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_const );
3324+ jl_aliasinfo_t aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memoryptr );
33253325 aliasinfo.decorateInst (LI);
33263326 Value *ptr = LI;
33273327 if (AS) {
@@ -3347,7 +3347,7 @@ static Value *emit_genericmemoryowner(jl_codectx_t &ctx, Value *t)
33473347 return emit_guarded_test (ctx, foreign, t, [&] {
33483348 addr = ctx.builder .CreateConstInBoundsGEP1_32 (ctx.types ().T_jlgenericmemory , m, 1 );
33493349 LoadInst *owner = ctx.builder .CreateAlignedLoad (ctx.types ().T_prjlvalue , addr, Align (sizeof (void *)));
3350- jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_const );
3350+ jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memoryptr );
33513351 ai.decorateInst (owner);
33523352 return ctx.builder .CreateSelect (ctx.builder .CreateIsNull (owner), t, owner);
33533353 });
@@ -4432,6 +4432,105 @@ static int compare_cgparams(const jl_cgparams_t *a, const jl_cgparams_t *b)
44324432}
44334433#endif
44344434
4435+ static auto *emit_genericmemory_unchecked (jl_codectx_t &ctx, Value *cg_nbytes, Value *cg_typ)
4436+ {
4437+ auto ptls = get_current_ptls (ctx);
4438+ auto call = prepare_call (jl_alloc_genericmemory_unchecked_func);
4439+ auto *alloc = ctx.builder .CreateCall (call, { ptls, cg_nbytes, cg_typ});
4440+ alloc->setAttributes (call->getAttributes ());
4441+ alloc->addRetAttr (Attribute::getWithAlignment (alloc->getContext (), Align (JL_HEAP_ALIGNMENT)));
4442+ call->addRetAttr (Attribute::getWithDereferenceableBytes (call->getContext (), sizeof (jl_genericmemory_t )));
4443+ return alloc;
4444+ }
4445+
4446+ static void emit_memory_zeroinit_and_stores (jl_codectx_t &ctx, jl_datatype_t *typ, Value* alloc, Value* nbytes, Value* nel, int zi)
4447+ {
4448+ auto arg_typename = [&] JL_NOTSAFEPOINT {
4449+ std::string type_str;
4450+ auto eltype = jl_tparam1 (typ);
4451+ if (jl_is_datatype (eltype))
4452+ type_str = jl_symbol_name (((jl_datatype_t *)eltype)->name ->name );
4453+ else if (jl_is_uniontype (eltype))
4454+ type_str = " Union" ;
4455+ else
4456+ type_str = " <unknown type>" ;
4457+ return " Memory{" + type_str + " }[]" ;
4458+ };
4459+ setName (ctx.emission_context , alloc, arg_typename);
4460+ // set length (jl_alloc_genericmemory_unchecked_func doesn't have it)
4461+ Value *decay_alloc = decay_derived (ctx, alloc);
4462+ Value *len_field = ctx.builder .CreateStructGEP (ctx.types ().T_jlgenericmemory , decay_alloc, 0 );
4463+ auto len_store = ctx.builder .CreateAlignedStore (nel, len_field, Align (sizeof (void *)));
4464+ auto aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memorylen );
4465+ aliasinfo.decorateInst (len_store);
4466+ // This avoids the length store from being deleted which is illegal
4467+ ctx.builder .CreateFence (AtomicOrdering::Release, SyncScope::SingleThread);
4468+ // zeroinit pointers and unions
4469+ if (zi) {
4470+ Value *memory_ptr = ctx.builder .CreateStructGEP (ctx.types ().T_jlgenericmemory , decay_alloc, 1 );
4471+ auto *load = ctx.builder .CreateAlignedLoad (ctx.types ().T_ptr , memory_ptr, Align (sizeof (void *)));
4472+ aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memoryptr );
4473+ aliasinfo.decorateInst (load);
4474+ auto int8t = getInt8Ty (ctx.builder .getContext ());
4475+ ctx.builder .CreateMemSet (load, ConstantInt::get (int8t, 0 ), nbytes, Align (sizeof (void *)));
4476+ }
4477+ return ;
4478+ }
4479+
4480+
4481+ static jl_cgval_t emit_const_len_memorynew (jl_codectx_t &ctx, jl_datatype_t *typ, size_t nel, jl_genericmemory_t *inst)
4482+ {
4483+ if (nel == 0 ) {
4484+ Value *empty_alloc = track_pjlvalue (ctx, literal_pointer_val (ctx, (jl_value_t *)inst));
4485+ return mark_julia_type (ctx, empty_alloc, true , typ);
4486+ }
4487+ const jl_datatype_layout_t *layout = ((jl_datatype_t *)typ)->layout ;
4488+ assert (((jl_datatype_t *)typ)->has_concrete_subtype && layout != NULL );
4489+ size_t elsz = layout->size ;
4490+ int isboxed = layout->flags .arrayelem_isboxed ;
4491+ int isunion = layout->flags .arrayelem_isunion ;
4492+ int zi = ((jl_datatype_t *)typ)->zeroinit ;
4493+ if (isboxed)
4494+ elsz = sizeof (void *);
4495+ size_t nbytes;
4496+ bool overflow = __builtin_mul_overflow (nel, elsz, &nbytes);
4497+ if (isunion) {
4498+ // an extra byte for each isbits union memory element, stored at m->ptr + m->length
4499+ overflow |= __builtin_add_overflow (nbytes, nel, &nbytes);
4500+ }
4501+ // overflow if signed size is too big or nel is too big (the latter matters iff elsz==0)
4502+ ssize_t tmp=1 ;
4503+ overflow |= __builtin_add_overflow (nel, 1 , &tmp) || __builtin_add_overflow (nbytes, 1 , &tmp);
4504+ if (overflow)
4505+ emit_error (ctx, prepare_call (jlargumenterror_func), " invalid GenericMemory size: the number of elements is either negative or too large for system address width" );
4506+
4507+ auto T_size = ctx.types ().T_size ;
4508+ auto cg_typ = literal_pointer_val (ctx, (jl_value_t *) typ);
4509+ auto cg_nbytes = ConstantInt::get (T_size, nbytes);
4510+ auto cg_nel = ConstantInt::get (T_size, nel);
4511+ size_t tot = nbytes + LLT_ALIGN (sizeof (jl_genericmemory_t ),JL_SMALL_BYTE_ALIGNMENT);
4512+ // if allocation fits within GC pools
4513+ int pooled = tot <= GC_MAX_SZCLASS;
4514+ Value *alloc, *decay_alloc, *memory_ptr;
4515+ jl_aliasinfo_t aliasinfo;
4516+ if (pooled) {
4517+ alloc = emit_allocobj (ctx, tot, cg_typ, false , JL_SMALL_BYTE_ALIGNMENT);
4518+ decay_alloc = decay_derived (ctx, alloc);
4519+ memory_ptr = ctx.builder .CreateStructGEP (ctx.types ().T_jlgenericmemory , decay_alloc, 1 );
4520+ setName (ctx.emission_context , memory_ptr, " memory_ptr" );
4521+ auto objref = emit_pointer_from_objref (ctx, alloc);
4522+ Value *memory_data = emit_ptrgep (ctx, objref, JL_SMALL_BYTE_ALIGNMENT);
4523+ auto *store = ctx.builder .CreateAlignedStore (memory_data, memory_ptr, Align (sizeof (void *)));
4524+ aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memoryptr );
4525+ aliasinfo.decorateInst (store);
4526+ setName (ctx.emission_context , memory_data, " memory_data" );
4527+ } else { // just use the dynamic length version since the malloc will be slow anyway
4528+ alloc = emit_genericmemory_unchecked (ctx, cg_nbytes, cg_typ);
4529+ }
4530+ emit_memory_zeroinit_and_stores (ctx, typ, alloc, cg_nbytes, cg_nel, zi);
4531+ return mark_julia_type (ctx, alloc, true , typ);
4532+ }
4533+
44354534static jl_cgval_t emit_memorynew (jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval_t nel, jl_genericmemory_t *inst)
44364535{
44374536 emit_typecheck (ctx, nel, (jl_value_t *)jl_long_type, " memorynew" );
@@ -4448,9 +4547,7 @@ static jl_cgval_t emit_memorynew(jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval
44484547 if (isboxed)
44494548 elsz = sizeof (void *);
44504549
4451- auto ptls = get_current_ptls (ctx);
44524550 auto T_size = ctx.types ().T_size ;
4453- auto int8t = getInt8Ty (ctx.builder .getContext ());
44544551 BasicBlock *emptymemBB, *nonemptymemBB, *retvalBB;
44554552 emptymemBB = BasicBlock::Create (ctx.builder .getContext (), " emptymem" );
44564553 nonemptymemBB = BasicBlock::Create (ctx.builder .getContext (), " nonemptymem" );
@@ -4466,18 +4563,7 @@ static jl_cgval_t emit_memorynew(jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval
44664563 ctx.builder .CreateBr (retvalBB);
44674564 nonemptymemBB->insertInto (ctx.f );
44684565 ctx.builder .SetInsertPoint (nonemptymemBB);
4469- // else actually allocate mem
4470- auto arg_typename = [&] JL_NOTSAFEPOINT {
4471- std::string type_str;
4472- auto eltype = jl_tparam1 (typ);
4473- if (jl_is_datatype (eltype))
4474- type_str = jl_symbol_name (((jl_datatype_t *)eltype)->name ->name );
4475- else if (jl_is_uniontype (eltype))
4476- type_str = " Union" ;
4477- else
4478- type_str = " <unknown type>" ;
4479- return " Memory{" + type_str + " }[]" ;
4480- };
4566+
44814567 auto cg_typ = literal_pointer_val (ctx, (jl_value_t *) typ);
44824568 auto cg_elsz = ConstantInt::get (T_size, elsz);
44834569
@@ -4501,27 +4587,10 @@ static jl_cgval_t emit_memorynew(jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval
45014587 overflow = ctx.builder .CreateOr (overflow, tobignel);
45024588 Value *notoverflow = ctx.builder .CreateNot (overflow);
45034589 error_unless (ctx, prepare_call (jlargumenterror_func), notoverflow, " invalid GenericMemory size: the number of elements is either negative or too large for system address width" );
4504- // actually allocate
4505- auto call = prepare_call (jl_alloc_genericmemory_unchecked_func);
4506- Value *alloc = ctx.builder .CreateCall (call, { ptls, nbytes, cg_typ});
4507- // set length (jl_alloc_genericmemory_unchecked_func doesn't have it)
4508- Value *decay_alloc = decay_derived (ctx, alloc);
4509- Value *len_field = ctx.builder .CreateStructGEP (ctx.types ().T_jlgenericmemory , decay_alloc, 0 );
4510- auto len_store = ctx.builder .CreateAlignedStore (nel_unboxed, len_field, Align (sizeof (void *)));
4511- auto aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memorylen );
4512- aliasinfo.decorateInst (len_store);
4513- // This avoids the length store from being deleted which is illegal
4514- ctx.builder .CreateFence (AtomicOrdering::Release, SyncScope::SingleThread);
4515- // zeroinit pointers and unions
4516- if (zi) {
4517- Value *memory_ptr = ctx.builder .CreateStructGEP (ctx.types ().T_jlgenericmemory , decay_alloc, 1 );
4518- auto *load = ctx.builder .CreateAlignedLoad (ctx.types ().T_ptr , memory_ptr, Align (sizeof (void *)));
4519- aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memoryptr );
4520- aliasinfo.decorateInst (load);
4521- ctx.builder .CreateMemSet (load, ConstantInt::get (int8t, 0 ), nbytes, Align (sizeof (void *)));
4522- }
4590+ // actually allocate the memory
45234591
4524- setName (ctx.emission_context , alloc, arg_typename);
4592+ Value *alloc = emit_genericmemory_unchecked (ctx, nbytes, cg_typ);
4593+ emit_memory_zeroinit_and_stores (ctx, typ, alloc, nbytes, nel_unboxed, zi);
45254594 ctx.builder .CreateBr (retvalBB);
45264595 nonemptymemBB = ctx.builder .GetInsertBlock ();
45274596 // phi node to choose which side of branch
0 commit comments