]> gcc.gnu.org Git - gcc.git/blob - libobjc/selector.c
In libobjc/: 2010-12-19 Nicola Pero <nicola.pero@meta-innovation.com>
[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
35 /* Initial selector hash table size. Value doesn't matter much. */
36 #define SELECTOR_HASH_SIZE 128
37
38 /* Tables mapping selector names to uid and opposite. */
39 static struct sarray *__objc_selector_array = 0; /* uid -> sel !T:MUTEX */
40 static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
41 static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */
42
43 /* Number of selectors stored in each of the above tables. */
44 unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */
45
46 void __objc_init_selector_tables (void)
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
51 = objc_hash_new (SELECTOR_HASH_SIZE,
52 (hash_func_type) objc_hash_string,
53 (compare_func_type) objc_compare_strings);
54 }
55
56 /* This routine is given a class and records all of the methods in its
57 class structure in the record table. */
58 void
59 __objc_register_selectors_from_class (Class class)
60 {
61 struct objc_method_list * method_list;
62
63 method_list = class->methods;
64 while (method_list)
65 {
66 __objc_register_selectors_from_list (method_list);
67 method_list = method_list->method_next;
68 }
69 }
70
71
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.
75
76 The name and type pointers in the method list must be permanent and
77 immutable. */
78 void
79 __objc_register_selectors_from_list (struct objc_method_list *method_list)
80 {
81 int i = 0;
82
83 objc_mutex_lock (__objc_runtime_mutex);
84 while (i < method_list->method_count)
85 {
86 Method method = &method_list->method_list[i];
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 }
93 i += 1;
94 }
95 objc_mutex_unlock (__objc_runtime_mutex);
96 }
97
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
101 lists of method descriptions, not methods. */
102 void
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 }
122
123 /* Register instance methods as class methods for root classes. */
124 void __objc_register_instance_methods_to_class (Class class)
125 {
126 struct objc_method_list *method_list;
127 struct objc_method_list *class_method_list;
128 int max_methods_no = 16;
129 struct objc_method_list *new_list;
130 Method curr_method;
131
132 /* Only if a root class. */
133 if (class->super_class)
134 return;
135
136 /* Allocate a method list to hold the new class methods. */
137 new_list = objc_calloc (sizeof (struct objc_method_list)
138 + sizeof (struct objc_method[max_methods_no]), 1);
139 method_list = class->methods;
140 class_method_list = class->class_pointer->methods;
141 curr_method = &new_list->method_list[0];
142
143 /* Iterate through the method lists for the class. */
144 while (method_list)
145 {
146 int i;
147
148 /* Iterate through the methods from this method list. */
149 for (i = 0; i < method_list->method_count; i++)
150 {
151 Method mth = &method_list->method_list[i];
152 if (mth->method_name
153 && ! search_for_method_in_list (class_method_list,
154 mth->method_name))
155 {
156 /* This instance method isn't a class method. Add it
157 into the new_list. */
158 *curr_method = *mth;
159
160 /* Reallocate the method list if necessary. */
161 if (++new_list->method_count == max_methods_no)
162 new_list =
163 objc_realloc (new_list, sizeof (struct objc_method_list)
164 + sizeof (struct
165 objc_method[max_methods_no += 16]));
166 curr_method = &new_list->method_list[new_list->method_count];
167 }
168 }
169
170 method_list = method_list->method_next;
171 }
172
173 /* If we created any new class methods then attach the method list
174 to the class. */
175 if (new_list->method_count)
176 {
177 new_list =
178 objc_realloc (new_list, sizeof (struct objc_method_list)
179 + sizeof (struct objc_method[new_list->method_count]));
180 new_list->method_next = class->class_pointer->methods;
181 class->class_pointer->methods = new_list;
182 }
183 else
184 objc_free(new_list);
185
186 __objc_update_dispatch_table_for_class (class->class_pointer);
187 }
188
189 BOOL
190 sel_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 }
197
198 /* Return YES iff t1 and t2 have same method types. Ignore the
199 argframe layout. */
200 BOOL
201 sel_types_match (const char *t1, const char *t2)
202 {
203 if (! t1 || ! t2)
204 return NO;
205 while (*t1 && *t2)
206 {
207 if (*t1 == '+') t1++;
208 if (*t2 == '+') t2++;
209 while (isdigit ((unsigned char) *t1)) t1++;
210 while (isdigit ((unsigned char) *t2)) t2++;
211 /* xxx Remove these next two lines when qualifiers are put in
212 all selectors, not just Protocol selectors. */
213 t1 = objc_skip_type_qualifiers (t1);
214 t2 = objc_skip_type_qualifiers (t2);
215 if (! *t1 && ! *t2)
216 return YES;
217 if (*t1 != *t2)
218 return NO;
219 t1++;
220 t2++;
221 }
222 return NO;
223 }
224
225 /* Return selector representing name. */
226 SEL
227 sel_get_typed_uid (const char *name, const char *types)
228 {
229 struct objc_list *l;
230 sidx i;
231
232 objc_mutex_lock (__objc_runtime_mutex);
233
234 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
235 if (i == 0)
236 {
237 objc_mutex_unlock (__objc_runtime_mutex);
238 return 0;
239 }
240
241 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
242 l; l = l->tail)
243 {
244 SEL s = (SEL) l->head;
245 if (types == 0 || s->sel_types == 0)
246 {
247 if (s->sel_types == types)
248 {
249 objc_mutex_unlock (__objc_runtime_mutex);
250 return s;
251 }
252 }
253 else if (sel_types_match (s->sel_types, types))
254 {
255 objc_mutex_unlock (__objc_runtime_mutex);
256 return s;
257 }
258 }
259
260 objc_mutex_unlock (__objc_runtime_mutex);
261 return 0;
262 }
263
264 /* Return selector representing name; prefer a selector with non-NULL
265 type. */
266 SEL
267 sel_get_any_typed_uid (const char *name)
268 {
269 struct objc_list *l;
270 sidx i;
271 SEL s = NULL;
272
273 objc_mutex_lock (__objc_runtime_mutex);
274
275 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
276 if (i == 0)
277 {
278 objc_mutex_unlock (__objc_runtime_mutex);
279 return 0;
280 }
281
282 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
283 l; l = l->tail)
284 {
285 s = (SEL) l->head;
286 if (s->sel_types)
287 {
288 objc_mutex_unlock (__objc_runtime_mutex);
289 return s;
290 }
291 }
292
293 objc_mutex_unlock (__objc_runtime_mutex);
294 return s;
295 }
296
297 /* Return selector representing name. */
298 SEL
299 sel_get_any_uid (const char *name)
300 {
301 struct objc_list *l;
302 sidx i;
303
304 objc_mutex_lock (__objc_runtime_mutex);
305
306 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
307 if (soffset_decode (i) == 0)
308 {
309 objc_mutex_unlock (__objc_runtime_mutex);
310 return 0;
311 }
312
313 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
314 objc_mutex_unlock (__objc_runtime_mutex);
315
316 if (l == 0)
317 return 0;
318
319 return (SEL) l->head;
320 }
321
322 /* Get the name of a selector. If the selector is unknown, the empty
323 string "" is returned. */
324 const char *sel_getName (SEL selector)
325 {
326 const char *ret;
327
328 if (selector == NULL)
329 return "<null selector>";
330
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))
334 ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
335 else
336 ret = 0;
337 objc_mutex_unlock (__objc_runtime_mutex);
338 return ret;
339 }
340
341 /* Traditional GNU Objective-C Runtime API. */
342 const char *sel_get_name (SEL selector)
343 {
344 if (selector == NULL)
345 return 0;
346
347 return sel_getName (selector);
348 }
349
350 BOOL
351 sel_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
357 const char *sel_getType (SEL selector)
358 {
359 if (selector)
360 return selector->sel_types;
361 else
362 return 0;
363 }
364
365 /* Traditional GNU Objective-C Runtime API. */
366 const char *sel_get_type (SEL selector)
367 {
368 return sel_getType (selector);
369 }
370
371 /* The uninstalled dispatch table. */
372 extern struct sarray *__objc_uninstalled_dtable;
373
374 /* __sel_register_typed_name allocates lots of struct objc_selector:s
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. */
387 #define SELECTOR_POOL_SIZE 62
388 static struct objc_selector *selector_pool;
389 static int selector_pool_left;
390
391 static struct objc_selector *
392 pool_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
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. */
410 SEL
411 __sel_register_typed_name (const char *name, const char *types,
412 struct objc_selector *orig, BOOL is_const)
413 {
414 struct objc_selector *j;
415 sidx i;
416 struct objc_list *l;
417
418 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
419 if (soffset_decode (i) != 0)
420 {
421 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
422 l; l = l->tail)
423 {
424 SEL s = (SEL) l->head;
425 if (types == 0 || s->sel_types == 0)
426 {
427 if (s->sel_types == types)
428 {
429 if (orig)
430 {
431 orig->sel_id = (void *) i;
432 return orig;
433 }
434 else
435 return s;
436 }
437 }
438 else if (! strcmp (s->sel_types, types))
439 {
440 if (orig)
441 {
442 orig->sel_id = (void *) i;
443 return orig;
444 }
445 else
446 return s;
447 }
448 }
449 if (orig)
450 j = orig;
451 else
452 j = pool_alloc_selector ();
453
454 j->sel_id = (void *) i;
455 /* Can we use the pointer or must copy types? Don't copy if
456 NULL. */
457 if ((is_const) || (types == 0))
458 j->sel_types = (const char *) types;
459 else
460 {
461 j->sel_types = (char *) objc_malloc (strlen (types) + 1);
462 strcpy ((char *) j->sel_types, types);
463 }
464 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
465 }
466 else
467 {
468 __objc_selector_max_index += 1;
469 i = soffset_encode (__objc_selector_max_index);
470 if (orig)
471 j = orig;
472 else
473 j = pool_alloc_selector ();
474
475 j->sel_id = (void *) i;
476 /* Can we use the pointer or must copy types? Don't copy if
477 NULL. */
478 if ((is_const) || (types == 0))
479 j->sel_types = (const char *) types;
480 else
481 {
482 j->sel_types = (char *) objc_malloc (strlen (types) + 1);
483 strcpy ((char *) j->sel_types, types);
484 }
485 l = 0;
486 }
487
488 DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
489 (long) soffset_decode (i));
490
491 {
492 int is_new = (l == 0);
493 const char *new_name;
494
495 /* Can we use the pointer or must copy name? Don't copy if
496 NULL. */
497 if ((is_const) || (name == 0))
498 new_name = name;
499 else
500 {
501 new_name = (char *) objc_malloc (strlen (name) + 1);
502 strcpy ((char *) new_name, name);
503 }
504
505 l = list_cons ((void *) j, l);
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)
509 objc_hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
510 }
511
512 sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
513
514 return (SEL) j;
515 }
516
517 SEL
518 sel_registerName (const char *name)
519 {
520 SEL ret;
521
522 objc_mutex_lock (__objc_runtime_mutex);
523 /* Assume that name is not constant static memory and needs to be
524 copied before put into a runtime structure. is_const == NO. */
525 ret = __sel_register_typed_name (name, 0, 0, NO);
526 objc_mutex_unlock (__objc_runtime_mutex);
527
528 return ret;
529 }
530
531 /* Traditional GNU Objective-C Runtime API. */
532 SEL
533 sel_register_name (const char *name)
534 {
535 return sel_registerName (name);
536 }
537
538 SEL
539 sel_registerTypedName (const char *name, const char *type)
540 {
541 SEL ret;
542
543 objc_mutex_lock (__objc_runtime_mutex);
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. */
547 ret = __sel_register_typed_name (name, type, 0, NO);
548 objc_mutex_unlock (__objc_runtime_mutex);
549
550 return ret;
551 }
552
553 SEL
554 sel_register_typed_name (const char *name, const char *type)
555 {
556 return sel_registerTypedName (name, type);
557 }
558
559 /* Return the selector representing name. */
560 SEL
561 sel_getUid (const char *name)
562 {
563 return sel_registerTypedName (name, 0);
564 }
565
566 /* Traditional GNU Objective-C Runtime API. */
567 SEL
568 sel_get_uid (const char *name)
569 {
570 return sel_getUid (name);
571 }
This page took 0.062002 seconds and 5 git commands to generate.