Im reading some deep implementations of ARC, by read the assemble code generated by xcode, we can see the compiler inserts code like, objc_release, objc_storeStrong, things like that.
if we have a code like:
-(void)foo
{
NSDate * _date = [[NSDate alloc] init];
}
the assemble code is like:
movq %rdi, -32(%rbp) ## 8-byte Spill
movq %rsi, %rdi
movq -32(%rbp), %rsi ## 8-byte Reload
callq _objc_msgSend (this is call of 'alloc')
movq L_OBJC_SELECTOR_REFERENCES_2(%rip), %rsi
movq %rax, %rdi
callq _objc_msgSend (this is call of 'init')
movq %rax, -24(%rbp)
.loc 1 30 0
and at the end of { }, compiler inserts _objc_storeStrong
movq %rdx, %rdi
callq _objc_storeStrong (in this _objc_storeStrong, _date is released)
addq $64, %rsp
popq %rbp
retq
compile does _objc_storeStrong(_date,nil); cos no one strong holds the Date variable.
That makes sense
then I write like this : date becomes a strong member variable
@interface MyView : UIView
@property(nonatomic,strong) NSDate * date;
@end
-(void)foo
{
self.date = [[NSDate alloc] init];
}
the assemble code is :
movq %rax, -48(%rbp) ## 8-byte Spill
callq _objc_msgSend (call alloc)
movq L_OBJC_SELECTOR_REFERENCES_2(%rip), %rsi
movq %rax, %rdi
callq _objc_msgSend (call init)
movq L_OBJC_SELECTOR_REFERENCES_4(%rip), %rsi
movq -48(%rbp), %rdi ## 8-byte Reload
movq %rax, %rdx
movq %rax, -56(%rbp) ## 8-byte Spill
callq _objc_msgSend (call setDate:)
movq -56(%rbp), %rax ## 8-byte Reload
movq %rax, %rdi
callq _objc_release ( a magic release,~!!!)
basically, setDate will retain the date, and the last line release it for a balance.(not its not, see below test)
Then I change the code to
@interface MyView : UIView
@property(nonatomic,strong) NSDate * date;
@end
-(void)foo
{
_date = [[NSDate alloc] init];
}
assemble code becomes
callq _objc_msgSend (call alloc)
movq L_OBJC_SELECTOR_REFERENCES_2(%rip), %rsi
movq %rax, %rdi
callq _objc_msgSend (call init)
movq -8(%rbp), %rsi
movq _OBJC_IVAR_$_MyView._date(%rip), %rdi (set date directly)
movq (%rsi,%rdi), %rcx
movq %rax, (%rsi,%rdi)
movq %rcx, %rdi
callq _objc_release ( a magic release? here? why, we didn't retain it? )
Compiler inserts an _objc_release either, why? we didn't add any retain code here,
this really confused me for a day, by testing it, the _date is not released actually, you could use it then.
I added a symbolic break point on objc_release to trace the retain count, if we use self.date = [[NSDate alloc] init], objc_release breaks 2 times, by checking the retain count (CFGetRetainCount), retainCount is 2 and then 1, which is correct.
if using _date = [[NSDate alloc] init], objc_release breaks only once, the retainCount is 1.
will someone help me to understand this ?
one more question, the symbolic point, I use register read on lldb to read the first register content, and print the retain count, is it correct? generally r0 r1 r2 contains parameters for the method.