日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OC底层原理-alloc流程

發布時間:2024/1/18 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OC底层原理-alloc流程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

alloc流程分析

可以通過opensource下載objc4來查看alloc的源碼,這里用objc4-818版本來分析

1.alloc

+ (id)alloc {return _objc_rootAlloc(self); }

2.objc_alloc

id objc_alloc(Class cls) {return callAlloc(cls, true/*checkNil*/, false/*allocWithZone*/); }

3.callAlloc

static ALWAYS_INLINE id callAlloc(Class cls, bool checkNil, bool allocWithZone=false) { #if __OBJC2__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)); }

ISA方法:

inline Class objc_object::ISA(bool authenticated) {ASSERT(!isTaggedPointer());return isa.getDecodedClass(authenticated); }// class or superclass has default alloc/allocWithZone: implementation // Note this is is stored in the metaclass. #define FAST_CACHE_HAS_DEFAULT_AWZ (1<<14) bool hasCustomAWZ() const {return !cache.getBit(FAST_CACHE_HAS_DEFAULT_AWZ); }

在callAlloc中,先通過cls的ISA返回一個Class對象,然后判斷cache中有沒有緩存,如果有,則執行_objc_rootAllocWithZone,如果沒有,則執行objc_msgSend。

4._objc_rootAllocWithZone

id _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); }

5._class_createInstanceFromZone

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);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);}if (slowpath(!obj)) {if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {return _objc_callBadAllocHandler(cls);}return nil;}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); }

_class_createInstanceFromZone創建實例分三步:
1.cls->instanceSize 計算對象所需要的的內存大小
2.cls->calloc 申請開辟內存
3.cls->initInstanceIsa 通過isa,將對象于類關聯

instanceSize

inline size_t instanceSize(size_t extraBytes) const {if (fastpath(cache.hasFastInstanceSize(extraBytes))) {return cache.fastInstanceSize(extraBytes);}size_t size = alignedInstanceSize() + extraBytes;// CF requires all objects be at least 16 bytes.if (size < 16) size = 16; return size;}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 setFastInstanceSizereturn align16(size + extra - FAST_CACHE_ALLOC_DELTA16);}}uint32_t unalignedInstanceSize() const {ASSERT(isRealized());return data()->ro()->instanceSize;}// Class's ivar size rounded up to a pointer-size boundary.uint32_t alignedInstanceSize() const {return word_align(unalignedInstanceSize());}

當cache中有緩存時,就調用fastInstanceSize來計算extraBytes,并返回大小,在fastInstanceSize中調用了align16進行16字節對齊;沒有緩存時,調用alignedInstanceSize進行8字節對齊。

calloc
calloc內部進行了16字節對齊,具體可以參考這里

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, UNUSED_WITHOUT_INDEXED_ISA_AND_DTOR_BIT bool hasCxxDtor) { ASSERT(!isTaggedPointer()); isa_t newisa(0);if (!nonpointer) {newisa.setClass(cls, this);} else {ASSERT(!DisableNonpointerIsa);ASSERT(!cls->instancesRequireRawIsa());#if SUPPORT_INDEXED_ISAASSERT(cls->classArrayIndex() > 0);newisa.bits = ISA_INDEX_MAGIC_VALUE;// isa.magic is part of ISA_MAGIC_VALUE// isa.nonpointer is part of ISA_MAGIC_VALUEnewisa.has_cxx_dtor = hasCxxDtor;newisa.indexcls = (uintptr_t)cls->classArrayIndex(); #elsenewisa.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_BITnewisa.has_cxx_dtor = hasCxxDtor; # endifnewisa.setClass(cls, this); #endifnewisa.extra_rc = 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 instantiationisa = newisa; }

可見,在initIsa里面新生成了isa,并將其和cls關聯起來

總結

在alloc執行流程中,cache中沒有緩存,使用objc_msgSend函數調用了alloc方法,然后再調用 _objc_rootAlloc -> callAlloc -> _objc_rootAllocWithZone -> _class_createInstanceFromZone -> instanceSize -> calloc -> initInstanceIsa
如果有緩存,就不會通過objc_msgSend調用alloc方法,就直接 _objc_rootAllocWithZone執行后面的流程

其實,alloc的主要目的就是開辟內存,并使得isa指針和cls類進行關聯。

總結

以上是生活随笔為你收集整理的OC底层原理-alloc流程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。