diff options
author | Jean Boussier <jean.boussier@gmail.com> | 2023-03-06 16:56:05 +0100 |
---|---|---|
committer | Jean Boussier <jean.boussier@gmail.com> | 2023-03-06 16:56:05 +0100 |
commit | ef6361c9c7035933df56626324160b5da8bec5ec (patch) | |
tree | 4433b811999c8b233db87f0f0072e8c442b78b10 | |
parent | 683036355de9af50188fdef796b976eddbcdac6a (diff) | |
download | ffi-ef6361c9c7035933df56626324160b5da8bec5ec.tar.gz |
Implement Write Barrier and dsize for FFI::StructByValue
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.
-rw-r--r-- | ext/ffi_c/StructByValue.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/ext/ffi_c/StructByValue.c b/ext/ffi_c/StructByValue.c index b4927e6..e2c589d 100644 --- a/ext/ffi_c/StructByValue.c +++ b/ext/ffi_c/StructByValue.c @@ -51,6 +51,7 @@ static VALUE sbv_allocate(VALUE); static VALUE sbv_initialize(VALUE, VALUE); static void sbv_mark(void *); static void sbv_free(void *); +static size_t sbv_memsize(const void *); VALUE rbffi_StructByValueClass = Qnil; @@ -59,10 +60,12 @@ static const rb_data_type_t sbv_type_data_type = { .function = { .dmark = sbv_mark, .dfree = sbv_free, - .dsize = NULL, + .dsize = sbv_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 }; static VALUE @@ -72,8 +75,8 @@ sbv_allocate(VALUE klass) VALUE obj = TypedData_Make_Struct(klass, StructByValue, &sbv_type_data_type, sbv); - sbv->rbStructClass = Qnil; - sbv->rbStructLayout = Qnil; + RB_OBJ_WRITE(obj, &sbv->rbStructClass, Qnil); + RB_OBJ_WRITE(obj, &sbv->rbStructLayout, Qnil); sbv->base.nativeType = NATIVE_STRUCT; sbv->base.ffiType = xcalloc(1, sizeof(*sbv->base.ffiType)); @@ -98,8 +101,8 @@ sbv_initialize(VALUE self, VALUE rbStructClass) TypedData_Get_Struct(rbLayout, StructLayout, &rbffi_struct_layout_data_type, layout); TypedData_Get_Struct(self, StructByValue, &sbv_type_data_type, sbv); - sbv->rbStructClass = rbStructClass; - sbv->rbStructLayout = rbLayout; + RB_OBJ_WRITE(self, &sbv->rbStructClass, rbStructClass); + RB_OBJ_WRITE(self, &sbv->rbStructLayout, rbLayout); /* We can just use everything from the ffi_type directly */ *sbv->base.ffiType = *layout->base.ffiType; @@ -123,6 +126,12 @@ sbv_free(void *data) xfree(sbv); } +static size_t +sbv_memsize(const void *data) +{ + const StructByValue *sbv = (const StructByValue *)data; + return sizeof(StructByValue) + sizeof(*sbv->base.ffiType); +} static VALUE sbv_layout(VALUE self) |