summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Kanis <lars@greiz-reinsdorf.de>2023-03-06 18:15:20 +0100
committerGitHub <noreply@github.com>2023-03-06 18:15:20 +0100
commit9aa3ff30dd20b6f9bcc6ec2093d1ae35046c5744 (patch)
treecdcf39a2144a3154b09126939616b7d7b5e420de
parentf523242cea0e00e161254f699dc0ae9b514ee055 (diff)
parent38e62e7d0ee149b63555c2b9a069e24968128ac7 (diff)
downloadffi-9aa3ff30dd20b6f9bcc6ec2093d1ae35046c5744.tar.gz
Merge pull request #1008 from casperisfine/variadic-write-barrier
Implement Write Barrier and dsize for FFI::VariadicInvoker
-rw-r--r--ext/ffi_c/Variadic.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/ext/ffi_c/Variadic.c b/ext/ffi_c/Variadic.c
index e379f4b..014fac2 100644
--- a/ext/ffi_c/Variadic.c
+++ b/ext/ffi_c/Variadic.c
@@ -66,6 +66,7 @@ static VALUE variadic_allocate(VALUE klass);
static VALUE variadic_initialize(VALUE self, VALUE rbFunction, VALUE rbParameterTypes,
VALUE rbReturnType, VALUE options);
static void variadic_mark(void *);
+static size_t variadic_memsize(const void *);
static VALUE classVariadicInvoker = Qnil;
@@ -74,9 +75,11 @@ static const rb_data_type_t variadic_data_type = {
.function = {
.dmark = variadic_mark,
.dfree = RUBY_TYPED_DEFAULT_FREE,
- .dsize = NULL,
+ .dsize = variadic_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
};
@@ -86,9 +89,9 @@ variadic_allocate(VALUE klass)
VariadicInvoker *invoker;
VALUE obj = TypedData_Make_Struct(klass, VariadicInvoker, &variadic_data_type, invoker);
- invoker->rbAddress = Qnil;
- invoker->rbEnums = Qnil;
- invoker->rbReturnType = Qnil;
+ RB_OBJ_WRITE(obj, &invoker->rbAddress, Qnil);
+ RB_OBJ_WRITE(obj, &invoker->rbEnums, Qnil);
+ RB_OBJ_WRITE(obj, &invoker->rbReturnType, Qnil);
invoker->blocking = false;
return obj;
@@ -103,6 +106,12 @@ variadic_mark(void *data)
rb_gc_mark(invoker->rbReturnType);
}
+static size_t
+variadic_memsize(const void *data)
+{
+ return sizeof(VariadicInvoker);
+}
+
static VALUE
variadic_initialize(VALUE self, VALUE rbFunction, VALUE rbParameterTypes, VALUE rbReturnType, VALUE options)
{
@@ -119,8 +128,8 @@ variadic_initialize(VALUE self, VALUE rbFunction, VALUE rbParameterTypes, VALUE
convention = rb_hash_aref(options, ID2SYM(rb_intern("convention")));
TypedData_Get_Struct(self, VariadicInvoker, &variadic_data_type, invoker);
- invoker->rbEnums = rb_hash_aref(options, ID2SYM(rb_intern("enums")));
- invoker->rbAddress = rbFunction;
+ RB_OBJ_WRITE(self, &invoker->rbEnums, rb_hash_aref(options, ID2SYM(rb_intern("enums"))));
+ RB_OBJ_WRITE(self, &invoker->rbAddress, rbFunction);
invoker->function = rbffi_AbstractMemory_Cast(rbFunction, rbffi_PointerClass)->address;
invoker->blocking = RTEST(rb_hash_aref(options, ID2SYM(rb_intern("blocking"))));
@@ -132,7 +141,7 @@ variadic_initialize(VALUE self, VALUE rbFunction, VALUE rbParameterTypes, VALUE
invoker->abi = FFI_DEFAULT_ABI;
#endif
- invoker->rbReturnType = rbffi_Type_Lookup(rbReturnType);
+ RB_OBJ_WRITE(self, &invoker->rbReturnType, rbffi_Type_Lookup(rbReturnType));
if (!RTEST(invoker->rbReturnType)) {
VALUE typeName = rb_funcall2(rbReturnType, rb_intern("inspect"), 0, NULL);
rb_raise(rb_eTypeError, "Invalid return type (%s)", RSTRING_PTR(typeName));