美文网首页
关于isa的结构分析

关于isa的结构分析

作者: _Luyouli | 来源:发表于2020-09-10 21:46 被阅读0次

isa是什么?

这里是苹果对isa给出的官方解释

A pointer to the class definition of which this object is an instance.

翻译过来就是“一个指向当前实例对象所属的类的指针”

简单来说就是通过isa知道当前对象到底是什么东西,比如一个人作为一个对象,他有很多属性,如身高年龄性别等,但通过这些属性并不知道这个对象到底是个什么东西,那么isa就是用来指向说这个对象是人类。也就是对象通过isa可以找到其根源。

联合体(union)的概念

  • 利用union可以用相同的存储空间存储不同型别的数据类型,从而节省内存空间。当访问其内成员时可用"."和"->"来直接访问。
  • 当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。在C Programming Language一书中对于联合体是这么描述的:
  • 联合体是一个结构;
  • 它的所有成员相对于基地址的偏移量都为0;
  • 此结构空间要大到足够容纳最"宽"的成员;
  • 其对齐方式要适合其中所有的成员;

isa创建流程

inline void 
objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)
{
    ASSERT(!cls->instancesRequireRawIsa());
    ASSERT(hasCxxDtor == cls->hasCxxDtor());

    initIsa(cls, true, hasCxxDtor);
}

inline void 
objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) 
{
    ASSERT(!isTaggedPointer()); 
    
    if (!nonpointer) {
        isa = isa_t((uintptr_t)cls);
    } else {
        ASSERT(!DisableNonpointerIsa);
        ASSERT(!cls->instancesRequireRawIsa());

        isa_t newisa(0);
#if SUPPORT_INDEXED_ISA
        ASSERT(cls->classArrayIndex() > 0);
        newisa.bits = ISA_INDEX_MAGIC_VALUE;
        // isa.magic is part of ISA_MAGIC_VALUE
        // isa.nonpointer is part of ISA_MAGIC_VALUE
        newisa.has_cxx_dtor = hasCxxDtor;
        newisa.indexcls = (uintptr_t)cls->classArrayIndex();
#else
        newisa.bits = ISA_MAGIC_VALUE;
        // isa.magic is part of ISA_MAGIC_VALUE
        // isa.nonpointer is part of ISA_MAGIC_VALUE
        newisa.has_cxx_dtor = hasCxxDtor;
        newisa.shiftcls = (uintptr_t)cls >> 3;
#endif
        // This write must be performed in a single store in some cases
        // (for example when realizing a class because other threads
        // may simultaneously try to use the class).
        // fixme use atomics here to guarantee single-store and to
        // guarantee memory order w.r.t. the class index table
        // ...but not too atomic because we don't want to hurt instantiation
        isa = newisa;
    }
}

我们通过查看alloc源码找到了initInstanceIsa的方法,点进来后里面就是创建isa以及关联类的流程,我们在此源码基础上找到isa的内部结构isa = isa_t((uintptr_t)cls);

isa的内部结构

我们通过查看isa_t发现isa里面是一个联合体

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_BITFIELD里面的结构得到下面的代码,分别是在arm64x86_64架构下的一个成员分布情况
# 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__
#   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)
isa内部成员大小

NONPOINTER_ISA 分析

这里我们仅仅对arm64架构下的结构进行分析

isa内部成员 意义
nonpointer 表示是否对 isa 指针开启指针优化 0:纯isa指针,1:不止是类对象地址,isa 中包含了类信息、对象的引用计数等
has_assoc 关联对象标志位,0没有,1存在
has_cxx_dtor 该对象是否有 C++ 或者 Objc 的析构器,如果有析构函数,则需要做析构逻辑, 如果没有,则可以更快的释放对象
shiftcls 存储类指针的值。开启指针优化的情况下,在 arm64 架构中有 33 位用来存储类指针
magic 用于调试器判断当前对象是真的对象还是没有初始化的空间
weakly_referenced 对象是否被指向或者曾经指向一个 ARC 的弱变量,没有弱引用的对象可以更快释放。
deallocating 标志对象是否正在释放内存
has_sidetable_rc 当对象引用技术大于 10 时,则需要借用该变量存储进位
extra_rc 当表示该对象的引用计数值,实际上是引用计数值减 1, 例如,如果对象的引用计数为 10,那么 extra_rc 为 9。如果引用计数大于 10, 则需要使用到下面的has_sidetable_rc

通过dealloc查看对象释放情况

通过查看dealloc源码发现对象在释放的时候也要对isa里面信息进行清除,这里的成员在我们前面看到的isa内部成员完全符合。

inline void
objc_object::rootDealloc()
{
    if (isTaggedPointer()) return;  
    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);
    }
}

isa与类进行关联

通过前面我们知道了isa其实包含了很多信息,但是isa是怎么和我们的类进行绑定的呢?我们再次查看创建流程的源码,进行断点调试发现在初始化isa后有这么一句代码

newisa.shiftcls = (uintptr_t)cls >> 3;

这句话是什么意思呢?我们知道shiftcls包含了类指针信息,这里将cls编码后右移了三位,cls正是我们的创建的类名字,在这句话之前我们打断点打印刚创建的newisa发现:

newisa

我们可以看到打印的newisa里面正好就有了前面所提到的那些结构,然后通过手动操作对cls编码进行右移三位

newisa与类绑定

我们发现打印的结果中shiftcls里面的值变成了cls的数值536871965,cls也变成了LGPerson,这里说明我们的类已经和新创建的isa绑定起来了,最后再返回该isa就完成了。

相关文章

  • 关于isa的结构分析

    isa是什么? 这里是苹果对isa给出的官方解释 A pointer to the class definitio...

  • Cache_t的结构和原理

    在之间的文章里我们分析了isa的指向和结构isa结构分析,分析了bits类的结构分析,在这篇文章里,我们来分析ob...

  • iOS - isa的初始化&指向分析

    isa结构及初始化分析 什么是isa,首先我们先看一下isa的结构: 由源码我们可以看出:isa的本质就是一个联合...

  • 类的结构分析

    我们在上一节isa的结构分析分析了isa的结构,我们在创建一个类的时候打印其地址得到的第一个地址就是它的isa地址...

  • isa结构分析

    什么是对象? 为了了解Objective-C类在底层会编译成什么,我们先新建一个类DebugPerson。 测试类...

  • isa结构分析

    isa结构分析 OC对象的本质 clang命令 把oc类编译成c++文件,对象在底层编译成struct 联合体(共...

  • isa结构分析

    OC对象的本质 在一个内中添加一个私有类,在main.m文件中添加一个LGPerson类 使用clang将main...

  • isa结构分析

    在我们iOS开发进行lldb调试的时候,经常会在控制台看到isa的存在,那么本文就来分析一下isa的结构。 在分析...

  • isa结构分析

    背景 书接上回alloc流程图分析中,在最后calloc分配空间,可得到空间的地址,那么calloc中系统是如何分...

  • ISA结构分析

    了解对象 Objective-C是一门面向对象编程语言。对象是什么,我们这篇文章讲的isa和对象又有什么样的关系呢...

网友评论

      本文标题:关于isa的结构分析

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