When I began to learn Objective C, I often heard of people talking about “sending message”, I was curious, come on, it’s just calling a method.
Then I recalled that I had that same feelings when functions become to methods as I began to touch C++.
To support polymorphism, C++ object model has a vtable inside every object which stores instance methods addresses, by which, C++ has a little dynamic characteristic.
But those dynamic are settled after compiling to machine code, unlike ruby or python, which has a virtual machine to dynamically interpreter the behaviors of a program, you might know, the duck typing.
Like C++, Objective C is also compiled to machine code, it supports polymiorphism, but also, to another level, it supports duck typing, you can send messages to any objects even the
What does it do to make it possible?
A Simple Program
Let’s do some tests by first creating a simple program.
1 2 3 4 5
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Example is created, then a message is sent to its instance
Producing assembly by
clang -S Example.m ->
The result is a little complicated. Generally speaking, it does three things.
First, setup necessary information, then make a call to
_objc_msgSend and store the return value to a local variable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Then we could jump to objc runtime source code to see what happens down the rabbit hole.
objc_msgSend is called during every message sending, which might happen millions of times only by booting the Mac OS X system, obviously, it needs to be fine tuned, no surprise, it is written in assembly.
Although those are assembly, they’re fairly readable by the good naming conventions and explainable comments.
1 2 3 4 5 6 7 8 9 10 11 12
NilTest macro, to check whether the message sending target is nil, if nil, then returns nil, that’s why we could send messages to a nil object.
GetIsaFast to get the
Every objc object has a member named
isa, it’s the blueprint of an object, which has all objc runtime needs to inspect an object and see what its class is and then seeing if it responds to some messages.
CacheLookup, objc runtime searches for the selector responsible for the message in a class method cache, and invokes the selector to finish the work.
Since objc is a object oriented language, some objects may inheritant hundreds of methods, but only some are frequently called, it’s not efficient to look up all the selectors every time a message is needed to be sent.
If objc runtime failed to find the selector for a message, it jumps to handle the cache miss.
MethodTableLookup will take the responsibility to look up for the selector from the target
1 2 3 4 5 6 7 8 9
MethodTableLookup simply transfers the responsibility.
1 2 3 4 5 6
Again, responsibility is transferred to
lookUpMethod, pay attention to the parameters assignments.
1 2 3 4 5 6 7 8 9 10 11
Finally, lookup is done, and cache is refilled.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
If you want to step deeper, objc runtime source can be downloaded at this place.
At last, where do I find the objc runtime in the Mac OS X system?
Why am I so sure?
Since I lost my mind, wanted to remove the runtime to see what will happen.
First, Terminal stopped working, then Apps became irresponsible, no new App could be opened, and even can’t reboot the whole system …
Now I deeply know how important the objc runtime is in Mac OS X, and thank it, boot to recovery has a terminal to use, I was lucky.