[前][次][番号順一覧][スレッド一覧]

ruby-changes:31231

From: ko1 <ko1@a...>
Date: Thu, 17 Oct 2013 05:21:11 +0900 (JST)
Subject: [ruby-changes:31231] ko1:r43310 (trunk): * ext/objspace/object_tracing.c: add new method

ko1	2013-10-17 05:21:04 +0900 (Thu, 17 Oct 2013)

  New Revision: 43310

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43310

  Log:
    * ext/objspace/object_tracing.c: add new method
      ObjectSpace.trace_object_allocations_debug_start for GC debugging.
      If you encounter the BUG "... is T_NONE" (and so on) on your
      application, please try this method at the beggining of your app.

  Modified files:
    trunk/ChangeLog
    trunk/ext/objspace/object_tracing.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 43309)
+++ ChangeLog	(revision 43310)
@@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Oct 17 05:17:33 2013  Koichi Sasada  <ko1@a...>
+
+	* ext/objspace/object_tracing.c: add new method
+	  ObjectSpace.trace_object_allocations_debug_start for GC debugging.
+	  If you encounter the BUG "... is T_NONE" (and so on) on your
+	  application, please try this method at the beggining of your app.
+
 Wed Oct 16 22:35:27 2013  Zachary Scott  <e@z...>
 
 	* ext/io/nonblock/nonblock.c: use rb_cIO instead of VALUE
Index: ext/objspace/object_tracing.c
===================================================================
--- ext/objspace/object_tracing.c	(revision 43309)
+++ ext/objspace/object_tracing.c	(revision 43310)
@@ -20,6 +20,7 @@ size_t rb_gc_count(void); /* from gc.c * https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L20
 
 struct traceobj_arg {
     int running;
+    int keep_remains;
     VALUE newobj_trace;
     VALUE freeobj_trace;
     st_table *object_table; /* obj (VALUE) -> allocation_info */
@@ -29,6 +30,11 @@ struct traceobj_arg { https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L30
 
 /* all of information don't need marking. */
 struct allocation_info {
+    int living;
+    VALUE flags;
+    VALUE klass;
+
+    /* allocation info */
     const char *path;
     unsigned long line;
     const char *class_path;
@@ -87,11 +93,23 @@ newobj_i(VALUE tpval, void *data) https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L93
     VALUE line = rb_tracearg_lineno(tparg);
     VALUE mid = rb_tracearg_method_id(tparg);
     VALUE klass = rb_tracearg_defined_class(tparg);
-    struct allocation_info *info = (struct allocation_info *)ruby_xmalloc(sizeof(struct allocation_info));
+    struct allocation_info *info;
     const char *path_cstr = RTEST(path) ? make_unique_str(arg->str_table, RSTRING_PTR(path), RSTRING_LEN(path)) : 0;
     VALUE class_path = RTEST(klass) ? rb_class_path(klass) : Qnil;
     const char *class_path_cstr = RTEST(class_path) ? make_unique_str(arg->str_table, RSTRING_PTR(class_path), RSTRING_LEN(class_path)) : 0;
 
+    if (arg->keep_remains && st_lookup(arg->object_table, (st_data_t)obj, (st_data_t *)&info)) {
+	if (info->living) rb_bug("newobj_i: reuse living object: %p", (void *)obj);
+	delete_unique_str(arg->str_table, info->path);
+	delete_unique_str(arg->str_table, info->class_path);
+    }
+    else {
+	info = (struct allocation_info *)ruby_xmalloc(sizeof(struct allocation_info));
+    }
+    info->living = 1;
+    info->flags = RBASIC(obj)->flags;
+    info->klass = RBASIC_CLASS(obj);
+
     info->path = path_cstr;
     info->line = NUM2INT(line);
     info->mid = mid;
@@ -108,10 +126,16 @@ freeobj_i(VALUE tpval, void *data) https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L126
     VALUE obj = rb_tracearg_object(tparg);
     struct allocation_info *info;
 
-    if (st_delete(arg->object_table, (st_data_t *)&obj, (st_data_t *)&info)) {
-	delete_unique_str(arg->str_table, info->path);
-	delete_unique_str(arg->str_table, info->class_path);
-	ruby_xfree(info);
+    if (st_lookup(arg->object_table, (st_data_t)obj, (st_data_t *)&info)) {
+	if (arg->keep_remains) {
+	    info->living = 0;
+	}
+	else {
+	    st_delete(arg->object_table, (st_data_t *)&obj, (st_data_t *)&info);
+	    delete_unique_str(arg->str_table, info->path);
+	    delete_unique_str(arg->str_table, info->class_path);
+	    ruby_xfree(info);
+	}
     }
 }
 
@@ -130,6 +154,7 @@ free_values_i(st_data_t key, st_data_t v https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L154
 }
 
 static struct traceobj_arg *tmp_trace_arg; /* TODO: Do not use global variables */
+static int tmp_keep_remains;               /* TODO: Do not use global variables */
 
 static struct traceobj_arg *
 get_traceobj_arg(void)
@@ -137,6 +162,7 @@ get_traceobj_arg(void) https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L162
     if (tmp_trace_arg == 0) {
 	tmp_trace_arg = ALLOC_N(struct traceobj_arg, 1);
 	tmp_trace_arg->running = 0;
+	tmp_trace_arg->keep_remains = tmp_keep_remains;
 	tmp_trace_arg->newobj_trace = 0;
 	tmp_trace_arg->freeobj_trace = 0;
 	tmp_trace_arg->object_table = st_init_numtable();
@@ -256,11 +282,53 @@ trace_object_allocations(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L282
     return rb_ensure(rb_yield, Qnil, trace_object_allocations_stop, self);
 }
 
+int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
+static int object_allocations_reporter_registerd = 0;
+
+static int
+object_allocations_reporter_i(st_data_t key, st_data_t val, st_data_t ptr)
+{
+    FILE *out = (FILE *)ptr;
+    VALUE obj = (VALUE)key;
+    struct allocation_info *info = (struct allocation_info *)val;
+
+    fprintf(out, "-- %p (%s F: %p, ", (void *)obj, info->living ? "live" : "dead", (void *)info->flags);
+    if (info->class_path) fprintf(out, "C: %s", info->class_path);
+    else                  fprintf(out, "C: %p", info->klass);
+    fprintf(out, "@%s:%lu", info->path ? info->path : "", info->line);
+    if (!NIL_P(info->mid)) fprintf(out, " (%s)", rb_id2name(SYM2ID(info->mid)));
+    fprintf(out, ")\n");
+
+    return ST_CONTINUE;
+}
+
+static void
+object_allocations_reporter(FILE *out, void *ptr)
+{
+    fprintf(out, "== object_allocations_reporter: START\n");
+    if (tmp_trace_arg) {
+	st_foreach(tmp_trace_arg->object_table, object_allocations_reporter_i, (st_data_t)out);
+    }
+    fprintf(out, "== object_allocations_reporter: END\n");
+}
+
+static VALUE
+trace_object_allocations_debug_start(VALUE self)
+{
+    tmp_keep_remains = 1;
+    if (object_allocations_reporter_registerd == 0) {
+	object_allocations_reporter_registerd = 1;
+	rb_bug_reporter_add(object_allocations_reporter, 0);
+    }
+
+    return trace_object_allocations_start(self);
+}
+
 static struct allocation_info *
 lookup_allocation_info(VALUE obj)
 {
     if (tmp_trace_arg) {
-	struct allocation_info *info;
+ 	struct allocation_info *info;
 	if (st_lookup(tmp_trace_arg->object_table, obj, (st_data_t *)&info)) {
 	    return info;
 	}
@@ -415,6 +483,8 @@ Init_object_tracing(VALUE rb_mObjSpace) https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L483
     rb_define_module_function(rb_mObjSpace, "trace_object_allocations_stop", trace_object_allocations_stop, 0);
     rb_define_module_function(rb_mObjSpace, "trace_object_allocations_clear", trace_object_allocations_clear, 0);
 
+    rb_define_module_function(rb_mObjSpace, "trace_object_allocations_debug_start", trace_object_allocations_debug_start, 0);
+
     rb_define_module_function(rb_mObjSpace, "allocation_sourcefile", allocation_sourcefile, 1);
     rb_define_module_function(rb_mObjSpace, "allocation_sourceline", allocation_sourceline, 1);
     rb_define_module_function(rb_mObjSpace, "allocation_class_path", allocation_class_path, 1);

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]