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
This commit is contained in:
Andrew Ruder 2007-04-09 18:04:50 +00:00 committed by Andrew Pinski
parent ecc0fc15ec
commit 80ae8e8ad2
3 changed files with 59 additions and 54 deletions

View File

@ -1,3 +1,10 @@
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>
* Makefile.in: Add dummy install-pdf target.

View File

@ -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);

View File

@ -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);
}
}
}