diff options
-rw-r--r-- | ChangeLog | 25 | ||||
-rw-r--r-- | gc.c | 28 |
2 files changed, 46 insertions, 7 deletions
@@ -1,5 +1,30 @@ 2011-10-15 Kaz Kylheku <kaz@kylheku.com> + Fixed broken GC on x86_64 (Ubuntu 11, gcc 4.5.2). + The issues is that due to the aggressive function inlining + in the gc module, the mark_mem_region function is not real + subroutine. The address of its local variable &gc_stack_top + ended up excluding the machine context saved by setjmp in + the parent function. I.e. the buffer was not between the + computed stack top and bottom. Thus registers were not being + scanned for references to values. I added a little abstraction + to the machine context in the process of fixing this. + + * gc.c (struct mach_context, mach_context_t): New type. + (save_context): New macro. + (mark): Takes two new arguments, pointer to the stack top and + machine context. It scans the machine context explicitly rather + than relying it to be on the stack, between the top and bottom. + This context is in fact only object within the garbage collector part + of the activation chain that we need to scan. + (gc): Use new abstraction to save machine context. Local variable + is used to derive the stack top here. The stack top is the top + of the stack above the activation frames in the garbage collector + itself. The gc has nothing on its stack that should be scanned, + except for the machine context, which is now handled explicitly. + +2011-10-15 Kaz Kylheku <kaz@kylheku.com> + * configure: POSIX Portability. Use = instead of == in test expressions. This was revealed by ubuntu's dash. @@ -49,6 +49,12 @@ typedef struct heap { obj_t block[HEAP_SIZE]; } heap_t; +typedef struct mach_context { + jmp_buf buf; +} mach_context_t; + +#define save_context(X) setjmp((X).buf) + int opt_gc_debug; #ifdef HAVE_VALGRIND int opt_vg_debug; @@ -341,19 +347,25 @@ static void mark_mem_region(val *low, val *high) } } -static void mark(void) +static void mark(mach_context_t *pmc, val *gc_stack_top) { - val gc_stack_top; val **rootloc; /* * First, scan the officially registered locations. */ - for (rootloc = prot_stack; rootloc != top; rootloc++) mark_obj(**rootloc); - mark_mem_region(&gc_stack_top, gc_stack_bottom); + /* + * Then the machine context + */ + mark_mem_region((val *) pmc, (val *) (pmc + 1)); + + /* + * Finally, the stack. + */ + mark_mem_region(gc_stack_top, gc_stack_bottom); } static void sweep(void) @@ -433,11 +445,13 @@ static void sweep(void) void gc(void) { + val gc_stack_top = nil; + if (gc_enabled) { - jmp_buf jmp; - setjmp(jmp); + mach_context_t mc; + save_context(mc); gc_enabled = 0; - mark(); + mark(&mc, &gc_stack_top); hash_process_weak(); sweep(); gc_enabled = 1; |