In libobjc/: 2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com>
[official-gcc.git] / libobjc / selector.c
blob0c12130ae3807dcaaaefb5906a6f881d8557a9de
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
5 This file is part of GCC.
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.
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.
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.
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/>. */
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"
35 /* Initial selector hash table size. Value doesn't matter much */
36 #define SELECTOR_HASH_SIZE 128
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 */
43 /* Number of selectors stored in each of the above tables */
44 unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */
46 void __objc_init_selector_tables (void)
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);
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)
61 MethodList_t method_list;
63 method_list = class->methods;
64 while (method_list)
66 __objc_register_selectors_from_list (method_list);
67 method_list = method_list->method_next;
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.
76 The name and type pointers in the method list must be permanent and
77 immutable.
79 void
80 __objc_register_selectors_from_list (MethodList_t method_list)
82 int i = 0;
84 objc_mutex_lock (__objc_runtime_mutex);
85 while (i < method_list->method_count)
87 Method_t method = &method_list->method_list[i];
88 if (method->method_name)
90 method->method_name
91 = __sel_register_typed_name ((const char *) method->method_name,
92 method->method_types, 0, YES);
94 i += 1;
96 objc_mutex_unlock (__objc_runtime_mutex);
100 /* Register instance methods as class methods for root classes */
101 void __objc_register_instance_methods_to_class (Class class)
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;
109 /* Only if a root class. */
110 if (class->super_class)
111 return;
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];
120 /* Iterate through the method lists for the class */
121 while (method_list)
123 int i;
125 /* Iterate through the methods from this method list */
126 for (i = 0; i < method_list->method_count; i++)
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))
133 /* This instance method isn't a class method.
134 Add it into the new_list. */
135 *curr_method = *mth;
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];
147 method_list = method_list->method_next;
150 /* If we created any new class methods
151 then attach the method list to the class */
152 if (new_list->method_count)
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;
160 else
161 objc_free(new_list);
163 __objc_update_dispatch_table_for_class (class->class_pointer);
166 BOOL
167 sel_isEqual (SEL s1, SEL s2)
169 if (s1 == 0 || s2 == 0)
170 return s1 == s2;
171 else
172 return s1->sel_id == s2->sel_id;
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)
180 if (! t1 || ! t2)
181 return NO;
182 while (*t1 && *t2)
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++;
199 return NO;
202 /* return selector representing name */
204 sel_get_typed_uid (const char *name, const char *types)
206 struct objc_list *l;
207 sidx i;
209 objc_mutex_lock (__objc_runtime_mutex);
211 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
212 if (i == 0)
214 objc_mutex_unlock (__objc_runtime_mutex);
215 return 0;
218 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
219 l; l = l->tail)
221 SEL s = (SEL) l->head;
222 if (types == 0 || s->sel_types == 0)
224 if (s->sel_types == types)
226 objc_mutex_unlock (__objc_runtime_mutex);
227 return s;
230 else if (sel_types_match (s->sel_types, types))
232 objc_mutex_unlock (__objc_runtime_mutex);
233 return s;
237 objc_mutex_unlock (__objc_runtime_mutex);
238 return 0;
241 /* Return selector representing name; prefer a selector with non-NULL type */
243 sel_get_any_typed_uid (const char *name)
245 struct objc_list *l;
246 sidx i;
247 SEL s = NULL;
249 objc_mutex_lock (__objc_runtime_mutex);
251 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
252 if (i == 0)
254 objc_mutex_unlock (__objc_runtime_mutex);
255 return 0;
258 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
259 l; l = l->tail)
261 s = (SEL) l->head;
262 if (s->sel_types)
264 objc_mutex_unlock (__objc_runtime_mutex);
265 return s;
269 objc_mutex_unlock (__objc_runtime_mutex);
270 return s;
273 /* return selector representing name */
275 sel_get_any_uid (const char *name)
277 struct objc_list *l;
278 sidx i;
280 objc_mutex_lock (__objc_runtime_mutex);
282 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
283 if (soffset_decode (i) == 0)
285 objc_mutex_unlock (__objc_runtime_mutex);
286 return 0;
289 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
290 objc_mutex_unlock (__objc_runtime_mutex);
292 if (l == 0)
293 return 0;
295 return (SEL) l->head;
298 /* Get name of selector. If selector is unknown, the empty string ""
299 is returned */
300 const char *sel_getName (SEL selector)
302 const char *ret;
304 if (selector == NULL)
305 return "<null selector>";
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;
317 /* Traditional GNU Objective-C Runtime API. */
318 const char *sel_get_name (SEL selector)
320 if (selector == NULL)
321 return 0;
323 return sel_getName (selector);
326 BOOL
327 sel_is_mapped (SEL selector)
329 unsigned int idx = soffset_decode ((sidx)selector->sel_id);
330 return ((idx > 0) && (idx <= __objc_selector_max_index));
333 const char *sel_getType (SEL selector)
335 if (selector)
336 return selector->sel_types;
337 else
338 return 0;
341 /* Traditional GNU Objective-C Runtime API. */
342 const char *sel_get_type (SEL selector)
344 return sel_getType (selector);
347 /* The uninstalled dispatch table */
348 extern struct sarray *__objc_uninstalled_dtable;
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.
357 Note that the objc_selector:s allocated from __sel_register_typed_name
358 are never freed.
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.
363 #define SELECTOR_POOL_SIZE 62
364 static struct objc_selector *selector_pool;
365 static int selector_pool_left;
367 static struct objc_selector *
368 pool_alloc_selector(void)
370 if (!selector_pool_left)
372 selector_pool = objc_malloc (sizeof (struct objc_selector)
373 * SELECTOR_POOL_SIZE);
374 selector_pool_left = SELECTOR_POOL_SIZE;
376 return &selector_pool[--selector_pool_left];
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. */
387 __sel_register_typed_name (const char *name, const char *types,
388 struct objc_selector *orig, BOOL is_const)
390 struct objc_selector *j;
391 sidx i;
392 struct objc_list *l;
394 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
395 if (soffset_decode (i) != 0)
397 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
398 l; l = l->tail)
400 SEL s = (SEL) l->head;
401 if (types == 0 || s->sel_types == 0)
403 if (s->sel_types == types)
405 if (orig)
407 orig->sel_id = (void *) i;
408 return orig;
410 else
411 return s;
414 else if (! strcmp (s->sel_types, types))
416 if (orig)
418 orig->sel_id = (void *) i;
419 return orig;
421 else
422 return s;
425 if (orig)
426 j = orig;
427 else
428 j = pool_alloc_selector ();
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);
438 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
440 else
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 ();
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);
457 l = 0;
460 DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
461 (long) soffset_decode (i));
464 int is_new = (l == 0);
465 const char *new_name;
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);
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);
482 sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
484 return (SEL) j;
488 sel_registerName (const char *name)
490 SEL ret;
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);
498 return ret;
501 /* Traditional GNU Objective-C Runtime API. */
503 sel_register_name (const char *name)
505 return sel_registerName (name);
509 sel_registerTypedName (const char *name, const char *type)
511 SEL ret;
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);
519 return ret;
523 sel_register_typed_name (const char *name, const char *type)
525 return sel_registerTypedName (name, type);
528 /* return selector representing name */
530 sel_getUid (const char *name)
532 return sel_registerTypedName (name, 0);
535 /* Traditional GNU Objective-C Runtime API. */
537 sel_get_uid (const char *name)
539 return sel_getUid (name);