2 * Copyright (c) 2009 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #ifndef _OBJC_INTERNAL_H
26 #define _OBJC_INTERNAL_H
29 * WARNING DANGER HAZARD BEWARE EEK
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.
37 * objc-internal.h: Private SPI for use by other system frameworks.
40 #include <objc/objc.h>
41 #include <objc/runtime.h>
42 #include <Availability.h>
43 #include <malloc/malloc.h>
44 #include <mach-o/loader.h>
45 #include <dispatch/dispatch.h>
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
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*))
60 // In-place construction of an Objective-C class.
61 // cls and metacls must each be OBJC_MAX_CLASS_SIZE bytes.
62 // Returns nil if a class with the same name already exists.
63 // Returns nil if the superclass is under construction.
64 // Call objc_registerClassPair() when you are done.
65 OBJC_EXPORT Class _Nullable
66 objc_initializeClassPair(Class _Nullable superclass
, const char * _Nonnull name
,
67 Class _Nonnull cls
, Class _Nonnull metacls
)
68 OBJC_AVAILABLE(10.6, 3.0, 9.0, 1.0, 2.0);
70 // Class and metaclass construction from a compiler-generated memory image.
71 // cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes.
72 // Extra bytes not used the the metadata must be zero.
73 // info is the same objc_image_info that would be emitted by a static compiler.
74 // Returns nil if a class with the same name already exists.
75 // Returns nil if the superclass is nil and the class is not marked as a root.
76 // Returns nil if the superclass is under construction.
77 // Do not call objc_registerClassPair().
79 struct objc_image_info
;
80 OBJC_EXPORT Class _Nullable
81 objc_readClassPair(Class _Nonnull cls
,
82 const struct objc_image_info
* _Nonnull info
)
83 OBJC_AVAILABLE(10.10, 8.0, 9.0, 1.0, 2.0);
86 // Batch object allocation using malloc_zone_batch_malloc().
88 class_createInstances(Class _Nullable cls
, size_t extraBytes
,
89 id _Nonnull
* _Nonnull results
, unsigned num_requested
)
90 OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0)
93 // Get the isa pointer written into objects just before being freed.
94 OBJC_EXPORT Class _Nonnull
95 _objc_getFreedObjectClass(void)
96 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
98 // env NSObjCMessageLoggingEnabled
100 instrumentObjcMessageSends(BOOL flag
)
101 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
103 // Initializer called by libSystem
107 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
109 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
112 // fork() safety called by libSystem
114 _objc_atfork_prepare(void)
115 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
118 _objc_atfork_parent(void)
119 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
122 _objc_atfork_child(void)
123 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
125 // Return YES if GC is on and `object` is a GC allocation.
127 objc_isAuto(id _Nullable object
)
128 __OSX_DEPRECATED(10.4, 10.8, "it always returns NO")
129 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
130 __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE
;
134 objc_dumpHeap(char * _Nonnull filename
, unsigned long length
)
135 __OSX_DEPRECATED(10.4, 10.8, "it always returns NO")
136 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
137 __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE
;
139 // GC startup callback from Foundation
140 OBJC_EXPORT malloc_zone_t
* _Nullable
141 objc_collect_init(int (* _Nonnull callback
)(void))
142 __OSX_DEPRECATED(10.4, 10.8, "it does nothing")
143 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
144 __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE
;
146 // Plainly-implemented GC barriers. Rosetta used to use these.
147 OBJC_EXPORT id _Nullable
148 objc_assign_strongCast_generic(id _Nullable value
, id _Nullable
* _Nonnull dest
)
149 UNAVAILABLE_ATTRIBUTE
;
151 OBJC_EXPORT id _Nullable
152 objc_assign_global_generic(id _Nullable value
, id _Nullable
* _Nonnull dest
)
153 UNAVAILABLE_ATTRIBUTE
;
155 OBJC_EXPORT id _Nullable
156 objc_assign_threadlocal_generic(id _Nullable value
,
157 id _Nullable
* _Nonnull dest
)
158 UNAVAILABLE_ATTRIBUTE
;
160 OBJC_EXPORT id _Nullable
161 objc_assign_ivar_generic(id _Nullable value
, id _Nonnull dest
, ptrdiff_t offset
)
162 UNAVAILABLE_ATTRIBUTE
;
164 // GC preflight for an app executable.
165 // 1: some slice requires GC
166 // 0: no slice requires GC
167 // -1: I/O or file format error
169 objc_appRequiresGC(int fd
)
170 __OSX_AVAILABLE(10.11)
171 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
172 __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE
;
174 // Install missing-class callback. Used by the late unlamented ZeroLink.
176 _objc_setClassLoader(BOOL (* _Nonnull newClassLoader
)(const char * _Nonnull
))
179 #if !(TARGET_OS_OSX && !TARGET_OS_IOSMAC && __i386__)
181 _objc_setClassCopyFixupHandler(void (* _Nonnull newFixupHandler
)
182 (Class _Nonnull oldClass
, Class _Nonnull newClass
));
183 // fixme work around bug in Swift
184 // OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0)
187 // Install handler for allocation failures.
188 // Handler may abort, or throw, or provide an object to return.
190 _objc_setBadAllocHandler(id
_Nullable (* _Nonnull newHandler
)
191 (Class _Nullable isa
))
192 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
194 // Used by ExceptionHandling.framework
197 _objc_error(id _Nullable rcv
, const char * _Nonnull fmt
, va_list args
)
198 __attribute__((noreturn
))
199 __OSX_DEPRECATED(10.0, 10.5, "use other logging facilities instead")
200 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
201 __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE
;
207 * Returns the names of all the classes within a library.
209 * @param image The mach header for library or framework you are inquiring about.
210 * @param outCount The number of class names returned.
212 * @return An array of C strings representing the class names.
214 OBJC_EXPORT
const char * _Nonnull
* _Nullable
215 objc_copyClassNamesForImageHeader(const struct mach_header
* _Nonnull mh
,
216 unsigned int * _Nullable outCount
)
217 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
219 // Tagged pointer objects.
222 #define OBJC_HAVE_TAGGED_POINTERS 1
225 #if OBJC_HAVE_TAGGED_POINTERS
227 // Tagged pointer layout and usage is subject to change on different OS versions.
229 // Tag indexes 0..<7 have a 60-bit payload.
230 // Tag index 7 is reserved.
231 // Tag indexes 8..<264 have a 52-bit payload.
232 // Tag index 264 is reserved.
234 #if __has_feature(objc_fixed_enum) || __cplusplus >= 201103L
235 enum objc_tag_index_t
: uint16_t
237 typedef uint16_t objc_tag_index_t
;
244 OBJC_TAG_NSString
= 2,
245 OBJC_TAG_NSNumber
= 3,
246 OBJC_TAG_NSIndexPath
= 4,
247 OBJC_TAG_NSManagedObjectID
= 5,
251 OBJC_TAG_RESERVED_7
= 7,
254 OBJC_TAG_Photos_1
= 8,
255 OBJC_TAG_Photos_2
= 9,
256 OBJC_TAG_Photos_3
= 10,
257 OBJC_TAG_Photos_4
= 11,
263 OBJC_TAG_First60BitPayload
= 0,
264 OBJC_TAG_Last60BitPayload
= 6,
265 OBJC_TAG_First52BitPayload
= 8,
266 OBJC_TAG_Last52BitPayload
= 263,
268 OBJC_TAG_RESERVED_264
= 264
270 #if __has_feature(objc_fixed_enum) && !defined(__cplusplus)
271 typedef enum objc_tag_index_t objc_tag_index_t
;
275 // Returns true if tagged pointers are enabled.
276 // The other functions below must not be called if tagged pointers are disabled.
278 _objc_taggedPointersEnabled(void);
280 // Register a class for a tagged pointer tag.
281 // Aborts if the tag is invalid or already in use.
283 _objc_registerTaggedPointerClass(objc_tag_index_t tag
, Class _Nonnull cls
)
284 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
286 // Returns the registered class for the given tag.
287 // Returns nil if the tag is valid but has no registered class.
288 // Aborts if the tag is invalid.
289 OBJC_EXPORT Class _Nullable
290 _objc_getClassForTag(objc_tag_index_t tag
)
291 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
293 // Create a tagged pointer object with the given tag and payload.
294 // Assumes the tag is valid.
295 // Assumes tagged pointers are enabled.
296 // The payload will be silently truncated to fit.
297 static inline void * _Nonnull
298 _objc_makeTaggedPointer(objc_tag_index_t tag
, uintptr_t payload
);
300 // Return true if ptr is a tagged pointer object.
301 // Does not check the validity of ptr's class.
303 _objc_isTaggedPointer(const void * _Nullable ptr
);
305 // Extract the tag value from the given tagged pointer object.
306 // Assumes ptr is a valid tagged pointer object.
307 // Does not check the validity of ptr's tag.
308 static inline objc_tag_index_t
309 _objc_getTaggedPointerTag(const void * _Nullable ptr
);
311 // Extract the payload from the given tagged pointer object.
312 // Assumes ptr is a valid tagged pointer object.
313 // The payload value is zero-extended.
314 static inline uintptr_t
315 _objc_getTaggedPointerValue(const void * _Nullable ptr
);
317 // Extract the payload from the given tagged pointer object.
318 // Assumes ptr is a valid tagged pointer object.
319 // The payload value is sign-extended.
320 static inline intptr_t
321 _objc_getTaggedPointerSignedValue(const void * _Nullable ptr
);
323 // Don't use the values below. Use the declarations above.
325 #if (TARGET_OS_OSX || TARGET_OS_IOSMAC) && __x86_64__
326 // 64-bit Mac - tag bit is LSB
327 # define OBJC_MSB_TAGGED_POINTERS 0
329 // Everything else - tag bit is MSB
330 # define OBJC_MSB_TAGGED_POINTERS 1
333 #define _OBJC_TAG_INDEX_MASK 0x7
334 // array slot includes the tag bit itself
335 #define _OBJC_TAG_SLOT_COUNT 16
336 #define _OBJC_TAG_SLOT_MASK 0xf
338 #define _OBJC_TAG_EXT_INDEX_MASK 0xff
339 // array slot has no extra bits
340 #define _OBJC_TAG_EXT_SLOT_COUNT 256
341 #define _OBJC_TAG_EXT_SLOT_MASK 0xff
343 #if OBJC_MSB_TAGGED_POINTERS
344 # define _OBJC_TAG_MASK (1UL<<63)
345 # define _OBJC_TAG_INDEX_SHIFT 60
346 # define _OBJC_TAG_SLOT_SHIFT 60
347 # define _OBJC_TAG_PAYLOAD_LSHIFT 4
348 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
349 # define _OBJC_TAG_EXT_MASK (0xfUL<<60)
350 # define _OBJC_TAG_EXT_INDEX_SHIFT 52
351 # define _OBJC_TAG_EXT_SLOT_SHIFT 52
352 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 12
353 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
355 # define _OBJC_TAG_MASK 1UL
356 # define _OBJC_TAG_INDEX_SHIFT 1
357 # define _OBJC_TAG_SLOT_SHIFT 0
358 # define _OBJC_TAG_PAYLOAD_LSHIFT 0
359 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
360 # define _OBJC_TAG_EXT_MASK 0xfUL
361 # define _OBJC_TAG_EXT_INDEX_SHIFT 4
362 # define _OBJC_TAG_EXT_SLOT_SHIFT 4
363 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 0
364 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
367 extern uintptr_t objc_debug_taggedpointer_obfuscator
;
369 static inline void * _Nonnull
370 _objc_encodeTaggedPointer(uintptr_t ptr
)
372 return (void *)(objc_debug_taggedpointer_obfuscator
^ ptr
);
375 static inline uintptr_t
376 _objc_decodeTaggedPointer(const void * _Nullable ptr
)
378 return (uintptr_t)ptr
^ objc_debug_taggedpointer_obfuscator
;
382 _objc_taggedPointersEnabled(void)
384 extern uintptr_t objc_debug_taggedpointer_mask
;
385 return (objc_debug_taggedpointer_mask
!= 0);
388 static inline void * _Nonnull
389 _objc_makeTaggedPointer(objc_tag_index_t tag
, uintptr_t value
)
391 // PAYLOAD_LSHIFT and PAYLOAD_RSHIFT are the payload extraction shifts.
392 // They are reversed here for payload insertion.
394 // assert(_objc_taggedPointersEnabled());
395 if (tag
<= OBJC_TAG_Last60BitPayload
) {
396 // assert(((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT) == value);
399 ((uintptr_t)tag
<< _OBJC_TAG_INDEX_SHIFT
) |
400 ((value
<< _OBJC_TAG_PAYLOAD_RSHIFT
) >> _OBJC_TAG_PAYLOAD_LSHIFT
));
401 return _objc_encodeTaggedPointer(result
);
403 // assert(tag >= OBJC_TAG_First52BitPayload);
404 // assert(tag <= OBJC_TAG_Last52BitPayload);
405 // assert(((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT) == value);
407 (_OBJC_TAG_EXT_MASK
|
408 ((uintptr_t)(tag
- OBJC_TAG_First52BitPayload
) << _OBJC_TAG_EXT_INDEX_SHIFT
) |
409 ((value
<< _OBJC_TAG_EXT_PAYLOAD_RSHIFT
) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT
));
410 return _objc_encodeTaggedPointer(result
);
415 _objc_isTaggedPointer(const void * _Nullable ptr
)
417 return ((uintptr_t)ptr
& _OBJC_TAG_MASK
) == _OBJC_TAG_MASK
;
420 static inline objc_tag_index_t
421 _objc_getTaggedPointerTag(const void * _Nullable ptr
)
423 // assert(_objc_isTaggedPointer(ptr));
424 uintptr_t value
= _objc_decodeTaggedPointer(ptr
);
425 uintptr_t basicTag
= (value
>> _OBJC_TAG_INDEX_SHIFT
) & _OBJC_TAG_INDEX_MASK
;
426 uintptr_t extTag
= (value
>> _OBJC_TAG_EXT_INDEX_SHIFT
) & _OBJC_TAG_EXT_INDEX_MASK
;
427 if (basicTag
== _OBJC_TAG_INDEX_MASK
) {
428 return (objc_tag_index_t
)(extTag
+ OBJC_TAG_First52BitPayload
);
430 return (objc_tag_index_t
)basicTag
;
434 static inline uintptr_t
435 _objc_getTaggedPointerValue(const void * _Nullable ptr
)
437 // assert(_objc_isTaggedPointer(ptr));
438 uintptr_t value
= _objc_decodeTaggedPointer(ptr
);
439 uintptr_t basicTag
= (value
>> _OBJC_TAG_INDEX_SHIFT
) & _OBJC_TAG_INDEX_MASK
;
440 if (basicTag
== _OBJC_TAG_INDEX_MASK
) {
441 return (value
<< _OBJC_TAG_EXT_PAYLOAD_LSHIFT
) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT
;
443 return (value
<< _OBJC_TAG_PAYLOAD_LSHIFT
) >> _OBJC_TAG_PAYLOAD_RSHIFT
;
447 static inline intptr_t
448 _objc_getTaggedPointerSignedValue(const void * _Nullable ptr
)
450 // assert(_objc_isTaggedPointer(ptr));
451 uintptr_t value
= _objc_decodeTaggedPointer(ptr
);
452 uintptr_t basicTag
= (value
>> _OBJC_TAG_INDEX_SHIFT
) & _OBJC_TAG_INDEX_MASK
;
453 if (basicTag
== _OBJC_TAG_INDEX_MASK
) {
454 return ((intptr_t)value
<< _OBJC_TAG_EXT_PAYLOAD_LSHIFT
) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT
;
456 return ((intptr_t)value
<< _OBJC_TAG_PAYLOAD_LSHIFT
) >> _OBJC_TAG_PAYLOAD_RSHIFT
;
460 // OBJC_HAVE_TAGGED_POINTERS
465 * Returns the method implementation of an object.
467 * @param obj An Objective-C object.
468 * @param name An Objective-C selector.
470 * @return The IMP corresponding to the instance method implemented by
471 * the class of \e obj.
473 * @note Equivalent to:
475 * class_getMethodImplementation(object_getClass(obj), name);
477 OBJC_EXPORT IMP _Nonnull
478 object_getMethodImplementation(id _Nullable obj
, SEL _Nonnull name
)
479 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
481 OBJC_EXPORT IMP _Nonnull
482 object_getMethodImplementation_stret(id _Nullable obj
, SEL _Nonnull name
)
483 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0)
484 OBJC_ARM64_UNAVAILABLE
;
488 * Adds multiple methods to a class in bulk. This amortizes overhead that can be
489 * expensive when adding methods one by one with class_addMethod.
491 * @param cls The class to which to add the methods.
492 * @param names An array of selectors for the methods to add.
493 * @param imps An array of functions which implement the new methods.
494 * @param types An array of strings that describe the types of each method's
496 * @param count The number of items in the names, imps, and types arrays.
497 * @param outFiledCount Upon return, contains the number of failed selectors in
498 * the returned array.
500 * @return A NULL-terminated C array of selectors which could not be added. A
501 * method cannot be added when a method of that name already exists on that
502 * class. When no failures occur, the return value is \c NULL. When a non-NULL
503 * value is returned, the caller must free the array with \c free().
507 OBJC_EXPORT _Nullable SEL
* _Nullable
508 class_addMethodsBulk(_Nullable Class cls
, _Nonnull
const SEL
* _Nonnull names
,
509 _Nonnull
const IMP
* _Nonnull imps
,
510 const char * _Nonnull
* _Nonnull types
, uint32_t count
,
511 uint32_t * _Nullable outFailedCount
)
512 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
516 * Replaces multiple methods in a class in bulk. This amortizes overhead that
517 * can be expensive when adding methods one by one with class_replaceMethod.
519 * @param cls The class to modify.
520 * @param names An array of selectors for the methods to replace.
521 * @param imps An array of functions will be the new method implementantations.
522 * @param types An array of strings that describe the types of each method's
524 * @param count The number of items in the names, imps, and types arrays.
528 class_replaceMethodsBulk(_Nullable Class cls
,
529 _Nonnull
const SEL
* _Nonnull names
,
530 _Nonnull
const IMP
* _Nonnull imps
,
531 const char * _Nonnull
* _Nonnull types
,
533 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
537 // Instance-specific instance variable layout. This is no longer implemented.
540 _class_setIvarLayoutAccessor(Class _Nullable cls
,
541 const uint8_t* _Nullable (* _Nonnull accessor
)
542 (id _Nullable object
))
543 UNAVAILABLE_ATTRIBUTE
;
545 OBJC_EXPORT
const uint8_t * _Nullable
546 _object_getIvarLayout(Class _Nullable cls
, id _Nullable object
)
547 UNAVAILABLE_ATTRIBUTE
;
551 "Unknown" includes non-object ivars and non-ARC non-__weak ivars
552 "Strong" includes ARC __strong ivars
553 "Weak" includes ARC and new MRC __weak ivars
554 "Unretained" includes ARC __unsafe_unretained and old GC+MRC __weak ivars
557 objc_ivar_memoryUnknown
, // unknown / unknown
558 objc_ivar_memoryStrong
, // direct access / objc_storeStrong
559 objc_ivar_memoryWeak
, // objc_loadWeak[Retained] / objc_storeWeak
560 objc_ivar_memoryUnretained
// direct access / direct access
561 } objc_ivar_memory_management_t
;
563 OBJC_EXPORT objc_ivar_memory_management_t
564 _class_getIvarMemoryManagement(Class _Nullable cls
, Ivar _Nonnull ivar
)
565 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
567 OBJC_EXPORT BOOL
_class_isFutureClass(Class _Nullable cls
)
568 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
571 // API to only be called by root classes like NSObject or NSProxy
575 _objc_rootRetain(id _Nonnull obj
)
576 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
580 _objc_rootRelease(id _Nonnull obj
)
581 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
585 _objc_rootReleaseWasZero(id _Nonnull obj
)
586 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
590 _objc_rootTryRetain(id _Nonnull obj
)
591 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
595 _objc_rootIsDeallocating(id _Nonnull obj
)
596 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
600 _objc_rootAutorelease(id _Nonnull obj
)
601 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
605 _objc_rootRetainCount(id _Nonnull obj
)
606 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
610 _objc_rootInit(id _Nonnull obj
)
611 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
615 _objc_rootAllocWithZone(Class _Nonnull cls
, malloc_zone_t
* _Nullable zone
)
616 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
620 _objc_rootAlloc(Class _Nonnull cls
)
621 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
625 _objc_rootDealloc(id _Nonnull obj
)
626 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
630 _objc_rootFinalize(id _Nonnull obj
)
631 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
634 malloc_zone_t
* _Nonnull
635 _objc_rootZone(id _Nonnull obj
)
636 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
640 _objc_rootHash(id _Nonnull obj
)
641 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
645 objc_autoreleasePoolPush(void)
646 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
650 objc_autoreleasePoolPop(void * _Nonnull context
)
651 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
654 OBJC_EXPORT id _Nullable
655 objc_alloc(Class _Nullable cls
)
656 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
658 OBJC_EXPORT id _Nullable
659 objc_allocWithZone(Class _Nullable cls
)
660 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
662 OBJC_EXPORT id _Nullable
663 objc_retain(id _Nullable obj
)
664 __asm__("_objc_retain")
665 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
668 objc_release(id _Nullable obj
)
669 __asm__("_objc_release")
670 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
672 OBJC_EXPORT id _Nullable
673 objc_autorelease(id _Nullable obj
)
674 __asm__("_objc_autorelease")
675 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
677 // Prepare a value at +1 for return through a +0 autoreleasing convention.
678 OBJC_EXPORT id _Nullable
679 objc_autoreleaseReturnValue(id _Nullable obj
)
680 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
682 // Prepare a value at +0 for return through a +0 autoreleasing convention.
683 OBJC_EXPORT id _Nullable
684 objc_retainAutoreleaseReturnValue(id _Nullable obj
)
685 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
687 // Accept a value returned through a +0 autoreleasing convention for use at +1.
688 OBJC_EXPORT id _Nullable
689 objc_retainAutoreleasedReturnValue(id _Nullable obj
)
690 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
692 // Accept a value returned through a +0 autoreleasing convention for use at +0.
693 OBJC_EXPORT id _Nullable
694 objc_unsafeClaimAutoreleasedReturnValue(id _Nullable obj
)
695 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
698 objc_storeStrong(id _Nullable
* _Nonnull location
, id _Nullable obj
)
699 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
701 OBJC_EXPORT id _Nullable
702 objc_retainAutorelease(id _Nullable obj
)
703 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
706 OBJC_EXPORT id _Nullable
707 objc_retain_autorelease(id _Nullable obj
)
708 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
710 OBJC_EXPORT id _Nullable
711 objc_loadWeakRetained(id _Nullable
* _Nonnull location
)
712 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
714 OBJC_EXPORT id _Nullable
715 objc_initWeak(id _Nullable
* _Nonnull location
, id _Nullable val
)
716 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
718 // Like objc_storeWeak, but stores nil if the new object is deallocating
719 // or the new object's class does not support weak references.
720 // Returns the value stored (either the new object or nil).
721 OBJC_EXPORT id _Nullable
722 objc_storeWeakOrNil(id _Nullable
* _Nonnull location
, id _Nullable obj
)
723 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
725 // Like objc_initWeak, but stores nil if the new object is deallocating
726 // or the new object's class does not support weak references.
727 // Returns the value stored (either the new object or nil).
728 OBJC_EXPORT id _Nullable
729 objc_initWeakOrNil(id _Nullable
* _Nonnull location
, id _Nullable val
)
730 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
733 objc_destroyWeak(id _Nullable
* _Nonnull location
)
734 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
737 objc_copyWeak(id _Nullable
* _Nonnull to
, id _Nullable
* _Nonnull from
)
738 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
741 objc_moveWeak(id _Nullable
* _Nonnull to
, id _Nullable
* _Nonnull from
)
742 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
746 _objc_autoreleasePoolPrint(void)
747 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
750 objc_should_deallocate(id _Nonnull object
)
751 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
754 objc_clear_deallocating(id _Nonnull object
)
755 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
758 // to make CF link for now
760 OBJC_EXPORT
void * _Nonnull
761 _objc_autoreleasePoolPush(void)
762 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
765 _objc_autoreleasePoolPop(void * _Nonnull context
)
766 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
769 // Extra @encode data for XPC, or NULL
770 OBJC_EXPORT
const char * _Nullable
771 _protocol_getMethodTypeEncoding(Protocol
* _Nonnull proto
, SEL _Nonnull sel
,
772 BOOL isRequiredMethod
, BOOL isInstanceMethod
)
773 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
776 // API to only be called by classes that provide their own reference count storage
779 _objc_deallocOnMainThreadHelper(void * _Nullable context
)
780 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
782 // On async versus sync deallocation and the _dealloc2main flag
786 // If order matters, then code must always: [self dealloc].
787 // If order doesn't matter, then always async should be safe.
791 // The _dealloc2main bit is set for GUI objects that may be retained by other
792 // threads. Once deallocation begins on the main thread, doing more async
793 // deallocation will at best cause extra UI latency and at worst cause
794 // use-after-free bugs in unretained delegate style patterns. Yes, this is
795 // extremely fragile. Yes, in the long run, developers should switch to weak
798 // Note is NOT safe to do any equality check against the result of
799 // dispatch_get_current_queue(). The main thread can and does drain more than
800 // one dispatch queue. That is why we call pthread_main_np().
804 _OBJC_RESURRECT_OBJECT
= -1, /* _logicBlock has called -retain, and scheduled a -release for later. */
805 _OBJC_DEALLOC_OBJECT_NOW
= 1, /* call [self dealloc] immediately. */
806 _OBJC_DEALLOC_OBJECT_LATER
= 2 /* call [self dealloc] on the main queue. */
807 } _objc_object_disposition_t
;
809 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \
811 /* this will fail to compile if _rc_ivar is an unsigned type */ \
812 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
813 __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \
814 if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \
815 __builtin_trap(); /* BUG: retain of over-released ref */ \
819 -(oneway void)release { \
820 __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \
823 } else if (_prev < 0) { \
824 __builtin_trap(); /* BUG: over-release */ \
826 _objc_object_disposition_t fate = _logicBlock(self); \
827 if (fate == _OBJC_RESURRECT_OBJECT) { \
830 /* mark the object as deallocating. */ \
831 if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \
832 __builtin_trap(); /* BUG: dangling ref did a retain */ \
834 if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \
836 } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \
837 dispatch_barrier_async_f(dispatch_get_main_queue(), self, \
838 _objc_deallocOnMainThreadHelper); \
840 __builtin_trap(); /* BUG: bogus fate value */ \
843 -(NSUInteger)retainCount { \
844 return (_rc_ivar + 2) >> 1; \
846 -(BOOL)_tryRetain { \
847 __typeof__(_rc_ivar) _prev; \
852 } else if (_prev == -2) { \
854 } else if (_prev < -2) { \
855 __builtin_trap(); /* BUG: over-release elsewhere */ \
857 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
860 -(BOOL)_isDeallocating { \
861 if (_rc_ivar == -2) { \
863 } else if (_rc_ivar < -2) { \
864 __builtin_trap(); /* BUG: over-release elsewhere */ \
866 return _rc_ivar & 1; \
869 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
870 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
871 if (_dealloc2main && !pthread_main_np()) { \
872 return _OBJC_DEALLOC_OBJECT_LATER; \
874 return _OBJC_DEALLOC_OBJECT_NOW; \
878 #define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0)
879 #define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1)