DevPrep

Все темы › Objective-C

Как работает objc_msgSend и кэширование селекторов?

Senior PRO

Что делает objc_msgSend

objc_msgSend(id self, SEL _cmd, ...) — точка входа каждой отправки сообщения. Это не обычная C-функция, а ручной ассемблер для каждой архитектуры (arm64, x86_64), потому что она должна:

  1. проверить self на nil (и tagged pointer) — если nil, обнулить регистры результата и вернуться;
  2. достать класс из isa (с маской для non-pointer isa);
  3. найти IMP в кэше класса по селектору;
  4. сделать tail-call (jump) в найденную IMP, не трогая регистры с аргументами — поэтому IMP видит те же self, _cmd и параметры, как если бы её вызвали напрямую, а в стеке objc_msgSend не остаётся.

Без ассемблера пришлось бы копировать произвольное число аргументов, зная сигнатуру, а её objc_msgSend как раз не знает.

Варианты: objc_msgSendSuper (для [super ...] — ищет с суперкласса, но self тот же), objc_msgSend_stret (возврат большой структуры через скрытый указатель, на arm64 не нужен), objc_msgSend_fpret (x86 для long double).

Продолжение ответа с кодом и уточняющими вопросами интервьюера — в приложении DevPrep.

Полный ответ — в DevPrep

Потренируйтесь перед собеседованием

В DevPrep эти ответы превращаются в задачи на минуту: что напечатает код, найди баг, пробное собеседование. По задаче в день.

Скачать DevPrep в App Store