OSDN Git Service

edc56aa9ec4d2679e7b8f8e53f6b67bd7785e797
[pf3gnuchains/gcc-fork.git] / libobjc / class.c
1 /* GNU Objective C Runtime class related functions
2    Copyright (C) 1993, 1995, 1996, 1997, 2001, 2002, 2009, 2010
3      Free Software Foundation, Inc.
4    Contributed by Kresten Krab Thorup and Dennis Glatting.
5
6    Lock-free class table code designed and written from scratch by
7    Nicola Pero, 2001.
8
9 This file is part of GCC.
10
11 GCC is free software; you can redistribute it and/or modify it under the
12 terms of the GNU General Public License as published by the Free Software
13 Foundation; either version 3, or (at your option) any later version.
14
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18 details.
19
20 Under Section 7 of GPL version 3, you are granted additional
21 permissions described in the GCC Runtime Library Exception, version
22 3.1, as published by the Free Software Foundation.
23
24 You should have received a copy of the GNU General Public License and
25 a copy of the GCC Runtime Library Exception along with this program;
26 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
27 <http://www.gnu.org/licenses/>.  */
28
29 /* The code in this file critically affects class method invocation
30   speed.  This long preamble comment explains why, and the issues
31   involved.
32
33   One of the traditional weaknesses of the GNU Objective-C runtime is
34   that class method invocations are slow.  The reason is that when you
35   write
36   
37   array = [NSArray new];
38   
39   this gets basically compiled into the equivalent of 
40   
41   array = [(objc_get_class ("NSArray")) new];
42   
43   objc_get_class returns the class pointer corresponding to the string
44   `NSArray'; and because of the lookup, the operation is more
45   complicated and slow than a simple instance method invocation.
46   
47   Most high performance Objective-C code (using the GNU Objc runtime)
48   I had the opportunity to read (or write) work around this problem by
49   caching the class pointer:
50   
51   Class arrayClass = [NSArray class];
52   
53   ... later on ...
54   
55   array = [arrayClass new];
56   array = [arrayClass new];
57   array = [arrayClass new];
58   
59   In this case, you always perform a class lookup (the first one), but
60   then all the [arrayClass new] methods run exactly as fast as an
61   instance method invocation.  It helps if you have many class method
62   invocations to the same class.
63   
64   The long-term solution to this problem would be to modify the
65   compiler to output tables of class pointers corresponding to all the
66   class method invocations, and to add code to the runtime to update
67   these tables - that should in the end allow class method invocations
68   to perform precisely as fast as instance method invocations, because
69   no class lookup would be involved.  I think the Apple Objective-C
70   runtime uses this technique.  Doing this involves synchronized
71   modifications in the runtime and in the compiler.
72   
73   As a first medicine to the problem, I [NP] have redesigned and
74   rewritten the way the runtime is performing class lookup.  This
75   doesn't give as much speed as the other (definitive) approach, but
76   at least a class method invocation now takes approximately 4.5 times
77   an instance method invocation on my machine (it would take approx 12
78   times before the rewriting), which is a lot better.
79
80   One of the main reason the new class lookup is so faster is because
81   I implemented it in a way that can safely run multithreaded without
82   using locks - a so-called `lock-free' data structure.  The atomic
83   operation is pointer assignment.  The reason why in this problem
84   lock-free data structures work so well is that you never remove
85   classes from the table - and the difficult thing with lock-free data
86   structures is freeing data when is removed from the structures.  */
87
88 #include "objc-private/common.h"
89 #include "objc-private/error.h"
90 #include "objc/runtime.h"
91 #include "objc/thr.h"
92 #include "objc-private/module-abi-8.h"  /* For CLS_ISCLASS and similar.  */
93 #include "objc-private/runtime.h"       /* the kitchen sink */
94 #include "objc-private/sarray.h"        /* For sarray_put_at_safe.  */
95 #include "objc-private/selector.h"      /* For sarray_put_at_safe.  */
96 #include <string.h>                     /* For memset */
97
98 /* We use a table which maps a class name to the corresponding class
99    pointer.  The first part of this file defines this table, and
100    functions to do basic operations on the table.  The second part of
101    the file implements some higher level Objective-C functionality for
102    classes by using the functions provided in the first part to manage
103    the table. */
104
105 /**
106  ** Class Table Internals
107  **/
108
109 /* A node holding a class */
110 typedef struct class_node
111 {
112   struct class_node *next;      /* Pointer to next entry on the list.
113                                    NULL indicates end of list. */
114   
115   const char *name;             /* The class name string */
116   int length;                   /* The class name string length */
117   Class pointer;                /* The Class pointer */
118   
119 } *class_node_ptr;
120
121 /* A table containing classes is a class_node_ptr (pointing to the
122    first entry in the table - if it is NULL, then the table is
123    empty). */
124
125 /* We have 1024 tables.  Each table contains all class names which
126    have the same hash (which is a number between 0 and 1023).  To look
127    up a class_name, we compute its hash, and get the corresponding
128    table.  Once we have the table, we simply compare strings directly
129    till we find the one which we want (using the length first).  The
130    number of tables is quite big on purpose (a normal big application
131    has less than 1000 classes), so that you shouldn't normally get any
132    collisions, and get away with a single comparison (which we can't
133    avoid since we need to know that you have got the right thing).  */
134 #define CLASS_TABLE_SIZE 1024
135 #define CLASS_TABLE_MASK 1023
136
137 static class_node_ptr class_table_array[CLASS_TABLE_SIZE];
138
139 /* The table writing mutex - we lock on writing to avoid conflicts
140    between different writers, but we read without locks.  That is
141    possible because we assume pointer assignment to be an atomic
142    operation.  TODO: This is only true under certain circumstances,
143    which should be clarified.  */
144 static objc_mutex_t __class_table_lock = NULL;
145
146 /* CLASS_TABLE_HASH is how we compute the hash of a class name.  It is
147    a macro - *not* a function - arguments *are* modified directly.
148
149    INDEX should be a variable holding an int;
150    HASH should be a variable holding an int;
151    CLASS_NAME should be a variable holding a (char *) to the class_name.  
152
153    After the macro is executed, INDEX contains the length of the
154    string, and HASH the computed hash of the string; CLASS_NAME is
155    untouched.  */
156
157 #define CLASS_TABLE_HASH(INDEX, HASH, CLASS_NAME)          \
158   HASH = 0;                                                  \
159   for (INDEX = 0; CLASS_NAME[INDEX] != '\0'; INDEX++)        \
160     {                                                        \
161       HASH = (HASH << 4) ^ (HASH >> 28) ^ CLASS_NAME[INDEX]; \
162     }                                                        \
163                                                              \
164   HASH = (HASH ^ (HASH >> 10) ^ (HASH >> 20)) & CLASS_TABLE_MASK;
165
166 /* Setup the table.  */
167 static void
168 class_table_setup (void)
169 {
170   /* Start - nothing in the table.  */
171   memset (class_table_array, 0, sizeof (class_node_ptr) * CLASS_TABLE_SIZE);
172
173   /* The table writing mutex.  */
174   __class_table_lock = objc_mutex_allocate ();
175 }
176
177
178 /* Insert a class in the table (used when a new class is
179    registered).  */
180 static void 
181 class_table_insert (const char *class_name, Class class_pointer)
182 {
183   int hash, length;
184   class_node_ptr new_node;
185
186   /* Find out the class name's hash and length.  */
187   CLASS_TABLE_HASH (length, hash, class_name);
188   
189   /* Prepare the new node holding the class.  */
190   new_node = objc_malloc (sizeof (struct class_node));
191   new_node->name = class_name;
192   new_node->length = length;
193   new_node->pointer = class_pointer;
194
195   /* Lock the table for modifications.  */
196   objc_mutex_lock (__class_table_lock);
197   
198   /* Insert the new node in the table at the beginning of the table at
199      class_table_array[hash].  */
200   new_node->next = class_table_array[hash];
201   class_table_array[hash] = new_node;
202   
203   objc_mutex_unlock (__class_table_lock);
204 }
205
206 /* Get a class from the table.  This does not need mutex protection.
207    Currently, this function is called each time you call a static
208    method, this is why it must be very fast.  */
209 static inline Class 
210 class_table_get_safe (const char *class_name)
211 {
212   class_node_ptr node;  
213   int length, hash;
214
215   /* Compute length and hash.  */
216   CLASS_TABLE_HASH (length, hash, class_name);
217   
218   node = class_table_array[hash];
219   
220   if (node != NULL)
221     {
222       do
223         {
224           if (node->length == length)
225             {
226               /* Compare the class names.  */
227               int i;
228
229               for (i = 0; i < length; i++)
230                 {
231                   if ((node->name)[i] != class_name[i]) 
232                     break;
233                 }
234               
235               if (i == length)
236                 {
237                   /* They are equal!  */
238                   return node->pointer;
239                 }
240             }
241         }
242       while ((node = node->next) != NULL);
243     }
244
245   return Nil;
246 }
247
248 /* Enumerate over the class table.  */
249 struct class_table_enumerator
250 {
251   int hash;
252   class_node_ptr node;
253 };
254
255
256 static Class
257 class_table_next (struct class_table_enumerator **e)
258 {
259   struct class_table_enumerator *enumerator = *e;
260   class_node_ptr next;
261   
262   if (enumerator == NULL)
263     {
264        *e = objc_malloc (sizeof (struct class_table_enumerator));
265       enumerator = *e;
266       enumerator->hash = 0;
267       enumerator->node = NULL;
268
269       next = class_table_array[enumerator->hash];
270     }
271   else
272     next = enumerator->node->next;
273   
274   if (next != NULL)
275     {
276       enumerator->node = next;
277       return enumerator->node->pointer;
278     }
279   else 
280     {
281       enumerator->hash++;
282      
283       while (enumerator->hash < CLASS_TABLE_SIZE)
284         {
285           next = class_table_array[enumerator->hash];
286           if (next != NULL)
287             {
288               enumerator->node = next;
289               return enumerator->node->pointer;
290             }
291           enumerator->hash++;
292         }
293       
294       /* Ok - table finished - done.  */
295       objc_free (enumerator);
296       return Nil;
297     }
298 }
299
300 #if 0 /* DEBUGGING FUNCTIONS */
301 /* Debugging function - print the class table.  */
302 void
303 class_table_print (void)
304 {
305   int i;
306   
307   for (i = 0; i < CLASS_TABLE_SIZE; i++)
308     {
309       class_node_ptr node;
310       
311       printf ("%d:\n", i);
312       node = class_table_array[i];
313       
314       while (node != NULL)
315         {
316           printf ("\t%s\n", node->name);
317           node = node->next;
318         }
319     }
320 }
321
322 /* Debugging function - print an histogram of number of classes in
323    function of hash key values.  Useful to evaluate the hash function
324    in real cases.  */
325 void
326 class_table_print_histogram (void)
327 {
328   int i, j;
329   int counter = 0;
330   
331   for (i = 0; i < CLASS_TABLE_SIZE; i++)
332     {
333       class_node_ptr node;
334       
335       node = class_table_array[i];
336       
337       while (node != NULL)
338         {
339           counter++;
340           node = node->next;
341         }
342       if (((i + 1) % 50) == 0)
343         {
344           printf ("%4d:", i + 1);
345           for (j = 0; j < counter; j++)
346             printf ("X");
347
348           printf ("\n");
349           counter = 0;
350         }
351     }
352   printf ("%4d:", i + 1);
353   for (j = 0; j < counter; j++)
354     printf ("X");
355
356   printf ("\n");
357 }
358 #endif /* DEBUGGING FUNCTIONS */
359
360 /**
361  ** Objective-C runtime functions
362  **/
363
364 /* From now on, the only access to the class table data structure
365    should be via the class_table_* functions.  */
366
367 /* This is a hook which is called by objc_get_class and
368    objc_lookup_class if the runtime is not able to find the class.
369    This may e.g. try to load in the class using dynamic loading.
370
371    This hook was a public, global variable in the Traditional GNU
372    Objective-C Runtime API (objc/objc-api.h).  The modern GNU
373    Objective-C Runtime API (objc/runtime.h) provides the
374    objc_setGetUnknownClassHandler() function instead.
375 */
376 Class (*_objc_lookup_class) (const char *name) = 0;      /* !T:SAFE */
377
378 /* The handler currently in use.  PS: if both
379    __obj_get_unknown_class_handler and _objc_lookup_class are defined,
380    __objc_get_unknown_class_handler is called first.  */
381 static objc_get_unknown_class_handler
382 __objc_get_unknown_class_handler = NULL;
383
384 objc_get_unknown_class_handler
385 objc_setGetUnknownClassHandler (objc_get_unknown_class_handler 
386                                 new_handler)
387 {
388   objc_get_unknown_class_handler old_handler 
389     = __objc_get_unknown_class_handler;
390   __objc_get_unknown_class_handler = new_handler;
391   return old_handler;
392 }
393
394
395 /* True when class links has been resolved.  */     
396 BOOL __objc_class_links_resolved = NO;                  /* !T:UNUSED */
397
398
399 void
400 __objc_init_class_tables (void)
401 {
402   /* Allocate the class hash table.  */
403   
404   if (__class_table_lock)
405     return;
406   
407   objc_mutex_lock (__objc_runtime_mutex);
408   
409   class_table_setup ();
410
411   objc_mutex_unlock (__objc_runtime_mutex);
412 }  
413
414 /* This function adds a class to the class hash table, and assigns the
415    class a number, unless it's already known.  Return 'YES' if the
416    class was added.  Return 'NO' if the class was already known.  */
417 BOOL
418 __objc_add_class_to_hash (Class class)
419 {
420   Class existing_class;
421
422   objc_mutex_lock (__objc_runtime_mutex);
423
424   /* Make sure the table is there.  */
425   assert (__class_table_lock);
426
427   /* Make sure it's not a meta class.  */
428   assert (CLS_ISCLASS (class));
429
430   /* Check to see if the class is already in the hash table.  */
431   existing_class = class_table_get_safe (class->name);
432
433   if (existing_class)
434     {
435       objc_mutex_unlock (__objc_runtime_mutex);
436       return NO;      
437     }
438   else
439     {
440       /* The class isn't in the hash table.  Add the class and assign
441          a class number.  */
442       static unsigned int class_number = 1;
443       
444       CLS_SETNUMBER (class, class_number);
445       CLS_SETNUMBER (class->class_pointer, class_number);
446
447       ++class_number;
448       class_table_insert (class->name, class);
449
450       objc_mutex_unlock (__objc_runtime_mutex);
451       return YES;
452     }
453 }
454
455 Class
456 objc_getClass (const char *name)
457 {
458   Class class;
459
460   if (name == NULL)
461     return Nil;
462
463   class = class_table_get_safe (name);
464   
465   if (class)
466     return class;
467
468   if (__objc_get_unknown_class_handler)
469     return (*__objc_get_unknown_class_handler) (name);
470
471   if (_objc_lookup_class)
472     return (*_objc_lookup_class) (name);
473
474   return Nil;
475 }
476
477 Class
478 objc_lookUpClass (const char *name)
479 {
480   if (name == NULL)
481     return Nil;
482   else
483     return class_table_get_safe (name);
484 }
485
486 Class
487 objc_getMetaClass (const char *name)
488 {
489   Class class = objc_getClass (name);
490
491   if (class)
492     return class->class_pointer;
493   else
494     return Nil;
495 }
496
497 Class
498 objc_getRequiredClass (const char *name)
499 {
500   Class class = objc_getClass (name);
501
502   if (class)
503     return class;
504   else
505     _objc_abort ("objc_getRequiredClass ('%s') failed: class not found\n", name);
506 }
507
508 int
509 objc_getClassList (Class *returnValue, int maxNumberOfClassesToReturn)
510 {
511   /* Iterate over all entries in the table.  */
512   int hash, count = 0;
513
514   for (hash = 0; hash < CLASS_TABLE_SIZE; hash++)
515     {
516       class_node_ptr node = class_table_array[hash];
517       
518       while (node != NULL)
519         {
520           if (returnValue)
521             {
522               if (count < maxNumberOfClassesToReturn)
523                 returnValue[count] = node->pointer;
524               else
525                 return count;
526             }
527           count++;
528           node = node->next;
529         }
530     }
531   
532   return count;
533 }
534
535 Class
536 objc_allocateClassPair (Class super_class, const char *class_name, size_t extraBytes)
537 {
538   Class new_class;
539   Class new_meta_class;
540
541   if (class_name == NULL)
542     return Nil;
543
544   if (objc_getClass (class_name))
545     return Nil;
546
547   if (super_class)
548     {
549       /* If you want to build a hierarchy of classes, you need to
550          build and register them one at a time.  The risk is that you
551          are able to cause confusion by registering a subclass before
552          the superclass or similar.  */
553       if (CLS_IS_IN_CONSTRUCTION (super_class))
554         return Nil;
555     }
556
557   /* Technically, we should create the metaclass first, then use
558      class_createInstance() to create the class.  That complication
559      would be relevant if we had class variables, but we don't, so we
560      just ignore it and create everything directly and assume all
561      classes have the same size.  */
562   new_class = objc_calloc (1, sizeof (struct objc_class) + extraBytes);
563   new_meta_class = objc_calloc (1, sizeof (struct objc_class) + extraBytes);
564
565   /* We create an unresolved class, similar to one generated by the
566      compiler.  It will be resolved later when we register it.
567
568      Note how the metaclass details are not that important; when the
569      class is resolved, the ones that matter will be fixed up.  */
570   new_class->class_pointer = new_meta_class;
571   new_meta_class->class_pointer = 0;
572
573   if (super_class)
574     {
575       /* Force the name of the superclass in place of the link to the
576          actual superclass, which will be put there when the class is
577          resolved.  */
578       const char *super_class_name = class_getName (super_class);
579       new_class->super_class = (void *)super_class_name;
580       new_meta_class->super_class = (void *)super_class_name;
581     }
582   else
583     {
584       new_class->super_class = (void *)0;
585       new_meta_class->super_class = (void *)0;
586     }
587
588   new_class->name = objc_malloc (strlen (class_name) + 1);
589   strcpy ((char*)new_class->name, class_name);
590   new_meta_class->name = new_class->name;
591
592   new_class->version = 0;
593   new_meta_class->version = 0;
594
595   new_class->info = _CLS_CLASS | _CLS_IN_CONSTRUCTION;
596   new_meta_class->info = _CLS_META | _CLS_IN_CONSTRUCTION;
597
598   if (super_class)
599     new_class->instance_size = super_class->instance_size;
600   else
601     new_class->instance_size = 0;
602   new_meta_class->instance_size = sizeof (struct objc_class);
603
604   return new_class;
605 }
606
607 void
608 objc_registerClassPair (Class class_)
609 {
610   if (class_ == Nil)
611     return;
612
613   if ((! CLS_ISCLASS (class_)) || (! CLS_IS_IN_CONSTRUCTION (class_)))
614     return;
615
616   if ((! CLS_ISMETA (class_->class_pointer)) || (! CLS_IS_IN_CONSTRUCTION (class_->class_pointer)))
617     return;
618
619   objc_mutex_lock (__objc_runtime_mutex);
620
621   if (objc_getClass (class_->name))
622     {
623       objc_mutex_unlock (__objc_runtime_mutex);
624       return;
625     }
626
627   CLS_SET_NOT_IN_CONSTRUCTION (class_);
628   CLS_SET_NOT_IN_CONSTRUCTION (class_->class_pointer);
629
630   __objc_init_class (class_);
631
632   /* Resolve class links immediately.  No point in waiting.  */
633   __objc_resolve_class_links ();
634
635   objc_mutex_unlock (__objc_runtime_mutex);
636 }
637
638 void
639 objc_disposeClassPair (Class class_)
640 {
641   if (class_ == Nil)
642     return;
643
644   if ((! CLS_ISCLASS (class_)) || (! CLS_IS_IN_CONSTRUCTION (class_)))
645     return;
646
647   if ((! CLS_ISMETA (class_->class_pointer)) || (! CLS_IS_IN_CONSTRUCTION (class_->class_pointer)))
648     return;
649
650   /* Undo any class_addIvar().  */
651   if (class_->ivars)
652     {
653       int i;
654       for (i = 0; i < class_->ivars->ivar_count; i++)
655         {
656           struct objc_ivar *ivar = &(class_->ivars->ivar_list[i]);
657
658           objc_free ((char *)ivar->ivar_name);
659           objc_free ((char *)ivar->ivar_type);
660         }
661       
662       objc_free (class_->ivars);
663     }
664
665   /* Undo any class_addMethod().  */
666   if (class_->methods)
667     {
668       struct objc_method_list *list = class_->methods;
669       while (list)
670         {
671           int i;
672           struct objc_method_list *next = list->method_next;
673
674           for (i = 0; i < list->method_count; i++)
675             {
676               struct objc_method *method = &(list->method_list[i]);
677
678               objc_free ((char *)method->method_name);
679               objc_free ((char *)method->method_types);
680             }
681
682           objc_free (list);
683           list = next;
684         }
685     }
686
687   /* Undo any class_addProtocol().  */
688   if (class_->protocols)
689     {
690       struct objc_protocol_list *list = class_->protocols;
691       while (list)
692         {
693           struct objc_protocol_list *next = list->next;
694
695           objc_free (list);
696           list = next;
697         }
698     }
699   
700   /* Undo any class_addMethod() on the meta-class.  */
701   if (class_->class_pointer->methods)
702     {
703       struct objc_method_list *list = class_->class_pointer->methods;
704       while (list)
705         {
706           int i;
707           struct objc_method_list *next = list->method_next;
708
709           for (i = 0; i < list->method_count; i++)
710             {
711               struct objc_method *method = &(list->method_list[i]);
712
713               objc_free ((char *)method->method_name);
714               objc_free ((char *)method->method_types);
715             }
716
717           objc_free (list);
718           list = next;
719         }
720     }
721
722   /* Undo objc_allocateClassPair().  */
723   objc_free ((char *)(class_->name));
724   objc_free (class_->class_pointer);
725   objc_free (class_);
726 }
727
728 /* Traditional GNU Objective-C Runtime API.  Important: this method is
729    called automatically by the compiler while messaging (if using the
730    traditional ABI), so it is worth keeping it fast; don't make it
731    just a wrapper around objc_getClass().  */
732 /* Note that this is roughly equivalent to objc_getRequiredClass().  */
733 /* Get the class object for the class named NAME.  If NAME does not
734    identify a known class, the hook _objc_lookup_class is called.  If
735    this fails, an error message is issued and the system aborts.  */
736 Class
737 objc_get_class (const char *name)
738 {
739   Class class;
740
741   class = class_table_get_safe (name);
742
743   if (class)
744     return class;
745
746   if (__objc_get_unknown_class_handler)
747     class = (*__objc_get_unknown_class_handler) (name);
748
749   if ((!class)  &&  _objc_lookup_class)
750     class = (*_objc_lookup_class) (name);
751
752   if (class)
753     return class;
754   
755   _objc_abort ("objc runtime: cannot find class %s\n", name);
756
757   return 0;
758 }
759
760 /* This is used by the compiler too.  */
761 Class
762 objc_get_meta_class (const char *name)
763 {
764   return objc_get_class (name)->class_pointer;
765 }
766
767 /* This is used when the implementation of a method changes.  It goes
768    through all classes, looking for the ones that have these methods
769    (either method_a or method_b; method_b can be NULL), and reloads
770    the implementation for these.  You should call this with the
771    runtime mutex already locked.  */
772 void
773 __objc_update_classes_with_methods (struct objc_method *method_a, struct objc_method *method_b)
774 {
775   int hash;
776
777   /* Iterate over all classes.  */
778   for (hash = 0; hash < CLASS_TABLE_SIZE; hash++)
779     {
780       class_node_ptr node = class_table_array[hash];
781       
782       while (node != NULL)
783         {
784           /* We execute this loop twice: the first time, we iterate
785              over all methods in the class (instance methods), while
786              the second time we iterate over all methods in the meta
787              class (class methods).  */
788           Class class = Nil;
789           BOOL done = NO;
790
791           while (done == NO)
792             {
793               struct objc_method_list * method_list;
794
795               if (class == Nil)
796                 {
797                   /* The first time, we work on the class.  */
798                   class = node->pointer;
799                 }
800               else
801                 {
802                   /* The second time, we work on the meta class.  */
803                   class = class->class_pointer;
804                   done = YES;
805                 }
806
807               method_list = class->methods;
808
809               while (method_list)
810                 {
811                   int i;
812                   
813                   for (i = 0; i < method_list->method_count; ++i)
814                     {
815                       struct objc_method *method = &method_list->method_list[i];
816                       
817                       /* If the method is one of the ones we are
818                          looking for, update the implementation.  */
819                       if (method == method_a)
820                         sarray_at_put_safe (class->dtable,
821                                             (sidx) method_a->method_name->sel_id,
822                                             method_a->method_imp);
823                       
824                       if (method == method_b)
825                         {
826                           if (method_b != NULL)
827                             sarray_at_put_safe (class->dtable,
828                                                 (sidx) method_b->method_name->sel_id,
829                                                 method_b->method_imp);
830                         }
831                     }
832                   
833                   method_list = method_list->method_next;
834                 }
835             }
836           node = node->next;
837         }
838     }
839 }
840
841 /* Resolve super/subclass links for all classes.  The only thing we
842    can be sure of is that the class_pointer for class objects point to
843    the right meta class objects.  */
844 void
845 __objc_resolve_class_links (void)
846 {
847   struct class_table_enumerator *es = NULL;
848   Class object_class = objc_get_class ("Object");
849   Class class1;
850
851   assert (object_class);
852
853   objc_mutex_lock (__objc_runtime_mutex);
854
855   /* Assign subclass links.  */
856   while ((class1 = class_table_next (&es)))
857     {
858       /* Make sure we have what we think we have.  */
859       assert (CLS_ISCLASS (class1));
860       assert (CLS_ISMETA (class1->class_pointer));
861
862       /* The class_pointer of all meta classes point to Object's meta
863          class.  */
864       class1->class_pointer->class_pointer = object_class->class_pointer;
865
866       if (! CLS_ISRESOLV (class1))
867         {
868           CLS_SETRESOLV (class1);
869           CLS_SETRESOLV (class1->class_pointer);
870               
871           if (class1->super_class)
872             {   
873               Class a_super_class 
874                 = objc_get_class ((char *) class1->super_class);
875               
876               assert (a_super_class);
877               
878               DEBUG_PRINTF ("making class connections for: %s\n",
879                             class1->name);
880               
881               /* Assign subclass links for superclass.  */
882               class1->sibling_class = a_super_class->subclass_list;
883               a_super_class->subclass_list = class1;
884               
885               /* Assign subclass links for meta class of superclass.  */
886               if (a_super_class->class_pointer)
887                 {
888                   class1->class_pointer->sibling_class
889                     = a_super_class->class_pointer->subclass_list;
890                   a_super_class->class_pointer->subclass_list 
891                     = class1->class_pointer;
892                 }
893             }
894           else /* A root class, make its meta object be a subclass of
895                   Object.  */
896             {
897               class1->class_pointer->sibling_class 
898                 = object_class->subclass_list;
899               object_class->subclass_list = class1->class_pointer;
900             }
901         }
902     }
903
904   /* Assign superclass links.  */
905    es = NULL;
906    while ((class1 = class_table_next (&es)))
907     {
908       Class sub_class;
909       for (sub_class = class1->subclass_list; sub_class;
910            sub_class = sub_class->sibling_class)
911         {
912           sub_class->super_class = class1;
913           if (CLS_ISCLASS (sub_class))
914             sub_class->class_pointer->super_class = class1->class_pointer;
915         }
916     }
917
918   objc_mutex_unlock (__objc_runtime_mutex);
919 }
920
921 const char *
922 class_getName (Class class_)
923 {
924   if (class_ == Nil)
925     return "nil";
926
927   return class_->name;
928 }
929
930 BOOL
931 class_isMetaClass (Class class_)
932 {
933   /* CLS_ISMETA includes the check for Nil class_.  */
934   return CLS_ISMETA (class_);
935 }
936
937 /* Even inside libobjc it may be worth using class_getSuperclass
938    instead of accessing class_->super_class directly because it
939    resolves the class links if needed.  If you access
940    class_->super_class directly, make sure to deal with the situation
941    where the class is not resolved yet!  */
942 Class
943 class_getSuperclass (Class class_)
944 {
945   if (class_ == Nil)
946     return Nil;
947
948   /* Classes that are in construction are not resolved, and still have
949      the class name (instead of a class pointer) in the
950      class_->super_class field.  In that case we need to lookup the
951      superclass name to return the superclass.  We can not resolve the
952      class until it is registered.  */
953   if (CLS_IS_IN_CONSTRUCTION (class_))
954     {
955       if (CLS_ISMETA (class_))
956         return object_getClass ((id)objc_lookUpClass ((const char *)(class_->super_class)));
957       else
958         return objc_lookUpClass ((const char *)(class_->super_class));
959     }
960
961   /* If the class is not resolved yet, super_class would point to a
962      string (the name of the super class) as opposed to the actual
963      super class.  In that case, we need to resolve the class links
964      before we can return super_class.  */
965   if (! CLS_ISRESOLV (class_))
966     __objc_resolve_class_links ();
967   
968   return class_->super_class;
969 }
970
971 int
972 class_getVersion (Class class_)
973 {
974   if (class_ == Nil)
975     return 0;
976
977   return (int)(class_->version);
978 }
979
980 void
981 class_setVersion (Class class_, int version)
982 {
983   if (class_ == Nil)
984     return;
985
986   class_->version = version;
987 }
988
989 size_t
990 class_getInstanceSize (Class class_)
991 {
992   if (class_ == Nil)
993     return 0;
994
995   return class_->instance_size;
996 }
997