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

ruby-changes:31016

From: ko1 <ko1@a...>
Date: Mon, 30 Sep 2013 17:17:35 +0900 (JST)
Subject: [ruby-changes:31016] ko1:r43095 (trunk): * ext/objspace/object_tracing.c: add new 3 methods to control tracing.

ko1	2013-09-30 17:17:30 +0900 (Mon, 30 Sep 2013)

  New Revision: 43095

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

  Log:
    * ext/objspace/object_tracing.c: add new 3 methods to control tracing.
    * ObjectSpace::trace_object_allocations_start
    * ObjectSpace::trace_object_allocations_stop
    * ObjectSpace::trace_object_allocations_clear
      And some refactoring.
    * test/objspace/test_objspace.rb: add a test for new methods.
    * NEWS: add a description for new methods.

  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/ext/objspace/object_tracing.c
    trunk/test/objspace/test_objspace.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 43094)
+++ ChangeLog	(revision 43095)
@@ -1,3 +1,15 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Mon Sep 30 16:46:58 2013  Koichi Sasada  <ko1@a...>
+
+	* ext/objspace/object_tracing.c: add new 3 methods to control tracing.
+	  * ObjectSpace::trace_object_allocations_start
+	  * ObjectSpace::trace_object_allocations_stop
+	  * ObjectSpace::trace_object_allocations_clear
+	  And some refactoring.
+
+	* test/objspace/test_objspace.rb: add a test for new methods.
+
+	* NEWS: add a description for new methods.
+
 Mon Sep 30 11:18:04 2013  Koichi Sasada  <ko1@a...>
 
 	* gc.c (rb_gc_disable): do rest_sweep() before disable GC.
Index: ext/objspace/object_tracing.c
===================================================================
--- ext/objspace/object_tracing.c	(revision 43094)
+++ ext/objspace/object_tracing.c	(revision 43095)
@@ -19,15 +19,15 @@ https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L19
 size_t rb_gc_count(void); /* from gc.c */
 
 struct traceobj_arg {
+    int running;
     VALUE newobj_trace;
     VALUE freeobj_trace;
-    st_table *object_table;
-    st_table *str_table;
+    st_table *object_table; /* obj (VALUE) -> allocation_info */
+    st_table *str_table;    /* cstr -> refcount */
     struct traceobj_arg *prev_traceobj_arg;
 };
 
-struct traceobj_arg *traceobj_arg; /* TODO: do not use GLOBAL VARIABLE!!! */
-
+/* all of information don't need marking. */
 struct allocation_info {
     const char *path;
     unsigned long line;
@@ -129,17 +129,94 @@ free_values_i(st_data_t key, st_data_t v https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L129
     return ST_CONTINUE;
 }
 
+static struct traceobj_arg *tmp_trace_arg; /* TODO: Do not use global variables */
+
+static struct traceobj_arg *
+get_traceobj_arg(void)
+{
+    if (tmp_trace_arg == 0) {
+	tmp_trace_arg = ALLOC_N(struct traceobj_arg, 1);
+	tmp_trace_arg->running = 0;
+	tmp_trace_arg->newobj_trace = 0;
+	tmp_trace_arg->freeobj_trace = 0;
+	tmp_trace_arg->object_table = st_init_numtable();
+	tmp_trace_arg->str_table = st_init_strtable();
+    }
+    return tmp_trace_arg;
+}
+
+/*
+ * call-seq: trace_object_allocations_start
+ *
+ * Starts tracing object allocations.
+ *
+ */
 static VALUE
-stop_trace_object_allocations(void *data)
+trace_object_allocations_start(VALUE self)
 {
-    struct traceobj_arg *arg = (struct traceobj_arg *)data;
-    rb_tracepoint_disable(arg->newobj_trace);
-    rb_tracepoint_disable(arg->freeobj_trace);
+    struct traceobj_arg *arg = get_traceobj_arg();
+
+    if (arg->running++ > 0) {
+	/* do nothing */
+    }
+    else {
+	if (arg->newobj_trace == 0) {
+	    arg->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, arg);
+	    arg->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, arg);
+	}
+	rb_tracepoint_enable(arg->newobj_trace);
+	rb_tracepoint_enable(arg->freeobj_trace);
+    }
+
+    return Qnil;
+}
+
+/*
+ * call-seq: trace_object_allocations_stop
+ *
+ * Stop tracing object allocations.
+ *
+ * Note that if trace_object_allocations_start is called n-times, then
+ * stop tracing after calling trace_object_allocations_stop n-times.
+ *
+ */
+static VALUE
+trace_object_allocations_stop(VALUE self)
+{
+    struct traceobj_arg *arg = get_traceobj_arg();
+
+    if (arg->running > 0) {
+	arg->running--;
+    }
+
+    if (arg->running == 0) {
+	rb_tracepoint_disable(arg->newobj_trace);
+	rb_tracepoint_disable(arg->freeobj_trace);
+	arg->newobj_trace = 0;
+	arg->freeobj_trace = 0;
+    }
+
+    return Qnil;
+}
+
+/*
+ * call-seq: trace_object_allocations_clear
+ *
+ * Clear recorded tracing information.
+ *
+ */
+static VALUE
+trace_object_allocations_clear(VALUE self)
+{
+    struct traceobj_arg *arg = get_traceobj_arg();
+
+    /* clear tables */
     st_foreach(arg->object_table, free_values_i, 0);
+    st_clear(arg->object_table);
     st_foreach(arg->str_table, free_keys_i, 0);
-    st_free_table(arg->object_table);
-    st_free_table(arg->str_table);
-    traceobj_arg = arg->prev_traceobj_arg;
+    st_clear(arg->str_table);
+
+    /* do not touch TracePoints */
 
     return Qnil;
 }
@@ -171,30 +248,18 @@ stop_trace_object_allocations(void *data https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L248
  * "<code>ObjectSpace::trace_object_allocations</code>" notation.
  */
 static VALUE
-trace_object_allocations(VALUE objspace)
+trace_object_allocations(VALUE self)
 {
-    struct traceobj_arg arg;
-
-    arg.newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, &arg);
-    arg.freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, &arg);
-    arg.object_table = st_init_numtable();
-    arg.str_table = st_init_strtable();
-
-    arg.prev_traceobj_arg = traceobj_arg;
-    traceobj_arg = &arg;
-
-    rb_tracepoint_enable(arg.newobj_trace);
-    rb_tracepoint_enable(arg.freeobj_trace);
-
-    return rb_ensure(rb_yield, Qnil, stop_trace_object_allocations, (VALUE)&arg);
+    trace_object_allocations_start(self);
+    return rb_ensure(rb_yield, Qnil, trace_object_allocations_stop, self);
 }
 
 static struct allocation_info *
 lookup_allocation_info(VALUE obj)
 {
-    if (traceobj_arg) {
+    if (tmp_trace_arg) {
 	struct allocation_info *info;
-	if (st_lookup(traceobj_arg->object_table, obj, (st_data_t *)&info)) {
+	if (st_lookup(tmp_trace_arg->object_table, obj, (st_data_t *)&info)) {
 	    return info;
 	}
     }
@@ -209,11 +274,12 @@ lookup_allocation_info(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L274
  * See ::trace_object_allocations for more information and examples.
  */
 static VALUE
-allocation_sourcefile(VALUE objspace, VALUE obj)
+allocation_sourcefile(VALUE self, VALUE obj)
 {
     struct allocation_info *info = lookup_allocation_info(obj);
-    if (info) {
-	return info->path ? rb_str_new2(info->path) : Qnil;
+
+    if (info && info->path) {
+	return rb_str_new2(info->path);
     }
     else {
 	return Qnil;
@@ -228,9 +294,10 @@ allocation_sourcefile(VALUE objspace, VA https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L294
  * See ::trace_object_allocations for more information and examples.
  */
 static VALUE
-allocation_sourceline(VALUE objspace, VALUE obj)
+allocation_sourceline(VALUE self, VALUE obj)
 {
     struct allocation_info *info = lookup_allocation_info(obj);
+
     if (info) {
 	return INT2FIX(info->line);
     }
@@ -258,11 +325,12 @@ allocation_sourceline(VALUE objspace, VA https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L325
  * See ::trace_object_allocations for more information and examples.
  */
 static VALUE
-allocation_class_path(VALUE objspace, VALUE obj)
+allocation_class_path(VALUE self, VALUE obj)
 {
     struct allocation_info *info = lookup_allocation_info(obj);
-    if (info) {
-	return info->class_path ? rb_str_new2(info->class_path) : Qnil;
+
+    if (info && info->class_path) {
+	return rb_str_new2(info->class_path);
     }
     else {
 	return Qnil;
@@ -290,7 +358,7 @@ allocation_class_path(VALUE objspace, VA https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L358
  * See ::trace_object_allocations for more information and examples.
  */
 static VALUE
-allocation_method_id(VALUE objspace, VALUE obj)
+allocation_method_id(VALUE self, VALUE obj)
 {
     struct allocation_info *info = lookup_allocation_info(obj);
     if (info) {
@@ -322,7 +390,7 @@ allocation_method_id(VALUE objspace, VAL https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L390
  * See ::trace_object_allocations for more information and examples.
  */
 static VALUE
-allocation_generation(VALUE objspace, VALUE obj)
+allocation_generation(VALUE self, VALUE obj)
 {
     struct allocation_info *info = lookup_allocation_info(obj);
     if (info) {
@@ -341,6 +409,10 @@ Init_object_tracing(VALUE rb_mObjSpace) https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L409
 #endif
 
     rb_define_module_function(rb_mObjSpace, "trace_object_allocations", trace_object_allocations, 0);
+    rb_define_module_function(rb_mObjSpace, "trace_object_allocations_start", trace_object_allocations_start, 0);
+    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, "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);
Index: NEWS
===================================================================
--- NEWS	(revision 43094)
+++ NEWS	(revision 43095)
@@ -239,6 +239,18 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L239
 
 === Stdlib compatibility issues (excluding feature bug fixes)
 
+* objspace
+  * new method:
+    * ObjectSpace.trace_object_allocations
+    * ObjectSpace.trace_object_allocations_start
+    * ObjectSpace.trace_object_allocations_stop
+    * ObjectSpace.trace_object_allocations_clear
+    * ObjectSpace.allocation_sourcefile
+    * ObjectSpace.allocation_sourceline
+    * ObjectSpace.allocation_class_path
+    * ObjectSpace.allocation_method_id
+    * ObjectSpace.allocation_generation
+
 * Set
   * incompatible changes:
     * Set#to_set now returns self instead of generating a copy.
Index: test/objspace/test_objspace.rb
===================================================================
--- test/objspace/test_objspace.rb	(revision 43094)
+++ test/objspace/test_objspace.rb	(revision 43095)
@@ -109,7 +109,7 @@ class TestObjSpace < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/objspace/test_objspace.rb#L109
     eom
   end
 
-  def test_traceobject
+  def test_trace_object_allocations
     o0 = Object.new
     ObjectSpace.trace_object_allocations{
       o1 = Object.new; line1 = __LINE__; c1 = GC.count
@@ -139,4 +139,37 @@ class TestObjSpace < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/objspace/test_objspace.rb#L139
       assert_equal(__method__,      ObjectSpace.allocation_method_id(o3))
     }
   end
+
+  def test_trace_object_allocations_start_stop_clear
+    begin
+      ObjectSpace.trace_object_allocations_start
+      begin
+        ObjectSpace.trace_object_allocations_start
+        begin
+          ObjectSpace.trace_object_allocations_start
+          obj0 = Object.new
+        ensure
+          ObjectSpace.trace_object_allocations_stop
+          obj1 = Object.new
+        end
+      ensure
+        ObjectSpace.trace_object_allocations_stop
+        obj2 = Object.new
+      end
+    ensure
+      ObjectSpace.trace_object_allocations_stop
+      obj3 = Object.new
+    end
+
+    assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(obj0))
+    assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(obj1))
+    assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(obj2))
+    assert_equal(nil     , ObjectSpace.allocation_sourcefile(obj3)) # after tracing
+
+    ObjectSpace.trace_object_allocations_clear
+    assert_equal(nil, ObjectSpace.allocation_sourcefile(obj0))
+    assert_equal(nil, ObjectSpace.allocation_sourcefile(obj1))
+    assert_equal(nil, ObjectSpace.allocation_sourcefile(obj2))
+    assert_equal(nil, ObjectSpace.allocation_sourcefile(obj3))
+  end
 end

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

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