Skip to content

Commit

Permalink
outline jl_gc_alignsz to deal with large allocation properlyw
Browse files Browse the repository at this point in the history
  • Loading branch information
vchuravy committed May 20, 2017
1 parent cdc5fd3 commit 295f1ef
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 19 deletions.
3 changes: 2 additions & 1 deletion src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,8 @@ int jl_gc_classify_pools(size_t sz, size_t alignment, int *osize)
if (sz > GC_MAX_SZCLASS)
return -1;
size_t allocsz = sz + sizeof(jl_taggedvalue_t);
int klass = jl_gc_szclass(allocsz, alignment);
size_t alignsz = jl_gc_alignsz(allocsz, alignment);
int klass = jl_gc_szclass(alignsz);
*osize = jl_gc_sizeclasses[klass];
return (int)(intptr_t)(&((jl_ptls_t)0)->heap.norm_pools[klass]);
}
Expand Down
41 changes: 23 additions & 18 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,20 +176,24 @@ static const int jl_gc_sizeclasses[JL_GC_N_POOLS] = {
// 64, 32, 160, 64, 16, 64, 112, 128, bytes lost
};

STATIC_INLINE int JL_CONST_FUNC jl_gc_szclass(size_t sz, size_t alignment)
STATIC_INLINE int JL_CONST_FUNC jl_gc_alignsz(size_t sz, size_t alignment)
{
// select a bucket with the correct alignment, by setting
// sz to a multiple of the alignment. sz = 48, alignment 32
// turns into sz = 64
// TODO: make sure that objects that are just at the border of the max pool size are handled correctly.
if (sz < alignment)
sz = alignment;
else if (sz > alignment) {
size_t aligned_sz = alignment;
while (aligned_sz < sz)
aligned_sz += alignment;
sz = aligned_sz;
}
// The pools are aligned wit JL_CACHE_BYTE_ALIGNMENT (typically 64)
// and we can't guarantee a bigger alignment.
assert(alignment <= JL_CACHE_BYTE_ALIGNMENT);
// Pools with the correct alignment will have an object size that
// is a multiple of the alignment. As an example an allocation with
// sz of 48 and an alignment of 32 will need to be in pool of size 64.
// An alignment of 0 or 1 means unaligned and we can use sz directly.
if (alignment != 0 && alignment != 1 && alignment != sz)
sz = ((sz / alignment) + 1) * alignment;
return sz;
}

// Use jl_gc_alignsz to obtain the right sz.
STATIC_INLINE int JL_CONST_FUNC jl_gc_szclass(size_t sz)
{
// Check that the object fits in the largest pool.
assert(sz <= GC_MAX_SZCLASS + sizeof(jl_taggedvalue_t));
#ifdef _P64
if (sz <= 8)
Expand Down Expand Up @@ -224,18 +228,19 @@ STATIC_INLINE int JL_CONST_FUNC jl_gc_szclass(size_t sz, size_t alignment)
STATIC_INLINE jl_value_t *jl_gc_alloc_(jl_ptls_t ptls, size_t sz, void *ty)
{
const size_t allocsz = sz + sizeof(jl_taggedvalue_t);
if (allocsz < sz) // overflow in adding offs, size was "negative"
jl_throw(jl_memory_exception);
size_t alignment = JL_SMALL_BYTE_ALIGNMENT;
if (ty && ((uintptr_t)ty != jl_buff_tag) &&
jl_is_datatype(ty) && ((jl_datatype_t*)ty)->layout)
alignment = jl_datatype_align(ty);
if (allocsz < sz) // overflow in adding offs, size was "negative"
jl_throw(jl_memory_exception);
const size_t alignsz = jl_gc_alignsz(allocsz, alignment);
jl_value_t *v;
if (allocsz <= GC_MAX_SZCLASS + sizeof(jl_taggedvalue_t)) {
int pool_id = jl_gc_szclass(allocsz, alignment);
if (alignsz <= GC_MAX_SZCLASS + sizeof(jl_taggedvalue_t)) {
int pool_id = jl_gc_szclass(alignsz);
jl_gc_pool_t *p = &ptls->heap.norm_pools[pool_id];
int osize;
if (jl_is_constexpr(allocsz)) {
if (jl_is_constexpr(alignsz)) {
osize = jl_gc_sizeclasses[pool_id];
}
else {
Expand Down

0 comments on commit 295f1ef

Please sign in to comment.