OSDN Git Service

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