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