OSDN Git Service

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