mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43294 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1fc32a34ef
commit
f241016825
3 changed files with 131 additions and 63 deletions
|
@ -1,3 +1,11 @@
|
|||
Tue Oct 15 19:18:13 2013 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* 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@fsij.org>
|
||||
|
||||
* process.c: Fix a typo. MacOS X doesn't have ENOTSUPP.
|
||||
|
|
185
gc.c
185
gc.c
|
@ -3452,7 +3452,9 @@ gc_mark_stacked_objects(rb_objspace_t *objspace)
|
|||
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)
|
|||
|
||||
#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,44 +3514,112 @@ show_mark_ticks(void)
|
|||
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
|
||||
|
||||
#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
|
||||
|
||||
#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("finalizer_table");
|
||||
mark_tbl(objspace, finalizer_table);
|
||||
|
||||
MARK_CHECKPOINT("mark_current_machine_context");
|
||||
mark_current_machine_context(objspace, th);
|
||||
|
||||
MARK_CHECKPOINT("rb_gc_mark_symbols");
|
||||
rb_gc_mark_symbols(full_mark);
|
||||
|
||||
MARK_CHECKPOINT("rb_gc_mark_encodings");
|
||||
rb_gc_mark_encodings();
|
||||
|
||||
/* mark protected global variables */
|
||||
MARK_CHECKPOINT("global_List");
|
||||
for (list = global_List; list; list = list->next) {
|
||||
rb_gc_mark_maybe(*list->varptr);
|
||||
}
|
||||
|
||||
MARK_CHECKPOINT("rb_mark_end_proc");
|
||||
rb_mark_end_proc();
|
||||
|
||||
MARK_CHECKPOINT("rb_gc_mark_global_tbl");
|
||||
rb_gc_mark_global_tbl();
|
||||
|
||||
/* mark generic instance variables for special constants */
|
||||
MARK_CHECKPOINT("rb_mark_generic_ivar_tbl");
|
||||
rb_mark_generic_ivar_tbl();
|
||||
|
||||
MARK_CHECKPOINT("rb_gc_mark_parser");
|
||||
rb_gc_mark_parser();
|
||||
|
||||
MARK_CHECKPOINT("rb_gc_mark_unlinked_live_method_entries");
|
||||
rb_gc_mark_unlinked_live_method_entries(th->vm);
|
||||
|
||||
/* marking-loop */
|
||||
MARK_CHECKPOINT("gc_mark_stacked_objects");
|
||||
gc_mark_stacked_objects(objspace);
|
||||
|
||||
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");
|
||||
|
||||
|
@ -3567,51 +3637,7 @@ gc_marks_body(rb_objspace_t *objspace, int full_mark)
|
|||
rgengc_mark_and_rememberset_clear(objspace);
|
||||
}
|
||||
#endif
|
||||
|
||||
MARK_CHECKPOINT;
|
||||
SET_STACK_END;
|
||||
th->vm->self ? rb_gc_mark(th->vm->self) : rb_vm_mark(th->vm);
|
||||
|
||||
MARK_CHECKPOINT;
|
||||
mark_tbl(objspace, finalizer_table);
|
||||
|
||||
MARK_CHECKPOINT;
|
||||
mark_current_machine_context(objspace, th);
|
||||
|
||||
MARK_CHECKPOINT;
|
||||
rb_gc_mark_symbols(full_mark);
|
||||
|
||||
MARK_CHECKPOINT;
|
||||
rb_gc_mark_encodings();
|
||||
|
||||
/* mark protected global variables */
|
||||
MARK_CHECKPOINT;
|
||||
for (list = global_List; list; list = list->next) {
|
||||
rb_gc_mark_maybe(*list->varptr);
|
||||
}
|
||||
|
||||
MARK_CHECKPOINT;
|
||||
rb_mark_end_proc();
|
||||
|
||||
MARK_CHECKPOINT;
|
||||
rb_gc_mark_global_tbl();
|
||||
|
||||
/* mark generic instance variables for special constants */
|
||||
MARK_CHECKPOINT;
|
||||
rb_mark_generic_ivar_tbl();
|
||||
|
||||
MARK_CHECKPOINT;
|
||||
rb_gc_mark_parser();
|
||||
|
||||
MARK_CHECKPOINT;
|
||||
rb_gc_mark_unlinked_live_method_entries(th->vm);
|
||||
|
||||
/* marking-loop */
|
||||
MARK_CHECKPOINT;
|
||||
gc_mark_stacked_objects(objspace);
|
||||
|
||||
MARK_CHECKPOINT;
|
||||
#undef MARK_CHECKPOINT
|
||||
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 obj, void (func)(VALUE, void *), void *
|
|||
}
|
||||
}
|
||||
|
||||
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 ------------------------
|
||||
*/
|
||||
|
|
1
gc.h
1
gc.h
|
@ -88,6 +88,7 @@ RUBY_SYMBOL_EXPORT_BEGIN
|
|||
/* 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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue