In libobjc/: 2010-10-14 Nicola Pero <nicola.pero@meta-innovation.com>
In libobjc/: 2010-10-14 Nicola Pero <nicola.pero@meta-innovation.com> * init.c (__objc_init_protocol): New function which fixes up a protocol's class pointer, registers it with the runtime, register all protocol selectors and registers associated protocols too. (objc_init_statics): Detect if we are initializing protocols, and if so, use __objc_init_protocol instead of only fixing up the class pointer. (__objc_init_protocls): Use __objc_init_protocol. * objc-private/module-abi-8.h: Updated comments. * objc-private/runtime.h (__objc_register_selectors_from_description_list): New. * selector.c (__objc_register_selectors_from_description_list): New. (struct objc_method_description_list): Declare. * Protocol.m ([-descriptionForInstanceMethod:]): Use sel_get_name when accessing the name of a method, which is now correctly a SEL. ([-descriptionForClassMethod:]): Same change. * protocols.c (protocol_getMethodDescription): Same change. * objc/runtime.h: Updated comments. (sel_registerTypedName): Fixed typo in function name. From-SVN: r165499
This commit is contained in:
parent
fbbf834e27
commit
f7185d4791
8 changed files with 152 additions and 42 deletions
|
@ -1,3 +1,24 @@
|
||||||
|
2010-10-14 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
|
* init.c (__objc_init_protocol): New function which fixes up a
|
||||||
|
protocol's class pointer, registers it with the runtime, register
|
||||||
|
all protocol selectors and registers associated protocols too.
|
||||||
|
(objc_init_statics): Detect if we are initializing protocols, and
|
||||||
|
if so, use __objc_init_protocol instead of only fixing up the
|
||||||
|
class pointer.
|
||||||
|
(__objc_init_protocls): Use __objc_init_protocol.
|
||||||
|
* objc-private/module-abi-8.h: Updated comments.
|
||||||
|
* objc-private/runtime.h
|
||||||
|
(__objc_register_selectors_from_description_list): New.
|
||||||
|
* selector.c (__objc_register_selectors_from_description_list):
|
||||||
|
New. (struct objc_method_description_list): Declare.
|
||||||
|
* Protocol.m ([-descriptionForInstanceMethod:]): Use sel_get_name
|
||||||
|
when accessing the name of a method, which is now correctly a SEL.
|
||||||
|
([-descriptionForClassMethod:]): Same change.
|
||||||
|
* protocols.c (protocol_getMethodDescription): Same change.
|
||||||
|
* objc/runtime.h: Updated comments.
|
||||||
|
(sel_registerTypedName): Fixed typo in function name.
|
||||||
|
|
||||||
2010-10-13 Nicola Pero <nicola.pero@meta-innovation.com>
|
2010-10-13 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
PR libobjc/23214
|
PR libobjc/23214
|
||||||
|
|
|
@ -85,7 +85,7 @@ struct objc_method_description_list {
|
||||||
if (instance_methods)
|
if (instance_methods)
|
||||||
for (i = 0; i < instance_methods->count; i++)
|
for (i = 0; i < instance_methods->count; i++)
|
||||||
{
|
{
|
||||||
if (!strcmp ((char*)instance_methods->list[i].name, name))
|
if (!strcmp (sel_get_name (instance_methods->list[i].name), name))
|
||||||
return &(instance_methods->list[i]);
|
return &(instance_methods->list[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ struct objc_method_description_list {
|
||||||
if (class_methods)
|
if (class_methods)
|
||||||
for (i = 0; i < class_methods->count; i++)
|
for (i = 0; i < class_methods->count; i++)
|
||||||
{
|
{
|
||||||
if (!strcmp ((char*)class_methods->list[i].name, name))
|
if (!strcmp (sel_get_name (class_methods->list[i].name), name))
|
||||||
return &(class_methods->list[i]);
|
return &(class_methods->list[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
#include "objc-private/objc-list.h"
|
#include "objc-private/objc-list.h"
|
||||||
#include "objc-private/runtime.h"
|
#include "objc-private/runtime.h"
|
||||||
#include "objc-private/objc-sync.h" /* For __objc_sync_init() */
|
#include "objc-private/objc-sync.h" /* For __objc_sync_init() */
|
||||||
#include "objc-private/protocols.h" /* For __objc_protocols_init() and __objc_protocols_add_protocol() */
|
#include "objc-private/protocols.h" /* For __objc_protocols_init(),
|
||||||
|
__objc_protocols_add_protocol()
|
||||||
|
__objc_protocols_register_selectors() */
|
||||||
|
|
||||||
/* The version number of this runtime. This must match the number
|
/* The version number of this runtime. This must match the number
|
||||||
defined in gcc (objc-act.c). */
|
defined in gcc (objc-act.c). */
|
||||||
|
@ -70,6 +72,9 @@ static void init_check_module_version (Module_t);
|
||||||
/* Assign isa links to protos. */
|
/* Assign isa links to protos. */
|
||||||
static void __objc_init_protocols (struct objc_protocol_list *protos);
|
static void __objc_init_protocols (struct objc_protocol_list *protos);
|
||||||
|
|
||||||
|
/* Assign isa link to a protocol, and register it. */
|
||||||
|
static void __objc_init_protocol (struct objc_protocol *protocol);
|
||||||
|
|
||||||
/* Add protocol to class. */
|
/* Add protocol to class. */
|
||||||
static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
|
static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
|
||||||
|
|
||||||
|
@ -490,11 +495,27 @@ objc_init_statics (void)
|
||||||
they were attached to classes or categories, and the
|
they were attached to classes or categories, and the
|
||||||
class/category loading code automatically fixes them
|
class/category loading code automatically fixes them
|
||||||
up), and some of them may not. We really need to go
|
up), and some of them may not. We really need to go
|
||||||
through the whole list to be sure! */
|
through the whole list to be sure! Protocols are
|
||||||
|
also special because we want to register them and
|
||||||
|
register all their selectors. */
|
||||||
id *inst;
|
id *inst;
|
||||||
|
|
||||||
for (inst = &statics->instances[0]; *inst; inst++)
|
if (strcmp (statics->class_name, "Protocol") == 0)
|
||||||
(*inst)->class_pointer = class;
|
{
|
||||||
|
/* Protocols are special, because not only we want
|
||||||
|
to fix up their class pointers, but we also want
|
||||||
|
to register them and their selectors with the
|
||||||
|
runtime. */
|
||||||
|
for (inst = &statics->instances[0]; *inst; inst++)
|
||||||
|
__objc_init_protocol ((struct objc_protocol *)*inst);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Other static instances (typically constant strings) are
|
||||||
|
easier as we just fix up their class pointers. */
|
||||||
|
for (inst = &statics->instances[0]; *inst; inst++)
|
||||||
|
(*inst)->class_pointer = class;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (module_initialized)
|
if (module_initialized)
|
||||||
|
@ -843,6 +864,49 @@ init_check_module_version (Module_t module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* __objc_init_protocol must be called with __objc_runtime_mutex
|
||||||
|
already locked, and the "Protocol" class already registered. */
|
||||||
|
static void
|
||||||
|
__objc_init_protocol (struct objc_protocol *protocol)
|
||||||
|
{
|
||||||
|
static Class proto_class = 0;
|
||||||
|
|
||||||
|
if (! proto_class)
|
||||||
|
proto_class = objc_get_class ("Protocol");
|
||||||
|
|
||||||
|
if (((size_t)protocol->class_pointer) == PROTOCOL_VERSION)
|
||||||
|
{
|
||||||
|
/* Assign class pointer */
|
||||||
|
protocol->class_pointer = proto_class;
|
||||||
|
|
||||||
|
/* Register all the selectors in the protocol with the runtime.
|
||||||
|
This both registers the selectors with the right types, and
|
||||||
|
it also fixes up the 'struct objc_method' structures inside
|
||||||
|
the protocol so that each method_name (a char * as compiled
|
||||||
|
by the compiler) is replaced with the appropriate runtime
|
||||||
|
SEL. */
|
||||||
|
if (protocol->class_methods)
|
||||||
|
__objc_register_selectors_from_description_list (protocol->class_methods);
|
||||||
|
|
||||||
|
if (protocol->instance_methods)
|
||||||
|
__objc_register_selectors_from_description_list (protocol->instance_methods);
|
||||||
|
|
||||||
|
/* Register the protocol in the hashtable or protocols by
|
||||||
|
name. */
|
||||||
|
__objc_protocols_add_protocol (protocol->protocol_name, protocol);
|
||||||
|
|
||||||
|
/* Init super protocols */
|
||||||
|
__objc_init_protocols (protocol->protocol_list);
|
||||||
|
}
|
||||||
|
else if (protocol->class_pointer != proto_class)
|
||||||
|
{
|
||||||
|
_objc_abort ("Version %d doesn't match runtime protocol version %d\n",
|
||||||
|
(int) ((char *) protocol->class_pointer
|
||||||
|
- (char *) 0),
|
||||||
|
PROTOCOL_VERSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
__objc_init_protocols (struct objc_protocol_list *protos)
|
__objc_init_protocols (struct objc_protocol_list *protos)
|
||||||
{
|
{
|
||||||
|
@ -871,25 +935,7 @@ __objc_init_protocols (struct objc_protocol_list *protos)
|
||||||
for (i = 0; i < protos->count; i++)
|
for (i = 0; i < protos->count; i++)
|
||||||
{
|
{
|
||||||
struct objc_protocol *aProto = protos->list[i];
|
struct objc_protocol *aProto = protos->list[i];
|
||||||
if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
|
__objc_init_protocol (aProto);
|
||||||
{
|
|
||||||
/* Assign class pointer */
|
|
||||||
aProto->class_pointer = proto_class;
|
|
||||||
|
|
||||||
/* Register the protocol in the hashtable or protocols by
|
|
||||||
name. */
|
|
||||||
__objc_protocols_add_protocol (aProto->protocol_name, aProto);
|
|
||||||
|
|
||||||
/* Init super protocols */
|
|
||||||
__objc_init_protocols (aProto->protocol_list);
|
|
||||||
}
|
|
||||||
else if (protos->list[i]->class_pointer != proto_class)
|
|
||||||
{
|
|
||||||
_objc_abort ("Version %d doesn't match runtime protocol version %d\n",
|
|
||||||
(int) ((char *) protos->list[i]->class_pointer
|
|
||||||
- (char *) 0),
|
|
||||||
PROTOCOL_VERSION);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
objc_mutex_unlock (__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
|
|
@ -115,13 +115,15 @@ struct objc_ivar_list
|
||||||
problem is a singly linked list of methods. */
|
problem is a singly linked list of methods. */
|
||||||
struct objc_method
|
struct objc_method
|
||||||
{
|
{
|
||||||
SEL method_name; /* This variable is the method's name. It
|
SEL method_name; /* This variable is the method's name.
|
||||||
is a char*. The unique integer passed
|
The compiler puts a char* here, and
|
||||||
to objc_msg_send is a char* too. It is
|
it's replaced by a real SEL at runtime
|
||||||
compared against method_name using
|
when the method is registered. */
|
||||||
strcmp. */
|
|
||||||
const char* method_types; /* Description of the method's parameter
|
const char* method_types; /* Description of the method's parameter
|
||||||
list. Useful for debuggers. */
|
list. Used when registering the
|
||||||
|
selector with the runtime. When that
|
||||||
|
happens, method_name will contain the
|
||||||
|
method's parameter list. */
|
||||||
IMP method_imp; /* Address of the method in the
|
IMP method_imp; /* Address of the method in the
|
||||||
executable. */
|
executable. */
|
||||||
};
|
};
|
||||||
|
@ -139,7 +141,12 @@ struct objc_method_list
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Currently defined in Protocol.m (that definition should go away
|
/* Currently defined in Protocol.m (that definition should go away
|
||||||
once we include this file). */
|
once we include this file). Note that a 'struct
|
||||||
|
objc_method_description' as embedded inside a Protocol uses the
|
||||||
|
same trick as a 'struct objc_method': the method_name is a 'char *'
|
||||||
|
according to the compiler, who puts the method name as a string in
|
||||||
|
there. At runtime, the selectors need to be registered, and the
|
||||||
|
method_name then becomes a SEL. */
|
||||||
struct objc_method_description_list
|
struct objc_method_description_list
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
|
|
|
@ -60,6 +60,8 @@ extern void __objc_install_premature_dtable(Class); /* (objc-dispatch.c) */
|
||||||
extern void __objc_resolve_class_links(void); /* (objc-class.c) */
|
extern void __objc_resolve_class_links(void); /* (objc-class.c) */
|
||||||
extern void __objc_register_selectors_from_class(Class); /* (objc-sel.c) */
|
extern void __objc_register_selectors_from_class(Class); /* (objc-sel.c) */
|
||||||
extern void __objc_register_selectors_from_list (struct objc_method_list *); /* (selector.c) */
|
extern void __objc_register_selectors_from_list (struct objc_method_list *); /* (selector.c) */
|
||||||
|
extern void __objc_register_selectors_from_description_list
|
||||||
|
(struct objc_method_description_list *method_list); /* (selector.c) */
|
||||||
extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */
|
extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */
|
||||||
|
|
||||||
extern int __objc_init_thread_system(void); /* thread.c */
|
extern int __objc_init_thread_system(void); /* thread.c */
|
||||||
|
|
|
@ -195,7 +195,7 @@ objc_EXPORT SEL sel_registerName (const char *name);
|
||||||
Compatibility Note: the Apple/NeXT runtime has untyped selectors,
|
Compatibility Note: the Apple/NeXT runtime has untyped selectors,
|
||||||
so it does not have this function, which is specific to the GNU
|
so it does not have this function, which is specific to the GNU
|
||||||
Runtime. */
|
Runtime. */
|
||||||
objc_EXPORT SEL set_registerTypedName (const char *name, const char *type);
|
objc_EXPORT SEL sel_registerTypedName (const char *name, const char *type);
|
||||||
|
|
||||||
/* Return YES if first_selector is the same as second_selector, and NO
|
/* Return YES if first_selector is the same as second_selector, and NO
|
||||||
if not. */
|
if not. */
|
||||||
|
@ -505,7 +505,7 @@ objc_EXPORT Method * class_copyMethodList (Class class_, unsigned int *numberOfR
|
||||||
objc_EXPORT unsigned int method_getNumberOfArguments (Method method);
|
objc_EXPORT unsigned int method_getNumberOfArguments (Method method);
|
||||||
|
|
||||||
/* Return the string encoding for the return type of method 'method'.
|
/* Return the string encoding for the return type of method 'method'.
|
||||||
The string is a standard NULL-terminated string in an area of
|
The string is a standard zero-terminated string in an area of
|
||||||
memory allocated with malloc(); you should free it with free() when
|
memory allocated with malloc(); you should free it with free() when
|
||||||
you finish using it. Return an empty string if method is NULL. */
|
you finish using it. Return an empty string if method is NULL. */
|
||||||
objc_EXPORT char * method_copyReturnType (Method method);
|
objc_EXPORT char * method_copyReturnType (Method method);
|
||||||
|
@ -513,7 +513,7 @@ objc_EXPORT char * method_copyReturnType (Method method);
|
||||||
/* Return the string encoding for the argument type of method
|
/* Return the string encoding for the argument type of method
|
||||||
'method', argument number 'argumentNumber' ('argumentNumber' is 0
|
'method', argument number 'argumentNumber' ('argumentNumber' is 0
|
||||||
for self, 1 for _cmd, and 2 or more for the additional arguments if
|
for self, 1 for _cmd, and 2 or more for the additional arguments if
|
||||||
any). The string is a standard NULL-terminated string in an area
|
any). The string is a standard zero-terminated string in an area
|
||||||
of memory allocated with malloc(); you should free it with free()
|
of memory allocated with malloc(); you should free it with free()
|
||||||
when you finish using it. Return an empty string if method is NULL
|
when you finish using it. Return an empty string if method is NULL
|
||||||
or if 'argumentNumber' refers to a non-existing argument. */
|
or if 'argumentNumber' refers to a non-existing argument. */
|
||||||
|
@ -524,10 +524,10 @@ objc_EXPORT char * method_copyArgumentType (Method method, unsigned int argument
|
||||||
'returnValue' string, which is of size 'returnValueSize'. No more
|
'returnValue' string, which is of size 'returnValueSize'. No more
|
||||||
than 'returnValueSize' characters are copied; if the encoding is
|
than 'returnValueSize' characters are copied; if the encoding is
|
||||||
smaller than 'returnValueSize', the rest of 'returnValue' is filled
|
smaller than 'returnValueSize', the rest of 'returnValue' is filled
|
||||||
with NULLs. If it is bigger, it is truncated (and would not be
|
with zeros. If it is bigger, it is truncated (and would not be
|
||||||
NULL-terminated). You should supply a big enough
|
zero-terminated). You should supply a big enough
|
||||||
'returnValueSize'. If the method is NULL, returnValue is set to a
|
'returnValueSize'. If the method is NULL, returnValue is set to a
|
||||||
string of NULLs. */
|
string of zeros. */
|
||||||
objc_EXPORT void method_getReturnType (Method method, char *returnValue,
|
objc_EXPORT void method_getReturnType (Method method, char *returnValue,
|
||||||
size_t returnValueSize);
|
size_t returnValueSize);
|
||||||
|
|
||||||
|
@ -538,10 +538,10 @@ objc_EXPORT void method_getReturnType (Method method, char *returnValue,
|
||||||
'returnValue' string, which is of size 'returnValueSize'. No more
|
'returnValue' string, which is of size 'returnValueSize'. No more
|
||||||
than 'returnValueSize' characters are copied; if the encoding is
|
than 'returnValueSize' characters are copied; if the encoding is
|
||||||
smaller than 'returnValueSize', the rest of 'returnValue' is filled
|
smaller than 'returnValueSize', the rest of 'returnValue' is filled
|
||||||
with NULLs. If it is bigger, it is truncated (and would not be
|
with zeros. If it is bigger, it is truncated (and would not be
|
||||||
NULL-terminated). You should supply a big enough
|
zero-terminated). You should supply a big enough
|
||||||
'returnValueSize'. If the method is NULL, returnValue is set to a
|
'returnValueSize'. If the method is NULL, returnValue is set to a
|
||||||
string of NULLs. */
|
string of zeros. */
|
||||||
objc_EXPORT void method_getArgumentType (Method method, unsigned int argumentNumber,
|
objc_EXPORT void method_getArgumentType (Method method, unsigned int argumentNumber,
|
||||||
char *returnValue, size_t returnValueSize);
|
char *returnValue, size_t returnValueSize);
|
||||||
|
|
||||||
|
|
|
@ -383,7 +383,7 @@ struct objc_method_description protocol_getMethodDescription (Protocol *protocol
|
||||||
{
|
{
|
||||||
for (i = 0; i < methods->count; i++)
|
for (i = 0; i < methods->count; i++)
|
||||||
{
|
{
|
||||||
if (strcmp ((char*)(methods->list[i].name), selector_name) == 0)
|
if (strcmp (sel_getName (methods->list[i].name), selector_name) == 0)
|
||||||
return methods->list[i];
|
return methods->list[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,40 @@ __objc_register_selectors_from_list (MethodList_t method_list)
|
||||||
objc_mutex_unlock (__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Temporary definition while we include objc/objc-api.h instead of
|
||||||
|
objc-private/module-abi-8.h. It should go away once we include
|
||||||
|
module-abi-8.h. */
|
||||||
|
struct objc_method_description_list
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
struct objc_method_description list[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The same as __objc_register_selectors_from_list, but works on a
|
||||||
|
struct objc_method_description_list* instead of a struct
|
||||||
|
objc_method_list*. This is only used for protocols, which have
|
||||||
|
lists of method descriptions, not methods.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
__objc_register_selectors_from_description_list
|
||||||
|
(struct objc_method_description_list *method_list)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
while (i < method_list->count)
|
||||||
|
{
|
||||||
|
struct objc_method_description *method = &method_list->list[i];
|
||||||
|
if (method->name)
|
||||||
|
{
|
||||||
|
method->name
|
||||||
|
= __sel_register_typed_name ((const char *) method->name,
|
||||||
|
method->types, 0, YES);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/* Register instance methods as class methods for root classes */
|
/* Register instance methods as class methods for root classes */
|
||||||
void __objc_register_instance_methods_to_class (Class class)
|
void __objc_register_instance_methods_to_class (Class class)
|
||||||
|
|
Loading…
Add table
Reference in a new issue