在OC方法调用快查找流程底层逻辑探究中,我们分析了方法调用快查找的逻辑,所谓的快查找也就是对方法缓存列表的查找,如果没有命中缓存,则会进入到慢查找的逻辑,即对类的方法列表的查找,下面我们就来探究下OC底层是如何进行慢查找的。
在快查找未命中的出口,有如下的代码逻辑:
|
|
共同指向了MethodTableLookup这个方法,我们来看看这个方法的实现:
|
|
我们暂时忽略寄存器先关操作,主要看方法调用逻辑,可以看到,内部是调用了_lookUpImpOrForward 这个方法,看命名应该能猜到是跟imp的查找和转发逻辑相关,那我们找找这个函数的定义,发现在汇编代码中没有相关定义,我们去runtime原文件中看看,果然在objc_runtime-new.mm的6094行发现了该函数的定义:
|
|
以上源码就是慢查找的整个流程,整体是一个递归查找继承连的过程,其中还有一些小的点可以在扩展下。
扩展一 对当前方法列表的查找策略
我们可以深入看看代码逻辑
|
|
扩展二 默认的imp
在查找函数的最前面,有下面这行初始化代码:
|
|
这个默认的imp具体指向哪里,我们来全局查找一下:
|
|
在汇编代码中找到 __objc_forward_handler这里就线索中断,这个猜测应该是一个回调函数,ok,那我们去源代码里面看看。
|
|
是不是看到了我们非常熟悉的一个错误信息,没有错,这个默认的imp就是找不到方法实现的错误处理函数。此时,坑点也就出现了,如果你使用class_getMethodImplementation去查找一个未实现的方法时,不会返回空,而是返回这个函数的地址,这里需要注意一下。
小结
以上就是整个慢查找的流程和其中的一些相关的知识点的梳理,除了整体流程的分析,上面的两个扩展也是比较重要的。其中还有一些比较重要的内容没有做深入分析,如realizeClassMaybeSwiftAndLeaveLocked和initializeAndLeaveLocked,留到以后再做分析,毕竟这篇文章主要分析慢查找的流程。