1// The ARC runtime entry points objc2 calls, which libobjc gained in 10.7 (objc_alloc in
2// 10.9); on 10.6 they were compiled into each binary from libarclite. Linked from an
3// archive, so only binaries that use Objective-C pull in libobjc.
4#include <objc/message.h>
5#include <objc/runtime.h>
6#include <stddef.h>
7
8typedef id (*Send)(id, SEL);
9#define SEND(receiver, selector) ((Send)objc_msgSend)((receiver), sel_registerName(selector))
10
11extern void *_Block_copy(const void *);
12
13id objc_retain(id object) { return object ? SEND(object, "retain") : nil; }
14void objc_release(id object) { if (object) SEND(object, "release"); }
15id objc_autorelease(id object) { return object ? SEND(object, "autorelease") : nil; }
16id objc_autoreleaseReturnValue(id object) { return objc_autorelease(object); }
17id objc_retainAutorelease(id object) { return objc_autorelease(objc_retain(object)); }
18id objc_retainAutoreleaseReturnValue(id object) { return objc_retainAutorelease(object); }
19id objc_retainAutoreleasedReturnValue(id object) { return objc_retain(object); }
20id objc_retainBlock(id block) { return (id)_Block_copy(block); }
21
22void objc_storeStrong(id *location, id value) {
23 id previous = *location;
24 *location = objc_retain(value);
25 objc_release(previous);
26}
27
28id objc_alloc(Class cls) { return cls ? SEND((id)cls, "alloc") : nil; }
29
30id objc_allocWithZone(Class cls) {
31 return cls ? ((id (*)(id, SEL, void *))objc_msgSend)((id)cls, sel_registerName("allocWithZone:"), NULL) : nil;
32}
33
34// Draining a pool also drains every pool pushed after it, as objc_autoreleasePoolPop does.
35void *objc_autoreleasePoolPush(void) {
36 return SEND(SEND((id)objc_getClass("NSAutoreleasePool"), "alloc"), "init");
37}
38
39void objc_autoreleasePoolPop(void *pool) { SEND((id)pool, "drain"); }
40
41// 10.6 has no zeroing weak references for non-GC code. These hold the object unretained
42// and never zero: sound only while the referent outlives the reference, as winit's view
43// and its window do.
44id objc_initWeak(id *location, id value) { return *location = value; }
45id objc_storeWeak(id *location, id value) { return *location = value; }
46id objc_loadWeakRetained(id *location) { return objc_retain(*location); }
47id objc_loadWeak(id *location) { return objc_autorelease(objc_loadWeakRetained(location)); }
48void objc_destroyWeak(id *location) { *location = nil; }
49void objc_copyWeak(id *to, id *from) { *to = *from; }
50void objc_moveWeak(id *to, id *from) { *to = *from; *from = nil; }