美文网首页
iOS - isa、class-rw-t、class-ro-t结

iOS - isa、class-rw-t、class-ro-t结

作者: 码代码的小马 | 来源:发表于2021-05-30 16:05 被阅读0次

源码objc-private.h

struct objc_object {
private:
    isa_t isa;

public:

    // ISA() assumes this is NOT a tagged pointer object
    Class ISA(bool authenticated = false);
    ···

}

isa_t

union isa_t {
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }
    uintptr_t bits;

private:
    // Accessing the class requires custom ptrauth operations, so
    // force clients to go through setClass/getClass by making this
    // private.
    Class cls;

public:
#if defined(ISA_BITFIELD)
    struct {
        ISA_BITFIELD;  // defined in isa.h
    };
};

ISA_BITFIELD

# if __arm64__
// ARM64 simulators have a larger address space, so use the ARM64e
// scheme even when simulators build for ARM64-not-e.
#   if __has_feature(ptrauth_calls) || TARGET_OS_SIMULATOR
#     define ISA_MASK        0x007ffffffffffff8ULL
#     define ISA_MAGIC_MASK  0x0000000000000001ULL
#     define ISA_MAGIC_VALUE 0x0000000000000001ULL
#     define ISA_HAS_CXX_DTOR_BIT 0
#     define ISA_BITFIELD                                                      \
        uintptr_t nonpointer        : 1;                                       \
        uintptr_t has_assoc         : 1;                                       \
        uintptr_t weakly_referenced : 1;                                       \
        uintptr_t shiftcls_and_sig  : 52;                                      \
        uintptr_t has_sidetable_rc  : 1;                                       \
        uintptr_t extra_rc          : 8
#     define RC_ONE   (1ULL<<56)
#     define RC_HALF  (1ULL<<7)

上面联合体 isa_t 涉及到一个位域的概念,可以参考《C语言位域(位段)详解》

因为部分数据在存储时候并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可。正是基于这种考虑,C语言又提供了一种叫做位域的数据结构。

isa_t 使用了位域,这里 ISA_BITFIELD 位域成员通过跟 bits 相与来取对应的值。 在 ISA_BITFIELD 中定义的参数的含义:

class_rw_t

objc-runtim-new.h

struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint16_t witness;
#if SUPPORT_INDEXED_ISA
    uint16_t index;
#endif
    // explicit_atomic 是为了安全操作
    explicit_atomic<uintptr_t> ro_or_rw_ext;

    Class firstSubclass;
    Class nextSiblingClass;
}

class_rw_ext_t 是class_rw_t的拓展

objc-runtime-new.h

struct class_rw_ext_t {
    DECLARE_AUTHED_PTR_TEMPLATE(class_ro_t)
    class_ro_t_authed_ptr<const class_ro_t> ro;
    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;
    char *demangledName;
    uint32_t version;
};

class-rw-t里的 methods、properties、protocols是二位数组

class method_array_t : 
public list_array_tt<method_t, method_list_t, method_list_t_authed_ptr>

class property_array_t : 
    public list_array_tt<property_t, property_list_t, RawPtr>

class protocol_array_t : 
    public list_array_tt<protocol_ref_t, protocol_list_t, RawPtr>

class-ro-t

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    union {
        const uint8_t * ivarLayout;
        Class nonMetaclass;
    };

    explicit_atomic<const char *> name;
    // With ptrauth, this is signed if it points to a small list, but
    // may be unsigned if it points to a big list.
    void *baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;

class_ro_t 里面的 baseMethodList、baseProtocols、ivars、baseProperties 是一维数组,是只读的,包含了类的初始内容,我们拿 baseMethodList 举例子:


method_t

using MethodListIMP = IMP;
struct method_t {
    static const uint32_t smallMethodListFlag = 0x80000000;

    method_t(const method_t &other) = delete;

    // The representation of a "big" method. This is the traditional
    // representation of three pointers storing the selector, types
    // and implementation.
    struct big {
        SEL name;  //方法、函数名
        const char *types;  //编码(参数类型、返回值类型)
        MethodListIMP imp;  //方法实现,指向方法、函数的指针
    };

方法缓存
Class 内部结构中有个方法缓存(cache_t),调用了方法之后会缓存在里面,他用散列表(哈希表)来缓存曾经调用过的方法,可以提高方法的查找速度。下面是整理出来的重要部分代码:


这里的散列表的原理就是,通过 @selector(methodName) & _mask 获得一个索引值,通过这个索引就能很快在 buckets 中拿到对应的 bucket_t(key, _imp);当然存放也是一样的方式。

存放:如果生成的索引在 buckets 下已经存在 data 。那么他会把 index - 1,减到零了还没有空闲位置,它会从数组最大值开始继续往前找位置,直到有位置;
获取:在拿到 bucket_t 后,会比较一下 key 与 @selector(methodName) 是否对应,如果不对应,那就回按照存放的那样方式一个一个找。如果存满了,buckets 就会走扩容。

这就是空间换时间。

相关文章

  • iOS - isa、class-rw-t、class-ro-t结

    源码objc-private.h中 isa_t ISA_BITFIELD 上面联合体 isa_t 涉及到一个位域的...

  • iOS Objective-C isa简介

    iOS Objective-C isa 1.isa简介 isa是 Objective—C 对象alloc的时候,伴...

  • 4-1 内存管理

    1.内存布局 2.iOS内存管理方案 [isa指针保存了内存管理的信息] 2.iOS内存管理方案 [isa指针...

  • iOS Objective-C isa 走位分析

    iOS Objective-C isa 走位分析 1. 判断isa是对象的第一个属性 isa<-->cls的关联 ...

  • isa指针的作用

    原文:iOS面试题大全 对象的isa指向类,类的isa指向元类(meta class),元类isa指向元类的根类。...

  • isa结构解析

    1. isa初始化 在 iOS alloc原理分析 中会 initInstanceIsa中初始化isa,源码如下:...

  • iOS底层探索004-类分析

    iOS底层探索-目录 1. 类的分析 主要分析两个部分:isa的走向和继承关系 isa分析 类的isa走向,参考这...

  • iOS底层-isa结构(isa_t)

    在iOS 底层-- isa指向探究中探索了isa的指向,那么isa的结构具体是什么样的。从源码中来着手研究。 一、...

  • iOS - ISA

    id是指向一个类的实例对象的指针。 类的底层定义 对象的底层定义,类继承自objc_object,所以类也是对象,...

  • iOS isa

    当一个对象的实例方法被调用的时候,会通过isa找到对应的类,然后在该类的class_data_bits_t中查找方...

网友评论

      本文标题:iOS - isa、class-rw-t、class-ro-t结

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