... objc_msgSend(id self, SEL _cmd, ...) {
fptr = ...lookup code...
return fptr(self, _cmd, args...)
}
There's no way to express that args... argument when calling the function pointer, and no way to express forwarding an arbitrary return value.However, Objective-C does not require objc_msgSend. With objc_msgSend, a method call site generates code that's essentially equivalent to (for a method that takes one object parameter and returns void):
((void (*)(id, SEL, id))objc_msgSend)(object, selector, parameter);
In other words, take objc_msgSend, cast it to a function pointer of the correct type, and call it.Instead of objc_msgSend, the runtime can provide a function which looks up the method implementation and returns it to the caller. The caller can then invoke that implementation itself. This is how the GNU runtime does it, since it needs to be more portable. Their lookup function is called objc_msg_lookup. The generated code would look like this:
void (*imp)(id, SEL, id) = (void (*)(id, SEL, id))objc_msgLookup(object, selector);
imp(object, selector, parameter);
However, each call now suffers the overhead of two function calls, so it's a bit slower. Apple prefers to put in the extra effort of writing assembly code to avoid this, since it's so critical to their platform.