此文实际成于 2015/08/12
- performSelector 是为了方便使用 objc_msgSend 的一个简单的封装
- performSelector 只处理了 0-2 个参数的情况,objc_msgSend 可以处理任意多个数参数的情况。
+ (id)performSelector:(SEL)sel {
if (!sel) [self doesNotRecognizeSelector:sel];
return ((id(*)(id, SEL))objc_msgSend)((id)self, sel);
}
+ (id)performSelector:(SEL)sel withObject:(id)obj {
if (!sel) [self doesNotRecognizeSelector:sel];
return ((id(*)(id, SEL, id))objc_msgSend)((id)self, sel, obj);
}
+ (id)performSelector:(SEL)sel withObject:(id)obj1 withObject:(id)obj2 {
if (!sel) [self doesNotRecognizeSelector:sel];
return ((id(*)(id, SEL, id, id))objc_msgSend)((id)self, sel, obj1, obj2);
}
- (id)performSelector:(SEL)sel {
if (!sel) [self doesNotRecognizeSelector:sel];
return ((id(*)(id, SEL))objc_msgSend)(self, sel);
}
- (id)performSelector:(SEL)sel withObject:(id)obj {
if (!sel) [self doesNotRecognizeSelector:sel];
return ((id(*)(id, SEL, id))objc_msgSend)(self, sel, obj);
}
- (id)performSelector:(SEL)sel withObject:(id)obj1 withObject:(id)obj2 {
if (!sel) [self doesNotRecognizeSelector:sel];
return ((id(*)(id, SEL, id, id))objc_msgSend)(self, sel, obj1, obj2);
}
objc_msgSend 的 X86_64 汇编实现
objc_msgSend 一系列方法是用汇编实现的。
其中 x86_64 实现如下
/********************************************************************
*
* id objc_msgSend(id self, SEL _cmd,...);
*
********************************************************************/
.data
.align 3
.globl _objc_debug_taggedpointer_classes
_objc_debug_taggedpointer_classes:
.fill 16, 8, 0
ENTRY _objc_msgSend
MESSENGER_START
NilTest NORMAL
GetIsaFast NORMAL // r11 = self->isa
CacheLookup NORMAL // calls IMP on success
NilTestSupport NORMAL
GetIsaSupport NORMAL
// cache miss: go search the method lists
LCacheMiss:
// isa still in r11
MethodTableLookup %a1, %a2 // r11 = IMP
cmp %r11, %r11 // set eq (nonstret) for forwarding
jmp *%r11 // goto *imp
END_ENTRY _objc_msgSend
ENTRY _objc_msgSend_fixup
int3
END_ENTRY _objc_msgSend_fixup
STATIC_ENTRY _objc_msgSend_fixedup
// Load _cmd from the message_ref
movq 8(%a2), %a2
jmp _objc_msgSend
END_ENTRY _objc_msgSend_fixedup