区块链技术博客
www.b2bchain.cn

大师重磅内容(13)-cache 结构分析求职学习资料

本文介绍了大师重磅内容(13)-cache 结构分析求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

一、cache 数据结构

HPObject *obj = [HPObject alloc]; Class objClass = [HPObject class];

首先根据源码明确objc_class

struct objc_class : objc_object {     Class ISA;//继承     Class superclass;     cache_t cache;        class_data_bits_t bits;  };

通过底层源码我们可以看看cache_t的数据结构:

struct cache_t { private:     explicit_atomic<uintptr_t> _bucketsAndMaybeMask; //unsigned long 8字节     union {         struct {             explicit_atomic<mask_t>    _maybeMask;//uint32_t 4字节 #if __LP64__             uint16_t                   _flags;//2字节 #endif             uint16_t                   _occupied;//2字节         };         explicit_atomic<preopt_cache_t *> _originalPreoptCache;//指针 8字节     }; };

接下来 我们可以通过 LLDB 去分析调试

(lldb) p/x [HPObject class] (Class) $0 = 0x00000001000083c8 HPObject (lldb) p (cache_t *)0x00000001000083D8 (cache_t *) $1 = 0x00000001000083d8 (lldb) p *$1 (cache_t) $2 = {   _bucketsAndMaybeMask = {     std::__1::atomic<unsigned long> = {       Value = 4298437472     }   }    = {      = {       _maybeMask = {         std::__1::atomic<unsigned int> = {           Value = 0         }       }       _flags = 32820       _occupied = 0     }     _originalPreoptCache = {       std::__1::atomic<preopt_cache_t *> = {         Value = 0x0000803400000000       }     }   } }
  • 获取类地址后平移0x10得到了cache的指针。
  • 打印cache结构与源码中看到的相同。

根据源码_originalPreoptCache与内部结构体是同一份数据,那么缓存数据是保存在_bucketsAndMaybeMask中呢?还是_originalPreoptCache中呢?selimp在哪块呢?

官方在这块并没有给注释,但是有个思路。既然是缓存那就应该有增删改查相应的操作。直接在cache_t中查找对应的方法会找到bucket_t相关的方法:

static bucket_t *emptyBuckets(); static bucket_t *allocateBuckets(mask_t newCapacity); static bucket_t *emptyBucketsForCapacity(mask_t capacity, bool allocate = true);  void insert(SEL sel, IMP imp, id receiver);

insert内部也是对bucket的操作。显然缓存应该与bucket(_bucketsAndMaybeMask)有关。

bucket_t源码结构如下:

struct bucket_t { private:     // IMP-first is better for arm64e ptrauth and no worse for arm64.     // SEL-first is better for armv7* and i386 and x86_64. #if __arm64__     explicit_atomic<uintptr_t> _imp;     explicit_atomic<SEL> _sel; #else     explicit_atomic<SEL> _sel;     explicit_atomic<uintptr_t> _imp; #endif };

发现了impsel,果然方法与bucket_t有关。
那么就有了如下结构对应关系:

大师重磅内容(13)-cache 结构分析

arm64bucket_t_sel_imp顺序不同。注释也说了顺序与架构有关,arm64eimp在前更好,估计是有优化

二、cache底层LLDB分析

上面分析出了_sel_imp保存在bucket_t中,那么接下来就验证下:

(lldb) p $2._bucketsAndMaybeMask (explicit_atomic<unsigned long>) $3 = {   std::__1::atomic<unsigned long> = {     Value = 4298437472   } } (lldb) p $3.Value error: <user expression 4>:1:4: no member named 'Value' in 'explicit_atomic<unsigned long>' $3.Value ~~ ^

_bucketsAndMaybeMask能正常获取但是Value却获取不到。同样的_maybeMask以及_flags_occupiedValue也获取不到。

只好分析下cache_t看有没有暴露什么方法,在源码中发现了buckets():

struct bucket_t *buckets() const;

验证分析:
“`c

一、cache 数据结构

HPObject *obj = [HPObject alloc]; Class objClass = [HPObject class];

首先根据源码明确objc_class

struct objc_class : objc_object {     Class ISA;//继承     Class superclass;     cache_t cache;        class_data_bits_t bits;  };

通过底层源码我们可以看看cache_t的数据结构:

struct cache_t { private:     explicit_atomic<uintptr_t> _bucketsAndMaybeMask; //unsigned long 8字节     union {         struct {             explicit_atomic<mask_t>    _maybeMask;//uint32_t 4字节 #if __LP64__             uint16_t                   _flags;//2字节 #endif             uint16_t                   _occupied;//2字节         };         explicit_atomic<preopt_cache_t *> _originalPreoptCache;//指针 8字节     }; };

接下来 我们可以通过 LLDB 去分析调试

(lldb) p/x [HPObject class] (Class) $0 = 0x00000001000083c8 HPObject (lldb) p (cache_t *)0x00000001000083D8 (cache_t *) $1 = 0x00000001000083d8 (lldb) p *$1 (cache_t) $2 = {   _bucketsAndMaybeMask = {     std::__1::atomic<unsigned long> = {       Value = 4298437472     }   }    = {      = {       _maybeMask = {         std::__1::atomic<unsigned int> = {           Value = 0         }       }       _flags = 32820       _occupied = 0     }     _originalPreoptCache = {       std::__1::atomic<preopt_cache_t *> = {         Value = 0x0000803400000000       }     }   } }
  • 获取类地址后平移0x10得到了cache的指针。
  • 打印cache结构与源码中看到的相同。

根据源码_originalPreoptCache与内部结构体是同一份数据,那么缓存数据是保存在_bucketsAndMaybeMask中呢?还是_originalPreoptCache中呢?selimp在哪块呢?

官方在这块并没有给注释,但是有个思路。既然是缓存那就应该有增删改查相应的操作。直接在cache_t中查找对应的方法会找到bucket_t相关的方法:

static bucket_t *emptyBuckets(); static bucket_t *allocateBuckets(mask_t newCapacity); static bucket_t *emptyBucketsForCapacity(mask_t capacity, bool allocate = true);  void insert(SEL sel, IMP imp, id receiver);

insert内部也是对bucket的操作。显然缓存应该与bucket(_bucketsAndMaybeMask)有关。

bucket_t源码结构如下:

struct bucket_t { private:     // IMP-first is better for arm64e ptrauth and no worse for arm64.     // SEL-first is better for armv7* and i386 and x86_64. #if __arm64__     explicit_atomic<uintptr_t> _imp;     explicit_atomic<SEL> _sel; #else     explicit_atomic<SEL> _sel;     explicit_atomic<uintptr_t> _imp; #endif };

发现了impsel,果然方法与bucket_t有关。
那么就有了如下结构对应关系:

大师重磅内容(13)-cache 结构分析

arm64bucket_t_sel_imp顺序不同。注释也说了顺序与架构有关,arm64eimp在前更好,估计是有优化

二、cache底层LLDB分析

上面分析出了_sel_imp保存在bucket_t中,那么接下来就验证下:

(lldb) p $2._bucketsAndMaybeMask (explicit_atomic<unsigned long>) $3 = {   std::__1::atomic<unsigned long> = {     Value = 4298437472   } } (lldb) p $3.Value error: <user expression 4>:1:4: no member named 'Value' in 'explicit_atomic<unsigned long>' $3.Value ~~ ^

_bucketsAndMaybeMask能正常获取但是Value却获取不到。同样的_maybeMask以及_flags_occupiedValue也获取不到。

只好分析下cache_t看有没有暴露什么方法,在源码中发现了buckets():

struct bucket_t *buckets() const;

验证分析:
“`c

一、cache 数据结构

HPObject *obj = [HPObject alloc]; Class objClass = [HPObject class];

首先根据源码明确objc_class

struct objc_class : objc_object {     Class ISA;//继承     Class superclass;     cache_t cache;        class_data_bits_t bits;  };

通过底层源码我们可以看看cache_t的数据结构:

struct cache_t { private:     explicit_atomic<uintptr_t> _bucketsAndMaybeMask; //unsigned long 8字节     union {         struct {             explicit_atomic<mask_t>    _maybeMask;//uint32_t 4字节 #if __LP64__             uint16_t                   _flags;//2字节 #endif             uint16_t                   _occupied;//2字节         };         explicit_atomic<preopt_cache_t *> _originalPreoptCache;//指针 8字节     }; };

接下来 我们可以通过 LLDB 去分析调试

(lldb) p/x [HPObject class] (Class) $0 = 0x00000001000083c8 HPObject (lldb) p (cache_t *)0x00000001000083D8 (cache_t *) $1 = 0x00000001000083d8 (lldb) p *$1 (cache_t) $2 = {   _bucketsAndMaybeMask = {     std::__1::atomic<unsigned long> = {       Value = 4298437472     }   }    = {      = {       _maybeMask = {         std::__1::atomic<unsigned int> = {           Value = 0         }       }       _flags = 32820       _occupied = 0     }     _originalPreoptCache = {       std::__1::atomic<preopt_cache_t *> = {         Value = 0x0000803400000000       }     }   } }
  • 获取类地址后平移0x10得到了cache的指针。
  • 打印cache结构与源码中看到的相同。

根据源码_originalPreoptCache与内部结构体是同一份数据,那么缓存数据是保存在_bucketsAndMaybeMask中呢?还是_originalPreoptCache中呢?selimp在哪块呢?

官方在这块并没有给注释,但是有个思路。既然是缓存那就应该有增删改查相应的操作。直接在cache_t中查找对应的方法会找到bucket_t相关的方法:

static bucket_t *emptyBuckets(); static bucket_t *allocateBuckets(mask_t newCapacity); static bucket_t *emptyBucketsForCapacity(mask_t capacity, bool allocate = true);  void insert(SEL sel, IMP imp, id receiver);

insert内部也是对bucket的操作。显然缓存应该与bucket(_bucketsAndMaybeMask)有关。

bucket_t源码结构如下:

struct bucket_t { private:     // IMP-first is better for arm64e ptrauth and no worse for arm64.     // SEL-first is better for armv7* and i386 and x86_64. #if __arm64__     explicit_atomic<uintptr_t> _imp;     explicit_atomic<SEL> _sel; #else     explicit_atomic<SEL> _sel;     explicit_atomic<uintptr_t> _imp; #endif };

发现了impsel,果然方法与bucket_t有关。
那么就有了如下结构对应关系:

大师重磅内容(13)-cache 结构分析

arm64bucket_t_sel_imp顺序不同。注释也说了顺序与架构有关,arm64eimp在前更好,估计是有优化

二、cache底层LLDB分析

上面分析出了_sel_imp保存在bucket_t中,那么接下来就验证下:

(lldb) p $2._bucketsAndMaybeMask (explicit_atomic<unsigned long>) $3 = {   std::__1::atomic<unsigned long> = {     Value = 4298437472   } } (lldb) p $3.Value error: <user expression 4>:1:4: no member named 'Value' in 'explicit_atomic<unsigned long>' $3.Value ~~ ^

_bucketsAndMaybeMask能正常获取但是Value却获取不到。同样的_maybeMask以及_flags_occupiedValue也获取不到。

只好分析下cache_t看有没有暴露什么方法,在源码中发现了buckets():

struct bucket_t *buckets() const;

验证分析:
“`c

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 大师重磅内容(13)-cache 结构分析求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们