summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Rakefile3
-rw-r--r--ext/ffi_c/AbstractMemory.c2
-rw-r--r--ext/ffi_c/ArrayType.c12
-rw-r--r--ext/ffi_c/Buffer.c11
-rw-r--r--ext/ffi_c/DynamicLibrary.c29
-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.c39
-rw-r--r--ext/ffi_c/StructByValue.c16
-rw-r--r--ext/ffi_c/StructLayout.c39
-rw-r--r--ext/ffi_c/Type.c29
-rw-r--r--ext/ffi_c/Variadic.c17
-rw-r--r--ext/ffi_c/compat.h30
-rwxr-xr-xext/ffi_c/extconf.rb2
m---------ext/ffi_c/libffi0
-rw-r--r--lib/ffi/platform/sw_64-linux/types.conf141
-rw-r--r--spec/ffi/function_spec.rb10
20 files changed, 379 insertions, 82 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/AbstractMemory.c b/ext/ffi_c/AbstractMemory.c
index 3cf16a7..10ddc28 100644
--- a/ext/ffi_c/AbstractMemory.c
+++ b/ext/ffi_c/AbstractMemory.c
@@ -150,7 +150,7 @@ memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary) \
if (likely(count > 0)) checkWrite(memory); \
checkBounds(memory, off, count * sizeof(type)); \
for (i = 0; i < count; i++) { \
- type tmp = (type) VAL(toNative(RARRAY_PTR(ary)[i]), swap); \
+ type tmp = (type) VAL(toNative(RARRAY_AREF(ary, i)), swap); \
memcpy(memory->address + off + (i * sizeof(type)), &tmp, sizeof(tmp)); \
} \
return self; \
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..bcbc8de 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()
@@ -223,8 +225,19 @@ dl_open(const char* name, int flags)
static void
dl_error(char* buf, int size)
{
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
- 0, buf, size, NULL);
+ // Get the last error code
+ DWORD error = GetLastError();
+
+ // Get the associated message
+ LPSTR message = NULL;
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL, error, 0, (LPSTR)&message, 0, NULL);
+
+ // Update the passed in buffer
+ snprintf(buf, size, "Failed with error %d: %s", error, message);
+
+ // Free the allocated message
+ LocalFree(message);
}
#endif
@@ -273,8 +286,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..9eb10ec 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.
@@ -129,7 +132,7 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
/* Call up into ruby code to adjust the layout */
if (nargs > 1) {
- VALUE rbLayout = rb_funcall2(CLASS_OF(self), id_layout, (int) RARRAY_LEN(rest), RARRAY_PTR(rest));
+ VALUE rbLayout = rb_apply(CLASS_OF(self), id_layout, rest);
RB_OBJ_WRITE(self, &s->rbLayout, rbLayout);
} else {
RB_OBJ_WRITE(self, &s->rbLayout, struct_class_layout(klass));
@@ -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/Type.c b/ext/ffi_c/Type.c
index 6089a14..194c81e 100644
--- a/ext/ffi_c/Type.c
+++ b/ext/ffi_c/Type.c
@@ -14,7 +14,7 @@
* * Neither the name of the Ruby FFI project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -52,8 +52,8 @@ VALUE rbffi_TypeClass = Qnil;
static VALUE classBuiltinType = Qnil;
static VALUE moduleNativeType = Qnil;
-static VALUE typeMap = Qnil, sizeMap = Qnil;
-static ID id_find_type = 0, id_type_size = 0, id_size = 0;
+static VALUE typeMap = Qnil;
+static ID id_type_size = 0, id_size = 0;
const rb_data_type_t rbffi_type_data_type = { /* extern */
.wrap_struct_name = "FFI::Type",
@@ -121,7 +121,7 @@ type_initialize(VALUE self, VALUE value)
} else {
rb_raise(rb_eArgError, "wrong type");
}
-
+
return self;
}
@@ -217,13 +217,13 @@ int
rbffi_type_size(VALUE type)
{
int t = TYPE(type);
-
+
if (t == T_FIXNUM || t == T_BIGNUM) {
return NUM2INT(type);
-
+
} else if (t == T_SYMBOL) {
/*
- * Try looking up directly in the type and size maps
+ * Try looking up directly in the type map
*/
VALUE nType;
if ((nType = rb_hash_lookup(typeMap, type)) != Qnil) {
@@ -231,7 +231,7 @@ rbffi_type_size(VALUE type)
Type* type;
TypedData_Get_Struct(nType, Type, &rbffi_type_data_type, type);
return (int) type->ffiType->size;
-
+
} else if (rb_respond_to(nType, id_size)) {
return NUM2INT(rb_funcall2(nType, id_size, 0, NULL));
}
@@ -239,7 +239,7 @@ rbffi_type_size(VALUE type)
/* Not found - call up to the ruby version to resolve */
return NUM2INT(rb_funcall2(rbffi_FFIModule, id_type_size, 1, &type));
-
+
} else {
return NUM2INT(rb_funcall2(type, id_size, 0, NULL));
}
@@ -251,14 +251,14 @@ rbffi_Type_Lookup(VALUE name)
int t = TYPE(name);
if (t == T_SYMBOL || t == T_STRING) {
/*
- * Try looking up directly in the type Map
+ * Try looking up directly in the type map
*/
VALUE nType;
if ((nType = rb_hash_lookup(typeMap, name)) != Qnil && rb_obj_is_kind_of(nType, rbffi_TypeClass)) {
return nType;
}
} else if (rb_obj_is_kind_of(name, rbffi_TypeClass)) {
-
+
return name;
}
@@ -282,10 +282,7 @@ rbffi_Type_Init(VALUE moduleFFI)
* Document-constant: FFI::TypeDefs
*/
rb_define_const(moduleFFI, "TypeDefs", typeMap = rb_hash_new());
- rb_define_const(moduleFFI, "SizeTypes", sizeMap = rb_hash_new());
rb_global_variable(&typeMap);
- rb_global_variable(&sizeMap);
- id_find_type = rb_intern("find_type");
id_type_size = rb_intern("type_size");
id_size = rb_intern("size");
@@ -328,7 +325,7 @@ rbffi_Type_Init(VALUE moduleFFI)
* * BUFFER_OUT
* * VARARGS (function takes a variable number of arguments)
*
- * All these constants are exported to {FFI} module prefixed with "TYPE_".
+ * All these constants are exported to {FFI} module prefixed with "TYPE_".
* They are objets from {FFI::Type::Builtin} class.
*/
moduleNativeType = rb_define_module_under(moduleFFI, "NativeType");
@@ -349,7 +346,7 @@ rbffi_Type_Init(VALUE moduleFFI)
/* Make Type::Builtin non-allocatable */
rb_undef_method(CLASS_OF(classBuiltinType), "new");
rb_define_method(classBuiltinType, "inspect", builtin_type_inspect, 0);
-
+
rb_global_variable(&rbffi_TypeClass);
rb_global_variable(&classBuiltinType);
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..856836f 100644
--- a/ext/ffi_c/compat.h
+++ b/ext/ffi_c/compat.h
@@ -32,26 +32,6 @@
#include <ruby.h>
-#ifndef RARRAY_LEN
-# define RARRAY_LEN(ary) RARRAY(ary)->len
-#endif
-
-#ifndef RARRAY_PTR
-# define RARRAY_PTR(ary) RARRAY(ary)->ptr
-#endif
-
-#ifndef RSTRING_LEN
-# define RSTRING_LEN(s) RSTRING(s)->len
-#endif
-
-#ifndef RSTRING_PTR
-# define RSTRING_PTR(s) RSTRING(s)->ptr
-#endif
-
-#ifndef NUM2ULL
-# define NUM2ULL(x) rb_num2ull((VALUE)x)
-#endif
-
#ifndef roundup
# define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
#endif
@@ -75,8 +55,14 @@
# define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
-#ifndef RB_GC_GUARD
-# define RB_GC_GUARD(x) (x)
+
+#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 b5bdc05..b3eb020 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/lib/ffi/platform/sw_64-linux/types.conf b/lib/ffi/platform/sw_64-linux/types.conf
new file mode 100644
index 0000000..aa8716d
--- /dev/null
+++ b/lib/ffi/platform/sw_64-linux/types.conf
@@ -0,0 +1,141 @@
+rbx.platform.typedef.*__caddr_t = char
+rbx.platform.typedef.__blkcnt64_t = long
+rbx.platform.typedef.__blkcnt_t = long
+rbx.platform.typedef.__blksize_t = int
+rbx.platform.typedef.__clock_t = long
+rbx.platform.typedef.__clockid_t = int
+rbx.platform.typedef.__daddr_t = int
+rbx.platform.typedef.__dev_t = ulong
+rbx.platform.typedef.__fd_mask = long
+rbx.platform.typedef.__fsblkcnt64_t = ulong
+rbx.platform.typedef.__fsblkcnt_t = ulong
+rbx.platform.typedef.__fsfilcnt64_t = ulong
+rbx.platform.typedef.__fsfilcnt_t = ulong
+rbx.platform.typedef.__fsword_t = long
+rbx.platform.typedef.__gid_t = uint
+rbx.platform.typedef.__id_t = uint
+rbx.platform.typedef.__ino64_t = ulong
+rbx.platform.typedef.__ino_t = ulong
+rbx.platform.typedef.__int16_t = short
+rbx.platform.typedef.__int32_t = int
+rbx.platform.typedef.__int64_t = long
+rbx.platform.typedef.__int8_t = char
+rbx.platform.typedef.__int_least16_t = short
+rbx.platform.typedef.__int_least32_t = int
+rbx.platform.typedef.__int_least64_t = long
+rbx.platform.typedef.__int_least8_t = char
+rbx.platform.typedef.__intmax_t = long
+rbx.platform.typedef.__intptr_t = long
+rbx.platform.typedef.__key_t = int
+rbx.platform.typedef.__loff_t = long
+rbx.platform.typedef.__mode_t = uint
+rbx.platform.typedef.__nlink_t = uint
+rbx.platform.typedef.__off64_t = long
+rbx.platform.typedef.__off_t = long
+rbx.platform.typedef.__pid_t = int
+rbx.platform.typedef.__priority_which_t = int
+rbx.platform.typedef.__quad_t = long
+rbx.platform.typedef.__rlim64_t = ulong
+rbx.platform.typedef.__rlim_t = ulong
+rbx.platform.typedef.__rlimit_resource_t = int
+rbx.platform.typedef.__rusage_who_t = int
+rbx.platform.typedef.__sig_atomic_t = int
+rbx.platform.typedef.__socklen_t = uint
+rbx.platform.typedef.__ssize_t = long
+rbx.platform.typedef.__suseconds_t = long
+rbx.platform.typedef.__syscall_slong_t = long
+rbx.platform.typedef.__syscall_ulong_t = ulong
+rbx.platform.typedef.__time_t = long
+rbx.platform.typedef.__timer_t = pointer
+rbx.platform.typedef.__u_char = uchar
+rbx.platform.typedef.__u_int = uint
+rbx.platform.typedef.__u_long = ulong
+rbx.platform.typedef.__u_quad_t = ulong
+rbx.platform.typedef.__u_short = ushort
+rbx.platform.typedef.__uid_t = uint
+rbx.platform.typedef.__uint16_t = ushort
+rbx.platform.typedef.__uint32_t = uint
+rbx.platform.typedef.__uint64_t = ulong
+rbx.platform.typedef.__uint8_t = uchar
+rbx.platform.typedef.__uint_least16_t = ushort
+rbx.platform.typedef.__uint_least32_t = uint
+rbx.platform.typedef.__uint_least64_t = ulong
+rbx.platform.typedef.__uint_least8_t = uchar
+rbx.platform.typedef.__uintmax_t = ulong
+rbx.platform.typedef.__useconds_t = uint
+rbx.platform.typedef.blkcnt_t = long
+rbx.platform.typedef.blksize_t = int
+rbx.platform.typedef.clock_t = long
+rbx.platform.typedef.clockid_t = int
+rbx.platform.typedef.daddr_t = int
+rbx.platform.typedef.dev_t = ulong
+rbx.platform.typedef.fd_mask = long
+rbx.platform.typedef.fsblkcnt_t = ulong
+rbx.platform.typedef.fsfilcnt_t = ulong
+rbx.platform.typedef.gid_t = uint
+rbx.platform.typedef.id_t = uint
+rbx.platform.typedef.in_addr_t = uint
+rbx.platform.typedef.in_port_t = ushort
+rbx.platform.typedef.ino_t = ulong
+rbx.platform.typedef.int16_t = short
+rbx.platform.typedef.int32_t = int
+rbx.platform.typedef.int64_t = long
+rbx.platform.typedef.int8_t = char
+rbx.platform.typedef.int_fast16_t = long
+rbx.platform.typedef.int_fast32_t = long
+rbx.platform.typedef.int_fast64_t = long
+rbx.platform.typedef.int_fast8_t = char
+rbx.platform.typedef.int_least16_t = short
+rbx.platform.typedef.int_least32_t = int
+rbx.platform.typedef.int_least64_t = long
+rbx.platform.typedef.int_least8_t = char
+rbx.platform.typedef.intmax_t = long
+rbx.platform.typedef.intptr_t = long
+rbx.platform.typedef.key_t = int
+rbx.platform.typedef.loff_t = long
+rbx.platform.typedef.mode_t = uint
+rbx.platform.typedef.nlink_t = uint
+rbx.platform.typedef.off_t = long
+rbx.platform.typedef.pid_t = int
+rbx.platform.typedef.pthread_key_t = uint
+rbx.platform.typedef.pthread_once_t = int
+rbx.platform.typedef.pthread_t = ulong
+rbx.platform.typedef.ptrdiff_t = long
+rbx.platform.typedef.quad_t = long
+rbx.platform.typedef.register_t = long
+rbx.platform.typedef.rlim_t = ulong
+rbx.platform.typedef.sa_family_t = ushort
+rbx.platform.typedef.size_t = ulong
+rbx.platform.typedef.socklen_t = uint
+rbx.platform.typedef.ssize_t = long
+rbx.platform.typedef.suseconds_t = long
+rbx.platform.typedef.time_t = long
+rbx.platform.typedef.timer_t = pointer
+rbx.platform.typedef.u_char = uchar
+rbx.platform.typedef.u_int = uint
+rbx.platform.typedef.u_int16_t = ushort
+rbx.platform.typedef.u_int32_t = uint
+rbx.platform.typedef.u_int64_t = ulong_long
+rbx.platform.typedef.u_int8_t = uchar
+rbx.platform.typedef.u_long = ulong
+rbx.platform.typedef.u_quad_t = ulong
+rbx.platform.typedef.u_short = ushort
+rbx.platform.typedef.uid_t = uint
+rbx.platform.typedef.uint = uint
+rbx.platform.typedef.uint16_t = ushort
+rbx.platform.typedef.uint32_t = uint
+rbx.platform.typedef.uint64_t = ulong
+rbx.platform.typedef.uint8_t = uchar
+rbx.platform.typedef.uint_fast16_t = ulong
+rbx.platform.typedef.uint_fast32_t = ulong
+rbx.platform.typedef.uint_fast64_t = ulong
+rbx.platform.typedef.uint_fast8_t = uchar
+rbx.platform.typedef.uint_least16_t = ushort
+rbx.platform.typedef.uint_least32_t = uint
+rbx.platform.typedef.uint_least64_t = ulong
+rbx.platform.typedef.uint_least8_t = uchar
+rbx.platform.typedef.uintmax_t = ulong
+rbx.platform.typedef.uintptr_t = ulong
+rbx.platform.typedef.ulong = ulong
+rbx.platform.typedef.ushort = ushort
+rbx.platform.typedef.wchar_t = int
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