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 位的系统,但是对象的指针不需要64位这么多位去编码。
虽然相当于原来的 isa 字段变成了一个总长为64位的,以位为基本分配单元的数据结构。
此数据结构还封装了其他数据,如一个对象的引用计算。是否是弱引用等。
它有两个好处:

  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.

应用的代码应该注意什么?

  1. 不要直接读取 obj->isa 字段。如果这么做了编译器会报错。
    应该改为使用 [obj class] 或者 object_getClass(obj)

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

  2. 也不要直接对 obj->isa 字段赋值。 应该使用 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 位 所代表的信息说明。

仅作参考 ,说不定现在的实现已经改变了呢。

(LSB)
 1 bit indexed       0 表示为原始的 isa , 1 表示是一个 non-pointer isa.
 1 bit has_assoc     对象有过或者曾经有过 关联引用 ,没有关联引用可以更快的 dealloc
 1 bit has_cxx_dtor  对象是否有 C++ 或者 ARC 的析构函数。没有析构函数可以更块的 dealloc
30 bits shiftcls     对象指针的非 0 位
 9 bits magic        为 0xd2. 用于识别是否是真正的对象而不是未初始化的没用的东西。
 1 bit weakly_referenced 对象有或曾经被一个 ARC 的 weak 变量引用过。没有引用过可以更快的dealloc
 1 bit deallocating  对象当前正在 deallocating
 1 bit has_sidetable_rc 对象的引用计算值太大无法内联存储。
19 bits extra_rc     对象除了1之外的引用计算。(如假设些值为 5 ,那么对象真实的引用计数为 6.)
(MSB)

根据最新的公开的
http://www.opensource.apple.com/tarballs/objc4/
Objective-C 源代码。objc4-647

  1. objc_object 的isa属性是一个 isa_t的类型。
  2. isa_t是一个联合。 对于 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字段最初是用来存储对象所对应的类的。后来isa字段的值变复杂的。
但是记录所指向的类还是本值工作。isa 也是 is a的联合。
即此对象是一个什么?
objc_object 结构有如下两个公开的方法:

    // 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

在深入了解其实现,先了解几点。

  1. SUPPORT_TAGGED_POINTERS 在 arm64 或者 64 位时它真。
  2. Tagged pointer 可以参考 Tagged pointer
    简单的来说,Tagged pointer 就是非单纯的指针。它还带有其他的数据信息。比如上面介绍的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指针。
后面几个函数都是同样的操作:

```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的函数在ARM64 下是以汇编来实现的如下:

    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中数据复制到老的isa中。同时也为设置关联的对象。
  1. ISA 与 MetaClass

更多说明见: Objective-C class

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351

推荐阅读更多精彩内容