diff options
-rw-r--r-- | ext/ffi_c/ArrayType.c | 12 | ||||
-rw-r--r-- | ext/ffi_c/Buffer.c | 11 | ||||
-rw-r--r-- | ext/ffi_c/DynamicLibrary.c | 14 | ||||
-rw-r--r-- | ext/ffi_c/Function.c | 17 | ||||
-rw-r--r-- | ext/ffi_c/FunctionInfo.c | 26 | ||||
-rw-r--r-- | ext/ffi_c/MappedType.c | 23 | ||||
-rw-r--r-- | ext/ffi_c/Pointer.c | 11 | ||||
-rw-r--r-- | ext/ffi_c/Struct.c | 37 | ||||
-rw-r--r-- | ext/ffi_c/StructByValue.c | 16 | ||||
-rw-r--r-- | ext/ffi_c/StructLayout.c | 39 | ||||
-rw-r--r-- | ext/ffi_c/Variadic.c | 17 | ||||
-rw-r--r-- | ext/ffi_c/compat.h | 9 | ||||
-rwxr-xr-x | ext/ffi_c/extconf.rb | 2 |
13 files changed, 197 insertions, 37 deletions
diff --git a/ext/ffi_c/ArrayType.c b/ext/ffi_c/ArrayType.c index 1d766a4..4bd77fd 100644 --- a/ext/ffi_c/ArrayType.c +++ b/ext/ffi_c/ArrayType.c @@ -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 *); @@ -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() @@ -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 diff --git a/ext/ffi_c/Buffer.c b/ext/ffi_c/Buffer.c index b3be778..0bfcc02 100644 --- a/ext/ffi_c/Buffer.c +++ b/ext/ffi_c/Buffer.c @@ -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); @@ -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() @@ -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 diff --git a/ext/ffi_c/DynamicLibrary.c b/ext/ffi_c/DynamicLibrary.c index 2e0bf4b..9bfe86e 100644 --- a/ext/ffi_c/DynamicLibrary.c +++ b/ext/ffi_c/DynamicLibrary.c @@ -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 = { @@ -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() @@ -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 diff --git a/ext/ffi_c/Function.c b/ext/ffi_c/Function.c index b73e8b7..0e68722 100644 --- a/ext/ffi_c/Function.c +++ b/ext/ffi_c/Function.c @@ -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); @@ -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() @@ -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 diff --git a/ext/ffi_c/FunctionInfo.c b/ext/ffi_c/FunctionInfo.c index 6aa93d9..7f77621 100644 --- a/ext/ffi_c/FunctionInfo.c +++ b/ext/ffi_c/FunctionInfo.c @@ -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 *); @@ -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() @@ -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]); + } } } diff --git a/ext/ffi_c/MappedType.c b/ext/ffi_c/MappedType.c index ed05c9d..b1532e1 100644 --- a/ext/ffi_c/MappedType.c +++ b/ext/ffi_c/MappedType.c @@ -31,6 +31,7 @@ #include <ffi.h> #include "rbffi.h" +#include "compat.h" #include "Type.h" #include "MappedType.h" @@ -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; @@ -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() @@ -70,7 +73,7 @@ mapped_allocate(VALUE klass) m->type = NULL; m->base.nativeType = NATIVE_MAPPED; m->base.ffiType = &ffi_type_void; - + return obj; } @@ -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"); } @@ -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 @@ -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"); diff --git a/ext/ffi_c/Pointer.c b/ext/ffi_c/Pointer.c index c926fe9..a6e8eb7 100644 --- a/ext/ffi_c/Pointer.c +++ b/ext/ffi_c/Pointer.c @@ -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 */ @@ -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() @@ -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 diff --git a/ext/ffi_c/Struct.c b/ext/ffi_c/Struct.c index 4f57cf3..b9b6b2c 100644 --- a/ext/ffi_c/Struct.c +++ b/ext/ffi_c/Struct.c @@ -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); @@ -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. @@ -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]); + } } } @@ -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. @@ -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 diff --git a/ext/ffi_c/StructByValue.c b/ext/ffi_c/StructByValue.c index e2c589d..94061f3 100644 --- a/ext/ffi_c/StructByValue.c +++ b/ext/ffi_c/StructByValue.c @@ -50,6 +50,7 @@ static VALUE sbv_allocate(VALUE); static VALUE sbv_initialize(VALUE, VALUE); static void sbv_mark(void *); +static void sbv_compact(void *); static void sbv_free(void *); static size_t sbv_memsize(const void *); @@ -61,6 +62,7 @@ static const rb_data_type_t sbv_type_data_type = { .dmark = sbv_mark, .dfree = sbv_free, .dsize = sbv_memsize, + ffi_compact_callback( sbv_compact ) }, .parent = &rbffi_type_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -106,7 +108,7 @@ sbv_initialize(VALUE self, VALUE rbStructClass) /* We can just use everything from the ffi_type directly */ *sbv->base.ffiType = *layout->base.ffiType; - + return self; } @@ -114,8 +116,16 @@ static void sbv_mark(void *data) { StructByValue *sbv = (StructByValue *)data; - rb_gc_mark(sbv->rbStructClass); - rb_gc_mark(sbv->rbStructLayout); + rb_gc_mark_movable(sbv->rbStructClass); + rb_gc_mark_movable(sbv->rbStructLayout); +} + +static void +sbv_compact(void *data) +{ + StructByValue *sbv = (StructByValue *)data; + ffi_gc_location(sbv->rbStructClass); + ffi_gc_location(sbv->rbStructLayout); } static void diff --git a/ext/ffi_c/StructLayout.c b/ext/ffi_c/StructLayout.c index f04b11f..548ddb5 100644 --- a/ext/ffi_c/StructLayout.c +++ b/ext/ffi_c/StructLayout.c @@ -52,9 +52,11 @@ #define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) static void struct_layout_mark(void *); +static void struct_layout_compact(void *); static void struct_layout_free(void *); static size_t struct_layout_memsize(const void *); static void struct_field_mark(void *); +static void struct_field_compact(void *); static size_t struct_field_memsize(const void *); VALUE rbffi_StructLayoutFieldClass = Qnil; @@ -70,6 +72,7 @@ const rb_data_type_t rbffi_struct_layout_data_type = { /* extern */ .dmark = struct_layout_mark, .dfree = struct_layout_free, .dsize = struct_layout_memsize, + ffi_compact_callback( struct_layout_compact ) }, .parent = &rbffi_type_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -83,6 +86,7 @@ const rb_data_type_t rbffi_struct_field_data_type = { /* extern */ .dmark = struct_field_mark, .dfree = RUBY_TYPED_DEFAULT_FREE, .dsize = struct_field_memsize, + ffi_compact_callback( struct_field_compact ) }, .parent = &rbffi_type_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -107,8 +111,16 @@ static void struct_field_mark(void *data) { StructField *f = (StructField *)data; - rb_gc_mark(f->rbType); - rb_gc_mark(f->rbName); + rb_gc_mark_movable(f->rbType); + rb_gc_mark_movable(f->rbName); +} + +static void +struct_field_compact(void *data) +{ + StructField *f = (StructField *)data; + ffi_gc_location(f->rbType); + ffi_gc_location(f->rbName); } static size_t @@ -628,12 +640,22 @@ static void struct_layout_mark(void *data) { StructLayout *layout = (StructLayout *)data; - rb_gc_mark(layout->rbFieldMap); - rb_gc_mark(layout->rbFieldNames); - rb_gc_mark(layout->rbFields); - for (size_t index = 0; index < FIELD_CACHE_ROWS; index++) { - rb_gc_mark(layout->cache_row[index].fieldName); - } + rb_gc_mark_movable(layout->rbFieldMap); + rb_gc_mark_movable(layout->rbFieldNames); + rb_gc_mark_movable(layout->rbFields); + /* The values stored in layout->cache_row.fieldName are primary stored in layout->rbFieldMap and are marked there */ +} + +static void +struct_layout_compact(void *data) +{ + StructLayout *layout = (StructLayout *)data; + ffi_gc_location(layout->rbFieldMap); + ffi_gc_location(layout->rbFieldNames); + ffi_gc_location(layout->rbFields); + + /* Clear the cache, to be safe from changes of fieldName VALUE by GC.compact */ + memset(&layout->cache_row, 0, sizeof(layout->cache_row)); } static void @@ -646,6 +668,7 @@ struct_layout_free(void *data) xfree(layout); } + static size_t struct_layout_memsize(const void * data) { diff --git a/ext/ffi_c/Variadic.c b/ext/ffi_c/Variadic.c index 04efd24..a255969 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 void variadic_compact(void *); static size_t variadic_memsize(const void *); static VALUE classVariadicInvoker = Qnil; @@ -76,6 +77,7 @@ static const rb_data_type_t variadic_data_type = { .dmark = variadic_mark, .dfree = RUBY_TYPED_DEFAULT_FREE, .dsize = variadic_memsize, + ffi_compact_callback( variadic_compact ) }, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() // macro to update VALUE references, as to trigger write barriers. @@ -101,9 +103,18 @@ static void variadic_mark(void *data) { VariadicInvoker *invoker = (VariadicInvoker *)data; - rb_gc_mark(invoker->rbEnums); - rb_gc_mark(invoker->rbAddress); - rb_gc_mark(invoker->rbReturnType); + rb_gc_mark_movable(invoker->rbEnums); + rb_gc_mark_movable(invoker->rbAddress); + rb_gc_mark_movable(invoker->rbReturnType); +} + +static void +variadic_compact(void *data) +{ + VariadicInvoker *invoker = (VariadicInvoker *)data; + ffi_gc_location(invoker->rbEnums); + ffi_gc_location(invoker->rbAddress); + ffi_gc_location(invoker->rbReturnType); } static size_t diff --git a/ext/ffi_c/compat.h b/ext/ffi_c/compat.h index 3f7bbae..889a4be 100644 --- a/ext/ffi_c/compat.h +++ b/ext/ffi_c/compat.h @@ -79,4 +79,13 @@ # define RB_GC_GUARD(x) (x) #endif +#ifdef HAVE_RB_GC_MARK_MOVABLE +#define ffi_compact_callback(x) .dcompact = (x), +#define ffi_gc_location(x) x = rb_gc_location(x) +#else +#define rb_gc_mark_movable(x) rb_gc_mark(x) +#define ffi_compact_callback(x) +#define ffi_gc_location(x) +#endif + #endif /* RBFFI_COMPAT_H */ diff --git a/ext/ffi_c/extconf.rb b/ext/ffi_c/extconf.rb index 2484543..a03b433 100755 --- a/ext/ffi_c/extconf.rb +++ b/ext/ffi_c/extconf.rb @@ -57,6 +57,8 @@ if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx' append_ldflags "-Wl,--exclude-libs,ALL" end + have_func 'rb_gc_mark_movable' # since ruby-2.7 + # Some linux archs need explicit linking to pthread, see https://github.com/ffi/ffi/issues/893 append_ldflags "-pthread" |