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