返回

缓存——方法缓存(下)

IOS

iOS底层08——缓存——方法缓存(下)

objc_msgsend在objc-runtime.h中被声明为:

id objc_msgsend(id self, SEL op, ...) __attribute__((__nothrow__));

它的实现可以在objc-runtime-new.mm中找到:

id objc_msgsend(id self, SEL op, ...) {
    va_list args;
    va_start(args, op);
    id result = _objc_msgSend_v(self, op, args);
    va_end(args);
    return result;
}

从中可以看出,objc_msgsend实际上是调用了_objc_msgSend_v,它接收一个id类型的self参数,一个SEL类型的op参数,以及一个不定长的参数列表。

_objc_msgSend_v的实现可以在objc-runtime-new.mm中找到:

id _objc_msgSend_v(id self, SEL op, va_list args) {
    struct objc_super super = { self, self->class_pointer };
    return _objc_msgSend_super(&super, op, args);
}

从代码中可以看出,_objc_msgSend_v实际上是调用了_objc_msgSend_super,它接收一个struct objc_super类型的super参数,一个SEL类型的op参数,以及一个不定长的参数列表。

_objc_msgSend_super的实现可以在objc-runtime-new.mm中找到:

id _objc_msgSend_super(struct objc_super *super, SEL op, va_list args) {
    struct objc_cache *cache;
    struct objc_method *imp;

    cache = _objc_msgSend_uncached(super, op, &imp);
    if (cache) {
        return (*cache->imp)(super->receiver, super->class, imp, args);
    }

    return _objc_msgSend_uncached(super, op, &imp);
}

从代码中可以看出,_objc_msgSend_super首先调用_objc_msgSend_uncached来获取方法缓存和方法实现,如果方法缓存存在,则直接调用方法缓存中的方法实现来执行方法调用,否则调用_objc_msgSend_uncached来执行方法调用。

_objc_msgSend_uncached的实现可以在objc-runtime-new.mm中找到:

struct objc_cache * _objc_msgSend_uncached(struct objc_super *super, SEL op, struct objc_method **out_imp) {
    struct objc_cache *cache;
    struct objc_method *imp = _objc_lookupMethod(super->class, op);
    if (imp) {
        cache = _objc_cache_get(imp);
        if (out_imp) {
            *out_imp = imp;
        }
        return cache;
    }

    return NULL;
}

从代码中可以看出,_objc_msgSend_uncached首先调用_objc_lookupMethod来查找方法实现,如果方法实现存在,则调用_objc_cache_get来获取方法缓存,如果方法缓存存在,则返回方法缓存,否则返回NULL。

通过分析汇编层的代码,我们可以看到objc_msgsend是如何调用Cache相关函数来实现方法缓存的。这些函数通过查找方法实现、获取方法缓存、调用方法缓存中的方法实现等步骤来实现方法调用的优化,提高了程序的执行效率。