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