summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Boussier <jean.boussier@gmail.com>2023-03-06 19:44:45 +0100
committerJean Boussier <jean.boussier@gmail.com>2023-03-06 19:44:45 +0100
commit5f1cbba44319d66d71eba6753c3e3e950c6f8efa (patch)
treeee92600a9cddc1f852262cad31f20f89e36079ee
parentd54ea5a985425d163860b9723ed9e93a82aac2c5 (diff)
downloadffi-5f1cbba44319d66d71eba6753c3e3e950c6f8efa.tar.gz
Implement the last missing Write Barriers and dsize
Ref: https://github.com/ffi/ffi/pull/991 Write barrier protected objects are allowed to be promoted to the old generation, which means they only get marked on major GC. The downside is that the RB_BJ_WRITE macro MUST be used to set references, otherwise the referenced object may be garbaged collected. This commit also implement a `dsize` function so that these instance report a more relevant size in various memory profilers. It's not counting everything because some types are opaque right now, so a larger refactoring would be needed.
-rw-r--r--ext/ffi_c/ArrayType.c20
-rw-r--r--ext/ffi_c/DynamicLibrary.c14
-rw-r--r--ext/ffi_c/LastError.c11
3 files changed, 36 insertions, 9 deletions
diff --git a/ext/ffi_c/ArrayType.c b/ext/ffi_c/ArrayType.c
index f6e6fc4..1d766a4 100644
--- a/ext/ffi_c/ArrayType.c
+++ b/ext/ffi_c/ArrayType.c
@@ -35,16 +35,19 @@ static VALUE array_type_s_allocate(VALUE klass);
static VALUE array_type_initialize(VALUE self, VALUE rbComponentType, VALUE rbLength);
static void array_type_mark(void *);
static void array_type_free(void *);
+static size_t array_type_memsize(const void *);
const rb_data_type_t rbffi_array_type_data_type = { /* extern */
.wrap_struct_name = "FFI::ArrayType",
.function = {
.dmark = array_type_mark,
.dfree = array_type_free,
- .dsize = NULL,
+ .dsize = array_type_memsize,
},
.parent = &rbffi_type_data_type,
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
+ // macro to update VALUE references, as to trigger write barriers.
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
@@ -63,7 +66,7 @@ array_type_s_allocate(VALUE klass)
array->base.ffiType->type = FFI_TYPE_STRUCT;
array->base.ffiType->size = 0;
array->base.ffiType->alignment = 0;
- array->rbComponentType = Qnil;
+ RB_OBJ_WRITE(obj, &array->rbComponentType, Qnil);
return obj;
}
@@ -84,6 +87,15 @@ array_type_free(void *data)
xfree(array);
}
+static size_t
+array_type_memsize(const void *data)
+{
+ const ArrayType *array = (const ArrayType *)data;
+ size_t memsize = sizeof(ArrayType);
+ memsize += array->length * sizeof(*array->ffiTypes);
+ memsize += sizeof(*array->base.ffiType);
+ return memsize;
+}
/*
* call-seq: initialize(component_type, length)
@@ -101,7 +113,7 @@ array_type_initialize(VALUE self, VALUE rbComponentType, VALUE rbLength)
TypedData_Get_Struct(self, ArrayType, &rbffi_array_type_data_type, array);
array->length = NUM2UINT(rbLength);
- array->rbComponentType = rbComponentType;
+ RB_OBJ_WRITE(self, &array->rbComponentType, rbComponentType);
TypedData_Get_Struct(rbComponentType, Type, &rbffi_type_data_type, array->componentType);
array->ffiTypes = xcalloc(array->length + 1, sizeof(*array->ffiTypes));
diff --git a/ext/ffi_c/DynamicLibrary.c b/ext/ffi_c/DynamicLibrary.c
index c69074a..2e0bf4b 100644
--- a/ext/ffi_c/DynamicLibrary.c
+++ b/ext/ffi_c/DynamicLibrary.c
@@ -56,7 +56,7 @@ typedef struct LibrarySymbol_ {
static VALUE library_initialize(VALUE self, VALUE libname, VALUE libflags);
static void library_free(void *);
-
+static size_t library_memsize(const void *);
static VALUE symbol_allocate(VALUE klass);
static VALUE symbol_new(VALUE library, void* address, VALUE name);
@@ -68,9 +68,11 @@ static const rb_data_type_t rbffi_library_data_type = {
.function = {
.dmark = NULL,
.dfree = library_free,
- .dsize = NULL,
+ .dsize = library_memsize,
},
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
+ // macro to update VALUE references, as to trigger write barriers.
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
static const rb_data_type_t library_symbol_data_type = {
@@ -200,6 +202,12 @@ library_free(void *data)
xfree(library);
}
+static size_t
+library_memsize(const void *data)
+{
+ return sizeof(Library);
+}
+
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(__CYGWIN__)
static void*
dl_open(const char* name, int flags)
diff --git a/ext/ffi_c/LastError.c b/ext/ffi_c/LastError.c
index 4cef93b..d5ef132 100644
--- a/ext/ffi_c/LastError.c
+++ b/ext/ffi_c/LastError.c
@@ -91,14 +91,21 @@ thread_data_free(void *ptr)
}
#else
+static size_t
+thread_data_memsize(const void *data) {
+ return sizeof(ThreadData);
+}
+
static const rb_data_type_t thread_data_data_type = {
.wrap_struct_name = "FFI::ThreadData",
.function = {
.dmark = NULL,
.dfree = RUBY_TYPED_DEFAULT_FREE,
- .dsize = NULL,
+ .dsize = thread_data_memsize,
},
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
+ // macro to update VALUE references, as to trigger write barriers.
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
static ID id_thread_data;