Objective-C What is ISA

此文實際成于 2015/08/09

[objc explain]: Non-pointer isa

from objc explain: Non-pointer isa

On iOS for arm64, the isa field of Objective-C objects is no longer a pointer.

主要是因為雖然是 64 位的系統(tǒng),但是對象的指針不需要64位這么多位去編碼。
雖然相當(dāng)于原來的 isa 字段變成了一個總長為64位的蚤氏,以位為基本分配單元的數(shù)據(jù)結(jié)構(gòu)留潦。
此數(shù)據(jù)結(jié)構(gòu)還封裝了其他數(shù)據(jù)故觅,如一個對象的引用計算掏觉。是否是弱引用等繁堡。
它有兩個好處:

  1. 性能更好瞎饲。
  2. 速度更快口叙。

Why change it?
Performance. Re-purposing these otherwise unused bits increases speed and decreases memory size. On iOS 7 the focus is on optimizing retain/release and alloc/dealloc.

應(yīng)用的代碼應(yīng)該注意什么?

  1. 不要直接讀取 obj->isa 字段企软。如果這么做了編譯器會報錯庐扫。
    應(yīng)該改為使用 [obj class] 或者 object_getClass(obj)

    Trust the Compiler. The Compiler is your friend. Use [obj class] or object_getClass(obj) instead.

  2. 也不要直接對 obj->isa 字段賦值。 應(yīng)該使用 object_setClass()
    注意:

    The 64-bit iOS simulator currently does not use non-pointer isa. Test your code on a real arm64 device.

What does this mean for debugging?

The debugger knows how to decode the class from the isa field. You should not need to examine it directly in most cases.

You can run your code with environment variable OBJC_DISABLE_NONPOINTER_ISA=YESto disable non-pointer isa for all classes. If your code works with this set and fails without it, you may be incorrectly accessing an isa field directly somewhere.

If you are writing a debugger-like tool, the Objective-C runtime exports some variables to help decode isa fields. objc_debug_isa_class_mask describes which bits are the class pointer: (isa & class_mask) == class pointer. objc_debug_isa_magic_mask and objc_debug_isa_magic_value describe some bits that help distinguish valid isa fields from other invalid values: (isa & magic_mask) == magic_value for isa fields that are not raw class pointers. These variables may change in the future so do not use them in application code.

64 位 所代表的信息說明仗哨。

僅作參考 形庭,說不定現(xiàn)在的實現(xiàn)已經(jīng)改變了呢。

(LSB)
 1 bit indexed       0 表示為原始的 isa , 1 表示是一個 non-pointer isa.
 1 bit has_assoc     對象有過或者曾經(jīng)有過 關(guān)聯(lián)引用 厌漂,沒有關(guān)聯(lián)引用可以更快的 dealloc
 1 bit has_cxx_dtor  對象是否有 C++ 或者 ARC 的析構(gòu)函數(shù)萨醒。沒有析構(gòu)函數(shù)可以更塊的 dealloc
30 bits shiftcls     對象指針的非 0 位
 9 bits magic        為 0xd2. 用于識別是否是真正的對象而不是未初始化的沒用的東西。
 1 bit weakly_referenced 對象有或曾經(jīng)被一個 ARC 的 weak 變量引用過苇倡。沒有引用過可以更快的dealloc
 1 bit deallocating  對象當(dāng)前正在 deallocating
 1 bit has_sidetable_rc 對象的引用計算值太大無法內(nèi)聯(lián)存儲富纸。
19 bits extra_rc     對象除了1之外的引用計算。(如假設(shè)些值為 5 旨椒,那么對象真實的引用計數(shù)為 6.)
(MSB)

根據(jù)最新的公開的
http://www.opensource.apple.com/tarballs/objc4/
Objective-C 源代碼晓褪。objc4-647

  1. objc_object 的isa屬性是一個 isa_t的類型。
  2. isa_t是一個聯(lián)合综慎。 對于 arm64來說其定義如下:(對于x86-64來說不同)
union isa_t 
{
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }

    Class cls;
    uintptr_t bits;
#   define ISA_MASK        0x00000001fffffff8ULL
#   define ISA_MAGIC_MASK  0x000003fe00000001ULL
#   define ISA_MAGIC_VALUE 0x000001a400000001ULL
    struct {
        uintptr_t indexed           : 1;
        uintptr_t has_assoc         : 1;
        uintptr_t has_cxx_dtor      : 1;
        uintptr_t shiftcls          : 30; // MACH_VM_MAX_ADDRESS 0x1a0000000
        uintptr_t magic             : 9;
        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)
    };
  };

ISA 與 Class

前面說到 isa字段最初是用來存儲對象所對應(yīng)的類的涣仿。后來isa字段的值變復(fù)雜的。
但是記錄所指向的類還是本值工作。isa 也是 is a的聯(lián)合好港。
即此對象是一個什么愉镰?
objc_object 結(jié)構(gòu)有如下兩個公開的方法:

    // ISA() assumes this is NOT a tagged pointer object
   Class ISA();

   // getIsa() allows this to be a tagged pointer object
   Class getIsa();

他們返回的類型的都 Class類型。

之前我們分析過钧汹,Classstruct objc_class的別名丈探。
struct objc_class繼承自 struct objc_object

在深入了解其實現(xiàn),先了解幾點拔莱。

  1. SUPPORT_TAGGED_POINTERS 在 arm64 或者 64 位時它真碗降。
  2. Tagged pointer 可以參考 Tagged pointer
    簡單的來說,Tagged pointer 就是非單純的指針辨宠。它還帶有其他的數(shù)據(jù)信息遗锣。比如上面介紹的isa的指針。
    Greg Parker 在這里有說明:舉例嗤形。 http://stackoverflow.com/questions/20362406/tagged-pointers-in-objective-c

更多說明見 Tagged Pointer.

  1. initIsa
 inline void 
objc_object::initIsa(Class cls){
 isa = (uintptr_t)cls; 
}

將其類的指針賦值給objc_object對象的 isa指針精偿。
后面幾個函數(shù)都是同樣的操作:

```cpp
    inline void objc_object::initClassIsa(Class cls) { initIsa(cls); }
    inline void objc_object::initProtocolIsa(Class cls) { initIsa(cls); }
    inline void objc_object::initInstanceIsa(Class cls, bool) { initIsa(cls); }
    inline void objc_object::initIsa(Class cls, bool, bool) { initIsa(cls); }
```
  1. changeIsa
    還可以更換一個對象的Class,isa這倒是挺有意思的赋兵”恃剩看objc是怎么做的。
```cpp
      inline Class 
    objc_object::changeIsa(Class cls)
    {
        assert(!isTaggedPointer()); 
        
        isa_t oldisa, newisa;
        newisa.cls = cls;
        do {
            oldisa = LoadExclusive(&isa.bits);
        } while (!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits));
        
        if (oldisa.cls  &&  oldisa.cls->instancesHaveAssociatedObjects()) {
            cls->setInstancesHaveAssociatedObjects();
        }
        
        return oldisa.cls;
    }
  ```

StoreExclusive的函數(shù)在ARM64 下是以匯編來實現(xiàn)的如下:

    static ALWAYS_INLINE
bool 
StoreExclusive(uintptr_t *dst, uintptr_t oldvalue __unused, uintptr_t value)
{
  uint32_t result;
  asm("stxr %w0, %x2, [%x3]" 
      : "=r" (result), "=m" (*dst) 
      : "r" (value), "r" (dst));
  return !result;
}
 原來changeIsa 的做法是將新的isa中數(shù)據(jù)復(fù)制到老的isa中霹期。同時也為設(shè)置關(guān)聯(lián)的對象叶组。
  1. ISA 與 MetaClass

更多說明見: Objective-C class

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市历造,隨后出現(xiàn)的幾起案子甩十,更是在濱河造成了極大的恐慌,老刑警劉巖吭产,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侣监,死亡現(xiàn)場離奇詭異,居然都是意外死亡臣淤,警方通過查閱死者的電腦和手機(jī)橄霉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邑蒋,“玉大人姓蜂,你說我怎么就攤上這事∫降酰” “怎么了钱慢?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長卿堂。 經(jīng)常有香客問我滩字,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任麦箍,我火速辦了婚禮,結(jié)果婚禮上陶珠,老公的妹妹穿的比我還像新娘挟裂。我一直安慰自己,他們只是感情好揍诽,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布诀蓉。 她就那樣靜靜地躺著,像睡著了一般暑脆。 火紅的嫁衣襯著肌膚如雪渠啤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天添吗,我揣著相機(jī)與錄音沥曹,去河邊找鬼。 笑死碟联,一個胖子當(dāng)著我的面吹牛妓美,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鲤孵,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼壶栋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了普监?” 一聲冷哼從身側(cè)響起贵试,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凯正,沒想到半個月后毙玻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡漆际,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年淆珊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奸汇。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡施符,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出擂找,到底是詐尸還是另有隱情戳吝,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布贯涎,位于F島的核電站听哭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜陆盘,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一普筹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧隘马,春花似錦太防、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至幔嗦,卻和暖如春酿愧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背邀泉。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工嬉挡, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人呼渣。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓棘伴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親屁置。 傳聞我的和親對象是個殘疾皇子焊夸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容