上面报告到alloc的底层是开发内存空间,它底层是调用_class_createInstanceFromZone函数处理处罚内存分配逻辑的,现实上它还处理处罚了isa!
而obj->initInstanceIsa(cls, hasCxxDtor);底层就是调用了obj->initIsa(cls);,以是obj->initIsa(cls);就是处理处罚isa的底层逻辑
inline void objc_object::initIsa(Class cls, bool nonpointer, UNUSED_WITHOUT_INDEXED_ISA_AND_DTOR_BIT bool hasCxxDtor){ ASSERT(!isTaggedPointer()); // taggedPointer 指针优化 isa_t newisa(0); // isa_t 是团结体 // nonpointer:表现是否对 isa 指针开启指针优化 0:纯isa指针,1:不止是类对象地点,isa 中包罗了类信息、对象的引用计数等 if (!nonpointer) { newisa.setClass(cls, this); // isa里生存了类对象 } else { ASSERT(!DisableNonpointerIsa); ASSERT(!cls->instancesRequireRawIsa());#if SUPPORT_INDEXED_ISA ASSERT(cls->classArrayIndex() > 0); newisa.bits = ISA_INDEX_MAGIC_VALUE; // isa.magic is part of ISA_MAGIC_VALUE // isa.nonpointer is part of ISA_MAGIC_VALUE newisa.has_cxx_dtor = hasCxxDtor; newisa.indexcls = (uintptr_t)cls->classArrayIndex();#else newisa.bits = ISA_MAGIC_VALUE; // isa.magic is part of ISA_MAGIC_VALUE // isa.nonpointer is part of ISA_MAGIC_VALUE# if ISA_HAS_CXX_DTOR_BIT newisa.has_cxx_dtor = hasCxxDtor;# endif newisa.setClass(cls, this); // isa里生存了类对象#endif newisa.extra_rc = 1; // isa里生存了 引用计数的值1 } // This write must be performed in a single store in some cases // (for example when realizing a class because other threads // may simultaneously try to use the class). // fixme use atomics here to guarantee single-store and to // guarantee memory order w.r.t. the class index table // ...but not too atomic because we don't want to hurt instantiation isa = newisa;}可以看到往isa里生存了很多多少信息,比如类对象、引用计数等等。
其次,来看看isa_t的声明,它是一个团结体:
#include "isa.h"union isa_t { isa_t() { } isa_t(uintptr_t value) : bits(value) { } uintptr_t bits;private: // Accessing the class requires custom ptrauth operations, so // force clients to go through setClass/getClass by making this // private. Class cls;public:#if defined(ISA_BITFIELD) struct { ISA_BITFIELD; // defined in isa.h }; bool isDeallocating() { return extra_rc == 0 && has_sidetable_rc == 0; } void setDeallocating() { extra_rc = 0; has_sidetable_rc = 0; }#endif void setClass(Class cls, objc_object *obj); Class getClass(bool authenticated); Class getDecodedClass(bool authenticated);};我们知道isa指针它是一个Class范例的布局体指针,主要用来存储内存地点的的,它占用8个字节(64位),但是我们的类对象的存储用不完这64的位域,于是苹果就把一些和对象息息相干的东西,一起生存到这64位域信息里。
这些存放的东西都在 ISA_BITFIELD 这个宏界说里,它是区分平台的(arm64、x86_64等等)。
苹果计划利用团结体isa_t的目的是去兼容老版本的isa,由于老版本的isa里只有Class cls,没有别的信息,而相干的信息又会必要别的内存空间,无疑造成内存浪费。nonPointerIsa可以明白成是新版本的isa。
nonPointerIsa里64位域里的内容: 怎样利用isa通过位运算后得到类对象?
我是通过模仿器调试的而且电脑芯片是Intel Core i5的,以是我直接看x86_64的ISA_BITFIELD声明:
我要得到中心的44位要怎样得到?
就是把低3位和高17位清0,再复位即得到中心的44位。x >> 3 << (17+3) >> 17
而苹果给的方案就是:isa地点 & ISA_MASK = 类对象地点
想要得到引用计数extra_rc的值:x >> (64-8)
留意验证的时间,要看清楚机型对应的架构。
末了附上objc_object总结图:
引用计数位extra_rc存储的值超了,会存储在has_sidetable_rc,在内存管理章节会讲。