mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Runtime] Eliminate stack frames in swift_retain and swift_bridgeObjectRetain on ARM64.
Rearrange the slow paths a bit to make them tail calls, which allows the compiler to emit these functions without frames. Clang is happy to emit frameless functions on ARM64 if no stack space is needed on all execution paths. However, when there's a fast path which doesn't need stack space, and a slow path which does, clang emits code that pushes a stack frame and then decides which path to take. This is fine, but it means we're paying more than we'd like to on the fast path. We can work around that by manually outlining the slow path, and ensuring that it's invoked with a tail call. Then the original function doesn't need a stack frame on any path and clang omits the stack frame. We tweak RefCounts::increment to return the object it's being called on, which allows `swift_retain` to tail-call it. We manually outline the objc_retain call in swift_bridgeObjectRetain, which allows the swift_retain path to be frameless. rdar://101764509
This commit is contained in:
@@ -342,8 +342,12 @@ _swift_release_dealloc(HeapObject *object);
|
||||
SWIFT_ALWAYS_INLINE
|
||||
static HeapObject *_swift_retain_(HeapObject *object) {
|
||||
SWIFT_RT_TRACK_INVOCATION(object, swift_retain);
|
||||
if (isValidPointerForNativeRetain(object))
|
||||
object->refCounts.increment(1);
|
||||
if (isValidPointerForNativeRetain(object)) {
|
||||
// Return the result of increment() to make the eventual call to
|
||||
// incrementSlow a tail call, which avoids pushing a stack frame on the fast
|
||||
// path on ARM64.
|
||||
return object->refCounts.increment(1);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user