• OC之runtime(共用体)


    在arm64架构之前,isa就是一个普通的指针,存储着Class、Meta-Class对象的地址

    从arm64架构开始,对isa进行了优化,变成了一个共用体(union)结构,还使用位域来

    存储更多信息,在apple源码objc中找到isa的结构源码大抵如下:

    # 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

    经过注释整理后的代码如下:

    union isa_t
    {
        Class cls;
        uintptr_t bits;
        struct {
            // nonpointer
            // 1 代表普通的指针,存储着Class、Meta-Class对象的内存地址
            // 0 代表优化过,使用位域存储更多信息
            uintptr_t nonpointer        : 1;
            // has_assoc 是否有设置过关联对象、如果没有,释放时会更快
            uintptr_t has_assoc         : 1;
            // has_cxx_dtor 是否有C++的析构函数,如果没有释放会更快
            uintptr_t has_cxx_dtor      : 1;
            // shiftcls 存储着Class、Meta-Class对象的内存地址信息
            uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/
            // magic 用于在调试时分辨对象是否未完成初始化
            uintptr_t magic             : 6;
            // weakly_referenced 是否有被弱引用指向过,如果没有,释放时会更快
            uintptr_t weakly_referenced : 1;
            // deallocating 对象是否正在被释放
            uintptr_t deallocating      : 1;
            // has_sidetable_rc 引用计数器是否过大无法存储在isa中,如果是1,引用计数将被存储到SideTable的类的属性中
            uintptr_t has_sidetable_rc  : 1;
            // extra_rc 里面存储的值是引用计数器减1
            uintptr_t extra_rc          : 19
        }
    }

    从源码中可以找到isa地址的方式:

    #if SUPPORT_NONPOINTER_ISA
    
    inline Class
    objc_object::ISA()
    {
        ASSERT(!isTaggedPointer());
    #if SUPPORT_INDEXED_ISA
        if (isa.nonpointer) {
            uintptr_t slot = isa.indexcls;
            return classForIndex((unsigned)slot);
        }
        return (Class)isa.bits;
    #else
        // define ISA_MASK        0x0000000ffffffff8ULL
        return (Class)(isa.bits & ISA_MASK);
    #endif
    }

    从上面代码可以看出,arm64真机条件下isa.bits & 0x0000000ffffffff8ULL 就是类的地址,而且地址后三位永远为0

  • 相关阅读:
    javascript深入理解js闭包
    【STL源码学习】STL算法学习之一
    【STL源码学习】细品vector
    【C++深入浅出】智能指针之auto_ptr学习
    【字典树应用】联想用户最想输入的词汇
    【数据结构】非常有用的hash表
    【WIN32进阶之路】:内存映射文件
    【WIN32进阶之路】:线程同步技术纲要
    win32进阶必备:多线程同步之互斥锁
    【C++深入浅出】设计模式学习之单例模式
  • 原文地址:https://www.cnblogs.com/muzichenyu/p/14238683.html
Copyright © 2020-2023  润新知