ruby-changes:6371
From: nari <ko1@a...>
Date: Sat, 5 Jul 2008 16:16:25 +0900 (JST)
Subject: [ruby-changes:6371] Ruby:r17887 (trunk): * gc.c: revert. before lazy sweep.
nari 2008-07-05 16:15:41 +0900 (Sat, 05 Jul 2008) New Revision: 17887 Modified files: trunk/ChangeLog trunk/gc.c Log: * gc.c: revert. before lazy sweep. http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17887 Index: ChangeLog =================================================================== --- ChangeLog (revision 17886) +++ ChangeLog (revision 17887) @@ -1,3 +1,7 @@ +Sat Jul 5 16:12:54 2008 Narihiro Nakamura <authorNari@g...> + + * gc.c: revert. before lazy sweep. + Sat Jul 5 09:55:44 2008 Masaki Suketa <masaki.suketa@n...> * ext/win32ole/win32ole.c: add WIN32OLE#ole_respond_to? @@ -56,7 +60,7 @@ * lib/net/ftp.rb (Net::FTP#sendport): use divmod. [ruby-core:17557] -Fri Jul 4 11:08:37 2008 nari <authorNari@g...> +Fri Jul 4 11:08:37 2008 Narihiro Nakamura <authorNari@g...> * gc.c (garbage_collect_force): sweep is completely ended. Index: gc.c =================================================================== --- gc.c (revision 17886) +++ gc.c (revision 17887) @@ -129,17 +129,10 @@ #pragma pack(pop) #endif -enum slot_color { - WHITE = 0x00, /* garbage */ - BLACK = 0x01, /* used */ - GRAY = 0x02, /* not sweep */ -}; - struct heaps_slot { void *membase; RVALUE *slot; int limit; - enum slot_color color; }; #define HEAP_MIN_SLOTS 10000 @@ -169,11 +162,6 @@ RVALUE *freelist; RVALUE *range[2]; RVALUE *freed; - size_t live; - size_t dead; - size_t do_heap_free; - size_t sweep_index; - size_t sweep_increment; } heap; struct { int dont_gc; @@ -191,7 +179,6 @@ struct gc_list *global_list; unsigned int count; int gc_stress; - int gc_not_lazy_sweep; } rb_objspace_t; #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE @@ -213,11 +200,6 @@ #define himem objspace->heap.range[1] #define heaps_inc objspace->heap.increment #define heaps_freed objspace->heap.freed -#define live objspace->heap.live -#define dead objspace->heap.dead -#define do_heap_free objspace->heap.do_heap_free -#define heaps_sweep_index objspace->heap.sweep_index -#define heaps_sweep_inc objspace->heap.sweep_increment #define dont_gc objspace->flags.dont_gc #define during_gc objspace->flags.during_gc #define finalizer_table objspace->final.table @@ -227,7 +209,6 @@ #define mark_stack_overflow objspace->markstack.overflow #define global_List objspace->global_list #define ruby_gc_stress objspace->gc_stress -#define ruby_gc_not_lazy_sweep objspace->gc_not_lazy_sweep #define need_call_final (finalizer_table && finalizer_table->num_entries) @@ -268,7 +249,6 @@ static void run_final(rb_objspace_t *objspace, VALUE obj); static int garbage_collect(rb_objspace_t *objspace); -static int garbage_collect_force(rb_objspace_t *objspace); void rb_global_variable(VALUE *var) @@ -345,11 +325,11 @@ if ((ruby_gc_stress && !ruby_disable_gc_stress) || (malloc_increase+size) > malloc_limit) { - garbage_collect_force(objspace); + garbage_collect(objspace); } RUBY_CRITICAL(mem = malloc(size)); if (!mem) { - if (garbage_collect_force(objspace)) { + if (garbage_collect(objspace)) { RUBY_CRITICAL(mem = malloc(size)); } if (!mem) { @@ -385,9 +365,10 @@ objspace->malloc_params.allocated_size -= size; ptr = (size_t *)ptr - 1; #endif + RUBY_CRITICAL(mem = realloc(ptr, size)); if (!mem) { - if (garbage_collect_force(objspace)) { + if (garbage_collect(objspace)) { RUBY_CRITICAL(mem = realloc(ptr, size)); } if (!mem) { @@ -578,8 +559,6 @@ heaps_length = next_heaps_length; } -#define RANY(o) ((RVALUE*)(o)) - static void assign_heap_slot(rb_objspace_t *objspace) { @@ -623,7 +602,6 @@ heaps[hi].membase = membase; heaps[hi].slot = p; heaps[hi].limit = objs; - heaps[hi].color = BLACK; pend = p + objs; if (lomem == 0 || lomem > p) lomem = p; if (himem < pend) himem = pend; @@ -635,9 +613,6 @@ freelist = p; p++; } - if (hi < heaps_sweep_index) { - heaps_sweep_index++; - } } static void @@ -680,13 +655,15 @@ return Qfalse; } +#define RANY(o) ((RVALUE*)(o)) + static VALUE rb_newobj_from_heap(rb_objspace_t *objspace) { VALUE obj; if ((ruby_gc_stress && !ruby_disable_gc_stress) || !freelist) { - if (!garbage_collect(objspace)) { + if (!heaps_increment(objspace) && !garbage_collect(objspace)) { rb_memerror(); } } @@ -1063,7 +1040,6 @@ if (obj->as.basic.flags == 0) return; /* free cell */ if (obj->as.basic.flags & FL_MARK) return; /* already marked */ obj->as.basic.flags |= FL_MARK; - live++; if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) { if (!mark_stack_overflow) { @@ -1099,7 +1075,6 @@ if (obj->as.basic.flags == 0) return; /* free cell */ if (obj->as.basic.flags & FL_MARK) return; /* already marked */ obj->as.basic.flags |= FL_MARK; - live++; marking: if (FL_TEST(obj, FL_EXIVAR)) { @@ -1359,131 +1334,139 @@ if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */ VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); p->as.free.flags = 0; + p->as.free.next = freelist; + freelist = p; } p = tmp; } } -void rb_gc_abort_threads(void); - -static int -slot_sweep(rb_objspace_t *objspace, struct heaps_slot *target) +static void +free_unused_heaps(rb_objspace_t *objspace) { - RVALUE *p, *pend, *free; - RVALUE *final; - int freed = 0; + size_t i, j; + RVALUE *last = 0; - if (target->color == BLACK || target->color == WHITE) { - return Qfalse; - } - - final = deferred_final_list; - free = freelist; - p = target->slot; pend = p + target->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { - if (p->as.basic.flags) { - obj_free(objspace, (VALUE)p); + for (i = j = 1; j < heaps_used; i++) { + if (heaps[i].limit == 0) { + if (!last) { + last = heaps[i].membase; } - if (need_call_final && FL_TEST(p, FL_FINALIZE)) { - p->as.free.flags = FL_MARK; /* remain marked */ - p->as.free.next = deferred_final_list; - deferred_final_list = p; - } else { - VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); - p->as.free.flags = 0; - p->as.free.next = freelist; - freelist = p; + free(heaps[i].membase); } - freed++; + heaps_used--; } - else if (RBASIC(p)->flags == FL_MARK) { - /* objects to be finalized */ - /* do nothing remain marked */ - } else { - p->as.basic.flags &= ~FL_MARK; + if (i != j) { + heaps[j] = heaps[i]; + } + j++; } - p++; } - dead += freed; - if (freed == target->limit && dead > do_heap_free) { - RVALUE *pp; - - target->limit = 0; - target->color = WHITE; - for (pp = deferred_final_list; pp != final; pp = pp->as.free.next) { - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ + if (last) { + if (last < heaps_freed) { + free(heaps_freed); + heaps_freed = last; } - freelist = free; /* cancel this page from freelist */ + else { + free(last); + } } - else { - target->color = BLACK; - } - return Qtrue; } static void -heap_sweep_increment(rb_objspace_t *objspace) +gc_sweep(rb_objspace_t *objspace) { - int i = 0; + RVALUE *p, *pend, *final_list; + size_t freed = 0; + size_t i; + size_t live = 0, free_min = 0, do_heap_free = 0; - while (i < heaps_sweep_inc && heaps_sweep_index < heaps_used) { - if (slot_sweep(objspace, &heaps[heaps_sweep_index])) { - i++; - } - heaps_sweep_index++; + do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65; + free_min = (heaps_used * HEAP_OBJ_LIMIT) * 0.2; + if (free_min < FREE_MIN) { + do_heap_free = heaps_used * HEAP_OBJ_LIMIT; + free_min = FREE_MIN; } -} -static void -heap_sweep(rb_objspace_t *objspace) -{ - while (!freelist && heaps_sweep_index < heaps_used) { - slot_sweep(objspace, &heaps[heaps_sweep_index]); - heaps_sweep_index++; - } -} + freelist = 0; + final_list = deferred_final_list; + deferred_final_list = 0; + for (i = 0; i < heaps_used; i++) { + int n = 0; + RVALUE *free = freelist; + RVALUE *final = final_list; -#define GC_NOT_LAZY_SWEEP 0 + p = heaps[i].slot; pend = p + heaps[i].limit; + while (p < pend) { + if (!(p->as.basic.flags & FL_MARK)) { + if (p->as.basic.flags) { + obj_free(objspace, (VALUE)p); + } + if (need_call_final && FL_TEST(p, FL_FINALIZE)) { + p->as.free.flags = FL_MARK; /* remain marked */ + p->as.free.next = final_list; + final_list = p; + } + else { + VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); + p->as.free.flags = 0; + p->as.free.next = freelist; + freelist = p; + } + n++; + } + else if (RBASIC(p)->flags == FL_MARK) { + /* objects to be finalized */ + /* do nothing remain marked */ + } + else { + RBASIC(p)->flags &= ~FL_MARK; + live++; + } + p++; + } + if (n == heaps[i].limit && freed > do_heap_free) { + RVALUE *pp; -static void -heap_all_sweep(rb_objspace_t *objspace) -{ - while (heaps_sweep_index < heaps_used) { - slot_sweep(objspace, &heaps[heaps_sweep_index]); - heaps_sweep_index++; + heaps[i].limit = 0; + for (pp = final_list; pp != final; pp = pp->as.free.next) { + p->as.free.flags |= FL_SINGLETON; /* freeing page mark */ + } + freelist = free; /* cancel this page from freelist */ + } + else { + freed += n; + } } -} - -static int -gc_lazy_sweep(rb_objspace_t *objspace, rb_thread_t *th) -{ - - if (heaps_increment(objspace)) { - heap_sweep_increment(objspace); + if (malloc_increase > malloc_limit) { + malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); + if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; } - else { - heap_sweep(objspace); + malloc_increase = 0; + if (freed < free_min) { + set_heaps_increment(objspace); + heaps_increment(objspace); } + during_gc = 0; - if (ruby_gc_not_lazy_sweep || GC_NOT_LAZY_SWEEP) { - heap_all_sweep(objspace); + /* clear finalization list */ + if (final_list) { + deferred_final_list = final_list; + return; } - - if (!freelist) { - return Qfalse; - } - - return Qtrue; + free_unused_heaps(objspace); } void rb_gc_force_recycle(VALUE p) { + rb_objspace_t *objspace = &rb_objspace; VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); RANY(p)->as.free.flags = 0; + RANY(p)->as.free.next = freelist; + freelist = RANY(p); } static void @@ -1684,87 +1667,30 @@ void rb_gc_mark_encodings(void); -static void -gc_mark_all_clear(rb_objspace_t *objspace) +static int +garbage_collect(rb_objspace_t *objspace) { - RVALUE *last = 0; - size_t i, j; - - for (i = j = 0; j < heaps_used; i++) { - if (heaps[i].color == WHITE && !deferred_final_list) { - if (!last) { - last = heaps[i].membase; - } - else { - free(heaps[i].membase); - } - heaps_used--; - } - else { - if (heaps[i].color == GRAY) { - RVALUE *p, *pend; - p = heaps[i].slot; pend = p + heaps[i].limit; - while (p < pend) { - if (!(RBASIC(p)->flags & FL_MARK)) { - if (p->as.basic.flags && !FL_TEST(p, FL_FINALIZE)) { - obj_free(objspace, (VALUE)p); - VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); - p->as.free.flags = 0; - } - } - else if (RBASIC(p)->flags != FL_MARK) { - p->as.basic.flags &= ~FL_MARK; - } - p++; - } - } - else { - heaps[i].color = GRAY; - } - if (i != j) { - heaps[j] = heaps[i]; - } - j++; - } - } - if (last) { - if (last < heaps_freed) { - free(heaps_freed); - heaps_freed = last; - } - else { - free(last); - } - } -} + struct gc_list *list; + rb_thread_t *th = GET_THREAD(); -static void -set_lazy_sweep_params(rb_objspace_t *objspace) -{ - size_t free_min = 0; + if (GC_NOTIFY) printf("start garbage_collect()\n"); - dead = 0; - heaps_sweep_index = 0; - heaps_sweep_inc = (heaps_used / 10) + 1; - do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65; - free_min = (heaps_used * HEAP_OBJ_LIMIT) * 0.2; - if (free_min < FREE_MIN) free_min = FREE_MIN; - if (free_min > (heaps_used * HEAP_OBJ_LIMIT - live)) { - set_heaps_increment(objspace); - heaps_sweep_inc = (heaps_used + heaps_sweep_inc) / heaps_sweep_inc + 1; + if (!heaps) { + return Qfalse; } -} -static void -gc_marks(rb_objspace_t *objspace, rb_thread_t *th) -{ - struct gc_list *list; + if (dont_gc || during_gc) { + if (!freelist) { + if (!heaps_increment(objspace)) { + set_heaps_increment(objspace); + heaps_increment(objspace); + } + } + return Qtrue; + } + during_gc++; + objspace->count++; - live = 0; - freelist = 0; - - gc_mark_all_clear(objspace); - SET_STACK_END; init_mark_stack(objspace); @@ -1781,7 +1707,6 @@ rb_gc_mark_symbols(); rb_gc_mark_encodings(); - /* mark protected global variables */ for (list = global_List; list; list = list->next) { rb_gc_mark_maybe(*list->varptr); @@ -1807,55 +1732,9 @@ } } - set_lazy_sweep_params(objspace); -} + gc_sweep(objspace); -static int -garbage_collect_force(rb_objspace_t *objspace) -{ - int is_gc_success; - - if (malloc_increase > malloc_limit) { - malloc_limit += (malloc_increase - malloc_limit) * (double)live / (heaps_used * HEAP_OBJ_LIMIT); - if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; - } - malloc_increase = 0; - ruby_gc_not_lazy_sweep = Qtrue; - is_gc_success = garbage_collect(objspace); - ruby_gc_not_lazy_sweep = Qfalse; - return is_gc_success; -} - -static int -garbage_collect(rb_objspace_t *objspace) -{ - rb_thread_t *th = GET_THREAD(); - - if (GC_NOTIFY) printf("start garbage_collect()\n"); - - if (!heaps) { - return Qfalse; - } - - if (dont_gc || during_gc) { - if (!freelist) { - if (!heaps_increment(objspace)) { - set_heaps_increment(objspace); - heaps_increment(objspace); - } - } - return Qtrue; - } - during_gc++; - objspace->count++; - - while (!gc_lazy_sweep(objspace, th)) { - gc_marks(objspace, th); - } - if (GC_NOTIFY) printf("end garbage_collect()\n"); - during_gc = 0; - return Qtrue; } @@ -1970,7 +1849,6 @@ p = heaps[i].slot; pend = p + heaps[i].limit; for (;p < pend; p++) { - if (!freelist) garbage_collect_force(objspace); if (p->as.basic.flags) { switch (BUILTIN_TYPE(p)) { case T_NONE: @@ -2156,6 +2034,7 @@ if (p) { finalize_list(objspace, p); } + free_unused_heaps(objspace); } void @@ -2227,8 +2106,8 @@ rb_gc(void) { rb_objspace_t *objspace = &rb_objspace; - gc_finalize_deferred(objspace); garbage_collect(objspace); + gc_finalize_deferred(objspace); } /* -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/