How does objc_msgSend work, and selector caching?
What objc_msgSend does
objc_msgSend(id self, SEL _cmd, ...) is the entry point of every message send. It is not an ordinary C function but hand-written assembly for each architecture (arm64, x86_64), because it must:
- check
selffornil(and tagged pointers) — ifnil, zero the result registers and return; - fetch the class from
isa(masking the non-pointer isa); - look up the IMP in the class cache by selector;
- tail-call (jump) into the found IMP without touching the argument registers — so the IMP sees the same
self,_cmdand parameters as if it had been called directly, andobjc_msgSendleaves no stack frame.
Without assembly it would have to copy an arbitrary number of arguments while knowing the signature — and the signature is exactly what objc_msgSend does not know.
Variants: objc_msgSendSuper (for [super ...] — searches from the superclass but self stays the same), objc_msgSend_stret (returning a large struct through a hidden pointer, unnecessary on arm64), objc_msgSend_fpret (x86 for long double).
The rest of this answer, with code and interview follow-ups, is in the DevPrep app.
Read the full answer in DevPrep