| 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 | |
| 8 | typedef id (*Send)(id, SEL); |
| 9 | #define SEND(receiver, selector) ((Send)objc_msgSend)((receiver), sel_registerName(selector)) |
| 10 | |
| 11 | extern void *_Block_copy(const void *); |
| 12 | |
| 13 | id objc_retain(id object) { return object ? SEND(object, "retain") : nil; } |
| 14 | void objc_release(id object) { if (object) SEND(object, "release"); } |
| 15 | id objc_autorelease(id object) { return object ? SEND(object, "autorelease") : nil; } |
| 16 | id objc_autoreleaseReturnValue(id object) { return objc_autorelease(object); } |
| 17 | id objc_retainAutorelease(id object) { return objc_autorelease(objc_retain(object)); } |
| 18 | id objc_retainAutoreleaseReturnValue(id object) { return objc_retainAutorelease(object); } |
| 19 | id objc_retainAutoreleasedReturnValue(id object) { return objc_retain(object); } |
| 20 | id objc_retainBlock(id block) { return (id)_Block_copy(block); } |
| 21 | |
| 22 | void objc_storeStrong(id *location, id value) { |
| 23 | id previous = *location; |
| 24 | *location = objc_retain(value); |
| 25 | objc_release(previous); |
| 26 | } |
| 27 | |
| 28 | id objc_alloc(Class cls) { return cls ? SEND((id)cls, "alloc") : nil; } |
| 29 | |
| 30 | id 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. |
| 35 | void *objc_autoreleasePoolPush(void) { |
| 36 | return SEND(SEND((id)objc_getClass("NSAutoreleasePool"), "alloc"), "init"); |
| 37 | } |
| 38 | |
| 39 | void 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. |
| 44 | id objc_initWeak(id *location, id value) { return *location = value; } |
| 45 | id objc_storeWeak(id *location, id value) { return *location = value; } |
| 46 | id objc_loadWeakRetained(id *location) { return objc_retain(*location); } |
| 47 | id objc_loadWeak(id *location) { return objc_autorelease(objc_loadWeakRetained(location)); } |
| 48 | void objc_destroyWeak(id *location) { *location = nil; } |
| 49 | void objc_copyWeak(id *to, id *from) { *to = *from; } |
| 50 | void objc_moveWeak(id *to, id *from) { *to = *from; *from = nil; } |