• 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

  • 相关阅读:
    电商企业怎样用好大数据
    网络编程入门
    TCP和UDP的常见面试题
    跨域请求
    微服务的统一异常处理
    Session和Cookie
    Restful风格
    正向代理和反向代理的总结
    解决虚拟机vmware安装64位系统“此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态”的问题
    MySQL数据的优化方案
  • 原文地址:https://www.cnblogs.com/muzichenyu/p/14238683.html
Copyright © 2020-2023  润新知