(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:
Richard Kenner 1997-03-15 07:56:13 -05:00
parent e335b3ee7e
commit f0a5229172
1 changed files with 140 additions and 5 deletions

View File

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