From 80ae8e8ad2efea97a01aad6cb4656e7fb5b0fd55 Mon Sep 17 00:00:00 2001 From: Andrew Ruder Date: Mon, 9 Apr 2007 18:04:50 +0000 Subject: [PATCH] sendmsg.c: Added __objc_msg_forward2... 2007-04-09 Andrew Ruder * sendmsg.c: Added __objc_msg_forward2, a hook that allows external libraries to provide a function that returns the real forwarding function based on both the selector and the receiver. * objc/objc-api.h: Define __objc_msg_forward2. From-SVN: r123678 --- libobjc/ChangeLog | 7 ++++ libobjc/objc/objc-api.h | 81 +++++++++++++++++++---------------------- libobjc/sendmsg.c | 25 ++++++++----- 3 files changed, 59 insertions(+), 54 deletions(-) diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog index e05cac4456f..e55fa509beb 100644 --- a/libobjc/ChangeLog +++ b/libobjc/ChangeLog @@ -1,3 +1,10 @@ +2007-04-09 Andrew Ruder + + * sendmsg.c: Added __objc_msg_forward2, a hook that allows + external libraries to provide a function that returns the real + forwarding function based on both the selector and the receiver. + * objc/objc-api.h: Define __objc_msg_forward2. + 2007-03-01 Brooks Moses * Makefile.in: Add dummy install-pdf target. diff --git a/libobjc/objc/objc-api.h b/libobjc/objc/objc-api.h index e0e49e21fdf..8100c6cfa27 100644 --- a/libobjc/objc/objc-api.h +++ b/libobjc/objc/objc-api.h @@ -41,11 +41,9 @@ extern "C" { /* For functions which return Method_t */ #define METHOD_NULL (Method_t)0 /* Boolean typedefs */ -/* -** Method descriptor returned by introspective Object methods. -** This is really just the first part of the more complete objc_method -** structure defined below and used internally by the runtime. -*/ +/* Method descriptor returned by introspective Object methods. + This is really just the first part of the more complete objc_method + structure defined below and used internally by the runtime. */ struct objc_method_description { SEL name; /* this is a selector, not a string */ @@ -85,36 +83,32 @@ struct objc_method_description #define _C_COMPLEX 'j' -/* -** Error handling -** -** Call objc_error() or objc_verror() to record an error; this error -** routine will generally exit the program but not necessarily if the -** user has installed his own error handler. -** -** Call objc_set_error_handler to assign your own function for -** handling errors. The function should return YES if it is ok -** to continue execution, or return NO or just abort if the -** program should be stopped. The default error handler is just to -** print a message on stderr. -** -** The error handler function should be of type objc_error_handler -** The first parameter is an object instance of relevance. -** The second parameter is an error code. -** The third parameter is a format string in the printf style. -** The fourth parameter is a variable list of arguments. -*/ +/* Error handling + + Call objc_error() or objc_verror() to record an error; this error + routine will generally exit the program but not necessarily if the + user has installed his own error handler. + + Call objc_set_error_handler to assign your own function for + handling errors. The function should return YES if it is ok + to continue execution, or return NO or just abort if the + program should be stopped. The default error handler is just to + print a message on stderr. + + The error handler function should be of type objc_error_handler + The first parameter is an object instance of relevance. + The second parameter is an error code. + The third parameter is a format string in the printf style. + The fourth parameter is a variable list of arguments. */ 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); extern 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. -*/ +/* 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 */ @@ -139,10 +133,8 @@ extern objc_error_handler objc_set_error_handler(objc_error_handler func); #define OBJC_ERR_BAD_STATE 40 /* Bad thread state */ -/* -** Set this variable nonzero to print a line describing each -** message that is sent. (this is currently disabled) -*/ +/* Set this variable nonzero to print a line describing each + message that is sent. (this is currently disabled) */ extern BOOL objc_trace; @@ -160,14 +152,12 @@ struct objc_static_instances #endif }; -/* -** Whereas a Module (defined further down) is the root (typically) of a file, -** a Symtab is the root of the class and category definitions within the -** module. -** -** A Symtab contains a variable length array of pointers to classes and -** categories defined in the module. -*/ +/* Whereas a Module (defined further down) is the root (typically) of a file, + a Symtab is the root of the class and category definitions within the + module. + + A Symtab contains a variable length array of pointers to classes and + categories defined in the module. */ typedef struct objc_symtab { unsigned long sel_ref_cnt; /* Unknown. */ SEL refs; /* Unknown. */ @@ -431,11 +421,14 @@ objc_EXPORT void *(*_objc_calloc)(size_t, size_t); objc_EXPORT void (*_objc_free)(void *); /* -** Hook for method forwarding. This makes it easy to substitute a +** Hooks for method forwarding. This makes it easy to substitute a ** library, such as ffcall, that implements closures, thereby avoiding -** gcc's __builtin_apply problems. +** gcc's __builtin_apply problems. __objc_msg_forward2's result will +** be preferred over that of __objc_msg_forward if both are set and +** return non-NULL. */ objc_EXPORT IMP (*__objc_msg_forward)(SEL); +objc_EXPORT IMP (*__objc_msg_forward2)(id, SEL); Method_t class_get_class_method(MetaClass _class, SEL aSel); diff --git a/libobjc/sendmsg.c b/libobjc/sendmsg.c index 9453ef3dd46..c1aed1c0f9a 100644 --- a/libobjc/sendmsg.c +++ b/libobjc/sendmsg.c @@ -52,10 +52,15 @@ Boston, MA 02110-1301, USA. */ /* The uninstalled dispatch table */ struct sarray *__objc_uninstalled_dtable = 0; /* !T:MUTEX */ -/* Hook for method forwarding. If it is set, is invoked to return a - function that performs the real forwarding. Otherwise the libgcc - based functions (__builtin_apply and friends) are used. */ +/* Two hooks for method forwarding. If either is set, it is invoked + * to return a function that performs the real forwarding. If both + * are set, the result of __objc_msg_forward2 will be preferred over + * that of __objc_msg_forward. If both return NULL or are unset, + * the libgcc based functions (__builtin_apply and friends) are + * used. + */ IMP (*__objc_msg_forward) (SEL) = NULL; +IMP (*__objc_msg_forward2) (id, SEL) = NULL; /* Send +initialize to class */ static void __objc_send_initialize (Class); @@ -69,8 +74,7 @@ static void __objc_init_install_dtable (id, SEL); return type for the selector. __objc_block_forward for structures. __objc_double_forward for floats/doubles. - __objc_word_forward for pointers or types that fit in registers. - */ + __objc_word_forward for pointers or types that fit in registers. */ static double __objc_double_forward (id, SEL, ...); static id __objc_word_forward (id, SEL, ...); typedef struct { id many[8]; } __big; @@ -87,10 +91,11 @@ id nil_method (id, SEL); /* Given a selector, return the proper forwarding implementation. */ inline IMP -__objc_get_forward_imp (SEL sel) +__objc_get_forward_imp (id rcv, SEL sel) { /* If a custom forwarding hook was registered, try getting a forwarding - * function from it. */ + function from it. There are two forward routine hooks, one that + takes the receiver as an argument and one that does not. */ if (__objc_msg_forward) { IMP result; @@ -99,7 +104,7 @@ __objc_get_forward_imp (SEL sel) } /* In all other cases, use the default forwarding functions built using - * __builtin_apply and friends. */ + __builtin_apply and friends. */ { const char *t = sel->sel_types; @@ -168,7 +173,7 @@ get_imp (Class class, SEL sel) is not in the dispatch table. So the method just doesn't exist for the class. Return the forwarding implementation. */ - res = __objc_get_forward_imp (sel); + res = __objc_get_forward_imp ((id)class, sel); } } } @@ -237,7 +242,7 @@ objc_msg_lookup (id receiver, SEL op) { /* If the method still just doesn't exist for the class, attempt to forward the method. */ - result = __objc_get_forward_imp (op); + result = __objc_get_forward_imp (receiver, op); } } }