From 6842a2829d1c8ff5e9937eae784481f3221f624a Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 5 Apr 2008 02:08:37 -0500 Subject: [PATCH] Fixing GC --- vm/code_gc.c | 3 +-- vm/data_gc.c | 47 +++++++++++++++++++---------------------------- vm/data_gc.h | 31 +++++++++++++++++++------------ 3 files changed, 39 insertions(+), 42 deletions(-) diff --git a/vm/code_gc.c b/vm/code_gc.c index 54979b8a01..8a05daf570 100755 --- a/vm/code_gc.c +++ b/vm/code_gc.c @@ -181,7 +181,6 @@ void free_unmarked(F_HEAP *heap) } break; case B_FREE: - printf("RECLAIMED\n"); if(prev && prev->status == B_FREE) prev->size += scan->size; break; @@ -290,7 +289,7 @@ DEFINE_PRIMITIVE(code_room) void code_gc(void) { - garbage_collection(TENURED,true,false,0); + garbage_collection(TENURED,false,0); } DEFINE_PRIMITIVE(code_gc) diff --git a/vm/data_gc.c b/vm/data_gc.c index 9f6b06a528..9b4f4fd583 100755 --- a/vm/data_gc.c +++ b/vm/data_gc.c @@ -1,10 +1,10 @@ #include "master.h" -//#define GC_DEBUG 1 +#define GC_DEBUG 0 #define ALLOC_DATA_HEAP "alloc_data_heap: gens=%ld, young_size=%ld, aging_size=%ld\n" -#define GC_REQUESTED "garbage_collection: code_gc=%d, growing_data_heap=%d, requested_bytes=%ld\n" -#define BEGIN_GC "begin_gc: code_gc=%d, growing_data_heap=%d, collecting_gen=%ld\n" +#define GC_REQUESTED "garbage_collection: growing_data_heap=%d, requested_bytes=%ld\n" +#define BEGIN_GC "begin_gc: growing_data_heap=%d, collecting_gen=%ld\n" #define END_GC "end_gc: gc_elapsed=%ld\n" #define END_AGING_GC "end_gc: aging_collections=%ld, cards_scanned=%ld\n" #define END_NURSERY_GC "end_gc: nursery_collections=%ld, cards_scanned=%ld\n" @@ -29,7 +29,10 @@ void init_cards_offset(void) - (data_heap->segment->start >> CARD_BITS); } -F_DATA_HEAP *alloc_data_heap(CELL gens, CELL young_size, CELL aging_size) +F_DATA_HEAP *alloc_data_heap(CELL gens, + CELL young_size, + CELL aging_size, + CELL tenured_size) { GC_PRINT(ALLOC_DATA_HEAP,gens,young_size,aging_size); @@ -405,7 +408,7 @@ void collect_stack_frame(F_STACK_FRAME *frame) callstack snapshot */ void collect_callstack(F_CONTEXT *stacks) { - if(collecting_code) + if(collecting_gen == TENURED) { CELL top = (CELL)stacks->callstack_top; CELL bottom = (CELL)stacks->callstack_bottom; @@ -583,11 +586,8 @@ CELL collect_next(CELL scan) { do_slots(scan,copy_handle); - if(collecting_code) - { - printf("do_code_slots\n"); + if(collecting_gen == TENURED) do_code_slots(scan); - } return scan + untagged_object_size(scan); } @@ -641,11 +641,11 @@ void begin_gc(CELL requested_bytes) } #ifdef GC_DEBUG - //printf("\n"); + printf("\n"); dump_generations(); printf("Newspace: "); dump_zone(newspace); - //printf("\n"); + printf("\n"); #endif; } @@ -690,7 +690,7 @@ void end_gc(void) nursery_collections++; } - if(collecting_code) + if(collecting_gen == TENURED) { /* now that all reachable code blocks have been marked, deallocate the rest */ @@ -704,7 +704,6 @@ void end_gc(void) If growing_data_heap_ is true, we must grow the data heap to such a size that an allocation of requested_bytes won't fail */ void garbage_collection(CELL gen, - bool code_gc, bool growing_data_heap_, CELL requested_bytes) { @@ -714,17 +713,14 @@ void garbage_collection(CELL gen, return; } - GC_PRINT(GC_REQUESTED,code_gc,growing_data_heap_,requested_bytes); + GC_PRINT(GC_REQUESTED,growing_data_heap_,requested_bytes); s64 start = current_millis(); performing_gc = true; - collecting_code = code_gc; growing_data_heap = growing_data_heap_; collecting_gen = gen; - //if(collecting_gen == TENURED) collecting_code = true; - /* we come back here if a generation is full */ if(setjmp(gc_jmp)) { @@ -732,15 +728,10 @@ void garbage_collection(CELL gen, resort to growing the data heap */ if(collecting_gen == TENURED) { - //if(collecting_code) - { - growing_data_heap = true; + growing_data_heap = true; - /* see the comment in unmark_marked() */ - unmark_marked(&code_heap); - } - //else - // collecting_code = true; + /* see the comment in unmark_marked() */ + unmark_marked(&code_heap); } /* we try collecting AGING space twice before going on to collect TENURED */ @@ -757,7 +748,7 @@ void garbage_collection(CELL gen, } } - GC_PRINT(BEGIN_GC,collecting_code,growing_data_heap,collecting_gen); + GC_PRINT(BEGIN_GC,growing_data_heap,collecting_gen); begin_gc(requested_bytes); /* initialize chase pointer */ @@ -768,7 +759,7 @@ void garbage_collection(CELL gen, /* collect objects referenced from older generations */ collect_cards(); - if(!collecting_code) + if(collecting_gen != TENURED) { /* don't scan code heap unless it has pointers to this generation or younger */ @@ -800,7 +791,7 @@ void garbage_collection(CELL gen, void data_gc(void) { - garbage_collection(TENURED,false,false,0); + garbage_collection(TENURED,false,0); } DEFINE_PRIMITIVE(data_gc) diff --git a/vm/data_gc.h b/vm/data_gc.h index 77d54854d7..ee2e51b6f8 100755 --- a/vm/data_gc.h +++ b/vm/data_gc.h @@ -145,7 +145,6 @@ CELL cards_scanned; /* only meaningful during a GC */ bool performing_gc; CELL collecting_gen; -bool collecting_code; /* if true, we collecting AGING space for the second time, so if it is still full, we go on to collect TENURED */ @@ -222,7 +221,6 @@ CELL heap_scan_ptr; bool gc_off; void garbage_collection(volatile CELL gen, - bool code_gc, bool growing_data_heap_, CELL requested_bytes); @@ -308,18 +306,27 @@ allocation (which does not call GC because of possible roots in volatile registers) does not run out of memory */ #define ALLOT_BUFFER_ZONE 1024 +#define SUFFICIENT_ROOM(a) (nursery->here + ALLOT_BUFFER_ZONE + a <= nursery->end) + INLINE void maybe_gc(CELL a) { - /* If we are requesting a huge object, grow immediately */ - if(nursery->size - ALLOT_BUFFER_ZONE <= a) - garbage_collection(TENURED,false,true,a); - /* If we have enough space in the nursery, just return. - Otherwise, perform a GC - this may grow the heap if - tenured space cannot hold all live objects from the nursery - even after a full GC */ - else if(a + ALLOT_BUFFER_ZONE + nursery->here > nursery->end) - garbage_collection(NURSERY,false,false,0); - /* There is now sufficient room in the nursery for 'a' */ + /* If there is enough room, return */ + if(SUFFICIENT_ROOM(a)) + return; + /* If the object is bigger than the nursery, grow immediately */ + else if(nursery->size - ALLOT_BUFFER_ZONE <= a) + garbage_collection(TENURED,true,a); + /* Otherwise, collect the nursery */ + else + { + garbage_collection(NURSERY,false,0); + + /* If there is still insufficient room, try growing the heap. + This can only happen if the number of generations is 1. */ + if(SUFFICIENT_ROOM(a)) return; + + garbage_collection(TENURED,true,a); + } } /*