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