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