iOS|iOS Runtime 的方法缓存(存储的形式、数据结构以及查找的过程?)

Runtime一部分源码

struct objc_class : objc_object { // Class ISA; Class superclass; cache_t cache; // formerly cache pointer and vtable class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flagsclass_rw_t *data() { return bits.data(); } void setData(class_rw_t *newData) { bits.setData(newData); } }

cache_t结构体
// 方法缓存结构体 struct cache_t { // 存储被缓存方法的哈希表 struct bucket_t *_buckets; // 占用的总大小 mask_t _mask; // 已使用大小 mask_t _occupied; public: struct bucket_t *buckets(); mask_t mask(); mask_t occupied(); void incrementOccupied(); void setBucketsAndMask(struct bucket_t *newBuckets, mask_t newMask); void initializeToEmpty(); mask_t capacity(); bool isConstantEmptyCache(); bool canBeFreed(); static size_t bytesForCapacity(uint32_t cap); static struct bucket_t * endMarker(struct bucket_t *b, uint32_t cap); void expand(); void reallocate(mask_t oldCapacity, mask_t newCapacity); struct bucket_t * find(cache_key_t key, id receiver); static void bad_cache(id receiver, SEL sel, Class isa) __attribute__((noreturn)); };

struct bucket_t { private: cache_key_t _key; ////SEL作为Key @selector() IMP _imp; // 函数的内存地址public: inline cache_key_t key() const { return _key; } inline IMP imp() const { return (IMP)_imp; } inline void setKey(cache_key_t newKey) { _key = newKey; } inline void setImp(IMP newImp) { _imp = newImp; }void set(cache_key_t newKey, IMP newImp); };

查找过程,在objc-cache.mm文件中
bucket_t * cache_t::find(cache_key_t k, id receiver) { assert(k != 0); // 断言bucket_t *b = buckets(); // 获取散列表 mask_t m = mask(); // 散列表长度 - 1 mask_t begin = cache_hash(k, m); // & 操作 mask_t i = begin; // 索引值 do { if (b[i].key() == 0||b[i].key() == k) { return &b[i]; } } while ((i = cache_next(i, m)) != begin); // i 的值最大等于mask,最小等于0。// hack Class cls = (Class)((uintptr_t)this - offsetof(objc_class, cache)); cache_t::bad_cache(receiver, (SEL)k, cls); }

总结 Runtime 的方法缓存? cache_t哈希表结构。哈希表内部存储的 bucket_t。
存储的形式、数据结构 bucket_t 中存储的是 SEL 和 IMP的键值对。
以及查找的过程? 【iOS|iOS Runtime 的方法缓存(存储的形式、数据结构以及查找的过程?)】如果是有序方法列表,采用二分查找
如果是无序方法列表,直接遍历查找

    推荐阅读