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