objc_msgSend() Tour Part 1: The Road Map

What follows (across this and 3 more posts, maybe more) is a rather detailed tour of objc_msgSend() as implemented in Mac OS X 10.6.2. Rather detailed in that every instruction will be explained. Even though it is relatively few instructions, there is a considerable amount of background information that is helpful to understanding the objc_msgSend() instruction stream.

The motivation behind these posts is entirely selfish. I find the best way for me to learn something is to know it well enough to be able to explain any detail to a room full of folks in full-blown student mode.

Table of Contents

  1. objc_msgSend() Tour Part 1: The Road Map
  2. objc_msgSend() Tour Part 2: Setting the Stage
  3. objc_msgSend() Tour Part 3: The Fast Path
  4. objc_msgSend() Tour Part 4: Method Lookup & Some Odds and Ends

For a variety of reasons, I oft find myself staring at streams of x86_64 instructions. This is often the stream of instructions that sit at the very core of Objective-C and dispatch each and every method call. That is, objc_msgSend().

Well, technically, a handful of different versions of objc_msgSend(), each written to handle the calling conventions required to deal with various return types under the x86_64 ABI (Application Binary Interface). Oh, and the vtable dispatch stuff (different post).

Obviously, objc_msgSend() is called 10s of millions of times simply booting the system and launching some apps. Thus, every cycle counts and, no surprise, objc_msgSend() is written in hand tuned assembly. Of all of the other performance optimizations and implementation details in this code, there are three that I find particularly notable.

Don’t Mess With Registers (unless absolutely necessary)
Tail Call Optimized
Don’t Mess with the Argument List

These are really all three part of the same thing (i.e. some arguments are in registers, for example). objc_msgSend() is designed to dynamically determine the implementation of a method — the function pointer that is the IMP tied to the selector on the targeted instance — without changing any of the caller/callee state. This enables a tail-call optimization that allows objc_msgSend() to jump [JMP] directly to the implementation of a method.

This is also the reason why you don’t see objc_msgSend() in backtraces save for when a crash occurs in objc_msgSend(). Given that there were several 10s of millions of invocations of objc_msgSend() prior to the one that crashed, you can pretty much always assume that the crash is because of a bad pointer being passed to objc_msgSend() and not due to a bug in objc_msgSend() itself. Of course, if you find yourself crashing in objc_msgSend(), go read and then re-read this.

This relative handful of instructions — 76 in the disassembly below (taken on Snow Leopard 10.6.2 — objc-437.1), most of which are not executed in a typical method dispatch — does an awful lot of stuff upon each invocation.

Namely:

  1. Check for ignored selectors (GC) and short-circuit.
  2. Check for nil target.
  3.     If nil & nil receiver handler configured, jump to handler
  4.     If nil & no handler (default), cleanup and return.
  5. Find the IMP on the class of the target and jump to it
  1. Search the class’s method cache for the method IMP
  2.     If found, jump to it.
  3. Not found: lookup the method IMP in the class itself
  4.  
        If found, jump to it.
  5. If not found, jump to forwarding mechanism.

The next part will set the stage for diving into the actual objc_msgSend() stream.



17 Responses to “objc_msgSend() Tour Part 1: The Road Map”

  1. Tweets that mention bbum’s weblog-o-mat » Blog Archive » objc_msgSend() Tour Part 1: The Road Map -- Topsy.com says:

    [...] This post was mentioned on Twitter by Bill Bumgarner, August Joki. August Joki said: RT @bbum: @patr1ck Lots more to go. Amazing how much happens for so few instructions! (objc_msgSend tour: http://tinyurl.com/ycpl7xg) [...]

  2. Michael Tsai - Blog - objc_msgSend() Tour says:

    [...] Bumgarner has written three good posts describing how objc_msgSend() [...]

  3. uberVU - social comments says:

    Social comments and analytics for this post…

    This post was mentioned on Twitter by bbum: @patr1ck Lots more to go. Amazing how much happens for so few instructions! (objc_msgSend tour: http://tinyurl.com/ycpl7xg)…

  4. August says:

    Does the tail call explain why gdb sometimes loses track of the backtrace and has ??? as the second stack frame?

  5. Karsten says:

    August: i think the ???s are due to stripped symbols.

  6. objc_msgSend() Tour http://www… | Wish Studios says:

    [...] objc_msgSend() Tour http://www.friday.com/bbum/2009/12/18/objc_msgsend-part-1-the-road-map/ [...]

  7. Twitter Updates for 2009-12-28 | Wish Studios says:

    [...] Tour http://www.friday.com/bbum/2009/12/18/objc_msgsend-part-1-the-road-map/ [...]

  8. bbum’s weblog-o-mat » Blog Archive » objc_msgSend() Tour Part 3: The Fast Path says:

    [...] objc_msgSend() Tour Part 1: The Road Map [...]

  9. bbum's weblog-o-mat » Blog Archive » objc_msgSend() Tour Part 4: Method Lookup & Some Odds and Ends says:

    [...] objc_msgSend() Tour Part 1: The Road Map [...]

  10. bbum's weblog-o-mat » Blog Archive » objc_msgSend() Tour Part 2: Setting the Stage says:

    [...] Commons Attribution-NonCommercial-ShareAlike 2.5 License. Amazon.com Widgets « objc_msgSend() Tour Part 1: The Road Map objc_msgSend() Tour Part 3: The Fast Path [...]

  11. Le Blog de ZOC » bbum’s weblog-o-mat » Blog Archive » objc_msgSend() Tour says:

    [...] C’est par là (en Anglais évidemment) : bbum’s weblog-o-mat » Blog Archive » objc_msgSend() Tour Part 1: The Road Map. [...]

  12. Jens Alfke says:

    Great stuff! You might want to fix the numbered list at the end, though — looks like there are two levels of hierarchy, but the nested list isn’t indented.

  13. Duncan Davidson escribe sobre el rendimiento de la máquina virtual de Android como ventaja competitiva contra el iPhone | Daring Fireball en español says:

    [...] lo que según Pullara está perjudicando el rendimiento del iPhone, no hay nada mejor que el reportaje en cuatro partes sobre cómo funciona objc_msgSend().) Buscar [...]

  14. Forbidden APIs, part 1 | robsadamsapple says:

    [...] started my journey right at the horse’s mouth, Bill Bumgarner’s blog.  Under the hood, all objective-c method calls are translated to plain old C calls.  For [...]

  15. Quora says:

    What things do people dislike the most about Objective-C?…

    I’ve been using Objective-C very heavily since 2002. Here’s my take: – Currently, the language is going through a lot of changes. Dot syntax and the addition of closures are two of the big ones. Some of the newer features have very “wrinkly” edge c…

  16. Mike Dong's Blog says:

    [...] as an objc_msgSend method call. For more detailed info about what actually happens here, see this series of posts by Bill Bumgarner, an Apple engineer who oversees the development of the Obj-C [...]

  17. Video Tutorial: Objective-C Runtime | Ray Wenderlich says:

    […] More on Objc_msgSend […]

Leave a Reply

Line and paragraph breaks automatic.
XHTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>