selector.c: Reindented some code and tidied up comments.
[platform/upstream/gcc.git] / libobjc / selector.c
1 /* GNU Objective C Runtime selector related functions
2    Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004, 2009 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 #include "objc-private/common.h"
26 #include "objc/objc-api.h"
27 #include "objc/thr.h"
28 #include "objc-private/hash.h"
29 #include "objc-private/objc-list.h" 
30 #include "objc-private/runtime.h"
31 #include "objc-private/sarray.h"
32 #include "objc/encoding.h"
33
34 /* Initial selector hash table size. Value doesn't matter much.  */
35 #define SELECTOR_HASH_SIZE 128
36
37 /* Tables mapping selector names to uid and opposite.  */
38 static struct sarray *__objc_selector_array = 0; /* uid -> sel  !T:MUTEX */
39 static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
40 static cache_ptr      __objc_selector_hash  = 0; /* name -> uid !T:MUTEX */
41
42 /* Number of selectors stored in each of the above tables.  */
43 unsigned int __objc_selector_max_index = 0;     /* !T:MUTEX */
44
45 void __objc_init_selector_tables (void)
46 {
47   __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
48   __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
49   __objc_selector_hash
50     = objc_hash_new (SELECTOR_HASH_SIZE,
51                      (hash_func_type) objc_hash_string,
52                      (compare_func_type) objc_compare_strings);
53 }  
54
55 /* This routine is given a class and records all of the methods in its
56    class structure in the record table.  */
57 void
58 __objc_register_selectors_from_class (Class class)
59 {
60   MethodList_t method_list;
61
62   method_list = class->methods;
63   while (method_list)
64     {
65       __objc_register_selectors_from_list (method_list);
66       method_list = method_list->method_next;
67     }
68 }
69
70
71 /* This routine is given a list of methods and records each of the
72    methods in the record table.  This is the routine that does the
73    actual recording work.
74
75    The name and type pointers in the method list must be permanent and
76    immutable.  */
77 void
78 __objc_register_selectors_from_list (MethodList_t method_list)
79 {
80   int i = 0;
81
82   objc_mutex_lock (__objc_runtime_mutex);
83   while (i < method_list->method_count)
84     {
85       Method_t method = &method_list->method_list[i];
86       if (method->method_name)
87         {
88           method->method_name
89             = __sel_register_typed_name ((const char *) method->method_name,
90                                          method->method_types, 0, YES);
91         }
92       i += 1;
93     }
94   objc_mutex_unlock (__objc_runtime_mutex);
95 }
96
97 /* Temporary definition while we include objc/objc-api.h instead of
98    objc-private/module-abi-8.h.  It should go away once we include
99    module-abi-8.h.  */
100 struct objc_method_description_list
101 {
102   int count;
103   struct objc_method_description list[1];
104 };
105
106 /* The same as __objc_register_selectors_from_list, but works on a
107    struct objc_method_description_list* instead of a struct
108    objc_method_list*.  This is only used for protocols, which have
109    lists of method descriptions, not methods.  */
110 void
111 __objc_register_selectors_from_description_list 
112 (struct objc_method_description_list *method_list)
113 {
114   int i = 0;
115   
116   objc_mutex_lock (__objc_runtime_mutex);
117   while (i < method_list->count)
118     {
119       struct objc_method_description *method = &method_list->list[i];
120       if (method->name)
121         {
122           method->name
123             = __sel_register_typed_name ((const char *) method->name,
124                                          method->types, 0, YES);
125         }
126       i += 1;
127     }
128   objc_mutex_unlock (__objc_runtime_mutex);
129 }
130
131 /* Register instance methods as class methods for root classes.  */
132 void __objc_register_instance_methods_to_class (Class class)
133 {
134   MethodList_t method_list;
135   MethodList_t class_method_list;
136   int max_methods_no = 16;
137   MethodList_t new_list;
138   Method_t curr_method;
139
140   /* Only if a root class. */
141   if (class->super_class)
142     return;
143
144   /* Allocate a method list to hold the new class methods.  */
145   new_list = objc_calloc (sizeof (struct objc_method_list)
146                           + sizeof (struct objc_method[max_methods_no]), 1);
147   method_list = class->methods;
148   class_method_list = class->class_pointer->methods;
149   curr_method = &new_list->method_list[0];
150   
151   /* Iterate through the method lists for the class.  */
152   while (method_list)
153     {
154       int i;
155       
156       /* Iterate through the methods from this method list.  */
157       for (i = 0; i < method_list->method_count; i++)
158         {
159           Method_t mth = &method_list->method_list[i];
160           if (mth->method_name
161               && ! search_for_method_in_list (class_method_list,
162                                               mth->method_name))
163             {
164               /* This instance method isn't a class method.  Add it
165                  into the new_list. */
166               *curr_method = *mth;
167               
168               /* Reallocate the method list if necessary.  */
169               if (++new_list->method_count == max_methods_no)
170                 new_list =
171                   objc_realloc (new_list, sizeof (struct objc_method_list)
172                                 + sizeof (struct 
173                                           objc_method[max_methods_no += 16]));
174               curr_method = &new_list->method_list[new_list->method_count];
175             }
176         }
177
178       method_list = method_list->method_next;
179     }
180
181   /* If we created any new class methods then attach the method list
182      to the class.  */
183   if (new_list->method_count)
184     {
185       new_list =
186         objc_realloc (new_list, sizeof (struct objc_method_list)
187                       + sizeof (struct objc_method[new_list->method_count]));
188       new_list->method_next = class->class_pointer->methods;
189       class->class_pointer->methods = new_list;
190     }
191   else
192     objc_free(new_list);
193   
194   __objc_update_dispatch_table_for_class (class->class_pointer);
195 }
196
197 BOOL
198 sel_isEqual (SEL s1, SEL s2)
199 {
200   if (s1 == 0 || s2 == 0)
201     return s1 == s2;
202   else
203     return s1->sel_id == s2->sel_id;
204 }
205
206 /* Return YES iff t1 and t2 have same method types.  Ignore the
207    argframe layout.  */
208 BOOL
209 sel_types_match (const char *t1, const char *t2)
210 {
211   if (! t1 || ! t2)
212     return NO;
213   while (*t1 && *t2)
214     {
215       if (*t1 == '+') t1++;
216       if (*t2 == '+') t2++;
217       while (isdigit ((unsigned char) *t1)) t1++;
218       while (isdigit ((unsigned char) *t2)) t2++;
219       /* xxx Remove these next two lines when qualifiers are put in
220          all selectors, not just Protocol selectors.  */
221       t1 = objc_skip_type_qualifiers (t1);
222       t2 = objc_skip_type_qualifiers (t2);
223       if (! *t1 && ! *t2)
224         return YES;
225       if (*t1 != *t2)
226         return NO;
227       t1++;
228       t2++;
229     }
230   return NO;
231 }
232
233 /* Return selector representing name.  */
234 SEL
235 sel_get_typed_uid (const char *name, const char *types)
236 {
237   struct objc_list *l;
238   sidx i;
239
240   objc_mutex_lock (__objc_runtime_mutex);
241
242   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
243   if (i == 0)
244     {
245       objc_mutex_unlock (__objc_runtime_mutex);
246       return 0;
247     }
248
249   for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
250        l; l = l->tail)
251     {
252       SEL s = (SEL) l->head;
253       if (types == 0 || s->sel_types == 0)
254         {
255           if (s->sel_types == types)
256             {
257               objc_mutex_unlock (__objc_runtime_mutex);
258               return s;
259             }
260         }
261       else if (sel_types_match (s->sel_types, types))
262         {
263           objc_mutex_unlock (__objc_runtime_mutex);
264           return s;
265         }
266     }
267
268   objc_mutex_unlock (__objc_runtime_mutex);
269   return 0;
270 }
271
272 /* Return selector representing name; prefer a selector with non-NULL
273    type.  */
274 SEL
275 sel_get_any_typed_uid (const char *name)
276 {
277   struct objc_list *l;
278   sidx i;
279   SEL s = NULL;
280
281   objc_mutex_lock (__objc_runtime_mutex);
282
283   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
284   if (i == 0)
285     {
286       objc_mutex_unlock (__objc_runtime_mutex);
287       return 0;
288     }
289
290   for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
291        l; l = l->tail)
292     {
293       s = (SEL) l->head;
294       if (s->sel_types)
295         {
296             objc_mutex_unlock (__objc_runtime_mutex);
297             return s;
298         }
299     }
300
301   objc_mutex_unlock (__objc_runtime_mutex);
302   return s;
303 }
304
305 /* Return selector representing name.  */
306 SEL
307 sel_get_any_uid (const char *name)
308 {
309   struct objc_list *l;
310   sidx i;
311
312   objc_mutex_lock (__objc_runtime_mutex);
313
314   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
315   if (soffset_decode (i) == 0)
316     {
317       objc_mutex_unlock (__objc_runtime_mutex);
318       return 0;
319     }
320
321   l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
322   objc_mutex_unlock (__objc_runtime_mutex);
323
324   if (l == 0)
325     return 0;
326
327   return (SEL) l->head;
328 }
329
330 /* Get the name of a selector.  If the selector is unknown, the empty
331    string "" is returned.  */ 
332 const char *sel_getName (SEL selector)
333 {
334   const char *ret;
335
336   if (selector == NULL)
337     return "<null selector>";
338   
339   objc_mutex_lock (__objc_runtime_mutex);
340   if ((soffset_decode ((sidx)selector->sel_id) > 0)
341       && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
342     ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
343   else
344     ret = 0;
345   objc_mutex_unlock (__objc_runtime_mutex);
346   return ret;
347 }
348
349 /* Traditional GNU Objective-C Runtime API.  */
350 const char *sel_get_name (SEL selector)
351 {
352   if (selector == NULL)
353     return 0;
354
355   return sel_getName (selector);
356 }
357
358 BOOL
359 sel_is_mapped (SEL selector)
360 {
361   unsigned int idx = soffset_decode ((sidx)selector->sel_id);
362   return ((idx > 0) && (idx <= __objc_selector_max_index));
363 }
364
365 const char *sel_getType (SEL selector)
366 {
367   if (selector)
368     return selector->sel_types;
369   else
370     return 0;
371 }
372
373 /* Traditional GNU Objective-C Runtime API.  */
374 const char *sel_get_type (SEL selector)
375 {
376   return sel_getType (selector);
377 }
378
379 /* The uninstalled dispatch table.  */
380 extern struct sarray *__objc_uninstalled_dtable;
381
382 /* __sel_register_typed_name allocates lots of struct objc_selector:s
383    of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the
384    number of malloc calls and memory lost to malloc overhead, we
385    allocate objc_selector:s in blocks here. This is only called from
386    __sel_register_typed_name, and __sel_register_typed_name may only
387    be called when __objc_runtime_mutex is locked.
388
389    Note that the objc_selector:s allocated from
390    __sel_register_typed_name are never freed.
391
392    62 because 62 * sizeof (struct objc_selector) = 496 (992). This
393    should let malloc add some overhead and use a nice, round 512
394    (1024) byte chunk.  */
395 #define SELECTOR_POOL_SIZE 62
396 static struct objc_selector *selector_pool;
397 static int selector_pool_left;
398
399 static struct objc_selector *
400 pool_alloc_selector(void)
401 {
402   if (!selector_pool_left)
403     {
404       selector_pool = objc_malloc (sizeof (struct objc_selector)
405                                    * SELECTOR_POOL_SIZE);
406       selector_pool_left = SELECTOR_POOL_SIZE;
407     }
408   return &selector_pool[--selector_pool_left];
409 }
410
411 /* Store the passed selector name in the selector record and return
412    its selector value (value returned by sel_get_uid).  Assume that
413    the calling function has locked down __objc_runtime_mutex.  The
414    is_const parameter tells us if the name and types parameters are
415    really constant or not.  If YES then they are constant and we can
416    just store the pointers.  If NO then we need to copy name and types
417    because the pointers may disappear later on.  */
418 SEL
419 __sel_register_typed_name (const char *name, const char *types, 
420                            struct objc_selector *orig, BOOL is_const)
421 {
422   struct objc_selector *j;
423   sidx i;
424   struct objc_list *l;
425
426   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
427   if (soffset_decode (i) != 0)
428     {
429       for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
430            l; l = l->tail)
431         {
432           SEL s = (SEL) l->head;
433           if (types == 0 || s->sel_types == 0)
434             {
435               if (s->sel_types == types)
436                 {
437                   if (orig)
438                     {
439                       orig->sel_id = (void *) i;
440                       return orig;
441                     }
442                   else
443                     return s;
444                 }
445             }
446           else if (! strcmp (s->sel_types, types))
447             {
448               if (orig)
449                 {
450                   orig->sel_id = (void *) i;
451                   return orig;
452                 }
453               else
454                 return s;
455             }
456         }
457       if (orig)
458         j = orig;
459       else
460         j = pool_alloc_selector ();
461       
462       j->sel_id = (void *) i;
463       /* Can we use the pointer or must copy types?  Don't copy if
464          NULL.  */
465       if ((is_const) || (types == 0))
466         j->sel_types = (const char *) types;
467       else
468         {
469           j->sel_types = (char *) objc_malloc (strlen (types) + 1);
470           strcpy ((char *) j->sel_types, types);
471         }
472       l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
473     }
474   else
475     {
476       __objc_selector_max_index += 1;
477       i = soffset_encode (__objc_selector_max_index);
478       if (orig)
479         j = orig;
480       else
481         j = pool_alloc_selector ();
482       
483       j->sel_id = (void *) i;
484       /* Can we use the pointer or must copy types?  Don't copy if
485          NULL.  */
486       if ((is_const) || (types == 0))
487         j->sel_types = (const char *) types;
488       else
489         {
490           j->sel_types = (char *) objc_malloc (strlen (types) + 1);
491           strcpy ((char *) j->sel_types, types);
492         }
493       l = 0;
494     }
495
496   DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types, 
497                 (long) soffset_decode (i));
498   
499   {
500     int is_new = (l == 0);
501     const char *new_name;
502
503     /* Can we use the pointer or must copy name?  Don't copy if
504        NULL.  */
505     if ((is_const) || (name == 0))
506       new_name = name;
507     else
508       {
509         new_name = (char *) objc_malloc (strlen (name) + 1);
510         strcpy ((char *) new_name, name);
511       }
512     
513     l = list_cons ((void *) j, l);
514     sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
515     sarray_at_put_safe (__objc_selector_array, i, (void *) l);
516     if (is_new)
517       objc_hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
518   }
519   
520   sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
521   
522   return (SEL) j;
523 }
524
525 SEL
526 sel_registerName (const char *name)
527 {
528   SEL ret;
529     
530   objc_mutex_lock (__objc_runtime_mutex);
531   /* Assume that name is not constant static memory and needs to be
532      copied before put into a runtime structure.  is_const == NO.  */
533   ret = __sel_register_typed_name (name, 0, 0, NO);
534   objc_mutex_unlock (__objc_runtime_mutex);
535   
536   return ret;
537 }
538
539 /* Traditional GNU Objective-C Runtime API.  */
540 SEL
541 sel_register_name (const char *name)
542 {
543   return sel_registerName (name);
544 }
545
546 SEL
547 sel_registerTypedName (const char *name, const char *type)
548 {
549   SEL ret;
550
551   objc_mutex_lock (__objc_runtime_mutex);
552   /* Assume that name and type are not constant static memory and need
553      to be copied before put into a runtime structure.  is_const ==
554      NO.  */
555   ret = __sel_register_typed_name (name, type, 0, NO);
556   objc_mutex_unlock (__objc_runtime_mutex);
557   
558   return ret;
559 }
560
561 SEL
562 sel_register_typed_name (const char *name, const char *type)
563 {
564   return sel_registerTypedName (name, type);
565 }
566
567 /* Return the selector representing name.  */
568 SEL
569 sel_getUid (const char *name)
570 {
571   return sel_registerTypedName (name, 0);
572 }
573
574 /* Traditional GNU Objective-C Runtime API.  */
575 SEL
576 sel_get_uid (const char *name)
577 {
578   return sel_getUid (name);
579 }