本章要点主要探索
NSObject的alloc源码?为什么要探索NSObject的源码呢, 上一篇手撕iOS底层02 -- 分析alloc&init&new不是分析过alloc的源码了嘛, 通过实践得知,NSObject *objc = [NSObject alloc];这行代码是不会直接走alloc方法里的, 这也就和我们之前探索的自定义类alloc流程有区别?所以这一章分析下NSObject的alloc和自定义类的alloc有什么区别?
0x00 -- objc_alloc

在断点处,点击Debug --> Debug Workflow --> Always Show Disassembly;

通过汇编调试得知:
-
NSObject的alloc之前会调用objc_alloc,自定义类Test也会先调用objc_alloc;
系统级别就把NSObject的初始化做了,所以NSObject的alloc的调用关系是:
alloc --> objc_alloc --> calloc --> _objc_rootAllocWithZone
而自定义类的调用关系是:
alloc --> objc_alloc --> calloc --> objc_msgSend(cls,alloc) --> alloc -- > calloc --> _objc_rootAllocWithZone
0x01 -- 分析自定义类调用俩次alloc
首先探究下,为什么自定义的类调用alloc会直接走到objc_alloc的方法内?
究其原因, 基于alloc的特殊性,应该是LLVM编译器帮我们做了函数指针跳转,所以找一份苹果开源的llvm-project,看看其中是否可以找到一些蛛丝马迹👩❤️👩
- 搜索
objc_alloc,找到如下所示,在当前文件由很多objc_alloc关键字;一点一点往下捋;

- 再往下看,
shouldUseRuntimeFunctionForCombinedAllocInit这个方法表示版本控制;

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

- 遇到不好查找的关键代码时,开启上帝视觉,当前查找关键字
omf-aloc

在下边会调用这个方法特殊消息发送方法tryGenerateSpecializedMessageSend 第一次会调用objc_alloc,然后条件不成立,走GenerateMessageSend普通消息发送,走到alloc流程;So
自定义类的流程alloc会走俩次,第一次发送alloc会走到objc_alloc,通过objc_alloc走到callAlloc消息发送,会再次走到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这个函数一定会走, 从上可知,这个函数里有一个case判断,如果是alloc,会调用objc_alloc,然后这个if条件不成立, 会执行下边GenerateMessageSend函数,执行普通的消息发送 ,走alloc流程。
0x02 -- 附上流程图

-
NSObject alloc流程图

- 自定义类
alloc流程图