An Illustrated History of objc_msgSend
Greg Parker on the Mavericks version of objc_msgSend
:
- The method cache data structure is rearranged for higher speed and smaller data cache footprint but larger total dirty memory footprint. Previously, the cache header was allocated separately from the cache buckets, and each cache bucket was a pointer to a Method struct containing the SEL and IMP. This required a chain of four pointer dereferences: object->isa->cache->method->imp. Now the cache header is stored in the class itself, and each cache bucket stores a SEL and IMP directly. The pointer dereference chain is now only three: object->isa->cache->imp, resulting in fewer serialized memory accesses and fewer data cache lines touched. The disadvantage is slower cache updates (to preserve thread-safety) and more dirty memory overall (to store SELs and IMPs in both the method list and the method cache).
- The new method cache data structure also requires fewer registers, so there are now zero register spills.
- One-byte branch hint instruction prefixes are added to the nil check and the tagged pointer check. The CPU’s instruction decoder is most efficient if the instructions are not packed too closely together, and these extra two bytes expand the first few instructions to the optimal size for current CPUs. The branch hints themselves are ignored by the CPU because its branch predictors are smarter than compile-time hinting. The only thing they do is take up space.
He has similar analyses for each version of Mac OS X.