1.为什么要用alloc?
我们在oc开发当中经常使用alloc来为对象申请开辟内存空间例如
School *s1 = [School alloc]
2.alloc 的流程
在苹果开源的源码文件NSObject.mm中可以轻易找到alloc的流程。如下
objetc_alloc->alloc->_objc_rootAlloc->callAlloc->_objc_rootAllocWithZone->_class_createInstanceFromZone
可以知道一点在_class_createInstanceFromZone后会有三个条件判断。这三个条件判断就是alloc的精髓也既是我们需要研究的对象
1.size= cls->instanceSize
这行代码可以清晰一个问题,我们alloc的时候首先需要知道实例化对象的类 需要多少/多大的内存空间。
instanceSize->cache.fastInstanceSize
到这里我们可以看到fastInstanceSize 下面有两行代码以及英文注释:(通过setFastInstanceSize函数移除已经添加的MASK)
继续深入下去会发现有三个问题1.flags是什么 2.mask掩码作用 3.为什么要进行逻辑与运算
1.size=_flags & MASK (mask其实只是一个定义在已初始化区里的一个常量=8)
这里我们可以看见size=16 也既证明了一个空对象能占16大小空间,size的大小取决于类的属性多少
2.align16(size extra - 宏8byte)
return (x 15) & ~15
这句代码是经典的16字节对齐算法,具体过程请参照c语言-逻辑运算.
2.obj=(id)calloc(1,size)
calloc->malloc_zone_calloc->zone->calloc->nano_malloc_check_clear->segregated_size_to_fit
千呼万唤始出来,终于找到关键函数
segregated_size_to_fit()
k=(size nano_size -1 ) >> shift_nano_quantum
k=(x 15)>>4
slot_bytes=k<<4
3.obc->initInstanceIsa(cls,hasCxxDtor)
对象在clang编译下会变成c 的结构体,大小为8字节*8=64位
initIsa->isa_t->newisa
特点:isa_t的结构是联合体位域union 包含cls bits;
ISA_BITFIELD 这里就是区分arm64架构和x86_64的地方 区别在与
nonpointer:1 是否对isa开启指针优化 0:代表纯isa指针 1:代表isa中包含了类信息,对象引用计数等
has_assoc:1是否有关联对象
has_cxx_dtor:1 是否有c 扩展
uintptr_t shiftcls :33/44 arm/x86 存放类信息
magic:6 是否初始化空间
weakly_referenced:1 是否被指向一个arc弱引用变量,没有可以更快的释放
deallocating:1 析构
has_sidetable_rc:1 散列表 当引用计数大于10时,则需要借用该变量存储进位
extra_rc:19 应用计数
newisa函数做了以下几件事
1.给bits cxx_dtor shiftcls 赋值
newisa.bits=ISA_MAGIC_VALUE; 0x001d800000000001ULL =59
newisa.has_cxx_dtor=hasCxxDtor
newisa.shiftcls = cls>>3左移三位 把noptr asoc cxx 这三个敏感信息移出
说明了isa关联了指针和类
isa & 0x00007ffffffffff8ULL = class
自此 通过initIsa(cls,true,hasCxxDtor)关联类和拓展 就完成了alloc下class_createInstanceFromZone的三个步骤。
我们可以发现知识涉及:isa结构 类 算法 缓存 逻辑运算 等等。