voidcall_load_methods(void){staticBOOLloading=NO;BOOLmore_categories;recursive_mutex_assert_locked(&loadMethodLock);// Re-entrant calls do nothing; the outermost call will finish the job.if(loading)return;loading=YES;void*pool=objc_autoreleasePoolPush();do{// 1. Repeatedly call class +loads until there aren't any morewhile(loadable_classes_used>0){call_class_loads();}// 2. Call category +loads ONCEmore_categories=call_category_loads();// 3. Run more +loads if there are classes OR more untried categories}while(loadable_classes_used>0||more_categories);objc_autoreleasePoolPop(pool);loading=NO;}
staticvoidcall_class_loads(void){inti;// Detach current loadable list.structloadable_class*classes=loadable_classes;intused=loadable_classes_used;loadable_classes=nil;loadable_classes_allocated=0;loadable_classes_used=0;// Call all +loads for the detached list.for(i=0;i<used;i++){Classcls=classes[i].cls;load_method_tload_method=(load_method_t)classes[i].method;if(!cls)continue;if(PrintLoading){_objc_inform("LOAD: +[%s load]\n",cls->nameForLogging());}(*load_method)(cls,SEL_load);}// Destroy the detached list.if(classes)_free_internal(classes);}
IMPlookUpImpOrForward(Classcls,SELsel,idinst,boolinitialize,boolcache,boolresolver){...rwlock_unlock_write(&runtimeLock);}if(initialize&&!cls->isInitialized()){_class_initialize(_class_getNonMetaClass(cls,inst));// If sel == initialize, _class_initialize will send +initialize and // then the messenger will send +initialize again after this // procedure finishes. Of course, if this is not being called // from the messenger then it won't happen. 2778172}// The lock is held to make method-lookup + cache-fill atomic // with respect to method addition. Otherwise, a category could ...}
void_class_initialize(Classcls){...Classsupercls;BOOLreallyInitialize=NO;// Make sure super is done initializing BEFORE beginning to initialize cls.// See note about deadlock above.supercls=cls->superclass;if(supercls&&!supercls->isInitialized()){_class_initialize(supercls);}// Try to atomically set CLS_INITIALIZING.monitor_enter(&classInitLock);if(!cls->isInitialized()&&!cls->isInitializing()){cls->setInitializing();reallyInitialize=YES;}monitor_exit(&classInitLock);if(reallyInitialize){// We successfully set the CLS_INITIALIZING bit. Initialize the class.// Record that we're initializing this class so we can message it._setThisThreadIsInitializingClass(cls);// Send the +initialize message.// Note that +initialize is sent to the superclass (again) if // this class doesn't implement +initialize. 2157218if(PrintInitializing){_objc_inform("INITIALIZE: calling +[%s initialize]",cls->nameForLogging());}((void(*)(Class,SEL))objc_msgSend)(cls,SEL_initialize);if(PrintInitializing){_objc_inform("INITIALIZE: finished +[%s initialize]",...}