Objective-C Rumtime-消息机制

2021-03-04  本文已影响0人  lieon

objc_msgSend执行流程

 [person personTest];
// objc_msgSend(person, @selector(personTest));

objc_msgSend执行流程-源码跟读

    END_ENTRY _objc_msgSend
    ENTRY _objc_msgLookup
    UNWIND _objc_msgLookup, NoFrame

    cmp x0, #0          // nil check and tagged pointer check
    b.le    LLookup_NilOrTagged //  (MSB tagged pointer looks negative)
    ldr x13, [x0]       // x13 = isa
    and x16, x13, #ISA_MASK // x16 = class  

LLookup_GetIsaDone:
    CacheLookup LOOKUP      // returns imp
      .macro CacheLookup
      .macro CheckMiss
      STATIC_ENTRY __objc_msgSend_uncached
      .macro MethodTableLookup
      __class_lookupMethodAndLoadCache3
STATIC_ENTRY __objc_msgForward_impcache
ENTRY __objc_msgForward

IMP lookUpImpOrForward(Class cls, SEL sel, id inst, 
                       bool initialize, bool cache, bool resolver)
{
    IMP imp = nil;
    bool triedResolver = NO;
    runtimeLock.assertUnlocked();
    if (cache) {
        imp = cache_getImp(cls, sel);
        if (imp) return imp;
    }
    runtimeLock.read();

    if (!cls->isRealized()) {
        runtimeLock.unlockRead();
        runtimeLock.write();
        realizeClass(cls);
        runtimeLock.unlockWrite();
        runtimeLock.read();
    }
    if (initialize  &&  !cls->isInitialized()) {
        runtimeLock.unlockRead();
        _class_initialize (_class_getNonMetaClass(cls, inst));
        runtimeLock.read();
    }
 retry:    
    runtimeLock.assertReading();

    // Try this class's cache.
    // 方法缓存中取,获取到直接跳出
    imp = cache_getImp(cls, sel);
    if (imp) goto done;

    // Try this class's method lists.
    // 从当前类中获取方法
    {
        Method meth = getMethodNoSuper_nolock(cls, sel);
        if (meth) {
            // 将获取到的方法填入缓存
            log_and_fill_cache(cls, meth->imp, sel, inst, cls);
            imp = meth->imp;
            // 跳出,执行下一步
            goto done;
        }
    }

    // Try superclass caches and method lists.
    // 从父类中获取方法
    {
        unsigned attempts = unreasonableClassCount();
        for (Class curClass = cls->superclass;
             curClass != nil;
             curClass = curClass->superclass)
        {
            // Halt if there is a cycle in the superclass chain.
            if (--attempts == 0) {
                _objc_fatal("Memory corruption in class list.");
            }
            
            // Superclass cache.
            // 从父类缓存中获取
            imp = cache_getImp(curClass, sel);
            if (imp) {
                if (imp != (IMP)_objc_msgForward_impcache) {
                    // Found the method in a superclass. Cache it in this class.
                    log_and_fill_cache(cls, imp, sel, inst, curClass);
                    goto done;
                } else {
                    // Found a forward:: entry in a superclass.
                    // Stop searching, but don't cache yet; call method 
                    // resolver for this class first.
                    break;
                }
            }
            
            // Superclass method list.
            // 从父类的方法列表中获取
            Method meth = getMethodNoSuper_nolock(curClass, sel);
            if (meth) {
                // 将父类中获取到的方法进行缓存
                log_and_fill_cache(cls, meth->imp, sel, inst, curClass);
                imp = meth->imp;
                goto done;
            }
        }
    }
    // No implementation found. Try method resolver once.
    // 都没有找到方法,进行动态方法解析
    if (resolver  &&  !triedResolver) {
        runtimeLock.unlockRead();
        _class_resolveMethod(cls, sel, inst);
        runtimeLock.read();
        // Don't cache the result; we don't hold the lock so it may have 
        // changed already. Re-do the search from scratch instead.
        triedResolver = YES;
        // 再次尝试方法查找
        goto retry;
    }
    // No implementation found, and method resolver didn't help. 
    // Use forwarding.
    // 消息发送和动态方法解析都没找到实现,那么进行消息转发
    imp = (IMP)_objc_msgForward_impcache;
    // 有消息转发,则填充缓存
    cache_fill(cls, sel, imp, inst);

 done:
    runtimeLock.unlockRead();
    return imp;
}

// 方法查找的核心算法,采用的是二分查找,在查找前对方法列表进行了排序
static method_t *findMethodInSortedMethodList(SEL key, const method_list_t *list)
{
    assert(list);
    const method_t * const first = &list->first;
    const method_t *base = first;
    const method_t *probe;
    uintptr_t keyValue = (uintptr_t)key;
    uint32_t count;
    // 二分查找
    for (count = list->count; count != 0; count >>= 1) {
        probe = base + (count >> 1);
        uintptr_t probeValue = (uintptr_t)probe->name;
        if (keyValue == probeValue) {
            while (probe > first && keyValue == (uintptr_t)probe[-1].name) {
                probe--;
            }
            return (method_t *)probe;
        }
        if (keyValue > probeValue) {
            base = probe + 1;
            count--;
        }
    }
    return nil;
}
消息发送的流程

动态方法解析

void _class_resolveMethod(Class cls, SEL sel, id inst)
{
    if (!cls->isMetaClass()) {
        // try [cls resolveInstanceMethod:sel]
        _class_resolveInstanceMethod(cls, sel, inst);
    } else {
        // try [nonMetaClass resolveClassMethod:sel]
        // and [cls resolveInstanceMethod:sel]
        _class_resolveClassMethod(cls, sel, inst);
        if (!lookUpImpOrNil(cls, sel, inst,  NO/*initialize*/, YES/*cache*/, NO/*resolver*/)) {
            _class_resolveInstanceMethod(cls, sel, inst);
        }
    }
}

static void _class_resolveClassMethod(Class cls, SEL sel, id inst)
{
    assert(cls->isMetaClass());
    // 查找 ``SEL_resolveClassMethod``的实现,即+ (BOOL)resolveInstanceMethod:(SEL)sel
    if (!lookUpImpOrNil(cls, SEL_resolveClassMethod, inst, NO/*initialize*/, YES/*cache*/, NO/*resolver*/)) {
        // Resolver not implemented.
        return;
    }
    BOOL (*msg)(Class, SEL, SEL) = (typeof(msg))objc_msgSend;
    bool resolved = msg(_class_getNonMetaClass(cls, inst), SEL_resolveClassMethod, sel);

    // Cache the result (good or bad) so the resolver doesn't fire next time.
    // +resolveClassMethod adds to self->ISA() a.k.a. cls
    IMP imp = lookUpImpOrNil(cls, sel, inst, NO/*initialize*/, YES/*cache*/, NO/*resolver*/);

    if (resolved && PrintResolving) {
        if (imp) {
            _objc_inform("RESOLVE: method %c[%s %s] "
                         "dynamically resolved to %p", 
                         cls->isMetaClass() ? '+' : '-', 
                         cls->nameForLogging(), sel_getName(sel), imp);
        } else {
            // Method resolver didn't add anything?
            _objc_inform("RESOLVE: +[%s resolveClassMethod:%s] returned YES"
                         ", but no new implementation of %c[%s %s] was found",
                         cls->nameForLogging(), sel_getName(sel), 
                         cls->isMetaClass() ? '+' : '-', 
                         cls->nameForLogging(), sel_getName(sel));
        }
    }
}

static void _class_resolveInstanceMethod(Class cls, SEL sel, id inst)
{
    // 查找 ``SEL_resolveClassMethod``的实现,即- (BOOL)resolveInstanceMethod:(SEL)sel
    if (!lookUpImpOrNil(cls->ISA(), SEL_resolveInstanceMethod, cls,  NO/*initialize*/, YES/*cache*/, NO/*resolver*/)) {
        // Resolver not implemented.
        return;
    }

    BOOL (*msg)(Class, SEL, SEL) = (typeof(msg))objc_msgSend;
    bool resolved = msg(cls, SEL_resolveInstanceMethod, sel);

    // Cache the result (good or bad) so the resolver doesn't fire next time.
    // +resolveInstanceMethod adds to self a.k.a. cls
    IMP imp = lookUpImpOrNil(cls, sel, inst,  NO/*initialize*/, YES/*cache*/, NO/*resolver*/);

    if (resolved  &&  PrintResolving) {
        if (imp) {
            _objc_inform("RESOLVE: method %c[%s %s] "
                         "dynamically resolved to %p", 
                         cls->isMetaClass() ? '+' : '-', 
                         cls->nameForLogging(), sel_getName(sel), imp);
        } else {
            // Method resolver didn't add anything?
            _objc_inform("RESOLVE: +[%s resolveInstanceMethod:%s] returned YES"
                         ", but no new implementation of %c[%s %s] was found",
                         cls->nameForLogging(), sel_getName(sel), 
                         cls->isMetaClass() ? '+' : '-', 
                         cls->nameForLogging(), sel_getName(sel));
        }
    }
}
动态方法解析流程

动态方法的添加

- (void)other
{
    NSLog(@"%s", __func__);
}

+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    if (sel == @selector(test)) {
        // 获取其他方法
        Method method = class_getInstanceMethod(self, @selector(other));
        // 动态添加test方法的实现
        class_addMethod(self, sel,method_getImplementation(method), method_getTypeEncoding(method));
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    if (sel == @selector(test)) {
        // 获取其他方法
        struct method_t *method = (struct method_t *)class_getInstanceMethod(self, @selector(other));

        // 动态添加test方法的实现
        class_addMethod(self, sel, method->imp, method->types);

        // 返回YES代表有动态添加方法
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

消息转发

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    if (aSelector == @selector(test)) {
        // 转发给MJCat对象来执行test方法,相当于使用objc_msgSend对cat对象发送消息 objc_msgSend([[MJCat alloc] init], aSelector)
        return [[MJCat alloc] init];
    }
    return [super forwardingTargetForSelector:aSelector];
}
  // 方法签名:返回值类型、参数类型
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    if (aSelector == @selector(test)) {
        return [NSMethodSignature signatureWithObjCTypes:"v16@0:8"];
    }
    return [super methodSignatureForSelector:aSelector];
}

// NSInvocation封装了一个方法调用,包括:方法调用者、方法名、方法参数
//    anInvocation.target 方法调用者
//    anInvocation.selector 方法名
//    [anInvocation getArgument:NULL atIndex:0]
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
//    anInvocation.target = [[MJCat alloc] init];
//    [anInvocation invoke];

    [anInvocation invokeWithTarget:[[MJCat alloc] init]];
    
}
上一篇 下一篇

猜你喜欢

热点阅读