iOS Runtime - isa指针

Objective-C是一门动态性比较强的编程语言,跟C、C++等语言有着很大的不同。普通语言的过程大致分为:编写代码 -> 编译链接 -> 运行。

OC的动态性怎么做到的呢?

Objective-C的动态性是由Runtime API来支撑的,Runtime API提供的接口基本都是C语言的,源码由C\C++\汇编语言编写,今天就来看看Runtime的本质和实现原理

isa的本质

在学习Runtime之前首先需要对isa的本质有一定的了解,这样之后学习Runtime会更便于理解。
这篇文章中iOS OC对象的本质窥探(一)讲到过每个OC对象都含有一个isa指针,在 __arm64__之前,isa仅仅是一个指针,保存着对象或类对象内存地址,在__arm64__架构之后,apple对isa进行了优化,变成了一个共用体(union)结构,同时使用位域来存储更多的信息。

我们知道OC对象的isa指针并不是直接指向类对象或者元类对象的地址,而是需要&ISA_MASK通过位运算才能获取到类对象或者元类对象的地址。今天来探寻一下为什么需要&ISA_MASK才能获取到类对象或者元类对象的地址,以及这样的好处。

首先在源码中找到isa指针,看一下isa指针的本质。

// objc_object内部分代码
struct objc_object {
private:
    isa_t isa;
}

isa指针其实是一个isa_t类型的共用体,来到isa_t内部查看其结构

// 精简过的isa_t共用体
union isa_t 
{
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }

    Class cls;
    uintptr_t bits;

#if SUPPORT_PACKED_ISA
# if __arm64__      
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
    struct {
        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
    struct {
        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)
    };

# else
#   error unknown architecture for packed isa
# endif
#endif

上述源码中isa_t是union类型,union表示共用体。可以看到共用体中有一个结构体,结构体内部分别定义了一些变量,变量后面的值代表的是该变量占用多少个二进制位,也就是位域技术。

共用体:在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体。


 

猜你喜欢

转载自blog.csdn.net/yezuiqingxin/article/details/119572019