After a conversation on Twitter with @jacobrelkin I decided to write a little post about how ARC works under the hood and how you can go about seeing what it’s doing. In this post I’ll explain about how ARC adds in retain, release and autorelease calls accordingly.
This outlines a few important aspects of ARC including direct access to ivars versus using a setter and how ARC will add autorelease calls when returning an object from a method based on the name of the method.
Let’s first look at the direct access to ivars versus using a setter. If we compile that code and look at the assembly then we’ll get an insight into what’s going on. I decided to use ARMv7 because it’s easier to understand what’s going on than x86 (in my opinion anyway!). We can turn ARC on and off with the -fobjc-arc and -fno-objc-arc compiler options. In these examples I’ve used optimisation level 3 which will mean the compiler will also remove redundant code which we’re not really interested in and would clog up the understanding (an exercise for the reader is to try without any optimisations and see what it looks like).
So to compile without ARC I used the following command:
We can instantly see the difference here. The changeFooSetter: is exactly the same whereas changeFooDirect: has changed with a single call to objc_storeStrong. That’s the interesting bit. If we looks at the LLVM documentation for this then we see that it’s doing a standard swap of the variable by releasing the old value and retain the new value. Whereas in the non-ARC version the ivar is just swapped without any retain or release. That’s just what we’d expect! Thanks ARC!
Now for the more interesting bit, the newNumber versus getNumber. Those methods in non-ARC land are both returning NSNumber objects which have a retain count of 1, i.e. the caller owns them. That sounds right for newNumber but not for getNumber according to Cocoa’s naming conventions. We’d expect to see an autorelease call when returning from getNumber. So let’s see what the code looks like without ARC:
And look at the single difference - a blx (this is a method call) to objc_autorelease in getNumber:. That’s just what we’d expect from ARC because it’s noticed that the method name doesn’t start with new or copy and it knows that at the point of return the NSNumber has a retain count of 1 so it adds in an autorelease call. Excellent!
This has just shown a little insight into how ARC works in two circumstances and I hope it inspires the reader to go away and look for themselves into how ARC works rather than just taking it for granted. It’s important as a programmer to understand how your tools work.