// Realize non-lazy classes (for +load methods and static instances) for (EACH_HEADER) { classref_tconst *classlist = hi->nlclslist(&count); for (i = 0; i < count; i++) { Class cls = remapClass(classlist[i]); if (!cls) continue; ///调试代码 确定是我们自定义的类 constchar *mangledName = cls->nonlazyMangledName(); constchar *customerClassName = "JSPerson"; if (strcmp(mangledName, customerClassName) == 0) { //打印类名 printf("%s -: non-lazy classes要研究的类: - %s\n",__func__,mangledName); }
addClassTableEntry(cls);
if (cls->isSwiftStable()) { if (cls->swiftMetadataInitializer()) { _objc_fatal("Swift class %s with a metadata initializer " "is not allowed to be non-lazy", cls->nameForLogging()); } // fixme also disallow relocatable classes // We can't disallow all Swift classes because of // classes like Swift.__EmptyArrayStorage } realizeClassWithoutSwift(cls, nil); } } ts.log("IMAGE TIMES: realize non-lazy classes"); // Realize newly-resolved future classes, in case CF manipulates them if (resolvedFutureClasses) { for (i = 0; i < resolvedFutureClassCount; i++) { Class cls = resolvedFutureClasses[i]; if (cls->isSwiftStable()) { _objc_fatal("Swift class is not allowed to be future"); } ///调试代码 确定是我们自定义的类 constchar *mangledName = cls->nonlazyMangledName(); constchar *customerClassName = "JSPerson"; if (strcmp(mangledName, customerClassName) == 0) { //打印类名 printf("%s -: realize future classes要研究的类: - %s\n",__func__,mangledName); } realizeClassWithoutSwift(cls, nil); cls->setInstancesRequireRawIsaRecursively(false/*inherited*/); } free(resolvedFutureClasses); } ts.log("IMAGE TIMES: realize future classes");
#if SUPPORT_NONPOINTER_ISA if (isMeta) { // Metaclasses do not need any features from non pointer ISA // This allows for a faspath for classes in objc_retain/objc_release. ///元类 不是non pointer ISA cls->setInstancesRequireRawIsa(); } else { // Disable non-pointer isa for some classes and/or platforms. // Set instancesRequireRawIsa. bool instancesRequireRawIsa = cls->instancesRequireRawIsa(); bool rawIsaIsInherited = false; staticbool hackedDispatch = false;
if (DisableNonpointerIsa) { //如果我们设置变量不使用 non pointer ISA 也会是纯的isa // Non-pointer isa disabled by environment or app SDK version instancesRequireRawIsa = true; } elseif (!hackedDispatch && 0 == strcmp(ro->getName(), "OS_object")) { // hack for libdispatch et al - isa also acts as vtable pointer hackedDispatch = true; instancesRequireRawIsa = true; } elseif (supercls && supercls->getSuperclass() && supercls->instancesRequireRawIsa()) { // This is also propagated by addSubclass() // but nonpointer isa setup needs it earlier. // Special case: instancesRequireRawIsa does not propagate // from root class to root metaclass instancesRequireRawIsa = true; rawIsaIsInherited = true; }
if (instancesRequireRawIsa) { cls->setInstancesRequireRawIsaRecursively(rawIsaIsInherited); } } // SUPPORT_NONPOINTER_ISA #endif // Update superclass and metaclass in case of remapping cls->setSuperclass(supercls); cls->initClassIsa(metacls);
staticvoidmethodizeClass(Class cls, Class previously) { runtimeLock.assertLocked(); bool isMeta = cls->isMetaClass(); auto rw = cls->data(); auto ro = rw->ro(); auto rwe = rw->ext(); // Methodizing for the first time if (PrintConnecting) { _objc_inform("CLASS: methodizing class '%s' %s", cls->nameForLogging(), isMeta ? "(meta)" : ""); } ///调试代码 确定是我们自定义的类 constchar *mangledName = cls->nonlazyMangledName(); constchar *customerClassName = "JSPerson"; if (strcmp(mangledName, customerClassName) == 0) { //打印类名 if (!isMeta) { printf("%s -: non-lazy classes要研究的类: - %s\n",__func__,mangledName); } } // Install methods and properties that the class implements itself. //取出方法列表 method_list_t *list = ro->baseMethods(); if (list) { prepareMethodLists(cls, &list, 1, YES, isBundleClass(cls), nullptr); if (rwe) rwe->methods.attachLists(&list, 1); } property_list_t *proplist = ro->baseProperties; if (rwe && proplist) { rwe->properties.attachLists(&proplist, 1); } protocol_list_t *protolist = ro->baseProtocols; if (rwe && protolist) { rwe->protocols.attachLists(&protolist, 1); } // Root classes get bonus method implementations if they don't have // them already. These apply before category replacements. if (cls->isRootMetaclass()) { // root metaclass addMethod(cls, @selector(initialize), (IMP)&objc_noop_imp, "", NO); } // Attach categories. if (previously) { if (isMeta) { objc::unattachedCategories.attachToClass(cls, previously, ATTACH_METACLASS); } else { // When a class relocates, categories with class methods // may be registered on the class itself rather than on // the metaclass. Tell attachToClass to look for those. objc::unattachedCategories.attachToClass(cls, previously, ATTACH_CLASS_AND_METACLASS); } } objc::unattachedCategories.attachToClass(cls, cls, isMeta ? ATTACH_METACLASS : ATTACH_CLASS);
#if DEBUG // Debug: sanity-check all SELs; log method list contents for (constauto& meth : rw->methods()) { if (PrintConnecting) { _objc_inform("METHOD %c[%s %s]", isMeta ? '+' : '-', cls->nameForLogging(), sel_getName(meth.name())); } ASSERT(sel_registerName(sel_getName(meth.name())) == meth.name()); } #endif }
staticvoid prepareMethodLists(Class cls, method_list_t **addedLists, int addedCount, bool baseMethods, bool methodsFromBundle, constchar *why) { runtimeLock.assertLocked(); if (addedCount == 0) return; // There exist RR/AWZ/Core special cases for some class's base methods. // But this code should never need to scan base methods for RR/AWZ/Core: // default RR/AWZ/Core cannot be set before setInitialized(). // Therefore we need not handle any special cases here. if (baseMethods) { ASSERT(cls->hasCustomAWZ() && cls->hasCustomRR() && cls->hasCustomCore()); } elseif (cls->cache.isConstantOptimizedCache()) { cls->setDisallowPreoptCachesRecursively(why); } elseif (cls->allowsPreoptInlinedSels()) { #if CONFIG_USE_PREOPT_CACHES SEL *sels = (SEL *)objc_opt_offsets[OBJC_OPT_INLINED_METHODS_START]; SEL *sels_end = (SEL *)objc_opt_offsets[OBJC_OPT_INLINED_METHODS_END]; if (method_lists_contains_any(addedLists, addedLists + addedCount, sels, sels_end - sels)) { cls->setDisallowPreoptInlinedSelsRecursively(why); } #endif } // Add method lists to array. // Reallocate un-fixed method lists. // The new methods are PREPENDED to the method list array.
for (int i = 0; i < addedCount; i++) { method_list_t *mlist = addedLists[i]; ASSERT(mlist); // Fixup selectors if necessary if (!mlist->isFixedUp()) { //核心代码 fixupMethodList(mlist, methodsFromBundle, true/*sort*/); } }
// If the class is initialized, then scan for method implementations // tracked by the class's flags. If it's not initialized yet, // then objc_class::setInitialized() will take care of it. if (cls->isInitialized()) { objc::AWZScanner::scanAddedMethodLists(cls, addedLists, addedCount); objc::RRScanner::scanAddedMethodLists(cls, addedLists, addedCount); objc::CoreScanner::scanAddedMethodLists(cls, addedLists, addedCount); } }
staticvoid fixupMethodList(method_list_t *mlist, bool bundleCopy, bool sort) { runtimeLock.assertLocked(); ASSERT(!mlist->isFixedUp()); // fixme lock less in attachMethodLists ? // dyld3 may have already uniqued, but not sorted, the list if (!mlist->isUniqued()) { mutex_locker_tlock(selLock); // Unique selectors in list. for (auto& meth : *mlist) { constchar *name = sel_cname(meth.name()); meth.setName(sel_registerNameNoLock(name, bundleCopy)); } } // Sort by selector address. // Don't try to sort small lists, as they're immutable. // Don't try to sort big lists of nonstandard size, as stable_sort // won't copy the entries properly. if (sort && !mlist->isSmallList() && mlist->entsize() == method_t::bigSize) { method_t::SortBySELAddress sorter; std::stable_sort(&mlist->begin()->big(), &mlist->end()->big(), sorter); } // Mark method list as uniqued and sorted. // Can't mark small lists, since they're immutable. if (!mlist->isSmallList()) { mlist->setFixedUp(); } }