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