From f25f4379cb7dee7a9c03236cdd65ad60b1f9dbc4 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 26 Jul 2015 09:27:33 -0400 Subject: [PATCH] Re-implement Oscar's GC scrub with a safer approach Instead of trashing pointer-like values on the stack, we fill dead objects that is possibly referred to from the stack with garbage. --- src/gc-debug.c | 28 ++++++++++++++++++++++++++++ src/gc.c | 11 +++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/gc-debug.c b/src/gc-debug.c index c2355ce161d8b..e396796f94026 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -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; @@ -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() @@ -321,4 +344,9 @@ static inline void gc_debug_init() { } +static void gc_scrub(char *stack_hi) +{ + (void)stack_hi; +} + #endif diff --git a/src/gc.c b/src/gc.c index db6d5c75720a9..10b9b83df9a80 100644 --- a/src/gc.c +++ b/src/gc.c @@ -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" @@ -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; @@ -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)