alloc底層調用
[Person alloc]
匯編調試?alloc ->?objc_alloc?
fixupMessageRef(message_ref_t *msg)
{?
? ? ...
? ??if (msg->imp == &objc_msgSend_fixup) {?
? ? ? ? if(msg->sel==@selector(alloc)) {
? ? ? ? ? ? msg->imp= (IMP)&objc_alloc;
? ? ? ? }
? ? }
? ? ....
}
調用alloc 方法,會查找objc_alloc的imp
查看源碼 ?objc_alloc ->?callAlloc
callAlloc有 3個分支
第一種
? ? if(fastpath(!cls->ISA()->hasCustomAWZ())) {
? ? ? ? return _objc_rootAllocWithZone(cls, nil);
? ? }
第二種
if(allocWithZone) {
? ? ? ? return((id(*)(id,SEL,struct_NSZone*))objc_msgSend)(cls,@selector(allocWithZone:),nil);
? ? }
第三種
return((id(*)(id,SEL))objc_msgSend)(cls,@selector(alloc));
斷點調試 第一次先執行?objc_msgSend即 NSObject 的 alloc 方法
源碼查看NSObject 的 alloc 方法 ->?_objc_rootAlloc ->?callAlloc
再一次調用callAlloc, 斷點得知這次執行第一種
判斷 isa 的?hasCustomAWZ()值
if(fastpath(!cls->ISA()->hasCustomAWZ()))
bool hasCustomAWZ() const {
? ? ? ? return !cache.getBit(FAST_CACHE_HAS_DEFAULT_AWZ);
? ? }
isa?cache 緩存存在,執行_objc_rootAllocWithZone, 斷點也可以得出結論
查看源碼 ->?_class_createInstanceFromZone
結論:alloc-> objc_alloc —> callAlloc —> objc_msgSend —> alloc —> _objc_rootAlloc —> callAlloc —> _objc_rootAllocWithZone —> _class_createInstanceFromZone
_class_createInstanceFromZone?源碼中包括下面代碼
實例對象 的實際大小, 8字節對齊,最小是16字節
算法 8的倍數?(x + 7) & ~7
? ? size = cls->instanceSize(extraBytes);
define WORD_MASK7UL
static inline uint32_t word_align(uint32_t x) {
? ? return (x + WORD_MASK) & ~WORD_MASK;
}
系統為實例對象 開辟的內存大小,以16字節對齊
?obj = (id)calloc(1, size);
為什么要字節對??
字節是內存的容量單位。但是,CPU在讀取內存的時候,卻不是以字節為單位來讀取的,?是以“塊”為單位讀取的,所以?家也經常聽到?塊內存,“塊”的??也就是內存存取的?度。如果不對?的話,在我們頻繁的存取內存的時候,CPU就需要花費?量的精?去分辨你要讀取多少字節,這就會造成CPU的效率低下,如果想要CPU能夠?效讀取數據,那就需要找?個規范,這個規范就是字節對?。
為什么對象內部的成員變量是以8字節對?,系統實際分配的內存以16字節對??
以空間換時間。蘋果采取16字節對?,是因為OC的對象中,第?位叫isa指針,它是必然存在的,?且它就占了8位字節,就算對象中沒有其他的屬性了,也?定有?個isa,那對象就?少要占?8位字節。如果以8位字節對?的話,如果連續的兩塊內存都是沒有屬性的對象,那么它們的內存空間就會完全的挨在?起,是容易混亂的。以16字節為?塊,這就保證了CPU在讀取的時候,按照塊讀取就可以,效率更?,同時還不容易混亂。
new ?: alloc + init 的語法糖
+ (id)new{
? ? return [callAlloc(self, false/*checkNil*/) init];
}
init : 返回創建的實例對象
工廠模式創建對象,可以重寫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;
}