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