Avoid memory leak and improve performance for common structures.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28939 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2009-11-02 18:32:35 +00:00
parent b3a520b2fe
commit 3d9e3eee57

View file

@ -138,12 +138,10 @@ cifframe_from_signature (NSMethodSignature *info)
have custom ffi_types with are allocated separately. We should allocate have custom ffi_types with are allocated separately. We should allocate
them in our cifframe so we don't leak memory. Or maybe we could them in our cifframe so we don't leak memory. Or maybe we could
cache structure types? */ cache structure types? */
rtype = cifframe_type( rtype = cifframe_type([info methodReturnType], NULL);
objc_skip_type_qualifiers ([info methodReturnType]), NULL);
for (i = 0; i < numargs; i++) for (i = 0; i < numargs; i++)
{ {
arg_types[i] = cifframe_type( arg_types[i] = cifframe_type([info getArgumentTypeAtIndex: i], NULL);
objc_skip_type_qualifiers([info getArgumentTypeAtIndex: i]), NULL);
} }
if (numargs > 0) if (numargs > 0)
@ -255,39 +253,10 @@ cifframe_arg_addr(cifframe_t *cframe, int index)
ffi_type * ffi_type *
cifframe_type(const char *typePtr, const char **advance) cifframe_type(const char *typePtr, const char **advance)
{ {
BOOL flag;
const char *type; const char *type;
ffi_type *ftype; ffi_type *ftype;
/* typePtr = objc_skip_type_qualifiers (typePtr);
* Skip past any type qualifiers
*/
flag = YES;
while (flag)
{
switch (*typePtr)
{
case _C_CONST:
case _C_IN:
case _C_INOUT:
case _C_OUT:
case _C_BYCOPY:
#ifdef _C_BYREF
case _C_BYREF:
#endif
case _C_ONEWAY:
#ifdef _C_GCINVISIBLE
case _C_GCINVISIBLE:
#endif
break;
default: flag = NO;
}
if (flag)
{
typePtr++;
}
}
type = typePtr; type = typePtr;
/* /*
@ -368,6 +337,94 @@ cifframe_type(const char *typePtr, const char **advance)
const char *adv; const char *adv;
unsigned align = __alignof(double); unsigned align = __alignof(double);
/* Standard structures can be handled using cached type information.
*/
if (GSSelectorTypesMatch(typePtr, @encode(NSRange)))
{
static ffi_type *elems[3];
static ffi_type stype = { 0 };
if (stype.type == 0)
{
if (*typePtr == _C_ULNG)
{
elems[0] = &gsffi_type_ulong;
}
#ifdef _C_LNG_LNG
else if (*typePtr == _C_ULNG_LNG)
{
elems[0] = &gsffi_type_ulong_long;
}
#endif
else
{
elems[0] = &gsffi_type_uint;
}
elems[1] = elems[0];
elems[2] = 0;
stype.elements = elems;
stype.type = FFI_TYPE_STRUCT;
}
ftype = &stype;
typePtr = objc_skip_typespec (typePtr);
break;
}
else if (GSSelectorTypesMatch(typePtr, @encode(NSSize)))
{
static ffi_type *elems[3];
static ffi_type stype = { 0 };
if (stype.type == 0)
{
if (*@encode(CGFloat) == _C_DBL)
{
elems[0] = &ffi_type_double;
}
else
{
elems[0] = &ffi_type_float;
}
elems[1] = elems[0];
elems[2] = 0;
stype.elements = elems;
stype.type = FFI_TYPE_STRUCT;
}
ftype = &stype;
typePtr = objc_skip_typespec (typePtr);
break;
}
else if (GSSelectorTypesMatch(typePtr, @encode(NSRect)))
{
static ffi_type *elems[3];
static ffi_type stype = { 0 };
if (stype.type == 0)
{
/* An NSRect is an NSPoint and an NSSize, but those
* two structures are actually identical.
*/
elems[0] = cifframe_type(@encode(NSSize), NULL);
elems[1] = elems[0];
elems[2] = 0;
stype.elements = elems;
stype.type = FFI_TYPE_STRUCT;
}
ftype = &stype;
typePtr = objc_skip_typespec (typePtr);
break;
}
/*
* Skip "<name>=" stuff.
*/
while (*typePtr != _C_STRUCT_E)
{
if (*typePtr++ == '=')
{
break;
}
}
types = 0; types = 0;
maxtypes = 4; maxtypes = 4;
size = sizeof(ffi_type); size = sizeof(ffi_type);
@ -380,16 +437,6 @@ cifframe_type(const char *typePtr, const char **advance)
ftype->alignment = 0; ftype->alignment = 0;
ftype->type = FFI_TYPE_STRUCT; ftype->type = FFI_TYPE_STRUCT;
ftype->elements = (void*)ftype + size; ftype->elements = (void*)ftype + size;
/*
* Skip "<name>=" stuff.
*/
while (*typePtr != _C_STRUCT_E)
{
if (*typePtr++ == '=')
{
break;
}
}
/* /*
* Continue accumulating structure size. * Continue accumulating structure size.
*/ */