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.c97
1 files changed, 68 insertions, 29 deletions
diff --git a/ext/ffi_c/Pointer.c b/ext/ffi_c/Pointer.c
index 153fff1..dae853a 100644
--- a/ext/ffi_c/Pointer.c
+++ b/ext/ffi_c/Pointer.c
@@ -33,16 +33,33 @@
#include <ruby.h>
#include "rbffi.h"
#include "rbffi_endian.h"
+#include "compat.h"
#include "AbstractMemory.h"
#include "Pointer.h"
-#define POINTER(obj) rbffi_AbstractMemory_Cast((obj), rbffi_PointerClass)
+#define POINTER(obj) rbffi_AbstractMemory_Cast((obj), &rbffi_pointer_data_type)
VALUE rbffi_PointerClass = Qnil;
VALUE rbffi_NullPointerSingleton = Qnil;
-static void ptr_release(Pointer* ptr);
-static void ptr_mark(Pointer* ptr);
+static void ptr_release(void *data);
+static void ptr_mark(void *data);
+static void ptr_compact(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 = ptr_memsize,
+ ffi_compact_callback( ptr_compact )
+ },
+ .parent = &rbffi_abstract_memory_data_type,
+ // 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 | FFI_RUBY_TYPED_FROZEN_SHAREABLE
+};
VALUE
rbffi_Pointer_NewInstance(void* addr)
@@ -54,12 +71,12 @@ rbffi_Pointer_NewInstance(void* addr)
return rbffi_NullPointerSingleton;
}
- obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p);
+ obj = TypedData_Make_Struct(rbffi_PointerClass, Pointer, &rbffi_pointer_data_type, p);
p->memory.address = 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;
}
@@ -70,8 +87,8 @@ ptr_allocate(VALUE klass)
Pointer* p;
VALUE obj;
- obj = Data_Make_Struct(klass, Pointer, ptr_mark, ptr_release, p);
- p->rbParent = Qnil;
+ obj = TypedData_Make_Struct(klass, Pointer, &rbffi_pointer_data_type, p);
+ RB_OBJ_WRITE(obj, &p->rbParent, Qnil);
p->memory.flags = MEM_RD | MEM_WR;
return obj;
@@ -95,7 +112,7 @@ ptr_initialize(int argc, VALUE* argv, VALUE self)
VALUE rbType = Qnil, rbAddress = Qnil;
int typeSize = 1;
- Data_Get_Struct(self, Pointer, p);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, p);
switch (rb_scan_args(argc, argv, "11", &rbType, &rbAddress)) {
case 1:
@@ -112,7 +129,7 @@ ptr_initialize(int argc, VALUE* argv, VALUE self)
switch (TYPE(rbAddress)) {
case T_FIXNUM:
case T_BIGNUM:
- p->memory.address = (void*) (uintptr_t) NUM2LL(rbAddress);
+ p->memory.address = (void*) (uintptr_t) NUM2ULL(rbAddress);
p->memory.size = LONG_MAX;
if (p->memory.address == NULL) {
p->memory.flags = 0;
@@ -123,8 +140,8 @@ ptr_initialize(int argc, VALUE* argv, VALUE self)
if (rb_obj_is_kind_of(rbAddress, rbffi_PointerClass)) {
Pointer* orig;
- p->rbParent = rbAddress;
- Data_Get_Struct(rbAddress, Pointer, orig);
+ RB_OBJ_WRITE(self, &p->rbParent, rbAddress);
+ TypedData_Get_Struct(rbAddress, Pointer, &rbffi_pointer_data_type, orig);
p->memory = orig->memory;
} else {
rb_raise(rb_eTypeError, "wrong argument type, expected Integer or FFI::Pointer");
@@ -153,7 +170,7 @@ ptr_initialize_copy(VALUE self, VALUE other)
AbstractMemory* src;
Pointer* dst;
- Data_Get_Struct(self, Pointer, dst);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, dst);
src = POINTER(other);
if (src->size == LONG_MAX) {
rb_raise(rb_eRuntimeError, "cannot duplicate unbounded memory area");
@@ -195,16 +212,16 @@ slice(VALUE self, long offset, long size)
Pointer* p;
VALUE retval;
- Data_Get_Struct(self, AbstractMemory, ptr);
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
checkBounds(ptr, offset, size == LONG_MAX ? 1 : size);
- retval = Data_Make_Struct(rbffi_PointerClass, Pointer, ptr_mark, -1, p);
+ retval = TypedData_Make_Struct(rbffi_PointerClass, Pointer, &rbffi_pointer_data_type, p);
p->memory.address = ptr->address + offset;
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;
}
@@ -222,7 +239,7 @@ ptr_plus(VALUE self, VALUE offset)
AbstractMemory* ptr;
long off = NUM2LONG(offset);
- Data_Get_Struct(self, AbstractMemory, ptr);
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
return slice(self, off, ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off);
}
@@ -252,7 +269,7 @@ ptr_inspect(VALUE self)
char buf[100];
Pointer* ptr;
- Data_Get_Struct(self, Pointer, ptr);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr);
if (ptr->memory.size != LONG_MAX) {
snprintf(buf, sizeof(buf), "#<%s address=%p size=%lu>",
@@ -275,7 +292,7 @@ ptr_null_p(VALUE self)
{
Pointer* ptr;
- Data_Get_Struct(self, Pointer, ptr);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr);
return ptr->memory.address == NULL ? Qtrue : Qfalse;
}
@@ -291,7 +308,7 @@ ptr_equals(VALUE self, VALUE other)
{
Pointer* ptr;
- Data_Get_Struct(self, Pointer, ptr);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr);
if (NIL_P(other)) {
return ptr->memory.address == NULL ? Qtrue : Qfalse;
@@ -310,7 +327,7 @@ ptr_address(VALUE self)
{
Pointer* ptr;
- Data_Get_Struct(self, Pointer, ptr);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr);
return ULL2NUM((uintptr_t) ptr->memory.address);
}
@@ -335,7 +352,7 @@ ptr_order(int argc, VALUE* argv, VALUE self)
{
Pointer* ptr;
- Data_Get_Struct(self, Pointer, ptr);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr);
if (argc == 0) {
int order = (ptr->memory.flags & MEM_SWAP) == 0 ? BYTE_ORDER : SWAPPED_ORDER;
return order == BIG_ENDIAN ? ID2SYM(rb_intern("big")) : ID2SYM(rb_intern("little"));
@@ -361,7 +378,7 @@ ptr_order(int argc, VALUE* argv, VALUE self)
Pointer* p2;
VALUE retval = slice(self, 0, ptr->memory.size);
- Data_Get_Struct(retval, Pointer, p2);
+ TypedData_Get_Struct(retval, Pointer, &rbffi_pointer_data_type, p2);
p2->memory.flags |= MEM_SWAP;
return retval;
}
@@ -381,7 +398,8 @@ ptr_free(VALUE self)
{
Pointer* ptr;
- Data_Get_Struct(self, Pointer, ptr);
+ rb_check_frozen(self);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr);
if (ptr->allocated) {
if (ptr->storage != NULL) {
@@ -404,7 +422,7 @@ ptr_type_size(VALUE self)
{
Pointer* ptr;
- Data_Get_Struct(self, Pointer, ptr);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr);
return INT2NUM(ptr->memory.typeSize);
}
@@ -420,7 +438,8 @@ ptr_autorelease(VALUE self, VALUE autorelease)
{
Pointer* ptr;
- Data_Get_Struct(self, Pointer, ptr);
+ rb_check_frozen(self);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr);
ptr->autorelease = autorelease == Qtrue;
return autorelease;
@@ -436,15 +455,16 @@ ptr_autorelease_p(VALUE self)
{
Pointer* ptr;
- Data_Get_Struct(self, Pointer, ptr);
+ TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr);
return ptr->autorelease ? Qtrue : Qfalse;
}
static void
-ptr_release(Pointer* ptr)
+ptr_release(void *data)
{
+ Pointer *ptr = (Pointer *)data;
if (ptr->autorelease && ptr->allocated && ptr->storage != NULL) {
xfree(ptr->storage);
ptr->storage = NULL;
@@ -453,9 +473,28 @@ ptr_release(Pointer* ptr)
}
static void
-ptr_mark(Pointer* ptr)
+ptr_mark(void *data)
{
- rb_gc_mark(ptr->rbParent);
+ Pointer *ptr = (Pointer *)data;
+ rb_gc_mark_movable(ptr->rbParent);
+}
+
+static void
+ptr_compact(void *data)
+{
+ Pointer *ptr = (Pointer *)data;
+ ffi_gc_location(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