本文由快学吧个人写作,以任何形式转载请表明原文出处
一、材料预备
objc4-818.2
对应mac的版本是11.1。可根据自己的系统版本挑选可以进行调试的源码。
二、思路
- 为什么要看objc_msgSend?
调用办法的实质便是objc_msgSend
- objc_msgSend在哪里?
在runtime中
- objc_msgSend是什么写的?
汇编
- objc_msgSend为什么用汇编?
C言语是静态言语。不行能写一个函数用来保留不知道的参数,还要做到跳转任一函数的指针。
汇编是更挨近机器指令的言语,
objc_msgSend
的功用就决定了它需要更快。
- 为什么要用objc4的源码?
由于objc_msgSend的源码是在
libobjc.A.dyld
库中,objc4里有这个库。
三、创立代码
- 在818.2中创立一个类(我创立的是JDPerson),继承于NSObject。而且界说一个实例办法。然后在main.m中创立实例,并调用这个实例办法。并在调用实例办法这一行打断点。
- 翻开汇编
- 运行项目
四、有关汇编的简单根底
五、objc_msgSend的源码
1. 如何找到objc_msgSend的源码
在818.2的源码中查找objc_msgSend
,找到arm64环境下的objc_msgSend
,并在其间找到带ENTRY
的objc_msgSend
,由于ENTRY
是进入的意思。
2. objc_msgSend汇编解析
1. ENTRY _objc_msgSend
,对消息接收者(id self,sel _cmd
)判别处理,tagged pointer判别处理。
2. GetClassFromIsa_p16
关于isa指针的处理,获得class(类)。
文件内查找GetClassFromIsa_p16
。找到源码后,对其间的#if SUPPORT_INDEXED_ISA
不需要看它里面的内容,找__LP64__
。
这里的ExtractISA
还不知道是什么,大局查找ExtractISA
:
这里的$1
便是isa
,$0
= $1
& #ISA_MASK
。也便是类信息。
3. 回到主线,CacheLookup
查找缓存
(1). CacheLookup
的注释 :
(2). 一些宏界说,CacheLookup
源码中会用到的 :
(3). CacheLookup
源码解析 :
(4). CacheHit
射中缓存的源码 :
首要清晰一点,CacheLookup
是NORMAL
。
直接调用了一个TailCallCachedImp
。
(5).
六、总结
- objc_msgSend会对消息的接收者进行判别处理。
- objc_msgSend中的
GetClassFromIsa_p16
会对isa进行处理,获取其间的类信息。 - objc_msgSend会在
CacheLookup
中经过类的内存平移获取到缓存,在缓存中拿到mask和buckets,经过掩码获取到单独的buckets。经过cache_hash获取sel的索引,经过遍历buckets中的bucket_t,查找缓存中是否有要调用的办法的完成。