isa結構分析

首先來看下c++

objc isa主要源碼

#include "isa.h"

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是一個聯合體union, cls 與bits是互斥關係。markdown

在看下ISA_BITFIELD宏定義 架構

# if __arm64__ //手機端
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
#   define ISA_BITFIELD                                                      \
      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
#   define RC_ONE   (1ULL<<45)
#   define RC_HALF  (1ULL<<18)

# elif __x86_64__ //終點架構(模擬器/mac)
#   define ISA_MASK        0x00007ffffffffff8ULL
#   define ISA_MAGIC_MASK  0x001f800000000001ULL
#   define ISA_MAGIC_VALUE 0x001d800000000001ULL
#   define ISA_BITFIELD                                                        \
      uintptr_t nonpointer        : 1;                                         \
      uintptr_t has_assoc         : 1;                                         \
      uintptr_t has_cxx_dtor      : 1;                                         \
      uintptr_t shiftcls          : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
      uintptr_t magic             : 6;                                         \
      uintptr_t weakly_referenced : 1;                                         \
      uintptr_t deallocating      : 1;                                         \
      uintptr_t has_sidetable_rc  : 1;                                         \
      uintptr_t extra_rc          : 8
#   define RC_ONE   (1ULL<<56)
#   define RC_HALF  (1ULL<<7)

# else
#   error unknown architecture for packed isa
# endif

// SUPPORT_PACKED_ISA
#endif
複製代碼

咱們來將其簡單分享分析一下ide

  • 位1(nonpointer) : 表示是否對isa指針開啓指針優化,0表示純isa指針,1表示不⽌是類對象地址,isa中包含了類信息、對象的引⽤計數等。函數

  • 位2( has_assoc) : 關聯對象標誌位,1——存在,0——沒有源碼分析

  • 位3(has_cxx_dtor): 該對象是否有C++或者Objc的析構器,若是有析構函數,則須要作析構邏輯,若是沒有,則能夠更快的釋放對象。優化

  • 位4(shiftcls) : 存儲類指針的值。開啓指針優化的狀況下,在arm64架構中有33位⽤來存儲類指針。ui

  • 位5(magic) : ⽤於調試器判斷當前對象是真的對象仍是沒有初始化的空間this

  • 位6(weakly_referenced) : 對象是否被指向或者曾經指向⼀個ARC的弱變量,沒有弱引⽤的對象能夠更快釋放。spa

  • 位7(deallocating) : 標誌對象是否正在釋放內存

  • 位8(has_sidetable_rc) : 當對象引⽤計數⼤於10時,則須要借⽤該變量存儲進位

  • 位9(extra_rc): 當表示該對象的引⽤計數值,其實是引⽤計數值減1, 例如,若是對象的引⽤計數爲10,那麼extra_rc爲9。若是引⽤計數⼤於10,則須要使⽤到下⾯的has_sidetable_rc

接下來咱們來看下對象釋放時候的一些處理

dealloc源碼分析

inline void
objc_object::rootDealloc()
{
    if (isTaggedPointer()) return;  // fixme necessary?

    if (fastpath(isa.nonpointer  &&  
                 !isa.weakly_referenced  &&  
                 !isa.has_assoc  &&  //關聯對象
                 !isa.has_cxx_dtor  &&  
                 !isa.has_sidetable_rc))//閃鏈表
    {
        assert(!sidetable_present());
        free(this);//移除處理
    } 
    else {
        object_dispose((id)this);//釋放
    }
}

id 
object_dispose(id obj)
{
    if (!obj) return nil;

    objc_destructInstance(obj);    
    free(obj);

    return nil;
}

objc_destructInstance(obj):
void *objc_destructInstance(id obj) 
{
    if (obj) {
        // Read all of the flags at once for performance.
        bool cxx = obj->hasCxxDtor();
        bool assoc = obj->hasAssociatedObjects();//關聯對象

        // This order is important.
        if (cxx) object_cxxDestruct(obj);//c++ 析構
        if (assoc) _object_remove_assocations(obj);//移除關聯對象
        obj->clearDeallocating();
    }

    return obj;
}

obj->clearDeallocating():
inline void 
objc_object::clearDeallocating()
{
    if (slowpath(!isa.nonpointer)) {
        // Slow path for raw pointer isa.
        sidetable_clearDeallocating();
    }
    else if (slowpath(isa.weakly_referenced  ||  isa.has_sidetable_rc)) {
        // Slow path for non-pointer isa with weak refs and/or side table data.
        clearDeallocating_slow();
    }

    assert(!sidetable_present());
}
複製代碼
相關文章
相關標籤/搜索