Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -767,10 +767,16 @@ static void gc_sync_cache_nolock(jl_ptls_t ptls, jl_gc_mark_cache_t *gc_cache) J
bigval_t *hdr = (bigval_t*)gc_ptr_clear_tag(ptr, 1);
gc_big_object_unlink(hdr);
if (gc_ptr_tag(ptr, 1)) {
hdr->owner_thread_ptls = ptls;
// No need to acquire the lock since this code either runs serially or
// it's guarded by the `gc_cache_lock`.
gc_big_object_link(hdr, &ptls->heap.big_objects);
}
else {
// Move hdr from `big_objects` list to `big_objects_marked list`
hdr->owner_thread_ptls = NULL;
// No need to acquire the lock since this code either runs serially or
// it's guarded by the `gc_cache_lock`.
gc_big_object_link(hdr, &big_objects_marked);
}
}
Expand Down Expand Up @@ -1027,7 +1033,10 @@ STATIC_INLINE jl_value_t *jl_gc_big_alloc_inner(jl_ptls_t ptls, size_t sz)
memset(v, 0xee, allocsz);
#endif
v->sz = allocsz;
v->owner_thread_ptls = ptls;
jl_mutex_lock_nogc(&ptls->heap.big_objects_lock);
gc_big_object_link(v, &ptls->heap.big_objects);
jl_mutex_unlock_nogc(&ptls->heap.big_objects_lock);
return jl_valueof(&v->header);
}

Expand Down Expand Up @@ -1055,7 +1064,7 @@ jl_value_t *jl_gc_big_alloc_noinline(jl_ptls_t ptls, size_t sz) {

// Sweep list rooted at *pv, removing and freeing any unmarked objects.
// Return pointer to last `next` field in the culled list.
static bigval_t **sweep_big_list(int sweep_full, bigval_t **pv) JL_NOTSAFEPOINT
static bigval_t **sweep_big_list(int sweep_full, jl_ptls_t ptls, bigval_t **pv) JL_NOTSAFEPOINT
{
bigval_t *v = *pv;
while (v != NULL) {
Expand All @@ -1067,6 +1076,7 @@ static bigval_t **sweep_big_list(int sweep_full, bigval_t **pv) JL_NOTSAFEPOINT
if (sweep_full || bits == GC_MARKED) {
bits = GC_OLD;
}
v->owner_thread_ptls = ptls;
v->bits.gc = bits;
}
else {
Expand Down Expand Up @@ -1095,10 +1105,10 @@ static void sweep_big(jl_ptls_t ptls, int sweep_full) JL_NOTSAFEPOINT
for (int i = 0; i < gc_n_threads; i++) {
jl_ptls_t ptls2 = gc_all_tls_states[i];
if (ptls2 != NULL)
sweep_big_list(sweep_full, &ptls2->heap.big_objects);
sweep_big_list(sweep_full, ptls2, &ptls2->heap.big_objects);
}
if (sweep_full) {
bigval_t **last_next = sweep_big_list(sweep_full, &big_objects_marked);
bigval_t **last_next = sweep_big_list(sweep_full, ptls, &big_objects_marked);
// Move all survivors from big_objects_marked list to the big_objects list of this thread.
if (ptls->heap.big_objects)
ptls->heap.big_objects->prev = last_next;
Expand Down Expand Up @@ -3876,6 +3886,7 @@ void jl_init_thread_heap(jl_ptls_t ptls)
small_arraylist_new(&heap->free_stacks[i], 0);
heap->mallocarrays = NULL;
heap->mafreelist = NULL;
JL_MUTEX_INIT(&heap->big_objects_lock, "big_objects");
heap->big_objects = NULL;
heap->remset = &heap->_remset[0];
heap->last_remset = &heap->_remset[1];
Expand Down Expand Up @@ -4198,14 +4209,20 @@ jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz)
bigval_t *hdr = bigval_header(v);
jl_ptls_t ptls = jl_current_task->ptls;
maybe_collect(ptls); // don't want this to happen during jl_gc_managed_realloc
jl_ptls_t ptls2 = hdr->owner_thread_ptls;
assert(ptls2 != NULL);
jl_mutex_lock_nogc(&ptls2->heap.big_objects_lock);
gc_big_object_unlink(hdr);
jl_mutex_unlock_nogc(&ptls2->heap.big_objects_lock);
// TODO: this is not safe since it frees the old pointer. ideally we'd like
// the old pointer to be left alone if we can't grow in place.
// for now it's up to the caller to make sure there are no references to the
// old pointer.
bigval_t *newbig = (bigval_t*)gc_managed_realloc_(ptls, hdr, allocsz, oldsz, 1, s, 0);
newbig->sz = allocsz;
jl_mutex_lock_nogc(&ptls->heap.big_objects_lock);
gc_big_object_link(newbig, &ptls->heap.big_objects);
jl_mutex_unlock_nogc(&ptls->heap.big_objects_lock);
jl_value_t *snew = jl_valueof(&newbig->header);
*(size_t*)snew = sz;
return snew;
Expand Down
9 changes: 5 additions & 4 deletions src/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,13 @@ JL_EXTENSION typedef struct _bigval_t {
struct _bigval_t *next;
struct _bigval_t **prev; // pointer to the next field of the prev entry
size_t sz;
jl_ptls_t owner_thread_ptls;
#ifdef _P64 // Add padding so that the value is 64-byte aligned
// (8 pointers of 8 bytes each) - (4 other pointers in struct)
void *_padding[8 - 4];
// (8 pointers of 8 bytes each) - (5 other pointers in struct)
void *_padding[8 - 5];
#else
// (16 pointers of 4 bytes each) - (4 other pointers in struct)
void *_padding[16 - 4];
// (16 pointers of 4 bytes each) - (5 other pointers in struct)
void *_padding[16 - 5];
#endif
//struct jl_taggedvalue_t <>;
union {
Expand Down
1 change: 1 addition & 0 deletions src/julia_threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ typedef struct {
struct _mallocarray_t *mafreelist;

// variables for tracking big objects
jl_mutex_t big_objects_lock;
struct _bigval_t *big_objects;

// variables for tracking "remembered set"
Expand Down