类对象的数据结构
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // 方法缓存
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
};
struct objc_object {
private:
isa_t isa;
};
其中cache_t就是方法缓存,用散列表缓存曾今调用过的方法
struct cache_t {
struct bucket_t *_buckets;// 散列表
mask_t _mask;// 散列表长度 -1
mask_t _occupied;// 已缓存的方法数量
};
struct bucket_t {
cache_key_t _key;// SEL作为Key
IMP _imp;// 函数内存地址
};
缓存查找方法在:源码的objc-cache.mm文件中
struct bucket_t *_bucket;
是一个散列表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个索引位置来访问记录,以加快查找的速度
。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
索引位置 | bucket_t |
---|---|
0 | Null |
1 | Null |
2 | bucket_t(_key = @selector(func1), _imp) |
3 | bucket_t(_key = @selector(func2), _imp) |
... | ...... |
SEL & _mask = 索引位置,再通过索引位置找到bucket_t,其中SEL为Key,最终找到的bucket_t为Value,计算索引位置的函数f(SEL) = SEL & _mask;
被称为散列函数(也叫哈希函数)。
- 在缓存方法的时候,通过散列函数和关键码值计算出一个索引位置,并把value放入散列表对应的索引位置处,其他还没有存放的位置全部初始化为Null;如果发现计算的索引位置已经存放了value,那么就根据自定义的规则把value存储到其他索引位置对应的value中。
- 值得注意的是,_mask关键码值是变化的,如果当前的散列表已经存放满的时候,_mask值会扩大,同时清空原来的散列表,重新进行缓存。
网友评论