cache_t 读取流程分析

- 发现写入缓存之前地调用的是
log_and_fill_cache
- 再之前是
lookUpImpOrForward
- 然后就是
objc_msgSend_uncached
- 看来这个写入是在方法调用走消息发送的时候调用的
runtime运行时理解
[peson say];
[person sayHello];
((void (*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("say"));
((void (*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("sayHello"));
- 调用方法 其实就是发送消息 =
objc_msgSend(id, cmd), id 是消息的接受者就是对象, cmd = sel + 参数,也就是消息主体
- 所以我们也可以这样来调用方法
objc_msgSend(person, sel_registerName("sayHello")), objc_msgSend(person, @selector(sayHello))
- 需要导入头文件
#import <objc/message.h>


子类声明了方法,但没有方法的实现,父类有方法的实现
- 当
子类调用该方法时,不会crash,而是会调用父类的方法实现

+方法同样也不会crash,所以方法会向上查找,直到找到有实现该方法的父类
- 反之,子类有实现,而父类没有,父类的对象调用,则会
crash
objc_msgSendSuper也可以直接给父类发送消息,也就是直接调用父类的方法
struct objc_super wlw_objc_super;
wlw_objc_super.receiver = person;
wlw_objc_super.super_class = LGPerson.class;
objc_msgSendSuper(&wlw_objc_super,@selector(look));
objec_msgSend流程
objec_msgSend 在底层是使用汇编代码写了,为了更高效,快速

- 不同架构下汇编代码,我们主要就看
arm64真机的代码
- 找到
ENTRY入口


cmp(比较) p0 是否为空,也就是isa是否是空的
b.le(<= 跳转),b.eq(= 跳转) 如果是空的并且支持 tagged pointer, 查找一下是否有 tagged pointer,没有则返回 zero, 并结束消息查找流程
- 如果不为空,则通过
isa&ISA_MASK拿到类,赋值给p16
- 然后会走缓存查找流程,查找
imp快速查找流程或者走 objc_msgSend_uncached也就是慢速查找流程