]> git.ipfire.org Git - thirdparty/gcc.git/blob - libobjc/init.c
In libobjc/: 2010-10-16 Nicola Pero <nicola.pero@meta-innovation.com>
[thirdparty/gcc.git] / libobjc / init.c
1 /* GNU Objective C Runtime initialization
2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2009
3 Free Software Foundation, Inc.
4 Contributed by Kresten Krab Thorup
5 +load support contributed by Ovidiu Predescu <ovidiu@net-community.com>
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under the
10 terms of the GNU General Public License as published by the Free Software
11 Foundation; either version 3, or (at your option) any later version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 details.
17
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
21
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
26
27 #include "objc-private/common.h"
28 #include "objc-private/error.h"
29 #include "objc/objc-api.h"
30 #include "objc/thr.h"
31 #include "objc-private/hash.h"
32 #include "objc-private/objc-list.h"
33 #include "objc-private/runtime.h"
34 #include "objc-private/objc-sync.h" /* For __objc_sync_init() */
35 #include "objc-private/protocols.h" /* For __objc_protocols_init(),
36 __objc_protocols_add_protocol()
37 __objc_protocols_register_selectors() */
38
39 /* The version number of this runtime. This must match the number
40 defined in gcc (objc-act.c). */
41 #define OBJC_VERSION 8
42 #define PROTOCOL_VERSION 2
43
44 /* This list contains all modules currently loaded into the runtime. */
45 static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */
46
47 /* This list contains all proto_list's not yet assigned class links. */
48 static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */
49
50 /* List of unresolved static instances. */
51 static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
52
53 /* Global runtime "write" mutex. Having a single mutex prevents
54 deadlocks, but reduces concurrency. To improve concurrency, some
55 groups of functions in the runtime have their own separate mutex
56 (eg, __class_table_lock in class.c); to avoid deadlocks, these
57 routines must make sure that they never acquire any other lock
58 while holding their own local lock. Ie, they should lock, execute
59 some C code that does not perform any calls to other runtime
60 functions which may potentially lock different locks, then unlock.
61 If they need to perform any calls to other runtime functions that
62 may potentially lock other locks, then they should use the global
63 __objc_runtime_mutex. */
64 objc_mutex_t __objc_runtime_mutex = 0;
65
66 /* Number of threads that are alive. */
67 int __objc_runtime_threads_alive = 1; /* !T:MUTEX */
68
69 /* Check compiler vs runtime version. */
70 static void init_check_module_version (Module_t);
71
72 /* Assign isa links to protos. */
73 static void __objc_init_protocols (struct objc_protocol_list *protos);
74
75 /* Assign isa link to a protocol, and register it. */
76 static void __objc_init_protocol (struct objc_protocol *protocol);
77
78 /* Add protocol to class. */
79 static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
80
81 /* This is a hook which is called by __objc_exec_class every time a
82 class or a category is loaded into the runtime. This may e.g. help
83 a dynamic loader determine the classes that have been loaded when
84 an object file is dynamically linked in. */
85 void (*_objc_load_callback) (Class class, Category *category); /* !T:SAFE */
86
87 /* Is all categories/classes resolved? */
88 BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
89
90 extern SEL
91 __sel_register_typed_name (const char *name, const char *types,
92 struct objc_selector *orig, BOOL is_const);
93
94 /* Sends +load to all classes and categories in certain situations. */
95 static void objc_send_load (void);
96
97 /* Inserts all the classes defined in module in a tree of classes that
98 resembles the class hierarchy. This tree is traversed in preorder
99 and the classes in its nodes receive the +load message if these
100 methods were not executed before. The algorithm ensures that when
101 the +load method of a class is executed all the superclasses have
102 been already received the +load message. */
103 static void __objc_create_classes_tree (Module_t module);
104
105 static void __objc_call_callback (Module_t module);
106
107 /* A special version that works only before the classes are completely
108 installed in the runtime. */
109 static BOOL class_is_subclass_of_class (Class class, Class superclass);
110
111 typedef struct objc_class_tree {
112 Class class;
113 struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */
114 } objc_class_tree;
115
116 /* This is a linked list of objc_class_tree trees. The head of these
117 trees are root classes (their super class is Nil). These different
118 trees represent different class hierarchies. */
119 static struct objc_list *__objc_class_tree_list = NULL;
120
121 /* Keeps the +load methods who have been already executed. This hash
122 should not be destroyed during the execution of the program. */
123 static cache_ptr __objc_load_methods = NULL;
124
125 /* This function is used when building the class tree used to send
126 ordinately the +load message to all classes needing it. The tree
127 is really needed so that superclasses will get the message before
128 subclasses.
129
130 This tree will contain classes which are being loaded (or have just
131 being loaded), and whose super_class pointers have not yet been
132 resolved. This implies that their super_class pointers point to a
133 string with the name of the superclass; when the first message is
134 sent to the class (/an object of that class) the class links will
135 be resolved, which will replace the super_class pointers with
136 pointers to the actual superclasses.
137
138 Unfortunately, the tree might also contain classes which had been
139 loaded previously, and whose class links have already been
140 resolved.
141
142 This function returns the superclass of a class in both cases, and
143 can be used to build the determine the class relationships while
144 building the tree.
145 */
146 static Class class_superclass_of_class (Class class)
147 {
148 char *super_class_name;
149
150 /* If the class links have been resolved, use the resolved
151 * links. */
152 if (CLS_ISRESOLV (class))
153 return class->super_class;
154
155 /* Else, 'class' has not yet been resolved. This means that its
156 * super_class pointer is really the name of the super class (rather
157 * than a pointer to the actual superclass). */
158 super_class_name = (char *)class->super_class;
159
160 /* Return Nil for a root class. */
161 if (super_class_name == NULL)
162 return Nil;
163
164 /* Lookup the superclass of non-root classes. */
165 return objc_lookup_class (super_class_name);
166 }
167
168
169 /* Creates a tree of classes whose topmost class is directly inherited
170 from `upper' and the bottom class in this tree is
171 `bottom_class'. The classes in this tree are super classes of
172 `bottom_class'. `subclasses' member of each tree node point to the
173 next subclass tree node. */
174
175 static objc_class_tree *
176 create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
177 {
178 Class superclass = bottom_class->super_class ?
179 objc_lookup_class ((char *) bottom_class->super_class)
180 : Nil;
181
182 objc_class_tree *tree, *prev;
183
184 DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
185 DEBUG_PRINTF ("bottom_class = %s, upper = %s\n",
186 (bottom_class ? bottom_class->name : NULL),
187 (upper ? upper->name : NULL));
188
189 tree = prev = objc_calloc (1, sizeof (objc_class_tree));
190 prev->class = bottom_class;
191
192 while (superclass != upper)
193 {
194 tree = objc_calloc (1, sizeof (objc_class_tree));
195 tree->class = superclass;
196 tree->subclasses = list_cons (prev, tree->subclasses);
197 superclass = class_superclass_of_class (superclass);
198 prev = tree;
199 }
200
201 return tree;
202 }
203
204 /* Insert the `class' into the proper place in the `tree' class
205 hierarchy. This function returns a new tree if the class has been
206 successfully inserted into the tree or NULL if the class is not
207 part of the classes hierarchy described by `tree'. This function is
208 private to objc_tree_insert_class (), you should not call it
209 directly. */
210
211 static objc_class_tree *
212 __objc_tree_insert_class (objc_class_tree *tree, Class class)
213 {
214 DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n",
215 tree, class->name);
216
217 if (tree == NULL)
218 return create_tree_of_subclasses_inherited_from (class, NULL);
219 else if (class == tree->class)
220 {
221 /* `class' has been already inserted */
222 DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
223 return tree;
224 }
225 else if (class_superclass_of_class (class) == tree->class)
226 {
227 /* If class is a direct subclass of tree->class then add class to the
228 list of subclasses. First check to see if it wasn't already
229 inserted. */
230 struct objc_list *list = tree->subclasses;
231 objc_class_tree *node;
232
233 while (list)
234 {
235 /* Class has been already inserted; do nothing just return
236 the tree. */
237 if (((objc_class_tree *) list->head)->class == class)
238 {
239 DEBUG_PRINTF ("2. class %s was previously inserted\n",
240 class->name);
241 return tree;
242 }
243 list = list->tail;
244 }
245
246 /* Create a new node class and insert it into the list of subclasses */
247 node = objc_calloc (1, sizeof (objc_class_tree));
248 node->class = class;
249 tree->subclasses = list_cons (node, tree->subclasses);
250 DEBUG_PRINTF ("3. class %s inserted\n", class->name);
251 return tree;
252 }
253 else
254 {
255 /* The class is not a direct subclass of tree->class. Search for
256 class's superclasses in the list of subclasses. */
257 struct objc_list *subclasses = tree->subclasses;
258
259 /* Precondition: the class must be a subclass of tree->class;
260 otherwise return NULL to indicate our caller that it must
261 take the next tree. */
262 if (! class_is_subclass_of_class (class, tree->class))
263 return NULL;
264
265 for (; subclasses != NULL; subclasses = subclasses->tail)
266 {
267 Class aClass = ((objc_class_tree *) (subclasses->head))->class;
268
269 if (class_is_subclass_of_class (class, aClass))
270 {
271 /* If we found one of class's superclasses we insert the
272 class into its subtree and return the original tree
273 since nothing has been changed. */
274 subclasses->head
275 = __objc_tree_insert_class (subclasses->head, class);
276 DEBUG_PRINTF ("4. class %s inserted\n", class->name);
277 return tree;
278 }
279 }
280
281 /* We haven't found a subclass of `class' in the `subclasses'
282 list. Create a new tree of classes whose topmost class is a
283 direct subclass of tree->class. */
284 {
285 objc_class_tree *new_tree
286 = create_tree_of_subclasses_inherited_from (class, tree->class);
287 tree->subclasses = list_cons (new_tree, tree->subclasses);
288 DEBUG_PRINTF ("5. class %s inserted\n", class->name);
289 return tree;
290 }
291 }
292 }
293
294 /* This function inserts `class' in the right tree hierarchy classes. */
295
296 static void
297 objc_tree_insert_class (Class class)
298 {
299 struct objc_list *list_node;
300 objc_class_tree *tree;
301
302 list_node = __objc_class_tree_list;
303 while (list_node)
304 {
305 tree = __objc_tree_insert_class (list_node->head, class);
306 if (tree)
307 {
308 list_node->head = tree;
309 break;
310 }
311 else
312 list_node = list_node->tail;
313 }
314
315 /* If the list was finished but the class hasn't been inserted,
316 insert it here. */
317 if (! list_node)
318 {
319 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
320 __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
321 }
322 }
323
324 /* Traverse tree in preorder. Used to send +load. */
325
326 static void
327 objc_preorder_traverse (objc_class_tree *tree,
328 int level,
329 void (*function) (objc_class_tree *, int))
330 {
331 struct objc_list *node;
332
333 (*function) (tree, level);
334 for (node = tree->subclasses; node; node = node->tail)
335 objc_preorder_traverse (node->head, level + 1, function);
336 }
337
338 /* Traverse tree in postorder. Used to destroy a tree. */
339
340 static void
341 objc_postorder_traverse (objc_class_tree *tree,
342 int level,
343 void (*function) (objc_class_tree *, int))
344 {
345 struct objc_list *node;
346
347 for (node = tree->subclasses; node; node = node->tail)
348 objc_postorder_traverse (node->head, level + 1, function);
349 (*function) (tree, level);
350 }
351
352 /* Used to print a tree class hierarchy. */
353
354 #ifdef DEBUG
355 static void
356 __objc_tree_print (objc_class_tree *tree, int level)
357 {
358 int i;
359
360 for (i = 0; i < level; i++)
361 printf (" ");
362 printf ("%s\n", tree->class->name);
363 }
364 #endif
365
366 /* Walks on a linked list of methods in the reverse order and executes
367 all the methods corresponding to `op' selector. Walking in the
368 reverse order assures the +load of class is executed first and then
369 +load of categories because of the way in which categories are
370 added to the class methods. */
371
372 static void
373 __objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
374 {
375 int i;
376
377 if (! method_list)
378 return;
379
380 /* First execute the `op' message in the following method lists */
381 __objc_send_message_in_list (method_list->method_next, class, op);
382
383 /* Search the method list. */
384 for (i = 0; i < method_list->method_count; i++)
385 {
386 Method_t mth = &method_list->method_list[i];
387
388 if (mth->method_name && sel_eq (mth->method_name, op)
389 && ! objc_hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
390 {
391 /* Add this method into the +load hash table */
392 objc_hash_add (&__objc_load_methods,
393 mth->method_imp,
394 mth->method_imp);
395
396 DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
397
398 /* The method was found and wasn't previously executed. */
399 (*mth->method_imp) ((id)class, mth->method_name);
400
401 break;
402 }
403 }
404 }
405
406 static void
407 __objc_send_load (objc_class_tree *tree,
408 int level __attribute__ ((__unused__)))
409 {
410 static SEL load_sel = 0;
411 Class class = tree->class;
412 MethodList_t method_list = class->class_pointer->methods;
413
414 if (! load_sel)
415 load_sel = sel_register_name ("load");
416
417 __objc_send_message_in_list (method_list, class, load_sel);
418 }
419
420 static void
421 __objc_destroy_class_tree_node (objc_class_tree *tree,
422 int level __attribute__ ((__unused__)))
423 {
424 objc_free (tree);
425 }
426
427 /* This is used to check if the relationship between two classes
428 before the runtime completely installs the classes. */
429
430 static BOOL
431 class_is_subclass_of_class (Class class, Class superclass)
432 {
433 for (; class != Nil;)
434 {
435 if (class == superclass)
436 return YES;
437 class = class_superclass_of_class (class);
438 }
439
440 return NO;
441 }
442
443 /* This list contains all the classes in the runtime system for whom
444 their superclasses are not yet known to the runtime. */
445 static struct objc_list *unresolved_classes = 0;
446
447 /* Extern function used to reference the Object and NXConstantString
448 classes. */
449
450 extern void __objc_force_linking (void);
451
452 void
453 __objc_force_linking (void)
454 {
455 extern void __objc_linking (void);
456 __objc_linking ();
457 }
458
459 /* Run through the statics list, removing modules as soon as all its
460 statics have been initialized. */
461
462 static void
463 objc_init_statics (void)
464 {
465 struct objc_list **cell = &uninitialized_statics;
466 struct objc_static_instances **statics_in_module;
467
468 objc_mutex_lock (__objc_runtime_mutex);
469
470 while (*cell)
471 {
472 int module_initialized = 1;
473
474 for (statics_in_module = (*cell)->head;
475 *statics_in_module; statics_in_module++)
476 {
477 struct objc_static_instances *statics = *statics_in_module;
478 Class class = objc_lookup_class (statics->class_name);
479
480 if (! class)
481 {
482 /* It is unfortunate that this will cause all the
483 statics initialization to be done again (eg, if we
484 already initialized constant strings, and are now
485 initializing protocols, setting module_initialized to
486 0 would cause constant strings to be initialized
487 again). It would be good to be able to track if we
488 have already initialized some of them. */
489 module_initialized = 0;
490 }
491 else
492 {
493 /* Note that if this is a list of Protocol objects, some
494 of them may have been initialized already (because
495 they were attached to classes or categories, and the
496 class/category loading code automatically fixes them
497 up), and some of them may not. We really need to go
498 through the whole list to be sure! Protocols are
499 also special because we want to register them and
500 register all their selectors. */
501 id *inst;
502
503 if (strcmp (statics->class_name, "Protocol") == 0)
504 {
505 /* Protocols are special, because not only we want
506 to fix up their class pointers, but we also want
507 to register them and their selectors with the
508 runtime. */
509 for (inst = &statics->instances[0]; *inst; inst++)
510 __objc_init_protocol ((struct objc_protocol *)*inst);
511 }
512 else
513 {
514 /* Other static instances (typically constant strings) are
515 easier as we just fix up their class pointers. */
516 for (inst = &statics->instances[0]; *inst; inst++)
517 (*inst)->class_pointer = class;
518 }
519 }
520 }
521 if (module_initialized)
522 {
523 /* Remove this module from the uninitialized list. */
524 struct objc_list *this = *cell;
525 *cell = this->tail;
526 objc_free (this);
527 }
528 else
529 cell = &(*cell)->tail;
530 }
531
532 objc_mutex_unlock (__objc_runtime_mutex);
533 } /* objc_init_statics */
534
535 /* This function is called by constructor functions generated for each
536 module compiled. (_GLOBAL_$I$...) The purpose of this function is
537 to gather the module pointers so that they may be processed by the
538 initialization routines as soon as possible. */
539
540 void
541 __objc_exec_class (Module_t module)
542 {
543 /* Have we processed any constructors previously? This flag is used to
544 indicate that some global data structures need to be built. */
545 static BOOL previous_constructors = 0;
546
547 static struct objc_list *unclaimed_categories = 0;
548
549 /* The symbol table (defined in objc-api.h) generated by gcc */
550 Symtab_t symtab = module->symtab;
551
552 /* The statics in this module */
553 struct objc_static_instances **statics
554 = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
555
556 /* Entry used to traverse hash lists */
557 struct objc_list **cell;
558
559 /* The table of selector references for this module */
560 SEL selectors = symtab->refs;
561
562 /* dummy counter */
563 int i;
564
565 DEBUG_PRINTF ("received module: %s\n", module->name);
566
567 /* check gcc version */
568 init_check_module_version (module);
569
570 /* On the first call of this routine, initialize some data structures. */
571 if (! previous_constructors)
572 {
573 /* Initialize thread-safe system */
574 __objc_init_thread_system ();
575 __objc_runtime_threads_alive = 1;
576 __objc_runtime_mutex = objc_mutex_allocate ();
577
578 __objc_init_selector_tables ();
579 __objc_init_class_tables ();
580 __objc_init_dispatch_tables ();
581 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
582 __objc_load_methods = objc_hash_new (128,
583 (hash_func_type)objc_hash_ptr,
584 objc_compare_ptrs);
585 __objc_protocols_init ();
586 __objc_sync_init ();
587 previous_constructors = 1;
588 }
589
590 /* Save the module pointer for later processing. (not currently used) */
591 objc_mutex_lock (__objc_runtime_mutex);
592 __objc_module_list = list_cons (module, __objc_module_list);
593
594 /* Replace referenced selectors from names to SEL's. */
595 if (selectors)
596 {
597 for (i = 0; selectors[i].sel_id; ++i)
598 {
599 const char *name, *type;
600 name = (char *) selectors[i].sel_id;
601 type = (char *) selectors[i].sel_types;
602 /* Constructors are constant static data so we can safely store
603 pointers to them in the runtime structures. is_const == YES */
604 __sel_register_typed_name (name, type,
605 (struct objc_selector *) &(selectors[i]),
606 YES);
607 }
608 }
609
610 /* Parse the classes in the load module and gather selector information. */
611 DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
612 for (i = 0; i < symtab->cls_def_cnt; ++i)
613 {
614 Class class = (Class) symtab->defs[i];
615 const char *superclass = (char *) class->super_class;
616
617 /* Make sure we have what we think. */
618 assert (CLS_ISCLASS (class));
619 assert (CLS_ISMETA (class->class_pointer));
620 DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
621
622 /* Initialize the subclass list to be NULL.
623 In some cases it isn't and this crashes the program. */
624 class->subclass_list = NULL;
625
626 __objc_init_class (class);
627
628 /* Check to see if the superclass is known in this point. If it's not
629 add the class to the unresolved_classes list. */
630 if (superclass && ! objc_lookup_class (superclass))
631 unresolved_classes = list_cons (class, unresolved_classes);
632 }
633
634 /* Process category information from the module. */
635 for (i = 0; i < symtab->cat_def_cnt; ++i)
636 {
637 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
638 Class class = objc_lookup_class (category->class_name);
639
640 /* If the class for the category exists then append its methods. */
641 if (class)
642 {
643
644 DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
645 module->name,
646 class->name);
647
648 /* Do instance methods. */
649 if (category->instance_methods)
650 class_add_method_list (class, category->instance_methods);
651
652 /* Do class methods. */
653 if (category->class_methods)
654 class_add_method_list ((Class) class->class_pointer,
655 category->class_methods);
656
657 if (category->protocols)
658 {
659 __objc_init_protocols (category->protocols);
660 __objc_class_add_protocols (class, category->protocols);
661 }
662
663 /* Register the instance methods as class methods, this is
664 only done for root classes. */
665 __objc_register_instance_methods_to_class (class);
666 }
667 else
668 {
669 /* The object to which the category methods belong can't be found.
670 Save the information. */
671 unclaimed_categories = list_cons (category, unclaimed_categories);
672 }
673 }
674
675 if (statics)
676 uninitialized_statics = list_cons (statics, uninitialized_statics);
677 if (uninitialized_statics)
678 objc_init_statics ();
679
680 /* Scan the unclaimed category hash. Attempt to attach any unclaimed
681 categories to objects. */
682 for (cell = &unclaimed_categories; *cell; )
683 {
684 Category_t category = (*cell)->head;
685 Class class = objc_lookup_class (category->class_name);
686
687 if (class)
688 {
689 DEBUG_PRINTF ("attaching stored categories to object: %s\n",
690 class->name);
691
692 list_remove_head (cell);
693
694 if (category->instance_methods)
695 class_add_method_list (class, category->instance_methods);
696
697 if (category->class_methods)
698 class_add_method_list ((Class) class->class_pointer,
699 category->class_methods);
700
701 if (category->protocols)
702 {
703 __objc_init_protocols (category->protocols);
704 __objc_class_add_protocols (class, category->protocols);
705 }
706
707 /* Register the instance methods as class methods, this is
708 only done for root classes. */
709 __objc_register_instance_methods_to_class (class);
710 }
711 else
712 cell = &(*cell)->tail;
713 }
714
715 if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
716 {
717 list_mapcar (unclaimed_proto_list,
718 (void (*) (void *))__objc_init_protocols);
719 list_free (unclaimed_proto_list);
720 unclaimed_proto_list = 0;
721 }
722
723 objc_send_load ();
724
725 objc_mutex_unlock (__objc_runtime_mutex);
726 }
727
728 static void
729 objc_send_load (void)
730 {
731 if (! __objc_module_list)
732 return;
733
734 /* Try to find out if all the classes loaded so far also have their
735 superclasses known to the runtime. We suppose that the objects
736 that are allocated in the +load method are in general of a class
737 declared in the same module. */
738 if (unresolved_classes)
739 {
740 Class class = unresolved_classes->head;
741
742 while (objc_lookup_class ((char *) class->super_class))
743 {
744 list_remove_head (&unresolved_classes);
745 if (unresolved_classes)
746 class = unresolved_classes->head;
747 else
748 break;
749 }
750
751 /* If we still have classes for whom we don't have yet their
752 super classes known to the runtime we don't send the +load
753 messages. */
754 if (unresolved_classes)
755 return;
756 }
757
758 /* Special check to allow creating and sending messages to constant
759 strings in +load methods. If these classes are not yet known,
760 even if all the other classes are known, delay sending of +load. */
761 if (! objc_lookup_class ("NXConstantString") ||
762 ! objc_lookup_class ("Object"))
763 return;
764
765 /* Iterate over all modules in the __objc_module_list and call on
766 them the __objc_create_classes_tree function. This function
767 creates a tree of classes that resembles the class hierarchy. */
768 list_mapcar (__objc_module_list,
769 (void (*) (void *)) __objc_create_classes_tree);
770
771 while (__objc_class_tree_list)
772 {
773 #ifdef DEBUG
774 objc_preorder_traverse (__objc_class_tree_list->head,
775 0, __objc_tree_print);
776 #endif
777 objc_preorder_traverse (__objc_class_tree_list->head,
778 0, __objc_send_load);
779 objc_postorder_traverse (__objc_class_tree_list->head,
780 0, __objc_destroy_class_tree_node);
781 list_remove_head (&__objc_class_tree_list);
782 }
783
784 list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback);
785 list_free (__objc_module_list);
786 __objc_module_list = NULL;
787 }
788
789 static void
790 __objc_create_classes_tree (Module_t module)
791 {
792 /* The runtime mutex is locked in this point */
793
794 Symtab_t symtab = module->symtab;
795 int i;
796
797 /* Iterate thru classes defined in this module and insert them in
798 the classes tree hierarchy. */
799 for (i = 0; i < symtab->cls_def_cnt; i++)
800 {
801 Class class = (Class) symtab->defs[i];
802
803 objc_tree_insert_class (class);
804 }
805 }
806
807 static void
808 __objc_call_callback (Module_t module)
809 {
810 /* The runtime mutex is locked in this point. */
811
812 Symtab_t symtab = module->symtab;
813 int i;
814
815 /* Iterate thru classes defined in this module and call the callback
816 for each one. */
817 for (i = 0; i < symtab->cls_def_cnt; i++)
818 {
819 Class class = (Class) symtab->defs[i];
820
821 /* Call the _objc_load_callback for this class. */
822 if (_objc_load_callback)
823 _objc_load_callback (class, 0);
824 }
825
826 /* Call the _objc_load_callback for categories. Don't register the
827 instance methods as class methods for categories to root classes
828 since they were already added in the class. */
829 for (i = 0; i < symtab->cat_def_cnt; i++)
830 {
831 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
832 Class class = objc_lookup_class (category->class_name);
833
834 if (_objc_load_callback)
835 _objc_load_callback (class, category);
836 }
837 }
838
839 /* Sanity check the version of gcc used to compile `module'. */
840
841 static void
842 init_check_module_version (Module_t module)
843 {
844 if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
845 {
846 _objc_abort ("Module %s version %d doesn't match runtime %d\n",
847 module->name, (int)module->version, OBJC_VERSION);
848 }
849 }
850
851 /* __objc_init_class must be called with __objc_runtime_mutex already locked. */
852 void
853 __objc_init_class (Class class)
854 {
855 /* Store the class in the class table and assign class numbers. */
856 __objc_add_class_to_hash (class);
857
858 /* Register all of the selectors in the class and meta class. */
859 __objc_register_selectors_from_class (class);
860 __objc_register_selectors_from_class ((Class) class->class_pointer);
861
862 /* Install the fake dispatch tables */
863 __objc_install_premature_dtable (class);
864 __objc_install_premature_dtable (class->class_pointer);
865
866 /* Register the instance methods as class methods, this is only done
867 for root classes. */
868 __objc_register_instance_methods_to_class (class);
869
870 if (class->protocols)
871 __objc_init_protocols (class->protocols);
872 }
873
874 /* __objc_init_protocol must be called with __objc_runtime_mutex
875 already locked, and the "Protocol" class already registered. */
876 static void
877 __objc_init_protocol (struct objc_protocol *protocol)
878 {
879 static Class proto_class = 0;
880
881 if (! proto_class)
882 proto_class = objc_get_class ("Protocol");
883
884 if (((size_t)protocol->class_pointer) == PROTOCOL_VERSION)
885 {
886 /* Assign class pointer */
887 protocol->class_pointer = proto_class;
888
889 /* Register all the selectors in the protocol with the runtime.
890 This both registers the selectors with the right types, and
891 it also fixes up the 'struct objc_method' structures inside
892 the protocol so that each method_name (a char * as compiled
893 by the compiler) is replaced with the appropriate runtime
894 SEL. */
895 if (protocol->class_methods)
896 __objc_register_selectors_from_description_list (protocol->class_methods);
897
898 if (protocol->instance_methods)
899 __objc_register_selectors_from_description_list (protocol->instance_methods);
900
901 /* Register the protocol in the hashtable or protocols by
902 name. */
903 __objc_protocols_add_protocol (protocol->protocol_name, protocol);
904
905 /* Init super protocols */
906 __objc_init_protocols (protocol->protocol_list);
907 }
908 else if (protocol->class_pointer != proto_class)
909 {
910 _objc_abort ("Version %d doesn't match runtime protocol version %d\n",
911 (int) ((char *) protocol->class_pointer
912 - (char *) 0),
913 PROTOCOL_VERSION);
914 }
915 }
916
917 static void
918 __objc_init_protocols (struct objc_protocol_list *protos)
919 {
920 size_t i;
921 static Class proto_class = 0;
922
923 if (! protos)
924 return;
925
926 objc_mutex_lock (__objc_runtime_mutex);
927
928 if (! proto_class)
929 proto_class = objc_lookup_class ("Protocol");
930
931 if (! proto_class)
932 {
933 unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
934 objc_mutex_unlock (__objc_runtime_mutex);
935 return;
936 }
937
938 #if 0
939 assert (protos->next == 0); /* only single ones allowed */
940 #endif
941
942 for (i = 0; i < protos->count; i++)
943 {
944 struct objc_protocol *aProto = protos->list[i];
945 __objc_init_protocol (aProto);
946 }
947
948 objc_mutex_unlock (__objc_runtime_mutex);
949 }
950
951 static void
952 __objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
953 {
954 /* Well... */
955 if (! protos)
956 return;
957
958 /* Add it... */
959 protos->next = class->protocols;
960 class->protocols = protos;
961 }