入口寄存器 p1 = SEL、p16 = isa。目标:在类的方法缓存哈希表里找到 {imp, sel} 匹配项。命中即跳进 IMP,扑空则转慢路径。下面按你笔记的四阶段拆解,并可逐步演示探测循环。
按平台三选一读 CACHE 字段,拆出高 16 位 mask 与低 48 位 buckets,算哈希 _cmd&mask。
算出起始 bucket,进入 do-while 循环逐格比对 sel,向低地址方向探测。
探到表头还没中 → 绕到表尾继续扫,直到回到最初探测位才停。
仅 dyld 共享缓存里的系统类走此路径,普通动态类用不到。
选一个要查找的 selector,逐步执行哈希定位与逐格比对,观察命中 / 扑空 / 回绕三种结局。
②的主探测循环与③的回绕循环,结构几乎一致,区别在于停止条件。
指令 ldp p17, p9, [x13], #-BUCKET_SIZE 是「先读取,再把指针减一个 bucket(16 字节)」的后变址写法。所以探测从哈希起点向低地址走;当走到表头(p13 < p10/buckets)仍没命中,就进入③把指针重置到表尾,环形地再扫一段,直到绕回最初探测位置 p12 才宣告未命中——这正是开放寻址哈希表的环形探测。撞到 sel==0 的空槽则立即判定未命中,因为缓存里方法是连续填充的,空槽意味着不可能再有该项。