1 /* GNU Objective C Runtime message lookup 2 Copyright (C) 1993, 1995, 1996, 1997, 1998, 3 2001, 2002, 2004, 2009, 2010 Free Software Foundation, Inc. 4 Contributed by Kresten Krab Thorup 5 6 This file is part of GCC. 7 8 GCC is free software; you can redistribute it and/or modify it under the 9 terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3, or (at your option) any later version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 15 details. 16 17 Under Section 7 of GPL version 3, you are granted additional 18 permissions described in the GCC Runtime Library Exception, version 19 3.1, as published by the Free Software Foundation. 20 21 You should have received a copy of the GNU General Public License and 22 a copy of the GCC Runtime Library Exception along with this program; 23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 <http://www.gnu.org/licenses/>. */ 25 26 /* Uncommented the following line to enable debug logging. Use this 27 only while debugging the runtime. */ 28 /* #define DEBUG 1 */ 29 30 /* FIXME: This file has no business including tm.h. */ 31 /* FIXME: This should be using libffi instead of __builtin_apply 32 and friends. */ 33 34 #include "objc-private/common.h" 35 #include "objc-private/error.h" 36 #include "tconfig.h" 37 #include "coretypes.h" 38 #include "tm.h" 39 #include "objc/runtime.h" 40 #include "objc/message.h" /* For objc_msg_lookup(), objc_msg_lookup_super(). */ 41 #include "objc/thr.h" 42 #include "objc-private/module-abi-8.h" 43 #include "objc-private/runtime.h" 44 #include "objc-private/hash.h" 45 #include "objc-private/sarray.h" 46 #include "objc-private/selector.h" /* For sel_is_mapped() */ 47 #include "runtime-info.h" 48 #include <assert.h> /* For assert */ 49 #include <string.h> /* For strlen */ 50 51 /* This is how we hack STRUCT_VALUE to be 1 or 0. */ 52 #define gen_rtx(args...) 1 53 #define gen_rtx_MEM(args...) 1 54 #define gen_rtx_REG(args...) 1 55 /* Already defined in gcc/coretypes.h. So prevent double definition warning. */ 56 #undef rtx 57 #define rtx int 58 59 #if ! defined (STRUCT_VALUE) || STRUCT_VALUE == 0 60 #define INVISIBLE_STRUCT_RETURN 1 61 #else 62 #define INVISIBLE_STRUCT_RETURN 0 63 #endif 64 65 /* The uninstalled dispatch table. If a class' dispatch table points 66 to __objc_uninstalled_dtable then that means it needs its dispatch 67 table to be installed. */ 68 struct sarray *__objc_uninstalled_dtable = 0; /* !T:MUTEX */ 69 70 /* Two hooks for method forwarding. If either is set, it is invoked to 71 * return a function that performs the real forwarding. If both are 72 * set, the result of __objc_msg_forward2 will be preferred over that 73 * of __objc_msg_forward. If both return NULL or are unset, the 74 * libgcc based functions (__builtin_apply and friends) are used. */ 75 IMP (*__objc_msg_forward) (SEL) = NULL; 76 IMP (*__objc_msg_forward2) (id, SEL) = NULL; 77 78 /* Send +initialize to class. */ 79 static void __objc_send_initialize (Class); 80 81 /* Forward declare some functions */ 82 static void __objc_install_dtable_for_class (Class cls); 83 static void __objc_prepare_dtable_for_class (Class cls); 84 static void __objc_install_prepared_dtable_for_class (Class cls); 85 86 static struct sarray *__objc_prepared_dtable_for_class (Class cls); 87 static IMP __objc_get_prepared_imp (Class cls,SEL sel); 88 89 90 /* Various forwarding functions that are used based upon the 91 return type for the selector. 92 __objc_block_forward for structures. 93 __objc_double_forward for floats/doubles. 94 __objc_word_forward for pointers or types that fit in registers. */ 95 static double __objc_double_forward (id, SEL, ...); 96 static id __objc_word_forward (id, SEL, ...); 97 typedef struct { id many[8]; } __big; 98 #if INVISIBLE_STRUCT_RETURN 99 static __big 100 #else 101 static id 102 #endif 103 __objc_block_forward (id, SEL, ...); 104 static struct objc_method * search_for_method_in_hierarchy (Class class, SEL sel); 105 struct objc_method * search_for_method_in_list (struct objc_method_list * list, SEL op); 106 id nil_method (id, SEL); 107 108 /* Make sure this inline function is exported regardless of GNU89 or C99 109 inlining semantics as it is part of the libobjc ABI. */ 110 extern IMP __objc_get_forward_imp (id, SEL); 111 112 /* Given a selector, return the proper forwarding implementation. */ 113 inline 114 IMP 115 __objc_get_forward_imp (id rcv, SEL sel) 116 { 117 /* If a custom forwarding hook was registered, try getting a 118 forwarding function from it. There are two forward routine hooks, 119 one that takes the receiver as an argument and one that does 120 not. */ 121 if (__objc_msg_forward2) 122 { 123 IMP result; 124 if ((result = __objc_msg_forward2 (rcv, sel)) != NULL) 125 return result; 126 } 127 if (__objc_msg_forward) 128 { 129 IMP result; 130 if ((result = __objc_msg_forward (sel)) != NULL) 131 return result; 132 } 133 134 /* In all other cases, use the default forwarding functions built 135 using __builtin_apply and friends. */ 136 { 137 const char *t = sel->sel_types; 138 139 if (t && (*t == '[' || *t == '(' || *t == '{') 140 #ifdef OBJC_MAX_STRUCT_BY_VALUE 141 && objc_sizeof_type (t) > OBJC_MAX_STRUCT_BY_VALUE 142 #endif 143 ) 144 return (IMP)__objc_block_forward; 145 else if (t && (*t == 'f' || *t == 'd')) 146 return (IMP)__objc_double_forward; 147 else 148 return (IMP)__objc_word_forward; 149 } 150 } 151 152 /* Selectors for +resolveClassMethod: and +resolveInstanceMethod:. 153 These are set up at startup. */ 154 static SEL selector_resolveClassMethod = NULL; 155 static SEL selector_resolveInstanceMethod = NULL; 156 157 /* Internal routines use to resolve a class method using 158 +resolveClassMethod:. 'class' is always a non-Nil class (*not* a 159 meta-class), and 'sel' is the selector that we are trying to 160 resolve. This must be called when class is not Nil, and the 161 dispatch table for class methods has already been installed. 162 163 This routine tries to call +resolveClassMethod: to give an 164 opportunity to resolve the method. If +resolveClassMethod: returns 165 YES, it tries looking up the method again, and if found, it returns 166 it. Else, it returns NULL. */ 167 static inline 168 IMP 169 __objc_resolve_class_method (Class class, SEL sel) 170 { 171 /* We need to lookup +resolveClassMethod:. */ 172 BOOL (*resolveMethodIMP) (id, SEL, SEL); 173 174 /* The dispatch table for class methods is already installed and we 175 don't want any forwarding to happen when looking up this method, 176 so we just look it up directly. Note that if 'sel' is precisely 177 +resolveClassMethod:, this would look it up yet again and find 178 nothing. That's no problem and there's no recursion. */ 179 resolveMethodIMP = (BOOL (*) (id, SEL, SEL))sarray_get_safe 180 (class->class_pointer->dtable, (size_t) selector_resolveClassMethod->sel_id); 181 182 if (resolveMethodIMP && resolveMethodIMP ((id)class, selector_resolveClassMethod, sel)) 183 { 184 /* +resolveClassMethod: returned YES. Look the method up again. 185 We already know the dtable is installed. */ 186 187 /* TODO: There is the case where +resolveClassMethod: is buggy 188 and returned YES without actually adding the method. We 189 could maybe print an error message. */ 190 return sarray_get_safe (class->class_pointer->dtable, (size_t) sel->sel_id); 191 } 192 193 return NULL; 194 } 195 196 /* Internal routines use to resolve a instance method using 197 +resolveInstanceMethod:. 'class' is always a non-Nil class, and 198 'sel' is the selector that we are trying to resolve. This must be 199 called when class is not Nil, and the dispatch table for instance 200 methods has already been installed. 201 202 This routine tries to call +resolveInstanceMethod: to give an 203 opportunity to resolve the method. If +resolveInstanceMethod: 204 returns YES, it tries looking up the method again, and if found, it 205 returns it. Else, it returns NULL. */ 206 static inline 207 IMP 208 __objc_resolve_instance_method (Class class, SEL sel) 209 { 210 /* We need to lookup +resolveInstanceMethod:. */ 211 BOOL (*resolveMethodIMP) (id, SEL, SEL); 212 213 /* The dispatch table for class methods may not be already installed 214 so we have to install it if needed. */ 215 resolveMethodIMP = sarray_get_safe (class->class_pointer->dtable, 216 (size_t) selector_resolveInstanceMethod->sel_id); 217 if (resolveMethodIMP == 0) 218 { 219 /* Try again after installing the dtable. */ 220 if (class->class_pointer->dtable == __objc_uninstalled_dtable) 221 { 222 objc_mutex_lock (__objc_runtime_mutex); 223 if (class->class_pointer->dtable == __objc_uninstalled_dtable) 224 __objc_install_dtable_for_class (class->class_pointer); 225 objc_mutex_unlock (__objc_runtime_mutex); 226 } 227 resolveMethodIMP = sarray_get_safe (class->class_pointer->dtable, 228 (size_t) selector_resolveInstanceMethod->sel_id); 229 } 230 231 if (resolveMethodIMP && resolveMethodIMP ((id)class, selector_resolveInstanceMethod, sel)) 232 { 233 /* +resolveInstanceMethod: returned YES. Look the method up 234 again. We already know the dtable is installed. */ 235 236 /* TODO: There is the case where +resolveInstanceMethod: is 237 buggy and returned YES without actually adding the method. 238 We could maybe print an error message. */ 239 return sarray_get_safe (class->dtable, (size_t) sel->sel_id); 240 } 241 242 return NULL; 243 } 244 245 /* Given a CLASS and selector, return the implementation corresponding 246 to the method of the selector. 247 248 If CLASS is a class, the instance method is returned. 249 If CLASS is a meta class, the class method is returned. 250 251 Since this requires the dispatch table to be installed, this function 252 will implicitly invoke +initialize for CLASS if it hasn't been 253 invoked yet. This also insures that +initialize has been invoked 254 when the returned implementation is called directly. 255 256 The forwarding hooks require the receiver as an argument (if they are to 257 perform dynamic lookup in proxy objects etc), so this function has a 258 receiver argument to be used with those hooks. */ 259 static inline 260 IMP 261 get_implementation (id receiver, Class class, SEL sel) 262 { 263 void *res; 264 265 if (class->dtable == __objc_uninstalled_dtable) 266 { 267 /* The dispatch table needs to be installed. */ 268 objc_mutex_lock (__objc_runtime_mutex); 269 270 /* Double-checked locking pattern: Check 271 __objc_uninstalled_dtable again in case another thread 272 installed the dtable while we were waiting for the lock to be 273 released. */ 274 if (class->dtable == __objc_uninstalled_dtable) 275 __objc_install_dtable_for_class (class); 276 277 /* If the dispatch table is not yet installed, we are still in 278 the process of executing +initialize. But the implementation 279 pointer should be available in the prepared ispatch table if 280 it exists at all. */ 281 if (class->dtable == __objc_uninstalled_dtable) 282 { 283 assert (__objc_prepared_dtable_for_class (class) != 0); 284 res = __objc_get_prepared_imp (class, sel); 285 } 286 else 287 res = 0; 288 289 objc_mutex_unlock (__objc_runtime_mutex); 290 /* Call ourselves with the installed dispatch table and get the 291 real method. */ 292 if (!res) 293 res = get_implementation (receiver, class, sel); 294 } 295 else 296 { 297 /* The dispatch table has been installed. */ 298 res = sarray_get_safe (class->dtable, (size_t) sel->sel_id); 299 if (res == 0) 300 { 301 /* The dispatch table has been installed, and the method is 302 not in the dispatch table. So the method just doesn't 303 exist for the class. */ 304 305 /* Try going through the +resolveClassMethod: or 306 +resolveInstanceMethod: process. */ 307 if (CLS_ISMETA (class)) 308 { 309 /* We have the meta class, but we need to invoke the 310 +resolveClassMethod: method on the class. So, we 311 need to obtain the class from the meta class, which 312 we do using the fact that both the class and the 313 meta-class have the same name. */ 314 Class realClass = objc_lookUpClass (class->name); 315 if (realClass) 316 res = __objc_resolve_class_method (realClass, sel); 317 } 318 else 319 res = __objc_resolve_instance_method (class, sel); 320 321 if (res == 0) 322 res = __objc_get_forward_imp (receiver, sel); 323 } 324 } 325 return res; 326 } 327 328 /* Make sure this inline function is exported regardless of GNU89 or C99 329 inlining semantics as it is part of the libobjc ABI. */ 330 extern IMP get_imp (Class, SEL); 331 332 inline 333 IMP 334 get_imp (Class class, SEL sel) 335 { 336 /* In a vanilla implementation we would first check if the dispatch 337 table is installed. Here instead, to get more speed in the 338 standard case (that the dispatch table is installed) we first try 339 to get the imp using brute force. Only if that fails, we do what 340 we should have been doing from the very beginning, that is, check 341 if the dispatch table needs to be installed, install it if it's 342 not installed, and retrieve the imp from the table if it's 343 installed. */ 344 void *res = sarray_get_safe (class->dtable, (size_t) sel->sel_id); 345 if (res == 0) 346 { 347 res = get_implementation(nil, class, sel); 348 } 349 return res; 350 } 351 352 /* The new name of get_imp(). */ 353 IMP 354 class_getMethodImplementation (Class class_, SEL selector) 355 { 356 if (class_ == Nil || selector == NULL) 357 return NULL; 358 359 /* get_imp is inlined, so we're good. */ 360 return get_imp (class_, selector); 361 } 362 363 /* Given a method, return its implementation. This has been replaced 364 by method_getImplementation() in the modern API. */ 365 IMP 366 method_get_imp (struct objc_method * method) 367 { 368 return (method != (struct objc_method *)0) ? method->method_imp : (IMP)0; 369 } 370 371 /* Query if an object can respond to a selector, returns YES if the 372 object implements the selector otherwise NO. Does not check if the 373 method can be forwarded. Since this requires the dispatch table to 374 installed, this function will implicitly invoke +initialize for the 375 class of OBJECT if it hasn't been invoked yet. */ 376 inline 377 BOOL 378 __objc_responds_to (id object, SEL sel) 379 { 380 void *res; 381 struct sarray *dtable; 382 383 /* Install dispatch table if need be */ 384 dtable = object->class_pointer->dtable; 385 if (dtable == __objc_uninstalled_dtable) 386 { 387 objc_mutex_lock (__objc_runtime_mutex); 388 if (object->class_pointer->dtable == __objc_uninstalled_dtable) 389 __objc_install_dtable_for_class (object->class_pointer); 390 391 /* If the dispatch table is not yet installed, we are still in 392 the process of executing +initialize. Yet the dispatch table 393 should be available. */ 394 if (object->class_pointer->dtable == __objc_uninstalled_dtable) 395 { 396 dtable = __objc_prepared_dtable_for_class (object->class_pointer); 397 assert (dtable); 398 } 399 else 400 dtable = object->class_pointer->dtable; 401 402 objc_mutex_unlock (__objc_runtime_mutex); 403 } 404 405 /* Get the method from the dispatch table. */ 406 res = sarray_get_safe (dtable, (size_t) sel->sel_id); 407 return (res != 0) ? YES : NO; 408 } 409 410 BOOL 411 class_respondsToSelector (Class class_, SEL selector) 412 { 413 struct sarray *dtable; 414 void *res; 415 416 if (class_ == Nil || selector == NULL) 417 return NO; 418 419 /* Install dispatch table if need be. */ 420 dtable = class_->dtable; 421 if (dtable == __objc_uninstalled_dtable) 422 { 423 objc_mutex_lock (__objc_runtime_mutex); 424 if (class_->dtable == __objc_uninstalled_dtable) 425 __objc_install_dtable_for_class (class_); 426 427 /* If the dispatch table is not yet installed, 428 we are still in the process of executing +initialize. 429 Yet the dispatch table should be available. */ 430 if (class_->dtable == __objc_uninstalled_dtable) 431 { 432 dtable = __objc_prepared_dtable_for_class (class_); 433 assert (dtable); 434 } 435 else 436 dtable = class_->dtable; 437 438 objc_mutex_unlock (__objc_runtime_mutex); 439 } 440 441 /* Get the method from the dispatch table. */ 442 res = sarray_get_safe (dtable, (size_t) selector->sel_id); 443 return (res != 0) ? YES : NO; 444 } 445 446 /* This is the lookup function. All entries in the table are either a 447 valid method *or* zero. If zero then either the dispatch table 448 needs to be installed or it doesn't exist and forwarding is 449 attempted. */ 450 IMP 451 objc_msg_lookup (id receiver, SEL op) 452 { 453 IMP result; 454 if (receiver) 455 { 456 /* First try a quick lookup assuming the dispatch table exists. */ 457 result = sarray_get_safe (receiver->class_pointer->dtable, 458 (sidx)op->sel_id); 459 if (result == 0) 460 { 461 /* Not found ... call get_implementation () to install the 462 dispatch table and call +initialize as required, 463 providing the method implementation or a forwarding 464 function. */ 465 result = get_implementation (receiver, receiver->class_pointer, op); 466 } 467 return result; 468 } 469 else 470 return (IMP)nil_method; 471 } 472 473 IMP 474 objc_msg_lookup_super (struct objc_super *super, SEL sel) 475 { 476 if (super->self) 477 return get_imp (super->super_class, sel); 478 else 479 return (IMP)nil_method; 480 } 481 482 void 483 __objc_init_dispatch_tables () 484 { 485 __objc_uninstalled_dtable = sarray_new (200, 0); 486 487 /* TODO: It would be cool to register typed selectors here. */ 488 selector_resolveClassMethod = sel_registerName ("resolveClassMethod:"); 489 selector_resolveInstanceMethod = sel_registerName ("resolveInstanceMethod:"); 490 } 491 492 493 /* Install dummy table for class which causes the first message to 494 that class (or instances hereof) to be initialized properly. */ 495 void 496 __objc_install_premature_dtable (Class class) 497 { 498 assert (__objc_uninstalled_dtable); 499 class->dtable = __objc_uninstalled_dtable; 500 } 501 502 /* Send +initialize to class if not already done. */ 503 static void 504 __objc_send_initialize (Class class) 505 { 506 /* This *must* be a class object. */ 507 assert (CLS_ISCLASS (class)); 508 assert (! CLS_ISMETA (class)); 509 510 /* class_add_method_list/__objc_update_dispatch_table_for_class may 511 have reset the dispatch table. The canonical way to insure that 512 we send +initialize just once, is this flag. */ 513 if (! CLS_ISINITIALIZED (class)) 514 { 515 DEBUG_PRINTF ("+initialize: need to initialize class '%s'\n", class->name); 516 CLS_SETINITIALIZED (class); 517 CLS_SETINITIALIZED (class->class_pointer); 518 519 /* Create the garbage collector type memory description. */ 520 __objc_generate_gc_type_description (class); 521 522 if (class->super_class) 523 __objc_send_initialize (class->super_class); 524 525 { 526 SEL op = sel_registerName ("initialize"); 527 struct objc_method *method = search_for_method_in_hierarchy (class->class_pointer, 528 op); 529 530 if (method) 531 { 532 DEBUG_PRINTF (" begin of [%s +initialize]\n", class->name); 533 (*method->method_imp) ((id)class, op); 534 DEBUG_PRINTF (" end of [%s +initialize]\n", class->name); 535 } 536 #ifdef DEBUG 537 else 538 { 539 DEBUG_PRINTF (" class '%s' has no +initialize method\n", class->name); 540 } 541 #endif 542 } 543 } 544 } 545 546 /* Walk on the methods list of class and install the methods in the 547 reverse order of the lists. Since methods added by categories are 548 before the methods of class in the methods list, this allows 549 categories to substitute methods declared in class. However if 550 more than one category replaces the same method nothing is 551 guaranteed about what method will be used. Assumes that 552 __objc_runtime_mutex is locked down. */ 553 static void 554 __objc_install_methods_in_dtable (struct sarray *dtable, struct objc_method_list * method_list) 555 { 556 int i; 557 558 if (! method_list) 559 return; 560 561 if (method_list->method_next) 562 __objc_install_methods_in_dtable (dtable, method_list->method_next); 563 564 for (i = 0; i < method_list->method_count; i++) 565 { 566 struct objc_method * method = &(method_list->method_list[i]); 567 sarray_at_put_safe (dtable, 568 (sidx) method->method_name->sel_id, 569 method->method_imp); 570 } 571 } 572 573 void 574 __objc_update_dispatch_table_for_class (Class class) 575 { 576 Class next; 577 struct sarray *arr; 578 579 DEBUG_PRINTF (" _objc_update_dtable_for_class (%s)\n", class->name); 580 581 objc_mutex_lock (__objc_runtime_mutex); 582 583 /* Not yet installed -- skip it unless in +initialize. */ 584 if (class->dtable == __objc_uninstalled_dtable) 585 { 586 if (__objc_prepared_dtable_for_class (class)) 587 { 588 /* There is a prepared table so we must be initialising this 589 class ... we must re-do the table preparation. */ 590 __objc_prepare_dtable_for_class (class); 591 } 592 objc_mutex_unlock (__objc_runtime_mutex); 593 return; 594 } 595 596 arr = class->dtable; 597 __objc_install_premature_dtable (class); /* someone might require it... */ 598 sarray_free (arr); /* release memory */ 599 600 /* Could have been lazy... */ 601 __objc_install_dtable_for_class (class); 602 603 if (class->subclass_list) /* Traverse subclasses. */ 604 for (next = class->subclass_list; next; next = next->sibling_class) 605 __objc_update_dispatch_table_for_class (next); 606 607 objc_mutex_unlock (__objc_runtime_mutex); 608 } 609 610 /* This function adds a method list to a class. This function is 611 typically called by another function specific to the run-time. As 612 such this function does not worry about thread safe issues. 613 614 This one is only called for categories. Class objects have their 615 methods installed right away, and their selectors are made into 616 SEL's by the function __objc_register_selectors_from_class. */ 617 void 618 class_add_method_list (Class class, struct objc_method_list * list) 619 { 620 /* Passing of a linked list is not allowed. Do multiple calls. */ 621 assert (! list->method_next); 622 623 __objc_register_selectors_from_list(list); 624 625 /* Add the methods to the class's method list. */ 626 list->method_next = class->methods; 627 class->methods = list; 628 629 /* Update the dispatch table of class. */ 630 __objc_update_dispatch_table_for_class (class); 631 } 632 633 struct objc_method * 634 class_getInstanceMethod (Class class_, SEL selector) 635 { 636 struct objc_method *m; 637 638 if (class_ == Nil || selector == NULL) 639 return NULL; 640 641 m = search_for_method_in_hierarchy (class_, selector); 642 if (m) 643 return m; 644 645 /* Try going through +resolveInstanceMethod:, and do the search 646 again if successful. */ 647 if (__objc_resolve_instance_method (class_, selector)) 648 return search_for_method_in_hierarchy (class_, selector); 649 650 return NULL; 651 } 652 653 struct objc_method * 654 class_getClassMethod (Class class_, SEL selector) 655 { 656 struct objc_method *m; 657 658 if (class_ == Nil || selector == NULL) 659 return NULL; 660 661 m = search_for_method_in_hierarchy (class_->class_pointer, 662 selector); 663 if (m) 664 return m; 665 666 /* Try going through +resolveClassMethod:, and do the search again 667 if successful. */ 668 if (__objc_resolve_class_method (class_, selector)) 669 return search_for_method_in_hierarchy (class_->class_pointer, 670 selector); 671 672 return NULL; 673 } 674 675 BOOL 676 class_addMethod (Class class_, SEL selector, IMP implementation, 677 const char *method_types) 678 { 679 struct objc_method_list *method_list; 680 struct objc_method *method; 681 const char *method_name; 682 683 if (class_ == Nil || selector == NULL || implementation == NULL 684 || method_types == NULL || (strcmp (method_types, "") == 0)) 685 return NO; 686 687 method_name = sel_getName (selector); 688 if (method_name == NULL) 689 return NO; 690 691 /* If the method already exists in the class, return NO. It is fine 692 if the method already exists in the superclass; in that case, we 693 are overriding it. */ 694 if (CLS_IS_IN_CONSTRUCTION (class_)) 695 { 696 /* The class only contains a list of methods; they have not been 697 registered yet, ie, the method_name of each of them is still 698 a string, not a selector. Iterate manually over them to 699 check if we have already added the method. */ 700 struct objc_method_list * method_list = class_->methods; 701 while (method_list) 702 { 703 int i; 704 705 /* Search the method list. */ 706 for (i = 0; i < method_list->method_count; ++i) 707 { 708 struct objc_method * method = &method_list->method_list[i]; 709 710 if (method->method_name 711 && strcmp ((char *)method->method_name, method_name) == 0) 712 return NO; 713 } 714 715 /* The method wasn't found. Follow the link to the next list of 716 methods. */ 717 method_list = method_list->method_next; 718 } 719 /* The method wasn't found. It's a new one. Go ahead and add 720 it. */ 721 } 722 else 723 { 724 /* Do the standard lookup. This assumes the selectors are 725 mapped. */ 726 if (search_for_method_in_list (class_->methods, selector)) 727 return NO; 728 } 729 730 method_list = (struct objc_method_list *)objc_calloc (1, sizeof (struct objc_method_list)); 731 method_list->method_count = 1; 732 733 method = &(method_list->method_list[0]); 734 method->method_name = objc_malloc (strlen (method_name) + 1); 735 strcpy ((char *)method->method_name, method_name); 736 737 method->method_types = objc_malloc (strlen (method_types) + 1); 738 strcpy ((char *)method->method_types, method_types); 739 740 method->method_imp = implementation; 741 742 if (CLS_IS_IN_CONSTRUCTION (class_)) 743 { 744 /* We only need to add the method to the list. It will be 745 registered with the runtime when the class pair is registered 746 (if ever). */ 747 method_list->method_next = class_->methods; 748 class_->methods = method_list; 749 } 750 else 751 { 752 /* Add the method to a live class. */ 753 objc_mutex_lock (__objc_runtime_mutex); 754 class_add_method_list (class_, method_list); 755 objc_mutex_unlock (__objc_runtime_mutex); 756 } 757 758 return YES; 759 } 760 761 IMP 762 class_replaceMethod (Class class_, SEL selector, IMP implementation, 763 const char *method_types) 764 { 765 struct objc_method * method; 766 767 if (class_ == Nil || selector == NULL || implementation == NULL 768 || method_types == NULL) 769 return NULL; 770 771 method = search_for_method_in_hierarchy (class_, selector); 772 773 if (method) 774 { 775 return method_setImplementation (method, implementation); 776 } 777 else 778 { 779 class_addMethod (class_, selector, implementation, method_types); 780 return NULL; 781 } 782 } 783 784 /* Search for a method starting from the current class up its 785 hierarchy. Return a pointer to the method's method structure if 786 found. NULL otherwise. */ 787 static struct objc_method * 788 search_for_method_in_hierarchy (Class cls, SEL sel) 789 { 790 struct objc_method * method = NULL; 791 Class class; 792 793 if (! sel_is_mapped (sel)) 794 return NULL; 795 796 /* Scan the method list of the class. If the method isn't found in 797 the list then step to its super class. */ 798 for (class = cls; ((! method) && class); class = class->super_class) 799 method = search_for_method_in_list (class->methods, sel); 800 801 return method; 802 } 803 804 805 806 /* Given a linked list of method and a method's name. Search for the 807 named method's method structure. Return a pointer to the method's 808 method structure if found. NULL otherwise. */ 809 struct objc_method * 810 search_for_method_in_list (struct objc_method_list * list, SEL op) 811 { 812 struct objc_method_list * method_list = list; 813 814 if (! sel_is_mapped (op)) 815 return NULL; 816 817 /* If not found then we'll search the list. */ 818 while (method_list) 819 { 820 int i; 821 822 /* Search the method list. */ 823 for (i = 0; i < method_list->method_count; ++i) 824 { 825 struct objc_method * method = &method_list->method_list[i]; 826 827 if (method->method_name) 828 if (method->method_name->sel_id == op->sel_id) 829 return method; 830 } 831 832 /* The method wasn't found. Follow the link to the next list of 833 methods. */ 834 method_list = method_list->method_next; 835 } 836 837 return NULL; 838 } 839 840 typedef void * retval_t; 841 typedef void * arglist_t; 842 843 static retval_t __objc_forward (id object, SEL sel, arglist_t args); 844 845 /* Forwarding pointers/integers through the normal registers. */ 846 static id 847 __objc_word_forward (id rcv, SEL op, ...) 848 { 849 void *args, *res; 850 851 args = __builtin_apply_args (); 852 res = __objc_forward (rcv, op, args); 853 if (res) 854 __builtin_return (res); 855 else 856 return res; 857 } 858 859 /* Specific routine for forwarding floats/double because of 860 architectural differences on some processors. i386s for example 861 which uses a floating point stack versus general registers for 862 floating point numbers. This forward routine makes sure that GCC 863 restores the proper return values. */ 864 static double 865 __objc_double_forward (id rcv, SEL op, ...) 866 { 867 void *args, *res; 868 869 args = __builtin_apply_args (); 870 res = __objc_forward (rcv, op, args); 871 __builtin_return (res); 872 } 873 874 #if INVISIBLE_STRUCT_RETURN 875 static __big 876 #else 877 static id 878 #endif 879 __objc_block_forward (id rcv, SEL op, ...) 880 { 881 void *args, *res; 882 883 args = __builtin_apply_args (); 884 res = __objc_forward (rcv, op, args); 885 if (res) 886 __builtin_return (res); 887 else 888 #if INVISIBLE_STRUCT_RETURN 889 return (__big) {{0, 0, 0, 0, 0, 0, 0, 0}}; 890 #else 891 return nil; 892 #endif 893 } 894 895 896 /* This function is called for methods which are not implemented, 897 unless a custom forwarding routine has been installed. Please note 898 that most serious users of libobjc (eg, GNUstep base) do install 899 their own forwarding routines, and hence this is never actually 900 used. But, if no custom forwarding routine is installed, this is 901 called when a selector is not recognized. */ 902 static retval_t 903 __objc_forward (id object, SEL sel, arglist_t args) 904 { 905 IMP imp; 906 static SEL frwd_sel = 0; /* !T:SAFE2 */ 907 SEL err_sel; 908 909 /* First try if the object understands forward::. */ 910 if (! frwd_sel) 911 frwd_sel = sel_get_any_uid ("forward::"); 912 913 if (__objc_responds_to (object, frwd_sel)) 914 { 915 imp = get_implementation (object, object->class_pointer, frwd_sel); 916 return (*imp) (object, frwd_sel, sel, args); 917 } 918 919 /* If the object recognizes the doesNotRecognize: method then we're 920 going to send it. */ 921 err_sel = sel_get_any_uid ("doesNotRecognize:"); 922 if (__objc_responds_to (object, err_sel)) 923 { 924 imp = get_implementation (object, object->class_pointer, err_sel); 925 return (*imp) (object, err_sel, sel); 926 } 927 928 /* The object doesn't recognize the method. Check for responding to 929 error:. If it does then sent it. */ 930 { 931 char msg[256 + strlen ((const char *) sel_getName (sel)) 932 + strlen ((const char *) object->class_pointer->name)]; 933 934 sprintf (msg, "(%s) %s does not recognize %s", 935 (CLS_ISMETA (object->class_pointer) 936 ? "class" 937 : "instance" ), 938 object->class_pointer->name, sel_getName (sel)); 939 940 /* The object doesn't respond to doesNotRecognize:. Therefore, a 941 default action is taken. */ 942 _objc_abort ("%s\n", msg); 943 944 return 0; 945 } 946 } 947 948 void 949 __objc_print_dtable_stats (void) 950 { 951 int total = 0; 952 953 objc_mutex_lock (__objc_runtime_mutex); 954 955 #ifdef OBJC_SPARSE2 956 printf ("memory usage: (%s)\n", "2-level sparse arrays"); 957 #else 958 printf ("memory usage: (%s)\n", "3-level sparse arrays"); 959 #endif 960 961 printf ("arrays: %d = %ld bytes\n", narrays, 962 (long) ((size_t) narrays * sizeof (struct sarray))); 963 total += narrays * sizeof (struct sarray); 964 printf ("buckets: %d = %ld bytes\n", nbuckets, 965 (long) ((size_t) nbuckets * sizeof (struct sbucket))); 966 total += nbuckets * sizeof (struct sbucket); 967 968 printf ("idxtables: %d = %ld bytes\n", 969 idxsize, (long) ((size_t) idxsize * sizeof (void *))); 970 total += idxsize * sizeof (void *); 971 printf ("-----------------------------------\n"); 972 printf ("total: %d bytes\n", total); 973 printf ("===================================\n"); 974 975 objc_mutex_unlock (__objc_runtime_mutex); 976 } 977 978 static cache_ptr prepared_dtable_table = 0; 979 980 /* This function is called by: objc_msg_lookup, get_imp and 981 __objc_responds_to (and the dispatch table installation functions 982 themselves) to install a dispatch table for a class. 983 984 If CLS is a class, it installs instance methods. 985 If CLS is a meta class, it installs class methods. 986 987 In either case +initialize is invoked for the corresponding class. 988 989 The implementation must insure that the dispatch table is not 990 installed until +initialize completes. Otherwise it opens a 991 potential race since the installation of the dispatch table is used 992 as gate in regular method dispatch and we need to guarantee that 993 +initialize is the first method invoked an that no other thread my 994 dispatch messages to the class before +initialize completes. */ 995 static void 996 __objc_install_dtable_for_class (Class cls) 997 { 998 /* If the class has not yet had its class links resolved, we must 999 re-compute all class links. */ 1000 if (! CLS_ISRESOLV (cls)) 1001 __objc_resolve_class_links (); 1002 1003 /* Make sure the super class has its dispatch table installed or is 1004 at least preparing. We do not need to send initialize for the 1005 super class since __objc_send_initialize will insure that. */ 1006 if (cls->super_class 1007 && cls->super_class->dtable == __objc_uninstalled_dtable 1008 && !__objc_prepared_dtable_for_class (cls->super_class)) 1009 { 1010 __objc_install_dtable_for_class (cls->super_class); 1011 /* The superclass initialisation may have also initialised the 1012 current class, in which case there is no more to do. */ 1013 if (cls->dtable != __objc_uninstalled_dtable) 1014 return; 1015 } 1016 1017 /* We have already been prepared but +initialize hasn't completed. 1018 The +initialize implementation is probably sending 'self' 1019 messages. We rely on _objc_get_prepared_imp to retrieve the 1020 implementation pointers. */ 1021 if (__objc_prepared_dtable_for_class (cls)) 1022 return; 1023 1024 /* We have this function cache the implementation pointers for 1025 _objc_get_prepared_imp but the dispatch table won't be initilized 1026 until __objc_send_initialize completes. */ 1027 __objc_prepare_dtable_for_class (cls); 1028 1029 /* We may have already invoked +initialize but 1030 __objc_update_dispatch_table_for_class invoked by 1031 class_add_method_list may have reset dispatch table. */ 1032 1033 /* Call +initialize. If we are a real class, we are installing 1034 instance methods. If we are a meta class, we are installing 1035 class methods. The __objc_send_initialize itself will insure 1036 that the message is called only once per class. */ 1037 if (CLS_ISCLASS (cls)) 1038 __objc_send_initialize (cls); 1039 else 1040 { 1041 /* Retrieve the class from the meta class. */ 1042 Class c = objc_getClass (cls->name); 1043 assert (CLS_ISMETA (cls)); 1044 assert (c); 1045 __objc_send_initialize (c); 1046 } 1047 1048 /* We install the dispatch table correctly when +initialize completed. */ 1049 __objc_install_prepared_dtable_for_class (cls); 1050 } 1051 1052 /* Builds the dispatch table for the class CLS and stores it in a 1053 place where it can be retrieved by __objc_get_prepared_imp until 1054 __objc_install_prepared_dtable_for_class installs it into the 1055 class. The dispatch table should not be installed into the class 1056 until +initialize has completed. */ 1057 static void 1058 __objc_prepare_dtable_for_class (Class cls) 1059 { 1060 struct sarray *dtable; 1061 struct sarray *super_dtable; 1062 1063 /* This table could be initialized in init.c. We can not use the 1064 class name since the class maintains the instance methods and the 1065 meta class maintains the the class methods yet both share the 1066 same name. Classes should be unique in any program. */ 1067 if (! prepared_dtable_table) 1068 prepared_dtable_table 1069 = objc_hash_new (32, 1070 (hash_func_type) objc_hash_ptr, 1071 (compare_func_type) objc_compare_ptrs); 1072 1073 /* If the class has not yet had its class links resolved, we must 1074 re-compute all class links. */ 1075 if (! CLS_ISRESOLV (cls)) 1076 __objc_resolve_class_links (); 1077 1078 assert (cls); 1079 assert (cls->dtable == __objc_uninstalled_dtable); 1080 1081 /* If there is already a prepared dtable for this class, we must 1082 replace it with a new version (since there must have been methods 1083 added to or otherwise modified in the class while executing 1084 +initialize, and the table needs to be recomputed. */ 1085 dtable = __objc_prepared_dtable_for_class (cls); 1086 if (dtable != 0) 1087 { 1088 objc_hash_remove (prepared_dtable_table, cls); 1089 sarray_free (dtable); 1090 } 1091 1092 /* Now prepare the dtable for population. */ 1093 assert (cls != cls->super_class); 1094 if (cls->super_class) 1095 { 1096 /* Inherit the method list from the super class. Yet the super 1097 class may still be initializing in the case when a class 1098 cluster sub class initializes its super classes. */ 1099 if (cls->super_class->dtable == __objc_uninstalled_dtable) 1100 __objc_install_dtable_for_class (cls->super_class); 1101 1102 super_dtable = cls->super_class->dtable; 1103 /* If the dispatch table is not yet installed, we are still in 1104 the process of executing +initialize. Yet the dispatch table 1105 should be available. */ 1106 if (super_dtable == __objc_uninstalled_dtable) 1107 super_dtable = __objc_prepared_dtable_for_class (cls->super_class); 1108 1109 assert (super_dtable); 1110 dtable = sarray_lazy_copy (super_dtable); 1111 } 1112 else 1113 dtable = sarray_new (__objc_selector_max_index, 0); 1114 1115 __objc_install_methods_in_dtable (dtable, cls->methods); 1116 1117 objc_hash_add (&prepared_dtable_table, 1118 cls, 1119 dtable); 1120 } 1121 1122 /* This wrapper only exists to allow an easy replacement of the lookup 1123 implementation and it is expected that the compiler will optimize 1124 it away. */ 1125 static struct sarray * 1126 __objc_prepared_dtable_for_class (Class cls) 1127 { 1128 struct sarray *dtable = 0; 1129 assert (cls); 1130 if (prepared_dtable_table) 1131 dtable = objc_hash_value_for_key (prepared_dtable_table, cls); 1132 /* dtable my be nil, since we call this to check whether we are 1133 currently preparing before we start preparing. */ 1134 return dtable; 1135 } 1136 1137 /* Helper function for messages sent to CLS or implementation pointers 1138 retrieved from CLS during +initialize before the dtable is 1139 installed. When a class implicitly initializes another class which 1140 in turn implicitly invokes methods in this class, before the 1141 implementation of +initialize of CLS completes, this returns the 1142 expected implementation. Forwarding remains the responsibility of 1143 objc_msg_lookup. This function should only be called under the 1144 global lock. */ 1145 static IMP 1146 __objc_get_prepared_imp (Class cls,SEL sel) 1147 { 1148 struct sarray *dtable; 1149 IMP imp; 1150 1151 assert (cls); 1152 assert (sel); 1153 assert (cls->dtable == __objc_uninstalled_dtable); 1154 dtable = __objc_prepared_dtable_for_class (cls); 1155 1156 assert (dtable); 1157 assert (dtable != __objc_uninstalled_dtable); 1158 imp = sarray_get_safe (dtable, (size_t) sel->sel_id); 1159 1160 /* imp may be Nil if the method does not exist and we may fallback 1161 to the forwarding implementation later. */ 1162 return imp; 1163 } 1164 1165 /* When this function is called +initialize should be completed. So 1166 now we are safe to install the dispatch table for the class so that 1167 they become available for other threads that may be waiting in the 1168 lock. */ 1169 static void 1170 __objc_install_prepared_dtable_for_class (Class cls) 1171 { 1172 assert (cls); 1173 assert (cls->dtable == __objc_uninstalled_dtable); 1174 cls->dtable = __objc_prepared_dtable_for_class (cls); 1175 1176 assert (cls->dtable); 1177 assert (cls->dtable != __objc_uninstalled_dtable); 1178 objc_hash_remove (prepared_dtable_table, cls); 1179 } 1180