diff --git a/ChangeLog b/ChangeLog index c0fc56027..bee5b0351 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2009-10-04 Richard Frith-Macdonald + + * Source/GNUmakefile: + * Source/NSMethodSignature.m: + * Source/GSFFCallInvocation.m: + * Source/mframe/mframe.head: + * Source/GSFFIInvocation.m: + * Source/NSInvocation.m: + * Source/cifframe.h: + * Source/mframe.m: + * Source/cifframe.m: + * Source/NSConnection.m: + * Source/callframe.h: + * Source/NSObjCRuntime.m: + * Source/callframe.m: + * Headers/Additions/GNUstepBase/DistributedObjects.h: + * Headers/Additions/GNUstepBase/preface.h.in: + Remove lots of obsolete code as part of the ong term process of + scrapping the old mframe stuff. + 2009-10-04 Richard Frith-Macdonald * Source/cifframe.h: Remove unused code diff --git a/Headers/Additions/GNUstepBase/DistributedObjects.h b/Headers/Additions/GNUstepBase/DistributedObjects.h index bde3406ae..4df605ed6 100644 --- a/Headers/Additions/GNUstepBase/DistributedObjects.h +++ b/Headers/Additions/GNUstepBase/DistributedObjects.h @@ -88,24 +88,4 @@ enum { - (id) conversation: (NSPort*)receivePort; @end -/* - * A structure for passing context information using in encoding/decoding - * arguments for DO - */ -typedef struct { - const char *type; // The type of the data - int flags; // Type qualifier flags - void *datum; // Where to get/store data - NSConnection *connection; // The connection in use - NSPortCoder *decoder; // The coder to use - NSPortCoder *encoder; // The coder to use - unsigned seq; // Sequence number - /* - * These next fields can store allocated memory that will need to be - * tidied up iff an exception occurs before they can be tidied normally. - */ - void *datToFree; // Data needing NSZoneFree() - id objToFree; // Data needing NSDeallocateObject() -} DOContext; - #endif /* __DistributedObjects_h */ diff --git a/Headers/Additions/GNUstepBase/objc-gnu2next.h b/Headers/Additions/GNUstepBase/objc-gnu2next.h deleted file mode 100644 index 69e5611af..000000000 --- a/Headers/Additions/GNUstepBase/objc-gnu2next.h +++ /dev/null @@ -1,294 +0,0 @@ -/* Definitions to allow compilation of GNU objc code with NeXT runtime - and the reverse. - - Copyright (C) 1993,1994,1996,2003 Free Software Foundation, Inc. - - Written by: Andrew Kachites McCallum - Date: May 1993 - - This file is part of the GNUstep Base Library. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. -*/ - -/* This file is by no means complete. */ - -#ifndef __objc_gnu2next_h_GNUSTEP_BASE_INCLUDE -#define __objc_gnu2next_h_GNUSTEP_BASE_INCLUDE - -#if defined(__cplusplus) -extern "C" { -#endif - -#if NeXT_RUNTIME - -#include -#include -#include -#include -#include - -/* Disable builtin functions for gcc < 3.x since it triggers a bad bug - (even some 3.x versions may have this bug). */ -#if __GNUC__ < 3 -#define __builtin_apply(a,b,c) 0 -#define __builtin_apply_args() 0 -#define __builtin_return(a) 0 -#endif - -typedef union { - char *arg_ptr; - char arg_regs[sizeof (char*)]; -} *arglist_t; /* argument frame */ -//#define arglist_t marg_list -#define retval_t void* -typedef void(*apply_t)(void); /* function pointer */ -#define TypedStream void* - -#define METHOD_NULL (struct objc_method *)0 - -#define _CLS_META CLS_META -#define _CLS_CLASS CLS_CLASS - -#define class_pointer isa -typedef struct objc_super Super; - -#define class_create_instance(CLASS) class_createInstance(CLASS, 0) -#define class_get_instance_method class_getInstanceMethod -#define class_add_method_list class_addMethods -#define class_set_version class_setVersion -#define class_get_version class_getVersion -#define class_pose_as class_poseAs -#define method_get_sizeof_arguments method_getSizeOfArguments -#define objc_lookup_class objc_lookUpClass -#define objc_get_class objc_getClass - -#define sel_register_name sel_registerName -#define sel_is_mapped sel_isMapped -#define sel_get_name sel_getName -#define sel_get_any_uid sel_getUid -#define sel_get_uid sel_getUid -#define sel_eq(s1, s2) (s1 == s2) - -#define __objc_update_dispatch_table_for_class _objc_flush_caches - -/* There's no support for typed sels in NeXT. These may not work */ -#define sel_get_typed_uid(_s, _t) sel_getUid(_s) -#define sel_get_any_typed_uid sel_getUid -#define sel_register_typed_name(_s, _t) sel_registerName(_s) -#define sel_get_type(_s) (NULL) - -#define class_get_class_name(CLASSPOINTER) \ - (((struct objc_class*)(CLASSPOINTER))->name) -#define object_get_class(OBJECT) \ - (((struct objc_class*)(OBJECT))->isa) -#define class_get_super_class(CLASSPOINTER) \ - (((struct objc_class*)(CLASSPOINTER))->super_class) -#define object_get_super_class(OBJECT) \ - (((struct objc_class*)(object_get_class(OBJECT)))->super_class) -#define object_get_class_name(OBJECT) \ - (((struct objc_class*)(object_get_class(OBJECT)))->name) - -#define __objc_responds_to(OBJECT,SEL) \ - (class_getInstanceMethod(object_get_class(OBJECT), SEL) != METHOD_NULL) -#define CLS_ISCLASS(CLASSPOINTER) \ - ((((struct objc_class*)(CLASSPOINTER))->info) & CLS_CLASS) -#define CLS_ISMETA(CLASSPOINTER) \ - ((((struct objc_class*)(CLASSPOINTER))->info) & CLS_META) -#define objc_msg_lookup(OBJ,SEL) \ - (class_getInstanceMethod(object_get_class(OBJ), SEL)->method_imp) -#define objc_msg_lookup_super(OBJ,SEL) \ - (class_getInstanceMethod(object_get_class(OBJ), SEL)->method_imp) - -#define objc_msg_sendv next_objc_msg_sendv - -extern id next_objc_msg_sendv(id self, SEL op, void* arg_frame); - -#define OBJC_READONLY 1 -#define OBJC_WRITEONLY 2 - -/* -** Standard functions for memory allocation and disposal. -** Users should use these functions in their ObjC programs so -** that they work properly with garbage collectors as well as -** can take advantage of the exception/error handling available. -*/ -void * -objc_malloc(size_t size); - -void * -objc_atomic_malloc(size_t size); - -void * -objc_valloc(size_t size); - -void * -objc_realloc(void *mem, size_t size); - -void * -objc_calloc(size_t nelem, size_t size); - -void -objc_free(void *mem); - -static inline BOOL -class_is_class(Class class) -{ - return CLS_ISCLASS(class); -} - -static inline BOOL -object_is_class(id object) -{ - return CLS_ISCLASS((Class)object); -} - -static inline long -class_get_instance_size(Class class) -{ - return CLS_ISCLASS(class)?class->instance_size:0; -} - -static inline IMP -method_get_imp(Method method) -{ - return (method!=0)?method->method_imp:(IMP)0; -} - -static inline IMP -get_imp(Class class, SEL aSel) -{ - return method_get_imp(class_getInstanceMethod(class, aSel)); -} - -static inline BOOL -object_is_instance(id object) -{ - return (object!=nil)&&CLS_ISCLASS(object->class_pointer); -} - -/* -** Hook functions for memory allocation and disposal. -** This makes it easy to substitute garbage collection systems -** such as Boehm's GC by assigning these function pointers -** to the GC's allocation routines. By default these point -** to the ANSI standard malloc, realloc, free, etc. -** -** Users should call the normal objc routines above for -** memory allocation and disposal within their programs. -*/ -extern void *(*_objc_malloc)(size_t); -extern void *(*_objc_atomic_malloc)(size_t); -extern void *(*_objc_valloc)(size_t); -extern void *(*_objc_realloc)(void *, size_t); -extern void *(*_objc_calloc)(size_t, size_t); -extern void (*_objc_free)(void *); - - -/* threading functions */ -typedef void *objc_mutex_t; - -objc_mutex_t objc_mutex_allocate (void); -int objc_mutex_deallocate (objc_mutex_t mutex); -int objc_mutex_lock (objc_mutex_t mutex); -int objc_mutex_unlock (objc_mutex_t mutex); -int objc_mutex_trylock (objc_mutex_t mutex); - -/* encoding functions */ -extern int objc_sizeof_type(const char* type); -extern int objc_alignof_type(const char* type); -extern int objc_aligned_size (const char* type); -extern int objc_promoted_size (const char* type); -extern const char *objc_skip_type_qualifiers (const char* type); -extern const char *objc_skip_typespec (const char* type); -extern const char *objc_skip_argspec (const char* type); -extern unsigned objc_get_type_qualifiers (const char* type); -extern BOOL sel_types_match (const char* t1, const char* t2); - -/* Error handling */ -extern void objc_error(id object, int code, const char* fmt, ...); -extern void objc_verror(id object, int code, const char* fmt, va_list ap); -typedef BOOL (*objc_error_handler)(id, int code, const char *fmt, va_list ap); -objc_error_handler objc_set_error_handler(objc_error_handler func); - -/* -** Error codes -** These are used by the runtime library, and your -** error handling may use them to determine if the error is -** hard or soft thus whether execution can continue or abort. -*/ -#define OBJC_ERR_UNKNOWN 0 /* Generic error */ - -#define OBJC_ERR_OBJC_VERSION 1 /* Incorrect runtime version */ -#define OBJC_ERR_GCC_VERSION 2 /* Incorrect compiler version */ -#define OBJC_ERR_MODULE_SIZE 3 /* Bad module size */ -#define OBJC_ERR_PROTOCOL_VERSION 4 /* Incorrect protocol version */ - -#define OBJC_ERR_MEMORY 10 /* Out of memory */ - -#define OBJC_ERR_RECURSE_ROOT 20 /* Attempt to archive the root - object more than once. */ -#define OBJC_ERR_BAD_DATA 21 /* Didn't read expected data */ -#define OBJC_ERR_BAD_KEY 22 /* Bad key for object */ -#define OBJC_ERR_BAD_CLASS 23 /* Unknown class */ -#define OBJC_ERR_BAD_TYPE 24 /* Bad type specification */ -#define OBJC_ERR_NO_READ 25 /* Cannot read stream */ -#define OBJC_ERR_NO_WRITE 26 /* Cannot write stream */ -#define OBJC_ERR_STREAM_VERSION 27 /* Incorrect stream version */ -#define OBJC_ERR_BAD_OPCODE 28 /* Bad opcode */ - -#define OBJC_ERR_UNIMPLEMENTED 30 /* Method is not implemented */ - -#define OBJC_ERR_BAD_STATE 40 /* Bad thread state */ - -#else /* NeXT_RUNTIME */ - -/* - * And to use the GNU runtime from old NeXT code ... - */ -#define class_createInstance(CLASS, X) class_create_instance(CLASS) -#define class_getInstanceMethod class_get_instance_method -#define class_addMethods class_add_method_list -#define class_setVersion class_set_version -#define class_getVersion class_get_version -#define class_poseAs class_pose_as -#define method_getSizeOfArguments method_get_sizeof_arguments -#define objc_lookUpClass objc_lookup_class -#define objc_getClass objc_get_class - -#define sel_registerName sel_register_name -#define sel_isMapped sel_is_mapped -#define sel_getName sel_get_name -#define sel_getUid sel_get_any_uid - -#define _objc_flush_caches __objc_update_dispatch_table_for_class - -#define class_getClassMethod(CLASS, SEL) \ - class_get_class_method((CLASS)->class_pointer, (SEL)) - -#define class_nextMethodList(aClass,anIterator) (({\ - if (*(anIterator) == 0) \ - *((struct objc_method_list**)(anIterator)) = (aClass)->methods; \ - else \ - *(anIterator) = (*((struct objc_method_list**)(anIterator)))->method_next; \ -}), *(anIterator)) - -#endif /* NeXT_RUNTIME */ - -#if defined(__cplusplus) -} -#endif - -#endif /* __objc_gnu2next_h_GNUSTEP_BASE_INCLUDE */ diff --git a/Headers/Additions/GNUstepBase/preface.h.in b/Headers/Additions/GNUstepBase/preface.h.in index d9f53cc36..aaba15cef 100644 --- a/Headers/Additions/GNUstepBase/preface.h.in +++ b/Headers/Additions/GNUstepBase/preface.h.in @@ -27,7 +27,6 @@ #include #include -#include #if defined(__WIN32__) || defined(_WIN32) || defined(__MS_WIN32__) #ifndef __WIN32__ diff --git a/Source/GNUmakefile b/Source/GNUmakefile index b3cc1cf82..cac9b0f42 100644 --- a/Source/GNUmakefile +++ b/Source/GNUmakefile @@ -103,12 +103,6 @@ ifeq ($(findstring openbsd, $(GNUSTEP_TARGET_OS)), openbsd) OBJC_LIBS += -lpthread endif -ifneq ($(OBJC_RUNTIME_LIB), gnu) - ifneq ($(OBJC_RUNTIME_LIB), gnugc) - GNU_MFILES += objc-gnu2next.m - endif -endif - ifeq ($(GNUSTEP_TARGET_OS), mingw32) GNU_MFILES += libgnustep-base-entry.m endif @@ -142,7 +136,6 @@ Unicode.h \ GNUstep.h \ behavior.h \ preface.h \ -objc-gnu2next.h \ GNU_HEADERS = $(ADD_HEADERS) diff --git a/Source/GSFFCallInvocation.m b/Source/GSFFCallInvocation.m index cc9cd0b9a..a9b0050b6 100644 --- a/Source/GSFFCallInvocation.m +++ b/Source/GSFFCallInvocation.m @@ -546,7 +546,7 @@ static IMP gs_objc_msg_forward (SEL sel) _sig = RETAIN(aSignature); _numArgs = [aSignature numberOfArguments]; _info = [aSignature methodInfo]; - _cframe = callframe_from_info(_info, _numArgs, &_retval); + _cframe = callframe_from_signature(_sig, &_retval); return self; } diff --git a/Source/GSFFIInvocation.m b/Source/GSFFIInvocation.m index d6bbcceee..b8d0227ad 100644 --- a/Source/GSFFIInvocation.m +++ b/Source/GSFFIInvocation.m @@ -191,7 +191,7 @@ static IMP gs_objc_msg_forward2 (id receiver, SEL sel) /* Note: We malloc 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_info([sig methodInfo], [sig numberOfArguments], 0); + cframe = cifframe_from_signature(sig); /* Autorelease the closure through GSAutoreleasedBuffer */ memory = [GSCodeBuffer memoryWithSize: sizeof(ffi_closure)]; @@ -312,7 +312,7 @@ static id gs_objc_proxy_lookup(id receiver, SEL op) _sig = RETAIN(aSignature); _numArgs = [aSignature numberOfArguments]; _info = [aSignature methodInfo]; - _cframe = cifframe_from_info(_info, _numArgs, 0); + _cframe = cifframe_from_signature(_sig); /* Make sure we have somewhere to store the return value if needed. */ diff --git a/Source/NSConnection.m b/Source/NSConnection.m index 446fdc331..792b6347b 100644 --- a/Source/NSConnection.m +++ b/Source/NSConnection.m @@ -66,7 +66,6 @@ static GC_descr nodeDesc; // Type descriptor for map node. #include "Foundation/NSConnection.h" #undef _IN_CONNECTION_M -#include #if defined(USE_LIBFFI) #include "cifframe.h" #elif defined(USE_FFCALL) @@ -1972,7 +1971,7 @@ static NSLock *cached_proxies_gate = nil; BOOL outParams; BOOL needsResponse; const char *type; - DOContext ctxt; + unsigned seq; NSRunLoop *runLoop = GSRunLoopForThread(nil); if ([IrunLoops indexOfObjectIdenticalTo: runLoop] == NSNotFound) @@ -2005,13 +2004,10 @@ static NSLock *cached_proxies_gate = nil; NSParameterAssert(type); NSParameterAssert(*type); - memset(&ctxt, 0, sizeof(ctxt)); - ctxt.connection = self; - - op = [self _makeOutRmc: 0 generate: (int*)&ctxt.seq reply: YES]; + op = [self _makeOutRmc: 0 generate: (int*)&seq reply: YES]; if (debug_connection > 4) - NSLog(@"building packet seq %d", ctxt.seq); + NSLog(@"building packet seq %d", seq); [inv setTarget: object]; outParams = [inv encodeWithDistantCoder: op passPointers: NO]; @@ -2043,7 +2039,7 @@ static NSLock *cached_proxies_gate = nil; [self _sendOutRmc: op type: METHOD_REQUEST]; NSDebugMLLog(@"NSConnection", @"Sent message %s RMC %d to 0x%x", - GSNameFromSelector([inv selector]), ctxt.seq, (uintptr_t)self); + GSNameFromSelector([inv selector]), seq, (uintptr_t)self); if (needsResponse == NO) { @@ -2055,7 +2051,7 @@ static NSLock *cached_proxies_gate = nil; * a response, we must check for it and scrap it if necessary. */ M_LOCK(IrefGate); - node = GSIMapNodeForKey(IreplyMap, (GSIMapKey)ctxt.seq); + node = GSIMapNodeForKey(IreplyMap, (GSIMapKey)seq); if (node != 0 && node->value.obj != dummyObject) { BOOL is_exception = NO; @@ -2069,7 +2065,7 @@ static NSLock *cached_proxies_gate = nil; NSLog(@"Got response with %@", NSStringFromSelector(sel)); [self _doneInRmc: node->value.obj]; } - GSIMapRemoveKey(IreplyMap, (GSIMapKey)ctxt.seq); + GSIMapRemoveKey(IreplyMap, (GSIMapKey)seq); M_UNLOCK(IrefGate); } else @@ -2086,7 +2082,7 @@ static NSLock *cached_proxies_gate = nil; [NSException raise: NSGenericException format: @"connection waiting for request was shut down"]; } - aRmc = [self _getReplyRmc: ctxt.seq]; + aRmc = [self _getReplyRmc: seq]; /* * Find out if the server is returning an exception instead @@ -2483,11 +2479,10 @@ static NSLock *cached_proxies_gate = nil; - (void) _service_forwardForProxy: (NSPortCoder*)aRmc { char *forward_type = 0; - DOContext ctxt; - - memset(&ctxt, 0, sizeof(ctxt)); - ctxt.connection = self; - ctxt.decoder = aRmc; + NSPortCoder *decoder = nil; + NSPortCoder *encoder = nil; + NSInvocation *inv = nil; + unsigned seq; /* * Make sure don't let exceptions caused by servicing the client's @@ -2495,7 +2490,20 @@ static NSLock *cached_proxies_gate = nil; */ NS_DURING { - NSRunLoop *runLoop = GSRunLoopForThread(nil); + NSRunLoop *runLoop = GSRunLoopForThread(nil); + const char *type; + const char *tmptype; + const char *etmptype; + id tmp; + id object; + SEL selector; + GSMethod meth = 0; + BOOL is_exception = NO; + unsigned flags; + int argnum; + BOOL out_parameters = NO; + NSMethodSignature *sig; + const char *encoded_types = forward_type; NSParameterAssert (IisValid); if ([IrunLoops indexOfObjectIdenticalTo: runLoop] == NSNotFound) @@ -2512,7 +2520,7 @@ static NSLock *cached_proxies_gate = nil; } /* Save this for later */ - [aRmc decodeValueOfObjCType: @encode(int) at: &ctxt.seq]; + [aRmc decodeValueOfObjCType: @encode(int) at: &seq]; /* * Get the types that we're using, so that we know @@ -2522,51 +2530,25 @@ static NSLock *cached_proxies_gate = nil; * to do this. */ [aRmc decodeValueOfObjCType: @encode(char*) at: &forward_type]; - ctxt.type = forward_type; if (debug_connection > 1) NSLog( @"Handling message (sig %s) RMC %d from %@", - ctxt.type, ctxt.seq, (uintptr_t)self); + forward_type, seq, (uintptr_t)self); IreqInCount++; /* Handling an incoming request. */ - { - /* The method type string obtained from the target's OBJC_METHOD - structure for the selector we're sending. */ - const char *type; - /* A pointer into the local variable TYPE string. */ - const char *tmptype; - /* A pointer into the argument ENCODED_TYPES string. */ - const char *etmptype; - /* The target object that will receive the message. */ - id object; - /* The selector for the message we're sending to the TARGET. */ - SEL selector; - /* The OBJECT's Method(_t) pointer for the SELECTOR. */ - GSMethod meth = 0; - BOOL is_exception = NO; - /* Type qualifier flags; see . */ - unsigned flags; - /* Which argument number are we processing now? */ - int argnum; - /* Does the method have any arguments that are passed by reference? - If so, we need to encode them, since the method may have changed them. */ - BOOL out_parameters = NO; - NSInvocation *inv; - /* Signature information */ - NSMethodSignature *sig; - const char *encoded_types = forward_type; + encoded_types = forward_type; etmptype = encoded_types; - ctxt.encoder = aRmc; + decoder = aRmc; /* Decode the object, (which is always the first argument to a method). */ - [aRmc decodeValueOfObjCType: @encode(id) at: &object]; + [decoder decodeValueOfObjCType: @encode(id) at: &object]; - /* Decode the selector, (which is always the second argument to a method). */ + /* Decode the selector, (which is the second argument to a method). */ /* xxx @encode(SEL) produces "^v" in gcc 2.5.8. It should be ":" */ - [aRmc decodeValueOfObjCType: @encode(SEL) at: &selector]; + [decoder decodeValueOfObjCType: @encode(SEL) at: &selector]; /* Get the "selector type" for this method. The "selector type" is a string that lists the return and argument types, and also @@ -2617,7 +2599,6 @@ static NSLock *cached_proxies_gate = nil; sig = [NSMethodSignature signatureWithObjCTypes: type]; inv = [[NSInvocation alloc] initWithMethodSignature: sig]; - ctxt.objToFree = inv; tmptype = objc_skip_argspec (type); etmptype = objc_skip_argspec (etmptype); @@ -2674,7 +2655,7 @@ static NSLock *cached_proxies_gate = nil; if ((flags & _F_IN) || !(flags & _F_OUT)) { datum = alloca (sizeof(char*)); - [aRmc decodeValueOfObjCType: tmptype at: datum]; + [decoder decodeValueOfObjCType: tmptype at: datum]; [inv setArgument: datum atIndex: argnum]; } break; @@ -2699,7 +2680,7 @@ static NSLock *cached_proxies_gate = nil; if ((flags & _F_IN) || !(flags & _F_OUT)) { datum = alloca (objc_sizeof_type (tmptype)); - [aRmc decodeValueOfObjCType: tmptype at: datum]; + [decoder decodeValueOfObjCType: tmptype at: datum]; [inv setArgument: &datum atIndex: argnum]; } break; @@ -2708,11 +2689,11 @@ static NSLock *cached_proxies_gate = nil; datum = alloca (objc_sizeof_type (tmptype)); if (*tmptype == _C_ID) { - *(id*)datum = [aRmc decodeObject]; + *(id*)datum = [decoder decodeObject]; } else { - [aRmc decodeValueOfObjCType: tmptype at: datum]; + [decoder decodeValueOfObjCType: tmptype at: datum]; } [inv setArgument: datum atIndex: argnum]; } @@ -2720,8 +2701,9 @@ static NSLock *cached_proxies_gate = nil; /* Stop using the decoder. */ - [self _doneInRmc: aRmc]; - ctxt.decoder = nil; + tmp = decoder; + decoder = nil; + [self _doneInRmc: tmp]; /* Invoke the method! */ [inv invoke]; @@ -2732,6 +2714,9 @@ static NSLock *cached_proxies_gate = nil; */ if ([self isValid] == NO) { + tmp = inv; + inv = nil; + [tmp release]; return; } @@ -2739,9 +2724,8 @@ static NSLock *cached_proxies_gate = nil; * later use if/when we are called again. We encode a flag to * say that this is not an exception. */ - aRmc = [self _makeOutRmc: ctxt.seq generate: 0 reply: NO]; - ctxt.encoder = aRmc; - [aRmc encodeValueOfObjCType: @encode(BOOL) at: &is_exception]; + encoder = [self _makeOutRmc: seq generate: 0 reply: NO]; + [encoder encodeValueOfObjCType: @encode(BOOL) at: &is_exception]; /* Encode the return value and pass-by-reference values, if there are any. This logic must match exactly that in @@ -2765,7 +2749,7 @@ static NSLock *cached_proxies_gate = nil; { int dummy = 0; - [aRmc encodeValueOfObjCType: @encode(int) at: (void*)&dummy]; + [encoder encodeValueOfObjCType: @encode(int) at: (void*)&dummy]; } /* No return value to encode; do nothing. */ } @@ -2785,7 +2769,7 @@ static NSLock *cached_proxies_gate = nil; datum = alloca (objc_sizeof_type (tmptype)); } [inv getReturnValue: datum]; - [aRmc encodeValueOfObjCType: tmptype at: datum]; + [encoder encodeValueOfObjCType: tmptype at: datum]; } @@ -2827,22 +2811,23 @@ static NSLock *cached_proxies_gate = nil; it is a pass-by-reference argument.*/ ++tmptype; [inv getArgument: &datum atIndex: argnum]; - [aRmc encodeValueOfObjCType: tmptype at: datum]; + [encoder encodeValueOfObjCType: tmptype at: datum]; } else if (*tmptype == _C_CHARPTR) { datum = alloca (sizeof (char*)); [inv getArgument: datum atIndex: argnum]; - [aRmc encodeValueOfObjCType: tmptype at: datum]; + [encoder encodeValueOfObjCType: tmptype at: datum]; } } } } - ctxt.objToFree = nil; - [inv release]; - [self _sendOutRmc: aRmc type: METHOD_REPLY]; - ctxt.encoder = nil; - } + tmp = inv; + inv = nil; + [tmp release]; + tmp = encoder; + encoder = nil; + [self _sendOutRmc: tmp type: METHOD_REPLY]; } NS_HANDLER { @@ -2858,25 +2843,19 @@ static NSLock *cached_proxies_gate = nil; { NSPortCoder *op; - if (ctxt.datToFree != 0) + if (inv != nil) { - NSZoneFree(NSDefaultMallocZone(), ctxt.datToFree); - ctxt.datToFree = 0; + [inv release]; } - if (ctxt.objToFree != nil) + if (decoder != nil) { - NSDeallocateObject(ctxt.objToFree); - ctxt.objToFree = nil; + [self _failInRmc: decoder]; } - if (ctxt.decoder != nil) + if (encoder != nil) { - [self _failInRmc: ctxt.decoder]; + [self _failOutRmc: encoder]; } - if (ctxt.encoder != nil) - { - [self _failOutRmc: ctxt.encoder]; - } - op = [self _makeOutRmc: ctxt.seq generate: 0 reply: NO]; + op = [self _makeOutRmc: seq generate: 0 reply: NO]; [op encodeValueOfObjCType: @encode(BOOL) at: &is_exception]; [op encodeBycopyObject: localException]; diff --git a/Source/NSInvocation.m b/Source/NSInvocation.m index 8734f1095..68e664e9a 100644 --- a/Source/NSInvocation.m +++ b/Source/NSInvocation.m @@ -32,7 +32,6 @@ #include "GSInvocation.h" #include "config.h" #include "GSPrivate.h" -#include #if defined(USE_LIBFFI) #include "cifframe.h" #elif defined(USE_FFCALL) @@ -228,22 +227,21 @@ _arg_addr(NSInvocation *inv, int index) } #else + static inline void _get_arg(NSInvocation *inv, int index, void *buffer) { - mframe_get_arg((arglist_t)inv->_cframe, &inv->_info[index+1], buffer); } static inline void _set_arg(NSInvocation *inv, int index, void *buffer) { - mframe_set_arg((arglist_t)inv->_cframe, &inv->_info[index+1], buffer); } static inline void * _arg_addr(NSInvocation *inv, int index) { - return mframe_arg_addr((arglist_t)inv->_cframe, &inv->_info[index+1]); + return 0; } #endif @@ -270,7 +268,7 @@ _arg_addr(NSInvocation *inv, int index) #elif defined(USE_FFCALL) NSInvocation_concrete_class = [GSFFCallInvocation class]; #else - NSInvocation_concrete_class = [GSFrameInvocation class]; + NSInvocation_concrete_class = [GSDummyInvocation class]; #endif } } @@ -306,14 +304,17 @@ _arg_addr(NSInvocation *inv, int index) { if (*_info[i].type == _C_CHARPTR) { - char *str; + char *str = 0; _get_arg(self, i-1, &str); - NSZoneFree(NSDefaultMallocZone(), str); + if (str != 0) + { + NSZoneFree(NSDefaultMallocZone(), str); + } } else if (*_info[i].type == _C_ID) { - id obj; + id obj = nil; _get_arg(self, i-1, &obj); RELEASE(obj); @@ -335,15 +336,6 @@ _arg_addr(NSInvocation *inv, int index) { NSZoneFree(NSDefaultMallocZone(), _cframe); } -#else - if (_cframe) - { - mframe_destroy_argframe([_sig methodType], (arglist_t)_cframe); - } - if (_retval) - { - NSZoneFree(NSDefaultMallocZone(), _retval); - } #endif if (_retptr) { @@ -400,17 +392,7 @@ _arg_addr(NSInvocation *inv, int index) if (*_info[0].type != _C_VOID) { - int length = _info[0].size; -#if !defined(USE_LIBFFI) && !defined(USE_FFCALL) -/* NOTE: This won't work unless -[NSMethodSignature methodReturnLength] - is also changed, but since mframe is depreciated, this should all - be removed in the near future anyway... */ -#if WORDS_BIGENDIAN - if (length < sizeof(void*)) - length = sizeof(void*); -#endif -#endif - memcpy(buffer, _retval, length); + memcpy(buffer, _retval, _info[0].size); } } @@ -512,18 +494,7 @@ _arg_addr(NSInvocation *inv, int index) if (*type != _C_VOID) { - int length = _info[0].size; - -#if !defined(USE_LIBFFI) && !defined(USE_FFCALL) -/* NOTE: This won't work unless -[NSMethodSignature methodReturnLength] - is also changed, but since mframe is depreciated, this should all - be removed in the near future anyway... */ -#if WORDS_BIGENDIAN - if (length < sizeof(void*)) - length = sizeof(void*); -#endif -#endif - memcpy(_retval, buffer, length); + memcpy(_retval, buffer, _info[0].size); } RETAIN_RETURN_VALUE; @@ -678,7 +649,7 @@ _arg_addr(NSInvocation *inv, int index) GSClassNameFromObject(self), \ self, \ _selector ? GSNameFromSelector(_selector) : "nil", \ - _target ? GSNameFromClass([_target class]) : "nil" \ + _target ? GSNameFromClass([_target class]) : "nil" \ ); return [NSString stringWithUTF8String: buffer]; @@ -708,14 +679,6 @@ _arg_addr(NSInvocation *inv, int index) { [aCoder encodeObject: *(id*)datum]; } -#if !defined(USE_LIBFFI) && !defined(USE_FFCALL) -#if MFRAME_STRUCT_BYREF - else if (*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B) - { - [aCoder encodeValueOfObjCType: type at: *(void**)datum]; - } -#endif -#endif else { [aCoder encodeValueOfObjCType: type at: datum]; @@ -752,18 +715,6 @@ _arg_addr(NSInvocation *inv, int index) for (i = 3; i <= _numArgs; i++) { datum = _arg_addr(self, i-1); -#if !defined(USE_LIBFFI) && !defined(USE_FFCALL) -#if MFRAME_STRUCT_BYREF - { - const char *t = _info[i].type; - if (*t == _C_STRUCT_B || *t == _C_UNION_B || *t == _C_ARY_B) - { - *(void**)datum = GSAutoreleasedBuffer(_info[i].size); - datum = *(void**)datum; - } - } -#endif -#endif [aCoder decodeValueOfObjCType: _info[i].type at: datum]; } _argsRetained = YES; @@ -894,29 +845,11 @@ _arg_addr(NSInvocation *inv, int index) @end #if !defined(USE_FFCALL) && !defined(USE_LIBFFI) -#warning Using unreliable NSInvocation implementation. It is strongly recommended that you use libffi. -@implementation GSFrameInvocation +#warning Using dummy NSInvocation implementation. It is strongly recommended that you use libffi. +@implementation GSDummyInvocation - (id) initWithArgframe: (arglist_t)frame selector: (SEL)aSelector { - self = [self initWithSelector: aSelector]; - if (self) - { - [self setSelector: aSelector]; - /* - * Copy the _cframe we were given. - */ - if (frame) - { - unsigned int i; - - mframe_get_arg(frame, &_info[1], &_target); - for (i = 1; i <= _numArgs; i++) - { - mframe_cpy_arg((arglist_t)_cframe, frame, &_info[i]); - } - } - } return self; } @@ -925,104 +858,26 @@ _arg_addr(NSInvocation *inv, int index) */ - (id) initWithMethodSignature: (NSMethodSignature*)aSignature { - if (aSignature == nil) - { - RELEASE(self); - return nil; - } - _sig = RETAIN(aSignature); - _numArgs = [aSignature numberOfArguments]; - _info = [aSignature methodInfo]; - _cframe = mframe_create_argframe([_sig methodType], &_retval); - if (_retval == 0 && _info[0].size > 0) - { - _retval = NSZoneMalloc(NSDefaultMallocZone(), _info[0].size); - } return self; } -- (void)invokeWithTarget: (id)anObject + +- (void) invokeWithTarget: (id)anObject { - id old_target; - retval_t returned; - IMP imp; - int stack_argsize; - - CLEAR_RETURN_VALUE_IF_OBJECT; _validReturn = NO; - /* * A message to a nil object returns nil. */ if (anObject == nil) { _validReturn = YES; - memset(_retval, '\0', _info[0].size); /* Clear return value */ return; } - - NSAssert(_selector != 0, @"you must set the selector before invoking"); - - /* - * Temporarily set new target and copy it (and the selector) into the - * _cframe. - */ - old_target = RETAIN(_target); - [self setTarget: anObject]; - - _set_arg(self, 0, &_target); - _set_arg(self, 1, &_selector); - - if (_sendToSuper == YES) - { - Super s; - -#ifndef NeXT_RUNTIME - s.self = _target; -#else - s.receiver = _target; -#endif - if (GSObjCIsInstance(_target)) - s.class = GSObjCSuper(GSObjCClass(_target)); - else - s.class = GSObjCSuper((Class)_target); - imp = objc_msg_lookup_super(&s, _selector); - } - else - { - GSMethod method; - method = GSGetMethod((GSObjCIsInstance(_target) - ? (id)GSObjCClass(_target) - : (id)_target), - _selector, - GSObjCIsInstance(_target), - YES); - imp = method_get_imp(method); - /* - * If fast lookup failed, we may be forwarding or something ... - */ - if (imp == 0) - imp = objc_msg_lookup(_target, _selector); - } - [self setTarget: old_target]; - RELEASE(old_target); - - stack_argsize = [_sig frameLength]; - - returned = __builtin_apply((void(*)(void))imp, - (arglist_t)_cframe, stack_argsize); - if (_info[0].size) - { - mframe_decode_return(_info[0].type, _retval, returned); - } - - RETAIN_RETURN_VALUE; - _validReturn = YES; } - (void*) returnFrame: (arglist_t)argFrame { - return mframe_handle_return(_info[0].type, _retval, argFrame); + return 0; } @end #endif diff --git a/Source/NSMethodSignature.m b/Source/NSMethodSignature.m index 63b2c8b2c..f1ab2f889 100644 --- a/Source/NSMethodSignature.m +++ b/Source/NSMethodSignature.m @@ -127,7 +127,7 @@ [super dealloc]; } -- (BOOL)isEqual:(id)other +- (BOOL) isEqual: (id)other { BOOL isEqual = YES; if (other == nil) diff --git a/Source/NSObjCRuntime.m b/Source/NSObjCRuntime.m index 4e0644dac..372479b26 100644 --- a/Source/NSObjCRuntime.m +++ b/Source/NSObjCRuntime.m @@ -30,7 +30,6 @@ #include "Foundation/NSException.h" #include "Foundation/NSObjCRuntime.h" #include "Foundation/NSString.h" -#include #include /** @@ -140,12 +139,12 @@ NSStringFromClass(Class aClass) const char * NSGetSizeAndAlignment(const char *typePtr, unsigned *sizep, unsigned *alignp) { - NSArgumentInfo info; - typePtr = mframe_next_arg(typePtr, &info, 0); + typePtr = objc_skip_offset (typePtr); + typePtr = objc_skip_type_qualifiers (typePtr); if (sizep) - *sizep = info.size; + *sizep = objc_sizeof_type (typePtr); if (alignp) - *alignp = info.align; + *alignp = objc_alignof_type (typePtr); return typePtr; } diff --git a/Source/callframe.h b/Source/callframe.h index 117e2b255..2da30f617 100644 --- a/Source/callframe.h +++ b/Source/callframe.h @@ -36,8 +36,8 @@ typedef struct _callframe_t { void **args; } callframe_t; -extern callframe_t *callframe_from_info (NSArgumentInfo *info, int numargs, - void **retval); +extern callframe_t *callframe_from_signature (NSMethodSignature *info, + void **retval); extern void callframe_set_arg(callframe_t *cframe, int index, void *buffer, int size); extern void callframe_get_arg(callframe_t *cframe, int index, void *buffer, diff --git a/Source/callframe.m b/Source/callframe.m index 6e1091875..785e43700 100644 --- a/Source/callframe.m +++ b/Source/callframe.m @@ -42,11 +42,12 @@ typedef int smallret_t; #endif callframe_t * -callframe_from_info (NSArgumentInfo *info, int numargs, void **retval) +callframe_from_signature (NSMethodSignature *info, void **retval) { unsigned size = sizeof(callframe_t); unsigned align = __alignof(double); unsigned offset = 0; + unsigned numargs = [info numberOfArguments]; void *buf; int i; callframe_t *cframe; @@ -65,8 +66,9 @@ callframe_from_info (NSArgumentInfo *info, int numargs, void **retval) } for (i = 0; i < numargs; i++) { - size += info[i+1].size; + const char *type = [info getArgumentTypeAtIndex: i]; + size += objc_sizeof_type (type); if (size % align != 0) { size += (align - size % align); @@ -81,15 +83,26 @@ callframe_from_info (NSArgumentInfo *info, int numargs, void **retval) */ if (retval) { - unsigned full = size; - unsigned pos; + const char *type = [info methodReturnType]; + unsigned full = size; + unsigned pos; + unsigned ret; if (full % align != 0) { full += (align - full % align); } + if (full % 8 != 0) + { + full += (8 - full % 8); + } pos = full; - full += MAX(info[0].size, sizeof(smallret_t)); + ret = MAX(objc_sizeof_type (type), sizeof(double)); + /* The addition of a constant '8' is a fudge applied simply because + * some return values write beynd the end of the memory if the buffer + * is sized exactly ... don't know why. + */ + full += ret + 8; #if GS_WITH_GC cframe = buf = NSAllocateCollectable(full, NSScannedOption); #else @@ -122,7 +135,7 @@ callframe_from_info (NSArgumentInfo *info, int numargs, void **retval) { cframe->args[i] = buf + offset; - offset += info[i+1].size; + offset += objc_sizeof_type ([info getArgumentTypeAtIndex: i]); if (offset % align != 0) { diff --git a/Source/cifframe.h b/Source/cifframe.h index 02a8ef1ee..e5ee8d6ff 100644 --- a/Source/cifframe.h +++ b/Source/cifframe.h @@ -50,8 +50,7 @@ typedef struct _cifframe_t { void **values; } cifframe_t; -extern cifframe_t *cifframe_from_info (NSArgumentInfo *info, int numargs, - void **retval); +extern cifframe_t *cifframe_from_signature (NSMethodSignature *info); extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size); diff --git a/Source/cifframe.m b/Source/cifframe.m index 2658cf544..09cf81288 100644 --- a/Source/cifframe.m +++ b/Source/cifframe.m @@ -121,7 +121,7 @@ cifframe_guess_struct_size(ffi_type *stype) cifframe_t * -cifframe_from_info (NSArgumentInfo *info, int numargs, void **retval) +cifframe_from_signature (NSMethodSignature *info) { unsigned size = sizeof(cifframe_t); unsigned align = __alignof(double); @@ -129,6 +129,7 @@ cifframe_from_info (NSArgumentInfo *info, int numargs, void **retval) unsigned offset = 0; void *buf; int i; + int numargs = [info numberOfArguments]; ffi_type *rtype; ffi_type *arg_types[numargs]; cifframe_t *cframe; @@ -137,10 +138,10 @@ cifframe_from_info (NSArgumentInfo *info, int numargs, void **retval) 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); + rtype = cifframe_type([info methodReturnType], NULL); for (i = 0; i < numargs; i++) { - arg_types[i] = cifframe_type(info[i+1].type, NULL); + arg_types[i] = cifframe_type([info getArgumentTypeAtIndex: i], NULL); } if (numargs > 0) @@ -176,48 +177,11 @@ cifframe_from_info (NSArgumentInfo *info, int numargs, void **retval) } } - /* - * If we need space allocated to store a return value, - * make room for it at the end of the cifframe so we - * only need to do a single malloc. - */ - if (rtype && (rtype->size > 0 || rtype->elements != NULL)) - { - unsigned full = size; - unsigned pos; - - if (full % align != 0) - { - full += (align - full % align); - } - pos = full; - if (rtype->elements) - full += cifframe_guess_struct_size(rtype); - else - full += MAX(rtype->size, sizeof(smallret_t)); - /* HACK ... not sure why, but on my 64bit intel system adding a bit - * more to the buffer size prevents writing outside the allocated - * memory by the ffi stuff. - */ - full += 64; #if GS_WITH_GC - cframe = buf = NSAllocateCollectable(full, NSScannedOption); + cframe = buf = NSAllocateCollectable(size, NSScannedOption); #else - cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), full, 1); + cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), size, 1); #endif - if (cframe && retval) - { - *retval = buf + pos; - } - } - else - { -#if GS_WITH_GC - cframe = buf = NSAllocateCollectable(size, NSScannedOption); -#else - cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), size, 1); -#endif - } if (cframe) { diff --git a/Source/mframe.m b/Source/mframe.m index c637fad98..27c9a7409 100644 --- a/Source/mframe.m +++ b/Source/mframe.m @@ -557,1243 +557,3 @@ method_types_get_size_of_register_arguments(const char *types) } } - -/* To fix temporary bug in method_get_next_argument() on NeXT boxes */ -/* xxx Perhaps this isn't working with the NeXT runtime? */ - -char* -method_types_get_next_argument (arglist_t argf, const char **type) -{ - const char *t = objc_skip_argspec (*type); - arglist_t argframe; - - argframe = (void*)argf; - - if (*t == '\0') - { - return 0; - } - *type = t; - t = objc_skip_typespec (t); - - if (*t == '+') - { - return argframe->arg_regs + atoi(++t); - } - else - { - /* xxx What's going on here? This -8 needed on my 68k NeXT box. */ -#if NeXT - return argframe->arg_ptr + (atoi(t) - 8); -#else - return argframe->arg_ptr + atoi(t); -#endif - } -} - -char* -method_types_get_first_argument (struct objc_method* m, - arglist_t argframe, - const char** type) -{ - *type = m->method_types; - return method_types_get_next_argument (argframe, type); -} - -int -method_types_get_sizeof_arguments (struct objc_method* mth) -{ - const char* type = objc_skip_typespec (mth->method_types); - return atoi (type); -} - - -/* mframe_dissect_call() - - This function encodes the arguments of a method call. - - Call it with an ARGFRAME that was returned by __builtin_args(), and - a TYPE string that describes the input and return locations, - i.e. from sel_get_types() or Method->method_types. - - The function ENCODER will be called once with each input argument. - - Returns YES iff there are any outparameters---parameters that for - which we will have to get new values after the method is run, - e.g. an argument declared (out char*). */ - -BOOL -mframe_dissect_call (arglist_t argframe, const char *type, - void (*encoder)(DOContext *), DOContext *ctxt) -{ - unsigned flags; - char *datum; - int argnum; - BOOL out_parameters = NO; - - if (*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B) { - datum = alloca((strlen(type)+1)*10); - type = mframe_build_signature(type, 0, 0, datum); - } - /* Enumerate all the arguments in ARGFRAME, and call ENCODER for - each one. METHOD_TYPES_GET_NEXT_ARGUEMENT() returns 0 when - there are no more arguments, otherwise it returns a pointer to the - argument in the ARGFRAME. */ - - for (datum = method_types_get_next_argument(argframe, &type), argnum=0; - datum; - datum = method_types_get_next_argument(argframe, &type), argnum++) - { - /* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */ - flags = objc_get_type_qualifiers(type); - - /* Skip over the type qualifiers, so now TYPE is pointing directly - at the char corresponding to the argument's type, as defined - in */ - type = objc_skip_type_qualifiers(type); - - /* Decide how, (or whether or not), to encode the argument - depending on its FLAGS and TYPE. Only the first two cases - involve parameters that may potentially be passed by - reference, and thus only the first two may change the value - of OUT_PARAMETERS. */ - - ctxt->type = type; - ctxt->flags = flags; - ctxt->datum = datum; - - switch (*type) - { - - case _C_CHARPTR: - /* Handle a (char*) argument. */ - /* If the char* is qualified as an OUT parameter, or if it - not explicitly qualified as an IN parameter, then we will - have to get this char* again after the method is run, - because the method may have changed it. Set - OUT_PARAMETERS accordingly. */ - if ((flags & _F_OUT) || !(flags & _F_IN)) - out_parameters = YES; - /* If the char* is qualified as an IN parameter, or not - explicity qualified as an OUT parameter, then encode - it. */ - if ((flags & _F_IN) || !(flags & _F_OUT)) - (*encoder) (ctxt); - break; - - case _C_PTR: - /* If the pointer's value is qualified as an OUT parameter, - or if it not explicitly qualified as an IN parameter, - then we will have to get the value pointed to again after - the method is run, because the method may have changed - it. Set OUT_PARAMETERS accordingly. */ - if ((flags & _F_OUT) || !(flags & _F_IN)) - out_parameters = YES; - /* Handle an argument that is a pointer to a non-char. But - (void*) and (anything**) is not allowed. */ - /* The argument is a pointer to something; increment TYPE - so we can see what it is a pointer to. */ - type++; - ctxt->type = type; - ctxt->datum = *(void**)datum; - /* If the pointer's value is qualified as an IN parameter, - or not explicity qualified as an OUT parameter, then - encode it. */ - if ((flags & _F_IN) || !(flags & _F_OUT)) - (*encoder) (ctxt); - break; - - case _C_STRUCT_B: - case _C_UNION_B: - case _C_ARY_B: - /* Handle struct and array arguments. */ - /* Whether DATUM points to the data, or points to a pointer - that points to the data, depends on the value of - MFRAME_STRUCT_BYREF. Do the right thing - so that ENCODER gets a pointer to directly to the data. */ -#if MFRAME_STRUCT_BYREF - ctxt->datum = *(void**)datum; -#endif - (*encoder) (ctxt); - break; - - default: - /* Handle arguments of all other types. */ - (*encoder) (ctxt); - } - } - - /* Return a BOOL indicating whether or not there are parameters that - were passed by reference; we will need to get those values again - after the method has finished executing because the execution of - the method may have changed them.*/ - return out_parameters; -} - - -/* mframe_do_call() - - This function decodes the arguments of method call, builds an - argframe of type arglist_t, and invokes the method using - __builtin_apply; then it encodes the return value and any - pass-by-reference arguments. - - ENCODED_TYPES should be a string that describes the return value - and arguments. It's argument types and argument type qualifiers - should match exactly those that were used when the arguments were - encoded with mframe_dissect_call()---mframe_do_call() uses - ENCODED_TYPES to determine which variable types it should decode. - - ENCODED_TYPES is used to get the types and type qualifiers, but not - to get the register and stack locations---we get that information - from the selector type of the SEL that is decoded as the second - argument. In this way, the ENCODED_TYPES may come from a machine - of a different architecture. Having the original ENCODED_TYPES is - good, just in case the machine running mframe_do_call() has some - slightly different qualifiers. Using different qualifiers for - encoding and decoding could lead to massive confusion. - - - DECODER should be a pointer to a function that obtains the method's - argument values. For example: - - void my_decoder (int argnum, void *data, const char *type) - - ARGNUM is the number of the argument, beginning at 0. - DATA is a pointer to the memory where the value should be placed. - TYPE is a pointer to the type string of this value. - - mframe_do_call() calls this function once for each of the methods - arguments. The DECODER function should place the ARGNUM'th - argument's value at the memory location DATA. - mframe_do_call() calls this function once with ARGNUM -1, DATA 0, - and TYPE 0 to denote completion of decoding. - - - If DECODER malloc's new memory in the course of doing its - business, then DECODER is responsible for making sure that the - memory will get free eventually. For example, if DECODER uses - -decodeValueOfCType:at:withName: to decode a char* string, you - should remember that -decodeValueOfCType:at:withName: malloc's - new memory to hold the string, and DECODER should autorelease the - malloc'ed pointer, using the NSData class. - - - ENCODER should be a pointer to a function that records the method's - return value and pass-by-reference values. For example: - - void my_encoder (int argnum, void *data, const char *type, int flags) - - ARGNUM is the number of the argument; this will be -1 for the - return value, and the argument index for the pass-by-reference - values; the indices start at 0. - DATA is a pointer to the memory where the value can be found. - TYPE is a pointer to the type string of this value. - FLAGS is a copy of the type qualifier flags for this argument; - (see ). - - mframe_do_call() calls this function after the method has been - run---once for the return value, and once for each of the - pass-by-reference parameters. The ENCODER function should place - the value at memory location DATA wherever the user wants to - record the ARGNUM'th return value. - - PASS_POINTERS is a flag saying whether pointers should be passed - as pointers (for local stuff) or should be assumed to point to a - single data item (for distributed objects). -*/ - -#if !defined(USE_FFCALL) && !defined(USE_LIBFFI) -static inline id retframe_id(void *rframe) -{ - __builtin_return (rframe); -} -static inline Class retframe_Class(void *rframe) -{ - __builtin_return (rframe); -} -static inline SEL retframe_SEL(void *rframe) -{ - __builtin_return (rframe); -} -static inline unsigned long retframe_long(void *rframe) -{ - __builtin_return (rframe); -} -static inline unsigned long long retframe_longlong(void *rframe) -{ - __builtin_return (rframe); -} -static inline char* retframe_pointer(void *rframe) -{ - __builtin_return (rframe); -} -typedef struct { - char val[4]; -} block; -static inline block retframe_block(void *rframe) -{ - __builtin_return (rframe); -} -static inline float retframe_float (void *rframe) -{ - __builtin_return (rframe); -} -/* For extracting a return value of type `double' from RETFRAME. */ -static inline double retframe_double (void *rframe) -{ - __builtin_return (rframe); -} -/* For extracting a return value of type `char' from RETFRAME */ -static inline char retframe_char (void *rframe) -{ - __builtin_return (rframe); -} -static inline short retframe_short (void *rframe) -{ - __builtin_return (rframe); -} -static inline int retframe_int (void *rframe) -{ - __builtin_return (rframe); -} - -void -mframe_do_call (DOContext *ctxt, - void(*decoder)(DOContext*), - void(*encoder)(DOContext*)) -{ - /* The method type string obtained from the target's OBJC_METHOD - structure for the selector we're sending. */ - const char *type; - /* A pointer into the local variable TYPE string. */ - const char *tmptype; - /* A pointer into the argument ENCODED_TYPES string. */ - const char *etmptype; - /* The target object that will receive the message. */ - id object; - /* The selector for the message we're sending to the TARGET. */ - SEL selector; - /* The OBJECT's Method(_t) pointer for the SELECTOR. */ - GSMethod meth = 0; - /* The OBJECT's implementation of the SELECTOR. */ - IMP method_implementation; - /* The number bytes for holding arguments passed on the stack. */ - int stack_argsize; - /* The number bytes for holding arguments passed in registers. */ - int reg_argsize; - /* The structure for holding the arguments to the method. */ - arglist_t argframe; - /* A pointer into the ARGFRAME; points at individual arguments. */ - char *datum; - /* Type qualifier flags; see . */ - unsigned flags; - /* Which argument number are we processing now? */ - int argnum; - /* A pointer to the memory holding the return value of the method. */ - void *retframe; - /* Does the method have any arguments that are passed by reference? - If so, we need to encode them, since the method may have changed them. */ - BOOL out_parameters = NO; - const char *encoded_types = ctxt->type; - - /* Decode the object, (which is always the first argument to a method), - into the local variable OBJECT. */ - ctxt->datum = &object; - ctxt->type = @encode(id); - (*decoder) (ctxt); - NSCParameterAssert (object); - - /* Decode the selector, (which is always the second argument to a - method), into the local variable SELECTOR. */ - /* xxx @encode(SEL) produces "^v" in gcc 2.5.8. It should be ":" */ - ctxt->datum = &selector; - ctxt->type = @encode(SEL); - (*decoder) (ctxt); - NSCParameterAssert (selector); - - /* Get the "selector type" for this method. The "selector type" is - a string that lists the return and argument types, and also - indicates in which registers and where on the stack the arguments - should be placed before the method call. The selector type - string we get here should have the same argument and return types - as the ENCODED_TYPES string, but it will have different register - and stack locations if the ENCODED_TYPES came from a machine of a - different architecture. */ - if (GSObjCIsClass(object)) - { - meth = GSGetMethod(object, selector, NO, YES); - } - else if (GSObjCIsInstance(object)) - { - meth = GSGetMethod(GSObjCClass(object), selector, YES, YES); - } - else - { - [NSException raise: NSInvalidArgumentException - format: @"decoded object %p is invalid", object]; - } - - if (meth != 0) - { - type = meth->method_types; - } - else - { - NSDebugLog(@"Local object <%p %s> doesn't implement: %s directly. " - @"Will search for arbitrary signature.", - object, - GSNameFromClass(GSObjCIsClass(object) - ? object : (id) GSObjCClass(object)), - GSNameFromSelector(selector)); - type = GSTypesFromSelector(selector); - } - - /* Make sure we successfully got the method type, and that its - types match the ENCODED_TYPES. */ - NSCParameterAssert (type); - NSCParameterAssert (GSSelectorTypesMatch(encoded_types, type)); - - /* - * The compiler/runtime doesn't always seem to get the encoding right - * for our purposes - so we generate our own encoding as required by - * __builtin_apply(). - */ - if (*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B) { - tmptype = alloca((strlen(type)+1)*10); - type = mframe_build_signature(type, 0, 0, (char*)tmptype); - } - - /* Allocate an argframe, using memory on the stack */ - - /* Calculate the amount of memory needed for storing variables that - are passed in registers, and the amount of memory for storing - variables that are passed on the stack. */ - stack_argsize = method_types_get_size_of_stack_arguments (type); - reg_argsize = method_types_get_size_of_register_arguments (type); - /* Allocate the space for variables passed in registers. */ - argframe = (arglist_t) alloca(sizeof(char*) + reg_argsize); - /* Allocate the space for variables passed on the stack. */ - if (stack_argsize) - argframe->arg_ptr = alloca (stack_argsize); - else - argframe->arg_ptr = 0; - - if (*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B) - { - void *buf; - - /* If we are passing a pointer to return a structure in, we must allocate - the memory for it and put it in the correct place in the argframe. */ - buf = alloca(objc_sizeof_type(type)); - MFRAME_SET_STRUCT_ADDR(argframe, type, buf); - } - - /* Put OBJECT and SELECTOR into the ARGFRAME. */ - - /* Initialize our temporary pointers into the method type strings. */ - tmptype = type; - etmptype = objc_skip_argspec (encoded_types); - /* Get a pointer into ARGFRAME, pointing to the location where the - first argument is to be stored. */ - datum = method_types_get_next_argument (argframe, &tmptype); - NSCParameterAssert (datum); - NSCParameterAssert (*tmptype == _C_ID); - /* Put the target object there. */ - *(id*)datum = object; - /* Get a pointer into ARGFRAME, pointing to the location where the - second argument is to be stored. */ - etmptype = objc_skip_argspec(etmptype); - datum = method_types_get_next_argument(argframe, &tmptype); - NSCParameterAssert (datum); - NSCParameterAssert (*tmptype == _C_SEL); - /* Put the selector there. */ - *(SEL*)datum = selector; - - - /* Decode arguments after OBJECT and SELECTOR, and put them into the - ARGFRAME. Step TMPTYPE and ETMPTYPE in lock-step through their - method type strings. */ - - for (datum = method_types_get_next_argument (argframe, &tmptype), - etmptype = objc_skip_argspec (etmptype), argnum = 2; - datum; - datum = method_types_get_next_argument (argframe, &tmptype), - etmptype = objc_skip_argspec (etmptype), argnum++) - { - /* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */ - flags = objc_get_type_qualifiers (etmptype); - /* Skip over the type qualifiers, so now TYPE is pointing directly - at the char corresponding to the argument's type, as defined - in */ - tmptype = objc_skip_type_qualifiers(tmptype); - - /* Decide how, (or whether or not), to decode the argument - depending on its FLAGS and TMPTYPE. Only the first two cases - involve parameters that may potentially be passed by - reference, and thus only the first two may change the value - of OUT_PARAMETERS. *** Note: This logic must match exactly - the code in mframe_dissect_call(); that function should - encode exactly what we decode here. *** */ - - ctxt->type = tmptype; - ctxt->datum = datum; - - switch (*tmptype) - { - - case _C_CHARPTR: - /* Handle a (char*) argument. */ - /* If the char* is qualified as an OUT parameter, or if it - not explicitly qualified as an IN parameter, then we will - have to get this char* again after the method is run, - because the method may have changed it. Set - OUT_PARAMETERS accordingly. */ - if ((flags & _F_OUT) || !(flags & _F_IN)) - out_parameters = YES; - /* If the char* is qualified as an IN parameter, or not - explicity qualified as an OUT parameter, then decode it. - Note: the decoder allocates memory for holding the - string, and it is also responsible for making sure that - the memory gets freed eventually, (usually through the - autorelease of NSData object). */ - if ((flags & _F_IN) || !(flags & _F_OUT)) - (*decoder) (ctxt); - - break; - - case _C_PTR: - /* If the pointer's value is qualified as an OUT parameter, - or if it not explicitly qualified as an IN parameter, - then we will have to get the value pointed to again after - the method is run, because the method may have changed - it. Set OUT_PARAMETERS accordingly. */ - if ((flags & _F_OUT) || !(flags & _F_IN)) - out_parameters = YES; - /* Handle an argument that is a pointer to a non-char. But - (void*) and (anything**) is not allowed. */ - /* The argument is a pointer to something; increment TYPE - so we can see what it is a pointer to. */ - tmptype++; - /* Allocate some memory to be pointed to, and to hold the - value. Note that it is allocated on the stack, and - methods that want to keep the data pointed to, will have - to make their own copies. */ - *(void**)datum = alloca (objc_sizeof_type (tmptype)); - /* If the pointer's value is qualified as an IN parameter, - or not explicity qualified as an OUT parameter, then - decode it. */ - ctxt->type = tmptype; - ctxt->datum = *(void**)datum; - if ((flags & _F_IN) || !(flags & _F_OUT)) - (*decoder) (ctxt); - break; - - case _C_STRUCT_B: - case _C_UNION_B: - case _C_ARY_B: - /* Handle struct and array arguments. */ - /* Whether DATUM points to the data, or points to a pointer - that points to the data, depends on the value of - MFRAME_STRUCT_BYREF. Do the right thing - so that ENCODER gets a pointer to directly to the data. */ -#if MFRAME_STRUCT_BYREF - /* Allocate some memory to be pointed to, and to hold the - data. Note that it is allocated on the stack, and - methods that want to keep the data pointed to, will have - to make their own copies. */ - *(void**)datum = alloca (objc_sizeof_type(tmptype)); - ctxt->datum = datum; -#endif - (*decoder) (ctxt); - break; - - default: - /* Handle arguments of all other types. */ - /* NOTE FOR OBJECTS: Unlike [Decoder decodeObjectAt:..], - this function does not generate a reference to the - object; the object may be autoreleased; if the method - wants to keep a reference to the object, it will have to - -retain it. */ - (*decoder) (ctxt); - } - } - /* End of the for () loop that enumerates the method's arguments. */ - ctxt->type = 0; - ctxt->datum = 0; - (*decoder) (ctxt); - - - /* Invoke the method! */ - - /* Find the target object's implementation of this selector. */ - method_implementation = objc_msg_lookup (object, selector); - NSCParameterAssert (method_implementation); - /* Do it! Send the message to the target, and get the return value - in RETFRAME. The arguments will still be in ARGFRAME, so we can - get the pass-by-reference info from there. */ - retframe = __builtin_apply((void(*)(void))method_implementation, - argframe, - stack_argsize); - - - /* Encode the return value and pass-by-reference values, if there - are any. This logic must match exactly that in - mframe_build_return(). */ - /* OUT_PARAMETERS should be true here in exactly the same - situations as it was true in mframe_dissect_call(). */ - - /* Get the qualifier type of the return value. */ - flags = objc_get_type_qualifiers (encoded_types); - /* Get the return type; store it our two temporary char*'s. */ - etmptype = objc_skip_type_qualifiers (encoded_types); - tmptype = objc_skip_type_qualifiers (type); - - /* Only encode return values if there is a non-void return value, - a non-oneway void return value, or if there are values that were - passed by reference. */ - - ctxt->type = tmptype; - ctxt->datum = retframe; - ctxt->flags = flags; - /* If there is a return value, encode it. */ - switch (*tmptype) - { - case _C_VOID: - if ((flags & _F_ONEWAY) == 0) - { - int dummy = 0; - - ctxt->datum = &dummy; - ctxt->type = @encode(int); - (*encoder) (ctxt); - } - /* No return value to encode; do nothing. */ - break; - - case _C_PTR: - /* The argument is a pointer to something; increment TYPE - so we can see what it is a pointer to. */ - tmptype++; - ctxt->type = tmptype; - ctxt->datum = *(void**)retframe; - /* Encode the value that was pointed to. */ - (*encoder) (ctxt); - break; - - case _C_STRUCT_B: - case _C_UNION_B: - case _C_ARY_B: - /* The argument is a structure or array returned by value. - (In C, are array's allowed to be returned by value?) */ - ctxt->datum = MFRAME_GET_STRUCT_ADDR(argframe, tmptype); - (*encoder)(ctxt); - break; - - case _C_FLT: - { - float ret = retframe_float (retframe); - ctxt->datum = &ret; - (*encoder) (ctxt); - break; - } - - case _C_DBL: - { - double ret = retframe_double (retframe); - ctxt->datum = &ret; - (*encoder) (ctxt); - break; - } - - case _C_SHT: - case _C_USHT: - /* On some (but not all) architectures, for C variable types - smaller than int, like short, the RETFRAME doesn't actually - point to the beginning of the short, it points to the - beginning of an int. So we let RETFRAME_SHORT() take care of - it. */ - { - short ret = retframe_short (retframe); - ctxt->datum = &ret; - (*encoder) (ctxt); - break; - } - - case _C_CHR: - case _C_UCHR: - /* On some (but not all) architectures, for C variable types - smaller than int, like char, the RETFRAME doesn't actually - point to the beginning of the char, it points to the - beginning of an int. So we let RETFRAME_SHORT() take care of - it. */ - { - char ret = retframe_char (retframe); - ctxt->datum = &ret; - (*encoder) (ctxt); - break; - } - - default: - /* case _C_INT: case _C_UINT: case _C_LNG: case _C_ULNG: - case _C_CHARPTR: case: _C_ID: */ - /* xxx I think this assumes that sizeof(int)==sizeof(void*) */ - (*encoder) (ctxt); - } - - - /* Encode the values returned by reference. Note: this logic - must match exactly the code in mframe_build_return(); that - function should decode exactly what we encode here. */ - - if (out_parameters) - { - /* Step through all the arguments, finding the ones that were - passed by reference. */ - for (datum = method_types_get_next_argument (argframe, &tmptype), - argnum = 1, - etmptype = objc_skip_argspec (etmptype); - datum; - datum = method_types_get_next_argument (argframe, &tmptype), - argnum++, - etmptype = objc_skip_argspec (etmptype)) - { - /* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */ - flags = objc_get_type_qualifiers(etmptype); - /* Skip over the type qualifiers, so now TYPE is pointing directly - at the char corresponding to the argument's type, as defined - in */ - tmptype = objc_skip_type_qualifiers (tmptype); - - ctxt->type = tmptype; - ctxt->datum = datum; - - /* Decide how, (or whether or not), to encode the argument - depending on its FLAGS and TMPTYPE. */ - - if ((*tmptype == _C_PTR) - && ((flags & _F_OUT) || !(flags & _F_IN))) - { - /* The argument is a pointer (to a non-char), and the - pointer's value is qualified as an OUT parameter, or - it not explicitly qualified as an IN parameter, then - it is a pass-by-reference argument.*/ - /* The argument is a pointer to something; increment TYPE - so we can see what it is a pointer to. */ - tmptype++; - ctxt->type = tmptype; - ctxt->datum = *(void**)datum; - /* Encode it. */ - (*encoder) (ctxt); - } - else if (*tmptype == _C_CHARPTR - && ((flags & _F_OUT) || !(flags & _F_IN))) - { - /* The argument is a pointer char string, and the - pointer's value is qualified as an OUT parameter, or - it not explicitly qualified as an IN parameter, then - it is a pass-by-reference argument. Encode it.*/ - /* xxx Perhaps we could save time and space by saving - a copy of the string before the method call, and then - comparing it to this string; if it didn't change, don't - bother to send it back again. */ - (*encoder) (ctxt); - } - } - } - - return; -} - -#if 0 - /* For returning structures etc */ - typedef struct { id many[8];} __big; -static __big return_block (void* data) - { - return *(__big*)data; - } -#endif - /* For returning a char (or unsigned char) */ -static char return_char (char data) - { - return data; - } - /* For returning a double */ -static double return_double (double data) - { - return data; - } - /* For returning a float */ -static float return_float (float data) - { - return data; - } - /* For returning a short (or unsigned short) */ -static short return_short (short data) - { - return data; - } -#if 0 -static retval_t apply_block(void* data) - { - void* args = __builtin_apply_args(); - return __builtin_apply((apply_t)return_block, args, sizeof(void*)); - } -#endif -static retval_t apply_char(char data) - { - void* args = __builtin_apply_args(); - return __builtin_apply((apply_t)return_char, args, sizeof(void*)); - } -static retval_t apply_float(float data) - { - void* args = __builtin_apply_args(); - return __builtin_apply((apply_t)return_float, args, sizeof(float)); - } -static retval_t apply_double(double data) - { - void* args = __builtin_apply_args(); - return __builtin_apply((apply_t)return_double, args, sizeof(double)); - } -static retval_t apply_short(short data) - { - void* args = __builtin_apply_args(); - return __builtin_apply((apply_t)return_short, args, sizeof(void*)); - } - -/* mframe_build_return() - - This function decodes the values returned from a method call, - builds a retframe of type retval_t that can be passed to GCC's - __builtin_return(), and updates the pass-by-reference arguments in - ARGFRAME. This function returns a retframe pointer. - - In the function that calls this one, be careful about calling more - functions after this one. The memory for the retframe is alloca()'ed, - and therefore is on the stack and can be tromped-on by future function calls. - - The callback function is finally called with the 'type' set to a null pointer - to tell it that the return value and all return parameters have been - dealt with. This permits the function to do any tidying up necessary. -*/ - -retval_t -mframe_build_return (arglist_t argframe, - const char *type, - BOOL out_parameters, - void(*decoder)(DOContext*), - DOContext *ctxt) -{ - /* A pointer to the memory that will hold the return value. */ - retval_t retframe = NULL; - /* The size, in bytes, of memory pointed to by RETFRAME. */ - unsigned int retsize; - /* Which argument number are we processing now? */ - int argnum; - /* Type qualifier flags; see . */ - int flags; - /* A pointer into the TYPE string. */ - const char *tmptype; - /* A pointer into the ARGFRAME; points at individual arguments. */ - void *datum; - const char *rettype; - - if (*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B) - { - tmptype = alloca((strlen(type)+1)*10); - type = mframe_build_signature(type, 0, 0, (char*)tmptype); - } - /* Get the return type qualifier flags, and the return type. */ - flags = objc_get_type_qualifiers(type); - tmptype = objc_skip_type_qualifiers(type); - rettype = tmptype; - - /* Decode the return value and pass-by-reference values, if there - are any. OUT_PARAMETERS should be the value returned by - mframe_dissect_call(). */ - if (out_parameters || *tmptype != _C_VOID || (flags & _F_ONEWAY) == 0) - /* xxx What happens with method declared "- (oneway) foo: (out int*)ip;" */ - /* xxx What happens with method declared "- (in char *) bar;" */ - /* xxx Is this right? Do we also have to check _F_ONEWAY? */ - { - /* If there is a return value, decode it, and put it in retframe. */ - if (*tmptype != _C_VOID || (flags & _F_ONEWAY) == 0) - { - /* Get the size of the returned value. */ - if (*tmptype == _C_VOID) - retsize = sizeof(void*); - else - retsize = objc_sizeof_type (tmptype); - /* Allocate memory on the stack to hold the return value. - It should be at least 4 * sizeof(void*). */ - /* xxx We need to test retsize's less than 4. Also note that - if we return structures using a structure-value-address, we - are potentially alloca'ing much more than we need here. */ - /* xxx Find out about returning structures by reference - on non--structure-value-address machines, and potentially - just always alloca(RETFRAME_SIZE == sizeof(void*)*4) */ - retframe = alloca (MAX(retsize, sizeof(void*)*4)); - - ctxt->type = tmptype; - ctxt->datum = retframe; - ctxt->flags = flags; - - switch (*tmptype) - { - case _C_PTR: - { - unsigned retLength; - - /* We are returning a pointer to something. */ - /* Increment TYPE so we can see what it is a pointer to. */ - tmptype++; - retLength = (unsigned int)objc_sizeof_type(tmptype); - /* Allocate memory to hold the value we're pointing to. */ - *(void**)retframe = - NSZoneMalloc(NSDefaultMallocZone(), retLength); - /* We are responsible for making sure this memory gets free'd - eventually. Ask NSData class to autorelease it. */ - [NSData dataWithBytesNoCopy: *(void**)retframe - length: retLength]; - ctxt->type = tmptype; - ctxt->datum = *(void**)retframe; - /* Decode the return value into the memory we allocated. */ - (*decoder) (ctxt); - } - break; - - case _C_STRUCT_B: - case _C_UNION_B: - case _C_ARY_B: - /* The argument is a structure or array returned by value. - (In C, are array's allowed to be returned by value?) */ - *(void**)retframe = MFRAME_GET_STRUCT_ADDR(argframe, tmptype); - /* Decode the return value into the memory we allocated. */ - ctxt->datum = *(void**)retframe; - (*decoder) (ctxt); - break; - - case _C_FLT: - case _C_DBL: - (*decoder) (ctxt); - break; - - case _C_VOID: - { - ctxt->type = @encode(int); - (*decoder) (ctxt); - } - break; - - default: - (*decoder) (ctxt); - } - } - - /* Decode the values returned by reference. Note: this logic - must match exactly the code in mframe_do_call(); that - function should decode exactly what we encode here. */ - - if (out_parameters) - { - /* Step through all the arguments, finding the ones that were - passed by reference. */ - for (datum = method_types_get_next_argument(argframe, &tmptype), - argnum=0; - datum; - (datum = method_types_get_next_argument(argframe, &tmptype)), - argnum++) - { - /* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */ - flags = objc_get_type_qualifiers(tmptype); - /* Skip over the type qualifiers, so now TYPE is - pointing directly at the char corresponding to the - argument's type, as defined in */ - tmptype = objc_skip_type_qualifiers(tmptype); - - /* Decide how, (or whether or not), to encode the - argument depending on its FLAGS and TMPTYPE. */ - - if (*tmptype == _C_PTR - && ((flags & _F_OUT) || !(flags & _F_IN))) - { - /* The argument is a pointer (to a non-char), and - the pointer's value is qualified as an OUT - parameter, or it not explicitly qualified as an - IN parameter, then it is a pass-by-reference - argument.*/ - /* The argument is a pointer to something; increment - TYPE so we can see what it is a pointer to. */ - tmptype++; - ctxt->flags = flags; - ctxt->type = tmptype; - ctxt->datum = *(void**)datum; - /* xxx Note that a (char**) is malloc'ed anew here. - Yucky, or worse than yucky. If the returned string - is smaller than the original, we should just put it - there; if the returned string is bigger, I don't know - what to do. */ - /* xxx __builtin_return can't return structures by value? */ - (*decoder) (ctxt); - } - else if (*tmptype == _C_CHARPTR - && ((flags & _F_OUT) || !(flags & _F_IN))) - { - /* The argument is a pointer char string, and the - pointer's value is qualified as an OUT parameter, - or it not explicitly qualified as an IN - parameter, then it is a pass-by-reference - argument. Encode it.*/ - /* xxx Perhaps we could save time and space by - saving a copy of the string before the method - call, and then comparing it to this string; if it - didn't change, don't bother to send it back - again. */ - ctxt->flags = flags; - ctxt->type = tmptype; - ctxt->datum = datum; - (*decoder) (ctxt); - } - } - } - ctxt->type = 0; - ctxt->datum = 0; - (*decoder) (ctxt); /* Tell it we have finished. */ - } - else /* matches `if (out_parameters)' */ - { - /* We are just returning void, but retframe needs to point to - something or else we can crash. */ - retframe = alloca (sizeof(void*)); - } - - switch (*rettype) { - case _C_CHR: - case _C_UCHR: - return apply_char(*(char*)retframe); - case _C_DBL: - return apply_double(*(double*)retframe); - case _C_FLT: - return apply_float(*(float*)retframe); - case _C_SHT: - case _C_USHT: - return apply_short(*(short*)retframe); -#if 0 - case _C_ARY_B: - case _C_UNION_B: - case _C_STRUCT_B: - if (objc_sizeof_type(rettype) > 8) { - return apply_block(*(void**)retframe); - } -#endif - } - - /* Return the retval_t pointer to the return value. */ - return retframe; -} - - - -arglist_t -mframe_create_argframe(const char *types, void** retbuf) -{ - arglist_t argframe = objc_calloc(MFRAME_ARGS_SIZE, 1); - const char* rtype = objc_skip_type_qualifiers(types); - int stack_argsize = atoi(objc_skip_typespec(rtype)); - - /* - * Allocate the space for variables passed on the stack. - */ - if (stack_argsize) - { - argframe->arg_ptr = objc_calloc(stack_argsize, 1); - } - else - { - argframe->arg_ptr = 0; - } - if (*rtype == _C_STRUCT_B || *rtype == _C_UNION_B || *rtype == _C_ARY_B) - { - /* - * If we haven't been passed a pointer to the location in which - * to store a returned structure - allocate space and return - * the address of the allocated space. - */ - if (*retbuf == 0) - { - *retbuf = objc_calloc(objc_sizeof_type(rtype), 1); - } - MFRAME_SET_STRUCT_ADDR(argframe, rtype, *retbuf); - } - return argframe; -} - -void -mframe_destroy_argframe(const char *types, arglist_t argframe) -{ - const char* rtype = objc_skip_type_qualifiers(types); - int stack_argsize = atoi(objc_skip_typespec(rtype)); - - if (stack_argsize) - { - NSZoneFree(NSDefaultMallocZone(), argframe->arg_ptr); - } - NSZoneFree(NSDefaultMallocZone(), argframe); -} - - - -BOOL -mframe_decode_return (const char *type, void* buffer, void* retframe) -{ - unsigned int size = 0; - - type = objc_skip_type_qualifiers(type); - NSGetSizeAndAlignment(type, &size, 0); - - switch (*type) - { - case _C_ID: - { - *(id*)buffer = retframe_id(retframe); - break; - } - - case _C_CLASS: - { - *(Class*)buffer = retframe_Class(retframe); - break; - } - - case _C_SEL: - { - *(SEL*)buffer = retframe_SEL(retframe); - break; - } - - case _C_CHR: - case _C_UCHR: - { - *(unsigned char*)buffer = retframe_char(retframe); - break; - } - - case _C_SHT: - case _C_USHT: - { - *(unsigned short*)buffer = retframe_short(retframe); - break; - } - - case _C_INT: - case _C_UINT: - { - *(unsigned int*)buffer = retframe_int(retframe); - break; - } - - case _C_LNG: - case _C_ULNG: - { - *(unsigned long*)buffer = retframe_long(retframe); - break; - } - - case _C_LNG_LNG: - case _C_ULNG_LNG: - { - *(unsigned long long*)buffer = retframe_longlong(retframe); - break; - } - - case _C_FLT: - { - *(float*)buffer = retframe_float(retframe); - break; - } - - case _C_DBL: - { - *(double*)buffer = retframe_double(retframe); - break; - } - - case _C_PTR: - case _C_ATOM: - case _C_CHARPTR: - { - *(char**)buffer = retframe_pointer(retframe); - break; - } - - case _C_ARY_B: - case _C_STRUCT_B: - case _C_UNION_B: - { - *(block*)buffer = retframe_block(retframe); - break; - } - - case _C_VOID: - break; - - default: - return NO; /* Unknown type. */ - } - return YES; -} - - - -void* -mframe_handle_return(const char* type, void* retval, arglist_t argframe) -{ - retval_t retframe; - - retframe = alloca(MFRAME_RESULT_SIZE); - - switch (*type) - { - case _C_VOID: - break; - case _C_CHR: - case _C_UCHR: - return apply_char(*(char*)retval); - case _C_DBL: - return apply_double(*(double*)retval); - case _C_FLT: - return apply_float(*(float*)retval); - case _C_SHT: - case _C_USHT: - return apply_short(*(short*)retval); - case _C_ARY_B: - case _C_UNION_B: - case _C_STRUCT_B: - { - int size = objc_sizeof_type(type); -#if 1 - void *dest; - - dest = MFRAME_GET_STRUCT_ADDR(argframe, type); - memcpy(dest, retval, size); -#else - if (size > 8) - { - return apply_block(*(void**)retval); - } - else - { - memcpy(retframe, retval, size); - } -#endif - break; - } - default: - memcpy(retframe, retval, objc_sizeof_type(type)); - break; - } - - return retframe; -} - -#endif //!defined(USE_FFCALL) && !defined(USE_LIBFFI) diff --git a/Source/mframe/mframe.head b/Source/mframe/mframe.head index a4aed7d78..a9fd2ffbf 100644 --- a/Source/mframe/mframe.head +++ b/Source/mframe/mframe.head @@ -43,56 +43,6 @@ typedef union { } *arglist_t; #endif -/* These functions are used to pull apart method calls, and put them - back together again. They are useful for things like distributed - objects, and cross-language communication glue between Objective C - and other languages. */ - -/* xxx Currently these function only work with the GNU Objective C - runtime, not the NeXT runtime. */ - - -/* Extract the arguments to a method call, as found in ARGFRAME, - according to type string TYPES, and encode them by calling ENCODER. - Return YES if and only if the method has some pass-by-reference - arguments. */ - -BOOL -mframe_dissect_call (arglist_t argframe, const char *types, - void (*encoder)(DOContext*), DOContext *ctxt); - -/* Decode the arguments to a method call by calling DECODER, knowing - what to decode by looking at type string ENCODED_TYPES. Build an - argframe of type arglist_t, and invoke the method. Then encode the - return value and the pass-by-reference values using ENCODER. */ - -void -mframe_do_call (DOContext *ctxt, - void(*decoder)(DOContext*), - void(*encoder)(DOContext*)); - -/* Decode the return value and pass-by-reference arguments using - DECODER, knowning what to decode by looking at type string TYPES - and OUT_PARAMETERS, and put then into ARGFRAME. Return the - retval_t structure that can be passed to __builtin_return(). */ - -retval_t -mframe_build_return (arglist_t argframe, const char *types, - BOOL out_parameters, - void(*decoder)(DOContext*), DOContext *ctxt); - -/* - * Copy the return value from retframe into the specified buffer. - */ -BOOL -mframe_decode_return(const char *type, void* buffer, void* retframe); - -/* - * Return the value of the specified type in 'retval' using argFrame. - */ -void* -mframe_handle_return(const char* type, void* retval, arglist_t argFrame); - /* * Step through method encoding information extracting details. */ @@ -108,21 +58,8 @@ char* mframe_build_signature(const char *typePtr, int *size, int *narg, char *buf); -arglist_t -mframe_create_argframe(const char *types, void** retbuf); - -void -mframe_destroy_argframe(const char *types, arglist_t argframe); - #define ROUND(V, A) \ ({ typeof(V) __v=(V); typeof(A) __a=(A); \ __a*((__v+__a-1)/__a); }) -int method_types_get_sizeof_arguments (struct objc_method* mth); -char* method_types_get_next_argument (arglist_t argf, const char **type); -char* method_types_get_first_argument (struct objc_method* m, - arglist_t argframe, - const char** type); - - diff --git a/Source/objc-gnu2next.m b/Source/objc-gnu2next.m deleted file mode 100644 index cef0d6858..000000000 --- a/Source/objc-gnu2next.m +++ /dev/null @@ -1,57 +0,0 @@ -/* Implementation to allow compilation of GNU objc code with NeXT runtime - Copyright (C) 1993,1994 Free Software Foundation, Inc. - - Author: Kresten Krab Thorup - Modified by: Andrew Kachites McCallum - Date: Sep 1994 - - This file is part of the GNUstep Base Library. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02111 USA. -*/ - -#include "config.h" -#include -#include "GNUstepBase/preface.h" -#include "mframe.h" - -id next_objc_msg_sendv(id object, SEL op, void* frame) -{ - arglist_t argFrame = __builtin_apply_args(); - struct objc_method *m = class_get_instance_method(object->class_pointer, op); - const char *type; - void *result; - - argFrame->arg_ptr = frame; - *((id*)method_types_get_first_argument (m, argFrame, &type)) = object; - *((SEL*)method_types_get_next_argument (argFrame, &type)) = op; - result = __builtin_apply((apply_t)m->method_imp, - argFrame, - method_get_sizeof_arguments (m)); - -#if !defined(BROKEN_BUILTIN_APPLY) && defined(i386) - /* Special hack to avoid pushing the poped float value back to the fp - stack on i386 machines. This happens with NeXT runtime and 2.7.2 - compiler. If the result value is floating point don't call - __builtin_return anymore. */ - if (*m->method_types == _C_FLT || *m->method_types == _C_DBL) { - long double value = *(long double*)(((char*)result) + 8); - asm("fld %0" : : "f" (value)); - } - else -#endif - __builtin_return(result); -}