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
5 This file is part of GCC.
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.
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
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.
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/>. */
25 #include "objc-private/common.h"
26 #include "objc/objc.h"
27 #include "objc/objc-api.h"
29 #include "objc-private/hash.h"
30 #include "objc-private/objc-list.h"
31 #include "objc-private/runtime.h"
32 #include "objc-private/sarray.h"
33 #include "objc/encoding.h"
35 /* Initial selector hash table size. Value doesn't matter much */
36 #define SELECTOR_HASH_SIZE 128
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 */
43 /* Number of selectors stored in each of the above tables */
44 unsigned int __objc_selector_max_index
= 0; /* !T:MUTEX */
46 void __objc_init_selector_tables (void)
48 __objc_selector_array
= sarray_new (SELECTOR_HASH_SIZE
, 0);
49 __objc_selector_names
= sarray_new (SELECTOR_HASH_SIZE
, 0);
51 = objc_hash_new (SELECTOR_HASH_SIZE
,
52 (hash_func_type
) objc_hash_string
,
53 (compare_func_type
) objc_compare_strings
);
56 /* This routine is given a class and records all of the methods in its class
57 structure in the record table. */
59 __objc_register_selectors_from_class (Class
class)
61 MethodList_t method_list
;
63 method_list
= class->methods
;
66 __objc_register_selectors_from_list (method_list
);
67 method_list
= method_list
->method_next
;
72 /* This routine is given a list of methods and records each of the methods in
73 the record table. This is the routine that does the actual recording
76 The name and type pointers in the method list must be permanent and
80 __objc_register_selectors_from_list (MethodList_t method_list
)
84 objc_mutex_lock (__objc_runtime_mutex
);
85 while (i
< method_list
->method_count
)
87 Method_t method
= &method_list
->method_list
[i
];
88 if (method
->method_name
)
91 = __sel_register_typed_name ((const char *) method
->method_name
,
92 method
->method_types
, 0, YES
);
96 objc_mutex_unlock (__objc_runtime_mutex
);
100 /* Register instance methods as class methods for root classes */
101 void __objc_register_instance_methods_to_class (Class
class)
103 MethodList_t method_list
;
104 MethodList_t class_method_list
;
105 int max_methods_no
= 16;
106 MethodList_t new_list
;
107 Method_t curr_method
;
109 /* Only if a root class. */
110 if (class->super_class
)
113 /* Allocate a method list to hold the new class methods */
114 new_list
= objc_calloc (sizeof (struct objc_method_list
)
115 + sizeof (struct objc_method
[max_methods_no
]), 1);
116 method_list
= class->methods
;
117 class_method_list
= class->class_pointer
->methods
;
118 curr_method
= &new_list
->method_list
[0];
120 /* Iterate through the method lists for the class */
125 /* Iterate through the methods from this method list */
126 for (i
= 0; i
< method_list
->method_count
; i
++)
128 Method_t mth
= &method_list
->method_list
[i
];
130 && ! search_for_method_in_list (class_method_list
,
133 /* This instance method isn't a class method.
134 Add it into the new_list. */
137 /* Reallocate the method list if necessary */
138 if (++new_list
->method_count
== max_methods_no
)
140 objc_realloc (new_list
, sizeof (struct objc_method_list
)
142 objc_method
[max_methods_no
+= 16]));
143 curr_method
= &new_list
->method_list
[new_list
->method_count
];
147 method_list
= method_list
->method_next
;
150 /* If we created any new class methods
151 then attach the method list to the class */
152 if (new_list
->method_count
)
155 objc_realloc (new_list
, sizeof (struct objc_method_list
)
156 + sizeof (struct objc_method
[new_list
->method_count
]));
157 new_list
->method_next
= class->class_pointer
->methods
;
158 class->class_pointer
->methods
= new_list
;
163 __objc_update_dispatch_table_for_class (class->class_pointer
);
167 /* Returns YES iff t1 and t2 have same method types, but we ignore
168 the argframe layout */
170 sel_types_match (const char *t1
, const char *t2
)
176 if (*t1
== '+') t1
++;
177 if (*t2
== '+') t2
++;
178 while (isdigit ((unsigned char) *t1
)) t1
++;
179 while (isdigit ((unsigned char) *t2
)) t2
++;
180 /* xxx Remove these next two lines when qualifiers are put in
181 all selectors, not just Protocol selectors. */
182 t1
= objc_skip_type_qualifiers (t1
);
183 t2
= objc_skip_type_qualifiers (t2
);
194 /* return selector representing name */
196 sel_get_typed_uid (const char *name
, const char *types
)
201 objc_mutex_lock (__objc_runtime_mutex
);
203 i
= (sidx
) objc_hash_value_for_key (__objc_selector_hash
, name
);
206 objc_mutex_unlock (__objc_runtime_mutex
);
210 for (l
= (struct objc_list
*) sarray_get_safe (__objc_selector_array
, i
);
213 SEL s
= (SEL
) l
->head
;
214 if (types
== 0 || s
->sel_types
== 0)
216 if (s
->sel_types
== types
)
218 objc_mutex_unlock (__objc_runtime_mutex
);
222 else if (sel_types_match (s
->sel_types
, types
))
224 objc_mutex_unlock (__objc_runtime_mutex
);
229 objc_mutex_unlock (__objc_runtime_mutex
);
233 /* Return selector representing name; prefer a selector with non-NULL type */
235 sel_get_any_typed_uid (const char *name
)
241 objc_mutex_lock (__objc_runtime_mutex
);
243 i
= (sidx
) objc_hash_value_for_key (__objc_selector_hash
, name
);
246 objc_mutex_unlock (__objc_runtime_mutex
);
250 for (l
= (struct objc_list
*) sarray_get_safe (__objc_selector_array
, i
);
256 objc_mutex_unlock (__objc_runtime_mutex
);
261 objc_mutex_unlock (__objc_runtime_mutex
);
265 /* return selector representing name */
267 sel_get_any_uid (const char *name
)
272 objc_mutex_lock (__objc_runtime_mutex
);
274 i
= (sidx
) objc_hash_value_for_key (__objc_selector_hash
, name
);
275 if (soffset_decode (i
) == 0)
277 objc_mutex_unlock (__objc_runtime_mutex
);
281 l
= (struct objc_list
*) sarray_get_safe (__objc_selector_array
, i
);
282 objc_mutex_unlock (__objc_runtime_mutex
);
287 return (SEL
) l
->head
;
290 /* return selector representing name */
292 sel_get_uid (const char *name
)
294 return sel_register_typed_name (name
, 0);
297 /* Get name of selector. If selector is unknown, the empty string ""
299 const char *sel_get_name (SEL selector
)
303 objc_mutex_lock (__objc_runtime_mutex
);
304 if ((soffset_decode ((sidx
)selector
->sel_id
) > 0)
305 && (soffset_decode ((sidx
)selector
->sel_id
) <= __objc_selector_max_index
))
306 ret
= sarray_get_safe (__objc_selector_names
, (sidx
) selector
->sel_id
);
309 objc_mutex_unlock (__objc_runtime_mutex
);
314 sel_is_mapped (SEL selector
)
316 unsigned int idx
= soffset_decode ((sidx
)selector
->sel_id
);
317 return ((idx
> 0) && (idx
<= __objc_selector_max_index
));
321 const char *sel_get_type (SEL selector
)
324 return selector
->sel_types
;
329 /* The uninstalled dispatch table */
330 extern struct sarray
*__objc_uninstalled_dtable
;
332 /* __sel_register_typed_name allocates lots of struct objc_selector:s
333 of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the number
334 of malloc calls and memory lost to malloc overhead, we allocate
335 objc_selector:s in blocks here. This is only called from
336 __sel_register_typed_name, and __sel_register_typed_name may only be
337 called when __objc_runtime_mutex is locked.
339 Note that the objc_selector:s allocated from __sel_register_typed_name
342 62 because 62 * sizeof (struct objc_selector) = 496 (992). This should
343 let malloc add some overhead and use a nice, round 512 (1024) byte chunk.
345 #define SELECTOR_POOL_SIZE 62
346 static struct objc_selector
*selector_pool
;
347 static int selector_pool_left
;
349 static struct objc_selector
*
350 pool_alloc_selector(void)
352 if (!selector_pool_left
)
354 selector_pool
= objc_malloc (sizeof (struct objc_selector
)
355 * SELECTOR_POOL_SIZE
);
356 selector_pool_left
= SELECTOR_POOL_SIZE
;
358 return &selector_pool
[--selector_pool_left
];
361 /* Store the passed selector name in the selector record and return its
362 selector value (value returned by sel_get_uid).
363 Assumes that the calling function has locked down __objc_runtime_mutex. */
364 /* is_const parameter tells us if the name and types parameters
365 are really constant or not. If YES then they are constant and
366 we can just store the pointers. If NO then we need to copy
367 name and types because the pointers may disappear later on. */
369 __sel_register_typed_name (const char *name
, const char *types
,
370 struct objc_selector
*orig
, BOOL is_const
)
372 struct objc_selector
*j
;
376 i
= (sidx
) objc_hash_value_for_key (__objc_selector_hash
, name
);
377 if (soffset_decode (i
) != 0)
379 for (l
= (struct objc_list
*) sarray_get_safe (__objc_selector_array
, i
);
382 SEL s
= (SEL
) l
->head
;
383 if (types
== 0 || s
->sel_types
== 0)
385 if (s
->sel_types
== types
)
389 orig
->sel_id
= (void *) i
;
396 else if (! strcmp (s
->sel_types
, types
))
400 orig
->sel_id
= (void *) i
;
410 j
= pool_alloc_selector ();
412 j
->sel_id
= (void *) i
;
413 /* Can we use the pointer or must copy types? Don't copy if NULL */
414 if ((is_const
) || (types
== 0))
415 j
->sel_types
= (const char *) types
;
417 j
->sel_types
= (char *) objc_malloc (strlen (types
) + 1);
418 strcpy ((char *) j
->sel_types
, types
);
420 l
= (struct objc_list
*) sarray_get_safe (__objc_selector_array
, i
);
424 __objc_selector_max_index
+= 1;
425 i
= soffset_encode (__objc_selector_max_index
);
429 j
= pool_alloc_selector ();
431 j
->sel_id
= (void *) i
;
432 /* Can we use the pointer or must copy types? Don't copy if NULL */
433 if ((is_const
) || (types
== 0))
434 j
->sel_types
= (const char *) types
;
436 j
->sel_types
= (char *) objc_malloc (strlen (types
) + 1);
437 strcpy ((char *) j
->sel_types
, types
);
442 DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name
, types
,
443 (long) soffset_decode (i
));
446 int is_new
= (l
== 0);
447 const char *new_name
;
449 /* Can we use the pointer or must copy name? Don't copy if NULL */
450 if ((is_const
) || (name
== 0))
453 new_name
= (char *) objc_malloc (strlen (name
) + 1);
454 strcpy ((char *) new_name
, name
);
457 l
= list_cons ((void *) j
, l
);
458 sarray_at_put_safe (__objc_selector_names
, i
, (void *) new_name
);
459 sarray_at_put_safe (__objc_selector_array
, i
, (void *) l
);
461 objc_hash_add (&__objc_selector_hash
, (void *) new_name
, (void *) i
);
464 sarray_realloc (__objc_uninstalled_dtable
, __objc_selector_max_index
+ 1);
470 sel_register_name (const char *name
)
474 objc_mutex_lock (__objc_runtime_mutex
);
475 /* Assume that name is not constant static memory and needs to be
476 copied before put into a runtime structure. is_const == NO */
477 ret
= __sel_register_typed_name (name
, 0, 0, NO
);
478 objc_mutex_unlock (__objc_runtime_mutex
);
484 sel_register_typed_name (const char *name
, const char *type
)
488 objc_mutex_lock (__objc_runtime_mutex
);
489 /* Assume that name and type are not constant static memory and need to
490 be copied before put into a runtime structure. is_const == NO */
491 ret
= __sel_register_typed_name (name
, type
, 0, NO
);
492 objc_mutex_unlock (__objc_runtime_mutex
);