diff options
Diffstat (limited to 'ext/ffi_c/FunctionInfo.c')
-rw-r--r-- | ext/ffi_c/FunctionInfo.c | 102 |
1 files changed, 78 insertions, 24 deletions
diff --git a/ext/ffi_c/FunctionInfo.c b/ext/ffi_c/FunctionInfo.c index 64e9874..b5150d8 100644 --- a/ext/ffi_c/FunctionInfo.c +++ b/ext/ffi_c/FunctionInfo.c @@ -51,8 +51,24 @@ static VALUE fntype_allocate(VALUE klass); static VALUE fntype_initialize(int argc, VALUE* argv, VALUE self); -static void fntype_mark(FunctionType*); -static void fntype_free(FunctionType *); +static void fntype_mark(void *); +static void fntype_compact(void *); +static void fntype_free(void *); +static size_t fntype_memsize(const void *); + +const rb_data_type_t rbffi_fntype_data_type = { /* extern */ + .wrap_struct_name = "FFI::FunctionType", + .function = { + .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() + // 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_FunctionTypeClass = Qnil; @@ -60,13 +76,13 @@ static VALUE fntype_allocate(VALUE klass) { FunctionType* fnInfo; - VALUE obj = Data_Make_Struct(klass, FunctionType, fntype_mark, fntype_free, fnInfo); + VALUE obj = TypedData_Make_Struct(klass, FunctionType, &rbffi_fntype_data_type, fnInfo); fnInfo->type.ffiType = &ffi_type_pointer; fnInfo->type.nativeType = NATIVE_FUNCTION; - fnInfo->rbReturnType = Qnil; - fnInfo->rbParameterTypes = Qnil; - fnInfo->rbEnums = Qnil; + RB_OBJ_WRITE(obj, &fnInfo->rbReturnType, Qnil); + RB_OBJ_WRITE(obj, &fnInfo->rbParameterTypes, Qnil); + RB_OBJ_WRITE(obj, &fnInfo->rbEnums, Qnil); fnInfo->invoke = rbffi_CallFunction; fnInfo->closurePool = NULL; @@ -74,19 +90,37 @@ fntype_allocate(VALUE klass) } static void -fntype_mark(FunctionType* fnInfo) +fntype_mark(void *data) { - rb_gc_mark(fnInfo->rbReturnType); - rb_gc_mark(fnInfo->rbParameterTypes); - rb_gc_mark(fnInfo->rbEnums); + FunctionType *fnInfo = (FunctionType *)data; + 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]); + } } } static void -fntype_free(FunctionType* fnInfo) +fntype_free(void *data) { + FunctionType *fnInfo = (FunctionType *)data; xfree(fnInfo->parameterTypes); xfree(fnInfo->ffiParameterTypes); xfree(fnInfo->nativeParameterTypes); @@ -97,6 +131,23 @@ fntype_free(FunctionType* fnInfo) xfree(fnInfo); } +static size_t +fntype_memsize(const void *data) +{ + const FunctionType *fnInfo = (const FunctionType *)data; + + size_t memsize = sizeof(FunctionType); + memsize += fnInfo->callbackCount * sizeof(VALUE); + + memsize += fnInfo->parameterCount * ( + sizeof(*fnInfo->parameterTypes) + + sizeof(ffi_type *) + + sizeof(*fnInfo->nativeParameterTypes) + ); + + return memsize; +} + /* * call-seq: initialize(return_type, param_types, options={}) * @param [Type, Symbol] return_type return type for the function @@ -129,13 +180,13 @@ fntype_initialize(int argc, VALUE* argv, VALUE self) Check_Type(rbParamTypes, T_ARRAY); - Data_Get_Struct(self, FunctionType, fnInfo); + TypedData_Get_Struct(self, FunctionType, &rbffi_fntype_data_type, fnInfo); fnInfo->parameterCount = (int) RARRAY_LEN(rbParamTypes); fnInfo->parameterTypes = xcalloc(fnInfo->parameterCount, sizeof(*fnInfo->parameterTypes)); fnInfo->ffiParameterTypes = xcalloc(fnInfo->parameterCount, sizeof(ffi_type *)); fnInfo->nativeParameterTypes = xcalloc(fnInfo->parameterCount, sizeof(*fnInfo->nativeParameterTypes)); - fnInfo->rbParameterTypes = rb_ary_new2(fnInfo->parameterCount); - fnInfo->rbEnums = rbEnums; + RB_OBJ_WRITE(self, &fnInfo->rbParameterTypes, rb_ary_new2(fnInfo->parameterCount)); + RB_OBJ_WRITE(self, &fnInfo->rbEnums, rbEnums); fnInfo->blocking = RTEST(rbBlocking); fnInfo->hasStruct = false; @@ -150,7 +201,8 @@ fntype_initialize(int argc, VALUE* argv, VALUE self) if (rb_obj_is_kind_of(type, rbffi_FunctionTypeClass)) { REALLOC_N(fnInfo->callbackParameters, VALUE, fnInfo->callbackCount + 1); - fnInfo->callbackParameters[fnInfo->callbackCount++] = type; + RB_OBJ_WRITE(self, &fnInfo->callbackParameters[fnInfo->callbackCount], type); + fnInfo->callbackCount++; } if (rb_obj_is_kind_of(type, rbffi_StructByValueClass)) { @@ -158,12 +210,12 @@ fntype_initialize(int argc, VALUE* argv, VALUE self) } rb_ary_push(fnInfo->rbParameterTypes, type); - Data_Get_Struct(type, Type, fnInfo->parameterTypes[i]); + TypedData_Get_Struct(type, Type, &rbffi_type_data_type, fnInfo->parameterTypes[i]); fnInfo->ffiParameterTypes[i] = fnInfo->parameterTypes[i]->ffiType; fnInfo->nativeParameterTypes[i] = fnInfo->parameterTypes[i]->nativeType; } - fnInfo->rbReturnType = rbffi_Type_Lookup(rbReturnType); + RB_OBJ_WRITE(self, &fnInfo->rbReturnType, rbffi_Type_Lookup(rbReturnType)); if (!RTEST(fnInfo->rbReturnType)) { VALUE typeName = rb_funcall2(rbReturnType, rb_intern("inspect"), 0, NULL); rb_raise(rb_eTypeError, "Invalid return type (%s)", RSTRING_PTR(typeName)); @@ -173,7 +225,7 @@ fntype_initialize(int argc, VALUE* argv, VALUE self) fnInfo->hasStruct = true; } - Data_Get_Struct(fnInfo->rbReturnType, Type, fnInfo->returnType); + TypedData_Get_Struct(fnInfo->rbReturnType, Type, &rbffi_type_data_type, fnInfo->returnType); fnInfo->ffiReturnType = fnInfo->returnType->ffiType; #if defined(X86_WIN32) @@ -199,20 +251,22 @@ fntype_initialize(int argc, VALUE* argv, VALUE self) fnInfo->invoke = rbffi_GetInvoker(fnInfo); + rb_obj_freeze(fnInfo->rbParameterTypes); + rb_obj_freeze(self); return self; } /* - * call-seq: result_type + * call-seq: return_type * @return [Type] * Get the return type of the function type */ static VALUE -fntype_result_type(VALUE self) +fntype_return_type(VALUE self) { FunctionType* ft; - Data_Get_Struct(self, FunctionType, ft); + TypedData_Get_Struct(self, FunctionType, &rbffi_fntype_data_type, ft); return ft->rbReturnType; } @@ -227,7 +281,7 @@ fntype_param_types(VALUE self) { FunctionType* ft; - Data_Get_Struct(self, FunctionType, ft); + TypedData_Get_Struct(self, FunctionType, &rbffi_fntype_data_type, ft); return rb_ary_dup(ft->rbParameterTypes); } @@ -259,7 +313,7 @@ rbffi_FunctionInfo_Init(VALUE moduleFFI) rb_define_alloc_func(rbffi_FunctionTypeClass, fntype_allocate); rb_define_method(rbffi_FunctionTypeClass, "initialize", fntype_initialize, -1); - rb_define_method(rbffi_FunctionTypeClass, "result_type", fntype_result_type, 0); + rb_define_method(rbffi_FunctionTypeClass, "return_type", fntype_return_type, 0); rb_define_method(rbffi_FunctionTypeClass, "param_types", fntype_param_types, 0); } |