objc4

作者: 携一两本单色书来 | 来源:发表于2020-09-01 15:19 被阅读0次

    从NSObject说起

    @interface NSObject <NSObject> {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wobjc-interface-ivars"
        Class isa  OBJC_ISA_AVAILABILITY;
    #pragma clang diagnostic pop
    }
    

    点击Class 我们可以明显看到,iOS中的Class是一个objc_class结构体

    typedef struct objc_class *Class;
    

    runtime.h里关于objc_class的声明,其中我们可以清楚看到部分属性

    struct objc_class {
    ///isa指针
        Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
    
    #if !__OBJC2__
    ///父类指针
        Class _Nullable super_class                              OBJC2_UNAVAILABLE;
        const char * _Nonnull name                               OBJC2_UNAVAILABLE;
        long version                                             OBJC2_UNAVAILABLE;
        long info                                                OBJC2_UNAVAILABLE;
        long instance_size                                       OBJC2_UNAVAILABLE;
    ///属性列表
        struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    ///方法列表
        struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    ///缓存数据
        struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    ///协议列表
        struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
    #endif
    
    } OBJC2_UNAVAILABLE;
    

    之后的底层实现就需要到官网去下载objc4源码查看具体实现

    以上代码在objc里的实现,而objc_object 就是我们开发见到的id对象

    /// An opaque type that represents an Objective-C class.
    typedef struct objc_class *Class;
    
    /// Represents an instance of a class.
    struct objc_object {
        Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
    };
    
    /// A pointer to an instance of a class.
    typedef struct objc_object *id;
    

    可以在objc-pivate.h里看到具体实现,包括MRC的retain,release方法,而其中只有一个属性,就是isa,

    struct objc_object {
    private:
        isa_t isa;
    
    public:
    Class getIsa();
       void initIsa(Class cls /*nonpointer=false*/);
        void initClassIsa(Class cls /*nonpointer=maybe*/);
        void initProtocolIsa(Class cls /*nonpointer=maybe*/);
        void initInstanceIsa(Class cls, bool hasCxxDtor);
        id retain();
        void release();
    

    isa_t的声明,可以看到isa_t是一个共用体,包含了cls 和bits两个属性

    union isa_t {
        isa_t() { }
        isa_t(uintptr_t value) : bits(value) { }
    
        Class cls;
        uintptr_t bits;
    #if defined(ISA_BITFIELD)
        struct {
            ISA_BITFIELD;  // defined in isa.h
        };
    #endif
    };
    

    objc_class 部分声明,可以看到class继承与objc_object,本质也是对象

    struct objc_class : objc_object {
        Class superclass;  //父类指针
        cache_t cache;             // 指针和 vtable
        class_data_bits_t bits;    // 存储类的方法、属性和遵循的协议等信息的地方
    }
    
    

    NSObject.mm里的retain操作
    如果是Tagged Pointer

    __attribute__((aligned(16), flatten, noinline))
    id 
    objc_retain(id obj)
    {
        if (!obj) return obj;
        if (obj->isTaggedPointer()) return obj;
        return obj->retain();
    }
    inline id 
    objc_object::retain()
    {
        ASSERT(!isTaggedPointer());
    
        if (fastpath(!ISA()->hasCustomRR())) {
            return rootRetain();
        }
    //objc_object执行retain
        return ((id(*)(objc_object *, SEL))objc_msgSend)(this, @selector(retain));
    }
    //rootRetain方法
    objc_object::rootRetain(bool tryRetain, bool handleOverflow)
    {
        if (isTaggedPointer()) return (id)this;
    
        bool sideTableLocked = false;
        bool transcribeToSideTable = false;
    
        isa_t oldisa;
        isa_t newisa;
    
        do {
            transcribeToSideTable = false;
            oldisa = LoadExclusive(&isa.bits);
            newisa = oldisa;
            if (slowpath(!newisa.nonpointer)) {
                ClearExclusive(&isa.bits);
                if (rawISA()->isMetaClass()) return (id)this;
                if (!tryRetain && sideTableLocked) sidetable_unlock();
                if (tryRetain) return sidetable_tryRetain() ? (id)this : nil;
                else return sidetable_retain();
            }
            // don't check newisa.fast_rr; we already called any RR overrides
            if (slowpath(tryRetain && newisa.deallocating)) {
                ClearExclusive(&isa.bits);
                if (!tryRetain && sideTableLocked) sidetable_unlock();
                return nil;
            }
            uintptr_t carry;
            newisa.bits = addc(newisa.bits, RC_ONE, 0, &carry);  // extra_rc++
    
            if (slowpath(carry)) {
                // newisa.extra_rc++ overflowed
                if (!handleOverflow) {
                    ClearExclusive(&isa.bits);
                    return rootRetain_overflow(tryRetain);
                }
                // Leave half of the retain counts inline and 
                // prepare to copy the other half to the side table.
                if (!tryRetain && !sideTableLocked) sidetable_lock();
                sideTableLocked = true;
                transcribeToSideTable = true;
                newisa.extra_rc = RC_HALF;
                newisa.has_sidetable_rc = true;
            }
        } while (slowpath(!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)));
    
        if (slowpath(transcribeToSideTable)) {
          //复制保留计数的另一半到 sidetable.
            sidetable_addExtraRC_nolock(RC_HALF);
        }
    
        if (slowpath(!tryRetain && sideTableLocked)) sidetable_unlock();
        return (id)this;
    }
    

    release操作

    __attribute__((aligned(16), flatten, noinline))
    void 
    objc_release(id obj)
    {
        if (!obj) return;
        if (obj->isTaggedPointer()) return;
        return obj->release();
    }
    inline void
    objc_object::release()
    {
        ASSERT(!isTaggedPointer());
    
        if (fastpath(!ISA()->hasCustomRR())) {
            rootRelease();
            return;
        }
    
        ((void(*)(objc_object *, SEL))objc_msgSend)(this, @selector(release));
    }
    objc_object::rootRelease(bool performDealloc, bool handleUnderflow)
    {
        if (isTaggedPointer()) return false;
    
        bool sideTableLocked = false;
    
        isa_t oldisa;
        isa_t newisa;
    
     retry:
        do {
            //加载isa
            oldisa = LoadExclusive(&isa.bits);
            newisa = oldisa;
            if (slowpath(!newisa.nonpointer)) {
                ClearExclusive(&isa.bits);
                if (rawISA()->isMetaClass()) return false;
                if (sideTableLocked) sidetable_unlock();
                return sidetable_release(performDealloc);
            }
            // don't check newisa.fast_rr; we already called any RR overrides
            uintptr_t carry;
            //将 isa 中的引用计数减一
            newisa.bits = subc(newisa.bits, RC_ONE, 0, &carry);  // extra_rc--
            if (slowpath(carry)) {
                // don't ClearExclusive()
                goto underflow;
            }
        } while (slowpath(!StoreReleaseExclusive(&isa.bits, 
                                                 oldisa.bits, newisa.bits)));
        //调用 StoreReleaseExclusive 方法保存新的 isa
    
        if (slowpath(sideTableLocked)) sidetable_unlock();
        return false;
    
     underflow:
        // newisa.extra_rc--  溢出: 从 side table 移除或dealloc
    
        // abandon newisa to undo the decrement
        newisa = oldisa;
    //如果存在clear
        if (slowpath(newisa.has_sidetable_rc)) {
            if (!handleUnderflow) {
                ClearExclusive(&isa.bits);
                return rootRelease_underflow(performDealloc);
            }
    
            // Transfer retain count from side table to inline storage.
    
            if (!sideTableLocked) {//清空bit
                ClearExclusive(&isa.bits);
                sidetable_lock();
                sideTableLocked = true;
                // Need to start over to avoid a race against 
                // the nonpointer -> raw pointer transition.
                goto retry;
            }
    
            // 试着把side table上的引用保留计数
            size_t borrowed = sidetable_subExtraRC_nolock(RC_HALF);
    
            // To avoid races, has_sidetable_rc must remain set 
            // even if the side table count is now zero.
    
            if (borrowed > 0) {
               //为了避免冲突,has_sidetable_rc必须保持设置,即使边表计数现在是零。
                newisa.extra_rc = borrowed - 1;  // redo the original decrement too
                bool stored = StoreReleaseExclusive(&isa.bits, 
                                                    oldisa.bits, newisa.bits);
                if (!stored) {
                    // Inline 更新失败。
                    // 重新尝试.这可以防止LL/SC上的锁
                    // architectures where the side table access itself may have 
                    // dropped the reservation.
                    isa_t oldisa2 = LoadExclusive(&isa.bits);
                    isa_t newisa2 = oldisa2;
                    if (newisa2.nonpointer) {
                        uintptr_t overflow;
                        newisa2.bits = 
                            addc(newisa2.bits, RC_ONE * (borrowed-1), 0, &overflow);
                        if (!overflow) {
                            stored = StoreReleaseExclusive(&isa.bits, oldisa2.bits, 
                                                           newisa2.bits);
                        }
                    }
                }
    
                if (!stored) {
                    // 更新失败
                    // 将 计数 返还给 side table.
                    sidetable_addExtraRC_nolock(borrowed);
                    goto retry;
                }
    
                // Decrement successful after borrowing from side table.
                // This decrement cannot be the deallocating decrement - the side 
                // table lock and has_sidetable_rc bit ensure that if everyone 
                // else tried to -release while we worked, the last one would block.
                sidetable_unlock();
                return false;
            }
            else {
                // Side table is empty after all. Fall-through to the dealloc path.
            }
        }
    
        // Really deallocate
        if (slowpath(newisa.deallocating)) {
            ClearExclusive(&isa.bits);
            if (sideTableLocked) sidetable_unlock();
            return overrelease_error();
            // does not actually return
        }
        newisa.deallocating = true;
        if (!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)) goto retry;
    
        if (slowpath(sideTableLocked)) sidetable_unlock();
    
        __c11_atomic_thread_fence(__ATOMIC_ACQUIRE);
    
        if (performDealloc) {
            ((void(*)(objc_object *, SEL))objc_msgSend)(this, @selector(dealloc));
        }
        return true;
    }
    
    

    autorelease

    __attribute__((aligned(16), flatten, noinline))
    id
    objc_autorelease(id obj)
    {
        if (!obj) return obj;
        if (obj->isTaggedPointer()) return obj;
        return obj->autorelease();
    }
    
    inline id 
    objc_object::autorelease()
    {
        ASSERT(!isTaggedPointer());
        if (fastpath(!ISA()->hasCustomRR())) {
            return rootAutorelease();
        }
    
        return ((id(*)(objc_object *, SEL))objc_msgSend)(this, @selector(autorelease));
    }
    
    

    相关文章

      网友评论

          本文标题:objc4

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