美文网首页
NSObject底层实现

NSObject底层实现

作者: 昵称是乱起的 | 来源:发表于2019-01-21 01:30 被阅读26次
    NSObject的实现(OC2.0)
    @interface NSObject <NSObject> {
        Class isa  OBJC_ISA_AVAILABILITY;
    }
    typedef struct objc_class *Class;
    struct objc_class : objc_object {
        // Class ISA;
        Class superclass;
        cache_t cache;             // formerly cache pointer and vtable
        class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    
        class_rw_t *data() { 
            return bits.data();
        }
        void setData(class_rw_t *newData) {
            bits.setData(newData);
        }
    。。。省略几十个方法
    }
    struct objc_object {
        isa_t isa;
    };
    //总的来说objc_class结构体主要有以下变量
    struct objc_class : objc_object {
        Class isa ;
        Class superclass;
        cache_t cache;             // formerly cache pointer and vtable
        class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    }
    union isa_t 
    {
        Class cls;
        uintptr_t bits;
    # 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)
        };
    }
    
    对于实例对象、类对象、元类对象 isa和superclass的关系还得看这张图,具体的isa过几天再总结
    isa.png
    cache_t cache; 方法缓存,用散列表(哈希表)来缓存曾经调用过的方法,可以提高方法的查找速度
    struct cache_t {
        struct bucket_t *_buckets;//散列表数组
        mask_t _mask;//散列表的长度-1
        mask_t _occupied;//已缓存方法数量
    }
    struct bucket_t {
        cache_key_t _key;//用SEL作为key
        IMP _imp;//函数的内存地址
    }
    //缓存查找的关键代码
    bucket_t * cache_t::find(cache_key_t k, id receiver)
    {
        assert(k != 0);
        bucket_t *b = buckets();
        mask_t m = mask();
        //哈希运算 取得索引
        mask_t begin = cache_hash(k, m);
        mask_t i = begin;
        do {
            if (b[i].key() == 0  ||  b[i].key() == k) {
                return &b[i];
            }
        } while ((i = cache_next(i, m)) != begin);
        // hack
        Class cls = (Class)((uintptr_t)this - offsetof(objc_class, cache));
        cache_t::bad_cache(receiver, (SEL)k, cls);
    }
    static inline mask_t cache_hash(cache_key_t key, mask_t mask) 
    {
        return (mask_t)(key & mask);
    }
    // __arm64__下是这个方法
    static inline mask_t cache_next(mask_t i, mask_t mask) {
        return i ? i-1 : mask;
    }
    
    上面缓存查找的思路

    用k(就是SEL方法名)与mask做一次cache_hash,得到一个begin索引,然后根据索引去buckets数组中取出bucket_t里面的key跟外面的k做比较,如果一样就返回这个bucket_t,如果不一样cache_next,arm64下就是begin索引-1,然后从buckets里面取出继续做比较,直到begin==0,然后又从buckets数组的count重新找,最多遍历一遍数组,如果找不到就去方法列表查找去了

    class_data_bits_t bits里面存着一些类的信息,比如class_rw_t,class_ro_t
    class_rw_t* data() {
            return (class_rw_t *)(bits & FAST_DATA_MASK);
      }
    struct class_rw_t {
        const class_ro_t *ro;
        method_array_t methods;
        property_array_t properties;
        protocol_array_t protocols;
    }
    //class_ro_t里面的baseMethodList、baseProtocols、ivars、baseProperties是一维数组,是只读的,包含了类的初始内容
    struct class_ro_t {
        method_list_t * baseMethodList;
        protocol_list_t * baseProtocols;
        const ivar_list_t * ivars;
    };
    struct method_t {
        SEL name;//函数名
        const char *types;//函数返回值、参数编码的字符串
        IMP imp;//函数地址
    };
    

    class_rw_t 的methods、properties、protocols里面是二位数组,看methods里面就可以,methods里面是method_list_t数组,method_list_t里面是method_list的结构体


    image.png

    相关文章

      网友评论

          本文标题:NSObject底层实现

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