Skip to content

Commit

Permalink
Merge pull request #1021 from larskanis/compact
Browse files Browse the repository at this point in the history
Make FFI classes GC.compact friendly
  • Loading branch information
larskanis committed Apr 16, 2023
2 parents 54651da + ce6b172 commit d5e0dd9
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 37 deletions.
12 changes: 11 additions & 1 deletion ext/ffi_c/ArrayType.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@

#include <ruby.h>
#include <ffi.h>
#include "compat.h"
#include "ArrayType.h"

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_compact(void *);
static void array_type_free(void *);
static size_t array_type_memsize(const void *);

Expand All @@ -43,6 +45,7 @@ const rb_data_type_t rbffi_array_type_data_type = { /* extern */
.dmark = array_type_mark,
.dfree = array_type_free,
.dsize = array_type_memsize,
ffi_compact_callback( array_type_compact )
},
.parent = &rbffi_type_data_type,
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
Expand Down Expand Up @@ -75,7 +78,14 @@ static void
array_type_mark(void *data)
{
ArrayType *array = (ArrayType *)data;
rb_gc_mark(array->rbComponentType);
rb_gc_mark_movable(array->rbComponentType);
}

static void
array_type_compact(void *data)
{
ArrayType *array = (ArrayType *)data;
ffi_gc_location(array->rbComponentType);
}

static void
Expand Down
11 changes: 10 additions & 1 deletion ext/ffi_c/Buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ static VALUE buffer_allocate(VALUE klass);
static VALUE buffer_initialize(int argc, VALUE* argv, VALUE self);
static void buffer_release(void *data);
static void buffer_mark(void *data);
static void buffer_compact(void *data);
static VALUE buffer_free(VALUE self);
static size_t allocated_buffer_memsize(const void *data);
static size_t buffer_memsize(const void *data);
Expand All @@ -61,6 +62,7 @@ static const rb_data_type_t buffer_data_type = {
.dmark = buffer_mark,
.dfree = RUBY_TYPED_DEFAULT_FREE,
.dsize = buffer_memsize,
ffi_compact_callback( buffer_compact )
},
.parent = &rbffi_abstract_memory_data_type,
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
Expand Down Expand Up @@ -337,7 +339,14 @@ static void
buffer_mark(void *data)
{
Buffer *ptr = (Buffer *)data;
rb_gc_mark(ptr->data.rbParent);
rb_gc_mark_movable(ptr->data.rbParent);
}

static void
buffer_compact(void *data)
{
Buffer *ptr = (Buffer *)data;
ffi_gc_location(ptr->data.rbParent);
}

static size_t
Expand Down
14 changes: 12 additions & 2 deletions ext/ffi_c/DynamicLibrary.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ static size_t library_memsize(const void *);
static VALUE symbol_allocate(VALUE klass);
static VALUE symbol_new(VALUE library, void* address, VALUE name);
static void symbol_mark(void *data);
static void symbol_compact(void *data);
static size_t symbol_memsize(const void *data);

static const rb_data_type_t rbffi_library_data_type = {
Expand All @@ -81,6 +82,7 @@ static const rb_data_type_t library_symbol_data_type = {
.dmark = symbol_mark,
.dfree = RUBY_TYPED_DEFAULT_FREE,
.dsize = symbol_memsize,
ffi_compact_callback( symbol_compact )
},
.parent = &rbffi_pointer_data_type,
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
Expand Down Expand Up @@ -273,8 +275,16 @@ static void
symbol_mark(void *data)
{
LibrarySymbol *sym = (LibrarySymbol *)data;
rb_gc_mark(sym->base.rbParent);
rb_gc_mark(sym->name);
rb_gc_mark_movable(sym->base.rbParent);
rb_gc_mark_movable(sym->name);
}

static void
symbol_compact(void *data)
{
LibrarySymbol *sym = (LibrarySymbol *)data;
ffi_gc_location(sym->base.rbParent);
ffi_gc_location(sym->name);
}

static size_t
Expand Down
17 changes: 14 additions & 3 deletions ext/ffi_c/Function.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ typedef struct Function_ {
} Function;

static void function_mark(void *data);
static void function_compact(void *data);
static void function_free(void *data);
static size_t function_memsize(const void *data);
static VALUE function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc);
Expand All @@ -102,6 +103,7 @@ static const rb_data_type_t function_data_type = {
.dmark = function_mark,
.dfree = function_free,
.dsize = function_memsize,
ffi_compact_callback( function_compact )
},
.parent = &rbffi_pointer_data_type,
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
Expand Down Expand Up @@ -168,9 +170,18 @@ static void
function_mark(void *data)
{
Function *fn = (Function *)data;
rb_gc_mark(fn->base.rbParent);
rb_gc_mark(fn->rbProc);
rb_gc_mark(fn->rbFunctionInfo);
rb_gc_mark_movable(fn->base.rbParent);
rb_gc_mark_movable(fn->rbProc);
rb_gc_mark_movable(fn->rbFunctionInfo);
}

static void
function_compact(void *data)
{
Function *fn = (Function *)data;
ffi_gc_location(fn->base.rbParent);
ffi_gc_location(fn->rbProc);
ffi_gc_location(fn->rbFunctionInfo);
}

static void
Expand Down
26 changes: 22 additions & 4 deletions ext/ffi_c/FunctionInfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
static VALUE fntype_allocate(VALUE klass);
static VALUE fntype_initialize(int argc, VALUE* argv, VALUE self);
static void fntype_mark(void *);
static void fntype_compact(void *);
static void fntype_free(void *);
static size_t fntype_memsize(const void *);

Expand All @@ -61,6 +62,7 @@ const rb_data_type_t rbffi_fntype_data_type = { /* extern */
.dmark = fntype_mark,
.dfree = fntype_free,
.dsize = fntype_memsize,
ffi_compact_callback( fntype_compact )
},
.parent = &rbffi_type_data_type,
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
Expand Down Expand Up @@ -91,11 +93,27 @@ static void
fntype_mark(void *data)
{
FunctionType *fnInfo = (FunctionType *)data;
rb_gc_mark(fnInfo->rbReturnType);
rb_gc_mark(fnInfo->rbParameterTypes);
rb_gc_mark(fnInfo->rbEnums);
rb_gc_mark_movable(fnInfo->rbReturnType);
rb_gc_mark_movable(fnInfo->rbParameterTypes);
rb_gc_mark_movable(fnInfo->rbEnums);
if (fnInfo->callbackCount > 0 && fnInfo->callbackParameters != NULL) {
rb_gc_mark_locations(&fnInfo->callbackParameters[0], &fnInfo->callbackParameters[fnInfo->callbackCount]);
for (size_t index = 0; index < fnInfo->callbackCount; index++) {
rb_gc_mark_movable(fnInfo->callbackParameters[index]);
}
}
}

static void
fntype_compact(void *data)
{
FunctionType *fnInfo = (FunctionType *)data;
ffi_gc_location(fnInfo->rbReturnType);
ffi_gc_location(fnInfo->rbParameterTypes);
ffi_gc_location(fnInfo->rbEnums);
if (fnInfo->callbackCount > 0 && fnInfo->callbackParameters != NULL) {
for (size_t index = 0; index < fnInfo->callbackCount; index++) {
ffi_gc_location(fnInfo->callbackParameters[index]);
}
}
}

Expand Down
23 changes: 17 additions & 6 deletions ext/ffi_c/MappedType.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include <ffi.h>
#include "rbffi.h"
#include "compat.h"

#include "Type.h"
#include "MappedType.h"
Expand All @@ -39,6 +40,7 @@
static VALUE mapped_allocate(VALUE);
static VALUE mapped_initialize(VALUE, VALUE);
static void mapped_mark(void *);
static void mapped_compact(void *);
static size_t mapped_memsize(const void *);
static ID id_native_type, id_to_native, id_from_native;

Expand All @@ -50,6 +52,7 @@ static const rb_data_type_t mapped_type_data_type = {
.dmark = mapped_mark,
.dfree = RUBY_TYPED_DEFAULT_FREE,
.dsize = mapped_memsize,
ffi_compact_callback( mapped_compact )
},
.parent = &rbffi_type_data_type,
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
Expand All @@ -70,7 +73,7 @@ mapped_allocate(VALUE klass)
m->type = NULL;
m->base.nativeType = NATIVE_MAPPED;
m->base.ffiType = &ffi_type_void;

return obj;
}

Expand All @@ -84,7 +87,7 @@ static VALUE
mapped_initialize(VALUE self, VALUE rbConverter)
{
MappedType* m = NULL;

if (!rb_respond_to(rbConverter, id_native_type)) {
rb_raise(rb_eNoMethodError, "native_type method not implemented");
}
Expand Down Expand Up @@ -114,8 +117,16 @@ static void
mapped_mark(void* data)
{
MappedType* m = (MappedType*)data;
rb_gc_mark(m->rbType);
rb_gc_mark(m->rbConverter);
rb_gc_mark_movable(m->rbType);
rb_gc_mark_movable(m->rbConverter);
}

static void
mapped_compact(void* data)
{
MappedType* m = (MappedType*)data;
ffi_gc_location(m->rbType);
ffi_gc_location(m->rbConverter);
}

static size_t
Expand Down Expand Up @@ -167,11 +178,11 @@ mapped_from_native(int argc, VALUE* argv, VALUE self)
void
rbffi_MappedType_Init(VALUE moduleFFI)
{
/*
/*
* Document-class: FFI::Type::Mapped < FFI::Type
*/
rbffi_MappedTypeClass = rb_define_class_under(rbffi_TypeClass, "Mapped", rbffi_TypeClass);

rb_global_variable(&rbffi_MappedTypeClass);

id_native_type = rb_intern("native_type");
Expand Down
11 changes: 10 additions & 1 deletion ext/ffi_c/Pointer.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ VALUE rbffi_NullPointerSingleton = Qnil;

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 */
Expand All @@ -51,6 +52,7 @@ const rb_data_type_t rbffi_pointer_data_type = { /* extern */
.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()
Expand Down Expand Up @@ -471,7 +473,14 @@ static void
ptr_mark(void *data)
{
Pointer *ptr = (Pointer *)data;
rb_gc_mark(ptr->rbParent);
rb_gc_mark_movable(ptr->rbParent);
}

static void
ptr_compact(void *data)
{
Pointer *ptr = (Pointer *)data;
ffi_gc_location(ptr->rbParent);
}

static size_t
Expand Down
37 changes: 32 additions & 5 deletions ext/ffi_c/Struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@ typedef struct InlineArray_ {


static void struct_mark(void *data);
static void struct_compact(void *data);
static void struct_free(void *data);
static size_t struct_memsize(const void *);
static VALUE struct_class_layout(VALUE klass);
static void struct_malloc(VALUE self, Struct* s);
static void inline_array_mark(void *);
static void inline_array_compact(void *);
static size_t inline_array_memsize(const void *);
static void store_reference_value(VALUE self, StructField* f, Struct* s, VALUE value);

Expand All @@ -76,6 +78,7 @@ const rb_data_type_t rbffi_struct_data_type = { /* extern */
.dmark = struct_mark,
.dfree = struct_free,
.dsize = struct_memsize,
ffi_compact_callback( struct_compact )
},
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
// macro to update VALUE references, as to trigger write barriers.
Expand Down Expand Up @@ -262,10 +265,25 @@ static void
struct_mark(void *data)
{
Struct *s = (Struct *)data;
rb_gc_mark(s->rbPointer);
rb_gc_mark(s->rbLayout);
rb_gc_mark_movable(s->rbPointer);
rb_gc_mark_movable(s->rbLayout);
if (s->rbReferences != NULL) {
rb_gc_mark_locations(&s->rbReferences[0], &s->rbReferences[s->layout->referenceFieldCount]);
for (size_t index = 0; index < s->layout->referenceFieldCount; index++) {
rb_gc_mark_movable(s->rbReferences[index]);
}
}
}

static void
struct_compact(void *data)
{
Struct *s = (Struct *)data;
ffi_gc_location(s->rbPointer);
ffi_gc_location(s->rbLayout);
if (s->rbReferences != NULL) {
for (size_t index = 0; index < s->layout->referenceFieldCount; index++) {
ffi_gc_location(s->rbReferences[index]);
}
}
}

Expand Down Expand Up @@ -522,6 +540,7 @@ static const rb_data_type_t inline_array_data_type = {
.dmark = inline_array_mark,
.dfree = RUBY_TYPED_DEFAULT_FREE,
.dsize = inline_array_memsize,
ffi_compact_callback( inline_array_compact )
},
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
// macro to update VALUE references, as to trigger write barriers.
Expand All @@ -545,8 +564,16 @@ static void
inline_array_mark(void *data)
{
InlineArray *array = (InlineArray *)data;
rb_gc_mark(array->rbField);
rb_gc_mark(array->rbMemory);
rb_gc_mark_movable(array->rbField);
rb_gc_mark_movable(array->rbMemory);
}

static void
inline_array_compact(void *data)
{
InlineArray *array = (InlineArray *)data;
ffi_gc_location(array->rbField);
ffi_gc_location(array->rbMemory);
}

static size_t
Expand Down
Loading

0 comments on commit d5e0dd9

Please sign in to comment.