mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-29 01:25:13 +08:00
(OBJC_VERSION): Increment version.
(objc_send_load, __objc_send_load): New functions. (__objc_send_message_in_list): New function. (__objc_force_linking): New function. (__objc_exec_class): Don't call _objc_load_callback here. (__objc_exec_class): Access statics from their new place in the defs variable. From-SVN: r13709
This commit is contained in:
parent
e335b3ee7e
commit
f0a5229172
145
gcc/objc/init.c
145
gcc/objc/init.c
@ -27,7 +27,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* The version number of this runtime. This must match the number
|
||||
defined in gcc (objc-act.c) */
|
||||
#define OBJC_VERSION 7
|
||||
#define OBJC_VERSION 8
|
||||
#define PROTOCOL_VERSION 2
|
||||
|
||||
/* This list contains all modules currently loaded into the runtime */
|
||||
@ -67,6 +67,25 @@ extern SEL
|
||||
__sel_register_typed_name (const char *name, const char *types,
|
||||
struct objc_selector *orig, BOOL is_const);
|
||||
|
||||
/* Send +load to all classes and categories from a module that implement
|
||||
this method */
|
||||
static void __objc_send_load(Module_t module);
|
||||
|
||||
/* This list contains all the classes in the runtime system for whom their
|
||||
superclasses are not yet know to the runtime. */
|
||||
static struct objc_list* unresolved_classes = 0;
|
||||
|
||||
/* Static function used to references the Object and NXConstantString classes. */
|
||||
static void
|
||||
__objc_force_linking (void)
|
||||
{
|
||||
extern void __objc_linking (void);
|
||||
__objc_linking ();
|
||||
|
||||
/* Call the function to avoid compiler warning */
|
||||
__objc_force_linking ();
|
||||
}
|
||||
|
||||
/* Run through the statics list, removing modules as soon as all its statics
|
||||
have been initialized. */
|
||||
static void
|
||||
@ -143,6 +162,10 @@ __objc_exec_class (Module_t module)
|
||||
/* The symbol table (defined in objc-api.h) generated by gcc */
|
||||
Symtab_t symtab = module->symtab;
|
||||
|
||||
/* The statics in this module */
|
||||
struct objc_static_instances **statics
|
||||
= symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
|
||||
|
||||
/* Entry used to traverse hash lists */
|
||||
struct objc_list** cell;
|
||||
|
||||
@ -196,6 +219,7 @@ __objc_exec_class (Module_t module)
|
||||
for (i = 0; i < symtab->cls_def_cnt; ++i)
|
||||
{
|
||||
Class class = (Class) symtab->defs[i];
|
||||
const char* superclass = (char*)class->super_class;
|
||||
|
||||
/* Make sure we have what we think. */
|
||||
assert (CLS_ISCLASS(class));
|
||||
@ -216,8 +240,10 @@ __objc_exec_class (Module_t module)
|
||||
if (class->protocols)
|
||||
__objc_init_protocols (class->protocols);
|
||||
|
||||
if (_objc_load_callback)
|
||||
_objc_load_callback(class, 0);
|
||||
/* Check to see if the superclass is known in this point. If it's not
|
||||
add the class to the unresolved_classes list. */
|
||||
if (superclass && !objc_lookup_class (superclass))
|
||||
unresolved_classes = list_cons (class, unresolved_classes);
|
||||
}
|
||||
|
||||
/* Process category information from the module. */
|
||||
@ -260,8 +286,8 @@ __objc_exec_class (Module_t module)
|
||||
}
|
||||
}
|
||||
|
||||
if (module->statics)
|
||||
uninitialized_statics = list_cons (module->statics, uninitialized_statics);
|
||||
if (statics)
|
||||
uninitialized_statics = list_cons (statics, uninitialized_statics);
|
||||
if (uninitialized_statics)
|
||||
objc_init_statics ();
|
||||
|
||||
@ -306,9 +332,118 @@ __objc_exec_class (Module_t module)
|
||||
unclaimed_proto_list = 0;
|
||||
}
|
||||
|
||||
objc_send_load ();
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
void objc_send_load (void)
|
||||
{
|
||||
if (!__objc_module_list)
|
||||
return;
|
||||
|
||||
/* Try to find out if all the classes loaded so far also have their
|
||||
superclasses known to the runtime. We suppose that the objects that are
|
||||
allocated in the +load method are in general of a class declared in the
|
||||
same module. */
|
||||
if (unresolved_classes)
|
||||
{
|
||||
Class class = unresolved_classes->head;
|
||||
|
||||
while (objc_lookup_class ((char*)class->super_class))
|
||||
{
|
||||
list_remove_head (&unresolved_classes);
|
||||
if (unresolved_classes)
|
||||
class = unresolved_classes->head;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we still have classes for which we don't have yet their super
|
||||
* classes known to the runtime we don't send the +load messages.
|
||||
*/
|
||||
if (unresolved_classes)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Special check to allow sending messages to constant strings in +load
|
||||
methods. If the class is not yet known, even if all the classes are known,
|
||||
delay sending of +load. */
|
||||
if (!objc_lookup_class ("NXConstantString"))
|
||||
return;
|
||||
|
||||
/* Iterate over all modules in the __objc_module_list and call on them the
|
||||
__objc_send_load function that sends the +load message. */
|
||||
list_mapcar (__objc_module_list, (void(*)(void*))__objc_send_load);
|
||||
list_free (__objc_module_list);
|
||||
__objc_module_list = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
__objc_send_message_in_list (MethodList_t method_list, id object, SEL op)
|
||||
{
|
||||
while (method_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Search the method list. */
|
||||
for (i = 0; i < method_list->method_count; i++)
|
||||
{
|
||||
Method_t mth = &method_list->method_list[i];
|
||||
|
||||
if (mth->method_name && sel_eq (mth->method_name, op))
|
||||
{
|
||||
/* The method was found. */
|
||||
(*mth->method_imp) (object, mth->method_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
method_list = method_list->method_next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
__objc_send_load(Module_t module)
|
||||
{
|
||||
/* The runtime mutex is locked in this point */
|
||||
|
||||
Symtab_t symtab = module->symtab;
|
||||
static SEL load_sel = 0;
|
||||
int i;
|
||||
|
||||
if (!load_sel)
|
||||
load_sel = sel_register_name ("load");
|
||||
|
||||
/* Iterate thru classes defined in this module and send them the +load
|
||||
message if they implement it. At this point all methods defined in
|
||||
categories were added to the corresponding class, so all the +load
|
||||
methods of categories are in their corresponding classes. */
|
||||
for (i = 0; i < symtab->cls_def_cnt; i++)
|
||||
{
|
||||
Class class = (Class) symtab->defs[i];
|
||||
MethodList_t method_list = class->class_pointer->methods;
|
||||
|
||||
__objc_send_message_in_list (method_list, (id)class, load_sel);
|
||||
|
||||
/* Call the _objc_load_callback for this class. */
|
||||
if (_objc_load_callback)
|
||||
_objc_load_callback(class, 0);
|
||||
}
|
||||
|
||||
/* Call the _objc_load_callback for categories. Don't register the instance
|
||||
methods as class methods for categories to root classes since they were
|
||||
already added in the class. */
|
||||
for (i = 0; i < symtab->cat_def_cnt; i++)
|
||||
{
|
||||
Category_t category = symtab->defs[i + symtab->cls_def_cnt];
|
||||
Class class = objc_lookup_class (category->class_name);
|
||||
|
||||
if (_objc_load_callback)
|
||||
_objc_load_callback(class, category);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check the version of gcc used to compile `module'*/
|
||||
static void init_check_module_version(Module_t module)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user