]> git.ipfire.org Git - thirdparty/gcc.git/blob - libobjc/selector.c
In libobjc/: 2010-12-24 Nicola Pero <nicola.pero@meta-innovation.com>
[thirdparty/gcc.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/runtime.h"
27 #include "objc/thr.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. */
35
36 /* Initial selector hash table size. Value doesn't matter much. */
37 #define SELECTOR_HASH_SIZE 128
38
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 */
43
44 /* Number of selectors stored in each of the above tables. */
45 unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */
46
47 /* Forward-declare an internal function. */
48 static SEL
49 __sel_register_typed_name (const char *name, const char *types,
50 struct objc_selector *orig, BOOL is_const);
51
52 void __objc_init_selector_tables (void)
53 {
54 __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
55 __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
56 __objc_selector_hash
57 = objc_hash_new (SELECTOR_HASH_SIZE,
58 (hash_func_type) objc_hash_string,
59 (compare_func_type) objc_compare_strings);
60 }
61
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. */
67 void
68 __objc_register_selectors_from_module (struct objc_selector *selectors)
69 {
70 int i;
71
72 for (i = 0; selectors[i].sel_id; ++i)
73 {
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
79 is_const == YES. */
80 __sel_register_typed_name (name, type, (struct objc_selector *) &(selectors[i]),
81 /* is_const */ YES);
82 }
83 }
84
85 /* This routine is given a class and records all of the methods in its
86 class structure in the record table. */
87 void
88 __objc_register_selectors_from_class (Class class)
89 {
90 struct objc_method_list * method_list;
91
92 method_list = class->methods;
93 while (method_list)
94 {
95 __objc_register_selectors_from_list (method_list);
96 method_list = method_list->method_next;
97 }
98 }
99
100
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.
104
105 The name and type pointers in the method list must be permanent and
106 immutable. */
107 void
108 __objc_register_selectors_from_list (struct objc_method_list *method_list)
109 {
110 int i = 0;
111
112 objc_mutex_lock (__objc_runtime_mutex);
113 while (i < method_list->method_count)
114 {
115 Method method = &method_list->method_list[i];
116 if (method->method_name)
117 {
118 method->method_name
119 = __sel_register_typed_name ((const char *) method->method_name,
120 method->method_types, 0, YES);
121 }
122 i += 1;
123 }
124 objc_mutex_unlock (__objc_runtime_mutex);
125 }
126
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. */
131 void
132 __objc_register_selectors_from_description_list
133 (struct objc_method_description_list *method_list)
134 {
135 int i = 0;
136
137 objc_mutex_lock (__objc_runtime_mutex);
138 while (i < method_list->count)
139 {
140 struct objc_method_description *method = &method_list->list[i];
141 if (method->name)
142 {
143 method->name
144 = __sel_register_typed_name ((const char *) method->name,
145 method->types, 0, YES);
146 }
147 i += 1;
148 }
149 objc_mutex_unlock (__objc_runtime_mutex);
150 }
151
152 /* Register instance methods as class methods for root classes. */
153 void __objc_register_instance_methods_to_class (Class class)
154 {
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;
159 Method curr_method;
160
161 /* Only if a root class. */
162 if (class->super_class)
163 return;
164
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];
171
172 /* Iterate through the method lists for the class. */
173 while (method_list)
174 {
175 int i;
176
177 /* Iterate through the methods from this method list. */
178 for (i = 0; i < method_list->method_count; i++)
179 {
180 Method mth = &method_list->method_list[i];
181 if (mth->method_name
182 && ! search_for_method_in_list (class_method_list,
183 mth->method_name))
184 {
185 /* This instance method isn't a class method. Add it
186 into the new_list. */
187 *curr_method = *mth;
188
189 /* Reallocate the method list if necessary. */
190 if (++new_list->method_count == max_methods_no)
191 new_list =
192 objc_realloc (new_list, sizeof (struct objc_method_list)
193 + sizeof (struct
194 objc_method[max_methods_no += 16]));
195 curr_method = &new_list->method_list[new_list->method_count];
196 }
197 }
198
199 method_list = method_list->method_next;
200 }
201
202 /* If we created any new class methods then attach the method list
203 to the class. */
204 if (new_list->method_count)
205 {
206 new_list =
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;
211 }
212 else
213 objc_free(new_list);
214
215 __objc_update_dispatch_table_for_class (class->class_pointer);
216 }
217
218 BOOL
219 sel_isEqual (SEL s1, SEL s2)
220 {
221 if (s1 == 0 || s2 == 0)
222 return s1 == s2;
223 else
224 return s1->sel_id == s2->sel_id;
225 }
226
227 /* Return YES iff t1 and t2 have same method types. Ignore the
228 argframe layout. */
229 BOOL
230 sel_types_match (const char *t1, const char *t2)
231 {
232 if (! t1 || ! t2)
233 return NO;
234 while (*t1 && *t2)
235 {
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);
244 if (! *t1 && ! *t2)
245 return YES;
246 if (*t1 != *t2)
247 return NO;
248 t1++;
249 t2++;
250 }
251 return NO;
252 }
253
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()). */
259 SEL
260 sel_get_typed_uid (const char *name, const char *types)
261 {
262 struct objc_list *l;
263 sidx i;
264
265 objc_mutex_lock (__objc_runtime_mutex);
266
267 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
268 if (i == 0)
269 {
270 objc_mutex_unlock (__objc_runtime_mutex);
271 return 0;
272 }
273
274 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
275 l; l = l->tail)
276 {
277 SEL s = (SEL) l->head;
278 if (types == 0 || s->sel_types == 0)
279 {
280 if (s->sel_types == types)
281 {
282 objc_mutex_unlock (__objc_runtime_mutex);
283 return s;
284 }
285 }
286 else if (sel_types_match (s->sel_types, types))
287 {
288 objc_mutex_unlock (__objc_runtime_mutex);
289 return s;
290 }
291 }
292
293 objc_mutex_unlock (__objc_runtime_mutex);
294 return 0;
295 }
296
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. */
300 SEL
301 sel_get_any_typed_uid (const char *name)
302 {
303 struct objc_list *l;
304 sidx i;
305 SEL s = NULL;
306
307 objc_mutex_lock (__objc_runtime_mutex);
308
309 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
310 if (i == 0)
311 {
312 objc_mutex_unlock (__objc_runtime_mutex);
313 return 0;
314 }
315
316 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
317 l; l = l->tail)
318 {
319 s = (SEL) l->head;
320 if (s->sel_types)
321 {
322 objc_mutex_unlock (__objc_runtime_mutex);
323 return s;
324 }
325 }
326
327 objc_mutex_unlock (__objc_runtime_mutex);
328 return s;
329 }
330
331 /* Return selector representing name. */
332 SEL
333 sel_get_any_uid (const char *name)
334 {
335 struct objc_list *l;
336 sidx i;
337
338 objc_mutex_lock (__objc_runtime_mutex);
339
340 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
341 if (soffset_decode (i) == 0)
342 {
343 objc_mutex_unlock (__objc_runtime_mutex);
344 return 0;
345 }
346
347 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
348 objc_mutex_unlock (__objc_runtime_mutex);
349
350 if (l == 0)
351 return 0;
352
353 return (SEL) l->head;
354 }
355
356 SEL
357 sel_getTypedSelector (const char *name)
358 {
359 sidx i;
360 objc_mutex_lock (__objc_runtime_mutex);
361
362 /* Look for a typed selector. */
363 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
364 if (i != 0)
365 {
366 struct objc_list *l;
367
368 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
369 l; l = l->tail)
370 {
371 SEL s = (SEL) l->head;
372 if (s->sel_types)
373 {
374 objc_mutex_unlock (__objc_runtime_mutex);
375 return s;
376 }
377 }
378 }
379
380 /* No typed selector found. Return NULL. */
381 objc_mutex_unlock (__objc_runtime_mutex);
382 return 0;
383 }
384
385 SEL *
386 sel_copyTypedSelectorList (const char *name, unsigned int *numberOfReturnedSelectors)
387 {
388 unsigned int count = 0;
389 SEL *returnValue = NULL;
390 sidx i;
391
392 if (name == NULL)
393 {
394 if (numberOfReturnedSelectors)
395 *numberOfReturnedSelectors = 0;
396 return NULL;
397 }
398
399 objc_mutex_lock (__objc_runtime_mutex);
400
401 /* Count how many selectors we have. */
402 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
403 if (i != 0)
404 {
405 struct objc_list *selector_list = NULL;
406 selector_list = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
407
408 /* Count how many selectors we have. */
409 {
410 struct objc_list *l;
411 for (l = selector_list; l; l = l->tail)
412 count++;
413 }
414
415 if (count != 0)
416 {
417 /* Allocate enough memory to hold them. */
418 returnValue = (SEL *)(malloc (sizeof (SEL) * (count + 1)));
419
420 /* Copy the selectors. */
421 {
422 unsigned int j;
423 for (j = 0; j < count; j++)
424 {
425 returnValue[j] = (SEL)(selector_list->head);
426 selector_list = selector_list->tail;
427 }
428 returnValue[j] = NULL;
429 }
430 }
431 }
432
433 objc_mutex_unlock (__objc_runtime_mutex);
434
435 if (numberOfReturnedSelectors)
436 *numberOfReturnedSelectors = count;
437
438 return returnValue;
439 }
440
441 /* Get the name of a selector. If the selector is unknown, the empty
442 string "" is returned. */
443 const char *sel_getName (SEL selector)
444 {
445 const char *ret;
446
447 if (selector == NULL)
448 return "<null selector>";
449
450 objc_mutex_lock (__objc_runtime_mutex);
451 if ((soffset_decode ((sidx)selector->sel_id) > 0)
452 && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
453 ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
454 else
455 ret = 0;
456 objc_mutex_unlock (__objc_runtime_mutex);
457 return ret;
458 }
459
460 /* Traditional GNU Objective-C Runtime API. */
461 const char *sel_get_name (SEL selector)
462 {
463 if (selector == NULL)
464 return 0;
465
466 return sel_getName (selector);
467 }
468
469 BOOL
470 sel_is_mapped (SEL selector)
471 {
472 unsigned int idx = soffset_decode ((sidx)selector->sel_id);
473 return ((idx > 0) && (idx <= __objc_selector_max_index));
474 }
475
476 const char *sel_getTypeEncoding (SEL selector)
477 {
478 if (selector)
479 return selector->sel_types;
480 else
481 return 0;
482 }
483
484 /* Traditional GNU Objective-C Runtime API. */
485 const char *sel_get_type (SEL selector)
486 {
487 return sel_getTypeEncoding (selector);
488 }
489
490 /* The uninstalled dispatch table. */
491 extern struct sarray *__objc_uninstalled_dtable;
492
493 /* __sel_register_typed_name allocates lots of struct objc_selector:s
494 of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the
495 number of malloc calls and memory lost to malloc overhead, we
496 allocate objc_selector:s in blocks here. This is only called from
497 __sel_register_typed_name, and __sel_register_typed_name may only
498 be called when __objc_runtime_mutex is locked.
499
500 Note that the objc_selector:s allocated from
501 __sel_register_typed_name are never freed.
502
503 62 because 62 * sizeof (struct objc_selector) = 496 (992). This
504 should let malloc add some overhead and use a nice, round 512
505 (1024) byte chunk. */
506 #define SELECTOR_POOL_SIZE 62
507 static struct objc_selector *selector_pool;
508 static int selector_pool_left;
509
510 static struct objc_selector *
511 pool_alloc_selector(void)
512 {
513 if (!selector_pool_left)
514 {
515 selector_pool = objc_malloc (sizeof (struct objc_selector)
516 * SELECTOR_POOL_SIZE);
517 selector_pool_left = SELECTOR_POOL_SIZE;
518 }
519 return &selector_pool[--selector_pool_left];
520 }
521
522 /* Store the passed selector name in the selector record and return
523 its selector value (value returned by sel_get_uid). Assume that
524 the calling function has locked down __objc_runtime_mutex. The
525 'is_const' parameter tells us if the name and types parameters are
526 really constant or not. If YES then they are constant and we can
527 just store the pointers. If NO then we need to copy name and types
528 because the pointers may disappear later on. If the 'orig'
529 parameter is not NULL, then we are registering a selector from a
530 module, and 'orig' is that selector. In this case, we can put the
531 selector in the tables if needed, and orig->sel_id is updated with
532 the selector ID of the registered selector, and 'orig' is
533 returned. */
534 static SEL
535 __sel_register_typed_name (const char *name, const char *types,
536 struct objc_selector *orig, BOOL is_const)
537 {
538 struct objc_selector *j;
539 sidx i;
540 struct objc_list *l;
541
542 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
543 if (soffset_decode (i) != 0)
544 {
545 /* There are already selectors with that name. Examine them to
546 see if the one we're registering already exists. */
547 for (l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
548 l; l = l->tail)
549 {
550 SEL s = (SEL)l->head;
551 if (types == 0 || s->sel_types == 0)
552 {
553 if (s->sel_types == types)
554 {
555 if (orig)
556 {
557 orig->sel_id = (void *)i;
558 return orig;
559 }
560 else
561 return s;
562 }
563 }
564 else if (! strcmp (s->sel_types, types))
565 {
566 if (orig)
567 {
568 orig->sel_id = (void *)i;
569 return orig;
570 }
571 else
572 return s;
573 }
574 }
575 /* A selector with this specific name/type combination does not
576 exist yet. We need to register it. */
577 if (orig)
578 j = orig;
579 else
580 j = pool_alloc_selector ();
581
582 j->sel_id = (void *)i;
583 /* Can we use the pointer or must we copy types ? Don't copy if
584 NULL. */
585 if ((is_const) || (types == 0))
586 j->sel_types = types;
587 else
588 {
589 j->sel_types = (char *)objc_malloc (strlen (types) + 1);
590 strcpy ((char *)j->sel_types, types);
591 }
592 l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
593 }
594 else
595 {
596 /* There are no other selectors with this name registered in the
597 runtime tables. */
598 const char *new_name;
599
600 /* Determine i. */
601 __objc_selector_max_index += 1;
602 i = soffset_encode (__objc_selector_max_index);
603
604 /* Prepare the selector. */
605 if (orig)
606 j = orig;
607 else
608 j = pool_alloc_selector ();
609
610 j->sel_id = (void *)i;
611 /* Can we use the pointer or must we copy types ? Don't copy if
612 NULL. */
613 if (is_const || (types == 0))
614 j->sel_types = types;
615 else
616 {
617 j->sel_types = (char *)objc_malloc (strlen (types) + 1);
618 strcpy ((char *)j->sel_types, types);
619 }
620
621 /* Since this is the first selector with this name, we need to
622 register the correspondence between 'i' (the sel_id) and
623 'name' (the actual string) in __objc_selector_names and
624 __objc_selector_hash. */
625
626 /* Can we use the pointer or must we copy name ? Don't copy if
627 NULL. (FIXME: Can the name really be NULL here ?) */
628 if (is_const || (name == 0))
629 new_name = name;
630 else
631 {
632 new_name = (char *)objc_malloc (strlen (name) + 1);
633 strcpy ((char *)new_name, name);
634 }
635
636 /* This maps the sel_id to the name. */
637 sarray_at_put_safe (__objc_selector_names, i, (void *)new_name);
638
639 /* This maps the name to the sel_id. */
640 objc_hash_add (&__objc_selector_hash, (void *)new_name, (void *)i);
641
642 l = 0;
643 }
644
645 DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
646 (long)soffset_decode (i));
647
648 /* Now add the selector to the list of selectors with that id. */
649 l = list_cons ((void *)j, l);
650 sarray_at_put_safe (__objc_selector_array, i, (void *)l);
651
652 sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
653
654 return (SEL)j;
655 }
656
657 SEL
658 sel_registerName (const char *name)
659 {
660 SEL ret;
661
662 objc_mutex_lock (__objc_runtime_mutex);
663 /* Assume that name is not constant static memory and needs to be
664 copied before put into a runtime structure. is_const == NO. */
665 ret = __sel_register_typed_name (name, 0, 0, NO);
666 objc_mutex_unlock (__objc_runtime_mutex);
667
668 return ret;
669 }
670
671 /* Traditional GNU Objective-C Runtime API. */
672 SEL
673 sel_register_name (const char *name)
674 {
675 return sel_registerName (name);
676 }
677
678 SEL
679 sel_registerTypedName (const char *name, const char *type)
680 {
681 SEL ret;
682
683 objc_mutex_lock (__objc_runtime_mutex);
684 /* Assume that name and type are not constant static memory and need
685 to be copied before put into a runtime structure. is_const ==
686 NO. */
687 ret = __sel_register_typed_name (name, type, 0, NO);
688 objc_mutex_unlock (__objc_runtime_mutex);
689
690 return ret;
691 }
692
693 SEL
694 sel_register_typed_name (const char *name, const char *type)
695 {
696 return sel_registerTypedName (name, type);
697 }
698
699 /* Return the selector representing name. */
700 SEL
701 sel_getUid (const char *name)
702 {
703 return sel_registerTypedName (name, 0);
704 }
705
706 /* Traditional GNU Objective-C Runtime API. */
707 SEL
708 sel_get_uid (const char *name)
709 {
710 return sel_getUid (name);
711 }