复杂度高的项目系统,我惯于花时间梳理出大手稿,作为参考,根据这个思路,我花时间对于OC底层的机制进行梳理,产出大手稿若干。
第二篇:实例化源码流程
上图
这篇画图废了10多个小时时间,先不展开写了,后面有空再补上吧
先占位一个简单地逐字稿
alloc init 这个方法,在 LLVM 的 CGObjC.cpp 中有一个 tryGenerateSpecializedMessageSend,给ObjCRuntime 提供了一些更快的代码执行入口点,相比于普通常规的 msgsend 的方法选择器来比较的,这个快速入口保证了一样的执行效果。如果这个入口点的内部只是一个消息发送的原生实现,使用它是一个这种方案,牺牲了几个循环的开销,以节省少量代码。
通过这个机制, alloc init 之后调用根本没有调用 NSObject 的 alloc 方法。
调用的是objc_alloc_init(cls)方法,再调用 callAlloc(Class cls, bool checkNil, bool allocWithZone=false)方法,传值(cls, true, false),这里也解释了为什么,真正的allocinit不会去调用allocWithZone。
cls拿到ISA指针蒙版运算得到objcClass
这个时候离开了NSObject层,来到runtime层,调用_objc_rootAllocWithZone,调用一个核心的方法 _createInstanceFromZone,但是zone传的是NULL,也就是是这个函数里面去组装填充所有ISA指针里面的信息,并且完成第一次的字节对齐,这里对齐是向上16对齐对齐,目前还没有调用calloc方法。
然后计算好size之后,调用 libmalloc 工程里面的 calloc 方法,这个方法会调用libmalloc里面的层层调用,最后在segregated_size_to_fit完成了16字节桶空间对齐,似的一个对象的内存大小总是16字节的整数倍。
InitInstanceIsa 初始化实例对象的 isa 指针,进行关联类对象实例。
然后完成之后回到上上上层方法,完成alloc,调用_objc_rootInit,然后就没有然后了,就返回对象了。
References
https://www.jianshu.com/p/9d649ce6d0b8
https://blog.csdn.net/myiphon/article/details/105159233
https://www.jianshu.com/p/9d649ce6d0b8
大感谢:霜神的这篇Objc 对象的今生今世
https://www.jianshu.com/p/f725d2828a2f
- Post link: http://yangzai360.top/2020/11/04/OCBigManuscript02_ObjectAllocInit/
- Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.