本章要點主要探索
NSObject
的alloc
源碼?為什么要探索NSObject
的源碼呢枷邪, 上一篇手撕iOS底層02 -- 分析alloc&init&new不是分析過alloc
的源碼了嘛昂芜, 通過實踐得知膜蛔,NSObject *objc = [NSObject alloc];
這行代碼是不會直接走alloc
方法里的螟深, 這也就和我們之前探索的自定義類alloc
流程有區(qū)別敬特?所以這一章分析下NSObject
的alloc
和自定義類的alloc
有什么區(qū)別柔吼?
0x00 -- objc_alloc
在斷點處,點擊Debug --> Debug Workflow --> Always Show Disassembly
毒费;
通過匯編調(diào)試得知:
-
NSObject
的alloc
之前會調(diào)用objc_alloc
,自定義類Test
也會先調(diào)用objc_alloc
;
系統(tǒng)級別就把NSObject
的初始化做了愈魏,所以NSObject
的alloc
的調(diào)用關(guān)系是:
alloc --> objc_alloc --> calloc --> _objc_rootAllocWithZone
而自定義類的調(diào)用關(guān)系是:
alloc --> objc_alloc --> calloc --> objc_msgSend(cls,alloc) --> alloc -- > calloc --> _objc_rootAllocWithZone
0x01 -- 分析自定義類調(diào)用倆次alloc
首先探究下觅玻,為什么自定義的類調(diào)用alloc
會直接走到objc_alloc
的方法內(nèi)?
究其原因蝌戒, 基于alloc
的特殊性串塑,應該是LLVM
編譯器幫我們做了函數(shù)指針跳轉(zhuǎn),所以找一份蘋果開源的llvm-project
北苟,看看其中是否可以找到一些蛛絲馬跡????????
- 搜索
objc_alloc
桩匪,找到如下所示,在當前文件由很多objc_alloc
關(guān)鍵字友鼻;一點一點往下捋傻昙;
- 再往下看闺骚,
shouldUseRuntimeFunctionForCombinedAllocInit
這個方法表示版本控制;
- 然后查找什么地方使用了版本控制妆档。找到特殊消息發(fā)送
tryEmitSpecializedAllocInit
- 遇到不好查找的關(guān)鍵代碼時僻爽,開啟上帝視覺,當前查找關(guān)鍵字
omf-aloc
在下邊會調(diào)用這個方法特殊消息發(fā)送方法tryGenerateSpecializedMessageSend
第一次會調(diào)用objc_alloc
贾惦,然后條件不成立胸梆,走GenerateMessageSend
普通消息發(fā)送,走到alloc
流程须板;So
自定義類的流程alloc
會走倆次碰镜,第一次發(fā)送alloc
會走到objc_alloc
,通過objc_alloc
走到callAlloc
消息發(fā)送习瑰,會再次走到alloc
源碼里绪颖;
CodeGen::RValue CGObjCRuntime::GeneratePossiblySpecializedMessageSend(
CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
Selector Sel, llvm::Value *Receiver, const CallArgList &Args,
const ObjCInterfaceDecl *OID, const ObjCMethodDecl *Method,
bool isClassMessage) {
if (Optional<llvm::Value *> SpecializedResult =
tryGenerateSpecializedMessageSend(CGF, ResultType, Receiver, Args,
Sel, Method, isClassMessage)) {
return RValue::get(SpecializedResult.getValue());
}
return GenerateMessageSend(CGF, Return, ResultType, Sel, Receiver, Args, OID,
Method);
}
這段代碼是解釋為什么走倆次
alloc
的, 在if
條件里的tryGenerateSpecializedMessageSend
這個函數(shù)一定會走甜奄, 從上可知柠横,這個函數(shù)里有一個case
判斷,如果是alloc
课兄,會調(diào)用objc_alloc
牍氛,然后這個if
條件不成立, 會執(zhí)行下邊GenerateMessageSend
函數(shù)第喳,執(zhí)行普通的消息發(fā)送 糜俗,走alloc
流程。
0x02 -- 附上流程圖
-
NSObject alloc
流程圖
- 自定義類
alloc
流程圖