summaryrefslogtreecommitdiff
path: root/memory_view.c
diff options
context:
space:
mode:
Diffstat (limited to 'memory_view.c')
-rw-r--r--memory_view.c163
1 files changed, 77 insertions, 86 deletions
diff --git a/memory_view.c b/memory_view.c
index 5d6ef14b3a..2de756d681 100644
--- a/memory_view.c
+++ b/memory_view.c
@@ -9,8 +9,9 @@
#include "internal.h"
#include "internal/hash.h"
#include "internal/variable.h"
-#include "internal/util.h"
#include "ruby/memory_view.h"
+#include "ruby/util.h"
+#include "vm_sync.h"
#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
# define INTPTR2NUM LL2NUM
@@ -30,6 +31,7 @@
// Exported Object Registry
+static st_table *exported_object_table = NULL;
VALUE rb_memory_view_exported_object_registry = Qundef;
static int
@@ -42,55 +44,35 @@ exported_object_registry_mark_key_i(st_data_t key, st_data_t value, st_data_t da
static void
exported_object_registry_mark(void *ptr)
{
- st_table *table = ptr;
- st_foreach(table, exported_object_registry_mark_key_i, 0);
+ // Don't use RB_VM_LOCK_ENTER here. It is unnecessary during GC.
+ st_foreach(exported_object_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);
+ RB_VM_LOCKING() {
+ st_clear(exported_object_table);
+ st_free_table(exported_object_table);
+ exported_object_table = NULL;
+ }
}
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,
+ exported_object_registry_mark,
+ exported_object_registry_free,
+ 0,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
-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)
+exported_object_add_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
{
+ ASSERT_vm_locking();
+
if (existing) {
*val += 1;
}
@@ -100,38 +82,35 @@ update_exported_object_ref_count(st_data_t *key, st_data_t *val, st_data_t arg,
return ST_CONTINUE;
}
+static int
+exported_object_dec_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
+{
+ ASSERT_vm_locking();
+
+ if (existing) {
+ *val -= 1;
+ if (*val == 0) {
+ return ST_DELETE;
+ }
+ }
+ return ST_CONTINUE;
+}
+
static void
register_exported_object(VALUE obj)
{
- if (rb_memory_view_exported_object_registry == Qundef) {
- init_exported_object_registry();
+ RB_VM_LOCKING() {
+ st_update(exported_object_table, (st_data_t)obj, exported_object_add_ref, 0);
+ RB_OBJ_WRITTEN(rb_memory_view_exported_object_registry, Qundef, obj);
}
-
- 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 = get_exported_object_table();
-
- st_data_t count;
- if (!st_lookup(table, (st_data_t)obj, &count)) {
- return;
- }
-
- if (--count == 0) {
- st_data_t key = (st_data_t)obj;
- st_delete(table, &key, &count);
- }
- else {
- st_insert(table, (st_data_t)obj, count);
+ RB_VM_LOCKING() {
+ if (exported_object_table)
+ st_update(exported_object_table, (st_data_t)obj, exported_object_dec_ref, 0);
}
}
@@ -142,16 +121,17 @@ static ID id_memory_view;
static const rb_data_type_t memory_view_entry_data_type = {
"memory_view/entry",
{
- 0,
- 0,
- 0,
+ 0,
+ 0,
+ 0,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
/* Register memory view functions for the given class */
bool
-rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry) {
+rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry)
+{
Check_Type(klass, T_CLASS);
VALUE entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil);
if (! NIL_P(entry_obj)) {
@@ -217,12 +197,12 @@ rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_si
}
/* Initialize view to expose a simple byte array */
-int
+bool
rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly)
{
view->obj = obj;
view->data = data;
- view->len = len;
+ view->byte_size = len;
view->readonly = readonly;
view->format = NULL;
view->item_size = 1;
@@ -232,9 +212,9 @@ rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data,
view->shape = NULL;
view->strides = NULL;
view->sub_offsets = NULL;
- *((void **)&view->private) = NULL;
+ view->private_data = NULL;
- return 1;
+ return true;
}
#ifdef HAVE_TRUE_LONG_LONG
@@ -395,7 +375,8 @@ get_format_size(const char *format, bool *native_p, ssize_t *alignment, endianne
}
static inline ssize_t
-calculate_padding(ssize_t total, ssize_t alignment_size) {
+calculate_padding(ssize_t total, ssize_t alignment_size)
+{
if (alignment_size > 1) {
ssize_t res = total % alignment_size;
if (res > 0) {
@@ -419,7 +400,7 @@ rb_memory_view_parse_item_format(const char *format,
ssize_t max_alignment_size = 0;
const char *p = format;
- if (*p == '|') { // alginment specifier
+ if (*p == '|') { // alignment specifier
alignment = true;
++format;
++p;
@@ -694,7 +675,7 @@ extract_item_member(const uint8_t *ptr, const rb_memory_view_item_component_t *m
return LL2NUM(val.ll);
}
else {
-#if SIZEOF_INT64_t == SIZEOF_LONG
+#if SIZEOF_INT64_T == SIZEOF_LONG
return LONG2NUM(val.i64);
#else
return LL2NUM(val.i64);
@@ -706,7 +687,7 @@ extract_item_member(const uint8_t *ptr, const rb_memory_view_item_component_t *m
return ULL2NUM(val.ull);
}
else {
-#if SIZEOF_UINT64_t == SIZEOF_LONG
+#if SIZEOF_UINT64_T == SIZEOF_LONG
return ULONG2NUM(val.u64);
#else
return ULL2NUM(val.u64);
@@ -771,7 +752,9 @@ rb_memory_view_prepare_item_desc(rb_memory_view_t *view)
{
if (view->item_desc.components == NULL) {
const char *err;
- ssize_t n = rb_memory_view_parse_item_format(view->format, &view->item_desc.components, &view->item_desc.length, &err);
+ rb_memory_view_item_component_t **p_components =
+ (rb_memory_view_item_component_t **)&view->item_desc.components;
+ ssize_t n = rb_memory_view_parse_item_format(view->format, p_components, &view->item_desc.length, &err);
if (n < 0) {
rb_raise(rb_eRuntimeError,
"Unable to parse item format at %"PRIdSIZE" in \"%s\"",
@@ -802,7 +785,7 @@ lookup_memory_view_entry(VALUE klass)
{
VALUE entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil);
while (NIL_P(entry_obj)) {
- klass = rb_class_get_superclass(klass);
+ klass = rb_class_superclass(klass);
if (klass == rb_cBasicObject || klass == rb_cObject)
return NULL;
@@ -817,7 +800,7 @@ lookup_memory_view_entry(VALUE klass)
}
/* Examine whether the given object supports memory view. */
-int
+bool
rb_memory_view_available_p(VALUE obj)
{
VALUE klass = CLASS_OF(obj);
@@ -825,56 +808,64 @@ rb_memory_view_available_p(VALUE obj)
if (entry)
return (* entry->available_p_func)(obj);
else
- return 0;
+ return false;
}
/* Obtain a memory view from obj, and substitute the information to view. */
-int
+bool
rb_memory_view_get(VALUE obj, rb_memory_view_t* view, int flags)
{
VALUE klass = CLASS_OF(obj);
const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass);
if (entry) {
if (!(*entry->available_p_func)(obj)) {
- return 0;
+ return false;
}
- int rv = (*entry->get_func)(obj, view, flags);
+ bool rv = (*entry->get_func)(obj, view, flags);
if (rv) {
+ view->_memory_view_entry = entry;
register_exported_object(view->obj);
}
return rv;
}
else
- return 0;
+ return false;
}
/* Release the memory view obtained from obj. */
-int
+bool
rb_memory_view_release(rb_memory_view_t* view)
{
- VALUE klass = CLASS_OF(view->obj);
- const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass);
+ const rb_memory_view_entry_t *entry = view->_memory_view_entry;
if (entry) {
- int rv = 1;
+ bool rv = true;
if (entry->release_func) {
rv = (*entry->release_func)(view->obj, view);
}
if (rv) {
unregister_exported_object(view->obj);
view->obj = Qnil;
- if (view->item_desc.components) {
- xfree(view->item_desc.components);
- }
+ SIZED_FREE_N((rb_memory_view_item_component_t *)view->item_desc.components, view->item_desc.length);
}
return rv;
}
else
- return 0;
+ return false;
}
void
Init_MemoryView(void)
{
+ exported_object_table = rb_init_identtable();
+
+ // exported_object_table is referred through rb_memory_view_exported_object_registry
+ // in -test-/memory_view extension.
+ VALUE obj = TypedData_Wrap_Struct(
+ 0, &rb_memory_view_exported_object_registry_data_type,
+ exported_object_table);
+ rb_vm_register_global_object(obj);
+ rb_memory_view_exported_object_registry = obj;
+
id_memory_view = rb_intern_const("__memory_view__");
}