diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-07-16 10:29:31 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-07-16 10:29:31 +0000 |
commit | a97c3b75855e86220d0c17544fb0f2c87c7e854d (patch) | |
tree | 3cc791289df8e783b6ded1b4bf6e7abecf78001d /gc.c | |
parent | 4106413465aa37e4cb81b71f56f06613d06d88d1 (diff) | |
download | ruby-a97c3b75855e86220d0c17544fb0f2c87c7e854d.tar.gz |
* 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.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42005 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 175 |
1 files changed, 84 insertions, 91 deletions
@@ -372,6 +372,7 @@ typedef struct rb_objspace { 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_objspace.gc_stress; #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 *stack); 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 *objspace, size_t next_heaps_length) } } -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) 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 *objspace, const rb_event_flag_t event, VALUE d } \ } 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, VALUE v1, VALUE v2, VALUE v3) } } - 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) 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, struct heaps_slot *sweep_slot) 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, struct heaps_slot *sweep_slot) 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) 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) 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 immediate_sweep) 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 immediate_sweep) } } -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); |