summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Rakefile3
-rw-r--r--ext/ffi_c/ArrayType.c12
-rw-r--r--ext/ffi_c/Buffer.c11
-rw-r--r--ext/ffi_c/DynamicLibrary.c14
-rw-r--r--ext/ffi_c/Function.c17
-rw-r--r--ext/ffi_c/FunctionInfo.c26
-rw-r--r--ext/ffi_c/MappedType.c23
-rw-r--r--ext/ffi_c/MethodHandle.c4
-rw-r--r--ext/ffi_c/Pointer.c11
-rw-r--r--ext/ffi_c/Struct.c37
-rw-r--r--ext/ffi_c/StructByValue.c16
-rw-r--r--ext/ffi_c/StructLayout.c39
-rw-r--r--ext/ffi_c/Variadic.c17
-rw-r--r--ext/ffi_c/compat.h9
-rwxr-xr-xext/ffi_c/extconf.rb2
m---------ext/ffi_c/libffi0
-rw-r--r--spec/ffi/function_spec.rb10
17 files changed, 211 insertions, 40 deletions
diff --git a/Rakefile b/Rakefile
index f3b3746..ce9c46a 100644
--- a/Rakefile
+++ b/Rakefile
@@ -31,8 +31,7 @@ CLEAN.include 'spec/ffi/fixtures/*.o'
CLEAN.include 'spec/ffi/embed-test/ext/*.{o,def}'
CLEAN.include 'spec/ffi/embed-test/ext/Makefile'
CLEAN.include "pkg/ffi-*-{mingw32,java}"
-CLEAN.include 'lib/1.*'
-CLEAN.include 'lib/2.*'
+CLEAN.include 'lib/{2,3}.*'
# clean all shipped files, that are not in git
CLEAN.include(
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/MethodHandle.c b/ext/ffi_c/MethodHandle.c
index d047e10..83f7b77 100644
--- a/ext/ffi_c/MethodHandle.c
+++ b/ext/ffi_c/MethodHandle.c
@@ -77,7 +77,9 @@
static bool prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize);
static long trampoline_size(void);
-#if defined(__x86_64__) && (defined(__linux__) || defined(__APPLE__))
+#if defined(__x86_64__) && \
+ (defined(__linux__) || defined(__APPLE__)) && \
+ !USE_FFI_ALLOC
# define CUSTOM_TRAMPOLINE 1
#endif
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"
diff --git a/ext/ffi_c/libffi b/ext/ffi_c/libffi
-Subproject 5c63b463b87d3c06102a4a7f05f395929d9ea79
+Subproject ac598b7f5272d536b75f4b3833a4610cf4cd940
diff --git a/spec/ffi/function_spec.rb b/spec/ffi/function_spec.rb
index a1a50f3..7f90ea3 100644
--- a/spec/ffi/function_spec.rb
+++ b/spec/ffi/function_spec.rb
@@ -59,6 +59,16 @@ describe FFI::Function do
expect(Foo.add(10, 10)).to eq(20)
end
+ it 'can be attached to two modules' do
+ module Foo1; end
+ module Foo2; end
+ fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd'))
+ fp.attach(Foo1, 'add')
+ fp.attach(Foo2, 'add')
+ expect(Foo1.add(11, 11)).to eq(22)
+ expect(Foo2.add(12, 12)).to eq(24)
+ end
+
it 'can be used to extend an object' do
fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd'))
foo = Object.new