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/