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 // This symbol is exported only from debug builds of libobjc itself.
61 #if defined(OBJC_IS_DEBUG_BUILD)
62 OBJC_EXPORT
void _objc_isDebugBuild(void);
65 // In-place construction of an Objective-C class.
66 // cls and metacls must each be OBJC_MAX_CLASS_SIZE bytes.
67 // Returns nil if a class with the same name already exists.
68 // Returns nil if the superclass is under construction.
69 // Call objc_registerClassPair() when you are done.
70 OBJC_EXPORT Class _Nullable
71 objc_initializeClassPair(Class _Nullable superclass
, const char * _Nonnull name
,
72 Class _Nonnull cls
, Class _Nonnull metacls
)
73 OBJC_AVAILABLE(10.6, 3.0, 9.0, 1.0, 2.0);
75 // Class and metaclass construction from a compiler-generated memory image.
76 // cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes.
77 // Extra bytes not used the the metadata must be zero.
78 // info is the same objc_image_info that would be emitted by a static compiler.
79 // Returns nil if a class with the same name already exists.
80 // Returns nil if the superclass is nil and the class is not marked as a root.
81 // Returns nil if the superclass is under construction.
82 // Do not call objc_registerClassPair().
84 struct objc_image_info
;
85 OBJC_EXPORT Class _Nullable
86 objc_readClassPair(Class _Nonnull cls
,
87 const struct objc_image_info
* _Nonnull info
)
88 OBJC_AVAILABLE(10.10, 8.0, 9.0, 1.0, 2.0);
91 // Batch object allocation using malloc_zone_batch_malloc().
93 class_createInstances(Class _Nullable cls
, size_t extraBytes
,
94 id _Nonnull
* _Nonnull results
, unsigned num_requested
)
95 OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0)
98 // Get the isa pointer written into objects just before being freed.
99 OBJC_EXPORT Class _Nonnull
100 _objc_getFreedObjectClass(void)
101 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
103 // env NSObjCMessageLoggingEnabled
105 instrumentObjcMessageSends(BOOL flag
)
106 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
108 // Initializer called by libSystem
112 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
114 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
117 // fork() safety called by libSystem
119 _objc_atfork_prepare(void)
120 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
123 _objc_atfork_parent(void)
124 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
127 _objc_atfork_child(void)
128 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
130 // Return YES if GC is on and `object` is a GC allocation.
132 objc_isAuto(id _Nullable object
)
133 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.4, 10.8, "it always returns NO");
137 objc_dumpHeap(char * _Nonnull filename
, unsigned long length
)
138 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.4, 10.8, "it always returns NO");
140 // GC startup callback from Foundation
141 OBJC_EXPORT malloc_zone_t
* _Nullable
142 objc_collect_init(int (* _Nonnull callback
)(void))
143 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.4, 10.8, "it does nothing");
146 // Copies the list of currently realized classes
147 // intended for introspection only
148 // most users will want objc_copyClassList instead.
150 Class _Nonnull
* _Nullable
151 objc_copyRealizedClassList(unsigned int *_Nullable outCount
)
152 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
154 typedef struct objc_imp_cache_entry
{
157 } objc_imp_cache_entry
;
160 objc_imp_cache_entry
*_Nullable
161 class_copyImpCache(Class _Nonnull cls
, int * _Nullable outCount
)
162 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
165 // Plainly-implemented GC barriers. Rosetta used to use these.
166 OBJC_EXPORT id _Nullable
167 objc_assign_strongCast_generic(id _Nullable value
, id _Nullable
* _Nonnull dest
)
168 UNAVAILABLE_ATTRIBUTE
;
170 OBJC_EXPORT id _Nullable
171 objc_assign_global_generic(id _Nullable value
, id _Nullable
* _Nonnull dest
)
172 UNAVAILABLE_ATTRIBUTE
;
174 OBJC_EXPORT id _Nullable
175 objc_assign_threadlocal_generic(id _Nullable value
,
176 id _Nullable
* _Nonnull dest
)
177 UNAVAILABLE_ATTRIBUTE
;
179 OBJC_EXPORT id _Nullable
180 objc_assign_ivar_generic(id _Nullable value
, id _Nonnull dest
, ptrdiff_t offset
)
181 UNAVAILABLE_ATTRIBUTE
;
183 // GC preflight for an app executable.
184 // 1: some slice requires GC
185 // 0: no slice requires GC
186 // -1: I/O or file format error
188 objc_appRequiresGC(int fd
)
189 __OSX_AVAILABLE(10.11)
190 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
191 __WATCHOS_UNAVAILABLE
192 #ifndef __APPLE_BLEACH_SDK__
193 __BRIDGEOS_UNAVAILABLE
197 // Install missing-class callback. Used by the late unlamented ZeroLink.
199 _objc_setClassLoader(BOOL (* _Nonnull newClassLoader
)(const char * _Nonnull
))
202 #if !(TARGET_OS_OSX && !TARGET_OS_IOSMAC && __i386__)
203 // Add a class copy fixup handler. The name is a misnomer, as
204 // multiple calls will install multiple handlers. Older versions
205 // of the Swift runtime call it by name, and it's only used by Swift
206 // so it's not worth deprecating this name in favor of a better one.
208 _objc_setClassCopyFixupHandler(void (* _Nonnull newFixupHandler
)
209 (Class _Nonnull oldClass
, Class _Nonnull newClass
))
210 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
213 // Install handler for allocation failures.
214 // Handler may abort, or throw, or provide an object to return.
216 _objc_setBadAllocHandler(id
_Nullable (* _Nonnull newHandler
)
217 (Class _Nullable isa
))
218 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
220 // Used by ExceptionHandling.framework
223 _objc_error(id _Nullable rcv
, const char * _Nonnull fmt
, va_list args
)
224 __attribute__((noreturn
, cold
))
225 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.0, 10.5, "use other logging facilities instead");
231 * Returns the names of all the classes within a library.
233 * @param image The mach header for library or framework you are inquiring about.
234 * @param outCount The number of class names returned.
236 * @return An array of C strings representing the class names.
238 OBJC_EXPORT
const char * _Nonnull
* _Nullable
239 objc_copyClassNamesForImageHeader(const struct mach_header
* _Nonnull mh
,
240 unsigned int * _Nullable outCount
)
241 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
243 // Tagged pointer objects.
246 #define OBJC_HAVE_TAGGED_POINTERS 1
249 #if OBJC_HAVE_TAGGED_POINTERS
251 // Tagged pointer layout and usage is subject to change on different OS versions.
253 // Tag indexes 0..<7 have a 60-bit payload.
254 // Tag index 7 is reserved.
255 // Tag indexes 8..<264 have a 52-bit payload.
256 // Tag index 264 is reserved.
258 #if __has_feature(objc_fixed_enum) || __cplusplus >= 201103L
259 enum objc_tag_index_t
: uint16_t
261 typedef uint16_t objc_tag_index_t
;
268 OBJC_TAG_NSString
= 2,
269 OBJC_TAG_NSNumber
= 3,
270 OBJC_TAG_NSIndexPath
= 4,
271 OBJC_TAG_NSManagedObjectID
= 5,
275 OBJC_TAG_RESERVED_7
= 7,
278 OBJC_TAG_Photos_1
= 8,
279 OBJC_TAG_Photos_2
= 9,
280 OBJC_TAG_Photos_3
= 10,
281 OBJC_TAG_Photos_4
= 11,
286 OBJC_TAG_NSColor
= 16,
287 OBJC_TAG_UIColor
= 17,
288 OBJC_TAG_CGColor
= 18,
289 OBJC_TAG_NSIndexSet
= 19,
291 OBJC_TAG_First60BitPayload
= 0,
292 OBJC_TAG_Last60BitPayload
= 6,
293 OBJC_TAG_First52BitPayload
= 8,
294 OBJC_TAG_Last52BitPayload
= 263,
296 OBJC_TAG_RESERVED_264
= 264
298 #if __has_feature(objc_fixed_enum) && !defined(__cplusplus)
299 typedef enum objc_tag_index_t objc_tag_index_t
;
303 // Returns true if tagged pointers are enabled.
304 // The other functions below must not be called if tagged pointers are disabled.
306 _objc_taggedPointersEnabled(void);
308 // Register a class for a tagged pointer tag.
309 // Aborts if the tag is invalid or already in use.
311 _objc_registerTaggedPointerClass(objc_tag_index_t tag
, Class _Nonnull cls
)
312 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
314 // Returns the registered class for the given tag.
315 // Returns nil if the tag is valid but has no registered class.
316 // Aborts if the tag is invalid.
317 OBJC_EXPORT Class _Nullable
318 _objc_getClassForTag(objc_tag_index_t tag
)
319 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
321 // Create a tagged pointer object with the given tag and payload.
322 // Assumes the tag is valid.
323 // Assumes tagged pointers are enabled.
324 // The payload will be silently truncated to fit.
325 static inline void * _Nonnull
326 _objc_makeTaggedPointer(objc_tag_index_t tag
, uintptr_t payload
);
328 // Return true if ptr is a tagged pointer object.
329 // Does not check the validity of ptr's class.
331 _objc_isTaggedPointer(const void * _Nullable ptr
);
333 // Extract the tag value from the given tagged pointer object.
334 // Assumes ptr is a valid tagged pointer object.
335 // Does not check the validity of ptr's tag.
336 static inline objc_tag_index_t
337 _objc_getTaggedPointerTag(const void * _Nullable ptr
);
339 // Extract the payload from the given tagged pointer object.
340 // Assumes ptr is a valid tagged pointer object.
341 // The payload value is zero-extended.
342 static inline uintptr_t
343 _objc_getTaggedPointerValue(const void * _Nullable ptr
);
345 // Extract the payload from the given tagged pointer object.
346 // Assumes ptr is a valid tagged pointer object.
347 // The payload value is sign-extended.
348 static inline intptr_t
349 _objc_getTaggedPointerSignedValue(const void * _Nullable ptr
);
351 // Don't use the values below. Use the declarations above.
353 #if (TARGET_OS_OSX || TARGET_OS_IOSMAC) && __x86_64__
354 // 64-bit Mac - tag bit is LSB
355 # define OBJC_MSB_TAGGED_POINTERS 0
357 // Everything else - tag bit is MSB
358 # define OBJC_MSB_TAGGED_POINTERS 1
361 #define _OBJC_TAG_INDEX_MASK 0x7
362 // array slot includes the tag bit itself
363 #define _OBJC_TAG_SLOT_COUNT 16
364 #define _OBJC_TAG_SLOT_MASK 0xf
366 #define _OBJC_TAG_EXT_INDEX_MASK 0xff
367 // array slot has no extra bits
368 #define _OBJC_TAG_EXT_SLOT_COUNT 256
369 #define _OBJC_TAG_EXT_SLOT_MASK 0xff
371 #if OBJC_MSB_TAGGED_POINTERS
372 # define _OBJC_TAG_MASK (1UL<<63)
373 # define _OBJC_TAG_INDEX_SHIFT 60
374 # define _OBJC_TAG_SLOT_SHIFT 60
375 # define _OBJC_TAG_PAYLOAD_LSHIFT 4
376 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
377 # define _OBJC_TAG_EXT_MASK (0xfUL<<60)
378 # define _OBJC_TAG_EXT_INDEX_SHIFT 52
379 # define _OBJC_TAG_EXT_SLOT_SHIFT 52
380 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 12
381 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
383 # define _OBJC_TAG_MASK 1UL
384 # define _OBJC_TAG_INDEX_SHIFT 1
385 # define _OBJC_TAG_SLOT_SHIFT 0
386 # define _OBJC_TAG_PAYLOAD_LSHIFT 0
387 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
388 # define _OBJC_TAG_EXT_MASK 0xfUL
389 # define _OBJC_TAG_EXT_INDEX_SHIFT 4
390 # define _OBJC_TAG_EXT_SLOT_SHIFT 4
391 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 0
392 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
395 extern uintptr_t objc_debug_taggedpointer_obfuscator
;
397 static inline void * _Nonnull
398 _objc_encodeTaggedPointer(uintptr_t ptr
)
400 return (void *)(objc_debug_taggedpointer_obfuscator
^ ptr
);
403 static inline uintptr_t
404 _objc_decodeTaggedPointer(const void * _Nullable ptr
)
406 return (uintptr_t)ptr
^ objc_debug_taggedpointer_obfuscator
;
410 _objc_taggedPointersEnabled(void)
412 extern uintptr_t objc_debug_taggedpointer_mask
;
413 return (objc_debug_taggedpointer_mask
!= 0);
416 static inline void * _Nonnull
417 _objc_makeTaggedPointer(objc_tag_index_t tag
, uintptr_t value
)
419 // PAYLOAD_LSHIFT and PAYLOAD_RSHIFT are the payload extraction shifts.
420 // They are reversed here for payload insertion.
422 // ASSERT(_objc_taggedPointersEnabled());
423 if (tag
<= OBJC_TAG_Last60BitPayload
) {
424 // ASSERT(((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT) == value);
427 ((uintptr_t)tag
<< _OBJC_TAG_INDEX_SHIFT
) |
428 ((value
<< _OBJC_TAG_PAYLOAD_RSHIFT
) >> _OBJC_TAG_PAYLOAD_LSHIFT
));
429 return _objc_encodeTaggedPointer(result
);
431 // ASSERT(tag >= OBJC_TAG_First52BitPayload);
432 // ASSERT(tag <= OBJC_TAG_Last52BitPayload);
433 // ASSERT(((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT) == value);
435 (_OBJC_TAG_EXT_MASK
|
436 ((uintptr_t)(tag
- OBJC_TAG_First52BitPayload
) << _OBJC_TAG_EXT_INDEX_SHIFT
) |
437 ((value
<< _OBJC_TAG_EXT_PAYLOAD_RSHIFT
) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT
));
438 return _objc_encodeTaggedPointer(result
);
443 _objc_isTaggedPointer(const void * _Nullable ptr
)
445 return ((uintptr_t)ptr
& _OBJC_TAG_MASK
) == _OBJC_TAG_MASK
;
448 static inline objc_tag_index_t
449 _objc_getTaggedPointerTag(const void * _Nullable ptr
)
451 // ASSERT(_objc_isTaggedPointer(ptr));
452 uintptr_t value
= _objc_decodeTaggedPointer(ptr
);
453 uintptr_t basicTag
= (value
>> _OBJC_TAG_INDEX_SHIFT
) & _OBJC_TAG_INDEX_MASK
;
454 uintptr_t extTag
= (value
>> _OBJC_TAG_EXT_INDEX_SHIFT
) & _OBJC_TAG_EXT_INDEX_MASK
;
455 if (basicTag
== _OBJC_TAG_INDEX_MASK
) {
456 return (objc_tag_index_t
)(extTag
+ OBJC_TAG_First52BitPayload
);
458 return (objc_tag_index_t
)basicTag
;
462 static inline uintptr_t
463 _objc_getTaggedPointerValue(const void * _Nullable ptr
)
465 // ASSERT(_objc_isTaggedPointer(ptr));
466 uintptr_t value
= _objc_decodeTaggedPointer(ptr
);
467 uintptr_t basicTag
= (value
>> _OBJC_TAG_INDEX_SHIFT
) & _OBJC_TAG_INDEX_MASK
;
468 if (basicTag
== _OBJC_TAG_INDEX_MASK
) {
469 return (value
<< _OBJC_TAG_EXT_PAYLOAD_LSHIFT
) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT
;
471 return (value
<< _OBJC_TAG_PAYLOAD_LSHIFT
) >> _OBJC_TAG_PAYLOAD_RSHIFT
;
475 static inline intptr_t
476 _objc_getTaggedPointerSignedValue(const void * _Nullable ptr
)
478 // ASSERT(_objc_isTaggedPointer(ptr));
479 uintptr_t value
= _objc_decodeTaggedPointer(ptr
);
480 uintptr_t basicTag
= (value
>> _OBJC_TAG_INDEX_SHIFT
) & _OBJC_TAG_INDEX_MASK
;
481 if (basicTag
== _OBJC_TAG_INDEX_MASK
) {
482 return ((intptr_t)value
<< _OBJC_TAG_EXT_PAYLOAD_LSHIFT
) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT
;
484 return ((intptr_t)value
<< _OBJC_TAG_PAYLOAD_LSHIFT
) >> _OBJC_TAG_PAYLOAD_RSHIFT
;
488 // OBJC_HAVE_TAGGED_POINTERS
493 * Returns the method implementation of an object.
495 * @param obj An Objective-C object.
496 * @param name An Objective-C selector.
498 * @return The IMP corresponding to the instance method implemented by
499 * the class of \e obj.
501 * @note Equivalent to:
503 * class_getMethodImplementation(object_getClass(obj), name);
505 OBJC_EXPORT IMP _Nonnull
506 object_getMethodImplementation(id _Nullable obj
, SEL _Nonnull name
)
507 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
509 OBJC_EXPORT IMP _Nonnull
510 object_getMethodImplementation_stret(id _Nullable obj
, SEL _Nonnull name
)
511 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0)
512 OBJC_ARM64_UNAVAILABLE
;
516 * Adds multiple methods to a class in bulk. This amortizes overhead that can be
517 * expensive when adding methods one by one with class_addMethod.
519 * @param cls The class to which to add the methods.
520 * @param names An array of selectors for the methods to add.
521 * @param imps An array of functions which implement the new methods.
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.
525 * @param outFiledCount Upon return, contains the number of failed selectors in
526 * the returned array.
528 * @return A NULL-terminated C array of selectors which could not be added. A
529 * method cannot be added when a method of that name already exists on that
530 * class. When no failures occur, the return value is \c NULL. When a non-NULL
531 * value is returned, the caller must free the array with \c free().
535 OBJC_EXPORT _Nullable SEL
* _Nullable
536 class_addMethodsBulk(_Nullable Class cls
, _Nonnull
const SEL
* _Nonnull names
,
537 _Nonnull
const IMP
* _Nonnull imps
,
538 const char * _Nonnull
* _Nonnull types
, uint32_t count
,
539 uint32_t * _Nullable outFailedCount
)
540 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
544 * Replaces multiple methods in a class in bulk. This amortizes overhead that
545 * can be expensive when adding methods one by one with class_replaceMethod.
547 * @param cls The class to modify.
548 * @param names An array of selectors for the methods to replace.
549 * @param imps An array of functions will be the new method implementantations.
550 * @param types An array of strings that describe the types of each method's
552 * @param count The number of items in the names, imps, and types arrays.
556 class_replaceMethodsBulk(_Nullable Class cls
,
557 _Nonnull
const SEL
* _Nonnull names
,
558 _Nonnull
const IMP
* _Nonnull imps
,
559 const char * _Nonnull
* _Nonnull types
,
561 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
565 // Instance-specific instance variable layout. This is no longer implemented.
568 _class_setIvarLayoutAccessor(Class _Nullable cls
,
569 const uint8_t* _Nullable (* _Nonnull accessor
)
570 (id _Nullable object
))
571 UNAVAILABLE_ATTRIBUTE
;
573 OBJC_EXPORT
const uint8_t * _Nullable
574 _object_getIvarLayout(Class _Nullable cls
, id _Nullable object
)
575 UNAVAILABLE_ATTRIBUTE
;
579 "Unknown" includes non-object ivars and non-ARC non-__weak ivars
580 "Strong" includes ARC __strong ivars
581 "Weak" includes ARC and new MRC __weak ivars
582 "Unretained" includes ARC __unsafe_unretained and old GC+MRC __weak ivars
585 objc_ivar_memoryUnknown
, // unknown / unknown
586 objc_ivar_memoryStrong
, // direct access / objc_storeStrong
587 objc_ivar_memoryWeak
, // objc_loadWeak[Retained] / objc_storeWeak
588 objc_ivar_memoryUnretained
// direct access / direct access
589 } objc_ivar_memory_management_t
;
591 OBJC_EXPORT objc_ivar_memory_management_t
592 _class_getIvarMemoryManagement(Class _Nullable cls
, Ivar _Nonnull ivar
)
593 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
595 OBJC_EXPORT BOOL
_class_isFutureClass(Class _Nullable cls
)
596 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
599 // API to only be called by root classes like NSObject or NSProxy
603 _objc_rootRetain(id _Nonnull obj
)
604 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
608 _objc_rootRelease(id _Nonnull obj
)
609 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
613 _objc_rootReleaseWasZero(id _Nonnull obj
)
614 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
618 _objc_rootTryRetain(id _Nonnull obj
)
619 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
623 _objc_rootIsDeallocating(id _Nonnull obj
)
624 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
628 _objc_rootAutorelease(id _Nonnull obj
)
629 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
633 _objc_rootRetainCount(id _Nonnull obj
)
634 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
638 _objc_rootInit(id _Nonnull obj
)
639 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
643 _objc_rootAllocWithZone(Class _Nonnull cls
, malloc_zone_t
* _Nullable zone
)
644 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
648 _objc_rootAlloc(Class _Nonnull cls
)
649 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
653 _objc_rootDealloc(id _Nonnull obj
)
654 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
658 _objc_rootFinalize(id _Nonnull obj
)
659 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
662 malloc_zone_t
* _Nonnull
663 _objc_rootZone(id _Nonnull obj
)
664 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
668 _objc_rootHash(id _Nonnull obj
)
669 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
673 objc_autoreleasePoolPush(void)
674 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
678 objc_autoreleasePoolPop(void * _Nonnull context
)
679 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
682 OBJC_EXPORT id _Nullable
683 objc_alloc(Class _Nullable cls
)
684 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
686 OBJC_EXPORT id _Nullable
687 objc_allocWithZone(Class _Nullable cls
)
688 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
690 OBJC_EXPORT id _Nullable
691 objc_alloc_init(Class _Nullable cls
)
692 OBJC_AVAILABLE(10.14.4, 12.2, 12.2, 5.2, 3.2);
694 OBJC_EXPORT id _Nullable
695 objc_opt_new(Class _Nullable cls
)
696 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
698 OBJC_EXPORT id _Nullable
699 objc_opt_self(id _Nullable obj
)
700 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
702 OBJC_EXPORT Class _Nullable
703 objc_opt_class(id _Nullable obj
)
704 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
707 objc_opt_respondsToSelector(id _Nullable obj
, SEL _Nullable sel
)
708 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
711 objc_opt_isKindOfClass(id _Nullable obj
, Class _Nullable cls
)
712 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
716 objc_sync_try_enter(id _Nonnull obj
)
717 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
719 OBJC_EXPORT id _Nullable
720 objc_retain(id _Nullable obj
)
721 __asm__("_objc_retain")
722 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
725 objc_release(id _Nullable obj
)
726 __asm__("_objc_release")
727 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
729 OBJC_EXPORT id _Nullable
730 objc_autorelease(id _Nullable obj
)
731 __asm__("_objc_autorelease")
732 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
734 // Prepare a value at +1 for return through a +0 autoreleasing convention.
735 OBJC_EXPORT id _Nullable
736 objc_autoreleaseReturnValue(id _Nullable obj
)
737 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
739 // Prepare a value at +0 for return through a +0 autoreleasing convention.
740 OBJC_EXPORT id _Nullable
741 objc_retainAutoreleaseReturnValue(id _Nullable obj
)
742 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
744 // Accept a value returned through a +0 autoreleasing convention for use at +1.
745 OBJC_EXPORT id _Nullable
746 objc_retainAutoreleasedReturnValue(id _Nullable obj
)
747 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
749 // Accept a value returned through a +0 autoreleasing convention for use at +0.
750 OBJC_EXPORT id _Nullable
751 objc_unsafeClaimAutoreleasedReturnValue(id _Nullable obj
)
752 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
755 objc_storeStrong(id _Nullable
* _Nonnull location
, id _Nullable obj
)
756 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
758 OBJC_EXPORT id _Nullable
759 objc_retainAutorelease(id _Nullable obj
)
760 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
763 OBJC_EXPORT id _Nullable
764 objc_retain_autorelease(id _Nullable obj
)
765 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
767 OBJC_EXPORT id _Nullable
768 objc_loadWeakRetained(id _Nullable
* _Nonnull location
)
769 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
771 OBJC_EXPORT id _Nullable
772 objc_initWeak(id _Nullable
* _Nonnull location
, id _Nullable val
)
773 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
775 // Like objc_storeWeak, but stores nil if the new object is deallocating
776 // or the new object's class does not support weak references.
777 // Returns the value stored (either the new object or nil).
778 OBJC_EXPORT id _Nullable
779 objc_storeWeakOrNil(id _Nullable
* _Nonnull location
, id _Nullable obj
)
780 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
782 // Like objc_initWeak, but stores nil if the new object is deallocating
783 // or the new object's class does not support weak references.
784 // Returns the value stored (either the new object or nil).
785 OBJC_EXPORT id _Nullable
786 objc_initWeakOrNil(id _Nullable
* _Nonnull location
, id _Nullable val
)
787 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
790 objc_destroyWeak(id _Nullable
* _Nonnull location
)
791 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
794 objc_copyWeak(id _Nullable
* _Nonnull to
, id _Nullable
* _Nonnull from
)
795 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
798 objc_moveWeak(id _Nullable
* _Nonnull to
, id _Nullable
* _Nonnull from
)
799 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
803 _objc_autoreleasePoolPrint(void)
804 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
807 objc_should_deallocate(id _Nonnull object
)
808 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
811 objc_clear_deallocating(id _Nonnull object
)
812 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
815 // to make CF link for now
817 OBJC_EXPORT
void * _Nonnull
818 _objc_autoreleasePoolPush(void)
819 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
822 _objc_autoreleasePoolPop(void * _Nonnull context
)
823 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
827 * Load a classref, which is a chunk of data containing a class
828 * pointer. May perform initialization and rewrite the classref to
829 * point to a new object, if needed. Returns the loaded Class.
831 * In particular, if the classref points to a stub class (indicated
832 * by setting the bottom bit of the class pointer to 1), then this
833 * will call the stub's initializer and then replace the classref
834 * value with the value returned by the initializer.
836 * @param clsref The classref to load.
837 * @return The loaded Class pointer.
840 OBJC_EXPORT _Nullable Class
841 objc_loadClassref(_Nullable Class
* _Nonnull clsref
)
842 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
846 // Extra @encode data for XPC, or NULL
847 OBJC_EXPORT
const char * _Nullable
848 _protocol_getMethodTypeEncoding(Protocol
* _Nonnull proto
, SEL _Nonnull sel
,
849 BOOL isRequiredMethod
, BOOL isInstanceMethod
)
850 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
854 * Function type for a function that is called when a realized class
855 * is about to be initialized.
857 * @param context The context pointer the function was registered with.
858 * @param cls The class that's about to be initialized.
861 typedef void (*_objc_func_willInitializeClass
)(void * _Nullable context
, Class _Nonnull cls
);
864 * Add a function to be called when a realized class is about to be
865 * initialized. The class can be queried and manipulated using runtime
866 * functions. Don't message it.
868 * When adding a new function, that function is immediately called with all
869 * realized classes that are already initialized or are in the process
872 * @param func The function to add.
873 * @param context A context pointer that will be passed to the function when called.
875 #define OBJC_WILLINITIALIZECLASSFUNC_DEFINED 1
876 OBJC_EXPORT
void _objc_addWillInitializeClassFunc(_objc_func_willInitializeClass _Nonnull func
, void * _Nullable context
)
877 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 4.0);
879 // API to only be called by classes that provide their own reference count storage
882 _objc_deallocOnMainThreadHelper(void * _Nullable context
)
883 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
885 // On async versus sync deallocation and the _dealloc2main flag
889 // If order matters, then code must always: [self dealloc].
890 // If order doesn't matter, then always async should be safe.
894 // The _dealloc2main bit is set for GUI objects that may be retained by other
895 // threads. Once deallocation begins on the main thread, doing more async
896 // deallocation will at best cause extra UI latency and at worst cause
897 // use-after-free bugs in unretained delegate style patterns. Yes, this is
898 // extremely fragile. Yes, in the long run, developers should switch to weak
901 // Note is NOT safe to do any equality check against the result of
902 // dispatch_get_current_queue(). The main thread can and does drain more than
903 // one dispatch queue. That is why we call pthread_main_np().
907 _OBJC_RESURRECT_OBJECT
= -1, /* _logicBlock has called -retain, and scheduled a -release for later. */
908 _OBJC_DEALLOC_OBJECT_NOW
= 1, /* call [self dealloc] immediately. */
909 _OBJC_DEALLOC_OBJECT_LATER
= 2 /* call [self dealloc] on the main queue. */
910 } _objc_object_disposition_t
;
912 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \
914 /* this will fail to compile if _rc_ivar is an unsigned type */ \
915 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
916 __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \
917 if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \
918 __builtin_trap(); /* BUG: retain of over-released ref */ \
922 -(oneway void)release { \
923 __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \
926 } else if (_prev < 0) { \
927 __builtin_trap(); /* BUG: over-release */ \
929 _objc_object_disposition_t fate = _logicBlock(self); \
930 if (fate == _OBJC_RESURRECT_OBJECT) { \
933 /* mark the object as deallocating. */ \
934 if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \
935 __builtin_trap(); /* BUG: dangling ref did a retain */ \
937 if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \
939 } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \
940 dispatch_barrier_async_f(dispatch_get_main_queue(), self, \
941 _objc_deallocOnMainThreadHelper); \
943 __builtin_trap(); /* BUG: bogus fate value */ \
946 -(NSUInteger)retainCount { \
947 return (_rc_ivar + 2) >> 1; \
949 -(BOOL)_tryRetain { \
950 __typeof__(_rc_ivar) _prev; \
955 } else if (_prev == -2) { \
957 } else if (_prev < -2) { \
958 __builtin_trap(); /* BUG: over-release elsewhere */ \
960 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
963 -(BOOL)_isDeallocating { \
964 if (_rc_ivar == -2) { \
966 } else if (_rc_ivar < -2) { \
967 __builtin_trap(); /* BUG: over-release elsewhere */ \
969 return _rc_ivar & 1; \
972 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
973 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
974 if (_dealloc2main && !pthread_main_np()) { \
975 return _OBJC_DEALLOC_OBJECT_LATER; \
977 return _OBJC_DEALLOC_OBJECT_NOW; \
981 #define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0)
982 #define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1)