iOS底层分析之objc_msgSend总结

223 阅读3分钟

和谐学习!不急不躁!!我是你们的老朋友小青龙~

大致流程

截屏2021-07-17 下午5.37.39.png

详细流程

objc_msgSend详细流程.jpg

下面针对每一个做了什么,进行主要阐述:

_objc_msgSend{
    非空判断;
    得到isa;
    得到Class;
    CacheLookup NORMAL, _objc_msgSend, __objc_msgSend_uncached
}
CacheLookup{
/** 其实就是缓存查找的过程,
    找到进入CacheHit,找不到就进入CacheLookup的第三个参数代表的函数*/
1class内存偏移找到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比较,一致则进入CacheHit6、不一致则bucket--,继续执行第5步,如此循环,如果一直都找不到就进入MissLabelDynamic参数对应的内容;
}
CacheHit{
判断第一个参数值:
1、如果等于NORMAL就进入TailCallCachedImp函数;
2、如果等于GETIMP则进入AuthAndResignAsIMP3、如果等于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{
    1MethodTableLookup//进行方法类表查找
    2TailCallFunctionPointer//回到函数
}
//方法列表查找
MethodTableLookup{
    _lookUpImpOrForward//查找imp
}
lookUpImpOrForward{
1、_objc_msgForward_impcache//生成一个默认forward_imp
2、checkIsKnownClass//检测类是否已经被注册
3、realizeAndInitializeIfNeeded_locked//初始化类、父类、元类、根元类
4for循环-死循环
    循环体大概是这样:
    用二分法在类的方法列表里查找,
        ->找到了,就调用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{
    //对异常方法的一些处理
}