class_data_bits_t bits;
objc_class 中还有一个成员是bits。这个成员存储着什么数据呢,我们一下继续往探寻。
struct class_data_bits_t {
// 表示objc_class是友元。objc_class可以访问class_data_bits_t的私有属性方法
friend objc_class;
// Values are the FAST_ flags above.
// uintptr_t 8字节的unsigned long
uintptr_t bits;
...
}
class_data_bits_t 含有一个成员bits 是一个8字节的数据。另外objc_class 是他的友元。在objc_clas中可以访问class_data_bits_t 的私有属性和方法
class_data_bits_t 的方法
#if __LP64__
// class is a Swift class from the pre-stable Swift ABI
#define FAST_IS_SWIFT_LEGACY (1UL<<0)
// class is a Swift class from the stable Swift ABI
#define FAST_IS_SWIFT_STABLE (1UL<<1)
// class or superclass has default retain/release/autorelease/retainCount/
// _tryRetain/_isDeallocating/retainWeakReference/allowsWeakReference
#define FAST_HAS_DEFAULT_RR (1UL<<2)
// data pointer
#define FAST_DATA_MASK 0x00007ffffffffff8UL // 0x00007ffffffffff8 二进制4到46位为1
// class_rw_t 后面会了解到存储着类的成员变量,属性,方法等数据
class_rw_t* data() const {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
void setData(class_rw_t *newData){
ASSERT(!data() || (newData->flags & (RW_REALIZING | RW_FUTURE)));
// Set during realization or construction only. No locking needed.
// Use a store-release fence because there may be concurrent
// readers of data and data's contents.
// 先将
uintptr_t newBits = (bits & ~FAST_DATA_MASK) | (uintptr_t)newData;
atomic_thread_fence(memory_order_release);
bits = newBits;
}

- bits的4到46为存储着 class_rw_t *的类型的指针。存储的逻辑是将4-46位置0,然后在 | 新的指针数据(指针是8字节,字节对齐,其实地址是8的倍数,所以后三位必定为0)
FAST_IS_SWIFT_STABLE - FAST_IS_SWIFT_LEGACY
FAST_IS_SWIFT_STABLE: class is a Swift class from the stable Swift ABI (1UL<<1)
FAST_IS_SWIFT_LEGACY: class is a Swift class from the pre-stable Swift ABI (1UL<<0)
bool getBit(uintptr_t bit) const{
return bits & bit;
}
bool isAnySwift() {
return isSwiftStable() || isSwiftLegacy();
}
bool isSwiftStable() {
return getBit(FAST_IS_SWIFT_STABLE);
}
void setIsSwiftStable() {
setAndClearBits(FAST_IS_SWIFT_STABLE, FAST_IS_SWIFT_LEGACY);
}
bool isSwiftLegacy() {
return getBit(FAST_IS_SWIFT_LEGACY);
}
void setIsSwiftLegacy() {
setAndClearBits(FAST_IS_SWIFT_LEGACY, FAST_IS_SWIFT_STABLE);
}
// fixme remove this once the Swift runtime uses the stable bits
bool isSwiftStable_ButAllowLegacyForNow() {
return isAnySwift();
}
FAST_HAS_DEFAULT_RR ( (1UL<<2))
class or superclass has default retain/release/autorelease/retainCount/_tryRetain/_isDeallocating/retainWeakReference/allowsWeak
#if FAST_HAS_DEFAULT_RR
bool hasCustomRR() const {
return !bits.getBit(FAST_HAS_DEFAULT_RR);
}
void setHasDefaultRR() {
bits.setBits(FAST_HAS_DEFAULT_RR);
}
void setHasCustomRR() {
bits.clearBits(FAST_HAS_DEFAULT_RR);
}
#else
bool hasCustomRR() const {
return !(bits.data()->flags & RW_HAS_DEFAULT_RR);
}
void setHasDefaultRR() {
bits.data()->setFlags(RW_HAS_DEFAULT_RR);
}
void setHasCustomRR() {
bits.data()->clearFlags(RW_HAS_DEFAULT_RR);
}
#endif
class_data_bits_t中存储的数据
所以,类的内存布局中:
- 1-2的0/1位则表示这是否swift 类,以及是否是 stable Swift ABI,还是 the pre-stable Swift ABI。(最多只会有一个生效)
- 第3位0/1位表示是否有默认的retain/release/autorelease/retainCount (在 LP64 最终的定义, 如果是在非 LP64。这是存储在 class_rw_t 的 flag 的对应位中)
- 从第4位开始,存储着 class_rw_t 的地址指针
class_rw_t
class_rw_t
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags; // 2
uint16_t witness; // 4
#if SUPPORT_INDEXED_ISA // __ARM_ARCH_7K__ >= 2 || (__arm64__ && ! __LP64__)
uint16_t index; // 2
#endif
explicit_atomic<uintptr_t> ro_or_rw_ext; // 8
Class firstSubclass; // 8 第一个子类
Class nextSiblingClass; // 8 下一个兄弟类
private:
// 声明一个类型别名。 using 别名 = 包括详细命名空间信息的具体的类型。 参考 c using的用法
// objc::PointerUnion 使用第一位来区分两种类型指针
using ro_or_rw_ext_t = objc::PointerUnion<const class_ro_t *, class_rw_ext_t *>;
...
}
(lldb) p/x Person.class
(Class) $0 = 0x0000000100003468 Person
(lldb) x/8xg 0x0000000100003468
0x100003468: 0x0000000100003490 0x0000000100334140
0x100003478: 0x0000000101130b60 0x0003804400000007
0x100003488: 0x0000000101130694 0x00000001003340f0
0x100003498: 0x00000001003340f0 0x0000000101021420
(lldb) p (class_data_bits_t * )0x100003488
(class_data_bits_t *) $1 = 0x0000000100003488
(lldb) p $1->data()
(class_rw_t *) $2 = 0x0000000101130690
(lldb) p *$2
(class_rw_t) $3 = {
flags = 2148007936
witness = 1
ro_or_rw_ext = {
std::__1::atomic<unsigned long> = 4294979656
}
firstSubclass = nil // 子类
nextSiblingClass = NSUUID // 父类
}
(lldb) p sizeof($3)
(unsigned long) $4 = 32
ro_or_rw_ext
ro_or_rw_ext 从定义上来看,是一个两种类型指针公用的指针。根据第一个的0/1 来全判断。 0 表示是class_ro_t *; 1表示是 class_rw_ext_t 。rw表示的readwrite。ro表示的readonly。
class_rw_ext_t 中存储着对一个的ro,方法列表,属性列表,协议等信息
struct class_rw_ext_t {
const class_ro_t *ro;
method_array_t methods;
property_array_t properties;
protocol_array_t protocols;
char *demangledName;
uint32_t version;
};
class_ro_t 中存储了编译期确定的数据。
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
const uint8_t * ivarLayout;
const char * name;
method_list_t * baseMethodList;
protocol_list_t * baseProtocols;
const ivar_list_t * ivars;
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
}
class_rw_t/class_ro_t 的flag中存储着很多与和ABI有关的编译器设置
// Values for class_ro_t->flags
// These are emitted by the compiler and are part of the ABI.
// Note: See CGObjCNonFragileABIMac::BuildClassRoTInitializer in clang
// class is a metaclass
#define RO_META (1<<0)
// class is a root class
#define RO_ROOT (1<<1)
// class has .cxx_construct/destruct implementations
#define RO_HAS_CXX_STRUCTORS (1<<2)
// class has +load implementation
// #define RO_HAS_LOAD_METHOD (1<<3)
// class has visibility=hidden set
#define RO_HIDDEN (1<<4)
// class has attribute(objc_exception): OBJC_EHTYPE_$_ThisClass is non-weak
#define RO_EXCEPTION (1<<5)
// class has ro field for Swift metadata initializer callback
#define RO_HAS_SWIFT_INITIALIZER (1<<6)
...
#define RO_REALIZED (1<<31)
// Values for class_rw_t->flags
// These are not emitted by the compiler and are never used in class_ro_t.
// Their presence should be considered in future ABI versions.
// class_t->data is class_rw_t, not class_ro_t
#define RW_REALIZED (1<<31)
// class is unresolved future class
#define RW_FUTURE (1<<30)
...
#define RW_META RO_META // (1<<0)
flag 的不同0/1位代表着不同的信息,是否是mataclass,是否是根类等,具体可以再源码中查看。
class_rw_t 中的方法
获取方法列表。根据 ro_or_rw_ext 的is()判断当前是哪种指针,然后从对应的指针中获取方法列表.
其他的协议列表也是类似的
const method_array_t methods() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>()->methods;
} else {
return method_array_t{v.get<const class_ro_t *>()->baseMethods()};
}
}

WWDC20 Advancements in the Objective-C runtime
- clean memoery 加载后不会改变, 当内存紧张时,可以移除,当需要再次引入。
- dirty memory 运行时会改变的数据,在mac上可以选择 swap out dirty memory。 但是ios 不适用swap。
类结构的变化。
使用一个中间的class_rw_t 保存dirty menory,(运行时可以改变或者交换方法,协议,属性)。然后因为很多没有使用,有分离出 class_rw_ext_t 结构保存哪些改变了的数据。

Relative Mathod List
类的方法列表发生了改变。原先mathod 中的sel, signature, imp 存储的都是 64位的确定地址。因为其都是存储在同一个二进制文件中,所以,优化为存储 32位的偏移地址,而且偏移地址从image中读取之后是固定的,就不需要修改,所以成了clean memory。
不能修改imp的地址,那么实现swizze,采用的是一个全局的swizzes表,用来存储swizzes的数据

tagged pointers
地址经常是没有完全使用的,高位和地位总会是0。所以在一些位置设置为特定的属性标签。
比如isa指针中第1位这是位1,表示这不是一个真正的对象指针(优化),然后就可以在其他的位置设置标签。


网友评论