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
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/runtime.h"
28 #include "objc-private/hash.h"
29 #include "objc-private/objc-list.h"
30 #include "objc-private/module-abi-8.h"
31 #include "objc-private/runtime.h"
32 #include "objc-private/sarray.h"
33 #include "objc-private/selector.h"
34 #include <stdlib.h> /* For malloc. */
36 /* Initial selector hash table size. Value doesn't matter much. */
37 #define SELECTOR_HASH_SIZE 128
39 /* Tables mapping selector names to uid and opposite. */
40 static struct sarray *__objc_selector_array = 0; /* uid -> sel !T:MUTEX */
41 static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
42 static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */
44 /* Number of selectors stored in each of the above tables. */
45 unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */
47 /* Forward-declare an internal function. */
49 __sel_register_typed_name (const char *name, const char *types,
50 struct objc_selector *orig, BOOL is_const);
52 void __objc_init_selector_tables (void)
54 __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
55 __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
57 = objc_hash_new (SELECTOR_HASH_SIZE,
58 (hash_func_type) objc_hash_string,
59 (compare_func_type) objc_compare_strings);
62 /* Register a bunch of selectors from the table of selectors in a
63 module. 'selectors' should not be NULL. The list is terminated by
64 a selectors with a NULL sel_id. The selectors are assumed to
65 contain the 'name' in the sel_id field; this is replaced with the
66 final selector id after they are registered. */
68 __objc_register_selectors_from_module (struct objc_selector *selectors)
72 for (i = 0; selectors[i].sel_id; ++i)
74 const char *name, *type;
75 name = (char *) selectors[i].sel_id;
76 type = (char *) selectors[i].sel_types;
77 /* Constructors are constant static data and we can safely store
78 pointers to them in the runtime structures, so we set
80 __sel_register_typed_name (name, type, (struct objc_selector *) &(selectors[i]),
85 /* This routine is given a class and records all of the methods in its
86 class structure in the record table. */
88 __objc_register_selectors_from_class (Class class)
90 struct objc_method_list * method_list;
92 method_list = class->methods;
95 __objc_register_selectors_from_list (method_list);
96 method_list = method_list->method_next;
101 /* This routine is given a list of methods and records each of the
102 methods in the record table. This is the routine that does the
103 actual recording work.
105 The name and type pointers in the method list must be permanent and
108 __objc_register_selectors_from_list (struct objc_method_list *method_list)
112 objc_mutex_lock (__objc_runtime_mutex);
113 while (i < method_list->method_count)
115 Method method = &method_list->method_list[i];
116 if (method->method_name)
119 = __sel_register_typed_name ((const char *) method->method_name,
120 method->method_types, 0, YES);
124 objc_mutex_unlock (__objc_runtime_mutex);
127 /* The same as __objc_register_selectors_from_list, but works on a
128 struct objc_method_description_list* instead of a struct
129 objc_method_list*. This is only used for protocols, which have
130 lists of method descriptions, not methods. */
132 __objc_register_selectors_from_description_list
133 (struct objc_method_description_list *method_list)
137 objc_mutex_lock (__objc_runtime_mutex);
138 while (i < method_list->count)
140 struct objc_method_description *method = &method_list->list[i];
144 = __sel_register_typed_name ((const char *) method->name,
145 method->types, 0, YES);
149 objc_mutex_unlock (__objc_runtime_mutex);
152 /* Register instance methods as class methods for root classes. */
153 void __objc_register_instance_methods_to_class (Class class)
155 struct objc_method_list *method_list;
156 struct objc_method_list *class_method_list;
157 int max_methods_no = 16;
158 struct objc_method_list *new_list;
161 /* Only if a root class. */
162 if (class->super_class)
165 /* Allocate a method list to hold the new class methods. */
166 new_list = objc_calloc (sizeof (struct objc_method_list)
167 + sizeof (struct objc_method[max_methods_no]), 1);
168 method_list = class->methods;
169 class_method_list = class->class_pointer->methods;
170 curr_method = &new_list->method_list[0];
172 /* Iterate through the method lists for the class. */
177 /* Iterate through the methods from this method list. */
178 for (i = 0; i < method_list->method_count; i++)
180 Method mth = &method_list->method_list[i];
182 && ! search_for_method_in_list (class_method_list,
185 /* This instance method isn't a class method. Add it
186 into the new_list. */
189 /* Reallocate the method list if necessary. */
190 if (++new_list->method_count == max_methods_no)
192 objc_realloc (new_list, sizeof (struct objc_method_list)
194 objc_method[max_methods_no += 16]));
195 curr_method = &new_list->method_list[new_list->method_count];
199 method_list = method_list->method_next;
202 /* If we created any new class methods then attach the method list
204 if (new_list->method_count)
207 objc_realloc (new_list, sizeof (struct objc_method_list)
208 + sizeof (struct objc_method[new_list->method_count]));
209 new_list->method_next = class->class_pointer->methods;
210 class->class_pointer->methods = new_list;
215 __objc_update_dispatch_table_for_class (class->class_pointer);
219 sel_isEqual (SEL s1, SEL s2)
221 if (s1 == 0 || s2 == 0)
224 return s1->sel_id == s2->sel_id;
227 /* Return YES iff t1 and t2 have same method types. Ignore the
230 sel_types_match (const char *t1, const char *t2)
236 if (*t1 == '+') t1++;
237 if (*t2 == '+') t2++;
238 while (isdigit ((unsigned char) *t1)) t1++;
239 while (isdigit ((unsigned char) *t2)) t2++;
240 /* xxx Remove these next two lines when qualifiers are put in
241 all selectors, not just Protocol selectors. */
242 t1 = objc_skip_type_qualifiers (t1);
243 t2 = objc_skip_type_qualifiers (t2);
254 /* Return selector representing name. In the Modern API, you'd
255 normally use sel_registerTypedName() for this, which does the same
256 but would register the selector with the runtime if not registered
257 yet (if you only want to check for selectors without registering,
258 use sel_copyTypedSelectorList()). */
260 sel_get_typed_uid (const char *name, const char *types)
265 objc_mutex_lock (__objc_runtime_mutex);
267 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
270 objc_mutex_unlock (__objc_runtime_mutex);
274 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
277 SEL s = (SEL) l->head;
278 if (types == 0 || s->sel_types == 0)
280 if (s->sel_types == types)
282 objc_mutex_unlock (__objc_runtime_mutex);
286 else if (sel_types_match (s->sel_types, types))
288 objc_mutex_unlock (__objc_runtime_mutex);
293 objc_mutex_unlock (__objc_runtime_mutex);
297 /* Return selector representing name; prefer a selector with non-NULL
298 type. In the Modern API, sel_getTypedSelector() is similar but
299 returns NULL if a typed selector couldn't be found. */
301 sel_get_any_typed_uid (const char *name)
307 objc_mutex_lock (__objc_runtime_mutex);
309 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
312 objc_mutex_unlock (__objc_runtime_mutex);
316 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
322 objc_mutex_unlock (__objc_runtime_mutex);
327 objc_mutex_unlock (__objc_runtime_mutex);
331 /* Return selector representing name. */
333 sel_get_any_uid (const char *name)
338 objc_mutex_lock (__objc_runtime_mutex);
340 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
341 if (soffset_decode (i) == 0)
343 objc_mutex_unlock (__objc_runtime_mutex);
347 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
348 objc_mutex_unlock (__objc_runtime_mutex);
353 return (SEL) l->head;
357 sel_getTypedSelector (const char *name)
364 objc_mutex_lock (__objc_runtime_mutex);
366 /* Look for a typed selector. */
367 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
372 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
375 SEL s = (SEL) l->head;
378 objc_mutex_unlock (__objc_runtime_mutex);
384 /* No typed selector found. Return NULL. */
385 objc_mutex_unlock (__objc_runtime_mutex);
390 sel_copyTypedSelectorList (const char *name, unsigned int *numberOfReturnedSelectors)
392 unsigned int count = 0;
393 SEL *returnValue = NULL;
398 if (numberOfReturnedSelectors)
399 *numberOfReturnedSelectors = 0;
403 objc_mutex_lock (__objc_runtime_mutex);
405 /* Count how many selectors we have. */
406 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
409 struct objc_list *selector_list = NULL;
410 selector_list = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
412 /* Count how many selectors we have. */
415 for (l = selector_list; l; l = l->tail)
421 /* Allocate enough memory to hold them. */
422 returnValue = (SEL *)(malloc (sizeof (SEL) * (count + 1)));
424 /* Copy the selectors. */
427 for (j = 0; j < count; j++)
429 returnValue[j] = (SEL)(selector_list->head);
430 selector_list = selector_list->tail;
432 returnValue[j] = NULL;
437 objc_mutex_unlock (__objc_runtime_mutex);
439 if (numberOfReturnedSelectors)
440 *numberOfReturnedSelectors = count;
445 /* Get the name of a selector. If the selector is unknown, the empty
446 string "" is returned. */
447 const char *sel_getName (SEL selector)
451 if (selector == NULL)
452 return "<null selector>";
454 objc_mutex_lock (__objc_runtime_mutex);
455 if ((soffset_decode ((sidx)selector->sel_id) > 0)
456 && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
457 ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
460 objc_mutex_unlock (__objc_runtime_mutex);
464 /* Traditional GNU Objective-C Runtime API. */
465 const char *sel_get_name (SEL selector)
467 if (selector == NULL)
470 return sel_getName (selector);
474 sel_is_mapped (SEL selector)
476 unsigned int idx = soffset_decode ((sidx)selector->sel_id);
477 return ((idx > 0) && (idx <= __objc_selector_max_index));
480 const char *sel_getTypeEncoding (SEL selector)
483 return selector->sel_types;
488 /* Traditional GNU Objective-C Runtime API. */
489 const char *sel_get_type (SEL selector)
491 return sel_getTypeEncoding (selector);
494 /* The uninstalled dispatch table. */
495 extern struct sarray *__objc_uninstalled_dtable;
497 /* __sel_register_typed_name allocates lots of struct objc_selector:s
498 of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the
499 number of malloc calls and memory lost to malloc overhead, we
500 allocate objc_selector:s in blocks here. This is only called from
501 __sel_register_typed_name, and __sel_register_typed_name may only
502 be called when __objc_runtime_mutex is locked.
504 Note that the objc_selector:s allocated from
505 __sel_register_typed_name are never freed.
507 62 because 62 * sizeof (struct objc_selector) = 496 (992). This
508 should let malloc add some overhead and use a nice, round 512
509 (1024) byte chunk. */
510 #define SELECTOR_POOL_SIZE 62
511 static struct objc_selector *selector_pool;
512 static int selector_pool_left;
514 static struct objc_selector *
515 pool_alloc_selector(void)
517 if (!selector_pool_left)
519 selector_pool = objc_malloc (sizeof (struct objc_selector)
520 * SELECTOR_POOL_SIZE);
521 selector_pool_left = SELECTOR_POOL_SIZE;
523 return &selector_pool[--selector_pool_left];
526 /* Store the passed selector name in the selector record and return
527 its selector value (value returned by sel_get_uid). Assume that
528 the calling function has locked down __objc_runtime_mutex. The
529 'is_const' parameter tells us if the name and types parameters are
530 really constant or not. If YES then they are constant and we can
531 just store the pointers. If NO then we need to copy name and types
532 because the pointers may disappear later on. If the 'orig'
533 parameter is not NULL, then we are registering a selector from a
534 module, and 'orig' is that selector. In this case, we can put the
535 selector in the tables if needed, and orig->sel_id is updated with
536 the selector ID of the registered selector, and 'orig' is
539 __sel_register_typed_name (const char *name, const char *types,
540 struct objc_selector *orig, BOOL is_const)
542 struct objc_selector *j;
546 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
547 if (soffset_decode (i) != 0)
549 /* There are already selectors with that name. Examine them to
550 see if the one we're registering already exists. */
551 for (l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
554 SEL s = (SEL)l->head;
555 if (types == 0 || s->sel_types == 0)
557 if (s->sel_types == types)
561 orig->sel_id = (void *)i;
568 else if (! strcmp (s->sel_types, types))
572 orig->sel_id = (void *)i;
579 /* A selector with this specific name/type combination does not
580 exist yet. We need to register it. */
584 j = pool_alloc_selector ();
586 j->sel_id = (void *)i;
587 /* Can we use the pointer or must we copy types ? Don't copy if
589 if ((is_const) || (types == 0))
590 j->sel_types = types;
593 j->sel_types = (char *)objc_malloc (strlen (types) + 1);
594 strcpy ((char *)j->sel_types, types);
596 l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
600 /* There are no other selectors with this name registered in the
602 const char *new_name;
605 __objc_selector_max_index += 1;
606 i = soffset_encode (__objc_selector_max_index);
608 /* Prepare the selector. */
612 j = pool_alloc_selector ();
614 j->sel_id = (void *)i;
615 /* Can we use the pointer or must we copy types ? Don't copy if
617 if (is_const || (types == 0))
618 j->sel_types = types;
621 j->sel_types = (char *)objc_malloc (strlen (types) + 1);
622 strcpy ((char *)j->sel_types, types);
625 /* Since this is the first selector with this name, we need to
626 register the correspondence between 'i' (the sel_id) and
627 'name' (the actual string) in __objc_selector_names and
628 __objc_selector_hash. */
630 /* Can we use the pointer or must we copy name ? Don't copy if
631 NULL. (FIXME: Can the name really be NULL here ?) */
632 if (is_const || (name == 0))
636 new_name = (char *)objc_malloc (strlen (name) + 1);
637 strcpy ((char *)new_name, name);
640 /* This maps the sel_id to the name. */
641 sarray_at_put_safe (__objc_selector_names, i, (void *)new_name);
643 /* This maps the name to the sel_id. */
644 objc_hash_add (&__objc_selector_hash, (void *)new_name, (void *)i);
649 DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
650 (long)soffset_decode (i));
652 /* Now add the selector to the list of selectors with that id. */
653 l = list_cons ((void *)j, l);
654 sarray_at_put_safe (__objc_selector_array, i, (void *)l);
656 sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
662 sel_registerName (const char *name)
669 objc_mutex_lock (__objc_runtime_mutex);
670 /* Assume that name is not constant static memory and needs to be
671 copied before put into a runtime structure. is_const == NO. */
672 ret = __sel_register_typed_name (name, 0, 0, NO);
673 objc_mutex_unlock (__objc_runtime_mutex);
678 /* Traditional GNU Objective-C Runtime API. */
680 sel_register_name (const char *name)
682 return sel_registerName (name);
686 sel_registerTypedName (const char *name, const char *type)
693 objc_mutex_lock (__objc_runtime_mutex);
694 /* Assume that name and type are not constant static memory and need
695 to be copied before put into a runtime structure. is_const ==
697 ret = __sel_register_typed_name (name, type, 0, NO);
698 objc_mutex_unlock (__objc_runtime_mutex);
704 sel_register_typed_name (const char *name, const char *type)
706 return sel_registerTypedName (name, type);
709 /* Return the selector representing name. */
711 sel_getUid (const char *name)
713 return sel_registerTypedName (name, 0);
716 /* Traditional GNU Objective-C Runtime API. */
718 sel_get_uid (const char *name)
720 return sel_getUid (name);