蘋果將ISA設(shè)計(jì)成了聯(lián)合體,在ISA中存儲了與該對象相關(guān)的一些內(nèi)存信息怎披,因?yàn)?并不需要64個二進(jìn)制全部都用來存儲指針
ISA 的結(jié)構(gòu)
// x86_64 架構(gòu)
struct {
uintptr_t nonpointer : 1; // 0:普通指針盛龄,1:優(yōu)化過饭耳,使用位域存儲更多信息
uintptr_t has_assoc : 1; // 對象是否含有或曾經(jīng)含有關(guān)聯(lián)引用
uintptr_t has_cxx_dtor : 1; // 表示是否有C++析構(gòu)函數(shù)或OC的dealloc
uintptr_t shiftcls : 44; // 存放著 Class爱只、Meta-Class 對象的內(nèi)存地址信息
uintptr_t magic : 6; // 用于在調(diào)試時分辨對象是否未完成初始化
uintptr_t weakly_referenced : 1; // 是否被弱引用指向
uintptr_t deallocating : 1; // 對象是否正在釋放
uintptr_t has_sidetable_rc : 1; // 是否需要使用 sidetable 來存儲引用計(jì)數(shù)
uintptr_t extra_rc : 8; // 引用計(jì)數(shù)能夠用 8 個二進(jìn)制位存儲時浪规,直接存儲在這里
};
// arm64 架構(gòu)
struct {
uintptr_t nonpointer : 1; // 0:普通指針结蟋,1:優(yōu)化過脯倚,使用位域存儲更多信息
uintptr_t has_assoc : 1; // 對象是否含有或曾經(jīng)含有關(guān)聯(lián)引用
uintptr_t has_cxx_dtor : 1; // 表示是否有C++析構(gòu)函數(shù)或OC的dealloc
uintptr_t shiftcls : 33; // 存放著 Class、Meta-Class 對象的內(nèi)存地址信息
uintptr_t magic : 6; // 用于在調(diào)試時分辨對象是否未完成初始化
uintptr_t weakly_referenced : 1; // 是否被弱引用指向
uintptr_t deallocating : 1; // 對象是否正在釋放
uintptr_t has_sidetable_rc : 1; // 是否需要使用 sidetable 來存儲引用計(jì)數(shù)
uintptr_t extra_rc : 19; // 引用計(jì)數(shù)能夠用 19 個二進(jìn)制位存儲時嵌屎,直接存儲在這里
};
這里的 has_sidetable_rc 和 extra_rc, has_sidetable_rc 表明了該指針是否引用了sidetable 散列表推正,之所以有這個選項(xiàng),是因?yàn)樯倭康囊糜?jì)數(shù)是不會直接存放在SideTables表中的宝惰,對象的引用計(jì)數(shù)會存放在extra_rc 中植榕,當(dāng)其被存滿時,才會存入相應(yīng)的SideTables 散列表中尼夺,SideTable 中有很多張SideTable尊残,每個SideTable 也都是一個散列表,而引用計(jì)數(shù)表就包含在SideTable之中淤堵。
散列表 (引用計(jì)數(shù)表寝衫,弱引用表)
引用計(jì)數(shù)要么存放在isa 的 extra_rc 中,要么存放在引用計(jì)數(shù)表中拐邪,而引用計(jì)數(shù)表中包含在一個叫SideTable 的結(jié)構(gòu)中慰毅,它是一個散列表,也就是哈希表扎阶。而SideTable又包含在一個全局的StripeMap的哈希映射表中汹胃,這個表的名字叫SideTables婶芭。
當(dāng)一個對象訪問SideTables 時:
1、首先會取得對象的地址统台,將地址進(jìn)行哈希運(yùn)算,與SideTables中的SideTabel的個數(shù)取余啡邑,最后得到的結(jié)果就是該對象所訪問的SideTable
2贱勃、在取的SideTable 中RefcountMap 表中再進(jìn)行一次哈希查找。找到該對象在引用計(jì)數(shù)表中對應(yīng)的位置谤逼。
3贵扰、如果該對象存在對應(yīng)的引用計(jì)數(shù),則對其進(jìn)行操作流部,如果沒有對應(yīng)的引用計(jì)數(shù)戚绕,則創(chuàng)建一個對應(yīng)的size_t對象,其實(shí)就是一個uint類型的無符號整型枝冀。
弱引用表也是一張哈希表的結(jié)構(gòu)舞丛,其內(nèi)部包含了每個對象對應(yīng)的弱引用表weak_entry_t,而weak_entry_t 是一個結(jié)構(gòu)數(shù)組果漾,其中包含的則是每一個對象弱引用的對象對應(yīng)的弱引用指針球切。