Objective-C Interop Extensions

Luna luna at foxgirls.gay
Sat Nov 16 22:29:36 UTC 2024


## Proposal

Currently DLang has, in some compilers, support for ObjectiveC 
types being declared. However, modern Objective-C code is 
strongly dependent on autorelease and auto release pools.
Without them Objective-C code leaks memory (see: 
https://developer.apple.com/documentation/quartzcore/cametallayer?language=objc).

To alleviate this, clang implements the concept of an 
`@autoreleasepool` block, this block frees all Objective-C 
classes which have called `autorelease`. In the case of Metal, 
for example, a lot of internal data uses autorelease calls.

The `@autoreleasepool` blocks in clang are implemented via 2 
helper functions declared in the objective-c runtime 
`libobjc.dylib` or the like in alternate runtime implementations.
```d
extern(C) extern void* objc_autoreleasePoolPush();
extern(C) extern void  objc_autoreleasePoolPop(void*);
```

My proposal is to add 2 new hooks to the D runtime emitted by the 
compiler as well as a new keyword, `autoreleasepool`. This 
keyword should be followed by a block.

The runtime hooks should have a default implementation which do 
nothing.
```d
void* _d_pool_enter() { return null; }
void  _d_pool_leave(void*) { }
```

Whenever an `autoreleasepool` block is encountered by the 
compiler, the following code should be emitted.
```d
// Note: __ctx_ptr is just a placeholder, the name of the 
variable should be unique.
void* __ctx_ptr = _d_pool_enter();

// Code goes here

_d_pool_leave(__ctx_ptr);
```

autorelease pools should additionally, on macOS, automatically be 
generated in the runtime entry point and wrap the user D main 
function, and threads created in D should also include pool enter 
and leave calls.

If the D compiler links to a library defining 
`objc_autoreleasePoolPush` and `objc_autoreleasePoolPop`, the D 
runtime hooks should link against those, instead.

## Why not use NSAutoreleasePool?

The `Foundation` library includes a class called 
NSAutoreleasePool, however i've found that if Objective-C's 
runtime is compiled with ARC (Automatic Reference Counting) 
support, then NSAutoreleasePool becomes no-op in some instances, 
which in turn causes memory leaks.


More information about the dip.ideas mailing list