以前一直都以为 ARC 只是做了在编译期帮助开发者寻找合适的位置插入诸如 release
autorelease
这样的事情,不过看了一些资料以后,发现 ARC 似乎并不仅仅在编译期有优化,甚至在运行时期也有一些优化,优化的目的之一就是巧妙地跳过调用 autorelease
方法。这里做一下总结。
正如前面几篇文章提到的那样,MRC 时代,如果一个方法创建了对象,然后 return
这个对象,那就需要手动调用对象的 autorelease
方法,以实现 非自己生成的对象自己也能持有
这样的需求。以前一直都以为编译器无非是在编译期帮我们找到了合适的位置插入 autorelease
,但是现在看来,并不是这么简单,ARC 似乎更聪明一些。
ARC 中有一个非常巧妙地运行时的优化方案用来跳过某些情况下 autorelease
机制的调用,如下是大致的流程:
当方法全部基于 ARC 实现时,在方法 return 的时候,ARC 会调用 objc_autoreleaseReturnValue()
替代 MRC 下的 autorelease
。在 MRC 下想要 retain 的时候,ARC 会调用 objc_retainAutoreleasedReturnValue()
。
在调用 objc_autoreleaseReturnValue()
时,会在栈上查询 return address 以确定 return value 是否会被传给 objc_retainAutoreleasedReturnValue
。如果没传,说明返回值不能直接从提供方发送给接受方,这时就会调用 autorelease
。反之,如果返回值能顺利地从提供方传送给接收方,那么就会跳过 autorelease
并修改 return address 以跳过 retain 的过程。