NEVER_INLINEid_objc_rootAllocWithZone(Class cls,malloc_zone_t*zone __unused){ // allocWithZone under __OBJC2__ ignores the zone parameterreturn_class_createInstanceFromZone(cls,0, nil, OBJECT_CONSTRUCT_CALL_BADALLOC);}
我们继续下一步
g. _class_createInstanceFromZone 创建实例
/************************************************************************ class_createInstance* fixme* Locking: none** Note: this function has been carefully written so that the fastpath* takes no branch.**********************************************************************/static ALWAYS_INLINE id_class_createInstanceFromZone(Class cls,size_t extraBytes,void*zone,int construct_flags = OBJECT_CONSTRUCT_NONE,bool cxxConstruct =true,size_t*outAllocatedSize = nil){ASSERT(cls->isRealized()); // Read class's info bits all at once for performancebool hasCxxCtor = cxxConstruct &&cls->hasCxxCtor();bool hasCxxDtor =cls->hasCxxDtor();bool fast =cls->canAllocNonpointer();size_t size; size =cls->instanceSize(extraBytes);// 1. 计算所需大小if (outAllocatedSize) *outAllocatedSize = size; id obj;if (zone) { obj = (id)malloc_zone_calloc((malloc_zone_t*)zone,1, size); } else { obj = (id)calloc(1, size); // 2. 开辟空间 }if (slowpath(!obj)) {if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {return_objc_callBadAllocHandler(cls); }return nil; }if (!zone && fast) {obj->initInstanceIsa(cls, hasCxxDtor); // 3. 实例化isa } else { // Use raw pointer isa on the assumption that they might be // doing something weird with the zone or RR.obj->initIsa(cls); }if (fastpath(!hasCxxCtor)) {return obj; } construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;returnobject_cxxConstructFromClass(obj, cls, construct_flags);}
g.1 instanceSize 大小
这里会去缓存中查找
CoreFoundation规定最小16个字节
有isa指针的8字节
还有8字节预留
// Class's ivar size rounded up to a pointer-size boundary.
成员变量的大小向上取整(一个指针的大小8字节)
即:成员变量的字节对齐
即:不足8字节就按8字节
// May be unaligned depending on class's ivars.
大小取决于成员变量的大小
inlinesize_tinstanceSize(size_t extraBytes) const {if (fastpath(cache.hasFastInstanceSize(extraBytes))) {returncache.fastInstanceSize(extraBytes); }size_t size =alignedInstanceSize() + extraBytes; // CF requires all objects be at least 16 bytes.if (size <16) size =16;return size;}// Class's ivar size rounded up to a pointer-size boundary.uint32_talignedInstanceSize() const {returnword_align(unalignedInstanceSize());}// May be unaligned depending on class's ivars.uint32_tunalignedInstanceSize() const {ASSERT(isRealized());returndata()->ro()->instanceSize;}
// Get the class pointer out of an isa. When ptrauth is supported,// this operation is optionally authenticated. Many code paths don't// need the authentication, so it can be skipped in those cases for// better performance.//// Note: this method does not support retrieving indexed isas. When// indexed isas are in use, it can only be used to retrieve the class// of a raw isa.#ifSUPPORT_INDEXED_ISA|| (ISA_SIGNING_AUTH_MODE!=ISA_SIGNING_AUTH)#defineMAYBE_UNUSED_AUTHENTICATED_PARAM__attribute__((unused))#else#defineMAYBE_UNUSED_AUTHENTICATED_PARAM UNUSED_WITHOUT_PTRAUTH#endifinline Classisa_t::getClass(MAYBE_UNUSED_AUTHENTICATED_PARAM bool authenticated) {#ifSUPPORT_INDEXED_ISAreturn cls;#elseuintptr_t clsbits = bits;# if __has_feature(ptrauth_calls)# ifISA_SIGNING_AUTH_MODE==ISA_SIGNING_AUTH // Most callers aren't security critical, so skip the // authentication unless they ask for it. Message sending and // cache filling are protected by the auth code in msgSend.if (authenticated) { // Mask off all bits besides the class pointer and signature. clsbits &= ISA_MASK;if (clsbits ==0)return Nil; clsbits = (uintptr_t)ptrauth_auth_data((void *)clsbits, ISA_SIGNING_KEY, ptrauth_blend_discriminator(this, ISA_SIGNING_DISCRIMINATOR));
} else { // If not authenticating, strip using the precomputed class mask. clsbits &= objc_debug_isa_class_mask; }# else // If not authenticating, strip using the precomputed class mask. clsbits &= objc_debug_isa_class_mask;# endif# else clsbits &= ISA_MASK;# endifreturn (Class)clsbits;#endif}
这里要拿到isa需要&一个mask,在isa.h中可以找到对应架构的定义
b.获取MASk
下面是ARM64的,其他架构的可以自行在头文件中查找,很简单的
# defineISA_MASK0x0000000ffffffff8ULL
c.复原出isa
再次输出
(lldb) po 0x000061a10441570d&0x0000000ffffffff8Ryukie