⭐ 表示「核心逻辑内容」
? 表示「分支知识扩展」
表示「苹果官方文档或者源码」
本文分析用到的资源:
objc4-源码
可编译的 objc4 源码 (Cooci大神)
LLVM源码
LLVM 优化处理后的结果?
项目中最常用的初始化对象的几个方式 alloc
init
new
,但通过反汇编看出实际调用的并不是自身 NSObject.mm
方法的 IMP
而实际调用的是 objc_alloc
objc_alloc_init
objc_opt_new
_ (:з」∠) _ 年轻人不讲码德、、
alloc具体流程可参考:iOS底层探险① OC对象初始化流程
调试代码如下:
用 clang
(llvm的前端) 编译输出下编译后的cpp文件
步骤1:打开终端 cd
到 main.m
的文件夹
步骤2:输入指令 clang -rewrite-objc main.m -o main.cpp
-o
是输出的意思,后面紧接输出文件名 main.cpp
. ( cpp
是 c plus plus 的意思 c++的文件后缀)
可以看到 Clang
编译后的上述代码如下:
⭐ 之前的 OC 方法都被转换成了 objc_msgSend
, 而到这一步并不是最终执行的机器码, Clang
编译器前端生成的代码还行进行 LLVM IR 优化
优化之后针对目标CPU架构转汇编 通过汇编再换成最终执行的机器码, 所以 Clang
前端编译得出的代码并不一定是最终执行的代码,可能在中间 LLVM IR 优化
被处理过
汇编查看本质——最终执行代码:
LLVM 中间到底做了什么
通过 VSCode 打开下载好的 LLVM源码 搜索刚才优化后调用的 objc_opt_new
很快就能找到:g_opt_dispatch_names
⭐ g_opt_dispatch_names
是个 C++
全局 set
优化用的 方法符号
,在上方 LLVM
也给除了注释说明:
目的是加速方法分发发送,提高效率。 原因是AWZ、RR、CORE系列方法很少被重写,编译器进行了替换,执行对应方法的时候一步到位(避免了OC继承链冗长的方法查找流程,这几个方法应该是方法查找链最长的了)。 当然也有条件检测,如果有哪个方法被重写会走原来的 objc_msgSend
优化函数调用流程:
核心方法在 CGObjC.cpp
的 tryGenerateSpecializedMessageSend()
函数, 函数声明及注释如下:
注释的内容基本同上,目的为了让消息处理更快,如果有重写方法异常走原来的 objc_msgSend
⭐ 分析源码可以看到,最终在 CGF.EmitObjcAlloc
方法里完成了 OC 方法 alloc
换成优化方法 objc_alloc
如下图:
其他 LLVM IR
优化方法调用处理类似, 值得一提的是 OC [[MyClass alloc]init]
这样非单个函数的代码写法也是被优化的 优化方法在 tryEmitSpecializedAllocInit
源码进行了很多校验,包括了是否是同一个 Class
的 alloc
init
等等, 可以看出编译器级别的优化是非常非常细致的
,在写项目、SDK做性能优化可以借鉴。
补充 AWZ、RR、CORE系列方法是什么
AWZ
顾名思义是 allocWithZone
的缩写,包含alloc/allocWithZone
方法
RR
是 retain release
的缩写,主要包含 retain/release/autorelease
方法
CORE
是OC对象核心的一些方法,包含new/self/class/respondsToSelector/isKindOfClass
方法
可以在 objc4源码 objc-runtime-new.h
找到其定义
// class or superclass has default alloc/allocWithZone: implementation
// Note this is is stored in the metaclass.
#define FAST_CACHE_HAS_DEFAULT_AWZ (1<<14)
// class or superclass has default retain/release/autorelease/retainCount/
// _tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference
#define FAST_HAS_DEFAULT_RR (1UL<<2)
// class or superclass has default new/self/class/respondsToSelector/isKindOfClass
#define FAST_CACHE_HAS_DEFAULT_CORE (1<<15)
复制代码
写在最后
文章的代码环境基于苹果 objc4-818.2 源码、Xcode12,内容尽量做到了结构化、精炼,以便节省读者阅读时间成本,如有哪里书写不对或者补充欢迎及时交流沟通~~
最后,感谢您的阅读 一切祝好哈 have a nice codding \(^o^)/~