blog
recent
archive
twitter

projects
Mac OS X
Keyboard
  backlight
CSC Menu
Valgrind
Fringe Player
pssh
Peal
Frankenmouse

   

Hamster Emporium archive

<<   [objc explain]: Classes and metaclasses   |   archive   |   Infinity isn't as long as you think   >>

(link) [objc explain]: Non-fragile ivars   (2009-01-27 09:30 PM)
 

Non-fragile instance variables are a headline feature of the modern Objective-C runtime available on iPhone and 64-bit Mac. They provide framework developers more flexibility without losing binary compatibility, and pave the way for automatically-synthesized property ivars and ivars declared outside a class's interface.

The fragile base class problem

Fragile ivars are a subset of the classic fragile base class problem. In some languages, a superclass cannot be changed without also recompiling all subclasses of that class. For example, adding data members or virtual member functions to a C++ superclass will break binary compatibility with any subclass of that class, even if the added members are private and invisible to the subclass.

In classic Objective-C, methods are mostly non-fragile, thanks to dynamic message dispatch. You can freely add methods to a superclass, as long as you don't have name conflicts. But Objective-C ivars are fragile on 32-bit Mac.

32-bit Mac: fragile Objective-C ivars

Say you're writing the world's next great pet shop application for Mac OS X Leopard. You might have this PetShopView subclass of NSView, with arrays for the puppies and kittens in the pet shop.

NSView (Leopard)
0 Class isa
4 NSRect bounds
20 NSView *superview
24 NSColor *bgColor
PetShopView
0 Class isa
4 NSRect bounds
20 NSView *superview
24 NSColor *bgColor
28 NSArray *kittens
32 NSArray *puppies

Then Mac OS X Def Leopard comes out, with its new multi-paw interface technology. The AppKit developers add some paw-tracking code to NSView.

NSView (Def Leopard)
0 Class isa
4 NSRect bounds
20 NSView *superview
24 NSColor *bgColor
28 NSSet *touchedPaws
PetShopView
0 Class isa
4 NSRect bounds
20 NSView *superview
24 NSColor *bgColor
28 NSArray *kittens
32 NSArray *puppies

Unfortunately, your kittens are doomed by fragile ivars. Alternatively, the AppKit developers are trapped with whatever ivars they chose in Mac OS X 10.0.

iPhone and 64-bit Mac: non-fragile Objective-C ivars

What you and the AppKit developers really want is something like this.

NSView (Def Leopard)
0 Class isa
4 NSRect bounds
20 NSView *superview
24 NSColor *bgColor
28 NSSet *touchedPaws
PetShopView
0 Class isa
4 NSRect bounds
20 NSView *superview
24 NSColor *bgColor
28 NSSet *touchedPaws
32 NSArray *kittens
36 NSArray *puppies

Here, the runtime has recognized that NSView is now larger than it was when PetShopView was compiled. The subclass ivars slide in response, without recompiling any code, and the kittens are saved by a dynamic runtime.

How it works

The generated code for classic Objective-C ivar access works like a C struct field. The offset to the ivar is a constant determined at compile time. The new ivar code instead creates a variable for each ivar which contains the offset to that ivar, and all code that accesses the ivar uses that variable. At launch time, the runtime can change any ivar offset variable if it detects an oversize superclass.

In the pet shop example, _OBJC_IVAR_PetShopView_kittens is 28 at compile time, but the runtime changes it to 32 when it sees the Def Leopard version of NSView. No code needs to be recompiled, and the performance overhead of the extra ivar offset variable is small. AppKit is happy, you're happy, and the kittens are happy.


seal! Greg Parker
gparker-web@sealiesoftware.com
Sealie Software