1 /* GNU Objective C Runtime selector related functions
2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004 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 2, 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 You should have received a copy of the GNU General Public License along with
17 GCC; see the file COPYING. If not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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. */
26 #include "objc/runtime.h"
27 #include "objc/sarray.h"
28 #include "objc/encoding.h"
30 /* Initial selector hash table size. Value doesn't matter much */
31 #define SELECTOR_HASH_SIZE 128
33 /* Tables mapping selector names to uid and opposite */
34 static struct sarray
*__objc_selector_array
= 0; /* uid -> sel !T:MUTEX */
35 static struct sarray
*__objc_selector_names
= 0; /* uid -> name !T:MUTEX */
36 static cache_ptr __objc_selector_hash
= 0; /* name -> uid !T:MUTEX */
38 /* Number of selectors stored in each of the above tables */
39 unsigned int __objc_selector_max_index
= 0; /* !T:MUTEX */
41 void __objc_init_selector_tables (void)
43 __objc_selector_array
= sarray_new (SELECTOR_HASH_SIZE
, 0);
44 __objc_selector_names
= sarray_new (SELECTOR_HASH_SIZE
, 0);
46 = objc_hash_new (SELECTOR_HASH_SIZE
,
47 (hash_func_type
) objc_hash_string
,
48 (compare_func_type
) objc_compare_strings
);
51 /* This routine is given a class and records all of the methods in its class
52 structure in the record table. */
54 __objc_register_selectors_from_class (Class
class)
56 MethodList_t method_list
;
58 method_list
= class->methods
;
61 __objc_register_selectors_from_list (method_list
);
62 method_list
= method_list
->method_next
;
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
71 The name and type pointers in the method list must be permanent and
75 __objc_register_selectors_from_list (MethodList_t method_list
)
79 objc_mutex_lock (__objc_runtime_mutex
);
80 while (i
< method_list
->method_count
)
82 Method_t method
= &method_list
->method_list
[i
];
83 if (method
->method_name
)
86 = __sel_register_typed_name ((const char *) method
->method_name
,
87 method
->method_types
, 0, YES
);
91 objc_mutex_unlock (__objc_runtime_mutex
);
95 /* Register instance methods as class methods for root classes */
96 void __objc_register_instance_methods_to_class (Class
class)
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
;
104 /* Only if a root class. */
105 if (class->super_class
)
108 /* Allocate a method list to hold the new class methods */
109 new_list
= objc_calloc (sizeof (struct objc_method_list
)
110 + sizeof (struct objc_method
[max_methods_no
]), 1);
111 method_list
= class->methods
;
112 class_method_list
= class->class_pointer
->methods
;
113 curr_method
= &new_list
->method_list
[0];
115 /* Iterate through the method lists for the class */
120 /* Iterate through the methods from this method list */
121 for (i
= 0; i
< method_list
->method_count
; i
++)
123 Method_t mth
= &method_list
->method_list
[i
];
125 && ! search_for_method_in_list (class_method_list
,
128 /* This instance method isn't a class method.
129 Add it into the new_list. */
132 /* Reallocate the method list if necessary */
133 if (++new_list
->method_count
== max_methods_no
)
135 objc_realloc (new_list
, sizeof (struct objc_method_list
)
137 objc_method
[max_methods_no
+= 16]));
138 curr_method
= &new_list
->method_list
[new_list
->method_count
];
142 method_list
= method_list
->method_next
;
145 /* If we created any new class methods
146 then attach the method list to the class */
147 if (new_list
->method_count
)
150 objc_realloc (new_list
, sizeof (struct objc_method_list
)
151 + sizeof (struct objc_method
[new_list
->method_count
]));
152 new_list
->method_next
= class->class_pointer
->methods
;
153 class->class_pointer
->methods
= new_list
;
158 __objc_update_dispatch_table_for_class (class->class_pointer
);
162 /* Returns YES iff t1 and t2 have same method types, but we ignore
163 the argframe layout */
165 sel_types_match (const char *t1
, const char *t2
)
171 if (*t1
== '+') t1
++;
172 if (*t2
== '+') t2
++;
173 while (isdigit ((unsigned char) *t1
)) t1
++;
174 while (isdigit ((unsigned char) *t2
)) t2
++;
175 /* xxx Remove these next two lines when qualifiers are put in
176 all selectors, not just Protocol selectors. */
177 t1
= objc_skip_type_qualifiers (t1
);
178 t2
= objc_skip_type_qualifiers (t2
);
189 /* return selector representing name */
191 sel_get_typed_uid (const char *name
, const char *types
)
196 objc_mutex_lock (__objc_runtime_mutex
);
198 i
= (sidx
) objc_hash_value_for_key (__objc_selector_hash
, name
);
201 objc_mutex_unlock (__objc_runtime_mutex
);
205 for (l
= (struct objc_list
*) sarray_get_safe (__objc_selector_array
, i
);
208 SEL s
= (SEL
) l
->head
;
209 if (types
== 0 || s
->sel_types
== 0)
211 if (s
->sel_types
== types
)
213 objc_mutex_unlock (__objc_runtime_mutex
);
217 else if (sel_types_match (s
->sel_types
, types
))
219 objc_mutex_unlock (__objc_runtime_mutex
);
224 objc_mutex_unlock (__objc_runtime_mutex
);
228 /* Return selector representing name; prefer a selector with non-NULL type */
230 sel_get_any_typed_uid (const char *name
)
236 objc_mutex_lock (__objc_runtime_mutex
);
238 i
= (sidx
) objc_hash_value_for_key (__objc_selector_hash
, name
);
241 objc_mutex_unlock (__objc_runtime_mutex
);
245 for (l
= (struct objc_list
*) sarray_get_safe (__objc_selector_array
, i
);
251 objc_mutex_unlock (__objc_runtime_mutex
);
256 objc_mutex_unlock (__objc_runtime_mutex
);
260 /* return selector representing name */
262 sel_get_any_uid (const char *name
)
267 objc_mutex_lock (__objc_runtime_mutex
);
269 i
= (sidx
) objc_hash_value_for_key (__objc_selector_hash
, name
);
270 if (soffset_decode (i
) == 0)
272 objc_mutex_unlock (__objc_runtime_mutex
);
276 l
= (struct objc_list
*) sarray_get_safe (__objc_selector_array
, i
);
277 objc_mutex_unlock (__objc_runtime_mutex
);
282 return (SEL
) l
->head
;
285 /* return selector representing name */
287 sel_get_uid (const char *name
)
289 return sel_register_typed_name (name
, 0);
292 /* Get name of selector. If selector is unknown, the empty string ""
294 const char *sel_get_name (SEL selector
)
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
))
301 ret
= sarray_get_safe (__objc_selector_names
, (sidx
) selector
->sel_id
);
304 objc_mutex_unlock (__objc_runtime_mutex
);
309 sel_is_mapped (SEL selector
)
311 unsigned int idx
= soffset_decode ((sidx
)selector
->sel_id
);
312 return ((idx
> 0) && (idx
<= __objc_selector_max_index
));
316 const char *sel_get_type (SEL selector
)
319 return selector
->sel_types
;
324 /* The uninstalled dispatch table */
325 extern struct sarray
*__objc_uninstalled_dtable
;
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.
334 Note that the objc_selector:s allocated from __sel_register_typed_name
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.
340 #define SELECTOR_POOL_SIZE 62
341 static struct objc_selector
*selector_pool
;
342 static int selector_pool_left
;
344 static struct objc_selector
*
345 pool_alloc_selector(void)
347 if (!selector_pool_left
)
349 selector_pool
= objc_malloc (sizeof (struct objc_selector
)
350 * SELECTOR_POOL_SIZE
);
351 selector_pool_left
= SELECTOR_POOL_SIZE
;
353 return &selector_pool
[--selector_pool_left
];
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. */
364 __sel_register_typed_name (const char *name
, const char *types
,
365 struct objc_selector
*orig
, BOOL is_const
)
367 struct objc_selector
*j
;
371 i
= (sidx
) objc_hash_value_for_key (__objc_selector_hash
, name
);
372 if (soffset_decode (i
) != 0)
374 for (l
= (struct objc_list
*) sarray_get_safe (__objc_selector_array
, i
);
377 SEL s
= (SEL
) l
->head
;
378 if (types
== 0 || s
->sel_types
== 0)
380 if (s
->sel_types
== types
)
384 orig
->sel_id
= (void *) i
;
391 else if (! strcmp (s
->sel_types
, types
))
395 orig
->sel_id
= (void *) i
;
405 j
= pool_alloc_selector ();
407 j
->sel_id
= (void *) i
;
408 /* Can we use the pointer or must copy types? Don't copy if NULL */
409 if ((is_const
) || (types
== 0))
410 j
->sel_types
= (const char *) types
;
412 j
->sel_types
= (char *) objc_malloc (strlen (types
) + 1);
413 strcpy ((char *) j
->sel_types
, types
);
415 l
= (struct objc_list
*) sarray_get_safe (__objc_selector_array
, i
);
419 __objc_selector_max_index
+= 1;
420 i
= soffset_encode (__objc_selector_max_index
);
424 j
= pool_alloc_selector ();
426 j
->sel_id
= (void *) i
;
427 /* Can we use the pointer or must copy types? Don't copy if NULL */
428 if ((is_const
) || (types
== 0))
429 j
->sel_types
= (const char *) types
;
431 j
->sel_types
= (char *) objc_malloc (strlen (types
) + 1);
432 strcpy ((char *) j
->sel_types
, types
);
437 DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name
, types
,
438 (long) soffset_decode (i
));
441 int is_new
= (l
== 0);
442 const char *new_name
;
444 /* Can we use the pointer or must copy name? Don't copy if NULL */
445 if ((is_const
) || (name
== 0))
448 new_name
= (char *) objc_malloc (strlen (name
) + 1);
449 strcpy ((char *) new_name
, name
);
452 l
= list_cons ((void *) j
, l
);
453 sarray_at_put_safe (__objc_selector_names
, i
, (void *) new_name
);
454 sarray_at_put_safe (__objc_selector_array
, i
, (void *) l
);
456 objc_hash_add (&__objc_selector_hash
, (void *) new_name
, (void *) i
);
459 sarray_realloc (__objc_uninstalled_dtable
, __objc_selector_max_index
+ 1);
465 sel_register_name (const char *name
)
469 objc_mutex_lock (__objc_runtime_mutex
);
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
);
473 objc_mutex_unlock (__objc_runtime_mutex
);
479 sel_register_typed_name (const char *name
, const char *type
)
483 objc_mutex_lock (__objc_runtime_mutex
);
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
);
487 objc_mutex_unlock (__objc_runtime_mutex
);