Darwin: Use direct runtime interface to manage autorelease pools

The Objective-C runtime supports autorelease pools via a language
specific ABI supplement, akin to the “Itanium” generic ABI for C++.

 https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support

These interfaces are used by NSAutoreleasePool internally, as well as
inserted by the compiler when using the @autoreleasepool syntax in
Objective-C code.

We have our own wrapper, QMacAutoReleasePool, which allows us to
set up pools in C++ code as well. We now use these lower level
interfaces in the implementation, instead of NSAutoreleasePool,
as this reduces overhead due to not needing to allocate and destroy
a NSAutoreleasePool.

This also opens up the possibility of using Automatic Reference Counting
(ARC) in Qt down the road, as explicit NSAutoreleasePool usage is forbidden
in that mode (while @autoreleasepool is not, and uses the runtime ABI
internally as before).

Change-Id: I06fdb4a24ae4972820f866e0a129a1b355bc8a6b
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Tor Arne Vestbø 2023-05-08 11:32:47 +02:00
parent 7cf7e88417
commit 08f85c27bb

View File

@ -224,10 +224,20 @@ QT_USE_NAMESPACE
QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAutoReleasePoolTracker);
#endif // QT_DEBUG
// Use the direct runtime interface to manage autorelease pools, as it
// has less overhead then allocating NSAutoreleasePools, and allows for
// a future where we use ARC (where NSAutoreleasePool is not allowed).
// https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support
extern "C" {
void *objc_autoreleasePoolPush(void);
void objc_autoreleasePoolPop(void *pool);
}
QT_BEGIN_NAMESPACE
QMacAutoReleasePool::QMacAutoReleasePool()
: pool([[NSAutoreleasePool alloc] init])
: pool(objc_autoreleasePoolPush())
{
#ifdef QT_DEBUG
static const bool debugAutoReleasePools = qEnvironmentVariableIsSet("QT_DARWIN_DEBUG_AUTORELEASEPOOLS");
@ -272,10 +282,7 @@ QMacAutoReleasePool::QMacAutoReleasePool()
QMacAutoReleasePool::~QMacAutoReleasePool()
{
// Drain behaves the same as release, with the advantage that
// if we're ever used in a garbage-collected environment, the
// drain acts as a hint to the garbage collector to collect.
[static_cast<NSAutoreleasePool*>(pool) drain];
objc_autoreleasePoolPop(pool);
}
#ifndef QT_NO_DEBUG_STREAM