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