]> git.ipfire.org Git - thirdparty/gcc.git/blame - libobjc/selector.c
arm.c (require_pic_register): Set INSN_LOCATOR for all instructions injected into...
[thirdparty/gcc.git] / libobjc / selector.c
CommitLineData
88e17b57 1/* GNU Objective C Runtime selector related functions
748086b7 2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004, 2009 Free Software Foundation, Inc.
88e17b57
BE
3 Contributed by Kresten Krab Thorup
4
38709cad 5This file is part of GCC.
88e17b57 6
38709cad 7GCC is free software; you can redistribute it and/or modify it under the
88e17b57 8terms of the GNU General Public License as published by the Free Software
748086b7 9Foundation; either version 3, or (at your option) any later version.
88e17b57 10
38709cad 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
88e17b57
BE
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14details.
15
748086b7
JJ
16Under Section 7 of GPL version 3, you are granted additional
17permissions described in the GCC Runtime Library Exception, version
183.1, as published by the Free Software Foundation.
19
20You should have received a copy of the GNU General Public License and
21a copy of the GCC Runtime Library Exception along with this program;
22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23<http://www.gnu.org/licenses/>. */
88e17b57 24
6dead247 25#include "objc-private/common.h"
9ecfa8de 26#include "objc/runtime.h"
a19fac96 27#include "objc/thr.h"
5be9cdc1 28#include "objc-private/hash.h"
9ecfa8de
NP
29#include "objc-private/objc-list.h"
30#include "objc-private/module-abi-8.h"
a19fac96 31#include "objc-private/runtime.h"
5d3b14bd 32#include "objc-private/sarray.h"
1af5b8f5 33#include "objc-private/selector.h"
88e17b57 34
d4645ada 35/* Initial selector hash table size. Value doesn't matter much. */
88e17b57
BE
36#define SELECTOR_HASH_SIZE 128
37
d4645ada 38/* Tables mapping selector names to uid and opposite. */
40165636
RB
39static struct sarray *__objc_selector_array = 0; /* uid -> sel !T:MUTEX */
40static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
88e17b57
BE
41static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */
42
d4645ada 43/* Number of selectors stored in each of the above tables. */
b62cc13a 44unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */
88e17b57 45
600cbba2
NP
46/* Forward-declare an internal function. */
47static SEL
48__sel_register_typed_name (const char *name, const char *types,
49 struct objc_selector *orig, BOOL is_const);
50
64cbe55e 51void __objc_init_selector_tables (void)
88e17b57
BE
52{
53 __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
54 __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
55 __objc_selector_hash
270a1283
DA
56 = objc_hash_new (SELECTOR_HASH_SIZE,
57 (hash_func_type) objc_hash_string,
58 (compare_func_type) objc_compare_strings);
88e17b57
BE
59}
60
600cbba2
NP
61/* Register a bunch of selectors from the table of selectors in a
62 module. 'selectors' should not be NULL. The list is terminated by
63 a selectors with a NULL sel_id. The selectors are assumed to
64 contain the 'name' in the sel_id field; this is replaced with the
65 final selector id after they are registered. */
66void
67__objc_register_selectors_from_module (struct objc_selector *selectors)
68{
69 int i;
70
71 for (i = 0; selectors[i].sel_id; ++i)
72 {
73 const char *name, *type;
74 name = (char *) selectors[i].sel_id;
75 type = (char *) selectors[i].sel_types;
76 /* Constructors are constant static data and we can safely store
77 pointers to them in the runtime structures, so we set
78 is_const == YES. */
79 __sel_register_typed_name (name, type, (struct objc_selector *) &(selectors[i]),
80 /* is_const */ YES);
81 }
82}
83
d4645ada
NP
84/* This routine is given a class and records all of the methods in its
85 class structure in the record table. */
88e17b57
BE
86void
87__objc_register_selectors_from_class (Class class)
88{
9ecfa8de 89 struct objc_method_list * method_list;
88e17b57
BE
90
91 method_list = class->methods;
92 while (method_list)
93 {
435317e2 94 __objc_register_selectors_from_list (method_list);
88e17b57
BE
95 method_list = method_list->method_next;
96 }
97}
98
99
d4645ada
NP
100/* This routine is given a list of methods and records each of the
101 methods in the record table. This is the routine that does the
102 actual recording work.
88e17b57 103
435317e2 104 The name and type pointers in the method list must be permanent and
d4645ada 105 immutable. */
435317e2 106void
9ecfa8de 107__objc_register_selectors_from_list (struct objc_method_list *method_list)
88e17b57
BE
108{
109 int i = 0;
435317e2
AP
110
111 objc_mutex_lock (__objc_runtime_mutex);
88e17b57
BE
112 while (i < method_list->method_count)
113 {
9ecfa8de 114 Method method = &method_list->method_list[i];
435317e2
AP
115 if (method->method_name)
116 {
117 method->method_name
118 = __sel_register_typed_name ((const char *) method->method_name,
119 method->method_types, 0, YES);
120 }
88e17b57
BE
121 i += 1;
122 }
435317e2 123 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
124}
125
f7185d47
NP
126/* The same as __objc_register_selectors_from_list, but works on a
127 struct objc_method_description_list* instead of a struct
128 objc_method_list*. This is only used for protocols, which have
d4645ada 129 lists of method descriptions, not methods. */
f7185d47
NP
130void
131__objc_register_selectors_from_description_list
132(struct objc_method_description_list *method_list)
133{
134 int i = 0;
135
136 objc_mutex_lock (__objc_runtime_mutex);
137 while (i < method_list->count)
138 {
139 struct objc_method_description *method = &method_list->list[i];
140 if (method->name)
141 {
142 method->name
143 = __sel_register_typed_name ((const char *) method->name,
144 method->types, 0, YES);
145 }
146 i += 1;
147 }
148 objc_mutex_unlock (__objc_runtime_mutex);
149}
88e17b57 150
d4645ada 151/* Register instance methods as class methods for root classes. */
40165636 152void __objc_register_instance_methods_to_class (Class class)
88e17b57 153{
9ecfa8de
NP
154 struct objc_method_list *method_list;
155 struct objc_method_list *class_method_list;
88e17b57 156 int max_methods_no = 16;
9ecfa8de
NP
157 struct objc_method_list *new_list;
158 Method curr_method;
88e17b57
BE
159
160 /* Only if a root class. */
40165636 161 if (class->super_class)
88e17b57
BE
162 return;
163
d4645ada 164 /* Allocate a method list to hold the new class methods. */
40165636 165 new_list = objc_calloc (sizeof (struct objc_method_list)
d4645ada 166 + sizeof (struct objc_method[max_methods_no]), 1);
88e17b57
BE
167 method_list = class->methods;
168 class_method_list = class->class_pointer->methods;
169 curr_method = &new_list->method_list[0];
d4645ada
NP
170
171 /* Iterate through the method lists for the class. */
88e17b57
BE
172 while (method_list)
173 {
174 int i;
d4645ada
NP
175
176 /* Iterate through the methods from this method list. */
88e17b57
BE
177 for (i = 0; i < method_list->method_count; i++)
178 {
9ecfa8de 179 Method mth = &method_list->method_list[i];
88e17b57 180 if (mth->method_name
40165636 181 && ! search_for_method_in_list (class_method_list,
88e17b57
BE
182 mth->method_name))
183 {
d4645ada
NP
184 /* This instance method isn't a class method. Add it
185 into the new_list. */
88e17b57 186 *curr_method = *mth;
d4645ada
NP
187
188 /* Reallocate the method list if necessary. */
40165636 189 if (++new_list->method_count == max_methods_no)
88e17b57 190 new_list =
40165636
RB
191 objc_realloc (new_list, sizeof (struct objc_method_list)
192 + sizeof (struct
d4645ada 193 objc_method[max_methods_no += 16]));
88e17b57
BE
194 curr_method = &new_list->method_list[new_list->method_count];
195 }
196 }
197
198 method_list = method_list->method_next;
199 }
200
d4645ada
NP
201 /* If we created any new class methods then attach the method list
202 to the class. */
88e17b57
BE
203 if (new_list->method_count)
204 {
205 new_list =
40165636 206 objc_realloc (new_list, sizeof (struct objc_method_list)
d4645ada 207 + sizeof (struct objc_method[new_list->method_count]));
88e17b57
BE
208 new_list->method_next = class->class_pointer->methods;
209 class->class_pointer->methods = new_list;
210 }
5af0e6ae
AF
211 else
212 objc_free(new_list);
d4645ada
NP
213
214 __objc_update_dispatch_table_for_class (class->class_pointer);
88e17b57
BE
215}
216
debfbfee
NP
217BOOL
218sel_isEqual (SEL s1, SEL s2)
219{
220 if (s1 == 0 || s2 == 0)
221 return s1 == s2;
222 else
223 return s1->sel_id == s2->sel_id;
224}
88e17b57 225
d4645ada
NP
226/* Return YES iff t1 and t2 have same method types. Ignore the
227 argframe layout. */
88e17b57 228BOOL
40165636 229sel_types_match (const char *t1, const char *t2)
88e17b57 230{
40165636 231 if (! t1 || ! t2)
88e17b57
BE
232 return NO;
233 while (*t1 && *t2)
234 {
235 if (*t1 == '+') t1++;
236 if (*t2 == '+') t2++;
40165636
RB
237 while (isdigit ((unsigned char) *t1)) t1++;
238 while (isdigit ((unsigned char) *t2)) t2++;
88e17b57 239 /* xxx Remove these next two lines when qualifiers are put in
d4645ada 240 all selectors, not just Protocol selectors. */
40165636
RB
241 t1 = objc_skip_type_qualifiers (t1);
242 t2 = objc_skip_type_qualifiers (t2);
243 if (! *t1 && ! *t2)
88e17b57
BE
244 return YES;
245 if (*t1 != *t2)
246 return NO;
247 t1++;
248 t2++;
249 }
250 return NO;
251}
252
d4645ada 253/* Return selector representing name. */
88e17b57
BE
254SEL
255sel_get_typed_uid (const char *name, const char *types)
256{
257 struct objc_list *l;
258 sidx i;
259
40165636 260 objc_mutex_lock (__objc_runtime_mutex);
88e17b57 261
270a1283 262 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
88e17b57
BE
263 if (i == 0)
264 {
40165636 265 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
266 return 0;
267 }
268
40165636 269 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
88e17b57
BE
270 l; l = l->tail)
271 {
40165636 272 SEL s = (SEL) l->head;
88e17b57
BE
273 if (types == 0 || s->sel_types == 0)
274 {
275 if (s->sel_types == types)
276 {
40165636 277 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
278 return s;
279 }
280 }
281 else if (sel_types_match (s->sel_types, types))
282 {
40165636 283 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
284 return s;
285 }
286 }
287
40165636 288 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
289 return 0;
290}
291
d4645ada
NP
292/* Return selector representing name; prefer a selector with non-NULL
293 type. */
88e17b57
BE
294SEL
295sel_get_any_typed_uid (const char *name)
296{
297 struct objc_list *l;
298 sidx i;
299 SEL s = NULL;
300
40165636 301 objc_mutex_lock (__objc_runtime_mutex);
88e17b57 302
270a1283 303 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
88e17b57
BE
304 if (i == 0)
305 {
40165636 306 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
307 return 0;
308 }
309
40165636 310 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
88e17b57
BE
311 l; l = l->tail)
312 {
313 s = (SEL) l->head;
314 if (s->sel_types)
315 {
48d69c57
NP
316 objc_mutex_unlock (__objc_runtime_mutex);
317 return s;
88e17b57
BE
318 }
319 }
320
40165636 321 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
322 return s;
323}
324
d4645ada 325/* Return selector representing name. */
88e17b57
BE
326SEL
327sel_get_any_uid (const char *name)
328{
329 struct objc_list *l;
330 sidx i;
331
40165636 332 objc_mutex_lock (__objc_runtime_mutex);
88e17b57 333
270a1283 334 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
88e17b57
BE
335 if (soffset_decode (i) == 0)
336 {
40165636 337 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
338 return 0;
339 }
340
40165636
RB
341 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
342 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
343
344 if (l == 0)
345 return 0;
346
40165636 347 return (SEL) l->head;
88e17b57
BE
348}
349
d4645ada
NP
350/* Get the name of a selector. If the selector is unknown, the empty
351 string "" is returned. */
bc18535a 352const char *sel_getName (SEL selector)
88e17b57
BE
353{
354 const char *ret;
355
524660d2
NP
356 if (selector == NULL)
357 return "<null selector>";
d4645ada 358
40165636
RB
359 objc_mutex_lock (__objc_runtime_mutex);
360 if ((soffset_decode ((sidx)selector->sel_id) > 0)
361 && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
88e17b57
BE
362 ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
363 else
364 ret = 0;
40165636 365 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
366 return ret;
367}
368
bc18535a
NP
369/* Traditional GNU Objective-C Runtime API. */
370const char *sel_get_name (SEL selector)
371{
524660d2
NP
372 if (selector == NULL)
373 return 0;
374
bc18535a
NP
375 return sel_getName (selector);
376}
377
88e17b57
BE
378BOOL
379sel_is_mapped (SEL selector)
380{
381 unsigned int idx = soffset_decode ((sidx)selector->sel_id);
382 return ((idx > 0) && (idx <= __objc_selector_max_index));
383}
384
bc18535a 385const char *sel_getType (SEL selector)
88e17b57
BE
386{
387 if (selector)
388 return selector->sel_types;
389 else
390 return 0;
391}
392
bc18535a
NP
393/* Traditional GNU Objective-C Runtime API. */
394const char *sel_get_type (SEL selector)
395{
396 return sel_getType (selector);
397}
398
d4645ada 399/* The uninstalled dispatch table. */
40165636 400extern struct sarray *__objc_uninstalled_dtable;
88e17b57 401
435317e2 402/* __sel_register_typed_name allocates lots of struct objc_selector:s
d4645ada
NP
403 of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the
404 number of malloc calls and memory lost to malloc overhead, we
405 allocate objc_selector:s in blocks here. This is only called from
406 __sel_register_typed_name, and __sel_register_typed_name may only
407 be called when __objc_runtime_mutex is locked.
408
409 Note that the objc_selector:s allocated from
410 __sel_register_typed_name are never freed.
411
412 62 because 62 * sizeof (struct objc_selector) = 496 (992). This
413 should let malloc add some overhead and use a nice, round 512
414 (1024) byte chunk. */
435317e2
AP
415#define SELECTOR_POOL_SIZE 62
416static struct objc_selector *selector_pool;
417static int selector_pool_left;
418
419static struct objc_selector *
420pool_alloc_selector(void)
421{
422 if (!selector_pool_left)
423 {
424 selector_pool = objc_malloc (sizeof (struct objc_selector)
425 * SELECTOR_POOL_SIZE);
426 selector_pool_left = SELECTOR_POOL_SIZE;
427 }
428 return &selector_pool[--selector_pool_left];
429}
430
d4645ada
NP
431/* Store the passed selector name in the selector record and return
432 its selector value (value returned by sel_get_uid). Assume that
433 the calling function has locked down __objc_runtime_mutex. The
600cbba2 434 'is_const' parameter tells us if the name and types parameters are
d4645ada
NP
435 really constant or not. If YES then they are constant and we can
436 just store the pointers. If NO then we need to copy name and types
600cbba2
NP
437 because the pointers may disappear later on. If the 'orig'
438 parameter is not NULL, then we are registering a selector from a
439 module, and 'orig' is that selector. In this case, we can put the
440 selector in the tables if needed, and orig->sel_id is updated with
441 the selector ID of the registered selector, and 'orig' is
442 returned. */
443static SEL
88e17b57
BE
444__sel_register_typed_name (const char *name, const char *types,
445 struct objc_selector *orig, BOOL is_const)
446{
40165636 447 struct objc_selector *j;
88e17b57
BE
448 sidx i;
449 struct objc_list *l;
450
270a1283 451 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
88e17b57
BE
452 if (soffset_decode (i) != 0)
453 {
40165636 454 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
88e17b57
BE
455 l; l = l->tail)
456 {
40165636 457 SEL s = (SEL) l->head;
88e17b57
BE
458 if (types == 0 || s->sel_types == 0)
459 {
460 if (s->sel_types == types)
461 {
462 if (orig)
463 {
40165636 464 orig->sel_id = (void *) i;
88e17b57
BE
465 return orig;
466 }
467 else
468 return s;
469 }
470 }
40165636 471 else if (! strcmp (s->sel_types, types))
88e17b57
BE
472 {
473 if (orig)
474 {
40165636 475 orig->sel_id = (void *) i;
88e17b57
BE
476 return orig;
477 }
478 else
479 return s;
480 }
481 }
482 if (orig)
483 j = orig;
484 else
435317e2 485 j = pool_alloc_selector ();
d4645ada 486
40165636 487 j->sel_id = (void *) i;
d4645ada
NP
488 /* Can we use the pointer or must copy types? Don't copy if
489 NULL. */
88e17b57 490 if ((is_const) || (types == 0))
40165636 491 j->sel_types = (const char *) types;
d4645ada
NP
492 else
493 {
494 j->sel_types = (char *) objc_malloc (strlen (types) + 1);
495 strcpy ((char *) j->sel_types, types);
496 }
40165636 497 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
88e17b57
BE
498 }
499 else
500 {
501 __objc_selector_max_index += 1;
40165636 502 i = soffset_encode (__objc_selector_max_index);
88e17b57
BE
503 if (orig)
504 j = orig;
505 else
435317e2 506 j = pool_alloc_selector ();
d4645ada 507
40165636 508 j->sel_id = (void *) i;
d4645ada
NP
509 /* Can we use the pointer or must copy types? Don't copy if
510 NULL. */
88e17b57 511 if ((is_const) || (types == 0))
40165636 512 j->sel_types = (const char *) types;
d4645ada
NP
513 else
514 {
515 j->sel_types = (char *) objc_malloc (strlen (types) + 1);
516 strcpy ((char *) j->sel_types, types);
517 }
88e17b57
BE
518 l = 0;
519 }
520
521 DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
435317e2 522 (long) soffset_decode (i));
88e17b57
BE
523
524 {
525 int is_new = (l == 0);
526 const char *new_name;
527
d4645ada
NP
528 /* Can we use the pointer or must copy name? Don't copy if
529 NULL. */
88e17b57
BE
530 if ((is_const) || (name == 0))
531 new_name = name;
d4645ada
NP
532 else
533 {
534 new_name = (char *) objc_malloc (strlen (name) + 1);
535 strcpy ((char *) new_name, name);
536 }
537
40165636 538 l = list_cons ((void *) j, l);
88e17b57
BE
539 sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
540 sarray_at_put_safe (__objc_selector_array, i, (void *) l);
541 if (is_new)
270a1283 542 objc_hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
88e17b57 543 }
d4645ada 544
40165636 545 sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
d4645ada 546
88e17b57
BE
547 return (SEL) j;
548}
549
550SEL
bc18535a 551sel_registerName (const char *name)
88e17b57
BE
552{
553 SEL ret;
554
40165636 555 objc_mutex_lock (__objc_runtime_mutex);
88e17b57 556 /* Assume that name is not constant static memory and needs to be
d4645ada 557 copied before put into a runtime structure. is_const == NO. */
88e17b57 558 ret = __sel_register_typed_name (name, 0, 0, NO);
40165636 559 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
560
561 return ret;
562}
563
bc18535a 564/* Traditional GNU Objective-C Runtime API. */
88e17b57 565SEL
bc18535a
NP
566sel_register_name (const char *name)
567{
568 return sel_registerName (name);
569}
570
571SEL
572sel_registerTypedName (const char *name, const char *type)
88e17b57
BE
573{
574 SEL ret;
435317e2 575
40165636 576 objc_mutex_lock (__objc_runtime_mutex);
d4645ada
NP
577 /* Assume that name and type are not constant static memory and need
578 to be copied before put into a runtime structure. is_const ==
579 NO. */
88e17b57 580 ret = __sel_register_typed_name (name, type, 0, NO);
40165636 581 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
582
583 return ret;
584}
bc18535a
NP
585
586SEL
587sel_register_typed_name (const char *name, const char *type)
588{
589 return sel_registerTypedName (name, type);
590}
591
d4645ada 592/* Return the selector representing name. */
bc18535a
NP
593SEL
594sel_getUid (const char *name)
595{
596 return sel_registerTypedName (name, 0);
597}
598
599/* Traditional GNU Objective-C Runtime API. */
600SEL
601sel_get_uid (const char *name)
602{
603 return sel_getUid (name);
604}