OSDN Git Service

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