Original source code, compiled with ARC:
-(NSString*)name {
return self->name;
}
-(void)caller {
self->thingName = [self->thing name];
}
-(NSString*)name {
return objc_retainAutoreleaseReturnValue(self->name);
}
-(void)caller {
self->thingName = objc_retainAutoreleasedReturnValue([self->thing name]);
}
objc_retainAutoreleaseReturnValue(x)
simply calls objc_autoreleaseReturnValue(objc_retain(x))
.
objc_autoreleaseReturnValue
checks if the caller is optimized.
If it is, stores the object pointer in TLS, and skips the autorelease;
otherwise, calls autorelease.
objc_retainAutoreleasedReturnValue
checks if the object pointer is in TLS.
If it is, clears TLS and skips the retain;
otherwise, calls retain.
Same code:
-(NSString*)name {
return objc_retainAutoreleaseReturnValue(self->name);
}
-(void)caller {
self->thingName = objc_retainAutoreleasedReturnValue([self->thing name]);
}
objc_retainAutoreleaseReturnValue
checks if the caller is optimized.
If it is, stores 0 in TLS, and skips both the retain and autorelease;
Otherwise, calls retain and autorelease.
objc_retainAutoreleasedReturnValue
checks if the TLS value is a 1.
It's not, so it calls retain, since the callee didn't retain.
What's the advantage? Previously the callee did one retain, now the caller does one retain. User code size is the same since the fused retain + autoreleaseRV operation was used in Lion too, it just didn't do any special optimization.