STATIC_ENTRY __objc_msgSend_uncached
UNWIND __objc_msgSend_uncached, FrameWithNoSaves
// THIS IS NOT A CALLABLE C FUNCTION// Out-of-band p16 is the class to search
MethodTableLookup
TailCallFunctionPointer x17
END_ENTRY __objc_msgSend_uncached
static method_t *getMethodNoSuper_nolock(Class cls, SEL sel){
runtimeLock.assertLocked();ASSERT(cls->isRealized());// fixme nil cls? // fixme nil sel?autoconst methods = cls->data()->methods();for(auto mlists = methods.beginLists(),
end = methods.endLists();
mlists != end;++mlists){
// <rdar://problem/46904873> getMethodNoSuper_nolock is the hottest// caller of search_method_list, inlining it turns// getMethodNoSuper_nolock into a frame-less function and eliminates// any store from this codepath.
method_t *m =search_method_list_inline(*mlists, sel);if(m)return m;}return nil;}
staticvoidresolveInstanceMethod(id inst, SEL sel, Class cls){
runtimeLock.assertUnlocked();ASSERT(cls->isRealized());
SEL resolve_sel =@selector(resolveInstanceMethod:);// 判断系统是否实现SEL_resolveInstanceMethod方法// 即+(BOOL)resolveInstanceMethod:(SEL)sel// 继承自NSObject的类,默认实现,返回NOif(!lookUpImpOrNil(cls, resolve_sel, cls->ISA())){
// Resolver not implemented.// 不是NSObject的子类,也未实现+(BOOL)resolveInstanceMethod:(SEL)sel,// 直接返回,没有动态解析的必要return;}// 系统补偿一次机会 - 针对 sel 来操作
BOOL (*msg)(Class, SEL, SEL)=(typeof(msg))objc_msgSend;
bool resolved =msg(cls, resolve_sel, 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 imp =lookUpImpOrNil(inst, sel, cls);// 只有这用了resolved, 所以返回NO或YES不影响forwardif(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));}}}
resolveClassMethod 实现如下:
staticvoidresolveClassMethod(id inst, SEL sel, Class cls){
runtimeLock.assertUnlocked();ASSERT(cls->isRealized());ASSERT(cls->isMetaClass());if(!lookUpImpOrNil(inst,@selector(resolveClassMethod:), cls)){
// Resolver not implemented.return;}
Class nonmeta;{
mutex_locker_t lock(runtimeLock);
nonmeta =getMaybeUnrealizedNonMetaClass(cls, inst);// +initialize path should have realized nonmeta alreadyif(!nonmeta->isRealized()){
_objc_fatal("nonmeta class %s (%p) unexpectedly not realized",
nonmeta->nameForLogging(), nonmeta);}}
BOOL (*msg)(Class, SEL, SEL)=(typeof(msg))objc_msgSend;
bool resolved =msg(nonmeta,@selector(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(inst, sel, cls);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));}}}