isa探索

作者: king_jensen | 来源:发表于2019-02-23 15:19 被阅读2次

    打开objc-750源码,找到结构体objc_object,直接对isa源码分析。

    struct objc_object {
        Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
    };
    
    struct objc_object {
    private:
        isa_t isa;
    
    public:
    
        // ISA() assumes this is NOT a tagged pointer object
        Class ISA();
    
        // getIsa() allows this to be a tagged pointer object
        Class getIsa();
    
        // initIsa() should be used to init the isa of new objects only.
        // If this object already has an isa, use changeIsa() for correctness.
        // initInstanceIsa(): objects with no custom RR/AWZ
        // initClassIsa(): class objects
        // initProtocolIsa(): protocol objects
        // initIsa(): other objects
        void initIsa(Class cls /*nonpointer=false*/);
        void initClassIsa(Class cls /*nonpointer=maybe*/);
        void initProtocolIsa(Class cls /*nonpointer=maybe*/);
        void initInstanceIsa(Class cls, bool hasCxxDtor);
    
        // changeIsa() should be used to change the isa of existing objects.
        // If this is a new object, use initIsa() for performance.
        Class changeIsa(Class newCls);
    
        bool hasNonpointerIsa();
        bool isTaggedPointer();
        bool isBasicTaggedPointer();
        bool isExtTaggedPointer();
        bool isClass();
    
        // object may have associated objects?
        bool hasAssociatedObjects();
        void setHasAssociatedObjects();
    
        // object may be weakly referenced?
        bool isWeaklyReferenced();
        void setWeaklyReferenced_nolock();
    
        // object may have -.cxx_destruct implementation?
        bool hasCxxDtor();
    
        // Optimized calls to retain/release methods
        id retain();
        void release();
        id autorelease();
    
        // Implementations of retain/release methods
        id rootRetain();
        bool rootRelease();
        id rootAutorelease();
        bool rootTryRetain();
        bool rootReleaseShouldDealloc();
        uintptr_t rootRetainCount();
    
        // Implementation of dealloc methods
        bool rootIsDeallocating();
        void clearDeallocating();
        void rootDealloc();
    
    private:
        void initIsa(Class newCls, bool nonpointer, bool hasCxxDtor);
    
        // Slow paths for inline control
        id rootAutorelease2();
        bool overrelease_error();
    
    #if SUPPORT_NONPOINTER_ISA
        // Unified retain count manipulation for nonpointer isa
        id rootRetain(bool tryRetain, bool handleOverflow);
        bool rootRelease(bool performDealloc, bool handleUnderflow);
        id rootRetain_overflow(bool tryRetain);
        bool rootRelease_underflow(bool performDealloc);
    
        void clearDeallocating_slow();
    
        // Side table retain count overflow for nonpointer isa
        void sidetable_lock();
        void sidetable_unlock();
    
        void sidetable_moveExtraRC_nolock(size_t extra_rc, bool isDeallocating, bool weaklyReferenced);
        bool sidetable_addExtraRC_nolock(size_t delta_rc);
        size_t sidetable_subExtraRC_nolock(size_t delta_rc);
        size_t sidetable_getExtraRC_nolock();
    #endif
    
        // Side-table-only retain count
        bool sidetable_isDeallocating();
        void sidetable_clearDeallocating();
    
        bool sidetable_isWeaklyReferenced();
        void sidetable_setWeaklyReferenced_nolock();
    
        id sidetable_retain();
        id sidetable_retain_slow(SideTable& table);
    
        uintptr_t sidetable_release(bool performDealloc = true);
        uintptr_t sidetable_release_slow(SideTable& table, bool performDealloc = true);
    
        bool sidetable_tryRetain();
    
        uintptr_t sidetable_retainCount();
    #if DEBUG
        bool sidetable_present();
    #endif
    };
    

    从代码中我们知道isa的类型是isa_t, 进入isa_t类型:

    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
    };
    

    我们发现isa_t是一个联合体,使用联合体数据共享一片内存,节省消耗.
    进入 Class ISA();

    #   define ISA_MASK        0x00007ffffffffff8ULL
    
    inline Class 
    objc_object::ISA() 
    {
        assert(!isTaggedPointer()); 
    #if SUPPORT_INDEXED_ISA
        if (isa.nonpointer) {
            uintptr_t slot = isa.indexcls;
            return classForIndex((unsigned)slot);
        }
        return (Class)isa.bits;
    #else
        return (Class)(isa.bits & ISA_MASK);
    #endif
    }
    

    代码中我们发现,isa_t联合体中的 bits & ISA_MASK,能直接得出该对象的isa对象的内存地址,我们用一个实例来验证一下。

       LGPerson *p = [[LGPerson alloc] init];
            p.name      = @"Cooci";
            p.age  
    
    E4760E68820834F90A96606A0B2B542C.png

    相关文章

      网友评论

          本文标题:isa探索

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