Skip to content

Commit

Permalink
Document Id::retain_autoreleased
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Mar 1, 2022
1 parent 5d1b3f9 commit b5297b9
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 7 deletions.
2 changes: 2 additions & 0 deletions objc2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Added convenience methods `Id::new_null`, `Id::as_ptr` and
`Id::retain_null`.
* The `objc2-encode` dependency is now exposed as `objc2::encode`.
* `Id::retain_autoreleased` to make following Cocoas memory management rules
more efficient.


## 0.3.0-alpha.6 - 2022-01-03
Expand Down
37 changes: 30 additions & 7 deletions objc2/src/rc/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ impl<T: Message, O: Ownership> Id<T, O> {
/// some API, and you would like to ensure that the object stays around
/// so that you can work with it.
///
/// If said API is a normal Objective-C method, you probably want to use
/// [`Id::retain_autoreleased`] instead.
///
/// This is rarely used to construct owned [`Id`]s, see [`Id::new`] for
/// that.
///
Expand Down Expand Up @@ -272,29 +275,49 @@ impl<T: Message, O: Ownership> Id<T, O> {
NonNull::new(ptr).map(|ptr| unsafe { Id::retain(ptr) })
}

/// TODO
/// Retains a previously autoreleased object pointer.
///
/// This is useful when calling Objective-C methods that return
/// autoreleaed objects, see [Cocoa's Memory Management Policy][mmRules].
///
/// This has exactly the same semantics as [`Id::retain`], except it can
/// sometimes avoid putting the object into the autorelease pool, possibly
/// yielding increased speed and reducing memory pressure.
///
/// Note: This relies heavily on being inlined right after [`msg_send!`],
/// be careful not accidentally require instructions between these.
///
/// [mmRules]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
///
/// # Safety
///
/// Same as [`Id::retain`].
#[doc(alias = "objc_retainAutoreleasedReturnValue")]
// This relies heavily on being inlined right after `objc_msgSend`.
#[inline(always)]
pub unsafe fn retain_autoreleased(ptr: NonNull<T>) -> Id<T, O> {
// Add magic nop instruction to participate in the fast autorelease
// scheme.
//
// See `callerAcceptsOptimizedReturn` in `objc-object.h`:
// https://github.com/apple-oss-distributions/objc4/blob/objc4-838/runtime/objc-object.h#L1209-L1377
//
// We will unconditionally emit these instructions, even if they end
// up being unused (for example because we're unlucky with inlining,
// some other work is done between the objc_msgSend and this, or the
// runtime version is too old to support it).
//
// See `callerAcceptsOptimizedReturn` in `objc-object.h`:
// https://github.com/apple-oss-distributions/objc4/blob/objc4-838/runtime/objc-object.h#L1209-L1377
// and this StackOverflow answer for some background on why the design
// is like it is: https://stackoverflow.com/a/23765612.
//
// It may seem like there should be a better way to do this, but
// emitting raw assembly is exactly what Clang and Swift does:
// swiftc: https://github.com/apple/swift/blob/swift-5.5.3-RELEASE/lib/IRGen/GenObjC.cpp#L148-L173
// Clang: https://github.com/llvm/llvm-project/blob/889317d47b7f046cf0e68746da8f7f264582fb5b/clang/lib/CodeGen/CGObjC.cpp#L2339-L2373
//
// Resources:
// - https://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html
// - https://www.galloway.me.uk/2012/02/how-does-objc_retainautoreleasedreturnvalue-work/
// - https://github.com/gfx-rs/metal-rs/issues/222
// - https://news.ycombinator.com/item?id=29311736
// - https://stackoverflow.com/a/23765612
//
// SAFETY:
// Based on https://doc.rust-lang.org/stable/reference/inline-assembly.html#rules-for-inline-assembly
//
Expand Down

0 comments on commit b5297b9

Please sign in to comment.