美文网首页
objc_msgSend流程分析

objc_msgSend流程分析

作者: MrHardy | 来源:发表于2021-06-29 17:22 被阅读0次

    先从源码objc-msg-arm64.s看起

    p0是消息的接受者,判断是否存在,存在将p0平移到p13

    A12 根据真机架构判断

    上面的代码提取关键部分,可以得到

    tbnz    p11, #0, LLookupPreopt\Function  // 判断 p11 的 0 号位置是否为0?  不为0的话走 LLookupPreopt\Function,LLookupPreopt查找共享缓存

    andp10, p11, #0x0000ffffffffffff    // p10 = buckets

    LLookupPreopt查找共享缓存

    LLookupStart -> CACHE_MASK_STORAGE_HIGH_16  //高16位真机架构

    ldr    p11, [x16, #CACHE]    // 获取cache         // p11 = mask|buckets

    eor p12, p1, p1, LSR#7 

    这里为什么要右移7位呢?

    看下面的insert函数

    jump cache_hash

    为什么要右移7,因为你在原始的时候,是一个读的过程,就得插入,如果当前要插的数据和sel一样的话,意味着插入的时候index右移了7,与上mask 得到值,再存起来,等取的时候,通过index取出来,所以两者的hash函数是一致的。就得出了 value ^= value >>7。

    and p12, p12, p11, LSR#48 这里为什么要右移48位呢?因为总共64位,前48位是bucket,后16是mask,右移出去,前面用0填充,得到mask。得到hash的inex。

    add p13, p10, p11, LSR#(48 - (1+PTRSHIFT))

    // p13 = buckets + (mask << 1+PTRSHIFT)

    // see comment about maskZeroBits

    mask等于7,7左移4位,就是7*16,已经到最后的位置,即p13就是最后的位置

    CacheHit \Mode 缓存命中

    MissLabelDynamic 没命中走

    MissLabelDynamic

     __objc_msgSend_uncached

    MethodTableLookup

    isKnownClass 当前的class是否已经注册到当前的缓存表里面了

    目标是imp的返回值

    缓存为什么要用混编写?而不是c++?

    1、缓存是为了提高效率,让当前的对象快速找到缓存。

    2、缓存的参数可能是未知的,汇编会更加的动态化。

    lookUpImpOrForward 慢速查找 不断的遍历methodlist

    慢速查找流程:

    1、查自己 methodlist-sel-imp (curClass method list.)

    2、父类->NSObject->nil->跳出

    小结:

    1: cmp    p0, #0 //判断p0是否存在

    2: GetClassFromIsa_p16 p13,1, x0    // p16 = class

    3: CacheLookup NORMAL, _objc_msgSend, __objc_msgSend_uncached

    3.1: LLookupStart -> CACHE_MASK_STORAGE_HIGH_16  //真机架构

    ldr    p11, [x16, #CACHE]    // 获取cache         // p11 = mask|buckets

    CONFIG_USE_PREOPT_CACHES ==1

    tbnz    p11, #0, LLookupPreopt\Function  // p11 的 0 号位置是否为0  不为0 -> LLookupPreopt

    and p10, p11, #0x0000ffffffffffff    // p10 = buckets

    // p1 sel >> 7 == value ^= value >> 7;

    eor    p12, p1, p1, LSR #7

    // 哈希 index

    and p12, p12, p11, LSR #48        // x12 = (_cmd ^ (_cmd >> 7)) & mask

    // index << 4

        // 2 * 16

    // buckets + 32

    // 对应下标 : p13 第一个要查bucket(sel imp)

    add    p13, p10, p12, LSL #(1+PTRSHIFT)

                        // p13 = buckets + ((_cmd & mask) << (1+PTRSHIFT))

    // sel -> imp 。缓存里的bucket sel 是否匹配,匹配的话返回imp

    未完待续......

    相关文章

      网友评论

          本文标题:objc_msgSend流程分析

          本文链接:https://www.haomeiwen.com/subject/ygoqultx.html