手撕 iOS 底層03 -- NSObject的alloc分析

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


0x00 -- objc_alloc

01.jpg

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

通過匯編調(diào)試得知:

  • NSObjectalloc之前會(huì)調(diào)用objc_alloc,自定義類Test也會(huì)先調(diào)用objc_alloc;

系統(tǒng)級別就把NSObject的初始化做了,所以NSObjectalloc的調(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,看看其中是否可以找到一些蛛絲馬跡????????

  1. 搜索objc_alloc,找到如下所示,在當(dāng)前文件由很多objc_alloc關(guān)鍵字;一點(diǎn)一點(diǎn)往下捋;
LLVM-1.png
  1. 再往下看,shouldUseRuntimeFunctionForCombinedAllocInit這個(gè)方法表示版本控制;
LLVM-2.png
  1. 然后查找什么地方使用了版本控制。找到特殊消息發(fā)送tryEmitSpecializedAllocInit
LLVM-3.png
  1. 遇到不好查找的關(guān)鍵代碼時(shí),開啟上帝視覺,當(dāng)前查找關(guān)鍵字omf-aloc
LLVM-4.png

在下邊會(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源碼里;

LLVM-5.png
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流程.png
  • NSObject alloc流程圖

2020大師.png
  • 自定義類alloc流程圖
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容