Alloc = [XXXX alloc] init [[XXXX alloc] init [[XXXX alloc] init]

JPerson *p = [JPerson alloc];
Copy the code

Hold down control and hit Step into to see the symbol objc_alloc, we set the symbol breakpoint objc_Alloc and you can see that objc_alloc is in libobjc.a.dylib

libobjc.A.dylib`objc_alloc
Copy the code

Objc4-781.2 is used here

objc_alloc

// Calls [cls alloc].
id
objc_alloc(Class cls)
{
    return callAlloc(cls, true/*checkNil*/, false/*allocWithZone*/);
}
Copy the code

callAlloc

// Call [cls alloc] or [cls allocWithZone:nil], with appropriate // shortcutting optimizations. static ALWAYS_INLINE id callAlloc(Class cls, bool checkNil, Bool allocWithZone=false) {#if (slowPath (checkNil &&! cls)) return nil; if (fastpath(! cls->ISA()->hasCustomAWZ())) { return _objc_rootAllocWithZone(cls, nil); } #endif // No shortcuts available. if (allocWithZone) { return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil); } return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc)); }Copy the code

So far we’re using objC2, so look at _objc_rootAllocWithZone first.

HasCustomAWZ () has a custom allocWithZone method, which we will explore later when we look at ISA

bool hasCustomAWZ() const { return ! cache.getBit(FAST_CACHE_HAS_DEFAULT_AWZ); }Copy the code

_objc_rootAllocWithZone

NEVER_INLINE id _objc_rootAllocWithZone(Class cls, // allocWithZone under __OBJC2__ ignores the zone parameter return _class_createInstanceFromZone(cls, 0, nil,OBJECT_CONSTRUCT_CALL_BADALLOC); }Copy the code

_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) {// Avoid multithreading problems, here also involves isa ASSERT(CLS ->isRealized()); // CLS and its parent have c++ constructors and destructors bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor(); bool hasCxxDtor = cls->hasCxxDtor(); Bool fast = CLS ->canAllocNonpointer(); bool fast = CLS ->canAllocNonpointer(); size_t size; Size = CLS ->instanceSize(extraBytes); if (outAllocatedSize) *outAllocatedSize = size; id obj; If (zone) {// zone is nil obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size); } else { obj = (id)calloc(1, size); } // Slowpath (!) slowpath(! obj)) { if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) { return _objc_callBadAllocHandler(cls); } return nil; } // canAllocNonpointer()=true if (! zone && fast) { obj->initInstanceIsa(cls, hasCxxDtor); } 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; return object_cxxConstructFromClass(obj, cls, construct_flags); }Copy the code

This method does: get the size of the space to be cleared, open the space, initialize ISA and return the pointer

instanceSize

Const size_t instanceSize (size_t extraBytes) {/ / ever cache size if need to open up the space (fastpath (cache. HasFastInstanceSize (extraBytes))) { return cache.fastInstanceSize(extraBytes); Size_t size = alignedInstanceSize() + extraBytes;} // 8 bytes aligned, if less than 16 bytes, return 16 bytes size_t size = alignedInstanceSize() + extraBytes; // CF requires all objects be at least 16 bytes. if (size < 16) size = 16; return size; }Copy the code

fastInstanceSize

size_t fastInstanceSize(size_t extra) const { ASSERT(hasFastInstanceSize(extra)); if (__builtin_constant_p(extra) && extra == 0) { return _flags & FAST_CACHE_ALLOC_MASK16; } else { size_t size = _flags & FAST_CACHE_ALLOC_MASK; // remove the FAST_CACHE_ALLOC_DELTA16 that was added // by setFastInstanceSize return align16(size + extra - FAST_CACHE_ALLOC_DELTA16); }}Copy the code

Call the align16

static inline size_t align16(size_t x) {
    return (x + size_t(15)) & ~size_t(15);
}
Copy the code

Zero the lower four bits after adding x to 15, or 16 bytes aligned

initInstanceIsa

inline void objc_object::initInstanceIsa(Class cls, bool hasCxxDtor) { ASSERT(! cls->instancesRequireRawIsa()); ASSERT(hasCxxDtor == cls->hasCxxDtor()); initIsa(cls, true, hasCxxDtor); } Inline void objC_object ::initIsa(Class CLS, bool nonpointer, bool hasCxxDtor) {// Cannot be a taggetPointer object ASSERT(! isTaggedPointer()); if (! nonpointer) { isa = isa_t((uintptr_t)cls); } else { ASSERT(! DisableNonpointerIsa); ASSERT(! cls->instancesRequireRawIsa()); isa_t newisa(0); #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 newisa.has_cxx_dtor = hasCxxDtor; newisa.shiftcls = (uintptr_t)cls >> 3; #endif // 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; }}Copy the code

So we’ve created isa and we’ve assigned some values to it, so what do those values mean and we’ll talk more about that when we analyze the ISA pointer

init

- (id)init {
    return _objc_rootInit(self);
}

id

_objc_rootInit(id obj)
{
    // In practice, it will be hard to rely on this function.
    // Many classes do not properly chain -init calls.
    return obj;
}

+ (id)new {
    return [callAlloc(self, false/*checkNil*/) init];
}
Copy the code

Init doesn’t actually implement anything, it just provides a convenient interface for developers, and new is just alloc and init, okay

Many ISA-related operations are covered in this article, and we will discuss ISA in detail in the next article

Refer to the article

# iOS Alloc process analysis