ruby-changes:31215
From: ko1 <ko1@a...>
Date: Tue, 15 Oct 2013 19:22:39 +0900 (JST)
Subject: [ruby-changes:31215] ko1:r43294 (trunk): * gc.h (rb_objspace_reachable_objects_from_root): added.
ko1 2013-10-15 19:22:33 +0900 (Tue, 15 Oct 2013) New Revision: 43294 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43294 Log: * gc.h (rb_objspace_reachable_objects_from_root): added. This API provides information which objects are root objects. `category' shows what kind of root objects. * gc.c (gc_mark_roots): separate from gc_marks_body(). Modified files: trunk/ChangeLog trunk/gc.c trunk/gc.h Index: ChangeLog =================================================================== --- ChangeLog (revision 43293) +++ ChangeLog (revision 43294) @@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue Oct 15 19:18:13 2013 Koichi Sasada <ko1@a...> + + * gc.h (rb_objspace_reachable_objects_from_root): added. + This API provides information which objects are root objects. + `category' shows what kind of root objects. + + * gc.c (gc_mark_roots): separate from gc_marks_body(). + Tue Oct 15 17:47:59 2013 Tanaka Akira <akr@f...> * process.c: Fix a typo. MacOS X doesn't have ENOTSUPP. Index: gc.c =================================================================== --- gc.c (revision 43293) +++ gc.c (revision 43294) @@ -3452,7 +3452,9 @@ gc_mark_stacked_objects(rb_objspace_t *o https://github.com/ruby/ruby/blob/trunk/gc.c#L3452 shrink_stack_chunk_cache(mstack); } +#ifndef RGENGC_PRINT_TICK #define RGENGC_PRINT_TICK 0 +#endif /* the following code is only for internal tuning. */ /* Source code to use RDTSC is quoted and modified from @@ -3504,7 +3506,7 @@ tick(void) https://github.com/ruby/ruby/blob/trunk/gc.c#L3506 #define MAX_TICKS 0x100 static tick_t mark_ticks[MAX_TICKS]; -static int mark_ticks_start_line; +static const char *mark_ticks_categories[MAX_TICKS]; static void show_mark_ticks(void) @@ -3512,106 +3514,130 @@ show_mark_ticks(void) https://github.com/ruby/ruby/blob/trunk/gc.c#L3514 int i; fprintf(stderr, "mark ticks result:\n"); for (i=0; i<MAX_TICKS; i++) { - if (mark_ticks[i] > 0) { - fprintf(stderr, "@%4d\t%8lu\n", i+mark_ticks_start_line, (unsigned long)mark_ticks[i]); - } + const char *category = mark_ticks_categories[i]; + if (category) { + fprintf(stderr, "%s\t%8lu\n", category, (unsigned long)mark_ticks[i]); + } + else { + break; + } } } #endif /* RGENGC_PRINT_TICK */ static void -gc_marks_body(rb_objspace_t *objspace, int full_mark) +gc_mark_roots(rb_objspace_t *objspace, int full_mark, const char **categoryp) { struct gc_list *list; rb_thread_t *th = GET_THREAD(); #if RGENGC_PRINT_TICK tick_t start_tick = tick(); - if (mark_ticks_start_line == 0) { - mark_ticks_start_line = __LINE__; + int tick_count = 0; + const char *prev_category = 0; + + if (mark_ticks_categories[0] == 0) { atexit(show_mark_ticks); } #endif -#define MARK_CHECKPOINT_PRINT_TICK do { \ - tick_t t = tick(); \ - mark_ticks[__LINE__ - mark_ticks_start_line] = t - start_tick; \ - start_tick = tick(); \ -} while (0) - #if RGENGC_CHECK_MODE > 1 -#define MARK_CHECKPOINT do { \ +#define MARK_CHECKPOINT_DEBUG(category) do { \ objspace->rgengc.parent_object = INT2FIX(__LINE__); \ } while (0) -#elif RGENGC_PRINT_TICK -#define MARK_CHECKPOINT MARK_CHECKPOINT_PRINT_TICK -#else -#define MARK_CHECKPOINT /* do nothing */ +#else /* RGENGC_CHECK_MODE > 1 */ +#define MARK_CHECKPOINT_DEBUG(category) #endif - /* start marking */ - rgengc_report(1, objspace, "gc_marks_body: start (%s)\n", full_mark ? "full" : "minor"); - -#if USE_RGENGC - objspace->rgengc.parent_object_is_promoted = FALSE; - objspace->rgengc.parent_object = Qundef; - objspace->rgengc.during_minor_gc = full_mark ? FALSE : TRUE; - - if (objspace->rgengc.during_minor_gc) { - objspace->profile.minor_gc_count++; - rgengc_rememberset_mark(objspace); - } - else { - objspace->profile.major_gc_count++; - rgengc_mark_and_rememberset_clear(objspace); - } +#if RGENGC_PRINT_TICK +#define MARK_CHECKPOINT_PRINT_TICK(category) do { \ + if (prev_category) { \ + tick_t t = tick(); \ + mark_ticks[tick_count] = t - start_tick; \ + mark_ticks_categories[tick_count] = prev_category; \ + tick_count++; \ + } \ + prev_category = category; \ + start_tick = tick(); \ +} while (0) +#else /* RGENGC_PRINT_TICK */ +#define MARK_CHECKPOINT_PRINT_TICK(category) #endif - MARK_CHECKPOINT; +#define MARK_CHECKPOINT(category) do { \ + if (categoryp) *categoryp = category; \ + MARK_CHECKPOINT_DEBUG(category); \ + MARK_CHECKPOINT_PRINT_TICK(category); \ +} while (0) + + MARK_CHECKPOINT("vm"); SET_STACK_END; th->vm->self ? rb_gc_mark(th->vm->self) : rb_vm_mark(th->vm); - MARK_CHECKPOINT; + MARK_CHECKPOINT("finalizer_table"); mark_tbl(objspace, finalizer_table); - MARK_CHECKPOINT; + MARK_CHECKPOINT("mark_current_machine_context"); mark_current_machine_context(objspace, th); - MARK_CHECKPOINT; + MARK_CHECKPOINT("rb_gc_mark_symbols"); rb_gc_mark_symbols(full_mark); - MARK_CHECKPOINT; + MARK_CHECKPOINT("rb_gc_mark_encodings"); rb_gc_mark_encodings(); /* mark protected global variables */ - MARK_CHECKPOINT; + MARK_CHECKPOINT("global_List"); for (list = global_List; list; list = list->next) { rb_gc_mark_maybe(*list->varptr); } - MARK_CHECKPOINT; + MARK_CHECKPOINT("rb_mark_end_proc"); rb_mark_end_proc(); - MARK_CHECKPOINT; + MARK_CHECKPOINT("rb_gc_mark_global_tbl"); rb_gc_mark_global_tbl(); /* mark generic instance variables for special constants */ - MARK_CHECKPOINT; + MARK_CHECKPOINT("rb_mark_generic_ivar_tbl"); rb_mark_generic_ivar_tbl(); - MARK_CHECKPOINT; + MARK_CHECKPOINT("rb_gc_mark_parser"); rb_gc_mark_parser(); - MARK_CHECKPOINT; + MARK_CHECKPOINT("rb_gc_mark_unlinked_live_method_entries"); rb_gc_mark_unlinked_live_method_entries(th->vm); /* marking-loop */ - MARK_CHECKPOINT; + MARK_CHECKPOINT("gc_mark_stacked_objects"); gc_mark_stacked_objects(objspace); - MARK_CHECKPOINT; + MARK_CHECKPOINT("finish"); #undef MARK_CHECKPOINT +} + +static void +gc_marks_body(rb_objspace_t *objspace, int full_mark) +{ + /* start marking */ + rgengc_report(1, objspace, "gc_marks_body: start (%s)\n", full_mark ? "full" : "minor"); + +#if USE_RGENGC + objspace->rgengc.parent_object_is_promoted = FALSE; + objspace->rgengc.parent_object = Qundef; + objspace->rgengc.during_minor_gc = full_mark ? FALSE : TRUE; + + if (objspace->rgengc.during_minor_gc) { + objspace->profile.minor_gc_count++; + rgengc_rememberset_mark(objspace); + } + else { + objspace->profile.major_gc_count++; + rgengc_mark_and_rememberset_clear(objspace); + } +#endif + gc_mark_roots(objspace, full_mark, 0); /* cleanup */ rgengc_report(1, objspace, "gc_marks_body: end (%s)\n", full_mark ? "full" : "minor"); @@ -4701,6 +4727,39 @@ rb_objspace_reachable_objects_from(VALUE https://github.com/ruby/ruby/blob/trunk/gc.c#L4727 } } +struct root_objects_data { + const char *category; + void (*func)(const char *category, VALUE, void *); + void *data; +}; + +static void +root_objects_from(VALUE obj, void *ptr) +{ + const struct root_objects_data *data = (struct root_objects_data *)ptr; + (*data->func)(data->category, obj, data->data); +} + +void +rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *passing_data) +{ + rb_objspace_t *objspace = &rb_objspace; + struct root_objects_data data; + struct mark_func_data_struct mfd; + + data.func = func; + data.data = passing_data; + + mfd.mark_func = root_objects_from; + mfd.data = &data; + + objspace->mark_func_data = &mfd; + { + gc_mark_roots(objspace, FALSE, &data.category); + } + objspace->mark_func_data = 0; +} + /* ------------------------ Extended allocator ------------------------ */ Index: gc.h =================================================================== --- gc.h (revision 43293) +++ gc.h (revision 43294) @@ -88,6 +88,7 @@ RUBY_SYMBOL_EXPORT_BEGIN https://github.com/ruby/ruby/blob/trunk/gc.h#L88 /* exports for objspace module */ size_t rb_objspace_data_type_memsize(VALUE obj); void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data); +void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *data); int rb_objspace_markable_object_p(VALUE obj); int rb_objspace_internal_object_p(VALUE obj); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/