1/* GNU Objective C Runtime class related functions 2 Copyright (C) 1993-2020 Free Software Foundation, Inc. 3 Contributed by Kresten Krab Thorup and Dennis Glatting. 4 5 Lock-free class table code designed and written from scratch by 6 Nicola Pero, 2001. 7 8This file is part of GCC. 9 10GCC is free software; you can redistribute it and/or modify it under the 11terms of the GNU General Public License as published by the Free Software 12Foundation; either version 3, or (at your option) any later version. 13 14GCC is distributed in the hope that it will be useful, but WITHOUT ANY 15WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17details. 18 19Under Section 7 of GPL version 3, you are granted additional 20permissions described in the GCC Runtime Library Exception, version 213.1, as published by the Free Software Foundation. 22 23You should have received a copy of the GNU General Public License and 24a copy of the GCC Runtime Library Exception along with this program; 25see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 26<http://www.gnu.org/licenses/>. */ 27 28/* The code in this file critically affects class method invocation 29 speed. This long preamble comment explains why, and the issues 30 involved. 31 32 One of the traditional weaknesses of the GNU Objective-C runtime is 33 that class method invocations are slow. The reason is that when you 34 write 35 36 array = [NSArray new]; 37 38 this gets basically compiled into the equivalent of 39 40 array = [(objc_get_class ("NSArray")) new]; 41 42 objc_get_class returns the class pointer corresponding to the string 43 `NSArray'; and because of the lookup, the operation is more 44 complicated and slow than a simple instance method invocation. 45 46 Most high performance Objective-C code (using the GNU Objc runtime) 47 I had the opportunity to read (or write) work around this problem by 48 caching the class pointer: 49 50 Class arrayClass = [NSArray class]; 51 52 ... later on ... 53 54 array = [arrayClass new]; 55 array = [arrayClass new]; 56 array = [arrayClass new]; 57 58 In this case, you always perform a class lookup (the first one), but 59 then all the [arrayClass new] methods run exactly as fast as an 60 instance method invocation. It helps if you have many class method 61 invocations to the same class. 62 63 The long-term solution to this problem would be to modify the 64 compiler to output tables of class pointers corresponding to all the 65 class method invocations, and to add code to the runtime to update 66 these tables - that should in the end allow class method invocations 67 to perform precisely as fast as instance method invocations, because 68 no class lookup would be involved. I think the Apple Objective-C 69 runtime uses this technique. Doing this involves synchronized 70 modifications in the runtime and in the compiler. 71 72 As a first medicine to the problem, I [NP] have redesigned and 73 rewritten the way the runtime is performing class lookup. This 74 doesn't give as much speed as the other (definitive) approach, but 75 at least a class method invocation now takes approximately 4.5 times 76 an instance method invocation on my machine (it would take approx 12 77 times before the rewriting), which is a lot better. 78 79 One of the main reason the new class lookup is so faster is because 80 I implemented it in a way that can safely run multithreaded without 81 using locks - a so-called `lock-free' data structure. The atomic 82 operation is pointer assignment. The reason why in this problem 83 lock-free data structures work so well is that you never remove 84 classes from the table - and the difficult thing with lock-free data 85 structures is freeing data when is removed from the structures. */ 86 87#include "objc-private/common.h" 88#include "objc-private/error.h" 89#include "objc/runtime.h" 90#include "objc/thr.h" 91#include "objc-private/module-abi-8.h" /* For CLS_ISCLASS and similar. */ 92#include "objc-private/runtime.h" /* the kitchen sink */ 93#include "objc-private/sarray.h" /* For sarray_put_at_safe. */ 94#include "objc-private/selector.h" /* For sarray_put_at_safe. */ 95#include <string.h> /* For memset */ 96 97/* We use a table which maps a class name to the corresponding class 98 pointer. The first part of this file defines this table, and 99 functions to do basic operations on the table. The second part of 100 the file implements some higher level Objective-C functionality for 101 classes by using the functions provided in the first part to manage 102 the table. */ 103 104/** 105 ** Class Table Internals 106 **/ 107 108/* A node holding a class */ 109typedef struct class_node 110{ 111 struct class_node *next; /* Pointer to next entry on the list. 112 NULL indicates end of list. */ 113 114 const char *name; /* The class name string */ 115 int length; /* The class name string length */ 116 Class pointer; /* The Class pointer */ 117 118} *class_node_ptr; 119 120/* A table containing classes is a class_node_ptr (pointing to the 121 first entry in the table - if it is NULL, then the table is 122 empty). */ 123 124/* We have 1024 tables. Each table contains all class names which 125 have the same hash (which is a number between 0 and 1023). To look 126 up a class_name, we compute its hash, and get the corresponding 127 table. Once we have the table, we simply compare strings directly 128 till we find the one which we want (using the length first). The 129 number of tables is quite big on purpose (a normal big application 130 has less than 1000 classes), so that you shouldn't normally get any 131 collisions, and get away with a single comparison (which we can't 132 avoid since we need to know that you have got the right thing). */ 133#define CLASS_TABLE_SIZE 1024 134#define CLASS_TABLE_MASK 1023 135 136static class_node_ptr class_table_array[CLASS_TABLE_SIZE]; 137 138/* The table writing mutex - we lock on writing to avoid conflicts 139 between different writers, but we read without locks. That is 140 possible because we assume pointer assignment to be an atomic 141 operation. TODO: This is only true under certain circumstances, 142 which should be clarified. */ 143static objc_mutex_t __class_table_lock = NULL; 144 145/* CLASS_TABLE_HASH is how we compute the hash of a class name. It is 146 a macro - *not* a function - arguments *are* modified directly. 147 148 INDEX should be a variable holding an int; 149 HASH should be a variable holding an int; 150 CLASS_NAME should be a variable holding a (char *) to the class_name. 151 152 After the macro is executed, INDEX contains the length of the 153 string, and HASH the computed hash of the string; CLASS_NAME is 154 untouched. */ 155 156#define CLASS_TABLE_HASH(INDEX, HASH, CLASS_NAME) \ 157 do { \ 158 HASH = 0; \ 159 for (INDEX = 0; CLASS_NAME[INDEX] != '\0'; INDEX++) \ 160 { \ 161 HASH = (HASH << 4) ^ (HASH >> 28) ^ CLASS_NAME[INDEX]; \ 162 } \ 163 \ 164 HASH = (HASH ^ (HASH >> 10) ^ (HASH >> 20)) & CLASS_TABLE_MASK; \ 165 } while (0) 166 167/* Setup the table. */ 168static void 169class_table_setup (void) 170{ 171 /* Start - nothing in the table. */ 172 memset (class_table_array, 0, sizeof (class_node_ptr) * CLASS_TABLE_SIZE); 173 174 /* The table writing mutex. */ 175 __class_table_lock = objc_mutex_allocate (); 176} 177 178 179/* Insert a class in the table (used when a new class is 180 registered). */ 181static void 182class_table_insert (const char *class_name, Class class_pointer) 183{ 184 int hash, length; 185 class_node_ptr new_node; 186 187 /* Find out the class name's hash and length. */ 188 CLASS_TABLE_HASH (length, hash, class_name); 189 190 /* Prepare the new node holding the class. */ 191 new_node = objc_malloc (sizeof (struct class_node)); 192 new_node->name = class_name; 193 new_node->length = length; 194 new_node->pointer = class_pointer; 195 196 /* Lock the table for modifications. */ 197 objc_mutex_lock (__class_table_lock); 198 199 /* Insert the new node in the table at the beginning of the table at 200 class_table_array[hash]. */ 201 new_node->next = class_table_array[hash]; 202 class_table_array[hash] = new_node; 203 204 objc_mutex_unlock (__class_table_lock); 205} 206 207/* Get a class from the table. This does not need mutex protection. 208 Currently, this function is called each time you call a static 209 method, this is why it must be very fast. */ 210static inline Class 211class_table_get_safe (const char *class_name) 212{ 213 class_node_ptr node; 214 int length, hash; 215 216 /* Compute length and hash. */ 217 CLASS_TABLE_HASH (length, hash, class_name); 218 219 node = class_table_array[hash]; 220 221 if (node != NULL) 222 { 223 do 224 { 225 if (node->length == length) 226 { 227 /* Compare the class names. */ 228 int i; 229 230 for (i = 0; i < length; i++) 231 { 232 if ((node->name)[i] != class_name[i]) 233 break; 234 } 235 236 if (i == length) 237 { 238 /* They are equal! */ 239 return node->pointer; 240 } 241 } 242 } 243 while ((node = node->next) != NULL); 244 } 245 246 return Nil; 247} 248 249/* Enumerate over the class table. */ 250struct class_table_enumerator 251{ 252 int hash; 253 class_node_ptr node; 254}; 255 256 257static Class 258class_table_next (struct class_table_enumerator **e) 259{ 260 struct class_table_enumerator *enumerator = *e; 261 class_node_ptr next; 262 263 if (enumerator == NULL) 264 { 265 *e = objc_malloc (sizeof (struct class_table_enumerator)); 266 enumerator = *e; 267 enumerator->hash = 0; 268 enumerator->node = NULL; 269 270 next = class_table_array[enumerator->hash]; 271 } 272 else 273 next = enumerator->node->next; 274 275 if (next != NULL) 276 { 277 enumerator->node = next; 278 return enumerator->node->pointer; 279 } 280 else 281 { 282 enumerator->hash++; 283 284 while (enumerator->hash < CLASS_TABLE_SIZE) 285 { 286 next = class_table_array[enumerator->hash]; 287 if (next != NULL) 288 { 289 enumerator->node = next; 290 return enumerator->node->pointer; 291 } 292 enumerator->hash++; 293 } 294 295 /* Ok - table finished - done. */ 296 objc_free (enumerator); 297 return Nil; 298 } 299} 300 301#if 0 /* DEBUGGING FUNCTIONS */ 302/* Debugging function - print the class table. */ 303void 304class_table_print (void) 305{ 306 int i; 307 308 for (i = 0; i < CLASS_TABLE_SIZE; i++) 309 { 310 class_node_ptr node; 311 312 printf ("%d:\n", i); 313 node = class_table_array[i]; 314 315 while (node != NULL) 316 { 317 printf ("\t%s\n", node->name); 318 node = node->next; 319 } 320 } 321} 322 323/* Debugging function - print an histogram of number of classes in 324 function of hash key values. Useful to evaluate the hash function 325 in real cases. */ 326void 327class_table_print_histogram (void) 328{ 329 int i, j; 330 int counter = 0; 331 332 for (i = 0; i < CLASS_TABLE_SIZE; i++) 333 { 334 class_node_ptr node; 335 336 node = class_table_array[i]; 337 338 while (node != NULL) 339 { 340 counter++; 341 node = node->next; 342 } 343 if (((i + 1) % 50) == 0) 344 { 345 printf ("%4d:", i + 1); 346 for (j = 0; j < counter; j++) 347 printf ("X"); 348 349 printf ("\n"); 350 counter = 0; 351 } 352 } 353 printf ("%4d:", i + 1); 354 for (j = 0; j < counter; j++) 355 printf ("X"); 356 357 printf ("\n"); 358} 359#endif /* DEBUGGING FUNCTIONS */ 360 361/** 362 ** Objective-C runtime functions 363 **/ 364 365/* From now on, the only access to the class table data structure 366 should be via the class_table_* functions. */ 367 368/* This is a hook which is called by objc_get_class and 369 objc_lookup_class if the runtime is not able to find the class. 370 This may e.g. try to load in the class using dynamic loading. 371 372 This hook was a public, global variable in the Traditional GNU 373 Objective-C Runtime API (objc/objc-api.h). The modern GNU 374 Objective-C Runtime API (objc/runtime.h) provides the 375 objc_setGetUnknownClassHandler() function instead. 376*/ 377Class (*_objc_lookup_class) (const char *name) = 0; /* !T:SAFE */ 378 379/* The handler currently in use. PS: if both 380 __obj_get_unknown_class_handler and _objc_lookup_class are defined, 381 __objc_get_unknown_class_handler is called first. */ 382static objc_get_unknown_class_handler 383__objc_get_unknown_class_handler = NULL; 384 385objc_get_unknown_class_handler 386objc_setGetUnknownClassHandler (objc_get_unknown_class_handler 387 new_handler) 388{ 389 objc_get_unknown_class_handler old_handler 390 = __objc_get_unknown_class_handler; 391 __objc_get_unknown_class_handler = new_handler; 392 return old_handler; 393} 394 395 396/* True when class links has been resolved. */ 397BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */ 398 399 400void 401__objc_init_class_tables (void) 402{ 403 /* Allocate the class hash table. */ 404 405 if (__class_table_lock) 406 return; 407 408 objc_mutex_lock (__objc_runtime_mutex); 409 410 class_table_setup (); 411 412 objc_mutex_unlock (__objc_runtime_mutex); 413} 414 415/* This function adds a class to the class hash table, and assigns the 416 class a number, unless it's already known. Return 'YES' if the 417 class was added. Return 'NO' if the class was already known. */ 418BOOL 419__objc_add_class_to_hash (Class class) 420{ 421 Class existing_class; 422 423 objc_mutex_lock (__objc_runtime_mutex); 424 425 /* Make sure the table is there. */ 426 assert (__class_table_lock); 427 428 /* Make sure it's not a meta class. */ 429 assert (CLS_ISCLASS (class)); 430 431 /* Check to see if the class is already in the hash table. */ 432 existing_class = class_table_get_safe (class->name); 433 434 if (existing_class) 435 { 436 objc_mutex_unlock (__objc_runtime_mutex); 437 return NO; 438 } 439 else 440 { 441 /* The class isn't in the hash table. Add the class and assign 442 a class number. */ 443 static unsigned int class_number = 1; 444 445 CLS_SETNUMBER (class, class_number); 446 CLS_SETNUMBER (class->class_pointer, class_number); 447 448 ++class_number; 449 class_table_insert (class->name, class); 450 451 objc_mutex_unlock (__objc_runtime_mutex); 452 return YES; 453 } 454} 455 456Class 457objc_getClass (const char *name) 458{ 459 Class class; 460 461 if (name == NULL) 462 return Nil; 463 464 class = class_table_get_safe (name); 465 466 if (class) 467 return class; 468 469 if (__objc_get_unknown_class_handler) 470 return (*__objc_get_unknown_class_handler) (name); 471 472 if (_objc_lookup_class) 473 return (*_objc_lookup_class) (name); 474 475 return Nil; 476} 477 478Class 479objc_lookUpClass (const char *name) 480{ 481 if (name == NULL) 482 return Nil; 483 else 484 return class_table_get_safe (name); 485} 486 487Class 488objc_getMetaClass (const char *name) 489{ 490 Class class = objc_getClass (name); 491 492 if (class) 493 return class->class_pointer; 494 else 495 return Nil; 496} 497 498Class 499objc_getRequiredClass (const char *name) 500{ 501 Class class = objc_getClass (name); 502 503 if (class) 504 return class; 505 else 506 _objc_abort ("objc_getRequiredClass ('%s') failed: class not found\n", name); 507} 508 509int 510objc_getClassList (Class *returnValue, int maxNumberOfClassesToReturn) 511{ 512 /* Iterate over all entries in the table. */ 513 int hash, count = 0; 514 515 for (hash = 0; hash < CLASS_TABLE_SIZE; hash++) 516 { 517 class_node_ptr node = class_table_array[hash]; 518 519 while (node != NULL) 520 { 521 if (returnValue) 522 { 523 if (count < maxNumberOfClassesToReturn) 524 returnValue[count] = node->pointer; 525 else 526 return count; 527 } 528 count++; 529 node = node->next; 530 } 531 } 532 533 return count; 534} 535 536Class 537objc_allocateClassPair (Class super_class, const char *class_name, size_t extraBytes) 538{ 539 Class new_class; 540 Class new_meta_class; 541 542 if (class_name == NULL) 543 return Nil; 544 545 if (objc_getClass (class_name)) 546 return Nil; 547 548 if (super_class) 549 { 550 /* If you want to build a hierarchy of classes, you need to 551 build and register them one at a time. The risk is that you 552 are able to cause confusion by registering a subclass before 553 the superclass or similar. */ 554 if (CLS_IS_IN_CONSTRUCTION (super_class)) 555 return Nil; 556 } 557 558 /* Technically, we should create the metaclass first, then use 559 class_createInstance() to create the class. That complication 560 would be relevant if we had class variables, but we don't, so we 561 just ignore it and create everything directly and assume all 562 classes have the same size. */ 563 new_class = objc_calloc (1, sizeof (struct objc_class) + extraBytes); 564 new_meta_class = objc_calloc (1, sizeof (struct objc_class) + extraBytes); 565 566 /* We create an unresolved class, similar to one generated by the 567 compiler. It will be resolved later when we register it. 568 569 Note how the metaclass details are not that important; when the 570 class is resolved, the ones that matter will be fixed up. */ 571 new_class->class_pointer = new_meta_class; 572 new_meta_class->class_pointer = 0; 573 574 if (super_class) 575 { 576 /* Force the name of the superclass in place of the link to the 577 actual superclass, which will be put there when the class is 578 resolved. */ 579 const char *super_class_name = class_getName (super_class); 580 new_class->super_class = (void *)super_class_name; 581 new_meta_class->super_class = (void *)super_class_name; 582 } 583 else 584 { 585 new_class->super_class = (void *)0; 586 new_meta_class->super_class = (void *)0; 587 } 588 589 new_class->name = objc_malloc (strlen (class_name) + 1); 590 strcpy ((char*)new_class->name, class_name); 591 new_meta_class->name = new_class->name; 592 593 new_class->version = 0; 594 new_meta_class->version = 0; 595 596 new_class->info = _CLS_CLASS | _CLS_IN_CONSTRUCTION; 597 new_meta_class->info = _CLS_META | _CLS_IN_CONSTRUCTION; 598 599 if (super_class) 600 new_class->instance_size = super_class->instance_size; 601 else 602 new_class->instance_size = 0; 603 new_meta_class->instance_size = sizeof (struct objc_class); 604 605 return new_class; 606} 607 608void 609objc_registerClassPair (Class class_) 610{ 611 if (class_ == Nil) 612 return; 613 614 if ((! CLS_ISCLASS (class_)) || (! CLS_IS_IN_CONSTRUCTION (class_))) 615 return; 616 617 if ((! CLS_ISMETA (class_->class_pointer)) || (! CLS_IS_IN_CONSTRUCTION (class_->class_pointer))) 618 return; 619 620 objc_mutex_lock (__objc_runtime_mutex); 621 622 if (objc_getClass (class_->name)) 623 { 624 objc_mutex_unlock (__objc_runtime_mutex); 625 return; 626 } 627 628 CLS_SET_NOT_IN_CONSTRUCTION (class_); 629 CLS_SET_NOT_IN_CONSTRUCTION (class_->class_pointer); 630 631 __objc_init_class (class_); 632 633 /* Resolve class links immediately. No point in waiting. */ 634 __objc_resolve_class_links (); 635 636 objc_mutex_unlock (__objc_runtime_mutex); 637} 638 639void 640objc_disposeClassPair (Class class_) 641{ 642 if (class_ == Nil) 643 return; 644 645 if ((! CLS_ISCLASS (class_)) || (! CLS_IS_IN_CONSTRUCTION (class_))) 646 return; 647 648 if ((! CLS_ISMETA (class_->class_pointer)) || (! CLS_IS_IN_CONSTRUCTION (class_->class_pointer))) 649 return; 650 651 /* Undo any class_addIvar(). */ 652 if (class_->ivars) 653 { 654 int i; 655 for (i = 0; i < class_->ivars->ivar_count; i++) 656 { 657 struct objc_ivar *ivar = &(class_->ivars->ivar_list[i]); 658 659 objc_free ((char *)ivar->ivar_name); 660 objc_free ((char *)ivar->ivar_type); 661 } 662 663 objc_free (class_->ivars); 664 } 665 666 /* Undo any class_addMethod(). */ 667 if (class_->methods) 668 { 669 struct objc_method_list *list = class_->methods; 670 while (list) 671 { 672 int i; 673 struct objc_method_list *next = list->method_next; 674 675 for (i = 0; i < list->method_count; i++) 676 { 677 struct objc_method *method = &(list->method_list[i]); 678 679 objc_free ((char *)method->method_name); 680 objc_free ((char *)method->method_types); 681 } 682 683 objc_free (list); 684 list = next; 685 } 686 } 687 688 /* Undo any class_addProtocol(). */ 689 if (class_->protocols) 690 { 691 struct objc_protocol_list *list = class_->protocols; 692 while (list) 693 { 694 struct objc_protocol_list *next = list->next; 695 696 objc_free (list); 697 list = next; 698 } 699 } 700 701 /* Undo any class_addMethod() on the meta-class. */ 702 if (class_->class_pointer->methods) 703 { 704 struct objc_method_list *list = class_->class_pointer->methods; 705 while (list) 706 { 707 int i; 708 struct objc_method_list *next = list->method_next; 709 710 for (i = 0; i < list->method_count; i++) 711 { 712 struct objc_method *method = &(list->method_list[i]); 713 714 objc_free ((char *)method->method_name); 715 objc_free ((char *)method->method_types); 716 } 717 718 objc_free (list); 719 list = next; 720 } 721 } 722 723 /* Undo objc_allocateClassPair(). */ 724 objc_free ((char *)(class_->name)); 725 objc_free (class_->class_pointer); 726 objc_free (class_); 727} 728 729/* Traditional GNU Objective-C Runtime API. Important: this method is 730 called automatically by the compiler while messaging (if using the 731 traditional ABI), so it is worth keeping it fast; don't make it 732 just a wrapper around objc_getClass(). */ 733/* Note that this is roughly equivalent to objc_getRequiredClass(). */ 734/* Get the class object for the class named NAME. If NAME does not 735 identify a known class, the hook _objc_lookup_class is called. If 736 this fails, an error message is issued and the system aborts. */ 737Class 738objc_get_class (const char *name) 739{ 740 Class class; 741 742 class = class_table_get_safe (name); 743 744 if (class) 745 return class; 746 747 if (__objc_get_unknown_class_handler) 748 class = (*__objc_get_unknown_class_handler) (name); 749 750 if ((!class) && _objc_lookup_class) 751 class = (*_objc_lookup_class) (name); 752 753 if (class) 754 return class; 755 756 _objc_abort ("objc runtime: cannot find class %s\n", name); 757 758 return 0; 759} 760 761/* This is used by the compiler too. */ 762Class 763objc_get_meta_class (const char *name) 764{ 765 return objc_get_class (name)->class_pointer; 766} 767 768/* This is not used by GCC, but the clang compiler seems to use it 769 when targeting the GNU runtime. That's wrong, but we have it to 770 be compatible. */ 771Class 772objc_lookup_class (const char *name) 773{ 774 return objc_getClass (name); 775} 776 777/* This is used when the implementation of a method changes. It goes 778 through all classes, looking for the ones that have these methods 779 (either method_a or method_b; method_b can be NULL), and reloads 780 the implementation for these. You should call this with the 781 runtime mutex already locked. */ 782void 783__objc_update_classes_with_methods (struct objc_method *method_a, struct objc_method *method_b) 784{ 785 int hash; 786 787 /* Iterate over all classes. */ 788 for (hash = 0; hash < CLASS_TABLE_SIZE; hash++) 789 { 790 class_node_ptr node = class_table_array[hash]; 791 792 while (node != NULL) 793 { 794 /* We execute this loop twice: the first time, we iterate 795 over all methods in the class (instance methods), while 796 the second time we iterate over all methods in the meta 797 class (class methods). */ 798 Class class = Nil; 799 BOOL done = NO; 800 801 while (done == NO) 802 { 803 struct objc_method_list * method_list; 804 805 if (class == Nil) 806 { 807 /* The first time, we work on the class. */ 808 class = node->pointer; 809 } 810 else 811 { 812 /* The second time, we work on the meta class. */ 813 class = class->class_pointer; 814 done = YES; 815 } 816 817 method_list = class->methods; 818 819 while (method_list) 820 { 821 int i; 822 823 for (i = 0; i < method_list->method_count; ++i) 824 { 825 struct objc_method *method = &method_list->method_list[i]; 826 827 /* If the method is one of the ones we are 828 looking for, update the implementation. */ 829 if (method == method_a) 830 sarray_at_put_safe (class->dtable, 831 (sidx) method_a->method_name->sel_id, 832 method_a->method_imp); 833 834 if (method == method_b) 835 { 836 if (method_b != NULL) 837 sarray_at_put_safe (class->dtable, 838 (sidx) method_b->method_name->sel_id, 839 method_b->method_imp); 840 } 841 } 842 843 method_list = method_list->method_next; 844 } 845 } 846 node = node->next; 847 } 848 } 849} 850 851/* Resolve super/subclass links for all classes. The only thing we 852 can be sure of is that the class_pointer for class objects point to 853 the right meta class objects. */ 854void 855__objc_resolve_class_links (void) 856{ 857 struct class_table_enumerator *es = NULL; 858 Class object_class = objc_get_class ("Object"); 859 Class class1; 860 861 assert (object_class); 862 863 objc_mutex_lock (__objc_runtime_mutex); 864 865 /* Assign subclass links. */ 866 while ((class1 = class_table_next (&es))) 867 { 868 /* Make sure we have what we think we have. */ 869 assert (CLS_ISCLASS (class1)); 870 assert (CLS_ISMETA (class1->class_pointer)); 871 872 /* The class_pointer of all meta classes point to Object's meta 873 class. */ 874 class1->class_pointer->class_pointer = object_class->class_pointer; 875 876 if (! CLS_ISRESOLV (class1)) 877 { 878 CLS_SETRESOLV (class1); 879 CLS_SETRESOLV (class1->class_pointer); 880 881 if (class1->super_class) 882 { 883 Class a_super_class 884 = objc_get_class ((char *) class1->super_class); 885 886 assert (a_super_class); 887 888 DEBUG_PRINTF ("making class connections for: %s\n", 889 class1->name); 890 891 /* Assign subclass links for superclass. */ 892 class1->sibling_class = a_super_class->subclass_list; 893 a_super_class->subclass_list = class1; 894 895 /* Assign subclass links for meta class of superclass. */ 896 if (a_super_class->class_pointer) 897 { 898 class1->class_pointer->sibling_class 899 = a_super_class->class_pointer->subclass_list; 900 a_super_class->class_pointer->subclass_list 901 = class1->class_pointer; 902 } 903 } 904 else /* A root class, make its meta object be a subclass of 905 Object. */ 906 { 907 class1->class_pointer->sibling_class 908 = object_class->subclass_list; 909 object_class->subclass_list = class1->class_pointer; 910 } 911 } 912 } 913 914 /* Assign superclass links. */ 915 es = NULL; 916 while ((class1 = class_table_next (&es))) 917 { 918 Class sub_class; 919 for (sub_class = class1->subclass_list; sub_class; 920 sub_class = sub_class->sibling_class) 921 { 922 sub_class->super_class = class1; 923 if (CLS_ISCLASS (sub_class)) 924 sub_class->class_pointer->super_class = class1->class_pointer; 925 } 926 } 927 928 objc_mutex_unlock (__objc_runtime_mutex); 929} 930 931const char * 932class_getName (Class class_) 933{ 934 if (class_ == Nil) 935 return "nil"; 936 937 return class_->name; 938} 939 940BOOL 941class_isMetaClass (Class class_) 942{ 943 /* CLS_ISMETA includes the check for Nil class_. */ 944 return CLS_ISMETA (class_); 945} 946 947/* Even inside libobjc it may be worth using class_getSuperclass 948 instead of accessing class_->super_class directly because it 949 resolves the class links if needed. If you access 950 class_->super_class directly, make sure to deal with the situation 951 where the class is not resolved yet! */ 952Class 953class_getSuperclass (Class class_) 954{ 955 if (class_ == Nil) 956 return Nil; 957 958 /* Classes that are in construction are not resolved, and still have 959 the class name (instead of a class pointer) in the 960 class_->super_class field. In that case we need to lookup the 961 superclass name to return the superclass. We cannot resolve the 962 class until it is registered. */ 963 if (CLS_IS_IN_CONSTRUCTION (class_)) 964 { 965 if (CLS_ISMETA (class_)) 966 return object_getClass ((id)objc_lookUpClass ((const char *)(class_->super_class))); 967 else 968 return objc_lookUpClass ((const char *)(class_->super_class)); 969 } 970 971 /* If the class is not resolved yet, super_class would point to a 972 string (the name of the super class) as opposed to the actual 973 super class. In that case, we need to resolve the class links 974 before we can return super_class. */ 975 if (! CLS_ISRESOLV (class_)) 976 __objc_resolve_class_links (); 977 978 return class_->super_class; 979} 980 981int 982class_getVersion (Class class_) 983{ 984 if (class_ == Nil) 985 return 0; 986 987 return (int)(class_->version); 988} 989 990void 991class_setVersion (Class class_, int version) 992{ 993 if (class_ == Nil) 994 return; 995 996 class_->version = version; 997} 998 999size_t 1000class_getInstanceSize (Class class_) 1001{ 1002 if (class_ == Nil) 1003 return 0; 1004 1005 return class_->instance_size; 1006} 1007 1008