美文网首页
Runtime初始化alloc

Runtime初始化alloc

作者: 昵称是乱起的 | 来源:发表于2019-01-22 19:29 被阅读8次
    alloc主要是做了isa的初始化,先看下isa_t联合体的结构
    union isa_t 
    {
        Class cls;
        uintptr_t bits;
        struct {
            uintptr_t nonpointer        : 1;
            uintptr_t has_assoc         : 1;
            uintptr_t has_cxx_dtor      : 1;
            uintptr_t shiftcls          : 33; // MACH_VM_MAX_ADDRESS 0x1000000000
            uintptr_t magic             : 6;
            uintptr_t weakly_referenced : 1;
            uintptr_t deallocating      : 1;
            uintptr_t has_sidetable_rc  : 1;
            uintptr_t extra_rc          : 19;
        };
    }
    
    nonpointer
    0,代表普通的指针,存储着Class、Meta-Class对象的内存地址
    1,代表优化过,使用位域存储更多的信息
    
    has_assoc
    是否有设置过关联对象,如果没有,释放时会更快
    
    has_cxx_dtor
    是否有C++的析构函数(.cxx_destruct),如果没有,释放时会更快
    
    shiftcls
    存储着Class、Meta-Class对象的内存地址信息
    
    magic
    用于在调试时分辨对象是否未完成初始化
    
    weakly_referenced
    是否有被弱引用指向过,如果没有,释放时会更快
    
    deallocating
    对象是否正在释放
    
    has_sidetable_rc
    引用计数器是否过大无法存储在isa中
    如果为1,那么引用计数会存储在一个叫SideTable的类的属性中
    
    extra_rc
    里面存储的值是引用计数器减1
    
    #alloc的调用栈
    - alloc
      - objc_rootAlloc(cls);
        - callAlloc(cls, false, false);
          - class_createInstance(cls, 0);
            - _class_createInstanceFromZone(cls, 0, nil);
              - initInstanceIsa(Class cls, bool hasCxxDtor)
                - initIsa(Class cls, bool nonpointer, bool hasCxxDtor)
    
    + (id)alloc {
        return _objc_rootAlloc(self);
    }
    id _objc_rootAlloc(Class cls)
    {
        return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
    }
    
    static ALWAYS_INLINE id
    callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
    {
    //__builtin_expect 起的是优化性能的作用,fastpath(x) 表示 x 较大概率为真,slowpath(x) 表示 x 较大概率为假
        if (slowpath(checkNil && !cls)) return nil;
    #if __OBJC2__
       //没有自己实现alloc/allocWithZone就走if里面的系统实现
        if (fastpath(!cls->ISA()->hasCustomAWZ())) {
            // No alloc/allocWithZone implementation. Go straight to the allocator.
            // fixme store hasCustomAWZ in the non-meta class and 
            // add it to canAllocFast's summary
            if (fastpath(cls->canAllocFast())) {//这个地方固定返回false,直接看else就行
                // No ctors, raw isa, etc. Go straight to the metal.
                bool dtor = cls->hasCxxDtor();
                id obj = (id)calloc(1, cls->bits.fastInstanceSize());
                if (slowpath(!obj)) return callBadAllocHandler(cls);
                obj->initInstanceIsa(cls, dtor);
                return obj;
            }
            else {
                // Has ctor or raw isa or something. Use the slower path.
               //重点关心的
                id obj = class_createInstance(cls, 0);
                //做一些错误处理,不需要关系
                if (slowpath(!obj)) return callBadAllocHandler(cls);
                return obj;
            }
        }
    #endif
        // No shortcuts available.
        if (allocWithZone) return [cls allocWithZone:nil];
        return [cls alloc];
    }
    
    id class_createInstance(Class cls, size_t extraBytes)
    {
        return _class_createInstanceFromZone(cls, extraBytes, nil);
    }
    static __attribute__((always_inline)) 
    id
    _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, 
                                  bool cxxConstruct = true, 
                                  size_t *outAllocatedSize = nil)
    {
        if (!cls) return nil;
        assert(cls->isRealized());
        // Read class's info bits all at once for performance
        //类构造函数和析构函数
        bool hasCxxCtor = cls->hasCxxCtor();
        bool hasCxxDtor = cls->hasCxxDtor();
       //支持isa_t 类型
        bool fast = cls->canAllocNonpointer();
        //根据内存对齐原则,最少分配16字节的内存
        size_t size = cls->instanceSize(extraBytes);
        if (outAllocatedSize) *outAllocatedSize = size;
        id obj;
        if (!zone  &&  fast) {//能进来这里
            obj = (id)calloc(1, size);
            if (!obj) return nil;
            //isa的初始化
            obj->initInstanceIsa(cls, hasCxxDtor);
        } 
        else {
            if (zone) {
                obj = (id)malloc_zone_calloc ((malloc_zone_t *)zone, 1, size);
            } else {
                obj = (id)calloc(1, size);
            }
            if (!obj) return nil;
            // Use raw pointer isa on the assumption that they might be 
            // doing something weird with the zone or RR.
            obj->initIsa(cls);
        }
        if (cxxConstruct && hasCxxCtor) {
            obj = _objc_constructOrFree(obj, cls);
        }
        return obj;
    }
    
    //分配内存大小
    uint32_t alignedInstanceSize() {
            return word_align(unalignedInstanceSize());
        }
        size_t instanceSize(size_t extraBytes) {
            size_t size = alignedInstanceSize() + extraBytes;
            // CF requires all objects be at least 16 bytes.
            if (size < 16) size = 16;
            return size;
        }
    
    inline void 
    objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)
    {
        assert(!cls->instancesRequireRawIsa());
        assert(hasCxxDtor == cls->hasCxxDtor());
        initIsa(cls, true, hasCxxDtor);
    }
    inline void 
    objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) 
    { 
        assert(!isTaggedPointer()); 
        if (!nonpointer) {
            isa.cls = cls;
        } else {//会来到这里面
            assert(!DisableNonpointerIsa);
            assert(!cls->instancesRequireRawIsa());
            //初始化一个所有位为 0 的指针
            isa_t newisa(0);
    #if SUPPORT_INDEXED_ISA
            assert(cls->classArrayIndex() > 0);
            newisa.bits = ISA_INDEX_MAGIC_VALUE;
            // isa.magic is part of ISA_MAGIC_VALUE
            // isa.nonpointer is part of ISA_MAGIC_VALUE
            newisa.has_cxx_dtor = hasCxxDtor;
            newisa.indexcls = (uintptr_t)cls->classArrayIndex();
    #else//会走这里
           //先将 newisa 的 bits 赋值为常量 ISA_MAGIC_VALUE,里面包括了 magic 和  nonpointer 的值
            newisa.bits = ISA_MAGIC_VALUE;
            // isa.magic is part of ISA_MAGIC_VALUE
            // isa.nonpointer is part of ISA_MAGIC_VALUE
           //有 C++ 析构函数标示上
            newisa.has_cxx_dtor = hasCxxDtor;
           //cls右移3位的原因是机器内存对齐的原因,最后的3位值都是0,右移后没有影响
            newisa.shiftcls = (uintptr_t)cls >> 3;
    #endif
            // This write must be performed in a single store in some cases
            // (for example when realizing a class because other threads
            // may simultaneously try to use the class).
            // fixme use atomics here to guarantee single-store and to
            // guarantee memory order w.r.t. the class index table
            // ...but not too atomic because we don't want to hurt instantiation
            isa = newisa;
        }
    }
    

    初始化完成后的isa结构,从右往左,从上往下看,64位域的分配图


    image.png
    init的底层其实什么也没做
    - (id)init {
        return _objc_rootInit(self);
    }
    id _objc_rootInit(id obj)
    {
        // In practice, it will be hard to rely on this function.
        // Many classes do not properly chain -init calls.
        return obj;
    }
    

    相关文章

      网友评论

          本文标题:Runtime初始化alloc

          本文链接:https://www.haomeiwen.com/subject/anekjqtx.html