objc_msgSend(id self, SEL _cmd, ...) 中SEL找到IMP的流程
以下是苹果开源代码中Runtime底层的部分删减后的汇编代码
ENTRY _objc_msgSend
ldr x13, [x0] // x13 = isa
and x16, x13, #ISA_MASK // x16 = class
cmp x0, #0 // nil check and tagged pointer check
b.le LNilOrTagged // (MSB tagged pointer looks negative)
LGetIsaDone:
CacheLookup NORMAL // calls imp or objc_msgSend_uncached
LNilOrTagged:
b.eq LReturnZero // nil check
END_ENTRY _objc_msgSend
1.首先会进入汇编中 ENTRY _objc_msgSend
2.如果指针小于等于 LNilOrTagged
直接return
返回
3.通过isa
找到相应类class
4.CacheLookup : NORMAL
CacheLookup
源码中注释为:
Locate the implementation for a selector in a class method cache.
在类的方法缓存中 为 SEL
定位到 IMP
。
5.此时全局搜索CacheLookup
,在objc_msg_arm64.s中会找到其对应的宏CacheHit
、CheckMiss
、add
。
.macro CacheLookup
1: CacheHit $0 // call or return imp
返回IMP,并执行
<1> MESSENGER_END_FAST 结束快速查找路径
<2> GETIMP 返回IMP
<3> LOOKUP
2: CheckMiss $0 // miss if bucket->sel == 0
执行
<1> GETIMP LGetImpMiss 没找到IMP
<2> __objc_msgSend_uncached
<3> __objc_msgLookup_uncached
3: add x12, x12, w11, UXTW #4 // x12 = buckets+(mask<<4)
执行
<1> CacheHit
<2> CheckMiss
<3> JumpMiss
6.当执行__objc_msgSend_uncached
时,说明没有相应缓存。将会在__objc_msgSend_uncached
中执行MethodTableLookup
。
STATIC_ENTRY __objc_msgSend_uncached
MethodTableLookup
END_ENTRY __objc_msgSend_uncached
在MethodTableLookup
的宏定义中会发现__class_lookupMethodAndLoadCache3
全局搜索__class_lookupMethodAndLoadCache3
发现没有什么多余的东西可以看,尝试去掉前边的_
后发现新大陆!
汇编通过_class_lookupMethodAndLoadCache3
方法跳转到了C,并且调用了lookUpImpOrForward
<