News: Stay up to date

The Étoilé community is an active group of developers, designers, testers and users. New work is being done every day. Visit often to find out what we've been up to.


Automatic Reference Counting

Posted on 3 July 2011 by David Chisnall

At FOSDEM this year, both Chris Lattner, the head of Apple's compiler group, and I were invited speakers, so we were put in the same hotel. I had a chance to chat with him about the future of Objective-C over breakfast one morning. I explained that I thought that the way Apple had implemented garbage collection was a disaster, and outlined how I thought it should have been done. Chris' reply was 'wait until the summer'.

I waited until the summer, and on my birthday this year I got a present from Apple: open sourcing their implementation of automatic reference counting (ARC) for Clang and LLVM. Note that I say Clang and LLVM. Clang inserts some quite naïve reference counting calls into the IR, but then an LLVM optimisation pass improves them. This is especially interesting, because it means that LanguageKit will be able to benefit from the same optimisations when it switches to using ARC.

ARC doesn't just provide you with automatic -retain and -release calls. It also tidies up the Objective-C memory model, making a clearer distinction between the C and Smalltalk parts of the language. Objective-C that doesn't do any low-level C things now behaves almost like Smalltalk, but there is a clear distinction between what the compiler and runtime track and what you track. If you want to store object pointers anywhere other than on the stack and in instance variables, then you are responsible for memory management. This is now formalised in the language.

There is another nice tweak to the language in ARC mode. You no longer need to write a -dealloc method if all of your instance variables are primitive or object types. ARC creates a -.cxx_destruct method. This has been around for a while to call C++ object destructors in Objective-C++ objects. It now calls Objective-C destructors too.

ARC should also offer a speed benefit. I've implemented it in the GNUstep runtime, via two mechanisms. If your class implements or inherits memory management methods and does not explicitly opt in to ARC, then it will be sent -retain, -release and -autorelease messages as usual. If, on the other hand, it opts in, then the ARC functions will skip the message sends and manipulate the reference counts directly. This is a lot faster.

There is also a special case, as with Apple's implementation in Lion / iOS 5, where objects that are autoreleased, returned, and then retained, never actually have their reference counts modified. They are first stored in thread-local storage, with an cleanup function that will send them a -release message when the thread is destroyed. If they are retained, then they are removed from thread-local storage and returned. If something else is autoreleased as a return value, then the original value is replaced and is autoreleased at that point.

ARC is supported in LLVM/Clang svn and by the upcoming libobjc2 release. It requires a little bit of tweaking for existing code, but for new code it's trivial to use. Oh, and unlike OS X 10.6, we do support __weak references with GNUstep.