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

ruby-changes:62640

From: Aaron <ko1@a...>
Date: Wed, 19 Aug 2020 11:11:13 +0900 (JST)
Subject: [ruby-changes:62640] 7a58ee9b96 (master): Update references when tracing allocations

https://git.ruby-lang.org/ruby.git/commit/?id=7a58ee9b96

From 7a58ee9b962ad0072e5213d3512c809048e4eba1 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <tenderlove@r...>
Date: Tue, 18 Aug 2020 17:34:03 -0700
Subject: Update references when tracing allocations

The allocation tracing code keeps essentially a weak reference to
objects that have been allocated (storing the allocation information
along with the weak ref).  Compacting the heap would break references in
this weak map, so the wrong values could be returned.

This commit just updates the values in the weak ref in order to fix the
allocation tracing book keeping

diff --git a/ext/objspace/object_tracing.c b/ext/objspace/object_tracing.c
index a057ac2..b6ffca8 100644
--- a/ext/objspace/object_tracing.c
+++ b/ext/objspace/object_tracing.c
@@ -151,6 +151,80 @@ free_values_i(st_data_t key, st_data_t value, st_data_t data) https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L151
     return ST_CONTINUE;
 }
 
+static void
+allocation_info_tracer_mark(void *ptr)
+{
+    struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
+    rb_gc_mark(trace_arg->newobj_trace);
+    rb_gc_mark(trace_arg->freeobj_trace);
+}
+
+static void
+allocation_info_tracer_free(void *ptr)
+{
+    struct traceobj_arg *arg = (struct traceobj_arg *)ptr;
+    /* clear tables */
+    st_foreach(arg->object_table, free_values_i, 0);
+    st_free_table(arg->object_table);
+    st_foreach(arg->str_table, free_keys_i, 0);
+    st_free_table(arg->str_table);
+    xfree(arg);
+}
+
+static size_t
+allocation_info_tracer_memsize(const void *ptr)
+{
+    size_t size;
+    struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
+    size = sizeof(*trace_arg);
+    size += st_memsize(trace_arg->object_table);
+    size += st_memsize(trace_arg->str_table);
+    return size;
+}
+
+static int
+hash_foreach_should_replace_key(st_data_t key, st_data_t value, st_data_t argp, int error)
+{
+    VALUE allocated_object;
+
+    allocated_object = (VALUE)value;
+    if (allocated_object != rb_gc_location(allocated_object)) {
+        return ST_REPLACE;
+    }
+
+    return ST_CONTINUE;
+}
+
+static int
+hash_replace_key(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
+{
+    *key = rb_gc_location((VALUE)*key);
+
+    return ST_CONTINUE;
+}
+
+static void
+allocation_info_tracer_compact(void *ptr)
+{
+    struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
+
+    if (st_foreach_with_replace(trace_arg->object_table, hash_foreach_should_replace_key, hash_replace_key, 0)) {
+        rb_raise(rb_eRuntimeError, "hash modified during iteration");
+    }
+}
+
+static const rb_data_type_t allocation_info_tracer_type = {
+    "ObjectTracing/allocation_info_tracer",
+    {
+        allocation_info_tracer_mark,
+        allocation_info_tracer_free, /* Never called because global */
+        allocation_info_tracer_memsize,
+        allocation_info_tracer_compact,
+    },
+    0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE traceobj_arg;
 static struct traceobj_arg *tmp_trace_arg; /* TODO: Do not use global variables */
 static int tmp_keep_remains;               /* TODO: Do not use global variables */
 
@@ -158,7 +232,9 @@ static struct traceobj_arg * https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L232
 get_traceobj_arg(void)
 {
     if (tmp_trace_arg == 0) {
-	tmp_trace_arg = ALLOC_N(struct traceobj_arg, 1);
+        VALUE obj = TypedData_Make_Struct(rb_cObject, struct traceobj_arg, &allocation_info_tracer_type, tmp_trace_arg);
+        traceobj_arg = obj;
+        rb_gc_register_mark_object(traceobj_arg);
 	tmp_trace_arg->running = 0;
 	tmp_trace_arg->keep_remains = tmp_keep_remains;
 	tmp_trace_arg->newobj_trace = 0;
@@ -186,9 +262,7 @@ trace_object_allocations_start(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/objspace/object_tracing.c#L262
     else {
 	if (arg->newobj_trace == 0) {
 	    arg->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, arg);
-	    rb_gc_register_mark_object(arg->newobj_trace);
 	    arg->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, arg);
-	    rb_gc_register_mark_object(arg->freeobj_trace);
 	}
 	rb_tracepoint_enable(arg->newobj_trace);
 	rb_tracepoint_enable(arg->freeobj_trace);
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 28c0431..42fbc3e 100644
--- a/test/objspace/test_objspace.rb
+++ b/test/objspace/test_objspace.rb
@@ -194,7 +194,7 @@ class TestObjSpace < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/objspace/test_objspace.rb#L194
       assert_equal(self.class.name, ObjectSpace.allocation_class_path(o3))
       assert_equal(__method__,      ObjectSpace.allocation_method_id(o3))
     }
-  end if false # TODO: tenderlove is debugging it [Tue Aug 18 11:00:49 2020 JST]
+  end
 
   def test_trace_object_allocations_start_stop_clear
     ObjectSpace.trace_object_allocations_clear # clear object_table to get rid of erroneous detection for obj3
-- 
cgit v0.10.2


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

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