Skip to content

Commit

Permalink
Re-implement Oscar's GC scrub with a safer approach
Browse files Browse the repository at this point in the history
Instead of trashing pointer-like values on the stack, we fill dead objects
that is possibly referred to from the stack with garbage.
  • Loading branch information
yuyichao committed Aug 1, 2015
1 parent 0122aa3 commit f25f437
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/gc-debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,10 @@ static int gc_debug_alloc_check(jl_alloc_num_t *num)
return ((num->num - num->min) % num->interv) == 0;
}

static char *gc_stack_lo;
static void gc_debug_init()
{
gc_stack_lo = (char*)gc_get_stack_ptr();
char *env = getenv("JL_GC_NO_GENERATIONAL");
if (env && strcmp(env, "0") != 0) {
gc_debug_env.sweep_mask = GC_MARKED;
Expand Down Expand Up @@ -301,6 +303,27 @@ static inline void gc_debug_print()
gc_debug_print_status();
}

static void gc_scrub_range(char *stack_lo, char *stack_hi)
{
stack_lo = (char*)((uintptr_t)stack_lo & ~(uintptr_t)15);
for (char **stack_p = (char**)stack_lo;
stack_p > (char**)stack_hi;stack_p--) {
char *p = *stack_p;
size_t osize;
jl_taggedvalue_t *tag = jl_gc_find_taggedvalue_pool(p, &osize);
if (!tag || gc_marked(tag) || osize <= sizeof_jl_taggedvalue_t)
continue;
jl_value_t *value = jl_valueof(tag);
size_t value_size = osize - sizeof_jl_taggedvalue_t;
memset(value, 0xff, value_size);
}
}

static void gc_scrub(char *stack_hi)
{
gc_scrub_range(gc_stack_lo, stack_hi);
}

#else

static inline int gc_debug_check_other()
Expand All @@ -321,4 +344,9 @@ static inline void gc_debug_init()
{
}

static void gc_scrub(char *stack_hi)
{
(void)stack_hi;
}

#endif
11 changes: 11 additions & 0 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,15 @@ static gcpage_t *page_metadata(void *data);
static void pre_mark(void);
static void post_mark(arraylist_t *list, int dryrun);
static region_t *find_region(void *ptr, int maybe);
jl_taggedvalue_t *jl_gc_find_taggedvalue_pool(char *p, size_t *osize_p);

NOINLINE static uintptr_t gc_get_stack_ptr()
{
void *dummy = NULL;
// The mask is to suppress the compiler warning about returning
// address of local variable
return (uintptr_t)&dummy & ~(uintptr_t)15;
}

#include "gc-debug.c"

Expand Down Expand Up @@ -1997,6 +2006,7 @@ void jl_gc_collect(int full)
{
if (!is_gc_enabled) return;
if (jl_in_gc) return;
char *stack_hi = (char*)gc_get_stack_ptr();
gc_debug_print();
JL_SIGATOMIC_BEGIN();
jl_in_gc = 1;
Expand Down Expand Up @@ -2098,6 +2108,7 @@ void jl_gc_collect(int full)
#endif
estimate_freed = live_bytes - scanned_bytes - perm_scanned_bytes + actual_allocd;

gc_scrub(stack_hi);
gc_verify();

#if defined(MEMPROFILE)
Expand Down

0 comments on commit f25f437

Please sign in to comment.