基於objc-runtime-new分析,老版的就先不記錄了
typedef struct objc_class *Class;
struct objc_object {
Class isa;
}
struct objc_class: objc_object {
Class superclass;
cache_t cache;
class_data_bits_t bits; // typedef unsigned long uintptr_t;這個就是讓系統分配64個位元組的記憶體給 isa 用而已
}
struct cache_t {
struct bucket_t *_buckets; // 快取方法的雜湊表
mask_t _mask; // typedef uint32_t mask_t; 雜湊表長度 - 1
mask_t _occupied; // 已經佔用的數量
}
struct bucket_t {
MethodCacheIMP _imp; // using MethodCacheIMP = IMP;
cache_key_t _key; // typedef uintptr_t cache_key_t;
}
union isa_t {
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
Class cls;
uintptr_t bits;
struct {
ISA_BITFIELD;
}
}
struct class_rw_t {
const class_ro_t *ro;
method_array_t methods;
property_array_t properties;
protocol_array_t protocols;
}
class class_ro_t {
const char * name;
method_list_t * baseMethodList;
protocol_list_t * baseProtocols;
const ivar_list_t * ivars;
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
}
struct method_t {
SEL name;
const char *type; // types包含了函式返回值,引數編碼的字串
MethodListIMP imp;
struct SortBySELAddress
}
複製程式碼
FAST_DATA_MASK 的值是 0x00007ffffffffff8UL bits 和 FAST_DATA_MASK 按位與,實際上就是取了 bits 中的[3,46]位 objc_msgSend第一次傳送訊息會觸發方法查詢,找到方法後會呼叫cache_fill()方法把方法快取到cache中 通過將@selector(key) & mask = index之後,bucket_t->set(key, imp) 最小的 buckets大小是4
= 3/4,擴容為兩倍