]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-internal.h
objc4-709.tar.gz
[apple/objc4.git] / runtime / objc-internal.h
1 /*
2 * Copyright (c) 2009 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #ifndef _OBJC_INTERNAL_H
26 #define _OBJC_INTERNAL_H
27
28 /*
29 * WARNING DANGER HAZARD BEWARE EEK
30 *
31 * Everything in this file is for Apple Internal use only.
32 * These will change in arbitrary OS updates and in unpredictable ways.
33 * When your program breaks, you get to keep both pieces.
34 */
35
36 /*
37 * objc-internal.h: Private SPI for use by other system frameworks.
38 */
39
40 #include <objc/objc.h>
41 #include <objc/runtime.h>
42 #include <Availability.h>
43 #include <malloc/malloc.h>
44 #include <dispatch/dispatch.h>
45
46 __BEGIN_DECLS
47
48 // Termination reasons in the OS_REASON_OBJC namespace.
49 #define OBJC_EXIT_REASON_UNSPECIFIED 1
50 #define OBJC_EXIT_REASON_GC_NOT_SUPPORTED 2
51
52 // This is the allocation size required for each of the class and the metaclass
53 // with objc_initializeClassPair() and objc_readClassPair().
54 // The runtime's class structure will never grow beyond this.
55 #define OBJC_MAX_CLASS_SIZE (32*sizeof(void*))
56
57 // In-place construction of an Objective-C class.
58 // cls and metacls must each be OBJC_MAX_CLASS_SIZE bytes.
59 // Returns nil if a class with the same name already exists.
60 // Returns nil if the superclass is under construction.
61 // Call objc_registerClassPair() when you are done.
62 OBJC_EXPORT Class objc_initializeClassPair(Class superclass, const char *name, Class cls, Class metacls)
63 OBJC_AVAILABLE(10.6, 3.0, 9.0, 1.0);
64
65 // Class and metaclass construction from a compiler-generated memory image.
66 // cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes.
67 // Extra bytes not used the the metadata must be zero.
68 // info is the same objc_image_info that would be emitted by a static compiler.
69 // Returns nil if a class with the same name already exists.
70 // Returns nil if the superclass is nil and the class is not marked as a root.
71 // Returns nil if the superclass is under construction.
72 // Do not call objc_registerClassPair().
73 #if __OBJC2__
74 struct objc_image_info;
75 OBJC_EXPORT Class objc_readClassPair(Class cls,
76 const struct objc_image_info *info)
77 OBJC_AVAILABLE(10.10, 8.0, 9.0, 1.0);
78 #endif
79
80 // Batch object allocation using malloc_zone_batch_malloc().
81 OBJC_EXPORT unsigned class_createInstances(Class cls, size_t extraBytes,
82 id *results, unsigned num_requested)
83 OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0)
84 OBJC_ARC_UNAVAILABLE;
85
86 // Get the isa pointer written into objects just before being freed.
87 OBJC_EXPORT Class _objc_getFreedObjectClass(void)
88 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);
89
90 // env NSObjCMessageLoggingEnabled
91 OBJC_EXPORT void instrumentObjcMessageSends(BOOL flag)
92 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);
93
94 // Initializer called by libSystem
95 OBJC_EXPORT void _objc_init(void)
96 #if __OBJC2__
97 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0);
98 #else
99 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0);
100 #endif
101
102 // fork() safety called by libSystem
103 OBJC_EXPORT void _objc_atfork_prepare(void)
104 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0);
105 OBJC_EXPORT void _objc_atfork_parent(void)
106 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0);
107 OBJC_EXPORT void _objc_atfork_child(void)
108 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0);
109
110 // Return YES if GC is on and `object` is a GC allocation.
111 OBJC_EXPORT BOOL objc_isAuto(id object)
112 __OSX_DEPRECATED(10.4, 10.8, "it always returns NO")
113 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
114
115 // GC startup callback from Foundation
116 OBJC_EXPORT malloc_zone_t *objc_collect_init(int (*callback)(void))
117 __OSX_DEPRECATED(10.4, 10.8, "it does nothing")
118 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
119
120 // Plainly-implemented GC barriers. Rosetta used to use these.
121 OBJC_EXPORT id objc_assign_strongCast_generic(id value, id *dest)
122 UNAVAILABLE_ATTRIBUTE;
123 OBJC_EXPORT id objc_assign_global_generic(id value, id *dest)
124 UNAVAILABLE_ATTRIBUTE;
125 OBJC_EXPORT id objc_assign_threadlocal_generic(id value, id *dest)
126 UNAVAILABLE_ATTRIBUTE;
127 OBJC_EXPORT id objc_assign_ivar_generic(id value, id dest, ptrdiff_t offset)
128 UNAVAILABLE_ATTRIBUTE;
129
130 // GC preflight for an app executable.
131 // 1: some slice requires GC
132 // 0: no slice requires GC
133 // -1: I/O or file format error
134 OBJC_EXPORT int objc_appRequiresGC(int fd)
135 __OSX_AVAILABLE(10.11)
136 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
137
138 // Install missing-class callback. Used by the late unlamented ZeroLink.
139 OBJC_EXPORT void _objc_setClassLoader(BOOL (*newClassLoader)(const char *)) OBJC2_UNAVAILABLE;
140
141 // Install handler for allocation failures.
142 // Handler may abort, or throw, or provide an object to return.
143 OBJC_EXPORT void _objc_setBadAllocHandler(id (*newHandler)(Class isa))
144 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0);
145
146 // This can go away when AppKit stops calling it (rdar://7811851)
147 #if __OBJC2__
148 OBJC_EXPORT void objc_setMultithreaded (BOOL flag)
149 __OSX_DEPRECATED(10.0, 10.5, "multithreading is always available")
150 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
151 #endif
152
153 // Used by ExceptionHandling.framework
154 #if !__OBJC2__
155 OBJC_EXPORT void _objc_error(id rcv, const char *fmt, va_list args)
156 __attribute__((noreturn))
157 __OSX_DEPRECATED(10.0, 10.5, "use other logging facilities instead")
158 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
159
160 #endif
161
162
163 // Tagged pointer objects.
164
165 #if __LP64__
166 #define OBJC_HAVE_TAGGED_POINTERS 1
167 #endif
168
169 #if OBJC_HAVE_TAGGED_POINTERS
170
171 // Tagged pointer layout and usage is subject to change on different OS versions.
172
173 // Tag indexes 0..<7 have a 60-bit payload.
174 // Tag index 7 is reserved.
175 // Tag indexes 8..<264 have a 52-bit payload.
176 // Tag index 264 is reserved.
177
178 #if __has_feature(objc_fixed_enum) || __cplusplus >= 201103L
179 enum objc_tag_index_t : uint16_t
180 #else
181 typedef uint16_t objc_tag_index_t;
182 enum
183 #endif
184 {
185 OBJC_TAG_NSAtom = 0,
186 OBJC_TAG_1 = 1,
187 OBJC_TAG_NSString = 2,
188 OBJC_TAG_NSNumber = 3,
189 OBJC_TAG_NSIndexPath = 4,
190 OBJC_TAG_NSManagedObjectID = 5,
191 OBJC_TAG_NSDate = 6,
192 OBJC_TAG_RESERVED_7 = 7,
193
194 OBJC_TAG_First60BitPayload = 0,
195 OBJC_TAG_Last60BitPayload = 6,
196 OBJC_TAG_First52BitPayload = 8,
197 OBJC_TAG_Last52BitPayload = 263,
198
199 OBJC_TAG_RESERVED_264 = 264
200 };
201 #if __has_feature(objc_fixed_enum) && !defined(__cplusplus)
202 typedef enum objc_tag_index_t objc_tag_index_t;
203 #endif
204
205
206 // Returns true if tagged pointers are enabled.
207 // The other functions below must not be called if tagged pointers are disabled.
208 static inline bool
209 _objc_taggedPointersEnabled(void);
210
211 // Register a class for a tagged pointer tag.
212 // Aborts if the tag is invalid or already in use.
213 OBJC_EXPORT void _objc_registerTaggedPointerClass(objc_tag_index_t tag, Class cls)
214 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
215
216 // Returns the registered class for the given tag.
217 // Returns nil if the tag is valid but has no registered class.
218 // Aborts if the tag is invalid.
219 OBJC_EXPORT Class _objc_getClassForTag(objc_tag_index_t tag)
220 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
221
222 // Create a tagged pointer object with the given tag and payload.
223 // Assumes the tag is valid.
224 // Assumes tagged pointers are enabled.
225 // The payload will be silently truncated to fit.
226 static inline void *
227 _objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t payload);
228
229 // Return true if ptr is a tagged pointer object.
230 // Does not check the validity of ptr's class.
231 static inline bool
232 _objc_isTaggedPointer(const void *ptr);
233
234 // Extract the tag value from the given tagged pointer object.
235 // Assumes ptr is a valid tagged pointer object.
236 // Does not check the validity of ptr's tag.
237 static inline objc_tag_index_t
238 _objc_getTaggedPointerTag(const void *ptr);
239
240 // Extract the payload from the given tagged pointer object.
241 // Assumes ptr is a valid tagged pointer object.
242 // The payload value is zero-extended.
243 static inline uintptr_t
244 _objc_getTaggedPointerValue(const void *ptr);
245
246 // Extract the payload from the given tagged pointer object.
247 // Assumes ptr is a valid tagged pointer object.
248 // The payload value is sign-extended.
249 static inline intptr_t
250 _objc_getTaggedPointerSignedValue(const void *ptr);
251
252 // Don't use the values below. Use the declarations above.
253
254 #if TARGET_OS_OSX && __x86_64__
255 // 64-bit Mac - tag bit is LSB
256 # define OBJC_MSB_TAGGED_POINTERS 0
257 #else
258 // Everything else - tag bit is MSB
259 # define OBJC_MSB_TAGGED_POINTERS 1
260 #endif
261
262 #define _OBJC_TAG_INDEX_MASK 0x7
263 // array slot includes the tag bit itself
264 #define _OBJC_TAG_SLOT_COUNT 16
265 #define _OBJC_TAG_SLOT_MASK 0xf
266
267 #define _OBJC_TAG_EXT_INDEX_MASK 0xff
268 // array slot has no extra bits
269 #define _OBJC_TAG_EXT_SLOT_COUNT 256
270 #define _OBJC_TAG_EXT_SLOT_MASK 0xff
271
272 #if OBJC_MSB_TAGGED_POINTERS
273 # define _OBJC_TAG_MASK (1ULL<<63)
274 # define _OBJC_TAG_INDEX_SHIFT 60
275 # define _OBJC_TAG_SLOT_SHIFT 60
276 # define _OBJC_TAG_PAYLOAD_LSHIFT 4
277 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
278 # define _OBJC_TAG_EXT_MASK (0xfULL<<60)
279 # define _OBJC_TAG_EXT_INDEX_SHIFT 52
280 # define _OBJC_TAG_EXT_SLOT_SHIFT 52
281 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 12
282 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
283 #else
284 # define _OBJC_TAG_MASK 1
285 # define _OBJC_TAG_INDEX_SHIFT 1
286 # define _OBJC_TAG_SLOT_SHIFT 0
287 # define _OBJC_TAG_PAYLOAD_LSHIFT 0
288 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
289 # define _OBJC_TAG_EXT_MASK 0xfULL
290 # define _OBJC_TAG_EXT_INDEX_SHIFT 4
291 # define _OBJC_TAG_EXT_SLOT_SHIFT 4
292 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 0
293 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
294 #endif
295
296 static inline bool
297 _objc_taggedPointersEnabled(void)
298 {
299 extern uintptr_t objc_debug_taggedpointer_mask;
300 return (objc_debug_taggedpointer_mask != 0);
301 }
302
303 static inline void *
304 _objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t value)
305 {
306 // PAYLOAD_LSHIFT and PAYLOAD_RSHIFT are the payload extraction shifts.
307 // They are reversed here for payload insertion.
308
309 // assert(_objc_taggedPointersEnabled());
310 if (tag <= OBJC_TAG_Last60BitPayload) {
311 // assert(((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT) == value);
312 return (void*)
313 (_OBJC_TAG_MASK |
314 ((uintptr_t)tag << _OBJC_TAG_INDEX_SHIFT) |
315 ((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT));
316 } else {
317 // assert(tag >= OBJC_TAG_First52BitPayload);
318 // assert(tag <= OBJC_TAG_Last52BitPayload);
319 // assert(((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT) == value);
320 return (void*)
321 (_OBJC_TAG_EXT_MASK |
322 ((uintptr_t)(tag - OBJC_TAG_First52BitPayload) << _OBJC_TAG_EXT_INDEX_SHIFT) |
323 ((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT));
324 }
325 }
326
327 static inline bool
328 _objc_isTaggedPointer(const void *ptr)
329 {
330 return ((intptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
331 }
332
333 static inline objc_tag_index_t
334 _objc_getTaggedPointerTag(const void *ptr)
335 {
336 // assert(_objc_isTaggedPointer(ptr));
337 uintptr_t basicTag = ((uintptr_t)ptr >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
338 uintptr_t extTag = ((uintptr_t)ptr >> _OBJC_TAG_EXT_INDEX_SHIFT) & _OBJC_TAG_EXT_INDEX_MASK;
339 if (basicTag == _OBJC_TAG_INDEX_MASK) {
340 return (objc_tag_index_t)(extTag + OBJC_TAG_First52BitPayload);
341 } else {
342 return (objc_tag_index_t)basicTag;
343 }
344 }
345
346 static inline uintptr_t
347 _objc_getTaggedPointerValue(const void *ptr)
348 {
349 // assert(_objc_isTaggedPointer(ptr));
350 uintptr_t basicTag = ((uintptr_t)ptr >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
351 if (basicTag == _OBJC_TAG_INDEX_MASK) {
352 return ((uintptr_t)ptr << _OBJC_TAG_EXT_PAYLOAD_LSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
353 } else {
354 return ((uintptr_t)ptr << _OBJC_TAG_PAYLOAD_LSHIFT) >> _OBJC_TAG_PAYLOAD_RSHIFT;
355 }
356 }
357
358 static inline intptr_t
359 _objc_getTaggedPointerSignedValue(const void *ptr)
360 {
361 // assert(_objc_isTaggedPointer(ptr));
362 uintptr_t basicTag = ((uintptr_t)ptr >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
363 if (basicTag == _OBJC_TAG_INDEX_MASK) {
364 return ((intptr_t)ptr << _OBJC_TAG_EXT_PAYLOAD_LSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
365 } else {
366 return ((intptr_t)ptr << _OBJC_TAG_PAYLOAD_LSHIFT) >> _OBJC_TAG_PAYLOAD_RSHIFT;
367 }
368 }
369
370 // OBJC_HAVE_TAGGED_POINTERS
371 #endif
372
373
374 /**
375 * Returns the method implementation of an object.
376 *
377 * @param obj An Objective-C object.
378 * @param name An Objective-C selector.
379 *
380 * @return The IMP corresponding to the instance method implemented by
381 * the class of \e obj.
382 *
383 * @note Equivalent to:
384 *
385 * class_getMethodImplementation(object_getClass(obj), name);
386 */
387 OBJC_EXPORT IMP object_getMethodImplementation(id obj, SEL name)
388 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
389
390 OBJC_EXPORT IMP object_getMethodImplementation_stret(id obj, SEL name)
391 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0)
392 OBJC_ARM64_UNAVAILABLE;
393
394
395 // Instance-specific instance variable layout.
396
397 OBJC_EXPORT void _class_setIvarLayoutAccessor(Class cls_gen, const uint8_t* (*accessor) (id object))
398 __OSX_AVAILABLE(10.7)
399 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
400 OBJC_EXPORT const uint8_t *_object_getIvarLayout(Class cls_gen, id object)
401 __OSX_AVAILABLE(10.7)
402 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
403
404 /*
405 "Unknown" includes non-object ivars and non-ARC non-__weak ivars
406 "Strong" includes ARC __strong ivars
407 "Weak" includes ARC and new MRC __weak ivars
408 "Unretained" includes ARC __unsafe_unretained and old GC+MRC __weak ivars
409 */
410 typedef enum {
411 objc_ivar_memoryUnknown, // unknown / unknown
412 objc_ivar_memoryStrong, // direct access / objc_storeStrong
413 objc_ivar_memoryWeak, // objc_loadWeak[Retained] / objc_storeWeak
414 objc_ivar_memoryUnretained // direct access / direct access
415 } objc_ivar_memory_management_t;
416
417 OBJC_EXPORT objc_ivar_memory_management_t _class_getIvarMemoryManagement(Class cls, Ivar ivar)
418 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0);
419
420 OBJC_EXPORT BOOL _class_isFutureClass(Class cls)
421 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
422
423
424 // API to only be called by root classes like NSObject or NSProxy
425
426 OBJC_EXPORT
427 id
428 _objc_rootRetain(id obj)
429 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
430
431 OBJC_EXPORT
432 void
433 _objc_rootRelease(id obj)
434 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
435
436 OBJC_EXPORT
437 bool
438 _objc_rootReleaseWasZero(id obj)
439 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
440
441 OBJC_EXPORT
442 bool
443 _objc_rootTryRetain(id obj)
444 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
445
446 OBJC_EXPORT
447 bool
448 _objc_rootIsDeallocating(id obj)
449 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
450
451 OBJC_EXPORT
452 id
453 _objc_rootAutorelease(id obj)
454 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
455
456 OBJC_EXPORT
457 uintptr_t
458 _objc_rootRetainCount(id obj)
459 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
460
461 OBJC_EXPORT
462 id
463 _objc_rootInit(id obj)
464 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
465
466 OBJC_EXPORT
467 id
468 _objc_rootAllocWithZone(Class cls, malloc_zone_t *zone)
469 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
470
471 OBJC_EXPORT
472 id
473 _objc_rootAlloc(Class cls)
474 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
475
476 OBJC_EXPORT
477 void
478 _objc_rootDealloc(id obj)
479 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
480
481 OBJC_EXPORT
482 void
483 _objc_rootFinalize(id obj)
484 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
485
486 OBJC_EXPORT
487 malloc_zone_t *
488 _objc_rootZone(id obj)
489 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
490
491 OBJC_EXPORT
492 uintptr_t
493 _objc_rootHash(id obj)
494 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
495
496 OBJC_EXPORT
497 void *
498 objc_autoreleasePoolPush(void)
499 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
500
501 OBJC_EXPORT
502 void
503 objc_autoreleasePoolPop(void *context)
504 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
505
506
507 OBJC_EXPORT id objc_alloc(Class cls)
508 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
509
510 OBJC_EXPORT id objc_allocWithZone(Class cls)
511 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
512
513 OBJC_EXPORT id objc_retain(id obj)
514 __asm__("_objc_retain")
515 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
516
517 OBJC_EXPORT void objc_release(id obj)
518 __asm__("_objc_release")
519 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
520
521 OBJC_EXPORT id objc_autorelease(id obj)
522 __asm__("_objc_autorelease")
523 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
524
525 // Prepare a value at +1 for return through a +0 autoreleasing convention.
526 OBJC_EXPORT
527 id
528 objc_autoreleaseReturnValue(id obj)
529 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
530
531 // Prepare a value at +0 for return through a +0 autoreleasing convention.
532 OBJC_EXPORT
533 id
534 objc_retainAutoreleaseReturnValue(id obj)
535 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
536
537 // Accept a value returned through a +0 autoreleasing convention for use at +1.
538 OBJC_EXPORT
539 id
540 objc_retainAutoreleasedReturnValue(id obj)
541 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
542
543 // Accept a value returned through a +0 autoreleasing convention for use at +0.
544 OBJC_EXPORT
545 id
546 objc_unsafeClaimAutoreleasedReturnValue(id obj)
547 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0);
548
549 OBJC_EXPORT
550 void
551 objc_storeStrong(id *location, id obj)
552 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
553
554 OBJC_EXPORT
555 id
556 objc_retainAutorelease(id obj)
557 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
558
559 // obsolete.
560 OBJC_EXPORT id objc_retain_autorelease(id obj)
561 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
562
563 OBJC_EXPORT
564 id
565 objc_loadWeakRetained(id *location)
566 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
567
568 OBJC_EXPORT
569 id
570 objc_initWeak(id *location, id val)
571 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
572
573 // Like objc_storeWeak, but stores nil if the new object is deallocating
574 // or the new object's class does not support weak references.
575 // Returns the value stored (either the new object or nil).
576 OBJC_EXPORT
577 id
578 objc_storeWeakOrNil(id *location, id obj)
579 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0);
580
581 // Like objc_initWeak, but stores nil if the new object is deallocating
582 // or the new object's class does not support weak references.
583 // Returns the value stored (either the new object or nil).
584 OBJC_EXPORT
585 id
586 objc_initWeakOrNil(id *location, id val)
587 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0);
588
589 OBJC_EXPORT
590 void
591 objc_destroyWeak(id *location)
592 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
593
594 OBJC_EXPORT
595 void
596 objc_copyWeak(id *to, id *from)
597 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
598
599 OBJC_EXPORT
600 void
601 objc_moveWeak(id *to, id *from)
602 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
603
604
605 OBJC_EXPORT
606 void
607 _objc_autoreleasePoolPrint(void)
608 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
609
610 OBJC_EXPORT BOOL objc_should_deallocate(id object)
611 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
612
613 OBJC_EXPORT void objc_clear_deallocating(id object)
614 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
615
616
617 // to make CF link for now
618
619 OBJC_EXPORT
620 void *
621 _objc_autoreleasePoolPush(void)
622 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
623
624 OBJC_EXPORT
625 void
626 _objc_autoreleasePoolPop(void *context)
627 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
628
629
630 // Extra @encode data for XPC, or NULL
631 OBJC_EXPORT const char *_protocol_getMethodTypeEncoding(Protocol *p, SEL sel, BOOL isRequiredMethod, BOOL isInstanceMethod)
632 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0);
633
634
635 // API to only be called by classes that provide their own reference count storage
636
637 OBJC_EXPORT
638 void
639 _objc_deallocOnMainThreadHelper(void *context)
640 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
641
642 // On async versus sync deallocation and the _dealloc2main flag
643 //
644 // Theory:
645 //
646 // If order matters, then code must always: [self dealloc].
647 // If order doesn't matter, then always async should be safe.
648 //
649 // Practice:
650 //
651 // The _dealloc2main bit is set for GUI objects that may be retained by other
652 // threads. Once deallocation begins on the main thread, doing more async
653 // deallocation will at best cause extra UI latency and at worst cause
654 // use-after-free bugs in unretained delegate style patterns. Yes, this is
655 // extremely fragile. Yes, in the long run, developers should switch to weak
656 // references.
657 //
658 // Note is NOT safe to do any equality check against the result of
659 // dispatch_get_current_queue(). The main thread can and does drain more than
660 // one dispatch queue. That is why we call pthread_main_np().
661 //
662
663 typedef enum {
664 _OBJC_RESURRECT_OBJECT = -1, /* _logicBlock has called -retain, and scheduled a -release for later. */
665 _OBJC_DEALLOC_OBJECT_NOW = 1, /* call [self dealloc] immediately. */
666 _OBJC_DEALLOC_OBJECT_LATER = 2 /* call [self dealloc] on the main queue. */
667 } _objc_object_disposition_t;
668
669 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \
670 -(id)retain { \
671 /* this will fail to compile if _rc_ivar is an unsigned type */ \
672 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
673 __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \
674 if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \
675 __builtin_trap(); /* BUG: retain of over-released ref */ \
676 } \
677 return self; \
678 } \
679 -(oneway void)release { \
680 __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \
681 if (_prev > 0) { \
682 return; \
683 } else if (_prev < 0) { \
684 __builtin_trap(); /* BUG: over-release */ \
685 } \
686 _objc_object_disposition_t fate = _logicBlock(self); \
687 if (fate == _OBJC_RESURRECT_OBJECT) { \
688 return; \
689 } \
690 /* mark the object as deallocating. */ \
691 if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \
692 __builtin_trap(); /* BUG: dangling ref did a retain */ \
693 } \
694 if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \
695 [self dealloc]; \
696 } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \
697 dispatch_barrier_async_f(dispatch_get_main_queue(), self, \
698 _objc_deallocOnMainThreadHelper); \
699 } else { \
700 __builtin_trap(); /* BUG: bogus fate value */ \
701 } \
702 } \
703 -(NSUInteger)retainCount { \
704 return (_rc_ivar + 2) >> 1; \
705 } \
706 -(BOOL)_tryRetain { \
707 __typeof__(_rc_ivar) _prev; \
708 do { \
709 _prev = _rc_ivar; \
710 if (_prev & 1) { \
711 return 0; \
712 } else if (_prev == -2) { \
713 return 0; \
714 } else if (_prev < -2) { \
715 __builtin_trap(); /* BUG: over-release elsewhere */ \
716 } \
717 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
718 return 1; \
719 } \
720 -(BOOL)_isDeallocating { \
721 if (_rc_ivar == -2) { \
722 return 1; \
723 } else if (_rc_ivar < -2) { \
724 __builtin_trap(); /* BUG: over-release elsewhere */ \
725 } \
726 return _rc_ivar & 1; \
727 }
728
729 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
730 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
731 if (_dealloc2main && !pthread_main_np()) { \
732 return _OBJC_DEALLOC_OBJECT_LATER; \
733 } else { \
734 return _OBJC_DEALLOC_OBJECT_NOW; \
735 } \
736 }))
737
738 #define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0)
739 #define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1)
740
741 __END_DECLS
742
743 #endif