iOS的内存管理

在ARM64操作系统下,一个指针占用64bit,但其实存储一个对象的地址32就够了。而且访问堆内存的效率比访问栈要慢。所以基于性能和内存使用效率,苹果推出了新的内存管理的功能。

我们知道,对象的定义为:

struct objc_object {
private:
    isa_t isa;

public:

    // ISA() assumes this is NOT a tagged pointer object
    Class ISA();

    // getIsa() allows this to be a tagged pointer object
    Class getIsa();

其中,将isa指针定义为private私有变量。是为了不让外部直接访问。

为什么不让访问呢?因为isa已经不再是一个堆内存对象的地址,而是一个union结构。

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
};

union的意思就是,可能是Class cls,也可能是uintptr_t bits,也可能是

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
}

那到底是什么呢?我们来看下获取isa的方法的实现。

inline Class objc_object::getIsa() 
{
    if (!isTaggedPointer()) return ISA();

    uintptr_t ptr = (uintptr_t)this;
    if (isExtTaggedPointer()) {
        uintptr_t slot = 
            (ptr >> _OBJC_TAG_EXT_SLOT_SHIFT) & _OBJC_TAG_EXT_SLOT_MASK;
        return objc_tag_ext_classes[slot];
    } else {
        uintptr_t slot = 
            (ptr >> _OBJC_TAG_SLOT_SHIFT) & _OBJC_TAG_SLOT_MASK;
        return objc_tag_classes[slot];
    }
}

可以看出,不是TaggedPoint时,使用的是ISA。当是TaggedPoint并且为ExtTaggedPointer,则按位操作,返回3~37字节的真实的对象的地址。当就是TaggedPoint且不为ExtTaggedPointer时,返回objc_tag_classes数组中的位置。

你可能感兴趣的:(iOS的内存管理)