Imprivemewnts to get NS_MESSAGE and NS_INVOCATION working for FFI.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@26733 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2008-06-30 05:29:19 +00:00
parent 7f1b63a68f
commit 1cc66c3501
6 changed files with 123 additions and 10 deletions

View file

@ -1,3 +1,12 @@
2008-06-30 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSFFIInvocation.m:
* Source/NSInvocation.m:
* Source/cifframe.h:
* Source/cifframe.m:
Tweaks to get NS_MESSAGE and NS_INVOCATION working on my 64bit
system.
2008-06-28 Richard Frith-Macdonald <rfm@gnu.org>
* configure.ac: Check for sys/mman.h and mprotect

View file

@ -253,23 +253,28 @@ static IMP gs_objc_msg_forward (SEL sel)
frame: (cifframe_t *)frame
signature: (NSMethodSignature*)aSignature
{
int i;
_sig = RETAIN(aSignature);
_numArgs = [aSignature numberOfArguments];
_info = [aSignature methodInfo];
_cframe = frame;
((cifframe_t *)_cframe)->cif = *cif;
/* Copy the arguments into our frame so that they are preserved
* in the NSInvocation if the stack is changed before the
* invocation is used.
*/
#if MFRAME_STRUCT_BYREF
{
int i;
/* Fix up some of the values. Do this on all processors that pass
structs by reference. Is there an automatic way to determine this? */
for (i = 0; i < ((cifframe_t *)_cframe)->nargs; i++)
{
const char *t = _info[i+1].type;
if (*t == _C_STRUCT_B || *t == _C_UNION_B || *t == _C_ARY_B)
{
/* Fix up some of the values. Do this on all processors that pass
structs by reference.
Is there an automatic way to determine this? */
memcpy(((cifframe_t *)_cframe)->values[i], *(void **)vals[i],
((cifframe_t *)_cframe)->arg_types[i]->size);
}
@ -279,14 +284,22 @@ static IMP gs_objc_msg_forward (SEL sel)
((cifframe_t *)_cframe)->arg_types[i]->size);
}
}
}
#else
((cifframe_t *)_cframe)->values = vals;
for (i = 0; i < ((cifframe_t *)_cframe)->nargs; i++)
{
memcpy(((cifframe_t *)_cframe)->values[i], vals[i],
((cifframe_t *)_cframe)->arg_types[i]->size);
}
#endif
_retval = retp;
return self;
}
- (void) _storeRetval
{
_retval = _cframe + retval_offset_from_info (_info, _numArgs);
}
/*
* This is implemented as a function so it can be used by other
* routines (like the DO forwarding)

View file

@ -43,6 +43,13 @@
#include <sys/mman.h>
#endif
@interface NSInvocation (Private)
/* Tell the invocation to store return values locally rather than writing
* themto the stack location specified when the invocation was produced
*/
- (void) _storeRetval;
@end
@implementation GSCodeBuffer
+ (GSCodeBuffer*) memoryWithSize: (unsigned)_size
@ -1147,6 +1154,7 @@ _arg_addr(NSInvocation *inv, int index)
- (void) forwardInvocation: (NSInvocation*)anInvocation
{
invocation = anInvocation;
[invocation _storeRetval];
}
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
{
@ -1161,3 +1169,10 @@ _arg_addr(NSInvocation *inv, int index)
return invocation;
}
@end
@implementation NSInvocation (Private)
- (void) _storeRetval
{
return; // subclass should implemente where necessary
}
@end

View file

@ -52,6 +52,8 @@ typedef struct _cifframe_t {
extern cifframe_t *cifframe_from_info (NSArgumentInfo *info, int numargs,
void **retval);
extern unsigned retval_offset_from_info (NSArgumentInfo *info, int numargs);
extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer,
int size);
extern void cifframe_get_arg(cifframe_t *cframe, int index, void *buffer,

View file

@ -246,6 +246,75 @@ cifframe_from_info (NSArgumentInfo *info, int numargs, void **retval)
return cframe;
}
/* NB. this must match the code in cifframe_from_info() so that it
* returns the offset for the returne value in the cframe.
*/
unsigned
retval_offset_from_info (NSArgumentInfo *info, int numargs)
{
unsigned size = sizeof(cifframe_t);
unsigned align = __alignof(double);
unsigned type_offset = 0;
unsigned offset = 0;
int i;
ffi_type *arg_types[numargs];
ffi_type *rtype;
/* FIXME: in cifframe_type, return values/arguments that are structures
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
cache structure types? */
rtype = cifframe_type(info[0].type, NULL);
if (rtype == 0 || (rtype->size == 0 && rtype->elements == NULL))
{
return 0;
}
for (i = 0; i < numargs; i++)
{
arg_types[i] = cifframe_type(info[i+1].type, NULL);
}
if (numargs > 0)
{
if (size % align != 0)
{
size += align - (size % align);
}
type_offset = size;
/* Make room to copy the arg_types */
size += sizeof(ffi_type *) * numargs;
if (size % align != 0)
{
size += align - (size % align);
}
offset = size;
size += numargs * sizeof(void*);
if (size % align != 0)
{
size += (align - (size % align));
}
for (i = 0; i < numargs; i++)
{
if (arg_types[i]->elements)
size += cifframe_guess_struct_size(arg_types[i]);
else
size += arg_types[i]->size;
if (size % align != 0)
{
size += (align - size % align);
}
}
}
if (size % align != 0)
{
size += (align - size % align);
}
return size;
}
void
cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size)
{

View file

@ -14,6 +14,8 @@
#include <Foundation/NSAutoreleasePool.h>
#include <Foundation/NSArchiver.h>
static int loop_int_result;
typedef struct {
char c;
int i;
@ -78,6 +80,7 @@ typedef struct {
}
- (int) loopInt: (int)v
{
loop_int_result = v+1;
return v+1;
}
- (large) loopLarge: (large)v
@ -255,22 +258,24 @@ printf("Calling proxy\n");
printf("Testing NS_MESSAGE ... ");
inv = NS_MESSAGE(t, loopInt: 5);
loop_int_result = 0;
[inv invoke];
[inv getReturnValue: &i];
if (i == 6)
if (i == 6 && loop_int_result == 6)
printf("OK\n");
else
printf("ERROR ... expecting 6 and got %d\n", i);
printf("ERROR ... expecting 6,6 and got %d,%d\n", i, loop_int_result);
printf("Testing NS_INVOCATION ... ");
inv = NS_INVOCATION([Target class], loopInt: 7);
[inv setTarget: t];
loop_int_result = 0;
[inv invoke];
[inv getReturnValue: &i];
if (i == 8)
if (i == 8 && loop_int_result == 8)
printf("OK\n");
else
printf("ERROR ... expecting 8 and got %d\n", i);
printf("ERROR ... expecting 8,8 and got %d,%d\n", i, loop_int_result);
#define SETUP(X) \
sig = [t methodSignatureForSelector: @selector(X)]; \