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 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under the 8terms of the GNU General Public License as published by the Free Software 9Foundation; either version 3, or (at your option) any later version. 10 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14details. 15 16Under Section 7 of GPL version 3, you are granted additional 17permissions described in the GCC Runtime Library Exception, version 183.1, as published by the Free Software Foundation. 19 20You should have received a copy of the GNU General Public License and 21a copy of the GCC Runtime Library Exception along with this program; 22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23<http://www.gnu.org/licenses/>. */ 24 25 26#include "objc/runtime.h" 27#include "objc/sarray.h" 28#include "objc/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 */ 34static struct sarray *__objc_selector_array = 0; /* uid -> sel !T:MUTEX */ 35static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */ 36static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */ 37 38/* Number of selectors stored in each of the above tables */ 39unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */ 40 41void __objc_init_selector_tables (void) 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 = objc_hash_new (SELECTOR_HASH_SIZE, 47 (hash_func_type) objc_hash_string, 48 (compare_func_type) objc_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 { 61 __objc_register_selectors_from_list (method_list); 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 71 The name and type pointers in the method list must be permanent and 72 immutable. 73 */ 74void 75__objc_register_selectors_from_list (MethodList_t method_list) 76{ 77 int i = 0; 78 79 objc_mutex_lock (__objc_runtime_mutex); 80 while (i < method_list->method_count) 81 { 82 Method_t method = &method_list->method_list[i]; 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 } 89 i += 1; 90 } 91 objc_mutex_unlock (__objc_runtime_mutex); 92} 93 94 95/* Register instance methods as class methods for root classes */ 96void __objc_register_instance_methods_to_class (Class class) 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. */ 105 if (class->super_class) 106 return; 107 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]; 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 125 && ! search_for_method_in_list (class_method_list, 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 */ 133 if (++new_list->method_count == max_methods_no) 134 new_list = 135 objc_realloc (new_list, sizeof (struct objc_method_list) 136 + sizeof (struct 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 = 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; 154 } 155 else 156 objc_free(new_list); 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 165sel_types_match (const char *t1, const char *t2) 166{ 167 if (! t1 || ! t2) 168 return NO; 169 while (*t1 && *t2) 170 { 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); 179 if (! *t1 && ! *t2) 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 196 objc_mutex_lock (__objc_runtime_mutex); 197 198 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name); 199 if (i == 0) 200 { 201 objc_mutex_unlock (__objc_runtime_mutex); 202 return 0; 203 } 204 205 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i); 206 l; l = l->tail) 207 { 208 SEL s = (SEL) l->head; 209 if (types == 0 || s->sel_types == 0) 210 { 211 if (s->sel_types == types) 212 { 213 objc_mutex_unlock (__objc_runtime_mutex); 214 return s; 215 } 216 } 217 else if (sel_types_match (s->sel_types, types)) 218 { 219 objc_mutex_unlock (__objc_runtime_mutex); 220 return s; 221 } 222 } 223 224 objc_mutex_unlock (__objc_runtime_mutex); 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 236 objc_mutex_lock (__objc_runtime_mutex); 237 238 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name); 239 if (i == 0) 240 { 241 objc_mutex_unlock (__objc_runtime_mutex); 242 return 0; 243 } 244 245 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i); 246 l; l = l->tail) 247 { 248 s = (SEL) l->head; 249 if (s->sel_types) 250 { 251 objc_mutex_unlock (__objc_runtime_mutex); 252 return s; 253 } 254 } 255 256 objc_mutex_unlock (__objc_runtime_mutex); 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 267 objc_mutex_lock (__objc_runtime_mutex); 268 269 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name); 270 if (soffset_decode (i) == 0) 271 { 272 objc_mutex_unlock (__objc_runtime_mutex); 273 return 0; 274 } 275 276 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i); 277 objc_mutex_unlock (__objc_runtime_mutex); 278 279 if (l == 0) 280 return 0; 281 282 return (SEL) l->head; 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 */ 294const char *sel_get_name (SEL selector) 295{ 296 const char *ret; 297 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); 302 else 303 ret = 0; 304 objc_mutex_unlock (__objc_runtime_mutex); 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 316const char *sel_get_type (SEL selector) 317{ 318 if (selector) 319 return selector->sel_types; 320 else 321 return 0; 322} 323 324/* The uninstalled dispatch table */ 325extern struct sarray *__objc_uninstalled_dtable; 326 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 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{ 367 struct objc_selector *j; 368 sidx i; 369 struct objc_list *l; 370 371 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name); 372 if (soffset_decode (i) != 0) 373 { 374 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i); 375 l; l = l->tail) 376 { 377 SEL s = (SEL) l->head; 378 if (types == 0 || s->sel_types == 0) 379 { 380 if (s->sel_types == types) 381 { 382 if (orig) 383 { 384 orig->sel_id = (void *) i; 385 return orig; 386 } 387 else 388 return s; 389 } 390 } 391 else if (! strcmp (s->sel_types, types)) 392 { 393 if (orig) 394 { 395 orig->sel_id = (void *) i; 396 return orig; 397 } 398 else 399 return s; 400 } 401 } 402 if (orig) 403 j = orig; 404 else 405 j = pool_alloc_selector (); 406 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; 411 else { 412 j->sel_types = (char *) objc_malloc (strlen (types) + 1); 413 strcpy ((char *) j->sel_types, types); 414 } 415 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i); 416 } 417 else 418 { 419 __objc_selector_max_index += 1; 420 i = soffset_encode (__objc_selector_max_index); 421 if (orig) 422 j = orig; 423 else 424 j = pool_alloc_selector (); 425 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; 430 else { 431 j->sel_types = (char *) objc_malloc (strlen (types) + 1); 432 strcpy ((char *) j->sel_types, types); 433 } 434 l = 0; 435 } 436 437 DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types, 438 (long) soffset_decode (i)); 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 { 448 new_name = (char *) objc_malloc (strlen (name) + 1); 449 strcpy ((char *) new_name, name); 450 } 451 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); 455 if (is_new) 456 objc_hash_add (&__objc_selector_hash, (void *) new_name, (void *) i); 457 } 458 459 sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1); 460 461 return (SEL) j; 462} 463 464SEL 465sel_register_name (const char *name) 466{ 467 SEL ret; 468 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); 474 475 return ret; 476} 477 478SEL 479sel_register_typed_name (const char *name, const char *type) 480{ 481 SEL ret; 482 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); 488 489 return ret; 490} 491