1 IMP lookUpImpOrForward(idinst, SEL sel, Class cls, intbehavior) 2 {// cache 中没有找到方法,开始走 lookUpImpOrForward 查找流程 3// 汇编有调 --> objc_msgForward --> 找不到方法报错信息的处理 4 const IMP forward_imp = (IMP)_objc_msgForward_impcache; 5 IMP imp = nil; 6 Class curClass; 8 runtimeLock.assertUnlocked(); 10// Optimistic cache lookup 11if (fastpath(behavior & LOOKUP_CACHE)) { 12// 找缓存 - 是为了出现在此过程中方法又被人调用加进缓存了,有缓存了就不必继续慢速找了 13 imp = cache_getImp(cls, sel); 14if (imp) goto done_nolock;// 找到了,去 done_nolock 15 } 17// runtimeLock is held during isRealized and isInitialized checking 18// to prevent races against concurrent realization. 20// runtimeLock is held during method search to make 21// method-lookup + cache-fill atomic with respect to method addition. 22// Otherwise, a category could be added but ignored indefinitely because 23// the cache was re-filled with the old value after the cache flush on 24// behalf of the category. 25// 注释翻译不如英文准确不翻了 26 runtimeLock.lock(); 28// We don't want people to be able to craft a binary blob that looks like 29// a class but really isn't one and do a CFI attack. 30// 31// To make these harder we want to make sure this is a class that was 32// either built into the binary or legitimately registered through 33// objc_duplicateClass, objc_initializeClassPair or objc_allocateClassPair. 34// 35// TODO: this check is quite costly during process startup. 36 checkIsKnownClass(cls); 38if (slowpath(!cls->isRealized())) {// cls 是否已实现,否则去将类信息进行处理 类元类方法全部要处理好的 --> 为了后面的方法查找 39 cls = realizeClassMaybeSwiftAndLeaveLocked(cls, runtimeLock); 40// runtimeLock may have been dropped but is now locked again 41 } 43// initialize 初始化 44if (slowpath((behavior & LOOKUP_INITIALIZE) && !cls->isInitialized())) { 45 cls = initializeAndLeaveLocked(cls, inst, runtimeLock); 46// runtimeLock may have been dropped but is now locked again 48// If sel == initialize, class_initialize will send +initialize and 49// then the messenger will send +initialize again after this 50// procedure finishes. Of course, if this is not being called 51// from the messenger then it won't happen. 2778172 52 } 54 runtimeLock.assertLocked(); 55 curClass = cls; 57// The code used to lookpu the class's cache again right after 58// we take the lock but for the vast majority of the cases 59// evidence shows this is a miss most of the time, hence a time loss. 60// 61// The only codepath calling into this without having performed some 62// kind of cache lookup is class_getInstanceMethod(). 64for (unsigned attempts = unreasonableClassCount();;) {// 死循环,没有出口条件,跳出逻辑在循环内部 65// curClass method list. 66 Method meth = getMethodNoSuper_nolock(curClass, sel);// 查找方法 67if (meth) {// 找着了 68 imp = meth->imp; 69 goto done; 70 } 71// 自己没找着 72// curClass = superClass 73// 是nil 则直接 没找着方法把nil的forward_imp赋给imp,并跳出循环 74if (slowpath((curClass = curClass->superclass) == nil)) { 75// No implementation found, and method resolver didn't help. 76// Use forwarding. 77 imp = forward_imp; 78 break; 79 } 80// superclass 不是 nil 继续向下走 82// Halt if there is a cycle in the superclass chain. 83// 如果超类链中存在循环,则停止 84if (slowpath(--attempts == 0)) { 85_objc_fatal("Memory corruption in class list.");// 类列表的内存污染了 86 } 88// Superclass cache. 89// 找父类的缓存 90/** 91 CacheLookup GETIMP, _cache_getImp 92 */ 93 imp = cache_getImp(curClass, sel); 94/* 95 STATIC_ENTRY _cache_getImp 97 GetClassFromIsa_p16 p0 98 CacheLookup GETIMP, _cache_getImp // GETIMP,cache查找的参数是GETIMP,checkMiss 100 LGetImpMiss:// cache 中没找到直接返回0 101 mov p0, #0 102 ret 104 END_ENTRY _cache_getImp 105 */ 108if (slowpath(imp == forward_imp)) {// 109// Found a forward:: entry in a superclass. 110// Stop searching, but don't cache yet; call method 111// resolver for this class first. 112 break; 113 } 114if (fastpath(imp)) {// 父类中找到了 goto done --> 对此方法进行缓存 115// Found the method in a superclass. Cache it in this class. 116 goto done; 117 } 118 } 120// No implementation found. Try method resolver once. 121// 上面找完了没找着方法 动态方法解析 resolver 一次 --> 此方法只会走一次once 122if (slowpath(behavior & LOOKUP_RESOLVER)) {/* &:3 & 2 = 0011 & 0010 = 0010 第二次(方法动态处理中会再回来查一遍)再来条件就为false了: 0001 & 0010 = 0000 */ 123 behavior ^= LOOKUP_RESOLVER;// 异或操作 behavior = 0011^0010 = 0001 124 return resolveMethod_locked(inst, sel, cls, behavior); 125 } 127done: 128 log_and_fill_cache(cls, imp, sel, inst, curClass); 129 runtimeLock.unlock(); 130 done_nolock: 131if (slowpath((behavior & LOOKUP_NIL) && imp == forward_imp)) { 132 return nil; 133 } 134 return imp; 135 }