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>
7 This file is part of GCC.
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.
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
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.
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/>. */
27 #include "objc-private/common.h"
28 #include "objc-private/error.h"
29 #include "objc/objc-api.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() and __objc_protocols_add_protocol() */
37 /* The version number of this runtime. This must match the number
38 defined in gcc (objc-act.c). */
39 #define OBJC_VERSION 8
40 #define PROTOCOL_VERSION 2
42 /* This list contains all modules currently loaded into the runtime. */
43 static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */
45 /* This list contains all proto_list's not yet assigned class links. */
46 static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */
48 /* List of unresolved static instances. */
49 static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
51 /* Global runtime "write" mutex. Having a single mutex prevents
52 deadlocks, but reduces concurrency. To improve concurrency, some
53 groups of functions in the runtime have their own separate mutex
54 (eg, __class_table_lock in class.c); to avoid deadlocks, these
55 routines must make sure that they never acquire any other lock
56 while holding their own local lock. Ie, they should lock, execute
57 some C code that does not perform any calls to other runtime
58 functions which may potentially lock different locks, then unlock.
59 If they need to perform any calls to other runtime functions that
60 may potentially lock other locks, then they should use the global
61 __objc_runtime_mutex. */
62 objc_mutex_t __objc_runtime_mutex = 0;
64 /* Number of threads that are alive. */
65 int __objc_runtime_threads_alive = 1; /* !T:MUTEX */
67 /* Check compiler vs runtime version. */
68 static void init_check_module_version (Module_t);
70 /* Assign isa links to protos. */
71 static void __objc_init_protocols (struct objc_protocol_list *protos);
73 /* Add protocol to class. */
74 static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
76 /* This is a hook which is called by __objc_exec_class every time a
77 class or a category is loaded into the runtime. This may e.g. help
78 a dynamic loader determine the classes that have been loaded when
79 an object file is dynamically linked in. */
80 void (*_objc_load_callback) (Class class, Category *category); /* !T:SAFE */
82 /* Is all categories/classes resolved? */
83 BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
86 __sel_register_typed_name (const char *name, const char *types,
87 struct objc_selector *orig, BOOL is_const);
89 /* Sends +load to all classes and categories in certain situations. */
90 static void objc_send_load (void);
92 /* Inserts all the classes defined in module in a tree of classes that
93 resembles the class hierarchy. This tree is traversed in preorder
94 and the classes in its nodes receive the +load message if these
95 methods were not executed before. The algorithm ensures that when
96 the +load method of a class is executed all the superclasses have
97 been already received the +load message. */
98 static void __objc_create_classes_tree (Module_t module);
100 static void __objc_call_callback (Module_t module);
102 /* A special version that works only before the classes are completely
103 installed in the runtime. */
104 static BOOL class_is_subclass_of_class (Class class, Class superclass);
106 typedef struct objc_class_tree {
108 struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */
111 /* This is a linked list of objc_class_tree trees. The head of these
112 trees are root classes (their super class is Nil). These different
113 trees represent different class hierarchies. */
114 static struct objc_list *__objc_class_tree_list = NULL;
116 /* Keeps the +load methods who have been already executed. This hash
117 should not be destroyed during the execution of the program. */
118 static cache_ptr __objc_load_methods = NULL;
120 /* This function is used when building the class tree used to send
121 ordinately the +load message to all classes needing it. The tree
122 is really needed so that superclasses will get the message before
125 This tree will contain classes which are being loaded (or have just
126 being loaded), and whose super_class pointers have not yet been
127 resolved. This implies that their super_class pointers point to a
128 string with the name of the superclass; when the first message is
129 sent to the class (/an object of that class) the class links will
130 be resolved, which will replace the super_class pointers with
131 pointers to the actual superclasses.
133 Unfortunately, the tree might also contain classes which had been
134 loaded previously, and whose class links have already been
137 This function returns the superclass of a class in both cases, and
138 can be used to build the determine the class relationships while
141 static Class class_superclass_of_class (Class class)
143 char *super_class_name;
145 /* If the class links have been resolved, use the resolved
147 if (CLS_ISRESOLV (class))
148 return class->super_class;
150 /* Else, 'class' has not yet been resolved. This means that its
151 * super_class pointer is really the name of the super class (rather
152 * than a pointer to the actual superclass). */
153 super_class_name = (char *)class->super_class;
155 /* Return Nil for a root class. */
156 if (super_class_name == NULL)
159 /* Lookup the superclass of non-root classes. */
160 return objc_lookup_class (super_class_name);
164 /* Creates a tree of classes whose topmost class is directly inherited
165 from `upper' and the bottom class in this tree is
166 `bottom_class'. The classes in this tree are super classes of
167 `bottom_class'. `subclasses' member of each tree node point to the
168 next subclass tree node. */
170 static objc_class_tree *
171 create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
173 Class superclass = bottom_class->super_class ?
174 objc_lookup_class ((char *) bottom_class->super_class)
177 objc_class_tree *tree, *prev;
179 DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
180 DEBUG_PRINTF ("bottom_class = %s, upper = %s\n",
181 (bottom_class ? bottom_class->name : NULL),
182 (upper ? upper->name : NULL));
184 tree = prev = objc_calloc (1, sizeof (objc_class_tree));
185 prev->class = bottom_class;
187 while (superclass != upper)
189 tree = objc_calloc (1, sizeof (objc_class_tree));
190 tree->class = superclass;
191 tree->subclasses = list_cons (prev, tree->subclasses);
192 superclass = class_superclass_of_class (superclass);
199 /* Insert the `class' into the proper place in the `tree' class
200 hierarchy. This function returns a new tree if the class has been
201 successfully inserted into the tree or NULL if the class is not
202 part of the classes hierarchy described by `tree'. This function is
203 private to objc_tree_insert_class (), you should not call it
206 static objc_class_tree *
207 __objc_tree_insert_class (objc_class_tree *tree, Class class)
209 DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n",
213 return create_tree_of_subclasses_inherited_from (class, NULL);
214 else if (class == tree->class)
216 /* `class' has been already inserted */
217 DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
220 else if (class_superclass_of_class (class) == tree->class)
222 /* If class is a direct subclass of tree->class then add class to the
223 list of subclasses. First check to see if it wasn't already
225 struct objc_list *list = tree->subclasses;
226 objc_class_tree *node;
230 /* Class has been already inserted; do nothing just return
232 if (((objc_class_tree *) list->head)->class == class)
234 DEBUG_PRINTF ("2. class %s was previously inserted\n",
241 /* Create a new node class and insert it into the list of subclasses */
242 node = objc_calloc (1, sizeof (objc_class_tree));
244 tree->subclasses = list_cons (node, tree->subclasses);
245 DEBUG_PRINTF ("3. class %s inserted\n", class->name);
250 /* The class is not a direct subclass of tree->class. Search for
251 class's superclasses in the list of subclasses. */
252 struct objc_list *subclasses = tree->subclasses;
254 /* Precondition: the class must be a subclass of tree->class;
255 otherwise return NULL to indicate our caller that it must
256 take the next tree. */
257 if (! class_is_subclass_of_class (class, tree->class))
260 for (; subclasses != NULL; subclasses = subclasses->tail)
262 Class aClass = ((objc_class_tree *) (subclasses->head))->class;
264 if (class_is_subclass_of_class (class, aClass))
266 /* If we found one of class's superclasses we insert the
267 class into its subtree and return the original tree
268 since nothing has been changed. */
270 = __objc_tree_insert_class (subclasses->head, class);
271 DEBUG_PRINTF ("4. class %s inserted\n", class->name);
276 /* We haven't found a subclass of `class' in the `subclasses'
277 list. Create a new tree of classes whose topmost class is a
278 direct subclass of tree->class. */
280 objc_class_tree *new_tree
281 = create_tree_of_subclasses_inherited_from (class, tree->class);
282 tree->subclasses = list_cons (new_tree, tree->subclasses);
283 DEBUG_PRINTF ("5. class %s inserted\n", class->name);
289 /* This function inserts `class' in the right tree hierarchy classes. */
292 objc_tree_insert_class (Class class)
294 struct objc_list *list_node;
295 objc_class_tree *tree;
297 list_node = __objc_class_tree_list;
300 tree = __objc_tree_insert_class (list_node->head, class);
303 list_node->head = tree;
307 list_node = list_node->tail;
310 /* If the list was finished but the class hasn't been inserted,
314 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
315 __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
319 /* Traverse tree in preorder. Used to send +load. */
322 objc_preorder_traverse (objc_class_tree *tree,
324 void (*function) (objc_class_tree *, int))
326 struct objc_list *node;
328 (*function) (tree, level);
329 for (node = tree->subclasses; node; node = node->tail)
330 objc_preorder_traverse (node->head, level + 1, function);
333 /* Traverse tree in postorder. Used to destroy a tree. */
336 objc_postorder_traverse (objc_class_tree *tree,
338 void (*function) (objc_class_tree *, int))
340 struct objc_list *node;
342 for (node = tree->subclasses; node; node = node->tail)
343 objc_postorder_traverse (node->head, level + 1, function);
344 (*function) (tree, level);
347 /* Used to print a tree class hierarchy. */
351 __objc_tree_print (objc_class_tree *tree, int level)
355 for (i = 0; i < level; i++)
357 printf ("%s\n", tree->class->name);
361 /* Walks on a linked list of methods in the reverse order and executes
362 all the methods corresponding to `op' selector. Walking in the
363 reverse order assures the +load of class is executed first and then
364 +load of categories because of the way in which categories are
365 added to the class methods. */
368 __objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
375 /* First execute the `op' message in the following method lists */
376 __objc_send_message_in_list (method_list->method_next, class, op);
378 /* Search the method list. */
379 for (i = 0; i < method_list->method_count; i++)
381 Method_t mth = &method_list->method_list[i];
383 if (mth->method_name && sel_eq (mth->method_name, op)
384 && ! objc_hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
386 /* Add this method into the +load hash table */
387 objc_hash_add (&__objc_load_methods,
391 DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
393 /* The method was found and wasn't previously executed. */
394 (*mth->method_imp) ((id)class, mth->method_name);
402 __objc_send_load (objc_class_tree *tree,
403 int level __attribute__ ((__unused__)))
405 static SEL load_sel = 0;
406 Class class = tree->class;
407 MethodList_t method_list = class->class_pointer->methods;
410 load_sel = sel_register_name ("load");
412 __objc_send_message_in_list (method_list, class, load_sel);
416 __objc_destroy_class_tree_node (objc_class_tree *tree,
417 int level __attribute__ ((__unused__)))
422 /* This is used to check if the relationship between two classes
423 before the runtime completely installs the classes. */
426 class_is_subclass_of_class (Class class, Class superclass)
428 for (; class != Nil;)
430 if (class == superclass)
432 class = class_superclass_of_class (class);
438 /* This list contains all the classes in the runtime system for whom
439 their superclasses are not yet known to the runtime. */
440 static struct objc_list *unresolved_classes = 0;
442 /* Extern function used to reference the Object and NXConstantString
445 extern void __objc_force_linking (void);
448 __objc_force_linking (void)
450 extern void __objc_linking (void);
454 /* Run through the statics list, removing modules as soon as all its
455 statics have been initialized. */
458 objc_init_statics (void)
460 struct objc_list **cell = &uninitialized_statics;
461 struct objc_static_instances **statics_in_module;
463 objc_mutex_lock (__objc_runtime_mutex);
467 int module_initialized = 1;
469 for (statics_in_module = (*cell)->head;
470 *statics_in_module; statics_in_module++)
472 struct objc_static_instances *statics = *statics_in_module;
473 Class class = objc_lookup_class (statics->class_name);
476 module_initialized = 0;
477 /* Actually, the static's class_pointer will be NULL when we
478 haven't been here before. However, the comparison is to be
479 reminded of taking into account class posing and to think about
480 possible semantics... */
481 else if (class != statics->instances[0]->class_pointer)
485 for (inst = &statics->instances[0]; *inst; inst++)
487 (*inst)->class_pointer = class;
489 /* ??? Make sure the object will not be freed. With
490 refcounting, invoke `-retain'. Without refcounting, do
491 nothing and hope that `-free' will never be invoked. */
493 /* ??? Send the object an `-initStatic' or something to
494 that effect now or later on? What are the semantics of
495 statically allocated instances, besides the trivial
496 NXConstantString, anyway? */
500 if (module_initialized)
502 /* Remove this module from the uninitialized list. */
503 struct objc_list *this = *cell;
508 cell = &(*cell)->tail;
511 objc_mutex_unlock (__objc_runtime_mutex);
512 } /* objc_init_statics */
514 /* This function is called by constructor functions generated for each
515 module compiled. (_GLOBAL_$I$...) The purpose of this function is
516 to gather the module pointers so that they may be processed by the
517 initialization routines as soon as possible. */
520 __objc_exec_class (Module_t module)
522 /* Have we processed any constructors previously? This flag is used to
523 indicate that some global data structures need to be built. */
524 static BOOL previous_constructors = 0;
526 static struct objc_list *unclaimed_categories = 0;
528 /* The symbol table (defined in objc-api.h) generated by gcc */
529 Symtab_t symtab = module->symtab;
531 /* The statics in this module */
532 struct objc_static_instances **statics
533 = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
535 /* Entry used to traverse hash lists */
536 struct objc_list **cell;
538 /* The table of selector references for this module */
539 SEL selectors = symtab->refs;
544 DEBUG_PRINTF ("received module: %s\n", module->name);
546 /* check gcc version */
547 init_check_module_version (module);
549 /* On the first call of this routine, initialize some data structures. */
550 if (! previous_constructors)
552 /* Initialize thread-safe system */
553 __objc_init_thread_system ();
554 __objc_runtime_threads_alive = 1;
555 __objc_runtime_mutex = objc_mutex_allocate ();
557 __objc_init_selector_tables ();
558 __objc_init_class_tables ();
559 __objc_init_dispatch_tables ();
560 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
561 __objc_load_methods = objc_hash_new (128,
562 (hash_func_type)objc_hash_ptr,
564 __objc_protocols_init ();
566 previous_constructors = 1;
569 /* Save the module pointer for later processing. (not currently used) */
570 objc_mutex_lock (__objc_runtime_mutex);
571 __objc_module_list = list_cons (module, __objc_module_list);
573 /* Replace referenced selectors from names to SEL's. */
576 for (i = 0; selectors[i].sel_id; ++i)
578 const char *name, *type;
579 name = (char *) selectors[i].sel_id;
580 type = (char *) selectors[i].sel_types;
581 /* Constructors are constant static data so we can safely store
582 pointers to them in the runtime structures. is_const == YES */
583 __sel_register_typed_name (name, type,
584 (struct objc_selector *) &(selectors[i]),
589 /* Parse the classes in the load module and gather selector information. */
590 DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
591 for (i = 0; i < symtab->cls_def_cnt; ++i)
593 Class class = (Class) symtab->defs[i];
594 const char *superclass = (char *) class->super_class;
596 /* Make sure we have what we think. */
597 assert (CLS_ISCLASS (class));
598 assert (CLS_ISMETA (class->class_pointer));
599 DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
601 /* Initialize the subclass list to be NULL.
602 In some cases it isn't and this crashes the program. */
603 class->subclass_list = NULL;
605 /* Store the class in the class table and assign class numbers. */
606 __objc_add_class_to_hash (class);
608 /* Register all of the selectors in the class and meta class. */
609 __objc_register_selectors_from_class (class);
610 __objc_register_selectors_from_class ((Class) class->class_pointer);
612 /* Install the fake dispatch tables */
613 __objc_install_premature_dtable (class);
614 __objc_install_premature_dtable (class->class_pointer);
616 /* Register the instance methods as class methods, this is
617 only done for root classes. */
618 __objc_register_instance_methods_to_class (class);
620 if (class->protocols)
621 __objc_init_protocols (class->protocols);
623 /* Check to see if the superclass is known in this point. If it's not
624 add the class to the unresolved_classes list. */
625 if (superclass && ! objc_lookup_class (superclass))
626 unresolved_classes = list_cons (class, unresolved_classes);
629 /* Process category information from the module. */
630 for (i = 0; i < symtab->cat_def_cnt; ++i)
632 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
633 Class class = objc_lookup_class (category->class_name);
635 /* If the class for the category exists then append its methods. */
639 DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
643 /* Do instance methods. */
644 if (category->instance_methods)
645 class_add_method_list (class, category->instance_methods);
647 /* Do class methods. */
648 if (category->class_methods)
649 class_add_method_list ((Class) class->class_pointer,
650 category->class_methods);
652 if (category->protocols)
654 __objc_init_protocols (category->protocols);
655 __objc_class_add_protocols (class, category->protocols);
658 /* Register the instance methods as class methods, this is
659 only done for root classes. */
660 __objc_register_instance_methods_to_class (class);
664 /* The object to which the category methods belong can't be found.
665 Save the information. */
666 unclaimed_categories = list_cons (category, unclaimed_categories);
671 uninitialized_statics = list_cons (statics, uninitialized_statics);
672 if (uninitialized_statics)
673 objc_init_statics ();
675 /* Scan the unclaimed category hash. Attempt to attach any unclaimed
676 categories to objects. */
677 for (cell = &unclaimed_categories; *cell; )
679 Category_t category = (*cell)->head;
680 Class class = objc_lookup_class (category->class_name);
684 DEBUG_PRINTF ("attaching stored categories to object: %s\n",
687 list_remove_head (cell);
689 if (category->instance_methods)
690 class_add_method_list (class, category->instance_methods);
692 if (category->class_methods)
693 class_add_method_list ((Class) class->class_pointer,
694 category->class_methods);
696 if (category->protocols)
698 __objc_init_protocols (category->protocols);
699 __objc_class_add_protocols (class, category->protocols);
702 /* Register the instance methods as class methods, this is
703 only done for root classes. */
704 __objc_register_instance_methods_to_class (class);
707 cell = &(*cell)->tail;
710 if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
712 list_mapcar (unclaimed_proto_list,
713 (void (*) (void *))__objc_init_protocols);
714 list_free (unclaimed_proto_list);
715 unclaimed_proto_list = 0;
720 objc_mutex_unlock (__objc_runtime_mutex);
724 objc_send_load (void)
726 if (! __objc_module_list)
729 /* Try to find out if all the classes loaded so far also have their
730 superclasses known to the runtime. We suppose that the objects
731 that are allocated in the +load method are in general of a class
732 declared in the same module. */
733 if (unresolved_classes)
735 Class class = unresolved_classes->head;
737 while (objc_lookup_class ((char *) class->super_class))
739 list_remove_head (&unresolved_classes);
740 if (unresolved_classes)
741 class = unresolved_classes->head;
746 /* If we still have classes for whom we don't have yet their
747 super classes known to the runtime we don't send the +load
749 if (unresolved_classes)
753 /* Special check to allow creating and sending messages to constant
754 strings in +load methods. If these classes are not yet known,
755 even if all the other classes are known, delay sending of +load. */
756 if (! objc_lookup_class ("NXConstantString") ||
757 ! objc_lookup_class ("Object"))
760 /* Iterate over all modules in the __objc_module_list and call on
761 them the __objc_create_classes_tree function. This function
762 creates a tree of classes that resembles the class hierarchy. */
763 list_mapcar (__objc_module_list,
764 (void (*) (void *)) __objc_create_classes_tree);
766 while (__objc_class_tree_list)
769 objc_preorder_traverse (__objc_class_tree_list->head,
770 0, __objc_tree_print);
772 objc_preorder_traverse (__objc_class_tree_list->head,
773 0, __objc_send_load);
774 objc_postorder_traverse (__objc_class_tree_list->head,
775 0, __objc_destroy_class_tree_node);
776 list_remove_head (&__objc_class_tree_list);
779 list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback);
780 list_free (__objc_module_list);
781 __objc_module_list = NULL;
785 __objc_create_classes_tree (Module_t module)
787 /* The runtime mutex is locked in this point */
789 Symtab_t symtab = module->symtab;
792 /* Iterate thru classes defined in this module and insert them in
793 the classes tree hierarchy. */
794 for (i = 0; i < symtab->cls_def_cnt; i++)
796 Class class = (Class) symtab->defs[i];
798 objc_tree_insert_class (class);
803 __objc_call_callback (Module_t module)
805 /* The runtime mutex is locked in this point. */
807 Symtab_t symtab = module->symtab;
810 /* Iterate thru classes defined in this module and call the callback
812 for (i = 0; i < symtab->cls_def_cnt; i++)
814 Class class = (Class) symtab->defs[i];
816 /* Call the _objc_load_callback for this class. */
817 if (_objc_load_callback)
818 _objc_load_callback (class, 0);
821 /* Call the _objc_load_callback for categories. Don't register the
822 instance methods as class methods for categories to root classes
823 since they were already added in the class. */
824 for (i = 0; i < symtab->cat_def_cnt; i++)
826 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
827 Class class = objc_lookup_class (category->class_name);
829 if (_objc_load_callback)
830 _objc_load_callback (class, category);
834 /* Sanity check the version of gcc used to compile `module'. */
837 init_check_module_version (Module_t module)
839 if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
841 _objc_abort ("Module %s version %d doesn't match runtime %d\n",
842 module->name, (int)module->version, OBJC_VERSION);
847 __objc_init_protocols (struct objc_protocol_list *protos)
850 static Class proto_class = 0;
855 objc_mutex_lock (__objc_runtime_mutex);
858 proto_class = objc_lookup_class ("Protocol");
862 unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
863 objc_mutex_unlock (__objc_runtime_mutex);
868 assert (protos->next == 0); /* only single ones allowed */
871 for (i = 0; i < protos->count; i++)
873 struct objc_protocol *aProto = protos->list[i];
874 if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
876 /* Assign class pointer */
877 aProto->class_pointer = proto_class;
879 /* Register the protocol in the hashtable or protocols by
881 __objc_protocols_add_protocol (aProto->protocol_name, aProto);
883 /* Init super protocols */
884 __objc_init_protocols (aProto->protocol_list);
886 else if (protos->list[i]->class_pointer != proto_class)
888 _objc_abort ("Version %d doesn't match runtime protocol version %d\n",
889 (int) ((char *) protos->list[i]->class_pointer
895 objc_mutex_unlock (__objc_runtime_mutex);
899 __objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
906 protos->next = class->protocols;
907 class->protocols = protos;