LibCore+LibWeb: Add ScopedAutoreleasePool and use it on macOS

On macOS, Objective-C methods frequently return autoreleased objects
that accumulate until an autorelease pool is drained. Our event loop
(Core::EventLoop) and rendering thread both lacked autorelease pools,
causing unbounded accumulation of autoreleased objects.

The rendering thread was the worst offender: every Skia flush triggers
Metal resource allocation which sets labels on GPU textures via
-[IOGPUMetalResource setLabel:], creating autoreleased CFData objects.
With ~1M+ such objects at 112 bytes each, this leaked ~121MB. Metal
command buffer objects (_MTLCommandBufferEncoderInfo, etc.) also
accumulated, adding another ~128MB.

Add Core::ScopedAutoreleasePool, a RAII wrapper around the ObjC runtime
autorelease pool (no-op on non-macOS), and drain it:
- Every event loop pump (like NSRunLoop does)
- Every compositor loop iteration on the rendering thread
This commit is contained in:
Andreas Kling 2026-03-14 21:02:18 -05:00 committed by Jelle Raaijmakers
parent e4a8fc4b7b
commit a25fc5ad8a
Notes: github-actions[bot] 2026-03-15 10:43:41 +00:00
5 changed files with 72 additions and 0 deletions

View file

@ -14,6 +14,7 @@
#include <LibCore/EventLoopImplementationUnix.h>
#include <LibCore/EventReceiver.h>
#include <LibCore/Notifier.h>
#include <LibCore/Platform/ScopedAutoreleasePool.h>
#include <LibCore/System.h>
#include <LibCore/ThreadEventQueue.h>
#include <LibThreading/Mutex.h>
@ -308,6 +309,7 @@ int EventLoopImplementationUnix::exec()
size_t EventLoopImplementationUnix::pump(PumpMode mode)
{
ScopedAutoreleasePool autorelease_pool;
static_cast<EventLoopManagerUnix&>(EventLoopManager::the()).wait_for_events(mode);
return ThreadEventQueue::current().process();
}