xref: /netbsd-src/external/gpl3/gcc.old/dist/libobjc/init.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
136ac495dSmrg /* GNU Objective C Runtime initialization
2*8feb0f0bSmrg    Copyright (C) 1993-2020 Free Software Foundation, Inc.
336ac495dSmrg    Contributed by Kresten Krab Thorup
436ac495dSmrg    +load support contributed by Ovidiu Predescu <ovidiu@net-community.com>
536ac495dSmrg 
636ac495dSmrg This file is part of GCC.
736ac495dSmrg 
836ac495dSmrg GCC is free software; you can redistribute it and/or modify it under the
936ac495dSmrg terms of the GNU General Public License as published by the Free Software
1036ac495dSmrg Foundation; either version 3, or (at your option) any later version.
1136ac495dSmrg 
1236ac495dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1336ac495dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1436ac495dSmrg FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
1536ac495dSmrg details.
1636ac495dSmrg 
1736ac495dSmrg Under Section 7 of GPL version 3, you are granted additional
1836ac495dSmrg permissions described in the GCC Runtime Library Exception, version
1936ac495dSmrg 3.1, as published by the Free Software Foundation.
2036ac495dSmrg 
2136ac495dSmrg You should have received a copy of the GNU General Public License and
2236ac495dSmrg a copy of the GCC Runtime Library Exception along with this program;
2336ac495dSmrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2436ac495dSmrg <http://www.gnu.org/licenses/>.  */
2536ac495dSmrg 
2636ac495dSmrg /* Uncommented the following line to enable debug logging.  Use this
2736ac495dSmrg    only while debugging the runtime.  */
2836ac495dSmrg /* #define DEBUG 1 */
2936ac495dSmrg 
3036ac495dSmrg #include "objc-private/common.h"
3136ac495dSmrg #include "objc-private/error.h"
3236ac495dSmrg #include "objc/runtime.h"
3336ac495dSmrg #include "objc/thr.h"
3436ac495dSmrg #include "objc-private/hash.h"
3536ac495dSmrg #include "objc-private/objc-list.h"
3636ac495dSmrg #include "objc-private/module-abi-8.h"
3736ac495dSmrg #include "objc-private/runtime.h"   /* For __objc_resolve_class_links().  */
3836ac495dSmrg #include "objc-private/selector.h"  /* For __sel_register_typed_name().  */
3936ac495dSmrg #include "objc-private/objc-sync.h" /* For __objc_sync_init() */
4036ac495dSmrg #include "objc-private/protocols.h" /* For __objc_protocols_init(),
4136ac495dSmrg 				       __objc_protocols_add_protocol()
4236ac495dSmrg 				       __objc_protocols_register_selectors() */
4336ac495dSmrg #include "objc-private/accessors.h" /* For __objc_accessors_init() */
4436ac495dSmrg 
4536ac495dSmrg /* The version number of this runtime.  This must match the number
4636ac495dSmrg    defined in gcc (objc-act.c).  */
4736ac495dSmrg #define OBJC_VERSION 8
4836ac495dSmrg #define PROTOCOL_VERSION 2
4936ac495dSmrg 
5036ac495dSmrg /* This list contains modules currently loaded into the runtime and
5136ac495dSmrg    for which the +load method (and the load callback, if any) has not
5236ac495dSmrg    been called yet.  */
5336ac495dSmrg static struct objc_list *__objc_module_list = 0; 	/* !T:MUTEX */
5436ac495dSmrg 
5536ac495dSmrg /* This list contains all proto_list's not yet assigned class
5636ac495dSmrg    links.  */
5736ac495dSmrg static struct objc_list *unclaimed_proto_list = 0; 	/* !T:MUTEX */
5836ac495dSmrg 
5936ac495dSmrg /* List of unresolved static instances.  */
6036ac495dSmrg static struct objc_list *uninitialized_statics = 0; 	/* !T:MUTEX */
6136ac495dSmrg 
6236ac495dSmrg /* List of duplicated classes found while loading modules.  If we find
6336ac495dSmrg    a class twice, we ignore it the second time.  On some platforms,
6436ac495dSmrg    where the order in which modules are loaded is well defined, this
6536ac495dSmrg    allows you to replace a class in a shared library by linking in a
6636ac495dSmrg    new implementation which is loaded in in the right order, and which
6736ac495dSmrg    overrides the existing one.
6836ac495dSmrg 
6936ac495dSmrg    Protected by __objc_runtime_mutex.  */
7036ac495dSmrg static cache_ptr duplicate_classes = NULL;
7136ac495dSmrg 
7236ac495dSmrg /* Global runtime "write" mutex.  Having a single mutex prevents
7336ac495dSmrg    deadlocks, but reduces concurrency.  To improve concurrency, some
7436ac495dSmrg    groups of functions in the runtime have their own separate mutex
7536ac495dSmrg    (eg, __class_table_lock in class.c); to avoid deadlocks, these
7636ac495dSmrg    routines must make sure that they never acquire any other lock
7736ac495dSmrg    while holding their own local lock.  Ie, they should lock, execute
7836ac495dSmrg    some C code that does not perform any calls to other runtime
7936ac495dSmrg    functions which may potentially lock different locks, then unlock.
8036ac495dSmrg    If they need to perform any calls to other runtime functions that
8136ac495dSmrg    may potentially lock other locks, then they should use the global
8236ac495dSmrg    __objc_runtime_mutex.  */
8336ac495dSmrg objc_mutex_t __objc_runtime_mutex = 0;
8436ac495dSmrg 
8536ac495dSmrg /* Number of threads that are alive.  */
8636ac495dSmrg int __objc_runtime_threads_alive = 1;			/* !T:MUTEX */
8736ac495dSmrg 
8836ac495dSmrg /* Check compiler vs runtime version.  */
8936ac495dSmrg static void init_check_module_version (struct objc_module *);
9036ac495dSmrg 
9136ac495dSmrg /* Assign isa links to protos.  */
9236ac495dSmrg static void __objc_init_protocols (struct objc_protocol_list *protos);
9336ac495dSmrg 
9436ac495dSmrg /* Assign isa link to a protocol, and register it.  */
9536ac495dSmrg static void __objc_init_protocol (struct objc_protocol *protocol);
9636ac495dSmrg 
9736ac495dSmrg /* Add protocol to class.  */
9836ac495dSmrg static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
9936ac495dSmrg 
10036ac495dSmrg /* Load callback hook.  */
10136ac495dSmrg void (*_objc_load_callback) (Class class, struct objc_category *category) = 0; /* !T:SAFE */
10236ac495dSmrg 
10336ac495dSmrg /* Are all categories/classes resolved ?  */
10436ac495dSmrg BOOL __objc_dangling_categories = NO;           /* !T:UNUSED */
10536ac495dSmrg 
10636ac495dSmrg /* Sends +load to all classes and categories in certain
10736ac495dSmrg    situations.  */
10836ac495dSmrg static void objc_send_load (void);
10936ac495dSmrg 
11036ac495dSmrg /* Inserts all the classes defined in module in a tree of classes that
11136ac495dSmrg    resembles the class hierarchy.  This tree is traversed in preorder
11236ac495dSmrg    and the classes in its nodes receive the +load message if these
11336ac495dSmrg    methods were not executed before.  The algorithm ensures that when
11436ac495dSmrg    the +load method of a class is executed all the superclasses have
11536ac495dSmrg    been already received the +load message.  */
11636ac495dSmrg static void __objc_create_classes_tree (struct objc_module *module);
11736ac495dSmrg 
11836ac495dSmrg /* Calls the _objc_load_callback for each class and category in the
11936ac495dSmrg    module (if _objc_load_callback is not NULL).  */
12036ac495dSmrg static void __objc_call_load_callback (struct objc_module *module);
12136ac495dSmrg 
12236ac495dSmrg /* A special version that works only before the classes are completely
12336ac495dSmrg    installed in the runtime.  */
12436ac495dSmrg static BOOL class_is_subclass_of_class (Class class, Class superclass);
12536ac495dSmrg 
12636ac495dSmrg /* This is a node in the class tree hierarchy used to send +load
12736ac495dSmrg    messages.  */
12836ac495dSmrg typedef struct objc_class_tree
12936ac495dSmrg {
13036ac495dSmrg   /* The class corresponding to the node.  */
13136ac495dSmrg   Class class;
13236ac495dSmrg 
13336ac495dSmrg   /* This is a linked list of all the direct subclasses of this class.
13436ac495dSmrg      'head' points to a subclass node; 'tail' points to the next
13536ac495dSmrg      objc_list node (whose 'head' points to another subclass node,
13636ac495dSmrg      etc).  */
13736ac495dSmrg   struct objc_list *subclasses;
13836ac495dSmrg } objc_class_tree;
13936ac495dSmrg 
14036ac495dSmrg /* This is a linked list of objc_class_tree trees.  The head of these
14136ac495dSmrg    trees are root classes (their super class is Nil).  These different
14236ac495dSmrg    trees represent different class hierarchies.  */
14336ac495dSmrg static struct objc_list *__objc_class_tree_list = NULL;
14436ac495dSmrg 
14536ac495dSmrg /* Keeps the +load methods who have been already executed. This hash
14636ac495dSmrg    should not be destroyed during the execution of the program.  */
14736ac495dSmrg static cache_ptr __objc_load_methods = NULL;
14836ac495dSmrg 
14936ac495dSmrg /* This function is used when building the class tree used to send
15036ac495dSmrg    ordinately the +load message to all classes needing it.  The tree
15136ac495dSmrg    is really needed so that superclasses will get the message before
15236ac495dSmrg    subclasses.
15336ac495dSmrg 
15436ac495dSmrg    This tree may contain classes which are being loaded (or have just
15536ac495dSmrg    being loaded), and whose super_class pointers have not yet been
15636ac495dSmrg    resolved.  This implies that their super_class pointers point to a
15736ac495dSmrg    string with the name of the superclass; when the first message is
15836ac495dSmrg    sent to the class (/an object of that class) the class links will
15936ac495dSmrg    be resolved, which will replace the super_class pointers with
16036ac495dSmrg    pointers to the actual superclasses.
16136ac495dSmrg 
16236ac495dSmrg    Unfortunately, the tree might also contain classes which had been
16336ac495dSmrg    loaded previously, and whose class links have already been
16436ac495dSmrg    resolved.
16536ac495dSmrg 
16636ac495dSmrg    This function returns the superclass of a class in both cases, and
16736ac495dSmrg    can be used to build the determine the class relationships while
16836ac495dSmrg    building the tree.  */
class_superclass_of_class(Class class)16936ac495dSmrg static Class  class_superclass_of_class (Class class)
17036ac495dSmrg {
17136ac495dSmrg   char *super_class_name;
17236ac495dSmrg 
17336ac495dSmrg   /* If the class links have been resolved, use the resolved
17436ac495dSmrg      links.  */
17536ac495dSmrg   if (CLS_ISRESOLV (class))
17636ac495dSmrg     return class->super_class;
17736ac495dSmrg 
17836ac495dSmrg   /* Else, 'class' has not yet been resolved.  This means that its
17936ac495dSmrg      super_class pointer is really the name of the super class (rather
18036ac495dSmrg      than a pointer to the actual superclass).  */
18136ac495dSmrg   super_class_name = (char *)class->super_class;
18236ac495dSmrg 
18336ac495dSmrg   /* Return Nil for a root class.  */
18436ac495dSmrg   if (super_class_name == NULL)
18536ac495dSmrg     return Nil;
18636ac495dSmrg 
18736ac495dSmrg   /* Lookup the superclass of non-root classes.  */
18836ac495dSmrg   return objc_getClass (super_class_name);
18936ac495dSmrg }
19036ac495dSmrg 
19136ac495dSmrg 
19236ac495dSmrg /* Creates a tree of classes whose topmost class is directly inherited
19336ac495dSmrg    from `upper' and the bottom class in this tree is `bottom_class'.
19436ac495dSmrg    If `upper' is Nil, creates a class hierarchy up to a root class.
19536ac495dSmrg    The classes in this tree are super classes of `bottom_class'.  The
19636ac495dSmrg    `subclasses' member of each tree node point to the list of
19736ac495dSmrg    subclasses for the node.  */
19836ac495dSmrg static objc_class_tree *
create_tree_of_subclasses_inherited_from(Class bottom_class,Class upper)19936ac495dSmrg create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
20036ac495dSmrg {
20136ac495dSmrg   Class superclass;
20236ac495dSmrg   objc_class_tree *tree, *prev;
20336ac495dSmrg 
20436ac495dSmrg   DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
20536ac495dSmrg   DEBUG_PRINTF (" bottom_class = %s, upper = %s\n",
20636ac495dSmrg 		(bottom_class ? bottom_class->name : NULL),
20736ac495dSmrg 		(upper ? upper->name : NULL));
20836ac495dSmrg 
20936ac495dSmrg   superclass = class_superclass_of_class (bottom_class);
21036ac495dSmrg 
21136ac495dSmrg   prev = objc_calloc (1, sizeof (objc_class_tree));
21236ac495dSmrg   prev->class = bottom_class;
21336ac495dSmrg 
21436ac495dSmrg   if (superclass == upper)
21536ac495dSmrg     return prev;
21636ac495dSmrg 
21736ac495dSmrg   while (superclass != upper)
21836ac495dSmrg     {
21936ac495dSmrg       tree = objc_calloc (1, sizeof (objc_class_tree));
22036ac495dSmrg       tree->class = superclass;
22136ac495dSmrg       tree->subclasses = list_cons (prev, tree->subclasses);
22236ac495dSmrg       superclass = class_superclass_of_class (superclass);
22336ac495dSmrg       prev = tree;
22436ac495dSmrg     }
22536ac495dSmrg 
22636ac495dSmrg   return tree;
22736ac495dSmrg }
22836ac495dSmrg 
22936ac495dSmrg /* Insert the `class' into the proper place in the `tree' class
23036ac495dSmrg    hierarchy.  This function returns a new tree if the class has been
23136ac495dSmrg    successfully inserted into the tree or NULL if the class is not
23236ac495dSmrg    part of the classes hierarchy described by `tree'.  This function
23336ac495dSmrg    is private to objc_tree_insert_class (), you should not call it
23436ac495dSmrg    directly.  */
23536ac495dSmrg static objc_class_tree *
__objc_tree_insert_class(objc_class_tree * tree,Class class)23636ac495dSmrg __objc_tree_insert_class (objc_class_tree *tree, Class class)
23736ac495dSmrg {
23836ac495dSmrg   DEBUG_PRINTF ("__objc_tree_insert_class: tree = %p (root: %s), class = %s\n",
23936ac495dSmrg 		tree, ((tree && tree->class) ? tree->class->name : "Nil"), class->name);
24036ac495dSmrg 
24136ac495dSmrg   if (tree == NULL)
24236ac495dSmrg     return create_tree_of_subclasses_inherited_from (class, NULL);
24336ac495dSmrg   else if (class == tree->class)
24436ac495dSmrg     {
24536ac495dSmrg       /* `class' has been already inserted.  */
24636ac495dSmrg       DEBUG_PRINTF (" 1. class %s was previously inserted\n", class->name);
24736ac495dSmrg       return tree;
24836ac495dSmrg     }
24936ac495dSmrg   else if (class_superclass_of_class (class) == tree->class)
25036ac495dSmrg     {
25136ac495dSmrg       /* If class is a direct subclass of tree->class then add class
25236ac495dSmrg 	 to the list of subclasses. First check to see if it wasn't
25336ac495dSmrg 	 already inserted.  */
25436ac495dSmrg       struct objc_list *list = tree->subclasses;
25536ac495dSmrg       objc_class_tree *node;
25636ac495dSmrg 
25736ac495dSmrg       while (list)
25836ac495dSmrg 	{
25936ac495dSmrg 	  /* Class has been already inserted; do nothing just return
26036ac495dSmrg 	     the tree.  */
26136ac495dSmrg 	  if (((objc_class_tree *) list->head)->class == class)
26236ac495dSmrg 	    {
26336ac495dSmrg 	      DEBUG_PRINTF (" 2. class %s was previously inserted\n",
26436ac495dSmrg 			    class->name);
26536ac495dSmrg 	      return tree;
26636ac495dSmrg 	    }
26736ac495dSmrg 	  list = list->tail;
26836ac495dSmrg 	}
26936ac495dSmrg 
27036ac495dSmrg       /* Create a new node class and insert it into the list of
27136ac495dSmrg 	 subclasses.  */
27236ac495dSmrg       node = objc_calloc (1, sizeof (objc_class_tree));
27336ac495dSmrg       node->class = class;
27436ac495dSmrg       tree->subclasses = list_cons (node, tree->subclasses);
27536ac495dSmrg       DEBUG_PRINTF (" 3. class %s inserted\n", class->name);
27636ac495dSmrg       return tree;
27736ac495dSmrg     }
27836ac495dSmrg   else
27936ac495dSmrg     {
28036ac495dSmrg       /* The class is not a direct subclass of tree->class.  Search
28136ac495dSmrg          for class's superclasses in the list of subclasses.  */
28236ac495dSmrg       struct objc_list *subclasses = tree->subclasses;
28336ac495dSmrg 
28436ac495dSmrg       /* Precondition: the class must be a subclass of tree->class;
28536ac495dSmrg          otherwise return NULL to indicate our caller that it must
28636ac495dSmrg          take the next tree.  */
28736ac495dSmrg       if (! class_is_subclass_of_class (class, tree->class))
28836ac495dSmrg 	return NULL;
28936ac495dSmrg 
29036ac495dSmrg       for (; subclasses != NULL; subclasses = subclasses->tail)
29136ac495dSmrg 	{
29236ac495dSmrg 	  Class aClass = ((objc_class_tree *) (subclasses->head))->class;
29336ac495dSmrg 
29436ac495dSmrg 	  if (class_is_subclass_of_class (class, aClass))
29536ac495dSmrg 	    {
29636ac495dSmrg 	      /* If we found one of class's superclasses we insert the
29736ac495dSmrg 	         class into its subtree and return the original tree
29836ac495dSmrg 	         since nothing has been changed.  */
29936ac495dSmrg 	      subclasses->head
30036ac495dSmrg 		  = __objc_tree_insert_class (subclasses->head, class);
30136ac495dSmrg  	      DEBUG_PRINTF (" 4. class %s inserted\n", class->name);
30236ac495dSmrg 	      return tree;
30336ac495dSmrg 	    }
30436ac495dSmrg 	}
30536ac495dSmrg 
30636ac495dSmrg       /* We haven't found a subclass of `class' in the `subclasses'
30736ac495dSmrg          list.  Create a new tree of classes whose topmost class is a
30836ac495dSmrg          direct subclass of tree->class.  */
30936ac495dSmrg       {
31036ac495dSmrg 	objc_class_tree *new_tree
31136ac495dSmrg 	  = create_tree_of_subclasses_inherited_from (class, tree->class);
31236ac495dSmrg 	tree->subclasses = list_cons (new_tree, tree->subclasses);
31336ac495dSmrg  	DEBUG_PRINTF (" 5. class %s inserted\n", class->name);
31436ac495dSmrg 	return tree;
31536ac495dSmrg       }
31636ac495dSmrg     }
31736ac495dSmrg }
31836ac495dSmrg 
31936ac495dSmrg /* This function inserts `class' in the right tree hierarchy classes.  */
32036ac495dSmrg static void
objc_tree_insert_class(Class class)32136ac495dSmrg objc_tree_insert_class (Class class)
32236ac495dSmrg {
32336ac495dSmrg   struct objc_list *list_node;
32436ac495dSmrg   objc_class_tree *tree;
32536ac495dSmrg 
32636ac495dSmrg   list_node = __objc_class_tree_list;
32736ac495dSmrg   while (list_node)
32836ac495dSmrg     {
32936ac495dSmrg       /* Try to insert the class in this class hierarchy.  */
33036ac495dSmrg       tree = __objc_tree_insert_class (list_node->head, class);
33136ac495dSmrg       if (tree)
33236ac495dSmrg 	{
33336ac495dSmrg 	  list_node->head = tree;
33436ac495dSmrg 	  return;
33536ac495dSmrg 	}
33636ac495dSmrg       else
33736ac495dSmrg 	list_node = list_node->tail;
33836ac495dSmrg     }
33936ac495dSmrg 
34036ac495dSmrg   /* If the list was finished but the class hasn't been inserted, we
34136ac495dSmrg      don't have an existing class hierarchy that can accommodate it.
34236ac495dSmrg      Create a new one.  */
34336ac495dSmrg   __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
34436ac495dSmrg   __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
34536ac495dSmrg }
34636ac495dSmrg 
34736ac495dSmrg /* Traverse tree in preorder. Used to send +load.  */
34836ac495dSmrg static void
objc_preorder_traverse(objc_class_tree * tree,int level,void (* function)(objc_class_tree *,int))34936ac495dSmrg objc_preorder_traverse (objc_class_tree *tree,
35036ac495dSmrg 			int level,
35136ac495dSmrg 			void (*function) (objc_class_tree *, int))
35236ac495dSmrg {
35336ac495dSmrg   struct objc_list *node;
35436ac495dSmrg 
35536ac495dSmrg   (*function) (tree, level);
35636ac495dSmrg   for (node = tree->subclasses; node; node = node->tail)
35736ac495dSmrg     objc_preorder_traverse (node->head, level + 1, function);
35836ac495dSmrg }
35936ac495dSmrg 
36036ac495dSmrg /* Traverse tree in postorder. Used to destroy a tree.  */
36136ac495dSmrg static void
objc_postorder_traverse(objc_class_tree * tree,int level,void (* function)(objc_class_tree *,int))36236ac495dSmrg objc_postorder_traverse (objc_class_tree *tree,
36336ac495dSmrg 			 int level,
36436ac495dSmrg 			 void (*function) (objc_class_tree *, int))
36536ac495dSmrg {
36636ac495dSmrg   struct objc_list *node;
36736ac495dSmrg 
36836ac495dSmrg   for (node = tree->subclasses; node; node = node->tail)
36936ac495dSmrg     objc_postorder_traverse (node->head, level + 1, function);
37036ac495dSmrg   (*function) (tree, level);
37136ac495dSmrg }
37236ac495dSmrg 
37336ac495dSmrg /* Used to print a tree class hierarchy.  */
37436ac495dSmrg #ifdef DEBUG
37536ac495dSmrg static void
__objc_tree_print(objc_class_tree * tree,int level)37636ac495dSmrg __objc_tree_print (objc_class_tree *tree, int level)
37736ac495dSmrg {
37836ac495dSmrg   int i;
37936ac495dSmrg 
38036ac495dSmrg   for (i = 0; i < level; i++)
38136ac495dSmrg     printf ("  ");
38236ac495dSmrg   printf ("%s\n", tree->class->name);
38336ac495dSmrg }
38436ac495dSmrg #endif
38536ac495dSmrg 
38636ac495dSmrg /* Walks on a linked list of methods in the reverse order and executes
38736ac495dSmrg    all the methods corresponding to the `+load' selector.  Walking in
38836ac495dSmrg    the reverse order assures the +load of class is executed first and
38936ac495dSmrg    then +load of categories because of the way in which categories are
39036ac495dSmrg    added to the class methods.  This function needs to be called with
39136ac495dSmrg    the objc_runtime_mutex locked.  */
39236ac495dSmrg static void
__objc_send_load_using_method_list(struct objc_method_list * method_list,Class class)39336ac495dSmrg __objc_send_load_using_method_list (struct objc_method_list *method_list, Class class)
39436ac495dSmrg {
39536ac495dSmrg   static SEL load_selector = 0;
39636ac495dSmrg   int i;
39736ac495dSmrg 
39836ac495dSmrg   if (!method_list)
39936ac495dSmrg     return;
40036ac495dSmrg 
40136ac495dSmrg   /* This needs no lock protection because we are called with the
40236ac495dSmrg      objc_runtime_mutex locked.  */
40336ac495dSmrg   if (!load_selector)
40436ac495dSmrg     load_selector = sel_registerName ("load");
40536ac495dSmrg 
40636ac495dSmrg   /* method_list is a linked list of method lists; since we're
40736ac495dSmrg      executing in reverse order, we need to do the next list before we
40836ac495dSmrg      do this one.  */
40936ac495dSmrg   __objc_send_load_using_method_list (method_list->method_next, class);
41036ac495dSmrg 
41136ac495dSmrg   /* Search the method list.  */
41236ac495dSmrg   for (i = 0; i < method_list->method_count; i++)
41336ac495dSmrg     {
41436ac495dSmrg       struct objc_method *mth = &method_list->method_list[i];
41536ac495dSmrg 
41636ac495dSmrg       /* We are searching for +load methods that we haven't executed
41736ac495dSmrg 	 yet.  */
41836ac495dSmrg       if (mth->method_name && sel_eq (mth->method_name, load_selector)
41936ac495dSmrg 	  && ! objc_hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
42036ac495dSmrg 	{
42136ac495dSmrg 	  /* Add this method into the +load hash table, so we won't
42236ac495dSmrg 	     execute it again next time.  */
42336ac495dSmrg 	  objc_hash_add (&__objc_load_methods,
42436ac495dSmrg 			 mth->method_imp,
42536ac495dSmrg 			 mth->method_imp);
42636ac495dSmrg 
42736ac495dSmrg 	  /* Call +load.  */
42836ac495dSmrg 	  DEBUG_PRINTF (" begin of [%s +load]\n", class->name);
42936ac495dSmrg 	  (*mth->method_imp) ((id)class, mth->method_name);
43036ac495dSmrg 	  DEBUG_PRINTF (" end of [%s +load]\n", class->name);
43136ac495dSmrg 
43236ac495dSmrg 	  break;
43336ac495dSmrg 	}
43436ac495dSmrg     }
43536ac495dSmrg }
43636ac495dSmrg 
43736ac495dSmrg /* This function needs to be called with the objc_runtime_mutex
43836ac495dSmrg    locked.  */
43936ac495dSmrg static void
__objc_send_load(objc_class_tree * tree,int level)44036ac495dSmrg __objc_send_load (objc_class_tree *tree,
44136ac495dSmrg 		  int level __attribute__ ((__unused__)))
44236ac495dSmrg {
44336ac495dSmrg   Class class = tree->class;
44436ac495dSmrg   struct objc_method_list *method_list = class->class_pointer->methods;
44536ac495dSmrg 
44636ac495dSmrg   DEBUG_PRINTF ("+load: need to send load to class '%s'\n", class->name);
44736ac495dSmrg   __objc_send_load_using_method_list (method_list, class);
44836ac495dSmrg }
44936ac495dSmrg 
45036ac495dSmrg static void
__objc_destroy_class_tree_node(objc_class_tree * tree,int level)45136ac495dSmrg __objc_destroy_class_tree_node (objc_class_tree *tree,
45236ac495dSmrg 				int level __attribute__ ((__unused__)))
45336ac495dSmrg {
45436ac495dSmrg   objc_free (tree);
45536ac495dSmrg }
45636ac495dSmrg 
45736ac495dSmrg /* This is used to check if the relationship between two classes
45836ac495dSmrg    before the runtime completely installs the classes.  */
45936ac495dSmrg static BOOL
class_is_subclass_of_class(Class class,Class superclass)46036ac495dSmrg class_is_subclass_of_class (Class class, Class superclass)
46136ac495dSmrg {
46236ac495dSmrg   for (; class != Nil;)
46336ac495dSmrg     {
46436ac495dSmrg       if (class == superclass)
46536ac495dSmrg 	return YES;
46636ac495dSmrg       class = class_superclass_of_class (class);
46736ac495dSmrg     }
46836ac495dSmrg 
46936ac495dSmrg   return NO;
47036ac495dSmrg }
47136ac495dSmrg 
47236ac495dSmrg /* This list contains all the classes in the runtime system for whom
47336ac495dSmrg    their superclasses are not yet known to the runtime.  */
47436ac495dSmrg static struct objc_list *unresolved_classes = 0;
47536ac495dSmrg 
47636ac495dSmrg /* Extern function used to reference the Object class.  */
47736ac495dSmrg extern void __objc_force_linking (void);
47836ac495dSmrg 
47936ac495dSmrg void
__objc_force_linking(void)48036ac495dSmrg __objc_force_linking (void)
48136ac495dSmrg {
48236ac495dSmrg   extern void __objc_linking (void);
48336ac495dSmrg   __objc_linking ();
48436ac495dSmrg }
48536ac495dSmrg 
48636ac495dSmrg /* Run through the statics list, removing modules as soon as all its
48736ac495dSmrg    statics have been initialized.  */
48836ac495dSmrg static void
objc_init_statics(void)48936ac495dSmrg objc_init_statics (void)
49036ac495dSmrg {
49136ac495dSmrg   struct objc_list **cell = &uninitialized_statics;
49236ac495dSmrg   struct objc_static_instances **statics_in_module;
49336ac495dSmrg 
49436ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
49536ac495dSmrg 
49636ac495dSmrg   while (*cell)
49736ac495dSmrg     {
49836ac495dSmrg       int module_initialized = 1;
49936ac495dSmrg 
50036ac495dSmrg       for (statics_in_module = (*cell)->head;
50136ac495dSmrg 	   *statics_in_module; statics_in_module++)
50236ac495dSmrg 	{
50336ac495dSmrg 	  struct objc_static_instances *statics = *statics_in_module;
50436ac495dSmrg 	  Class class = objc_getClass (statics->class_name);
50536ac495dSmrg 
50636ac495dSmrg 	  if (! class)
50736ac495dSmrg 	    {
50836ac495dSmrg 	      /* It is unfortunate that this will cause all the
50936ac495dSmrg 		 statics initialization to be done again (eg, if we
51036ac495dSmrg 		 already initialized constant strings, and are now
51136ac495dSmrg 		 initializing protocols, setting module_initialized to
51236ac495dSmrg 		 0 would cause constant strings to be initialized
51336ac495dSmrg 		 again).  It would be good to be able to track if we
51436ac495dSmrg 		 have already initialized some of them.  */
51536ac495dSmrg 	      module_initialized = 0;
51636ac495dSmrg 	    }
51736ac495dSmrg 	  else
51836ac495dSmrg 	    {
51936ac495dSmrg 	      /* Note that if this is a list of Protocol objects, some
52036ac495dSmrg 		 of them may have been initialized already (because
52136ac495dSmrg 		 they were attached to classes or categories, and the
52236ac495dSmrg 		 class/category loading code automatically fixes them
52336ac495dSmrg 		 up), and some of them may not.  We really need to go
52436ac495dSmrg 		 through the whole list to be sure!  Protocols are
52536ac495dSmrg 		 also special because we want to register them and
52636ac495dSmrg 		 register all their selectors.  */
52736ac495dSmrg 	      id *inst;
52836ac495dSmrg 
52936ac495dSmrg 	      if (strcmp (statics->class_name, "Protocol") == 0)
53036ac495dSmrg 		{
53136ac495dSmrg 		  /* Protocols are special, because not only we want
53236ac495dSmrg 		     to fix up their class pointers, but we also want
53336ac495dSmrg 		     to register them and their selectors with the
53436ac495dSmrg 		     runtime.  */
53536ac495dSmrg 		  for (inst = &statics->instances[0]; *inst; inst++)
53636ac495dSmrg 		    __objc_init_protocol ((struct objc_protocol *)*inst);
53736ac495dSmrg 		}
53836ac495dSmrg 	      else
53936ac495dSmrg 		{
54036ac495dSmrg 		  /* Other static instances (typically constant
54136ac495dSmrg 		     strings) are easier as we just fix up their class
54236ac495dSmrg 		     pointers.  */
54336ac495dSmrg 		  for (inst = &statics->instances[0]; *inst; inst++)
54436ac495dSmrg 		    (*inst)->class_pointer = class;
54536ac495dSmrg 		}
54636ac495dSmrg 	    }
54736ac495dSmrg 	}
54836ac495dSmrg       if (module_initialized)
54936ac495dSmrg 	{
55036ac495dSmrg 	  /* Remove this module from the uninitialized list.  */
55136ac495dSmrg 	  struct objc_list *this = *cell;
55236ac495dSmrg 	  *cell = this->tail;
55336ac495dSmrg 	  objc_free (this);
55436ac495dSmrg 	}
55536ac495dSmrg       else
55636ac495dSmrg 	cell = &(*cell)->tail;
55736ac495dSmrg     }
55836ac495dSmrg 
55936ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
56036ac495dSmrg }
56136ac495dSmrg 
56236ac495dSmrg /* This function is called by constructor functions generated for each
56336ac495dSmrg    module compiled.  (_GLOBAL_$I$...) The purpose of this function is
56436ac495dSmrg    to gather the module pointers so that they may be processed by the
56536ac495dSmrg    initialization routines as soon as possible.  */
56636ac495dSmrg void
__objc_exec_class(struct objc_module * module)56736ac495dSmrg __objc_exec_class (struct objc_module *module)
56836ac495dSmrg {
56936ac495dSmrg   /* Have we processed any constructors previously?  This flag is used
57036ac495dSmrg      to indicate that some global data structures need to be
57136ac495dSmrg      built.  */
57236ac495dSmrg   static BOOL previous_constructors = 0;
57336ac495dSmrg 
57436ac495dSmrg   static struct objc_list *unclaimed_categories = 0;
57536ac495dSmrg 
57636ac495dSmrg   /* The symbol table (defined in objc-private/module-abi-8.h)
57736ac495dSmrg      generated by gcc.  */
57836ac495dSmrg   struct objc_symtab *symtab = module->symtab;
57936ac495dSmrg 
58036ac495dSmrg   /* The statics in this module.  */
58136ac495dSmrg   struct objc_static_instances **statics
58236ac495dSmrg     = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
58336ac495dSmrg 
58436ac495dSmrg   /* Entry used to traverse hash lists.  */
58536ac495dSmrg   struct objc_list **cell;
58636ac495dSmrg 
58736ac495dSmrg   /* The table of selector references for this module.  */
58836ac495dSmrg   struct objc_selector *selectors = symtab->refs;
58936ac495dSmrg 
59036ac495dSmrg   int i;
59136ac495dSmrg 
59236ac495dSmrg   DEBUG_PRINTF ("\n__objc_exec_class (%p) - start processing module...\n", module);
59336ac495dSmrg 
59436ac495dSmrg   /* Check gcc version.  */
59536ac495dSmrg   init_check_module_version (module);
59636ac495dSmrg 
59736ac495dSmrg   /* On the first call of this routine, initialize some data
59836ac495dSmrg      structures.  */
59936ac495dSmrg   if (! previous_constructors)
60036ac495dSmrg     {
60136ac495dSmrg 	/* Initialize thread-safe system.  */
60236ac495dSmrg       __objc_init_thread_system ();
60336ac495dSmrg       __objc_runtime_threads_alive = 1;
60436ac495dSmrg       __objc_runtime_mutex = objc_mutex_allocate ();
60536ac495dSmrg 
60636ac495dSmrg       __objc_init_selector_tables ();
60736ac495dSmrg       __objc_init_class_tables ();
60836ac495dSmrg       __objc_init_dispatch_tables ();
60936ac495dSmrg       duplicate_classes = objc_hash_new (8,
61036ac495dSmrg 					 (hash_func_type)objc_hash_ptr,
61136ac495dSmrg 					 objc_compare_ptrs);
61236ac495dSmrg       __objc_load_methods = objc_hash_new (128,
61336ac495dSmrg 					   (hash_func_type)objc_hash_ptr,
61436ac495dSmrg 					   objc_compare_ptrs);
61536ac495dSmrg       __objc_protocols_init ();
61636ac495dSmrg       __objc_accessors_init ();
61736ac495dSmrg       __objc_sync_init ();
61836ac495dSmrg       previous_constructors = 1;
61936ac495dSmrg     }
62036ac495dSmrg 
62136ac495dSmrg   /* Save the module pointer so that later we remember to call +load
62236ac495dSmrg      on all classes and categories on it.  */
62336ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
62436ac495dSmrg   __objc_module_list = list_cons (module, __objc_module_list);
62536ac495dSmrg 
62636ac495dSmrg   /* Replace referenced selectors from names to SELs.  */
62736ac495dSmrg   if (selectors)
62836ac495dSmrg     {
62936ac495dSmrg       DEBUG_PRINTF (" registering selectors\n");
63036ac495dSmrg       __objc_register_selectors_from_module (selectors);
63136ac495dSmrg     }
63236ac495dSmrg 
63336ac495dSmrg   /* Parse the classes in the load module and gather selector
63436ac495dSmrg      information.  */
63536ac495dSmrg   for (i = 0; i < symtab->cls_def_cnt; ++i)
63636ac495dSmrg     {
63736ac495dSmrg       Class class = (Class) symtab->defs[i];
63836ac495dSmrg       const char *superclass = (char *) class->super_class;
63936ac495dSmrg 
64036ac495dSmrg       /* Make sure we have what we think.  */
64136ac495dSmrg       assert (CLS_ISCLASS (class));
64236ac495dSmrg       assert (CLS_ISMETA (class->class_pointer));
64336ac495dSmrg       DEBUG_PRINTF (" installing class '%s'\n", class->name);
64436ac495dSmrg 
64536ac495dSmrg       /* Workaround for a bug in clang: Clang may set flags other than
64636ac495dSmrg 	 _CLS_CLASS and _CLS_META even when compiling for the
64736ac495dSmrg 	 traditional ABI (version 8), confusing our runtime.  Try to
64836ac495dSmrg 	 wipe these flags out.  */
64936ac495dSmrg       if (CLS_ISCLASS (class))
65036ac495dSmrg 	__CLS_INFO (class) = _CLS_CLASS;
65136ac495dSmrg       else
65236ac495dSmrg 	__CLS_INFO (class) = _CLS_META;
65336ac495dSmrg 
65436ac495dSmrg       /* Initialize the subclass list to be NULL.  In some cases it
65536ac495dSmrg 	 isn't and this crashes the program.  */
65636ac495dSmrg       class->subclass_list = NULL;
65736ac495dSmrg 
65836ac495dSmrg       if (__objc_init_class (class))
65936ac495dSmrg 	{
66036ac495dSmrg 	  /* Check to see if the superclass is known in this point. If
66136ac495dSmrg 	     it's not add the class to the unresolved_classes list.  */
66236ac495dSmrg 	  if (superclass && ! objc_getClass (superclass))
66336ac495dSmrg 	    unresolved_classes = list_cons (class, unresolved_classes);
66436ac495dSmrg 	}
66536ac495dSmrg     }
66636ac495dSmrg 
66736ac495dSmrg   /* Process category information from the module.  */
66836ac495dSmrg   for (i = 0; i < symtab->cat_def_cnt; ++i)
66936ac495dSmrg     {
67036ac495dSmrg       struct objc_category *category = symtab->defs[i + symtab->cls_def_cnt];
67136ac495dSmrg       Class class = objc_getClass (category->class_name);
67236ac495dSmrg 
67336ac495dSmrg       /* If the class for the category exists then append its
67436ac495dSmrg 	 methods.  */
67536ac495dSmrg       if (class)
67636ac495dSmrg 	{
67736ac495dSmrg 	  DEBUG_PRINTF (" installing category '%s (%s)'\n", category->class_name, category->category_name);
67836ac495dSmrg 	  /* Do instance methods.  */
67936ac495dSmrg 	  if (category->instance_methods)
68036ac495dSmrg 	    class_add_method_list (class, category->instance_methods);
68136ac495dSmrg 
68236ac495dSmrg 	  /* Do class methods.  */
68336ac495dSmrg 	  if (category->class_methods)
68436ac495dSmrg 	    class_add_method_list ((Class) class->class_pointer,
68536ac495dSmrg 				   category->class_methods);
68636ac495dSmrg 
68736ac495dSmrg 	  if (category->protocols)
68836ac495dSmrg 	    {
68936ac495dSmrg 	      __objc_init_protocols (category->protocols);
69036ac495dSmrg 	      __objc_class_add_protocols (class, category->protocols);
69136ac495dSmrg 	    }
69236ac495dSmrg 
69336ac495dSmrg           /* Register the instance methods as class methods, this is
69436ac495dSmrg              only done for root classes.  */
69536ac495dSmrg           __objc_register_instance_methods_to_class (class);
69636ac495dSmrg 	}
69736ac495dSmrg       else
69836ac495dSmrg 	{
69936ac495dSmrg 	  DEBUG_PRINTF (" delaying installation of category '%s (%s)'\n", category->class_name, category->category_name);
70036ac495dSmrg 	  /* The object to which the category methods belong can't be
70136ac495dSmrg 	     found.  Save the information.  */
70236ac495dSmrg 	  unclaimed_categories = list_cons (category, unclaimed_categories);
70336ac495dSmrg 	}
70436ac495dSmrg     }
70536ac495dSmrg 
70636ac495dSmrg   if (statics)
70736ac495dSmrg     uninitialized_statics = list_cons (statics, uninitialized_statics);
70836ac495dSmrg   if (uninitialized_statics)
70936ac495dSmrg     objc_init_statics ();
71036ac495dSmrg 
71136ac495dSmrg   /* Scan the unclaimed category hash.  Attempt to attach any
71236ac495dSmrg      unclaimed categories to objects.  */
71336ac495dSmrg   for (cell = &unclaimed_categories; *cell; )
71436ac495dSmrg     {
71536ac495dSmrg       struct objc_category *category = (*cell)->head;
71636ac495dSmrg       Class class = objc_getClass (category->class_name);
71736ac495dSmrg 
71836ac495dSmrg       if (class)
71936ac495dSmrg 	{
72036ac495dSmrg 	  DEBUG_PRINTF (" installing (delayed) category '%s (%s)'\n", category->class_name, category->category_name);
72136ac495dSmrg 	  list_remove_head (cell);
72236ac495dSmrg 
72336ac495dSmrg 	  if (category->instance_methods)
72436ac495dSmrg 	    class_add_method_list (class, category->instance_methods);
72536ac495dSmrg 
72636ac495dSmrg 	  if (category->class_methods)
72736ac495dSmrg 	    class_add_method_list ((Class) class->class_pointer,
72836ac495dSmrg 				   category->class_methods);
72936ac495dSmrg 
73036ac495dSmrg 	  if (category->protocols)
73136ac495dSmrg 	    {
73236ac495dSmrg 	      __objc_init_protocols (category->protocols);
73336ac495dSmrg 	      __objc_class_add_protocols (class, category->protocols);
73436ac495dSmrg 	    }
73536ac495dSmrg 
73636ac495dSmrg           /* Register the instance methods as class methods, this is
73736ac495dSmrg              only done for root classes.  */
73836ac495dSmrg           __objc_register_instance_methods_to_class (class);
73936ac495dSmrg 	}
74036ac495dSmrg       else
74136ac495dSmrg 	cell = &(*cell)->tail;
74236ac495dSmrg     }
74336ac495dSmrg 
74436ac495dSmrg   if (unclaimed_proto_list && objc_getClass ("Protocol"))
74536ac495dSmrg     {
74636ac495dSmrg       list_mapcar (unclaimed_proto_list,
74736ac495dSmrg 		   (void (*) (void *))__objc_init_protocols);
74836ac495dSmrg       list_free (unclaimed_proto_list);
74936ac495dSmrg       unclaimed_proto_list = 0;
75036ac495dSmrg     }
75136ac495dSmrg 
75236ac495dSmrg   objc_send_load ();
75336ac495dSmrg 
75436ac495dSmrg   /* Check if there are no unresolved classes (ie, classes whose
75536ac495dSmrg      superclass has not been loaded yet) and that the 'Object' class,
75636ac495dSmrg      used as the class of classes, exist.  If so, it is worth
75736ac495dSmrg      "resolving the class links" at this point, which will setup all
75836ac495dSmrg      the class/superclass pointers.  */
75936ac495dSmrg   if (!unresolved_classes && objc_getClass ("Object"))
76036ac495dSmrg     {
76136ac495dSmrg       DEBUG_PRINTF (" resolving class links\n");
76236ac495dSmrg       __objc_resolve_class_links ();
76336ac495dSmrg     }
76436ac495dSmrg 
76536ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
76636ac495dSmrg 
76736ac495dSmrg   DEBUG_PRINTF ("__objc_exec_class (%p) - finished processing module...\n\n", module);
76836ac495dSmrg }
76936ac495dSmrg 
77036ac495dSmrg /* This function needs to be called with the objc_runtime_mutex
77136ac495dSmrg    locked.  */
77236ac495dSmrg static void
objc_send_load(void)77336ac495dSmrg objc_send_load (void)
77436ac495dSmrg {
77536ac495dSmrg   if (!__objc_module_list)
77636ac495dSmrg     return;
77736ac495dSmrg 
77836ac495dSmrg   /* Try to find out if all the classes loaded so far also have their
77936ac495dSmrg      superclasses known to the runtime.  We suppose that the objects
78036ac495dSmrg      that are allocated in the +load method are in general of a class
78136ac495dSmrg      declared in the same module.  */
78236ac495dSmrg   if (unresolved_classes)
78336ac495dSmrg     {
78436ac495dSmrg       Class class = unresolved_classes->head;
78536ac495dSmrg 
78636ac495dSmrg       while (objc_getClass ((char *) class->super_class))
78736ac495dSmrg 	{
78836ac495dSmrg 	  list_remove_head (&unresolved_classes);
78936ac495dSmrg 	  if (unresolved_classes)
79036ac495dSmrg 	    class = unresolved_classes->head;
79136ac495dSmrg 	  else
79236ac495dSmrg 	    break;
79336ac495dSmrg 	}
79436ac495dSmrg 
79536ac495dSmrg       /* If we still have classes for whom we don't have yet their
79636ac495dSmrg          super classes known to the runtime we don't send the +load
79736ac495dSmrg          messages (and call the load callback) yet.  */
79836ac495dSmrg       if (unresolved_classes)
79936ac495dSmrg 	return;
80036ac495dSmrg     }
80136ac495dSmrg 
80236ac495dSmrg   /* Special check.  If 'Object', which is used by meta-classes, has
80336ac495dSmrg      not been loaded yet, delay sending of +load.  */
80436ac495dSmrg   if (! objc_getClass ("Object"))
80536ac495dSmrg     return;
80636ac495dSmrg 
80736ac495dSmrg   /* Iterate over all modules in the __objc_module_list and call on
80836ac495dSmrg      them the __objc_create_classes_tree function.  This function
80936ac495dSmrg      creates a tree of classes that resembles the class hierarchy.  */
81036ac495dSmrg   list_mapcar (__objc_module_list,
81136ac495dSmrg 	       (void (*) (void *)) __objc_create_classes_tree);
81236ac495dSmrg 
81336ac495dSmrg   while (__objc_class_tree_list)
81436ac495dSmrg     {
81536ac495dSmrg #ifdef DEBUG
81636ac495dSmrg       objc_preorder_traverse (__objc_class_tree_list->head,
81736ac495dSmrg 			      0, __objc_tree_print);
81836ac495dSmrg #endif
81936ac495dSmrg       objc_preorder_traverse (__objc_class_tree_list->head,
82036ac495dSmrg 			      0, __objc_send_load);
82136ac495dSmrg       objc_postorder_traverse (__objc_class_tree_list->head,
82236ac495dSmrg 			      0, __objc_destroy_class_tree_node);
82336ac495dSmrg       list_remove_head (&__objc_class_tree_list);
82436ac495dSmrg     }
82536ac495dSmrg 
82636ac495dSmrg   /* For each module, call the _objc_load_callback if any is
82736ac495dSmrg      defined.  */
82836ac495dSmrg   list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_load_callback);
82936ac495dSmrg 
83036ac495dSmrg   /* Empty the list of modules.  */
83136ac495dSmrg   list_free (__objc_module_list);
83236ac495dSmrg   __objc_module_list = NULL;
83336ac495dSmrg }
83436ac495dSmrg 
83536ac495dSmrg static void
__objc_create_classes_tree(struct objc_module * module)83636ac495dSmrg __objc_create_classes_tree (struct objc_module *module)
83736ac495dSmrg {
83836ac495dSmrg   /* The runtime mutex is locked at this point */
83936ac495dSmrg   struct objc_symtab *symtab = module->symtab;
84036ac495dSmrg   int i;
84136ac495dSmrg 
84236ac495dSmrg   /* Iterate through classes defined in this module and insert them in
84336ac495dSmrg      the classes tree hierarchy.  */
84436ac495dSmrg   for (i = 0; i < symtab->cls_def_cnt; i++)
84536ac495dSmrg     {
84636ac495dSmrg       Class class = (Class) symtab->defs[i];
84736ac495dSmrg 
84836ac495dSmrg       if (!objc_hash_is_key_in_hash (duplicate_classes, class))
84936ac495dSmrg 	objc_tree_insert_class (class);
85036ac495dSmrg     }
85136ac495dSmrg 
85236ac495dSmrg   /* Now iterate over "claimed" categories too (ie, categories that
85336ac495dSmrg      extend a class that has already been loaded by the runtime), and
85436ac495dSmrg      insert them in the classes tree hiearchy too.  Otherwise, if you
85536ac495dSmrg      add a category, its +load method would not be called if the class
85636ac495dSmrg      is already loaded in the runtime.  It the category is
85736ac495dSmrg      "unclaimed", ie, we haven't loaded the main class yet, postpone
85836ac495dSmrg      sending +load as we want to execute +load from the class before
85936ac495dSmrg      we execute the one from the category.  */
86036ac495dSmrg   for (i = 0; i < symtab->cat_def_cnt; ++i)
86136ac495dSmrg     {
86236ac495dSmrg       struct objc_category *category = symtab->defs[i + symtab->cls_def_cnt];
86336ac495dSmrg       Class class = objc_getClass (category->class_name);
86436ac495dSmrg 
86536ac495dSmrg       /* If the class for the category exists then append its
86636ac495dSmrg 	 methods.  */
86736ac495dSmrg       if (class)
86836ac495dSmrg 	objc_tree_insert_class (class);
86936ac495dSmrg     }
87036ac495dSmrg }
87136ac495dSmrg 
87236ac495dSmrg static void
__objc_call_load_callback(struct objc_module * module)87336ac495dSmrg __objc_call_load_callback (struct objc_module *module)
87436ac495dSmrg {
87536ac495dSmrg   if (_objc_load_callback)
87636ac495dSmrg     {
87736ac495dSmrg       /* The runtime mutex is locked at this point.  */
87836ac495dSmrg       struct objc_symtab *symtab = module->symtab;
87936ac495dSmrg       int i;
88036ac495dSmrg 
88136ac495dSmrg       /* Iterate through classes defined in this module and call the callback
88236ac495dSmrg 	 for each one.  */
88336ac495dSmrg       for (i = 0; i < symtab->cls_def_cnt; i++)
88436ac495dSmrg 	{
88536ac495dSmrg 	  Class class = (Class) symtab->defs[i];
88636ac495dSmrg 
88736ac495dSmrg 	  if (!objc_hash_is_key_in_hash (duplicate_classes, class))
88836ac495dSmrg 	    {
88936ac495dSmrg 	      /* Call the _objc_load_callback for this class.  */
89036ac495dSmrg 	      DEBUG_PRINTF (" calling the load callback for class '%s'\n", class->name);
89136ac495dSmrg 	      _objc_load_callback (class, 0);
89236ac495dSmrg 	    }
89336ac495dSmrg 	}
89436ac495dSmrg 
89536ac495dSmrg       /* Call the _objc_load_callback for categories.  Don't register
89636ac495dSmrg 	 the instance methods as class methods for categories to root
89736ac495dSmrg 	 classes since they were already added in the class.  */
89836ac495dSmrg       for (i = 0; i < symtab->cat_def_cnt; i++)
89936ac495dSmrg 	{
90036ac495dSmrg 	  struct objc_category *category = symtab->defs[i + symtab->cls_def_cnt];
90136ac495dSmrg 	  Class class = objc_getClass (category->class_name);
90236ac495dSmrg 
90336ac495dSmrg 	  DEBUG_PRINTF (" calling the load callback for category '%s (%s)'\n",
90436ac495dSmrg 			category->class_name, category->category_name);
90536ac495dSmrg 	  _objc_load_callback (class, category);
90636ac495dSmrg 	}
90736ac495dSmrg     }
90836ac495dSmrg }
90936ac495dSmrg 
91036ac495dSmrg /* Sanity check the version of gcc used to compile `module'.  */
91136ac495dSmrg static void
init_check_module_version(struct objc_module * module)91236ac495dSmrg init_check_module_version (struct objc_module *module)
91336ac495dSmrg {
91436ac495dSmrg   if ((module->version != OBJC_VERSION) || (module->size != sizeof (struct objc_module)))
91536ac495dSmrg     {
91636ac495dSmrg       _objc_abort ("Module %s version %d doesn't match runtime %d\n",
91736ac495dSmrg 		   module->name, (int)module->version, OBJC_VERSION);
91836ac495dSmrg     }
91936ac495dSmrg }
92036ac495dSmrg 
92136ac495dSmrg /* __objc_init_class must be called with __objc_runtime_mutex already
92236ac495dSmrg    locked.  Return YES if the class could be setup; return NO if the
92336ac495dSmrg    class could not be setup because a class with the same name already
92436ac495dSmrg    exists.  */
92536ac495dSmrg BOOL
__objc_init_class(Class class)92636ac495dSmrg __objc_init_class (Class class)
92736ac495dSmrg {
92836ac495dSmrg   /* Store the class in the class table and assign class numbers.  */
92936ac495dSmrg   if (__objc_add_class_to_hash (class))
93036ac495dSmrg     {
93136ac495dSmrg       /* Register all of the selectors in the class and meta class.  */
93236ac495dSmrg       __objc_register_selectors_from_class (class);
93336ac495dSmrg       __objc_register_selectors_from_class ((Class) class->class_pointer);
93436ac495dSmrg 
93536ac495dSmrg       /* Install the fake dispatch tables.  */
93636ac495dSmrg       __objc_install_premature_dtable (class);
93736ac495dSmrg       __objc_install_premature_dtable (class->class_pointer);
93836ac495dSmrg 
93936ac495dSmrg       /* Register the instance methods as class methods, this is only
94036ac495dSmrg 	 done for root classes.  */
94136ac495dSmrg       __objc_register_instance_methods_to_class (class);
94236ac495dSmrg 
94336ac495dSmrg       if (class->protocols)
94436ac495dSmrg 	__objc_init_protocols (class->protocols);
94536ac495dSmrg 
94636ac495dSmrg       return YES;
94736ac495dSmrg     }
94836ac495dSmrg   else
94936ac495dSmrg     {
95036ac495dSmrg       /* The module contains a duplicate class.  Remember it so that
95136ac495dSmrg 	 we will ignore it later.  */
95236ac495dSmrg       DEBUG_PRINTF (" duplicate class '%s' - will be ignored\n", class->name);
95336ac495dSmrg       objc_hash_add (&duplicate_classes, class, class);
95436ac495dSmrg       return NO;
95536ac495dSmrg     }
95636ac495dSmrg }
95736ac495dSmrg 
95836ac495dSmrg /* __objc_init_protocol must be called with __objc_runtime_mutex
95936ac495dSmrg    already locked, and the "Protocol" class already registered.  */
96036ac495dSmrg static void
__objc_init_protocol(struct objc_protocol * protocol)96136ac495dSmrg __objc_init_protocol (struct objc_protocol *protocol)
96236ac495dSmrg {
96336ac495dSmrg   static Class proto_class = 0;
96436ac495dSmrg 
96536ac495dSmrg   if (! proto_class)
96636ac495dSmrg     proto_class = objc_getClass ("Protocol");
96736ac495dSmrg 
96836ac495dSmrg   if (((size_t)protocol->class_pointer) == PROTOCOL_VERSION)
96936ac495dSmrg     {
97036ac495dSmrg       /* Assign class pointer.  */
97136ac495dSmrg       protocol->class_pointer = proto_class;
97236ac495dSmrg 
97336ac495dSmrg       /* Register all the selectors in the protocol with the runtime.
97436ac495dSmrg 	 This both registers the selectors with the right types, and
97536ac495dSmrg 	 it also fixes up the 'struct objc_method' structures inside
97636ac495dSmrg 	 the protocol so that each method_name (a char * as compiled
97736ac495dSmrg 	 by the compiler) is replaced with the appropriate runtime
97836ac495dSmrg 	 SEL.  */
97936ac495dSmrg       if (protocol->class_methods)
98036ac495dSmrg 	__objc_register_selectors_from_description_list (protocol->class_methods);
98136ac495dSmrg 
98236ac495dSmrg       if (protocol->instance_methods)
98336ac495dSmrg 	__objc_register_selectors_from_description_list (protocol->instance_methods);
98436ac495dSmrg 
98536ac495dSmrg       /* Register the protocol in the hashtable or protocols by
98636ac495dSmrg 	 name.  */
98736ac495dSmrg       __objc_protocols_add_protocol (protocol->protocol_name, protocol);
98836ac495dSmrg 
98936ac495dSmrg       /* Init super protocols.  */
99036ac495dSmrg       __objc_init_protocols (protocol->protocol_list);
99136ac495dSmrg     }
99236ac495dSmrg   else if (protocol->class_pointer != proto_class)
99336ac495dSmrg     {
99436ac495dSmrg       _objc_abort ("Version %d doesn't match runtime protocol version %d\n",
99536ac495dSmrg 		   (int) ((char *) protocol->class_pointer
99636ac495dSmrg 			  - (char *) 0),
99736ac495dSmrg 		   PROTOCOL_VERSION);
99836ac495dSmrg     }
99936ac495dSmrg }
100036ac495dSmrg 
100136ac495dSmrg static void
__objc_init_protocols(struct objc_protocol_list * protos)100236ac495dSmrg __objc_init_protocols (struct objc_protocol_list *protos)
100336ac495dSmrg {
100436ac495dSmrg   size_t i;
100536ac495dSmrg   static Class proto_class = 0;
100636ac495dSmrg 
100736ac495dSmrg   if (! protos)
100836ac495dSmrg     return;
100936ac495dSmrg 
101036ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
101136ac495dSmrg 
101236ac495dSmrg   if (! proto_class)
101336ac495dSmrg     proto_class = objc_getClass ("Protocol");
101436ac495dSmrg 
101536ac495dSmrg   if (! proto_class)
101636ac495dSmrg     {
101736ac495dSmrg       unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
101836ac495dSmrg       objc_mutex_unlock (__objc_runtime_mutex);
101936ac495dSmrg       return;
102036ac495dSmrg     }
102136ac495dSmrg 
102236ac495dSmrg #if 0
102336ac495dSmrg   assert (protos->next == 0); /* Only single ones allowed.  */
102436ac495dSmrg #endif
102536ac495dSmrg 
102636ac495dSmrg   for (i = 0; i < protos->count; i++)
102736ac495dSmrg     {
102836ac495dSmrg       struct objc_protocol *aProto = protos->list[i];
102936ac495dSmrg       __objc_init_protocol (aProto);
103036ac495dSmrg     }
103136ac495dSmrg 
103236ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
103336ac495dSmrg }
103436ac495dSmrg 
103536ac495dSmrg static void
__objc_class_add_protocols(Class class,struct objc_protocol_list * protos)103636ac495dSmrg __objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
103736ac495dSmrg {
103836ac495dSmrg   if (! protos)
103936ac495dSmrg     return;
104036ac495dSmrg 
104136ac495dSmrg   protos->next = class->protocols;
104236ac495dSmrg   class->protocols = protos;
104336ac495dSmrg }
1044