和谐学习!不急不躁!!我是你们的老朋友小青龙~
-
iOS底层分析之objc_msgSend消息转发
前面几篇文章带着大伙儿一步步的分析了objc_msgSend底层调用的大概流程,接下来我们对其做一个总结:
大致流程
详细流程
下面针对每一个做了什么,进行主要阐述:
_objc_msgSend{
非空判断;
得到isa;
得到Class;
CacheLookup NORMAL, _objc_msgSend, __objc_msgSend_uncached
}
CacheLookup{
/** 其实就是缓存查找的过程,
找到进入CacheHit,找不到就进入CacheLookup的第三个参数代表的函数*/
1、class内存偏移找到cache_t
2、cache_t与上mask得到mask地址,cache_t与上bucket得到bucket地址;
3、mask与上sel得到sel-imp下标index;
4、bucket根据index内存平移,得到对应的bucket
5、取出bucket的sel和obj_msgSend传进来的sel比较,一致则进入CacheHit;
6、不一致则bucket--,继续执行第5步,如此循环,如果一直都找不到就进入MissLabelDynamic参数对应的内容;
}
CacheHit{
判断第一个参数值:
1、如果等于NORMAL就进入TailCallCachedImp函数;
2、如果等于GETIMP则进入AuthAndResignAsIMP;
3、如果等于LOOKUP则进入AuthAndResignAsIMP;
}
//cache imp解码,得到真正的imp,并进入imp
TailCallCachedImp{
// $0 = cached imp, $1 = address of cached imp, $2 = SEL, $3 = isa
eor $0, $0, $3
br $0
}
//就是与上Class解码,得到真正的imp
AuthAndResignAsIMP{
// $0 = cache imp , $1 = buckets的地址, $2 = SEL $3 = class
// $0 = $0 ^ $3 = imp ^ class = 解码后的imp
eor $0, $0, $3
}
//这一步已经是开始慢速查找了
__objc_msgSend_uncached{
1、MethodTableLookup//进行方法类表查找
2、TailCallFunctionPointer//回到函数
}
//方法列表查找
MethodTableLookup{
_lookUpImpOrForward//查找imp
}
lookUpImpOrForward{
1、_objc_msgForward_impcache//生成一个默认forward_imp
2、checkIsKnownClass//检测类是否已经被注册
3、realizeAndInitializeIfNeeded_locked//初始化类、父类、元类、根元类
4、for循环-死循环
循环体大概是这样:
用二分法在类的方法列表里查找,
->找到了,就调用log_and_fill_cache写入缓存;
->找不到,就开始调用_cache_getImp查找父类缓存,找到了就写入缓存,找不到就进入下一次循环体,只不过curClass变成了父类;
一直这样循环,找到了就写入缓存,直到curClass变成了nil(NSObject的父类是nil),就把默认forward_imp传给imp,跳出for循环;
}
LGetImpMissDynamic{
就做了一件事:返回0
}
_cache_getImp{
GetClassFromIsa_p16 p0, 0//获得isa
CacheLookup GETIMP, _cache_getImp, LGetImpMissDynamic, LGetImpMissConstant//缓存查找
}
__objc_msgForward_impcache{
b __objc_msgForward //跳转进入__objc_msgForward
END_ENTRY __objc_msgForward_impcache
}
__objc_msgForward{
adrp x17, __objc_forward_handler@PAGE
ldr p17, [x17, __objc_forward_handler@PAGEOFF]
/** TailCallFunctionPointer就是跳转进入$0参数也就是x17,
x17就是__objc_forward_handler,
所以__objc_msgForward就是进入__objc_forward_handler
*/
TailCallFunctionPointer x17
}
__attribute__((noreturn, cold)) void
objc_defaultForwardHandler(id self, SEL sel)
{
_objc_fatal("%c[%s %s]: unrecognized selector sent to instance %p "
"(no message forward handler is installed)",
class_isMetaClass(object_getClass(self)) ? '+' : '-',
object_getClassName(self), sel_getName(sel), self);
}
//_objc_forward_handler就是objc_defaultForwardHandler
void *_objc_forward_handler = (void*)objc_defaultForwardHandler;
+ (BOOL)resolveInstanceMethod:(SEL)sel {
//给对象添加方法实现,比如sel是run,那么返回的imp可以是sleep的imp;
}
+ (BOOL)resolveClassMethod:(SEL)sel{
//给类添加方法实现,同上
}
//快速消息转发
- (id)forwardingTargetForSelector:(SEL)aSelector{
//设定新的消息接收者
}
//消息慢速转发
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
//返回方法签名
}
///anInvocation包含了方法签名的信息,
//在forwardInvocation方法里,我们可以对异常方法调用进行处理或不处理,都不会崩溃
- (void)forwardInvocation:(NSInvocation *)anInvocation{
//对异常方法的一些处理
}