1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
| .macro CacheLookup Mode, Function, MissLabelDynamic, MissLabelConstant // // Restart protocol: // // As soon as we're past the LLookupStart\Function label we may have // loaded an invalid cache pointer or mask. // // When task_restartable_ranges_synchronize() is called, // (or when a signal hits us) before we're past LLookupEnd\Function, // then our PC will be reset to LLookupRecover\Function which forcefully // jumps to the cache-miss codepath which have the following // requirements: // // GETIMP: // The cache-miss is just returning NULL (setting x0 to 0) // // NORMAL and LOOKUP: // - x0 contains the receiver // - x1 contains the selector // - x16 contains the isa // - other registers are set as per calling conventions //
mov x15, x16 // stash the original isa LLookupStart\Function: // p1 = SEL, p16 = isa #if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16_BIG_ADDRS ldr p10, [x16, #CACHE] // p10 = mask|buckets lsr p11, p10, #48 // p11 = mask and p10, p10, #0xffffffffffff // p10 = buckets and w12, w1, w11 // x12 = _cmd & mask //64位真机 #elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16 //将x16 平移 CACHE大小 16位 CACHE = (2 * __SIZEOF_POINTER__)2个指针大小 //也就是isa 平移 0x10 找到cache p11 = cache ldr p11, [x16, #CACHE] // p11 = mask|buckets //64位真机 #if CONFIG_USE_PREOPT_CACHES //arm64e A12(iPhone X)及之后机型 #if __has_feature(ptrauth_calls) //判断p11(cache)是否存在 不存在跳转LLookupPreopt 存在继续执行 tbnz p11, #0, LLookupPreopt\Function //p10 = cahce&mask = buckets and p10, p11, #0x0000ffffffffffff // p10 = buckets #else and p10, p11, #0x0000fffffffffffe // p10 = buckets tbnz p11, #0, LLookupPreopt\Function #endif // p12 = p1^(p1>>7) p1 = _cmd eor p12, p1, p1, LSR #7 // p12 = p12&(p11>>48) 哈希编码index and p12, p12, p11, LSR #48 // x12 = (_cmd ^ (_cmd >> 7)) & mask #else and p10, p11, #0x0000ffffffffffff // p10 = buckets and p12, p1, p11, LSR #48 // x12 = _cmd & mask #endif // CONFIG_USE_PREOPT_CACHES #elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_LOW_4 ldr p11, [x16, #CACHE] // p11 = mask|buckets and p10, p11, #~0xf // p10 = buckets and p11, p11, #0xf // p11 = maskShift mov p12, #0xffff lsr p11, p12, p11 // p11 = mask = 0xffff >> p11 and p12, p1, p11 // x12 = _cmd & mask #else #error Unsupported cache mask storage for ARM64. #endif // 根据index找到对应的地址 p13 = bukects[index] PTRSHIFT=3 add p13, p10, p12, LSL #(1+PTRSHIFT) // p13 = buckets + ((_cmd & mask) << (1+PTRSHIFT))
// do { // 从p13取出imp和sel p17=imp p9=sel bucket-- 1: ldp p17, p9, [x13], #-BUCKET_SIZE // {imp, sel} = *bucket-- //判断p9是否等于传入的cmd cmp p9, p1 // if (sel != _cmd) { //不相等,跳转到 3f b.ne 3f // scan more // } else { //缓存命中 2: CacheHit \Mode // hit: call or return imp // } //p9为空 3: cbz p9, \MissLabelDynamic // if (sel == 0) goto Miss; //p13>p10(首地址) 循环查找buckets cmp p13, p10 // } while (bucket >= buckets) b.hs 1b
// wrap-around: // p10 = first bucket // p11 = mask (and maybe other bits on LP64) // p12 = _cmd & mask // // A full cache can happen with CACHE_ALLOW_FULL_UTILIZATION. // So stop when we circle back to the first probed bucket // rather than when hitting the first bucket again. // // Note that we might probe the initial bucket twice // when the first probed slot is the last entry.
#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16_BIG_ADDRS add p13, p10, w11, UXTW #(1+PTRSHIFT) // p13 = buckets + (mask << 1+PTRSHIFT) //64位真机 #elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16 // add p13, p10, p11, LSR #(48 - (1+PTRSHIFT)) // p13 = buckets + (mask << 1+PTRSHIFT) // see comment about maskZeroBits #elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_LOW_4 add p13, p10, p11, LSL #(1+PTRSHIFT) // p13 = buckets + (mask << 1+PTRSHIFT) #else #error Unsupported cache mask storage for ARM64. #endif add p12, p10, p12, LSL #(1+PTRSHIFT) // p12 = first probed bucket
// do { 4: ldp p17, p9, [x13], #-BUCKET_SIZE // {imp, sel} = *bucket-- cmp p9, p1 // if (sel == _cmd) b.eq 2b // goto hit cmp p9, #0 // } while (sel != 0 && ccmp p13, p12, #0, ne // bucket > first_probed) b.hi 4b
LLookupEnd\Function: LLookupRecover\Function: b \MissLabelDynamic
|