mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
rework memory management for ffi
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@30611 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
23fb22bf40
commit
4e0ef853d3
6 changed files with 58 additions and 15 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
2010-06-07 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSInvocation.h:
|
||||
* Source/GSFFIInvocation.m:
|
||||
* Source/NSInvocation.m:
|
||||
* Source/cifframe.h:
|
||||
* Source/cifframe.m:
|
||||
Rework memory management for frame used in FFI invocation so that
|
||||
the memory has a retain count and multiple invocations can use the
|
||||
same frame since it looks like the way FFI works, if you cache the
|
||||
method implementation of a proxy, the same frame memory is re-used
|
||||
in multiple invocations.
|
||||
|
||||
2010-06-07 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSFFIInvocation.m: Fix breakage caused by David's changes.
|
||||
|
|
|
@ -141,6 +141,7 @@ gs_find_by_receiver_best_typed_sel (id receiver, SEL sel)
|
|||
|
||||
static IMP gs_objc_msg_forward2 (id receiver, SEL sel)
|
||||
{
|
||||
void *frame;
|
||||
cifframe_t *cframe;
|
||||
ffi_closure *cclosure;
|
||||
NSMethodSignature *sig;
|
||||
|
@ -183,7 +184,6 @@ static IMP gs_objc_msg_forward2 (id receiver, SEL sel)
|
|||
"receiver, or you must be using an old/faulty version of the "
|
||||
"Objective-C runtime library.\n", sel_get_name(sel));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Default signature is for a method returning an object.
|
||||
*/
|
||||
|
@ -198,10 +198,15 @@ static IMP gs_objc_msg_forward2 (id receiver, SEL sel)
|
|||
NSCAssert1(sig, @"No signature for selector %@", NSStringFromSelector(sel));
|
||||
|
||||
/* Construct the frame and closure. */
|
||||
/* Note: We malloc cframe here, but it's passed to GSFFIInvocationCallback
|
||||
/* Note: We obtain cframe here, but it's passed to GSFFIInvocationCallback
|
||||
where it becomes owned by the callback invocation, so we don't have to
|
||||
worry about freeing it */
|
||||
cframe = cifframe_from_signature(sig);
|
||||
worry about ownership */
|
||||
frame = cifframe_from_signature(sig);
|
||||
#if GS_WITH_GC
|
||||
cframe = frame;
|
||||
#else
|
||||
cframe = [(NSMutableData*)frame mutableBytes];
|
||||
#endif
|
||||
/* Autorelease the closure through GSAutoreleasedBuffer */
|
||||
|
||||
memory = [GSCodeBuffer memoryWithSize: sizeof(ffi_closure)];
|
||||
|
@ -211,7 +216,7 @@ static IMP gs_objc_msg_forward2 (id receiver, SEL sel)
|
|||
[NSException raise: NSMallocException format: @"Allocating closure"];
|
||||
}
|
||||
if (ffi_prep_closure(cclosure, &(cframe->cif),
|
||||
GSFFIInvocationCallback, cframe) != FFI_OK)
|
||||
GSFFIInvocationCallback, frame) != FFI_OK)
|
||||
{
|
||||
[NSException raise: NSGenericException format: @"Preping closure"];
|
||||
}
|
||||
|
@ -328,7 +333,14 @@ static id gs_objc_proxy_lookup(id receiver, SEL op)
|
|||
_sig = RETAIN(aSignature);
|
||||
_numArgs = [aSignature numberOfArguments];
|
||||
_info = [aSignature methodInfo];
|
||||
#if GS_WITH_GC
|
||||
_frame = nil;
|
||||
_cframe = cifframe_from_signature(_sig);
|
||||
#else
|
||||
_frame = (NSMutableData*)cifframe_from_signature(_sig);
|
||||
[_frame retain];
|
||||
_cframe = [_frame mutableBytes];
|
||||
#endif
|
||||
|
||||
/* Make sure we have somewhere to store the return value if needed.
|
||||
*/
|
||||
|
@ -354,7 +366,7 @@ static id gs_objc_proxy_lookup(id receiver, SEL op)
|
|||
but we own it now so we can free it */
|
||||
- (id) initWithCallback: (ffi_cif *)cif
|
||||
values: (void **)vals
|
||||
frame: (cifframe_t *)frame
|
||||
frame: (void *)frame
|
||||
signature: (NSMethodSignature*)aSignature
|
||||
{
|
||||
cifframe_t *f;
|
||||
|
@ -363,7 +375,14 @@ static id gs_objc_proxy_lookup(id receiver, SEL op)
|
|||
_sig = RETAIN(aSignature);
|
||||
_numArgs = [aSignature numberOfArguments];
|
||||
_info = [aSignature methodInfo];
|
||||
#if GS_WITH_GC
|
||||
_frame = nil;
|
||||
_cframe = frame;
|
||||
#else
|
||||
_frame = (NSMutableData*)frame;
|
||||
[_frame retain];
|
||||
_cframe = [_frame mutableBytes];
|
||||
#endif
|
||||
f = (cifframe_t *)_cframe;
|
||||
f->cif = *cif;
|
||||
|
||||
|
@ -548,7 +567,8 @@ GSFFIInvocationCallback(ffi_cif *cif, void *retp, void **args, void *user)
|
|||
obj = *(id *)args[0];
|
||||
selector = *(SEL *)args[1];
|
||||
|
||||
if (!class_respondsToSelector(obj->class_pointer, @selector(forwardInvocation:)))
|
||||
if (!class_respondsToSelector(obj->class_pointer,
|
||||
@selector(forwardInvocation:)))
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"GSFFIInvocation: Class '%s'(%s) does not respond"
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include <Foundation/NSInvocation.h>
|
||||
|
||||
@class NSMutableData;
|
||||
|
||||
typedef struct {
|
||||
int offset;
|
||||
unsigned size;
|
||||
|
@ -39,7 +41,9 @@ typedef struct {
|
|||
|
||||
@interface GSFFIInvocation : NSInvocation
|
||||
{
|
||||
@public
|
||||
uint8_t _retbuf[32]; // Store return values of up to 32 bytes here.
|
||||
NSMutableData *_frame;
|
||||
}
|
||||
@end
|
||||
|
||||
|
|
|
@ -334,7 +334,11 @@ _arg_addr(NSInvocation *inv, int index)
|
|||
#if defined(USE_LIBFFI)
|
||||
if (_cframe)
|
||||
{
|
||||
NSZoneFree(NSDefaultMallocZone(), _cframe);
|
||||
/* If we get here then we are not using GC, so the _frame instance
|
||||
* variable points to a mutable data object containing _cframe and
|
||||
* we can release it.
|
||||
*/
|
||||
[((GSFFIInvocation*)self)->_frame release];
|
||||
}
|
||||
#elif defined(USE_FFCALL)
|
||||
if (_cframe)
|
||||
|
|
|
@ -50,7 +50,7 @@ typedef struct _cifframe_t {
|
|||
void **values;
|
||||
} cifframe_t;
|
||||
|
||||
extern cifframe_t *cifframe_from_signature (NSMethodSignature *info);
|
||||
extern void *cifframe_from_signature (NSMethodSignature *info);
|
||||
|
||||
extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer,
|
||||
int size);
|
||||
|
|
|
@ -122,13 +122,14 @@ cifframe_guess_struct_size(ffi_type *stype)
|
|||
}
|
||||
|
||||
|
||||
cifframe_t *
|
||||
void *
|
||||
cifframe_from_signature (NSMethodSignature *info)
|
||||
{
|
||||
unsigned size = sizeof(cifframe_t);
|
||||
unsigned align = __alignof(double);
|
||||
unsigned type_offset = 0;
|
||||
unsigned offset = 0;
|
||||
void *result;
|
||||
void *buf;
|
||||
int i;
|
||||
int numargs = [info numberOfArguments];
|
||||
|
@ -180,9 +181,11 @@ cifframe_from_signature (NSMethodSignature *info)
|
|||
}
|
||||
|
||||
#if GS_WITH_GC
|
||||
cframe = buf = NSAllocateCollectable(size, NSScannedOption);
|
||||
cframe = buf = result = NSAllocateCollectable(size, NSScannedOption);
|
||||
#else
|
||||
cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), size, 1);
|
||||
result = (void*)[NSMutableData dataWithCapacity: size];
|
||||
[(NSMutableData*)result setLength: size];
|
||||
cframe = buf = [(NSMutableData*)result mutableBytes];
|
||||
#endif
|
||||
|
||||
if (cframe)
|
||||
|
@ -196,8 +199,7 @@ cifframe_from_signature (NSMethodSignature *info)
|
|||
if (ffi_prep_cif (&cframe->cif, FFI_DEFAULT_ABI, cframe->nargs,
|
||||
rtype, cframe->arg_types) != FFI_OK)
|
||||
{
|
||||
objc_free(cframe);
|
||||
cframe = NULL;
|
||||
cframe = result = NULL;
|
||||
}
|
||||
|
||||
if (cframe)
|
||||
|
@ -222,7 +224,7 @@ cifframe_from_signature (NSMethodSignature *info)
|
|||
}
|
||||
}
|
||||
|
||||
return cframe;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue