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

ruby-changes:63797

From: Kenta <ko1@a...>
Date: Mon, 30 Nov 2020 14:53:33 +0900 (JST)
Subject: [ruby-changes:63797] 73a337e214 (master): Keep references of memory-view-exported objects (#3816)

https://git.ruby-lang.org/ruby.git/commit/?id=73a337e214

From 73a337e21461469290005f169c05bc1791112d67 Mon Sep 17 00:00:00 2001
From: Kenta Murata <mrkn@u...>
Date: Mon, 30 Nov 2020 14:53:13 +0900
Subject: Keep references of memory-view-exported objects (#3816)

* memory_view.c: remove a reference in view->obj at rb_memory_view_release

* memory_view.c: keep references of memory-view-exported objects

* Update common.mk

* memory_view.c: Use st_update

diff --git a/common.mk b/common.mk
index 6120761..994b5c3 100644
--- a/common.mk
+++ b/common.mk
@@ -8006,6 +8006,7 @@ math.$(OBJEXT): {$(VPATH)}missing.h https://github.com/ruby/ruby/blob/trunk/common.mk#L8006
 math.$(OBJEXT): {$(VPATH)}st.h
 math.$(OBJEXT): {$(VPATH)}subst.h
 memory_view.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h
 memory_view.$(OBJEXT): $(top_srcdir)/internal/util.h
 memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h
 memory_view.$(OBJEXT): {$(VPATH)}assert.h
diff --git a/ext/-test-/memory_view/memory_view.c b/ext/-test-/memory_view/memory_view.c
index 0ae9f45..7f1f007 100644
--- a/ext/-test-/memory_view/memory_view.c
+++ b/ext/-test-/memory_view/memory_view.c
@@ -24,36 +24,11 @@ static VALUE sym_endianness; https://github.com/ruby/ruby/blob/trunk/ext/-test-/memory_view/memory_view.c#L24
 static VALUE sym_little_endian;
 static VALUE sym_big_endian;
 
-static VALUE exported_objects;
-
 static int
 exportable_string_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
 {
     VALUE str = rb_ivar_get(obj, id_str);
     rb_memory_view_init_as_byte_array(view, obj, RSTRING_PTR(str), RSTRING_LEN(str), true);
-
-    VALUE count = rb_hash_lookup2(exported_objects, obj, INT2FIX(0));
-    count = rb_funcall(count, '+', 1, INT2FIX(1));
-    rb_hash_aset(exported_objects, obj, count);
-
-    return 1;
-}
-
-static int
-exportable_string_release_memory_view(VALUE obj, rb_memory_view_t *view)
-{
-    VALUE count = rb_hash_lookup2(exported_objects, obj, INT2FIX(0));
-    if (INT2FIX(1) == count) {
-        rb_hash_delete(exported_objects, obj);
-    }
-    else if (INT2FIX(0) == count) {
-        rb_raise(rb_eRuntimeError, "Duplicated releasing of a memory view has been occurred for %"PRIsVALUE, obj);
-    }
-    else {
-        count = rb_funcall(count, '-', 1, INT2FIX(1));
-        rb_hash_aset(exported_objects, obj, count);
-    }
-
     return 1;
 }
 
@@ -65,7 +40,7 @@ exportable_string_memory_view_available_p(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/-test-/memory_view/memory_view.c#L40
 
 static const rb_memory_view_entry_t exportable_string_memory_view_entry = {
     exportable_string_get_memory_view,
-    exportable_string_release_memory_view,
+    NULL,
     exportable_string_memory_view_available_p
 };
 
@@ -207,6 +182,54 @@ memory_view_fill_contiguous_strides(VALUE mod, VALUE ndim_v, VALUE item_size_v, https://github.com/ruby/ruby/blob/trunk/ext/-test-/memory_view/memory_view.c#L182
 }
 
 static VALUE
+memory_view_get_ref_count(VALUE obj)
+{
+    extern VALUE rb_memory_view_exported_object_registry;
+    extern const rb_data_type_t rb_memory_view_exported_object_registry_data_type;
+
+    if (rb_memory_view_exported_object_registry == Qundef) {
+        return Qnil;
+    }
+
+    st_table *table;
+    TypedData_Get_Struct(rb_memory_view_exported_object_registry, st_table,
+                         &rb_memory_view_exported_object_registry_data_type,
+                         table);
+
+    st_data_t count;
+    if (st_lookup(table, (st_data_t)obj, &count)) {
+        return ULL2NUM(count);
+    }
+
+    return Qnil;
+}
+
+static VALUE
+memory_view_ref_count_while_exporting_i(VALUE obj, long n)
+{
+    if (n == 0) {
+        return memory_view_get_ref_count(obj);
+    }
+
+    rb_memory_view_t view;
+    if (!rb_memory_view_get(obj, &view, 0)) {
+        return Qnil;
+    }
+
+    VALUE ref_count = memory_view_ref_count_while_exporting_i(obj, n-1);
+    rb_memory_view_release(&view);
+
+    return ref_count;
+}
+
+static VALUE
+memory_view_ref_count_while_exporting(VALUE mod, VALUE obj, VALUE n)
+{
+    Check_Type(n, T_FIXNUM);
+    return memory_view_ref_count_while_exporting_i(obj, FIX2LONG(n));
+}
+
+static VALUE
 expstr_initialize(VALUE obj, VALUE s)
 {
     rb_ivar_set(obj, id_str, s);
@@ -247,28 +270,6 @@ mdview_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags) https://github.com/ruby/ruby/blob/trunk/ext/-test-/memory_view/memory_view.c#L270
     view->shape = shape;
     view->strides = strides;
 
-    VALUE count = rb_hash_lookup2(exported_objects, obj, INT2FIX(0));
-    count = rb_funcall(count, '+', 1, INT2FIX(1));
-    rb_hash_aset(exported_objects, obj, count);
-
-    return 1;
-}
-
-static int
-mdview_release_memory_view(VALUE obj, rb_memory_view_t *view)
-{
-    VALUE count = rb_hash_lookup2(exported_objects, obj, INT2FIX(0));
-    if (INT2FIX(1) == count) {
-        rb_hash_delete(exported_objects, obj);
-    }
-    else if (INT2FIX(0) == count) {
-        rb_raise(rb_eRuntimeError, "Duplicated releasing of a memory view has been occurred for %"PRIsVALUE, obj);
-    }
-    else {
-        count = rb_funcall(count, '-', 1, INT2FIX(1));
-        rb_hash_aset(exported_objects, obj, count);
-    }
-
     return 1;
 }
 
@@ -280,7 +281,7 @@ mdview_memory_view_available_p(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ext/-test-/memory_view/memory_view.c#L281
 
 static const rb_memory_view_entry_t mdview_memory_view_entry = {
     mdview_get_memory_view,
-    mdview_release_memory_view,
+    NULL,
     mdview_memory_view_available_p
 };
 
@@ -340,6 +341,7 @@ Init_memory_view(void) https://github.com/ruby/ruby/blob/trunk/ext/-test-/memory_view/memory_view.c#L341
     rb_define_module_function(mMemoryViewTestUtils, "parse_item_format", memory_view_parse_item_format, 1);
     rb_define_module_function(mMemoryViewTestUtils, "get_memory_view_info", memory_view_get_memory_view_info, 1);
     rb_define_module_function(mMemoryViewTestUtils, "fill_contiguous_strides", memory_view_fill_contiguous_strides, 4);
+    rb_define_module_function(mMemoryViewTestUtils, "ref_count_while_exporting", memory_view_ref_count_while_exporting, 2);
 
     VALUE cExportableString = rb_define_class_under(mMemoryViewTestUtils, "ExportableString", rb_cObject);
     rb_define_method(cExportableString, "initialize", expstr_initialize, 1);
@@ -393,7 +395,4 @@ Init_memory_view(void) https://github.com/ruby/ruby/blob/trunk/ext/-test-/memory_view/memory_view.c#L395
     DEF_ALIGNMENT_CONST(double, DOUBLE);
 
 #undef DEF_ALIGNMENT_CONST
-
-    exported_objects = rb_hash_new();
-    rb_gc_register_mark_object(exported_objects);
 }
diff --git a/include/ruby/memory_view.h b/include/ruby/memory_view.h
index e3897f8..e2c5cd9 100644
--- a/include/ruby/memory_view.h
+++ b/include/ruby/memory_view.h
@@ -136,6 +136,10 @@ int rb_memory_view_available_p(VALUE obj); https://github.com/ruby/ruby/blob/trunk/include/ruby/memory_view.h#L136
 int rb_memory_view_get(VALUE obj, rb_memory_view_t* memory_view, int flags);
 int rb_memory_view_release(rb_memory_view_t* memory_view);
 
+/* for testing */
+RUBY_EXTERN VALUE rb_memory_view_exported_object_registry;
+RUBY_EXTERN const rb_data_type_t rb_memory_view_exported_object_registry_data_type;
+
 RBIMPL_SYMBOL_EXPORT_END()
 
 RBIMPL_ATTR_PURE()
diff --git a/memory_view.c b/memory_view.c
index b2d81cb..aade3a4 100644
--- a/memory_view.c
+++ b/memory_view.c
@@ -7,6 +7,7 @@ https://github.com/ruby/ruby/blob/trunk/memory_view.c#L7
 **********************************************************************/
 
 #include "internal.h"
+#include "internal/hash.h"
 #include "internal/variable.h"
 #include "internal/util.h"
 #include "ruby/memory_view.h"
@@ -15,10 +16,119 @@ https://github.com/ruby/ruby/blob/trunk/memory_view.c#L16
     (result) = RUBY_ALIGNOF(T); \
 } while(0)
 
+// Exported Object Registry
+
+VALUE rb_memory_view_exported_object_registry = Qundef;
+
+static int
+exported_object_registry_mark_key_i(st_data_t key, st_data_t value, st_data_t data)
+{
+    rb_gc_mark(key);
+    return ST_CONTINUE;
+}
+
+static void
+exported_object_registry_mark(void *ptr)
+{
+    st_table *table = ptr;
+    st_foreach(table, exported_object_registry_mark_key_i, 0);
+}
+
+static void
+exported_object_registry_free(void *ptr)
+{
+    st_table *table = ptr;
+    st_clear(table);
+    st_free_table(table);
+}
+
+const rb_data_type_t rb_memory_view_exported_object_registry_data_type = {
+    "memory_view/exported_object_registry",
+    {
+	exported_object_registry_mark,
+	exported_object_registry_free,
+	0,
+    },
+    0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static void
+init_exported_object_registry(void)
+{
+    if (rb_memory_view_exported_object_registry != Qundef) {
+        return;
+    }
+
+    st_table *table = rb_init_identtable();
+    VALUE obj = TypedData_Wrap_Struct(
+        0, &rb_memory_view_exported_object_registry_data_type, table);
+    rb_gc_register_mark_object(obj);
+    rb_memory_view_exported_object_registry = obj;
+}
+
+static inline st_table *
+get_exported_object_table(void)
+{
+    st_table *table;
+    TypedData_Get_Struct(rb_memory_view_exported_object_registry, st_table,
+                         &rb_memory_view_exported_object_registry_data_type,
+                         table);
+    return table;
+}
+
+static int
+update_exported_object_ref_count(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
+{
+    if (existing) {
+        *val += 1;
+    }
+    else {
+        *val = 1;
+    }
+    return ST_CONTINUE;
+}
+
+static void
+register_exported_object(VALUE obj)
+{
+    if (rb_memory_view_exported_object_registry == Qundef) {
+        init_exported_object_registry();
+    }
+
+    st_table *table = get_exported_object_table();
+
+    st_update(table, (st_data_t)obj, update_exported_object_ref_count, 0);
+}
+
+static void
+unregister_exported_object(VALUE obj)
+{
+    if (rb_memory_view_exported_object_registry == Qundef) {
+        return;
+    }
+
+    st_table *table = ge (... truncated)

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

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