美文网首页
593,Runtime 的方法缓存?存储的形式、数据结构以及查找

593,Runtime 的方法缓存?存储的形式、数据结构以及查找

作者: 枫叶1234 | 来源:发表于2021-03-23 12:15 被阅读0次

    说一下 Runtime 的方法缓存?存储的形式、数据结构以及查找的过程?

    cache_t增量扩展的哈希表结构。哈希表内部存储的 bucket_t

    bucket_t 中存储的是 SELIMP的键值对。

    • 如果是有序方法列表,采用二分查找

    • 如果是无序方法列表,直接遍历查找

    cache_t结构体
    // 缓存曾经调用过的方法,提高查找速率
    struct cache_t {
        struct bucket_t *_buckets; // 散列表
        mask_t _mask; //散列表的长度 - 1
        mask_t _occupied; // 已经缓存的方法数量,散列表的长度使大于已经缓存的数量的。
        //...
    }
    
    struct bucket_t {
        cache_key_t _key; //SEL作为Key @selector()
        IMP _imp; // 函数的内存地址
        //...
    }
    

    散列表查找过程,在objc-cache.mm文件中

    // 查询散列表,k
    bucket_t * cache_t::find(cache_key_t k, id receiver)
    {
        assert(k != 0); // 断言
    
        bucket_t *b = buckets(); // 获取散列表
        mask_t m = mask(); // 散列表长度 - 1
        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);
        // i 的值最大等于mask,最小等于0。
    
        // hack
        Class cls = (Class)((uintptr_t)this - offsetof(objc_class, cache));
        cache_t::bad_cache(receiver, (SEL)k, cls);
    }
    

    上面是查询散列表函数,其中cache_hash(k, m)是静态内联方法,将传入的keymask进行&操作返回uint32_t索引值。do-while循环查找过程,当发生冲突cache_next方法将索引值减1。

    相关文章

      网友评论

          本文标题:593,Runtime 的方法缓存?存储的形式、数据结构以及查找

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