返回

iOS底层原理11:objc_msgSend慢速查找流程

IOS

在上一篇iOS底层原理10:objc_msgSend快速查找流程文章中,我们分析了快速查找流程,如果快速查不到,则会进入慢速查找流程,本文将分析慢速查找的流程。

慢速查找流程

上述的汇编流程,我们可以通过汇编调试来验证。在main中,[p say]对象方法调用处加一个断点。

开启汇编调试【product】->【debug executable】,选择【All CPU Subprocesses】调试子进程。在断点处停止后,使用单步指令【Step】进行调试,可以查看汇编指令的执行过程。

在慢速查找流程中,主要分为以下几个步骤:

  1. 通过objc_getClass方法获取类对象,然后通过class_getInstanceMethod方法获取方法实现。
  2. 比较方法实现的地址和方法列表的地址,如果相等,则说明找到了方法实现,直接调用。
  3. 如果方法实现的地址和方法列表的地址不相等,则说明没有找到方法实现,继续遍历方法列表,直到找到方法实现或者遍历完整个方法列表。
  4. 如果遍历完整个方法列表都没有找到方法实现,则说明该类中没有该方法,需要向上查找父类。
  5. 继续向上查找父类,直到找到方法实现或者遍历完所有父类。

汇编调试验证

在汇编调试中,我们可以看到慢速查找流程的具体执行过程。例如,在main中,[p say]对象方法调用处加一个断点,然后使用单步指令【Step】进行调试,可以看到以下汇编指令:

0x100060fb8: bl    0x100027b28 ; __objc_msgSendSuper2
0x100060fbd: mov   x1, #0x0
0x100060fc2: movk  x2, #0x2000, lsl #16
0x100060fc6: movk  x2, #0x18, lsl #0
0x100060fca: bl    0x100026538 ; __objc_msgSend

其中,0x100027b28是__objc_msgSendSuper2函数的地址,0x100026538是__objc_msgSend函数的地址。

在__objc_msgSend函数中,首先通过objc_getClass方法获取类对象,然后通过class_getInstanceMethod方法获取方法实现。如果方法实现的地址和方法列表的地址相等,则说明找到了方法实现,直接调用。否则,继续遍历方法列表,直到找到方法实现或者遍历完整个方法列表。

如果遍历完整个方法列表都没有找到方法实现,则说明该类中没有该方法,需要向上查找父类。继续向上查找父类,直到找到方法实现或者遍历完所有父类。

总结

慢速查找流程是objc_msgSend方法调用机制中的一种重要流程,它可以保证在快速查找流程无法找到方法实现时,也能找到正确的方法实现。通过汇编调试,我们可以看到慢速查找流程的具体执行过程,从而更深入地理解iOS底层原理。