ruby-changes:29953
From: ko1 <ko1@a...>
Date: Tue, 16 Jul 2013 19:29:42 +0900 (JST)
Subject: [ruby-changes:29953] ko1:r42005 (trunk): * gc.c: slim a path of newobj_of().
ko1 2013-07-16 19:29:31 +0900 (Tue, 16 Jul 2013) New Revision: 42005 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42005 Log: * gc.c: slim a path of newobj_of(). * gc.c (objspace): add a new field objspace::freelist, which contains available RVALUEs. * gc.c (newobj_of): simply call new function `get_freeobj()'. get_freeobj() returns objspace::freelist. If objspace::freelist is not available, refill objspace::freelist with a slot pointed by objspace::heap::free_slots. * gc.c (before_gc_sweep): clear objspace::freelist. * gc.c (slot_sweep): clear slot::freelist. * gc.c (heaps_prepare_freeslot): renamed to heaps_prepare_freeslot. * gc.c (unlink_free_heap_slot): remove unused function. * gc.c (rb_free_const_table): remove unused function. Modified files: trunk/ChangeLog trunk/gc.c Index: ChangeLog =================================================================== --- ChangeLog (revision 42004) +++ ChangeLog (revision 42005) @@ -1,3 +1,25 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue Jul 16 19:18:51 2013 Koichi Sasada <ko1@a...> + + * gc.c: slim a path of newobj_of(). + + * gc.c (objspace): add a new field objspace::freelist, which contains + available RVALUEs. + + * gc.c (newobj_of): simply call new function `get_freeobj()'. + get_freeobj() returns objspace::freelist. If objspace::freelist + is not available, refill objspace::freelist with a slot pointed by + objspace::heap::free_slots. + + * gc.c (before_gc_sweep): clear objspace::freelist. + + * gc.c (slot_sweep): clear slot::freelist. + + * gc.c (heaps_prepare_freeslot): renamed to heaps_prepare_freeslot. + + * gc.c (unlink_free_heap_slot): remove unused function. + + * gc.c (rb_free_const_table): remove unused function. + Tue Jul 16 19:05:12 2013 Tanaka Akira <akr@f...> * bignum.c (big_shift3): Big shift width is not a problem for right Index: gc.c =================================================================== --- gc.c (revision 42004) +++ gc.c (revision 42005) @@ -372,6 +372,7 @@ typedef struct rb_objspace { https://github.com/ruby/ruby/blob/trunk/gc.c#L372 size_t total_freed_object_num; rb_event_flag_t hook_events; /* this place may be affinity with memory cache */ VALUE gc_stress; + RVALUE *freelist; struct mark_func_data_struct { void *data; @@ -500,7 +501,6 @@ VALUE *ruby_initial_gc_stress_ptr = &rb_ https://github.com/ruby/ruby/blob/trunk/gc.c#L501 #endif #define RANY(o) ((RVALUE*)(o)) -#define has_free_object (objspace->heap.free_slots && objspace->heap.free_slots->freelist) int ruby_gc_debug_indent = 0; VALUE rb_mGC; @@ -523,8 +523,8 @@ static void init_mark_stack(mark_stack_t https://github.com/ruby/ruby/blob/trunk/gc.c#L523 static VALUE lazy_sweep_enable(void); static int garbage_collect(rb_objspace_t *, int full_mark, int immediate_sweep, int reason); static int garbage_collect_body(rb_objspace_t *, int full_mark, int immediate_sweep, int reason); -static int gc_prepare_free_objects(rb_objspace_t *); static void mark_tbl(rb_objspace_t *, st_table *); +static int lazy_sweep(rb_objspace_t *objspace); static void rest_sweep(rb_objspace_t *); static void gc_mark_stacked_objects(rb_objspace_t *); @@ -732,13 +732,6 @@ allocate_sorted_heaps(rb_objspace_t *obj https://github.com/ruby/ruby/blob/trunk/gc.c#L732 } } -static void -unlink_free_heap_slot(rb_objspace_t *objspace, struct heaps_slot *slot) -{ - objspace->heap.free_slots = slot->free_next; - slot->free_next = NULL; -} - static inline void slot_add_freeobj(rb_objspace_t *objspace, struct heaps_slot *slot, VALUE obj) { @@ -919,6 +912,83 @@ heaps_increment(rb_objspace_t *objspace) https://github.com/ruby/ruby/blob/trunk/gc.c#L912 return FALSE; } +static int +ready_to_gc(rb_objspace_t *objspace) +{ + if (dont_gc || during_gc) { + if (!objspace->freelist && !objspace->heap.free_slots) { + if (!heaps_increment(objspace)) { + set_heaps_increment(objspace); + heaps_increment(objspace); + } + } + return FALSE; + } + return TRUE; +} + +static struct heaps_slot * +heaps_prepare_freeslot(rb_objspace_t *objspace) +{ + if (!GC_ENABLE_LAZY_SWEEP && objspace->flags.dont_lazy_sweep) { + if (heaps_increment(objspace) == 0 && + garbage_collect(objspace, FALSE, TRUE, GPR_FLAG_NEWOBJ) == 0) { + goto err; + } + goto ok; + } + + if (!ready_to_gc(objspace)) return objspace->heap.free_slots; + + during_gc++; + + if ((is_lazy_sweeping(objspace) && lazy_sweep(objspace)) || + heaps_increment(objspace)) { + goto ok; + } + +#if GC_PROFILE_MORE_DETAIL + objspace->profile.prepare_time = 0; +#endif + + if (garbage_collect_body(objspace, 0, 0, GPR_FLAG_NEWOBJ) == 0) { + err: + during_gc = 0; + rb_memerror(); + } + ok: + during_gc = 0; + return objspace->heap.free_slots; +} + +static inline struct heaps_slot * +heaps_get_freeslot(rb_objspace_t *objspace) +{ + struct heaps_slot *slot; + + slot = objspace->heap.free_slots; + while (slot == NULL) { + slot = heaps_prepare_freeslot(objspace); + } + objspace->heap.free_slots = slot->free_next; + + return slot; +} + +static inline VALUE +get_freeobj(rb_objspace_t *objspace) +{ + RVALUE *p = objspace->freelist; + + while (UNLIKELY(p == NULL)) { + struct heaps_slot *slot = heaps_get_freeslot(objspace); + p = objspace->freelist = slot->freelist; + } + objspace->freelist = p->as.free.next; + + return (VALUE)p; +} + void rb_objspace_set_event_hook(const rb_event_flag_t event) { @@ -939,7 +1009,6 @@ gc_event_hook_body(rb_objspace_t *objspa https://github.com/ruby/ruby/blob/trunk/gc.c#L1009 } \ } while (0) - static VALUE newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3) { @@ -959,18 +1028,7 @@ newobj_of(VALUE klass, VALUE flags, VALU https://github.com/ruby/ruby/blob/trunk/gc.c#L1028 } } - if (UNLIKELY(!has_free_object)) { - if (!gc_prepare_free_objects(objspace)) { - during_gc = 0; - rb_memerror(); - } - } - - obj = (VALUE)objspace->heap.free_slots->freelist; - objspace->heap.free_slots->freelist = RANY(obj)->as.free.next; - if (objspace->heap.free_slots->freelist == NULL) { - unlink_free_heap_slot(objspace, objspace->heap.free_slots); - } + obj = get_freeobj(objspace); /* OBJSETUP */ RBASIC(obj)->flags = flags; @@ -1127,23 +1185,6 @@ rb_free_const_table(st_table *tbl) https://github.com/ruby/ruby/blob/trunk/gc.c#L1185 st_free_table(tbl); } -static int obj_free(rb_objspace_t *, VALUE); - -static inline struct heaps_slot * -add_slot_local_freelist(rb_objspace_t *objspace, RVALUE *p) -{ - struct heaps_slot *slot; - - (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); - p->as.free.flags = 0; - slot = GET_HEAP_SLOT(p); - p->as.free.next = slot->freelist; - slot->freelist = p; - rgengc_report(3, objspace, "add_slot_local_freelist: %p (%s) is added to freelist\n", p, obj_type_name((VALUE)p)); - - return slot; -} - static void unlink_heap_slot(rb_objspace_t *objspace, struct heaps_slot *slot) { @@ -2218,6 +2259,7 @@ slot_sweep(rb_objspace_t *objspace, stru https://github.com/ruby/ruby/blob/trunk/gc.c#L2259 rgengc_report(1, objspace, "slot_sweep: start.\n"); + sweep_slot->freelist = NULL; p = sweep_slot->header->start; pend = p + sweep_slot->header->limit; offset = p - NUM_IN_SLOT(p); bits = GET_HEAP_MARK_BITS(p); @@ -2308,21 +2350,6 @@ slot_sweep(rb_objspace_t *objspace, stru https://github.com/ruby/ruby/blob/trunk/gc.c#L2350 rgengc_report(1, objspace, "slot_sweep: end.\n"); } -static int -ready_to_gc(rb_objspace_t *objspace) -{ - if (dont_gc || during_gc) { - if (!has_free_object) { - if (!heaps_increment(objspace)) { - set_heaps_increment(objspace); - heaps_increment(objspace); - } - } - return FALSE; - } - return TRUE; -} - #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4 __attribute__((noinline)) #endif @@ -2341,6 +2368,7 @@ before_gc_sweep(rb_objspace_t *objspace) https://github.com/ruby/ruby/blob/trunk/gc.c#L2368 objspace->heap.sweep_slots = heaps; objspace->heap.free_num = 0; objspace->heap.free_slots = NULL; + objspace->freelist = NULL; malloc_increase2 += ATOMIC_SIZE_EXCHANGE(malloc_increase,0); @@ -2408,7 +2436,7 @@ lazy_sweep(rb_objspace_t *objspace) https://github.com/ruby/ruby/blob/trunk/gc.c#L2436 if (!next) after_gc_sweep(objspace); - if (has_free_object) { + if (objspace->heap.free_slots) { result = TRUE; break; } @@ -2455,7 +2483,7 @@ gc_sweep(rb_objspace_t *objspace, int im https://github.com/ruby/ruby/blob/trunk/gc.c#L2483 lazy_sweep(objspace); } - if (!has_free_object) { + if (!objspace->heap.free_slots) { /* there is no free after slot_sweep() */ set_heaps_increment(objspace); if (!heaps_increment(objspace)) { /* can't allocate additional free objects */ @@ -2465,41 +2493,6 @@ gc_sweep(rb_objspace_t *objspace, int im https://github.com/ruby/ruby/blob/trunk/gc.c#L2493 } } -static int -gc_prepare_free_objects(rb_objspace_t *objspace) -{ - if (!GC_ENABLE_LAZY_SWEEP || objspace->flags.dont_lazy_sweep) { - if (heaps_increment(objspace)) { - return TRUE; - } - else { - return garbage_collect(objspace, FALSE, TRUE, GPR_FLAG_NEWOBJ); - } - } - - if (!ready_to_gc(objspace)) return TRUE; - - during_gc++; - - if (is_lazy_sweeping(objspace)) { - if (lazy_sweep(objspace)) { - during_gc = 0; - return TRUE; - } - } - else { - if (heaps_increment(objspace)) { - during_gc = 0; - return TRUE; - } - } - -#if GC_PROFILE_MORE_DETAIL - objspace->profile.prepare_time = 0; -#endif - return garbage_collect_body(objspace, 0, 0, GPR_FLAG_NEWOBJ); -} - /* Marking stack */ static void push_mark_stack(mark_stack_t *, VALUE); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/