本章要點(diǎn)主要探索
NSObject的alloc源碼?為什么要探索NSObject的源碼呢, 上一篇手撕iOS底層02 -- 分析alloc&init&new不是分析過alloc的源碼了嘛, 通過實(shí)踐得知,NSObject *objc = [NSObject alloc];這行代碼是不會(huì)直接走alloc方法里的, 這也就和我們之前探索的自定義類alloc流程有區(qū)別?所以這一章分析下NSObject的alloc和自定義類的alloc有什么區(qū)別?
0x00 -- objc_alloc

在斷點(diǎn)處,點(diǎn)擊Debug --> Debug Workflow --> Always Show Disassembly;

通過匯編調(diào)試得知:
-
NSObject的alloc之前會(huì)調(diào)用objc_alloc,自定義類Test也會(huì)先調(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會(huì)直接走到objc_alloc的方法內(nèi)?
究其原因, 基于alloc的特殊性,應(yīng)該是LLVM編譯器幫我們做了函數(shù)指針跳轉(zhuǎn),所以找一份蘋果開源的llvm-project,看看其中是否可以找到一些蛛絲馬跡????????
- 搜索
objc_alloc,找到如下所示,在當(dāng)前文件由很多objc_alloc關(guān)鍵字;一點(diǎn)一點(diǎn)往下捋;

- 再往下看,
shouldUseRuntimeFunctionForCombinedAllocInit這個(gè)方法表示版本控制;

- 然后查找什么地方使用了版本控制。找到特殊消息發(fā)送
tryEmitSpecializedAllocInit

- 遇到不好查找的關(guān)鍵代碼時(shí),開啟上帝視覺,當(dāng)前查找關(guān)鍵字
omf-aloc

在下邊會(huì)調(diào)用這個(gè)方法特殊消息發(fā)送方法tryGenerateSpecializedMessageSend 第一次會(huì)調(diào)用objc_alloc,然后條件不成立,走GenerateMessageSend普通消息發(fā)送,走到alloc流程;So
自定義類的流程alloc會(huì)走倆次,第一次發(fā)送alloc會(huì)走到objc_alloc,通過objc_alloc走到callAlloc消息發(fā)送,會(huì)再次走到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這個(gè)函數(shù)一定會(huì)走, 從上可知,這個(gè)函數(shù)里有一個(gè)case判斷,如果是alloc,會(huì)調(diào)用objc_alloc,然后這個(gè)if條件不成立, 會(huì)執(zhí)行下邊GenerateMessageSend函數(shù),執(zhí)行普通的消息發(fā)送 ,走alloc流程。
0x02 -- 附上流程圖

-
NSObject alloc流程圖

- 自定義類
alloc流程圖