summaryrefslogtreecommitdiff
path: root/ext/ffi_c/Pointer.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ffi_c/Pointer.c')
-rw-r--r--ext/ffi_c/Pointer.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/ext/ffi_c/Pointer.c b/ext/ffi_c/Pointer.c
index 3d26555..cfa841e 100644
--- a/ext/ffi_c/Pointer.c
+++ b/ext/ffi_c/Pointer.c
@@ -43,16 +43,19 @@ VALUE rbffi_NullPointerSingleton = Qnil;
static void ptr_release(void *data);
static void ptr_mark(void *data);
+static size_t ptr_memsize(const void *data);
const rb_data_type_t rbffi_pointer_data_type = { /* extern */
.wrap_struct_name = "FFI::Pointer",
.function = {
.dmark = ptr_mark,
.dfree = ptr_release,
- .dsize = NULL,
+ .dsize = ptr_memsize,
},
.parent = &rbffi_abstract_memory_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
};
VALUE
@@ -70,7 +73,7 @@ rbffi_Pointer_NewInstance(void* addr)
p->memory.size = LONG_MAX;
p->memory.flags = (addr == NULL) ? 0 : (MEM_RD | MEM_WR);
p->memory.typeSize = 1;
- p->rbParent = Qnil;
+ RB_OBJ_WRITE(obj, &p->rbParent, Qnil);
return obj;
}
@@ -82,7 +85,7 @@ ptr_allocate(VALUE klass)
VALUE obj;
obj = TypedData_Make_Struct(klass, Pointer, &rbffi_pointer_data_type, p);
- p->rbParent = Qnil;
+ RB_OBJ_WRITE(obj, &p->rbParent, Qnil);
p->memory.flags = MEM_RD | MEM_WR;
return obj;
@@ -134,7 +137,7 @@ ptr_initialize(int argc, VALUE* argv, VALUE self)
if (rb_obj_is_kind_of(rbAddress, rbffi_PointerClass)) {
Pointer* orig;
- p->rbParent = rbAddress;
+ RB_OBJ_WRITE(self, &p->rbParent, rbAddress);
TypedData_Get_Struct(rbAddress, Pointer, &rbffi_pointer_data_type, orig);
p->memory = orig->memory;
} else {
@@ -215,7 +218,7 @@ slice(VALUE self, long offset, long size)
p->memory.size = size;
p->memory.flags = ptr->flags;
p->memory.typeSize = ptr->typeSize;
- p->rbParent = self;
+ RB_OBJ_WRITE(retval, &p->rbParent, self);
return retval;
}
@@ -471,6 +474,17 @@ ptr_mark(void *data)
rb_gc_mark(ptr->rbParent);
}
+static size_t
+ptr_memsize(const void *data)
+{
+ const Pointer *ptr = (const Pointer *)data;
+ size_t memsize = sizeof(Pointer);
+ if (ptr->allocated) {
+ memsize += ptr->memory.size;
+ }
+ return memsize;
+}
+
void
rbffi_Pointer_Init(VALUE moduleFFI)
{