美文网首页
objc_msgSend分析

objc_msgSend分析

作者: MrHardy | 来源:发表于2021-07-01 14:41 被阅读0次
  • 先从源码objc-msg-arm64.s看起
  • p0是消息的接受者,判断是否存在,存在将p0平移到p13

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

  • tbnz p11, #0, LLookupPreopt\Function // 判断 p11 的 0 号位置是否为0? 不为0的话走
  • LLookupPreopt\Function,LLookupPreopt查找共享缓存
  • andp10, p11, #0x0000ffffffffffff // p10 = buckets
  • LLookupStart -> CACHE_MASK_STORAGE_HIGH_16 //高16位真机架构
  • ldr p11, [x16, #CACHE] // 获取cache // p11 = mask|buckets
  • eor p12, p1, p1, LSR#7

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

  • 看下面的insert函数
  • 因为你在原始的时候,是一个读的过程,就得插入,如果当前要插的数据和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 没命中走
  • __objc_msgSend_uncached
  • isKnownClass 当前的class是否已经注册到当前的缓存表里面了

缓存为什么要用混编写?而不是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/jwvjultx.html