OSDN Git Service

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