This chapter is a supplement to the previous chapter, through the flow chart and real machine assembly analysis quick search, random lead to the next chapter of slow search. The last cache_t expansion is a note to cache_t!

Cache Query Flowchart

Flow chart:

Graph TB A[objc_msgSend] -->B{CMP p0, #0<br> -- > < br >} B whether | | D/object through the isa for class B - > is | | C {whether to support the < br > taggegpointer object} -- > C is | | E {small objects or empty < br > judge LNilOrTagged < br >} D - > G [get finished isa LGetIsaDone] E - > | small object isa processing | G C - > whether | | F direct return empty LReturnZero] [E - > | | empty F G -- > H [to cache lookup process < br > CacheLookup NORMAL<br>] H --> I <br> BUCKETS <br>buckets <br> p10,p11 Mask p11, LSR #48<br>] K1 --> K2 <br> K["p12=buckets+((_cmd &mask)<<(1+PTRSHIFT))<br> "] K2 -> K K - > L [" is obtained by the bucket structure < br > {imp, sel} = * bucket < br > "] L - > M {judgment to query the sel and the current _cmd equal whether < br > < br >} M - > | | is N/hit the cache CacheHit $0 M - > M1 [if coming from the last element traversal < br > still can't find CheckMiss < br >] M - > whether | | O {" judge whether the current query bucket for < br > the first element bucket = = buckets < br > "} O - > | | P [" the current query bucket is set to the last element < br > p12 = buckets + (mask < < 1 + PTRSHIFT) < br > "] O - > whether | | Q [" forward looking for < br > {imp, sel} = * - bucket < br > "] Q -- - > | recursive search | M P - > Q

An assembly flow chart simplifies the explanation

  • 1. Judge the presentThe receiverIf there is a
cmp	p0, #0
Copy the code
  • 2. Byisagetclass
GetClassFromIsa_p16 p13, 1, x0
Copy the code
  • 3. Enter theCacheLookupProcess, two outcomes, find and throwimp“, did not find through__objc_msgSend_uncachedEnter the followingSlow to findprocess
CacheLookup NORMAL, _objc_msgSend,__objc_msgSend_uncached
Copy the code
  • 4.LLookupStartTo find the beginning, decompose hereThe simulator,A:,arm64Architecture,A12The above chip assemblies, only those that meet this condition are listed below
/ / simulator
CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16_BIG_ADDRS // Emulator for MAC (x86-64) and ARM64
/ / real machine
CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
    / / amr64 real machine
    CONFIG_USE_PREOPT_CACHES = 1
    // is to determine whether the compiler supports pointer authentication for arm64E
    //A12 + chip (support ARM64E)
     __has_feature(ptrauth_calls)
Copy the code
  • 5. WillisaThe offset16Bytes, byp11 = mask|bucketsgetcache_t
ldr	p11, [x16, #CACHE]
Copy the code
  • 6. Determinecache_tthe0 no.Is the location0If theDon'tIf the value is 0, executeLLookupPreopt, to findShared cache, if 0, willcache_t(_bucketsAndMaybeMask) & #0x0000ffffffffffffAnd got abucekts
tbnz	p11, #0, LLookupPreopt\Function
and	p10, p11, #0x0000ffffffffffff	// p10 = buckets
Copy the code
  • 7.Sel moves 7 bits to the rightMake logic with yourselfExclusive or ^Assigned top12That will becache_t(_bucketsAndMaybeMask)Moves to the right48Bits, that’s emptybuckets, can be obtainedmask, in the end will bep12 & mask, get the first lookupbucket_ttheindex, i.e.,first_probed
/ / p1 = _cmd, eor is exclusive or, p12 p1 = ^ (p1 > > 7) = _cmd ^ (_cmd > > 7)
eor p12, p1, p1, LSR #7
//p11 >> 48 = _bucketsAndMaybeMask >> 48 = mask
//p12 = p12 & (p11 >> 48) = _cmd ^ (_cmd >> 7) & mask
//p12 = (_cmd ^ (_cmd >> 7)) &mask
and p12, p12, p11, LSR #48 // x12 = (_cmd ^ (_cmd >> 7)) & mask
Copy the code
  • 7.1clangGet c++ source code:
static inline mask_t cache_hash(SEL sel, mask_t mask) 
{
    uintptr_t value = (uintptr_t)sel;
#if CONFIG_USE_PREOPT_CACHES
    value ^= value >> 7;
#endif
    return (mask_t)(value & mask);
}
Copy the code
  • 8. What do you want to knowbucket_tThe subscriptindexThen the next step is to passThe offsetTo thisbucket_tGet it insideselwithimp, here is the willindexThe offset to the left4Bit, understood asIndex * (1 << 4),index * 16So, what you get isOffset distance. The offsetfourBecause of abucket_tAccount for16 bytesAnd then we addbucketsAddress, you get the first one to comparebucket_t.
add	p13, p10, p12, LSL #(1+PTRSHIFT)// p13 = buckets + ((_cmd & mask) << (1+PTRSHIFT))
Copy the code
  • 9.1 will bep13Within theimpandselTake it out and exist separatelyp17andp9, the implementation ofbucket--. ifsel ! = _cmd, the implementation of3fTo determineselDoes it exist, does it have a value, willThe bucket (current) andBucekts (bucket first)Compare, if >0, continue the loop, go back1b, the implementation ofbucket--. If the process finds its target_cmdTo jump to2, the cache is hit, and the search ends.
                                            // do{
1:	ldp	p17, p9, [x13], #-BUCKET_SIZE  // {imp, sel} = *bucket--
	cmp	p9, p1			      // if (sel ! = _cmd) {
	b.ne	3f			            // scan more
                                           / /}
Copy the code
                                           // else {
2:	CacheHit \Mode                       // hit: call or return imp
                                           / /}
Copy the code
3:	cbz	p9, \MissLabelDynamic         // if (sel == 0) goto Miss;
	cmp	p13, p10                      // } while (bucket >= buckets)
	b.hs	1b
Copy the code
  • 9.2 If YesbucketNone of the first matches the target_cmd, directly jumps tomaskplacebucket(the bottombucket_t) to find the remaining ones in the cachebucketsAnd we also get the position of the first probeindexTo avoid repeated probes.4The inner operation is willbucket_ttheimpandselTake it out and assign it top17andp9.bucket--And compare theselwith_cmdIf successful, execute2b, hit the cache, and judgep9Exists or not, judge currentbucketIs it greater than the first probebucketIf all the above conditions are met, the loop continues4b, until the cache is hit. If all are searched and no hits are found, enterSlow to findProcess.
#elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16/ / / arm64 real machine
add	p13, p10, p11, LSR #(48 - (1+PTRSHIFT)) // p13 = buckets + (mask << 1+PTRSHIFT)
Copy the code
add p12, p10, p12, LSL #(1+PTRSHIFT)// p12 = first probed bucket
Copy the code
                                            // 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
Copy the code

Real machine debugging (assembly analysis)

Case source:

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

@interface CJPerson : NSObject
- (void)saySomething;
@end

@implementation FFPerson
- (void)saySomething{
    NSLog(@"%s",__func__);
}
@end
int main(int argc, char * argv[]) {
    @autoreleasepool {

        CJPerson *p = [CJPerson alloc];
        [p saySomething];
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
Copy the code

Identify the classes and methods being explored

Real machine assembly decomposition diagram:

libobjc.A.dylib`objc_msgSend:
    // objc_msgSend (x0 = 0x00000002803b8180) (x0 = 0x00000002803b8180) (x0 = 0x00000002803b8180)
->  0x19ef9b1c0 <+0>:   cmp    x0, #0x0                  ; =0x0 

    0x19ef9b1c4 <+4>:   b.le   0x19ef9b28c               ; <+204>
    // assign the isa value of p in x0 to x13
    X13 (x13 = 0x01000001026CD441 (0x00000001026CD441) (void *) 0x4800000001026CD4)
    // For details see x/4gx 0x00000002803b8180 in 'Underlying Principles (3)'
    0x19ef9b1c8 <+8>:   ldr    x13, [x0]
    // assign x13&0x7FFFFFFFFff8 to x16(x16 = 0x00000001026cd440 (void *) 0x00000001026CD418: // assign x13&0x7FFFFFFFFff8 to x16(x16 = 0x00000001026cd440 (void *) 0x00000001026CD418: CJPerson)
    0x19ef9b1cc <+12>:  and    x16, x13, #0x7ffffffffffff8
    // assign x0 to x10(copy instance p to x10 = 0x00000002803b8180)
    0x19ef9b1d0 <+16>:  mov    x10, x0
    // Change the content data in x10 from 48 bits to 0x6AE1 (x10 = 0x6AE10002803b8180)
    0x19ef9b1d4 <+20>:  movk   x10, #0x6ae1, lsl #48
    //(x16 = 0x00000001026cd440 (void *)0x00000001026cd418: CJPerson)
    0x19ef9b1d8 <+24>:  autda  x16, x10
    // Assign x16 to x15(x15 = 0x00000001026cd440 (void *) 0x00000001026CD418: CJPerson)
    0x19ef9b1dc <+28>:  mov    x15, x16
    // Read cache_t, px16+0x10(x/4gx 0x00000001026CD440) after reading the content data to (x11 = 0x00010002801be4A0)
    0x19ef9b1e0 <+32>:  ldr    x11, [x16, #0x10]
    // Check whether the 0th bit of w11(w11 = 0x801Be4A0) is 0. If it is 0, continue to go down. If it is not 0, jump to 0x19ef9B240
    0x19ef9b1e4 <+36>:  tbnz   w11, #0x0.0x19ef9b240    ; <+128>
    //x10 = x11&0xffFFFFFFFFFF (x10 = 0x00000002801be4A0)
    0x19ef9b1e8 <+40>:  and    x10, x11, #0xffffffffffff
    (x12 = 0x00000001026C718e "saySomething")(x12 = 0x000000010068a96d = 0x00000001026C718e ^)(x12 = 0x00000001026C718e ^ 0x000000000204d8e3)
    0x19ef9b1ec <+44>:  eor    x12, x1, x1, lsr #7
    Mask = 0x00010002801BE4A0 >> 48 = 0x0000000000000001
    //x12 = mask & x12 (x12 = 0x0000000000000001) is the first retrieved location (first_prepot)
    0x19ef9b1f0 <+48>:  and    x12, x12, x11, lsr #48
    Buckets + first_preop x13 = (0x00000002801Be4A0 + (0x01 << 4 = 0x10)) = 0x00000002801Be4B0
    0x19ef9b1f4 <+52>:  add    x13, x10, x12, lsl #4
    //p x13-0x10 gets the old region x/4gx 0x00000002801Be4B0 Take the first two and assign values x17 = 0xDD1A3D019efBeB34, x9 = 0x00000001DA0a38AE respectively
    0x19ef9b1f8 <+56>:  ldp    x17, x9, [x13], #-0x10
    X9 == x1 == 0x00000001DA0a38AE == 0x00000001026C718e
    0x19ef9b1fc <+60>:  cmp    x9, x1
    // Unequal jump to 0x19ef9b210
    0x19ef9b200 <+64>:  b.ne   0x19ef9b210               ; <+80>
    // x10 = x10 xOR x1
    0x19ef9b204 <+68>:  eor    x10, x10, x1
    // x10 = x10 ^ x16
    0x19ef9b208 <+72>:  eor    x10, x10, x16
    //
    0x19ef9b20c <+76>:  brab   x17, x10
    // 
    0x19ef9b210 <+80>:  cbz    x9, 0x19ef9b600           ; _objc_msgSend_uncached
    // Compare x13 with x10, i.e. 0x00000002801BE4A0 == 0x00000002801Be4A0
    0x19ef9b214 <+84>:  cmp    x13, x10
    // When equal, jump to 0x19ef9B1f8 from the start but x13 = 0x00000002801Be4A0 than 0x00000002801Be4B0-0x10
    0x19ef9b218 <+88>:  b.hs   0x19ef9b1f8               ; <+56>
    // If no, x13 = (x10 = 0x00000002801Be4A0) + ((x11 = 0x00010002801Be4A0)>>44 = 0x00000000000000000010) = 0x00000002801Be4B0
    0x19ef9b21c <+92>:  add    x13, x10, x11, lsr #44
    //x12 = (x10 = 0x00000002801be4a0) + (x12 = 0x0000000000000001 << 4) = 0x00000002801be4b0
    0x19ef9b220 <+96>:  add    x12, x10, x12, lsl #4
    X17 = 0xDD1a3D019efBeb34, x9 = 0x00000001da0a38AE
    0x19ef9b224 <+100>: ldp    x17, x9, [x13], #-0x10
    X9 = 0x00000001DA0a38AE x1 = 0x00000001026C718e "saySomething"
    0x19ef9b228 <+104>: cmp    x9, x1
    // If they are equal, jump to 0x19ef9B204
    0x19ef9b22c <+108>: b.eq   0x19ef9b204               ; <+68>
    // Check whether x9 is 0x00
    0x19ef9b230 <+112>: cmp    x9, #0x0                  ; =0x0 
    //x13 = 0x00000002801be4a0, x12 = 0x00000002801be4b
    0x19ef9b234 <+116>: ccmp   x13, x12, #0x0, ne

    0x19ef9b238 <+120>: b.hi   0x19ef9b224               ; <+100>
    // Jump to 0x19ef9b600 and run _objc_msgSend_uncached(slow look up)
    0x19ef9b23c <+124>: b      0x19ef9b600               ; _objc_msgSend_uncached
    //x10 = x11 & 0x7ffffffffffffe
    0x19ef9b240 <+128>: and    x10, x11, #0x7ffffffffffffe
    
    0x19ef9b244 <+132>: autdb  x10, x16

    0x19ef9b248 <+136>: adrp   x9, 239235

    0x19ef9b24c <+140>: add    x9, x9, #0x4ae            ; =0x4ae 

    0x19ef9b250 <+144>: sub    x12, x1, x9

    0x19ef9b254 <+148>: lsr    x17, x11, #55

    0x19ef9b258 <+152>: lsr    w9, w12, w17

    0x19ef9b25c <+156>: lsr    x17, x11, #60

    0x19ef9b260 <+160>: mov    x11, #0x7fff

    0x19ef9b264 <+164>: lsr    x11, x11, x17

    0x19ef9b268 <+168>: and    x9, x9, x11

    0x19ef9b26c <+172>: ldr    x17, [x10, x9, lsl #3]

    0x19ef9b270 <+176>: cmp    x12, w17, uxtw

    0x19ef9b274 <+180>: b.ne   0x19ef9b280               ; <+192>

    0x19ef9b278 <+184>: sub    x17, x16, x17, lsr #32

    0x19ef9b27c <+188>: br     x17

    0x19ef9b280 <+192>: ldursw x9, [x10, #-0x8]

    0x19ef9b284 <+196>: add    x16, x16, x9

    0x19ef9b288 <+200>: b      0x19ef9b1e0               ; <+32>

    0x19ef9b28c <+204>: b.eq   0x19ef9b2b0               ; <+240>

    0x19ef9b290 <+208>: and    x10, x0, #0x7

    0x19ef9b294 <+212>: asr    x11, x0, #55

    0x19ef9b298 <+216>: cmp    x10, #0x7                 ; =0x7 

    0x19ef9b29c <+220>: csel   x12, x11, x10, eq

    0x19ef9b2a0 <+224>: adrp   x10, 320424

    0x19ef9b2a4 <+228>: add    x10, x10, #0x820          ; =0x820 

    0x19ef9b2a8 <+232>: ldr    x16, [x10, x12, lsl #3]

    0x19ef9b2ac <+236>: b      0x19ef9b1dc               ; <+28>

    0x19ef9b2b0 <+240>: mov    x1, #0x0

    0x19ef9b2b4 <+244>: movi   d0, #0000000000000000

    0x19ef9b2b8 <+248>: movi   d1, #0000000000000000

    0x19ef9b2bc <+252>: movi   d2, #0000000000000000

    0x19ef9b2c0 <+256>: movi   d3, #0000000000000000

    0x19ef9b2c4 <+260>: ret    

    0x19ef9b2c8 <+264>: nop    

    0x19ef9b2cc <+268>: nop    

    0x19ef9b2d0 <+272>: nop    

    0x19ef9b2d4 <+276>: nop    

    0x19ef9b2d8 <+280>: nop    

    0x19ef9b2dc <+284>: nop    

Copy the code

Add the content

Source code emulation of cache_T class memory expansion in real machine case

Demo address part key source code:

typedef uint32_t mask_t;  // x86_64 & arm64 asm are less efficient

//preopt_cache_entry_t Source code impersonation
struct ff_preopt_cache_entry_t {
    uint32_t sel_offs;
    uint32_t imp_offs;
};

//preopt_cache_t Source code imitation
struct ff_preopt_cache_t {
    int32_t  fallback_class_offset;
    union {
        struct {
            uint16_t shift       :  5;
            uint16_t mask        : 11;
        };
        uint16_t hash_params;
    };
    uint16_t occupied    : 14;
    uint16_t has_inlines :  1;
    uint16_t bit_one     :  1;
    struct ff_preopt_cache_entry_t entries;
    
    inline int capacity() const {
        return mask + 1; }};//bucket_t source code imitation
struct ff_bucket_t {
    IMP _imp;
    SEL _sel;
};

// Cache_t source parody
struct ff_cache_t {
    uintptr_t _bucketsAndMaybeMask; / / 8
    struct ff_preopt_cache_t _originalPreoptCache; / / 8

    static constexpr uintptr_t maskShift = 48;

    static constexpr uintptr_t maskZeroBits = 4;

    static constexpr uintptr_t maxMask = ((uintptr_t)1< < (64 - maskShift)) - 1;
    
    static constexpr uintptr_t bucketsMask = ((uintptr_t)1 << (maskShift - maskZeroBits)) - 1;
    
    static constexpr uintptr_t preoptBucketsMarker = 1ul;

    static constexpr uintptr_t preoptBucketsMask = 0x007ffffffffffffe;
    
    ff_bucket_t *buckets() {
        return (ff_bucket_t *)(_bucketsAndMaybeMask & bucketsMask);
    }
    
    uint32_t mask() const {
        return_bucketsAndMaybeMask >> maskShift; }};//class_data_bits_t
struct ff_class_data_bits_t {
    uintptr_t objc_class;
};

// Class source code imitation
struct ff_objc_class {
    Class isa;
    Class superclass;
    struct ff_cache_t cache;
    struct ff_class_data_bits_t bits;
};


void test(Class cls) {
    
    // Convert person to a custom source ff_objC_class type for subsequent operations
    struct ff_objc_class *pClass = (__bridge struct ff_objc_class *)(cls);
    
    struct ff_cache_t cache = pClass->cache;
    struct ff_bucket_t * buckets = cache.buckets();
    struct ff_preopt_cache_t origin = cache._originalPreoptCache;
    uintptr_t _bucketsAndMaybeMask = cache._bucketsAndMaybeMask;
    uintptr_t mask = cache.mask();
    
    
    
    NSLog(@"class: %p", pClass);
    NSLog(@"_bucketsAndMaybeMask: 0x%lx, mask: %lu", _bucketsAndMaybeMask, mask);
    
    // Print how many methods are currently cached and the maximum number of caches
    NSLog(@"%u-%u",origin.occupied,origin.capacity());
    
    / / print buckets
    for (int i = 0; i < mask + 1; i++ ) {
        SEL sel = buckets[i]._sel;
        IMP imp = buckets[i]._imp;
        NSLog(@"%@-%p".NSStringFromSelector(sel),imp); }}int main(int argc, char * argv[]) {

    @autoreleasepool {
        
        // Allocate memory to person
        FFPerson *person = [FFPerson alloc];
        // Call the method[person likeGirls]; test(person.class); [person likeFoods]; test(person.class); [person likeflower]; test(person.class); [person likeStudy]; test(person.class); [person enjoyLift]; test(person.class); [person lnspireCreativity]; test(person.class); . }return UIApplicationMain(argc, argv, nil.NSStringFromClass([AppDelegate class]));
}
Copy the code

Print the result

2021- 06- 30 23:38:39.523507+0800 002- Cache real machine source restore [2001:757686] -[FFPerson likeGirls]
2021- 06- 30 23:38:39.524594+0800 002- Cache real machine source restore [2001:757686] class: 0x102ef9680
2021- 06- 30 23:38:39.524617+0800 002- Cache real machine source restore [2001:757686] _bucketsAndMaybeMask: 0x10002835b60e0, mask: 1
2021- 06- 30 23:38:39.524633+0800 002- Cache real machine source restore [2001:757686] 1- 1025.
2021- 06- 30 23:38:39.524651+0800 002- Cache real machine source restore [2001:757686] (null)-0x0
2021- 06- 30 23:38:39.524706+0800 002- Cache real machine source restore [2001:757686] likeGirls-0xe00f9f8102ef148c
2021- 06- 30 23:38:39.524728+0800 002- Cache real machine source restore [2001:757686] -[FFPerson likeFoods]
2021- 06- 30 23:38:39.524868+0800 002- Cache real machine source restore [2001:757686] class: 0x102ef9680
2021- 06- 30 23:38:39.525038+0800 002- Cache real machine source restore [2001:757686] _bucketsAndMaybeMask: 0x10002835b60e0, mask: 1
2021- 06- 30 23:38:39.525138+0800 002- Cache real machine source restore [2001:757686] 2- 1025.
2021- 06- 30 23:38:39.525253+0800 002- Cache real machine source restore [2001:757686] likeFoods-0xf64c0b0102ef1504
2021- 06- 30 23:38:39.525279+0800 002- Cache real machine source restore [2001:757686] likeGirls-0xe00f9f8102ef148c
2021- 06- 30 23:38:39.525298+0800 002- Cache real machine source restore [2001:757686] -[FFPerson likeflower]
2021- 06- 30 23:38:39.525312+0800 002- Cache real machine source restore [2001:757686] class: 0x102ef9680
2021- 06- 30 23:38:39.525326+0800 002- Cache real machine source restore [2001:757686] _bucketsAndMaybeMask: 0x30002820b4c40, mask: 3
2021- 06- 30 23:38:39.525437+0800 002- Cache real machine source restore [2001:757686] 1- 1025.
2021- 06- 30 23:38:39.525517+0800 002- Cache real machine source restore [2001:757686] (null)-0x0
2021- 06- 30 23:38:39.525783+0800 002- Cache real machine source restore [2001:757686] (null)-0x0
2021- 06- 30 23:38:39.525910+0800 002- Cache real machine source restore [2001:757686] (null)-0x0
2021- 06- 30 23:38:39.526071+0800 002- Cache real machine source restore [2001:757686] likeflower-0x2d78768102ef14c8
2021- 06- 30 23:38:39.526236+0800 002- Cache real machine source restore [2001:757686] -[FFPerson likeStudy]
2021- 06- 30 23:38:39.526347+0800 002- Cache real machine source restore [2001:757686] class: 0x102ef9680
2021- 06- 30 23:38:39.526438+0800 002- Cache real machine source restore [2001:757686] _bucketsAndMaybeMask: 0x30002820b4c40, mask: 3
2021- 06- 30 23:38:39.526548+0800 002- Cache real machine source restore [2001:757686] 2- 1025.
2021- 06- 30 23:38:39.526643+0800 002- Cache real machine source restore [2001:757686] (null)-0x0
2021- 06- 30 23:38:39.526745+0800 002- Cache real machine source restore [2001:757686] (null)-0x0
2021- 06- 30 23:38:39.526900+0800 002- Cache real machine source restore [2001:757686] likeStudy-0xf26c730102ef1540
2021- 06- 30 23:38:39.527019+0800 002- Cache real machine source restore [2001:757686] likeflower-0x2d78768102ef14c8
2021- 06- 30 23:38:39.527098+0800 002- Cache real machine source restore [2001:757686] -[FFPerson enjoyLift]
2021- 06- 30 23:38:39.527195+0800 002- Cache real machine source restore [2001:757686] class: 0x102ef9680
2021- 06- 30 23:38:39.527316+0800 002- Cache real machine source restore [2001:757686] _bucketsAndMaybeMask: 0x30002820b4c40, mask: 3
2021- 06- 30 23:38:39.527427+0800 002- Cache real machine source restore [2001:757686] 3- 1025.
2021- 06- 30 23:38:39.527520+0800 002- Cache real machine source restore [2001:757686] (null)-0x0
2021- 06- 30 23:38:39.527626+0800 002- Cache real machine source restore [2001:757686] enjoyLift-0x8e617e8102ef157c
2021- 06- 30 23:38:39.527728+0800 002- Cache real machine source restore [2001:757686] likeStudy-0xf26c730102ef1540
2021- 06- 30 23:38:39.527829+0800 002- Cache real machine source restore [2001:757686] likeflower-0x2d78768102ef14c8
2021- 06- 30 23:38:39.528005+0800 002- Cache real machine source restore [2001:757686] -[FFPerson lnspireCreativity]
2021- 06- 30 23:38:39.528130+0800 002- Cache real machine source restore [2001:757686] class: 0x102ef9680
2021- 06- 30 23:38:39.528236+0800 002- Cache real machine source restore [2001:757686] _bucketsAndMaybeMask: 0x30002820b4c40, mask: 3
2021- 06- 30 23:38:39.528349+0800 002- Cache real machine source restore [2001:757686] 4- 1025.
2021- 06- 30 23:38:39.528450+0800 002- Cache real machine source restore [2001:757686] lnspireCreativity-0xc6607b8102ef15b8
2021- 06- 30 23:38:39.528536+0800 002- Cache real machine source restore [2001:757686] enjoyLift-0x8e617e8102ef157c
2021- 06- 30 23:38:39.528705+0800 002- Cache real machine source restore [2001:757686] likeStudy-0xf26c730102ef1540
2021- 06- 30 23:38:39.528804+0800 002- Cache real machine source restore [2001:757686] likeflower-0x2d78768102ef14c8
Copy the code
INIT_CACHE_SIZE_LOG2 #if CACHE_END_MARKER || (__arm64__ && ! __LP64__) INIT_CACHE_SIZE_LOG2 = 2, #else INIT_CACHE_SIZE_LOG2 = 1, #endifCopy the code
cache_fill_ratio #if __arm__ || __x86_64__ || __i386__ #define CACHE_END_MARKER 1 static inline mask_t cache_fill_ratio(mask_t capacity) { return capacity * 3 / 4; } #elif __arm64__ && ! __LP64__ #define CACHE_END_MARKER 0 static inline mask_t cache_fill_ratio(mask_t capacity) { return capacity * 3 / 4; } #elif __arm64__ && __LP64__ #define CACHE_END_MARKER 0 static inline mask_t cache_fill_ratio(mask_t capacity) { return  capacity * 7 / 8; } #define CACHE_ALLOW_FULL_UTILIZATION 1 #else #error unknown architecture #endifCopy the code

Conclusion:

  • iPhoneXs, the initial cache capacity is 2 (INIT_CACHE_SIZE = (1 << 1))
  • The capacity expansion of the real machine is doubled according to the 7/8 rule, so the capacity expansion law is 2-> 4 -> 8 -> 16 -> 2^n
  • x86_64The initial architecture capacity is 4 (INIT_CACHE_SIZE = (1 << 2))
  • 4 -> 8 -> 16 -> 2^(n+1)