Commit 80ae8e8a by Andrew Ruder Committed by Andrew Pinski

sendmsg.c: Added __objc_msg_forward2...

2007-04-09  Andrew Ruder  <andy@aeruder.net>

        * 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
parent ecc0fc15
2007-04-09 Andrew Ruder <andy@aeruder.net>
* 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 <brooks.moses@codesourcery.com> 2007-03-01 Brooks Moses <brooks.moses@codesourcery.com>
* Makefile.in: Add dummy install-pdf target. * Makefile.in: Add dummy install-pdf target.
......
...@@ -41,11 +41,9 @@ extern "C" { ...@@ -41,11 +41,9 @@ extern "C" {
/* For functions which return Method_t */ /* For functions which return Method_t */
#define METHOD_NULL (Method_t)0 #define METHOD_NULL (Method_t)0
/* Boolean typedefs */ /* Boolean typedefs */
/* /* Method descriptor returned by introspective Object methods.
** Method descriptor returned by introspective Object methods. This is really just the first part of the more complete objc_method
** This is really just the first part of the more complete objc_method structure defined below and used internally by the runtime. */
** structure defined below and used internally by the runtime.
*/
struct objc_method_description struct objc_method_description
{ {
SEL name; /* this is a selector, not a string */ SEL name; /* this is a selector, not a string */
...@@ -85,36 +83,32 @@ struct objc_method_description ...@@ -85,36 +83,32 @@ struct objc_method_description
#define _C_COMPLEX 'j' #define _C_COMPLEX 'j'
/* /* Error handling
** Error handling
** Call objc_error() or objc_verror() to record an error; this error
** Call objc_error() or objc_verror() to record an error; this error routine will generally exit the program but not necessarily if the
** routine will generally exit the program but not necessarily if the user has installed his own error handler.
** user has installed his own error handler.
** Call objc_set_error_handler to assign your own function for
** Call objc_set_error_handler to assign your own function for handling errors. The function should return YES if it is ok
** handling errors. The function should return YES if it is ok to continue execution, or return NO or just abort if the
** to continue execution, or return NO or just abort if the program should be stopped. The default error handler is just to
** program should be stopped. The default error handler is just to print a message on stderr.
** print a message on stderr.
** The error handler function should be of type objc_error_handler
** The error handler function should be of type objc_error_handler The first parameter is an object instance of relevance.
** The first parameter is an object instance of relevance. The second parameter is an error code.
** The second parameter is an error code. The third parameter is a format string in the printf style.
** The third parameter is a format string in the printf style. The fourth parameter is a variable list of arguments. */
** The fourth parameter is a variable list of arguments.
*/
extern void objc_error(id object, int code, const char* fmt, ...); 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); 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); 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); extern objc_error_handler objc_set_error_handler(objc_error_handler func);
/* /* Error codes
** Error codes These are used by the runtime library, and your
** These are used by the runtime library, and your error handling may use them to determine if the error is
** error handling may use them to determine if the error is hard or soft thus whether execution can continue or abort. */
** hard or soft thus whether execution can continue or abort.
*/
#define OBJC_ERR_UNKNOWN 0 /* Generic error */ #define OBJC_ERR_UNKNOWN 0 /* Generic error */
#define OBJC_ERR_OBJC_VERSION 1 /* Incorrect runtime version */ #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); ...@@ -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 */ #define OBJC_ERR_BAD_STATE 40 /* Bad thread state */
/* /* Set this variable nonzero to print a line describing each
** Set this variable nonzero to print a line describing each message that is sent. (this is currently disabled) */
** message that is sent. (this is currently disabled)
*/
extern BOOL objc_trace; extern BOOL objc_trace;
...@@ -160,14 +152,12 @@ struct objc_static_instances ...@@ -160,14 +152,12 @@ struct objc_static_instances
#endif #endif
}; };
/* /* Whereas a Module (defined further down) is the root (typically) of a file,
** 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
** a Symtab is the root of the class and category definitions within the module.
** module.
** A Symtab contains a variable length array of pointers to classes and
** A Symtab contains a variable length array of pointers to classes and categories defined in the module. */
** categories defined in the module.
*/
typedef struct objc_symtab { typedef struct objc_symtab {
unsigned long sel_ref_cnt; /* Unknown. */ unsigned long sel_ref_cnt; /* Unknown. */
SEL refs; /* Unknown. */ SEL refs; /* Unknown. */
...@@ -431,11 +421,14 @@ objc_EXPORT void *(*_objc_calloc)(size_t, size_t); ...@@ -431,11 +421,14 @@ objc_EXPORT void *(*_objc_calloc)(size_t, size_t);
objc_EXPORT void (*_objc_free)(void *); 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 ** 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_forward)(SEL);
objc_EXPORT IMP (*__objc_msg_forward2)(id, SEL);
Method_t class_get_class_method(MetaClass _class, SEL aSel); Method_t class_get_class_method(MetaClass _class, SEL aSel);
......
...@@ -52,10 +52,15 @@ Boston, MA 02110-1301, USA. */ ...@@ -52,10 +52,15 @@ Boston, MA 02110-1301, USA. */
/* The uninstalled dispatch table */ /* The uninstalled dispatch table */
struct sarray *__objc_uninstalled_dtable = 0; /* !T:MUTEX */ struct sarray *__objc_uninstalled_dtable = 0; /* !T:MUTEX */
/* Hook for method forwarding. If it is set, is invoked to return a /* Two hooks for method forwarding. If either is set, it is invoked
function that performs the real forwarding. Otherwise the libgcc * to return a function that performs the real forwarding. If both
based functions (__builtin_apply and friends) are used. */ * 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_forward) (SEL) = NULL;
IMP (*__objc_msg_forward2) (id, SEL) = NULL;
/* Send +initialize to class */ /* Send +initialize to class */
static void __objc_send_initialize (Class); static void __objc_send_initialize (Class);
...@@ -69,8 +74,7 @@ static void __objc_init_install_dtable (id, SEL); ...@@ -69,8 +74,7 @@ static void __objc_init_install_dtable (id, SEL);
return type for the selector. return type for the selector.
__objc_block_forward for structures. __objc_block_forward for structures.
__objc_double_forward for floats/doubles. __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 double __objc_double_forward (id, SEL, ...);
static id __objc_word_forward (id, SEL, ...); static id __objc_word_forward (id, SEL, ...);
typedef struct { id many[8]; } __big; typedef struct { id many[8]; } __big;
...@@ -87,10 +91,11 @@ id nil_method (id, SEL); ...@@ -87,10 +91,11 @@ id nil_method (id, SEL);
/* Given a selector, return the proper forwarding implementation. */ /* Given a selector, return the proper forwarding implementation. */
inline inline
IMP 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 /* 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) if (__objc_msg_forward)
{ {
IMP result; IMP result;
...@@ -99,7 +104,7 @@ __objc_get_forward_imp (SEL sel) ...@@ -99,7 +104,7 @@ __objc_get_forward_imp (SEL sel)
} }
/* In all other cases, use the default forwarding functions built using /* 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; const char *t = sel->sel_types;
...@@ -168,7 +173,7 @@ get_imp (Class class, SEL sel) ...@@ -168,7 +173,7 @@ get_imp (Class class, SEL sel)
is not in the dispatch table. So the method just is not in the dispatch table. So the method just
doesn't exist for the class. Return the forwarding doesn't exist for the class. Return the forwarding
implementation. */ 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) ...@@ -237,7 +242,7 @@ objc_msg_lookup (id receiver, SEL op)
{ {
/* If the method still just doesn't exist for the /* If the method still just doesn't exist for the
class, attempt to forward the method. */ class, attempt to forward the method. */
result = __objc_get_forward_imp (op); result = __objc_get_forward_imp (receiver, op);
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment