xref: /dragonfly/contrib/gcc-4.7/libobjc/sendmsg.c (revision 71990c18)
1 /* GNU Objective C Runtime message lookup
2    Copyright (C) 1993, 1995, 1996, 1997, 1998,
3    2001, 2002, 2004, 2009, 2010 Free Software Foundation, Inc.
4    Contributed by Kresten Krab Thorup
5 
6 This file is part of GCC.
7 
8 GCC is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 3, or (at your option) any later version.
11 
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15 details.
16 
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
20 
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 <http://www.gnu.org/licenses/>.  */
25 
26 /* Uncommented the following line to enable debug logging.  Use this
27    only while debugging the runtime.  */
28 /* #define DEBUG 1 */
29 
30 /* FIXME: This file has no business including tm.h.  */
31 /* FIXME: This should be using libffi instead of __builtin_apply
32    and friends.  */
33 
34 #include "objc-private/common.h"
35 #include "objc-private/error.h"
36 #include "tconfig.h"
37 #include "coretypes.h"
38 #include "tm.h"
39 #include "objc/runtime.h"
40 #include "objc/message.h"          /* For objc_msg_lookup(), objc_msg_lookup_super().  */
41 #include "objc/thr.h"
42 #include "objc-private/module-abi-8.h"
43 #include "objc-private/runtime.h"
44 #include "objc-private/hash.h"
45 #include "objc-private/sarray.h"
46 #include "objc-private/selector.h" /* For sel_is_mapped() */
47 #include "runtime-info.h"
48 #include <assert.h> /* For assert */
49 #include <string.h> /* For strlen */
50 
51 /* This is how we hack STRUCT_VALUE to be 1 or 0.   */
52 #define gen_rtx(args...) 1
53 #define gen_rtx_MEM(args...) 1
54 #define gen_rtx_REG(args...) 1
55 /* Already defined in gcc/coretypes.h. So prevent double definition warning.  */
56 #undef rtx
57 #define rtx int
58 
59 #if ! defined (STRUCT_VALUE) || STRUCT_VALUE == 0
60 #define INVISIBLE_STRUCT_RETURN 1
61 #else
62 #define INVISIBLE_STRUCT_RETURN 0
63 #endif
64 
65 /* The uninstalled dispatch table.  If a class' dispatch table points
66    to __objc_uninstalled_dtable then that means it needs its dispatch
67    table to be installed.  */
68 struct sarray *__objc_uninstalled_dtable = 0;   /* !T:MUTEX */
69 
70 /* Two hooks for method forwarding. If either is set, it is invoked to
71  * return a function that performs the real forwarding.  If both are
72  * set, the result of __objc_msg_forward2 will be preferred over that
73  * of __objc_msg_forward.  If both return NULL or are unset, the
74  * libgcc based functions (__builtin_apply and friends) are used.  */
75 IMP (*__objc_msg_forward) (SEL) = NULL;
76 IMP (*__objc_msg_forward2) (id, SEL) = NULL;
77 
78 /* Send +initialize to class.  */
79 static void __objc_send_initialize (Class);
80 
81 /* Forward declare some functions */
82 static void __objc_install_dtable_for_class (Class cls);
83 static void __objc_prepare_dtable_for_class (Class cls);
84 static void __objc_install_prepared_dtable_for_class (Class cls);
85 
86 static struct sarray *__objc_prepared_dtable_for_class (Class cls);
87 static IMP __objc_get_prepared_imp (Class cls,SEL sel);
88 
89 
90 /* Various forwarding functions that are used based upon the
91    return type for the selector.
92    __objc_block_forward for structures.
93    __objc_double_forward for floats/doubles.
94    __objc_word_forward for pointers or types that fit in registers.  */
95 static double __objc_double_forward (id, SEL, ...);
96 static id __objc_word_forward (id, SEL, ...);
97 typedef struct { id many[8]; } __big;
98 #if INVISIBLE_STRUCT_RETURN
99 static __big
100 #else
101 static id
102 #endif
103 __objc_block_forward (id, SEL, ...);
104 static struct objc_method * search_for_method_in_hierarchy (Class class, SEL sel);
105 struct objc_method * search_for_method_in_list (struct objc_method_list * list, SEL op);
106 id nil_method (id, SEL);
107 
108 /* Make sure this inline function is exported regardless of GNU89 or C99
109    inlining semantics as it is part of the libobjc ABI.  */
110 extern IMP __objc_get_forward_imp (id, SEL);
111 
112 /* Given a selector, return the proper forwarding implementation.  */
113 inline
114 IMP
115 __objc_get_forward_imp (id rcv, SEL sel)
116 {
117   /* If a custom forwarding hook was registered, try getting a
118      forwarding function from it. There are two forward routine hooks,
119      one that takes the receiver as an argument and one that does
120      not.  */
121   if (__objc_msg_forward2)
122     {
123       IMP result;
124       if ((result = __objc_msg_forward2 (rcv, sel)) != NULL)
125        return result;
126     }
127   if (__objc_msg_forward)
128     {
129       IMP result;
130       if ((result = __objc_msg_forward (sel)) != NULL)
131 	return result;
132     }
133 
134   /* In all other cases, use the default forwarding functions built
135      using __builtin_apply and friends.  */
136     {
137       const char *t = sel->sel_types;
138 
139       if (t && (*t == '[' || *t == '(' || *t == '{')
140 #ifdef OBJC_MAX_STRUCT_BY_VALUE
141           && objc_sizeof_type (t) > OBJC_MAX_STRUCT_BY_VALUE
142 #endif
143           )
144         return (IMP)__objc_block_forward;
145       else if (t && (*t == 'f' || *t == 'd'))
146         return (IMP)__objc_double_forward;
147       else
148         return (IMP)__objc_word_forward;
149     }
150 }
151 
152 /* Selectors for +resolveClassMethod: and +resolveInstanceMethod:.
153    These are set up at startup.  */
154 static SEL selector_resolveClassMethod = NULL;
155 static SEL selector_resolveInstanceMethod = NULL;
156 
157 /* Internal routines use to resolve a class method using
158    +resolveClassMethod:.  'class' is always a non-Nil class (*not* a
159    meta-class), and 'sel' is the selector that we are trying to
160    resolve.  This must be called when class is not Nil, and the
161    dispatch table for class methods has already been installed.
162 
163    This routine tries to call +resolveClassMethod: to give an
164    opportunity to resolve the method.  If +resolveClassMethod: returns
165    YES, it tries looking up the method again, and if found, it returns
166    it.  Else, it returns NULL.  */
167 static inline
168 IMP
169 __objc_resolve_class_method (Class class, SEL sel)
170 {
171   /* We need to lookup +resolveClassMethod:.  */
172   BOOL (*resolveMethodIMP) (id, SEL, SEL);
173 
174   /* The dispatch table for class methods is already installed and we
175      don't want any forwarding to happen when looking up this method,
176      so we just look it up directly.  Note that if 'sel' is precisely
177      +resolveClassMethod:, this would look it up yet again and find
178      nothing.  That's no problem and there's no recursion.  */
179   resolveMethodIMP = (BOOL (*) (id, SEL, SEL))sarray_get_safe
180     (class->class_pointer->dtable, (size_t) selector_resolveClassMethod->sel_id);
181 
182   if (resolveMethodIMP && resolveMethodIMP ((id)class, selector_resolveClassMethod, sel))
183     {
184       /* +resolveClassMethod: returned YES.  Look the method up again.
185 	 We already know the dtable is installed.  */
186 
187       /* TODO: There is the case where +resolveClassMethod: is buggy
188 	 and returned YES without actually adding the method.  We
189 	 could maybe print an error message.  */
190       return sarray_get_safe (class->class_pointer->dtable, (size_t) sel->sel_id);
191     }
192 
193   return NULL;
194 }
195 
196 /* Internal routines use to resolve a instance method using
197    +resolveInstanceMethod:.  'class' is always a non-Nil class, and
198    'sel' is the selector that we are trying to resolve.  This must be
199    called when class is not Nil, and the dispatch table for instance
200    methods has already been installed.
201 
202    This routine tries to call +resolveInstanceMethod: to give an
203    opportunity to resolve the method.  If +resolveInstanceMethod:
204    returns YES, it tries looking up the method again, and if found, it
205    returns it.  Else, it returns NULL.  */
206 static inline
207 IMP
208 __objc_resolve_instance_method (Class class, SEL sel)
209 {
210   /* We need to lookup +resolveInstanceMethod:.  */
211   BOOL (*resolveMethodIMP) (id, SEL, SEL);
212 
213   /* The dispatch table for class methods may not be already installed
214      so we have to install it if needed.  */
215   resolveMethodIMP = sarray_get_safe (class->class_pointer->dtable,
216 				      (size_t) selector_resolveInstanceMethod->sel_id);
217   if (resolveMethodIMP == 0)
218     {
219       /* Try again after installing the dtable.  */
220       if (class->class_pointer->dtable == __objc_uninstalled_dtable)
221 	{
222 	  objc_mutex_lock (__objc_runtime_mutex);
223 	  if (class->class_pointer->dtable == __objc_uninstalled_dtable)
224 	    __objc_install_dtable_for_class (class->class_pointer);
225 	  objc_mutex_unlock (__objc_runtime_mutex);
226 	}
227       resolveMethodIMP = sarray_get_safe (class->class_pointer->dtable,
228 					  (size_t) selector_resolveInstanceMethod->sel_id);
229     }
230 
231   if (resolveMethodIMP && resolveMethodIMP ((id)class, selector_resolveInstanceMethod, sel))
232     {
233       /* +resolveInstanceMethod: returned YES.  Look the method up
234 	 again.  We already know the dtable is installed.  */
235 
236       /* TODO: There is the case where +resolveInstanceMethod: is
237 	 buggy and returned YES without actually adding the method.
238 	 We could maybe print an error message.  */
239       return sarray_get_safe (class->dtable, (size_t) sel->sel_id);
240     }
241 
242   return NULL;
243 }
244 
245 /* Given a CLASS and selector, return the implementation corresponding
246    to the method of the selector.
247 
248    If CLASS is a class, the instance method is returned.
249    If CLASS is a meta class, the class method is returned.
250 
251    Since this requires the dispatch table to be installed, this function
252    will implicitly invoke +initialize for CLASS if it hasn't been
253    invoked yet.  This also insures that +initialize has been invoked
254    when the returned implementation is called directly.
255 
256    The forwarding hooks require the receiver as an argument (if they are to
257    perform dynamic lookup in proxy objects etc), so this function has a
258    receiver argument to be used with those hooks.  */
259 static inline
260 IMP
261 get_implementation (id receiver, Class class, SEL sel)
262 {
263   void *res;
264 
265   if (class->dtable == __objc_uninstalled_dtable)
266     {
267       /* The dispatch table needs to be installed.  */
268       objc_mutex_lock (__objc_runtime_mutex);
269 
270       /* Double-checked locking pattern: Check
271 	 __objc_uninstalled_dtable again in case another thread
272 	 installed the dtable while we were waiting for the lock to be
273 	 released.  */
274       if (class->dtable == __objc_uninstalled_dtable)
275 	__objc_install_dtable_for_class (class);
276 
277       /* If the dispatch table is not yet installed, we are still in
278 	 the process of executing +initialize.  But the implementation
279 	 pointer should be available in the prepared ispatch table if
280 	 it exists at all.  */
281       if (class->dtable == __objc_uninstalled_dtable)
282 	{
283 	  assert (__objc_prepared_dtable_for_class (class) != 0);
284 	  res = __objc_get_prepared_imp (class, sel);
285 	}
286       else
287 	res = 0;
288 
289       objc_mutex_unlock (__objc_runtime_mutex);
290       /* Call ourselves with the installed dispatch table and get the
291 	 real method.  */
292       if (!res)
293 	res = get_implementation (receiver, class, sel);
294     }
295   else
296     {
297       /* The dispatch table has been installed.  */
298       res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
299       if (res == 0)
300 	{
301 	  /* The dispatch table has been installed, and the method is
302 	     not in the dispatch table.  So the method just doesn't
303 	     exist for the class.  */
304 
305 	  /* Try going through the +resolveClassMethod: or
306 	     +resolveInstanceMethod: process.  */
307 	  if (CLS_ISMETA (class))
308 	    {
309 	      /* We have the meta class, but we need to invoke the
310 		 +resolveClassMethod: method on the class.  So, we
311 		 need to obtain the class from the meta class, which
312 		 we do using the fact that both the class and the
313 		 meta-class have the same name.  */
314 	      Class realClass = objc_lookUpClass (class->name);
315 	      if (realClass)
316 		res = __objc_resolve_class_method (realClass, sel);
317 	    }
318 	  else
319 	    res = __objc_resolve_instance_method (class, sel);
320 
321 	  if (res == 0)
322 	    res = __objc_get_forward_imp (receiver, sel);
323 	}
324     }
325   return res;
326 }
327 
328 /* Make sure this inline function is exported regardless of GNU89 or C99
329    inlining semantics as it is part of the libobjc ABI.  */
330 extern IMP get_imp (Class, SEL);
331 
332 inline
333 IMP
334 get_imp (Class class, SEL sel)
335 {
336   /* In a vanilla implementation we would first check if the dispatch
337      table is installed.  Here instead, to get more speed in the
338      standard case (that the dispatch table is installed) we first try
339      to get the imp using brute force.  Only if that fails, we do what
340      we should have been doing from the very beginning, that is, check
341      if the dispatch table needs to be installed, install it if it's
342      not installed, and retrieve the imp from the table if it's
343      installed.  */
344   void *res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
345   if (res == 0)
346     {
347       res = get_implementation(nil, class, sel);
348     }
349   return res;
350 }
351 
352 /* The new name of get_imp().  */
353 IMP
354 class_getMethodImplementation (Class class_, SEL selector)
355 {
356   if (class_ == Nil  ||  selector == NULL)
357     return NULL;
358 
359   /* get_imp is inlined, so we're good.  */
360   return get_imp (class_, selector);
361 }
362 
363 /* Given a method, return its implementation.  This has been replaced
364    by method_getImplementation() in the modern API.  */
365 IMP
366 method_get_imp (struct objc_method * method)
367 {
368   return (method != (struct objc_method *)0) ? method->method_imp : (IMP)0;
369 }
370 
371 /* Query if an object can respond to a selector, returns YES if the
372    object implements the selector otherwise NO.  Does not check if the
373    method can be forwarded.  Since this requires the dispatch table to
374    installed, this function will implicitly invoke +initialize for the
375    class of OBJECT if it hasn't been invoked yet.  */
376 inline
377 BOOL
378 __objc_responds_to (id object, SEL sel)
379 {
380   void *res;
381   struct sarray *dtable;
382 
383   /* Install dispatch table if need be */
384   dtable = object->class_pointer->dtable;
385   if (dtable == __objc_uninstalled_dtable)
386     {
387       objc_mutex_lock (__objc_runtime_mutex);
388       if (object->class_pointer->dtable == __objc_uninstalled_dtable)
389         __objc_install_dtable_for_class (object->class_pointer);
390 
391       /* If the dispatch table is not yet installed, we are still in
392          the process of executing +initialize.  Yet the dispatch table
393          should be available.  */
394       if (object->class_pointer->dtable == __objc_uninstalled_dtable)
395         {
396           dtable = __objc_prepared_dtable_for_class (object->class_pointer);
397           assert (dtable);
398         }
399       else
400         dtable = object->class_pointer->dtable;
401 
402       objc_mutex_unlock (__objc_runtime_mutex);
403     }
404 
405   /* Get the method from the dispatch table.  */
406   res = sarray_get_safe (dtable, (size_t) sel->sel_id);
407   return (res != 0) ? YES : NO;
408 }
409 
410 BOOL
411 class_respondsToSelector (Class class_, SEL selector)
412 {
413   struct sarray *dtable;
414   void *res;
415 
416   if (class_ == Nil  ||  selector == NULL)
417     return NO;
418 
419   /* Install dispatch table if need be.  */
420   dtable = class_->dtable;
421   if (dtable == __objc_uninstalled_dtable)
422     {
423       objc_mutex_lock (__objc_runtime_mutex);
424       if (class_->dtable == __objc_uninstalled_dtable)
425 	__objc_install_dtable_for_class (class_);
426 
427       /* If the dispatch table is not yet installed,
428          we are still in the process of executing +initialize.
429          Yet the dispatch table should be available.  */
430       if (class_->dtable == __objc_uninstalled_dtable)
431         {
432           dtable = __objc_prepared_dtable_for_class (class_);
433           assert (dtable);
434         }
435       else
436         dtable = class_->dtable;
437 
438       objc_mutex_unlock (__objc_runtime_mutex);
439     }
440 
441   /* Get the method from the dispatch table.  */
442   res = sarray_get_safe (dtable, (size_t) selector->sel_id);
443   return (res != 0) ? YES : NO;
444 }
445 
446 /* This is the lookup function.  All entries in the table are either a
447    valid method *or* zero.  If zero then either the dispatch table
448    needs to be installed or it doesn't exist and forwarding is
449    attempted.  */
450 IMP
451 objc_msg_lookup (id receiver, SEL op)
452 {
453   IMP result;
454   if (receiver)
455     {
456       /* First try a quick lookup assuming the dispatch table exists.  */
457       result = sarray_get_safe (receiver->class_pointer->dtable,
458 				(sidx)op->sel_id);
459       if (result == 0)
460 	{
461 	  /* Not found ... call get_implementation () to install the
462              dispatch table and call +initialize as required,
463              providing the method implementation or a forwarding
464              function.  */
465 	  result = get_implementation (receiver, receiver->class_pointer, op);
466 	}
467       return result;
468     }
469   else
470     return (IMP)nil_method;
471 }
472 
473 IMP
474 objc_msg_lookup_super (struct objc_super *super, SEL sel)
475 {
476   if (super->self)
477     return get_imp (super->super_class, sel);
478   else
479     return (IMP)nil_method;
480 }
481 
482 void
483 __objc_init_dispatch_tables ()
484 {
485   __objc_uninstalled_dtable = sarray_new (200, 0);
486 
487   /* TODO: It would be cool to register typed selectors here.  */
488   selector_resolveClassMethod = sel_registerName ("resolveClassMethod:");
489   selector_resolveInstanceMethod = sel_registerName ("resolveInstanceMethod:");
490 }
491 
492 
493 /* Install dummy table for class which causes the first message to
494    that class (or instances hereof) to be initialized properly.  */
495 void
496 __objc_install_premature_dtable (Class class)
497 {
498   assert (__objc_uninstalled_dtable);
499   class->dtable = __objc_uninstalled_dtable;
500 }
501 
502 /* Send +initialize to class if not already done.  */
503 static void
504 __objc_send_initialize (Class class)
505 {
506   /* This *must* be a class object.  */
507   assert (CLS_ISCLASS (class));
508   assert (! CLS_ISMETA (class));
509 
510   /* class_add_method_list/__objc_update_dispatch_table_for_class may
511      have reset the dispatch table.  The canonical way to insure that
512      we send +initialize just once, is this flag.  */
513   if (! CLS_ISINITIALIZED (class))
514     {
515       DEBUG_PRINTF ("+initialize: need to initialize class '%s'\n", class->name);
516       CLS_SETINITIALIZED (class);
517       CLS_SETINITIALIZED (class->class_pointer);
518 
519       /* Create the garbage collector type memory description.  */
520       __objc_generate_gc_type_description (class);
521 
522       if (class->super_class)
523 	__objc_send_initialize (class->super_class);
524 
525       {
526 	SEL op = sel_registerName ("initialize");
527         struct objc_method *method = search_for_method_in_hierarchy (class->class_pointer,
528 								     op);
529 
530 	if (method)
531 	  {
532 	    DEBUG_PRINTF (" begin of [%s +initialize]\n", class->name);
533 	    (*method->method_imp) ((id)class, op);
534 	    DEBUG_PRINTF (" end of [%s +initialize]\n", class->name);
535 	  }
536 #ifdef DEBUG
537 	else
538 	  {
539 	    DEBUG_PRINTF (" class '%s' has no +initialize method\n", class->name);
540 	  }
541 #endif
542       }
543     }
544 }
545 
546 /* Walk on the methods list of class and install the methods in the
547    reverse order of the lists.  Since methods added by categories are
548    before the methods of class in the methods list, this allows
549    categories to substitute methods declared in class.  However if
550    more than one category replaces the same method nothing is
551    guaranteed about what method will be used.  Assumes that
552    __objc_runtime_mutex is locked down.  */
553 static void
554 __objc_install_methods_in_dtable (struct sarray *dtable, struct objc_method_list * method_list)
555 {
556   int i;
557 
558   if (! method_list)
559     return;
560 
561   if (method_list->method_next)
562     __objc_install_methods_in_dtable (dtable, method_list->method_next);
563 
564   for (i = 0; i < method_list->method_count; i++)
565     {
566       struct objc_method * method = &(method_list->method_list[i]);
567       sarray_at_put_safe (dtable,
568 			  (sidx) method->method_name->sel_id,
569 			  method->method_imp);
570     }
571 }
572 
573 void
574 __objc_update_dispatch_table_for_class (Class class)
575 {
576   Class next;
577   struct sarray *arr;
578 
579   DEBUG_PRINTF (" _objc_update_dtable_for_class (%s)\n", class->name);
580 
581   objc_mutex_lock (__objc_runtime_mutex);
582 
583   /* Not yet installed -- skip it unless in +initialize.  */
584   if (class->dtable == __objc_uninstalled_dtable)
585     {
586       if (__objc_prepared_dtable_for_class (class))
587 	{
588 	  /* There is a prepared table so we must be initialising this
589 	     class ... we must re-do the table preparation.  */
590 	  __objc_prepare_dtable_for_class (class);
591 	}
592       objc_mutex_unlock (__objc_runtime_mutex);
593       return;
594     }
595 
596   arr = class->dtable;
597   __objc_install_premature_dtable (class); /* someone might require it... */
598   sarray_free (arr);			   /* release memory */
599 
600   /* Could have been lazy...  */
601   __objc_install_dtable_for_class (class);
602 
603   if (class->subclass_list)	/* Traverse subclasses.  */
604     for (next = class->subclass_list; next; next = next->sibling_class)
605       __objc_update_dispatch_table_for_class (next);
606 
607   objc_mutex_unlock (__objc_runtime_mutex);
608 }
609 
610 /* This function adds a method list to a class.  This function is
611    typically called by another function specific to the run-time.  As
612    such this function does not worry about thread safe issues.
613 
614    This one is only called for categories. Class objects have their
615    methods installed right away, and their selectors are made into
616    SEL's by the function __objc_register_selectors_from_class.  */
617 void
618 class_add_method_list (Class class, struct objc_method_list * list)
619 {
620   /* Passing of a linked list is not allowed.  Do multiple calls.  */
621   assert (! list->method_next);
622 
623   __objc_register_selectors_from_list(list);
624 
625   /* Add the methods to the class's method list.  */
626   list->method_next = class->methods;
627   class->methods = list;
628 
629   /* Update the dispatch table of class.  */
630   __objc_update_dispatch_table_for_class (class);
631 }
632 
633 struct objc_method *
634 class_getInstanceMethod (Class class_, SEL selector)
635 {
636   struct objc_method *m;
637 
638   if (class_ == Nil  ||  selector == NULL)
639     return NULL;
640 
641   m = search_for_method_in_hierarchy (class_, selector);
642   if (m)
643     return m;
644 
645   /* Try going through +resolveInstanceMethod:, and do the search
646      again if successful.  */
647   if (__objc_resolve_instance_method (class_, selector))
648     return search_for_method_in_hierarchy (class_, selector);
649 
650   return NULL;
651 }
652 
653 struct objc_method *
654 class_getClassMethod (Class class_, SEL selector)
655 {
656   struct objc_method *m;
657 
658   if (class_ == Nil  ||  selector == NULL)
659     return NULL;
660 
661   m = search_for_method_in_hierarchy (class_->class_pointer,
662 				      selector);
663   if (m)
664     return m;
665 
666   /* Try going through +resolveClassMethod:, and do the search again
667      if successful.  */
668   if (__objc_resolve_class_method (class_, selector))
669     return search_for_method_in_hierarchy (class_->class_pointer,
670 					   selector);
671 
672   return NULL;
673 }
674 
675 BOOL
676 class_addMethod (Class class_, SEL selector, IMP implementation,
677 		 const char *method_types)
678 {
679   struct objc_method_list *method_list;
680   struct objc_method *method;
681   const char *method_name;
682 
683   if (class_ == Nil  ||  selector == NULL  ||  implementation == NULL
684       || method_types == NULL  || (strcmp (method_types, "") == 0))
685     return NO;
686 
687   method_name = sel_getName (selector);
688   if (method_name == NULL)
689     return NO;
690 
691   /* If the method already exists in the class, return NO.  It is fine
692      if the method already exists in the superclass; in that case, we
693      are overriding it.  */
694   if (CLS_IS_IN_CONSTRUCTION (class_))
695     {
696       /* The class only contains a list of methods; they have not been
697 	 registered yet, ie, the method_name of each of them is still
698 	 a string, not a selector.  Iterate manually over them to
699 	 check if we have already added the method.  */
700       struct objc_method_list * method_list = class_->methods;
701       while (method_list)
702 	{
703 	  int i;
704 
705 	  /* Search the method list.  */
706 	  for (i = 0; i < method_list->method_count; ++i)
707 	    {
708 	      struct objc_method * method = &method_list->method_list[i];
709 
710 	      if (method->method_name
711 		  && strcmp ((char *)method->method_name, method_name) == 0)
712 		return NO;
713 	    }
714 
715 	  /* The method wasn't found.  Follow the link to the next list of
716 	     methods.  */
717 	  method_list = method_list->method_next;
718 	}
719       /* The method wasn't found.  It's a new one.  Go ahead and add
720 	 it.  */
721     }
722   else
723     {
724       /* Do the standard lookup.  This assumes the selectors are
725 	 mapped.  */
726       if (search_for_method_in_list (class_->methods, selector))
727 	return NO;
728     }
729 
730   method_list = (struct objc_method_list *)objc_calloc (1, sizeof (struct objc_method_list));
731   method_list->method_count = 1;
732 
733   method = &(method_list->method_list[0]);
734   method->method_name = objc_malloc (strlen (method_name) + 1);
735   strcpy ((char *)method->method_name, method_name);
736 
737   method->method_types = objc_malloc (strlen (method_types) + 1);
738   strcpy ((char *)method->method_types, method_types);
739 
740   method->method_imp = implementation;
741 
742   if (CLS_IS_IN_CONSTRUCTION (class_))
743     {
744       /* We only need to add the method to the list.  It will be
745 	 registered with the runtime when the class pair is registered
746 	 (if ever).  */
747       method_list->method_next = class_->methods;
748       class_->methods = method_list;
749     }
750   else
751     {
752       /* Add the method to a live class.  */
753       objc_mutex_lock (__objc_runtime_mutex);
754       class_add_method_list (class_, method_list);
755       objc_mutex_unlock (__objc_runtime_mutex);
756     }
757 
758   return YES;
759 }
760 
761 IMP
762 class_replaceMethod (Class class_, SEL selector, IMP implementation,
763 		     const char *method_types)
764 {
765   struct objc_method * method;
766 
767   if (class_ == Nil  ||  selector == NULL  ||  implementation == NULL
768       || method_types == NULL)
769     return NULL;
770 
771   method = search_for_method_in_hierarchy (class_, selector);
772 
773   if (method)
774     {
775       return method_setImplementation (method, implementation);
776     }
777   else
778     {
779       class_addMethod (class_, selector, implementation, method_types);
780       return NULL;
781     }
782 }
783 
784 /* Search for a method starting from the current class up its
785    hierarchy.  Return a pointer to the method's method structure if
786    found.  NULL otherwise.  */
787 static struct objc_method *
788 search_for_method_in_hierarchy (Class cls, SEL sel)
789 {
790   struct objc_method * method = NULL;
791   Class class;
792 
793   if (! sel_is_mapped (sel))
794     return NULL;
795 
796   /* Scan the method list of the class.  If the method isn't found in
797      the list then step to its super class.  */
798   for (class = cls; ((! method) && class); class = class->super_class)
799     method = search_for_method_in_list (class->methods, sel);
800 
801   return method;
802 }
803 
804 
805 
806 /* Given a linked list of method and a method's name.  Search for the
807    named method's method structure.  Return a pointer to the method's
808    method structure if found.  NULL otherwise.  */
809 struct objc_method *
810 search_for_method_in_list (struct objc_method_list * list, SEL op)
811 {
812   struct objc_method_list * method_list = list;
813 
814   if (! sel_is_mapped (op))
815     return NULL;
816 
817   /* If not found then we'll search the list.  */
818   while (method_list)
819     {
820       int i;
821 
822       /* Search the method list.  */
823       for (i = 0; i < method_list->method_count; ++i)
824         {
825           struct objc_method * method = &method_list->method_list[i];
826 
827           if (method->method_name)
828             if (method->method_name->sel_id == op->sel_id)
829               return method;
830         }
831 
832       /* The method wasn't found.  Follow the link to the next list of
833          methods.  */
834       method_list = method_list->method_next;
835     }
836 
837   return NULL;
838 }
839 
840 typedef void * retval_t;
841 typedef void * arglist_t;
842 
843 static retval_t __objc_forward (id object, SEL sel, arglist_t args);
844 
845 /* Forwarding pointers/integers through the normal registers.  */
846 static id
847 __objc_word_forward (id rcv, SEL op, ...)
848 {
849   void *args, *res;
850 
851   args = __builtin_apply_args ();
852   res = __objc_forward (rcv, op, args);
853   if (res)
854     __builtin_return (res);
855   else
856     return res;
857 }
858 
859 /* Specific routine for forwarding floats/double because of
860    architectural differences on some processors.  i386s for example
861    which uses a floating point stack versus general registers for
862    floating point numbers.  This forward routine makes sure that GCC
863    restores the proper return values.  */
864 static double
865 __objc_double_forward (id rcv, SEL op, ...)
866 {
867   void *args, *res;
868 
869   args = __builtin_apply_args ();
870   res = __objc_forward (rcv, op, args);
871   __builtin_return (res);
872 }
873 
874 #if INVISIBLE_STRUCT_RETURN
875 static __big
876 #else
877 static id
878 #endif
879 __objc_block_forward (id rcv, SEL op, ...)
880 {
881   void *args, *res;
882 
883   args = __builtin_apply_args ();
884   res = __objc_forward (rcv, op, args);
885   if (res)
886     __builtin_return (res);
887   else
888 #if INVISIBLE_STRUCT_RETURN
889     return (__big) {{0, 0, 0, 0, 0, 0, 0, 0}};
890 #else
891     return nil;
892 #endif
893 }
894 
895 
896 /* This function is called for methods which are not implemented,
897    unless a custom forwarding routine has been installed.  Please note
898    that most serious users of libobjc (eg, GNUstep base) do install
899    their own forwarding routines, and hence this is never actually
900    used.  But, if no custom forwarding routine is installed, this is
901    called when a selector is not recognized.  */
902 static retval_t
903 __objc_forward (id object, SEL sel, arglist_t args)
904 {
905   IMP imp;
906   static SEL frwd_sel = 0;                      /* !T:SAFE2 */
907   SEL err_sel;
908 
909   /* First try if the object understands forward::.  */
910   if (! frwd_sel)
911     frwd_sel = sel_get_any_uid ("forward::");
912 
913   if (__objc_responds_to (object, frwd_sel))
914     {
915       imp = get_implementation (object, object->class_pointer, frwd_sel);
916       return (*imp) (object, frwd_sel, sel, args);
917     }
918 
919   /* If the object recognizes the doesNotRecognize: method then we're
920      going to send it.  */
921   err_sel = sel_get_any_uid ("doesNotRecognize:");
922   if (__objc_responds_to (object, err_sel))
923     {
924       imp = get_implementation (object, object->class_pointer, err_sel);
925       return (*imp) (object, err_sel, sel);
926     }
927 
928   /* The object doesn't recognize the method.  Check for responding to
929      error:.  If it does then sent it.  */
930   {
931     char msg[256 + strlen ((const char *) sel_getName (sel))
932              + strlen ((const char *) object->class_pointer->name)];
933 
934     sprintf (msg, "(%s) %s does not recognize %s",
935 	     (CLS_ISMETA (object->class_pointer)
936 	      ? "class"
937 	      : "instance" ),
938              object->class_pointer->name, sel_getName (sel));
939 
940     /* The object doesn't respond to doesNotRecognize:.  Therefore, a
941        default action is taken.  */
942     _objc_abort ("%s\n", msg);
943 
944     return 0;
945   }
946 }
947 
948 void
949 __objc_print_dtable_stats (void)
950 {
951   int total = 0;
952 
953   objc_mutex_lock (__objc_runtime_mutex);
954 
955 #ifdef OBJC_SPARSE2
956   printf ("memory usage: (%s)\n", "2-level sparse arrays");
957 #else
958   printf ("memory usage: (%s)\n", "3-level sparse arrays");
959 #endif
960 
961   printf ("arrays: %d = %ld bytes\n", narrays,
962 	  (long) ((size_t) narrays * sizeof (struct sarray)));
963   total += narrays * sizeof (struct sarray);
964   printf ("buckets: %d = %ld bytes\n", nbuckets,
965 	  (long) ((size_t) nbuckets * sizeof (struct sbucket)));
966   total += nbuckets * sizeof (struct sbucket);
967 
968   printf ("idxtables: %d = %ld bytes\n",
969 	  idxsize, (long) ((size_t) idxsize * sizeof (void *)));
970   total += idxsize * sizeof (void *);
971   printf ("-----------------------------------\n");
972   printf ("total: %d bytes\n", total);
973   printf ("===================================\n");
974 
975   objc_mutex_unlock (__objc_runtime_mutex);
976 }
977 
978 static cache_ptr prepared_dtable_table = 0;
979 
980 /* This function is called by: objc_msg_lookup, get_imp and
981    __objc_responds_to (and the dispatch table installation functions
982    themselves) to install a dispatch table for a class.
983 
984    If CLS is a class, it installs instance methods.
985    If CLS is a meta class, it installs class methods.
986 
987    In either case +initialize is invoked for the corresponding class.
988 
989    The implementation must insure that the dispatch table is not
990    installed until +initialize completes.  Otherwise it opens a
991    potential race since the installation of the dispatch table is used
992    as gate in regular method dispatch and we need to guarantee that
993    +initialize is the first method invoked an that no other thread my
994    dispatch messages to the class before +initialize completes.  */
995 static void
996 __objc_install_dtable_for_class (Class cls)
997 {
998   /* If the class has not yet had its class links resolved, we must
999      re-compute all class links.  */
1000   if (! CLS_ISRESOLV (cls))
1001     __objc_resolve_class_links ();
1002 
1003   /* Make sure the super class has its dispatch table installed or is
1004      at least preparing.  We do not need to send initialize for the
1005      super class since __objc_send_initialize will insure that.  */
1006   if (cls->super_class
1007       && cls->super_class->dtable == __objc_uninstalled_dtable
1008       && !__objc_prepared_dtable_for_class (cls->super_class))
1009     {
1010       __objc_install_dtable_for_class (cls->super_class);
1011       /* The superclass initialisation may have also initialised the
1012          current class, in which case there is no more to do.  */
1013       if (cls->dtable != __objc_uninstalled_dtable)
1014 	return;
1015     }
1016 
1017   /* We have already been prepared but +initialize hasn't completed.
1018      The +initialize implementation is probably sending 'self'
1019      messages.  We rely on _objc_get_prepared_imp to retrieve the
1020      implementation pointers.  */
1021   if (__objc_prepared_dtable_for_class (cls))
1022     return;
1023 
1024   /* We have this function cache the implementation pointers for
1025      _objc_get_prepared_imp but the dispatch table won't be initilized
1026      until __objc_send_initialize completes.  */
1027   __objc_prepare_dtable_for_class (cls);
1028 
1029   /* We may have already invoked +initialize but
1030      __objc_update_dispatch_table_for_class invoked by
1031      class_add_method_list may have reset dispatch table.  */
1032 
1033   /* Call +initialize.  If we are a real class, we are installing
1034      instance methods.  If we are a meta class, we are installing
1035      class methods.  The __objc_send_initialize itself will insure
1036      that the message is called only once per class.  */
1037   if (CLS_ISCLASS (cls))
1038     __objc_send_initialize (cls);
1039   else
1040     {
1041       /* Retrieve the class from the meta class.  */
1042       Class c = objc_getClass (cls->name);
1043       assert (CLS_ISMETA (cls));
1044       assert (c);
1045       __objc_send_initialize (c);
1046     }
1047 
1048   /* We install the dispatch table correctly when +initialize completed.  */
1049   __objc_install_prepared_dtable_for_class (cls);
1050 }
1051 
1052 /* Builds the dispatch table for the class CLS and stores it in a
1053    place where it can be retrieved by __objc_get_prepared_imp until
1054    __objc_install_prepared_dtable_for_class installs it into the
1055    class.  The dispatch table should not be installed into the class
1056    until +initialize has completed.  */
1057 static void
1058 __objc_prepare_dtable_for_class (Class cls)
1059 {
1060   struct sarray *dtable;
1061   struct sarray *super_dtable;
1062 
1063   /* This table could be initialized in init.c.  We can not use the
1064      class name since the class maintains the instance methods and the
1065      meta class maintains the the class methods yet both share the
1066      same name.  Classes should be unique in any program.  */
1067   if (! prepared_dtable_table)
1068     prepared_dtable_table
1069       = objc_hash_new (32,
1070 		       (hash_func_type) objc_hash_ptr,
1071 		       (compare_func_type) objc_compare_ptrs);
1072 
1073   /* If the class has not yet had its class links resolved, we must
1074      re-compute all class links.  */
1075   if (! CLS_ISRESOLV (cls))
1076     __objc_resolve_class_links ();
1077 
1078   assert (cls);
1079   assert (cls->dtable == __objc_uninstalled_dtable);
1080 
1081   /* If there is already a prepared dtable for this class, we must
1082      replace it with a new version (since there must have been methods
1083      added to or otherwise modified in the class while executing
1084      +initialize, and the table needs to be recomputed.  */
1085   dtable = __objc_prepared_dtable_for_class (cls);
1086   if (dtable != 0)
1087     {
1088       objc_hash_remove (prepared_dtable_table, cls);
1089       sarray_free (dtable);
1090     }
1091 
1092   /* Now prepare the dtable for population.  */
1093   assert (cls != cls->super_class);
1094   if (cls->super_class)
1095     {
1096       /* Inherit the method list from the super class.  Yet the super
1097          class may still be initializing in the case when a class
1098          cluster sub class initializes its super classes.  */
1099       if (cls->super_class->dtable == __objc_uninstalled_dtable)
1100 	__objc_install_dtable_for_class (cls->super_class);
1101 
1102       super_dtable = cls->super_class->dtable;
1103       /* If the dispatch table is not yet installed, we are still in
1104 	 the process of executing +initialize.  Yet the dispatch table
1105 	 should be available.  */
1106       if (super_dtable == __objc_uninstalled_dtable)
1107 	super_dtable = __objc_prepared_dtable_for_class (cls->super_class);
1108 
1109       assert (super_dtable);
1110       dtable = sarray_lazy_copy (super_dtable);
1111     }
1112   else
1113     dtable = sarray_new (__objc_selector_max_index, 0);
1114 
1115   __objc_install_methods_in_dtable (dtable, cls->methods);
1116 
1117   objc_hash_add (&prepared_dtable_table,
1118 		 cls,
1119 		 dtable);
1120 }
1121 
1122 /* This wrapper only exists to allow an easy replacement of the lookup
1123    implementation and it is expected that the compiler will optimize
1124    it away.  */
1125 static struct sarray *
1126 __objc_prepared_dtable_for_class (Class cls)
1127 {
1128   struct sarray *dtable = 0;
1129   assert (cls);
1130   if (prepared_dtable_table)
1131     dtable = objc_hash_value_for_key (prepared_dtable_table, cls);
1132   /* dtable my be nil, since we call this to check whether we are
1133      currently preparing before we start preparing.  */
1134   return dtable;
1135 }
1136 
1137 /* Helper function for messages sent to CLS or implementation pointers
1138    retrieved from CLS during +initialize before the dtable is
1139    installed.  When a class implicitly initializes another class which
1140    in turn implicitly invokes methods in this class, before the
1141    implementation of +initialize of CLS completes, this returns the
1142    expected implementation.  Forwarding remains the responsibility of
1143    objc_msg_lookup.  This function should only be called under the
1144    global lock.  */
1145 static IMP
1146 __objc_get_prepared_imp (Class cls,SEL sel)
1147 {
1148   struct sarray *dtable;
1149   IMP imp;
1150 
1151   assert (cls);
1152   assert (sel);
1153   assert (cls->dtable == __objc_uninstalled_dtable);
1154   dtable = __objc_prepared_dtable_for_class (cls);
1155 
1156   assert (dtable);
1157   assert (dtable != __objc_uninstalled_dtable);
1158   imp = sarray_get_safe (dtable, (size_t) sel->sel_id);
1159 
1160   /* imp may be Nil if the method does not exist and we may fallback
1161      to the forwarding implementation later.  */
1162   return imp;
1163 }
1164 
1165 /* When this function is called +initialize should be completed.  So
1166    now we are safe to install the dispatch table for the class so that
1167    they become available for other threads that may be waiting in the
1168    lock.  */
1169 static void
1170 __objc_install_prepared_dtable_for_class (Class cls)
1171 {
1172   assert (cls);
1173   assert (cls->dtable == __objc_uninstalled_dtable);
1174   cls->dtable = __objc_prepared_dtable_for_class (cls);
1175 
1176   assert (cls->dtable);
1177   assert (cls->dtable != __objc_uninstalled_dtable);
1178   objc_hash_remove (prepared_dtable_table, cls);
1179 }
1180