美文网首页
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