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