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 // ... };
// Values are the FAST_ flags above. uintptr_t bits; // ...
public:
class_rw_t* data() const { return (class_rw_t *)(bits & FAST_DATA_MASK); } // data,存储可动态改变的部分,内部还包含只读的部分 // ... // Get the class's ro data, even in the presence of concurrent realization. // fixme this isn't really safe without a compiler barrier at least // and probably a memory barrier when realizeClass changes the data field const class_ro_t *safe_ro() { class_rw_t *maybe_rw = data(); if (maybe_rw->flags & RW_REALIZED) { // maybe_rw is rw return maybe_rw->ro; } else { // maybe_rw is actually ro return (class_ro_t *)maybe_rw; } } // 将只读部分暴露出来 // ... };
struct ivar_t { #if __x86_64__ // *offset was originally 64-bit on some x86_64 platforms. // We read and write only 32 bits of it. // Some metadata provides all 64 bits. This is harmless for unsigned // little-endian values. // Some code uses all 64 bits. class_addIvar() over-allocates the // offset for their benefit. #endif int32_t *offset; // 地址的偏移 constchar *name; // 变量名 constchar *type; // 变量类型 // alignment is sometimes -1; use alignment() instead uint32_t alignment_raw; uint32_t size;
Class cls; uintptr_t bits; #if defined(ISA_BITFIELD) struct { ISA_BITFIELD; // defined in isa.h }; #endif };
isa 是一个联合体,在 64 位机器上这个共用体就是 64 位的(32 位下就是 32 位的)。
isa 可能是指针型的,也可能是非指针型的。 指针型就是说这个联合体的内容存储的就是一个指针,比如一个对象的 isa 指针找到对象的类对象。 非指针型的是说,这个联合体中的部分位代表地址,其他位表示一些其他信息。因为 64 位用于存储地址是多余的,只需要部分位已经能满足寻址需要,那么其他剩余的位置就可以存储一些别的。
isa 不总是指向实例所属的类,比如 KVO 就是将被观察对象的 isa 指向一个中间类。确定实例所属的类应该使用 class 方法。
/// Specifies the superclass of an instance. struct objc_super { /// Specifies an instance of a class. __unsafe_unretained _Nonnull id receiver; // 还是调用者本身
/// Specifies the particular superclass of the instance to message. #if !defined(__cplusplus) && !__OBJC2__ /* For compatibility with old objc-runtime.h header */ __unsafe_unretained _Nonnull Class class; #else __unsafe_unretained _Nonnull Class super_class; #endif /* super_class is the first class to search */ };