]> gcc.gnu.org Git - gcc.git/blame - libobjc/selector.c
type_traits: Implement rank.
[gcc.git] / libobjc / selector.c
CommitLineData
88e17b57 1/* GNU Objective C Runtime selector related functions
435317e2 2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004 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
BE
8terms of the GNU General Public License as published by the Free Software
9Foundation; either version 2, or (at your option) any later version.
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
16You should have received a copy of the GNU General Public License along with
38709cad 17GCC; see the file COPYING. If not, write to the Free Software
88e17b57
BE
18Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20/* As a special exception, if you link this library with files compiled with
21 GCC to produce an executable, this does not cause the resulting executable
22 to be covered by the GNU General Public License. This exception does not
23 however invalidate any other reasons why the executable file might be
24 covered by the GNU General Public License. */
25
26#include "runtime.h"
bce1b489 27#include "sarray.h"
88e17b57
BE
28#include "encoding.h"
29
30/* Initial selector hash table size. Value doesn't matter much */
31#define SELECTOR_HASH_SIZE 128
32
33/* Tables mapping selector names to uid and opposite */
40165636
RB
34static struct sarray *__objc_selector_array = 0; /* uid -> sel !T:MUTEX */
35static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
88e17b57
BE
36static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */
37
88e17b57 38/* Number of selectors stored in each of the above tables */
b62cc13a 39unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */
88e17b57 40
40165636 41void __objc_init_selector_tables ()
88e17b57
BE
42{
43 __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
44 __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
45 __objc_selector_hash
46 = hash_new (SELECTOR_HASH_SIZE,
47 (hash_func_type) hash_string,
48 (compare_func_type) compare_strings);
49}
50
51/* This routine is given a class and records all of the methods in its class
52 structure in the record table. */
53void
54__objc_register_selectors_from_class (Class class)
55{
56 MethodList_t method_list;
57
58 method_list = class->methods;
59 while (method_list)
60 {
435317e2 61 __objc_register_selectors_from_list (method_list);
88e17b57
BE
62 method_list = method_list->method_next;
63 }
64}
65
66
67/* This routine is given a list of methods and records each of the methods in
68 the record table. This is the routine that does the actual recording
69 work.
70
435317e2
AP
71 The name and type pointers in the method list must be permanent and
72 immutable.
88e17b57 73 */
435317e2
AP
74void
75__objc_register_selectors_from_list (MethodList_t method_list)
88e17b57
BE
76{
77 int i = 0;
435317e2
AP
78
79 objc_mutex_lock (__objc_runtime_mutex);
88e17b57
BE
80 while (i < method_list->method_count)
81 {
82 Method_t method = &method_list->method_list[i];
435317e2
AP
83 if (method->method_name)
84 {
85 method->method_name
86 = __sel_register_typed_name ((const char *) method->method_name,
87 method->method_types, 0, YES);
88 }
88e17b57
BE
89 i += 1;
90 }
435317e2 91 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
92}
93
94
95/* Register instance methods as class methods for root classes */
40165636 96void __objc_register_instance_methods_to_class (Class class)
88e17b57
BE
97{
98 MethodList_t method_list;
99 MethodList_t class_method_list;
100 int max_methods_no = 16;
101 MethodList_t new_list;
102 Method_t curr_method;
103
104 /* Only if a root class. */
40165636 105 if (class->super_class)
88e17b57
BE
106 return;
107
108 /* Allocate a method list to hold the new class methods */
40165636
RB
109 new_list = objc_calloc (sizeof (struct objc_method_list)
110 + sizeof (struct objc_method[max_methods_no]), 1);
88e17b57
BE
111 method_list = class->methods;
112 class_method_list = class->class_pointer->methods;
113 curr_method = &new_list->method_list[0];
114
115 /* Iterate through the method lists for the class */
116 while (method_list)
117 {
118 int i;
119
120 /* Iterate through the methods from this method list */
121 for (i = 0; i < method_list->method_count; i++)
122 {
123 Method_t mth = &method_list->method_list[i];
124 if (mth->method_name
40165636 125 && ! search_for_method_in_list (class_method_list,
88e17b57
BE
126 mth->method_name))
127 {
128 /* This instance method isn't a class method.
129 Add it into the new_list. */
130 *curr_method = *mth;
131
132 /* Reallocate the method list if necessary */
40165636 133 if (++new_list->method_count == max_methods_no)
88e17b57 134 new_list =
40165636
RB
135 objc_realloc (new_list, sizeof (struct objc_method_list)
136 + sizeof (struct
88e17b57
BE
137 objc_method[max_methods_no += 16]));
138 curr_method = &new_list->method_list[new_list->method_count];
139 }
140 }
141
142 method_list = method_list->method_next;
143 }
144
145 /* If we created any new class methods
146 then attach the method list to the class */
147 if (new_list->method_count)
148 {
149 new_list =
40165636
RB
150 objc_realloc (new_list, sizeof (struct objc_method_list)
151 + sizeof (struct objc_method[new_list->method_count]));
88e17b57
BE
152 new_list->method_next = class->class_pointer->methods;
153 class->class_pointer->methods = new_list;
154 }
5af0e6ae
AF
155 else
156 objc_free(new_list);
88e17b57
BE
157
158 __objc_update_dispatch_table_for_class (class->class_pointer);
159}
160
161
162/* Returns YES iff t1 and t2 have same method types, but we ignore
163 the argframe layout */
164BOOL
40165636 165sel_types_match (const char *t1, const char *t2)
88e17b57 166{
40165636 167 if (! t1 || ! t2)
88e17b57
BE
168 return NO;
169 while (*t1 && *t2)
170 {
171 if (*t1 == '+') t1++;
172 if (*t2 == '+') t2++;
40165636
RB
173 while (isdigit ((unsigned char) *t1)) t1++;
174 while (isdigit ((unsigned char) *t2)) t2++;
88e17b57
BE
175 /* xxx Remove these next two lines when qualifiers are put in
176 all selectors, not just Protocol selectors. */
40165636
RB
177 t1 = objc_skip_type_qualifiers (t1);
178 t2 = objc_skip_type_qualifiers (t2);
179 if (! *t1 && ! *t2)
88e17b57
BE
180 return YES;
181 if (*t1 != *t2)
182 return NO;
183 t1++;
184 t2++;
185 }
186 return NO;
187}
188
189/* return selector representing name */
190SEL
191sel_get_typed_uid (const char *name, const char *types)
192{
193 struct objc_list *l;
194 sidx i;
195
40165636 196 objc_mutex_lock (__objc_runtime_mutex);
88e17b57
BE
197
198 i = (sidx) hash_value_for_key (__objc_selector_hash, name);
199 if (i == 0)
200 {
40165636 201 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
202 return 0;
203 }
204
40165636 205 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
88e17b57
BE
206 l; l = l->tail)
207 {
40165636 208 SEL s = (SEL) l->head;
88e17b57
BE
209 if (types == 0 || s->sel_types == 0)
210 {
211 if (s->sel_types == types)
212 {
40165636 213 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
214 return s;
215 }
216 }
217 else if (sel_types_match (s->sel_types, types))
218 {
40165636 219 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
220 return s;
221 }
222 }
223
40165636 224 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
225 return 0;
226}
227
228/* Return selector representing name; prefer a selector with non-NULL type */
229SEL
230sel_get_any_typed_uid (const char *name)
231{
232 struct objc_list *l;
233 sidx i;
234 SEL s = NULL;
235
40165636 236 objc_mutex_lock (__objc_runtime_mutex);
88e17b57
BE
237
238 i = (sidx) hash_value_for_key (__objc_selector_hash, name);
239 if (i == 0)
240 {
40165636 241 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
242 return 0;
243 }
244
40165636 245 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
88e17b57
BE
246 l; l = l->tail)
247 {
248 s = (SEL) l->head;
249 if (s->sel_types)
250 {
40165636 251 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
252 return s;
253 }
254 }
255
40165636 256 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
257 return s;
258}
259
260/* return selector representing name */
261SEL
262sel_get_any_uid (const char *name)
263{
264 struct objc_list *l;
265 sidx i;
266
40165636 267 objc_mutex_lock (__objc_runtime_mutex);
88e17b57
BE
268
269 i = (sidx) hash_value_for_key (__objc_selector_hash, name);
270 if (soffset_decode (i) == 0)
271 {
40165636 272 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
273 return 0;
274 }
275
40165636
RB
276 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
277 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
278
279 if (l == 0)
280 return 0;
281
40165636 282 return (SEL) l->head;
88e17b57
BE
283}
284
285/* return selector representing name */
286SEL
287sel_get_uid (const char *name)
288{
289 return sel_register_typed_name (name, 0);
290}
291
292/* Get name of selector. If selector is unknown, the empty string ""
293 is returned */
40165636 294const char *sel_get_name (SEL selector)
88e17b57
BE
295{
296 const char *ret;
297
40165636
RB
298 objc_mutex_lock (__objc_runtime_mutex);
299 if ((soffset_decode ((sidx)selector->sel_id) > 0)
300 && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
88e17b57
BE
301 ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
302 else
303 ret = 0;
40165636 304 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
305 return ret;
306}
307
308BOOL
309sel_is_mapped (SEL selector)
310{
311 unsigned int idx = soffset_decode ((sidx)selector->sel_id);
312 return ((idx > 0) && (idx <= __objc_selector_max_index));
313}
314
315
40165636 316const char *sel_get_type (SEL selector)
88e17b57
BE
317{
318 if (selector)
319 return selector->sel_types;
320 else
321 return 0;
322}
323
324/* The uninstalled dispatch table */
40165636 325extern struct sarray *__objc_uninstalled_dtable;
88e17b57 326
435317e2
AP
327/* __sel_register_typed_name allocates lots of struct objc_selector:s
328 of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the number
329 of malloc calls and memory lost to malloc overhead, we allocate
330 objc_selector:s in blocks here. This is only called from
331 __sel_register_typed_name, and __sel_register_typed_name may only be
332 called when __objc_runtime_mutex is locked.
333
334 Note that the objc_selector:s allocated from __sel_register_typed_name
335 are never freed.
336
337 62 because 62 * sizeof (struct objc_selector) = 496 (992). This should
338 let malloc add some overhead and use a nice, round 512 (1024) byte chunk.
339 */
340#define SELECTOR_POOL_SIZE 62
341static struct objc_selector *selector_pool;
342static int selector_pool_left;
343
344static struct objc_selector *
345pool_alloc_selector(void)
346{
347 if (!selector_pool_left)
348 {
349 selector_pool = objc_malloc (sizeof (struct objc_selector)
350 * SELECTOR_POOL_SIZE);
351 selector_pool_left = SELECTOR_POOL_SIZE;
352 }
353 return &selector_pool[--selector_pool_left];
354}
355
88e17b57
BE
356/* Store the passed selector name in the selector record and return its
357 selector value (value returned by sel_get_uid).
358 Assumes that the calling function has locked down __objc_runtime_mutex. */
359/* is_const parameter tells us if the name and types parameters
360 are really constant or not. If YES then they are constant and
361 we can just store the pointers. If NO then we need to copy
362 name and types because the pointers may disappear later on. */
363SEL
364__sel_register_typed_name (const char *name, const char *types,
365 struct objc_selector *orig, BOOL is_const)
366{
40165636 367 struct objc_selector *j;
88e17b57
BE
368 sidx i;
369 struct objc_list *l;
370
371 i = (sidx) hash_value_for_key (__objc_selector_hash, name);
372 if (soffset_decode (i) != 0)
373 {
40165636 374 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
88e17b57
BE
375 l; l = l->tail)
376 {
40165636 377 SEL s = (SEL) l->head;
88e17b57
BE
378 if (types == 0 || s->sel_types == 0)
379 {
380 if (s->sel_types == types)
381 {
382 if (orig)
383 {
40165636 384 orig->sel_id = (void *) i;
88e17b57
BE
385 return orig;
386 }
387 else
388 return s;
389 }
390 }
40165636 391 else if (! strcmp (s->sel_types, types))
88e17b57
BE
392 {
393 if (orig)
394 {
40165636 395 orig->sel_id = (void *) i;
88e17b57
BE
396 return orig;
397 }
398 else
399 return s;
400 }
401 }
402 if (orig)
403 j = orig;
404 else
435317e2 405 j = pool_alloc_selector ();
88e17b57 406
40165636 407 j->sel_id = (void *) i;
88e17b57
BE
408 /* Can we use the pointer or must copy types? Don't copy if NULL */
409 if ((is_const) || (types == 0))
40165636 410 j->sel_types = (const char *) types;
88e17b57 411 else {
40165636
RB
412 j->sel_types = (char *) objc_malloc (strlen (types) + 1);
413 strcpy ((char *) j->sel_types, types);
88e17b57 414 }
40165636 415 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
88e17b57
BE
416 }
417 else
418 {
419 __objc_selector_max_index += 1;
40165636 420 i = soffset_encode (__objc_selector_max_index);
88e17b57
BE
421 if (orig)
422 j = orig;
423 else
435317e2 424 j = pool_alloc_selector ();
88e17b57 425
40165636 426 j->sel_id = (void *) i;
88e17b57
BE
427 /* Can we use the pointer or must copy types? Don't copy if NULL */
428 if ((is_const) || (types == 0))
40165636 429 j->sel_types = (const char *) types;
88e17b57 430 else {
40165636
RB
431 j->sel_types = (char *) objc_malloc (strlen (types) + 1);
432 strcpy ((char *) j->sel_types, types);
88e17b57
BE
433 }
434 l = 0;
435 }
436
437 DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
435317e2 438 (long) soffset_decode (i));
88e17b57
BE
439
440 {
441 int is_new = (l == 0);
442 const char *new_name;
443
444 /* Can we use the pointer or must copy name? Don't copy if NULL */
445 if ((is_const) || (name == 0))
446 new_name = name;
447 else {
40165636
RB
448 new_name = (char *) objc_malloc (strlen (name) + 1);
449 strcpy ((char *) new_name, name);
88e17b57
BE
450 }
451
40165636 452 l = list_cons ((void *) j, l);
88e17b57
BE
453 sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
454 sarray_at_put_safe (__objc_selector_array, i, (void *) l);
455 if (is_new)
456 hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
457 }
458
40165636 459 sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
88e17b57
BE
460
461 return (SEL) j;
462}
463
464SEL
465sel_register_name (const char *name)
466{
467 SEL ret;
468
40165636 469 objc_mutex_lock (__objc_runtime_mutex);
88e17b57
BE
470 /* Assume that name is not constant static memory and needs to be
471 copied before put into a runtime structure. is_const == NO */
472 ret = __sel_register_typed_name (name, 0, 0, NO);
40165636 473 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
474
475 return ret;
476}
477
478SEL
479sel_register_typed_name (const char *name, const char *type)
480{
481 SEL ret;
435317e2 482
40165636 483 objc_mutex_lock (__objc_runtime_mutex);
88e17b57
BE
484 /* Assume that name and type are not constant static memory and need to
485 be copied before put into a runtime structure. is_const == NO */
486 ret = __sel_register_typed_name (name, type, 0, NO);
40165636 487 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
488
489 return ret;
490}
This page took 0.500703 seconds and 5 git commands to generate.