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 <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*))
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);
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().
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);
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)
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);
90 // env NSObjCMessageLoggingEnabled
91 OBJC_EXPORT
void instrumentObjcMessageSends(BOOL flag
)
92 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);
94 // Initializer called by libSystem
95 OBJC_EXPORT
void _objc_init(void)
97 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0);
99 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0);
102 // Return YES if GC is on and `object` is a GC allocation.
103 OBJC_EXPORT BOOL
objc_isAuto(id object
)
104 __OSX_DEPRECATED(10.4, 10.8, "it always returns NO")
105 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE
;
107 // GC startup callback from Foundation
108 OBJC_EXPORT malloc_zone_t
*objc_collect_init(int (*callback
)(void))
109 __OSX_DEPRECATED(10.4, 10.8, "it does nothing")
110 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE
;
112 // Plainly-implemented GC barriers. Rosetta used to use these.
113 OBJC_EXPORT id
objc_assign_strongCast_generic(id value
, id
*dest
)
114 UNAVAILABLE_ATTRIBUTE
;
115 OBJC_EXPORT id
objc_assign_global_generic(id value
, id
*dest
)
116 UNAVAILABLE_ATTRIBUTE
;
117 OBJC_EXPORT id
objc_assign_threadlocal_generic(id value
, id
*dest
)
118 UNAVAILABLE_ATTRIBUTE
;
119 OBJC_EXPORT id
objc_assign_ivar_generic(id value
, id dest
, ptrdiff_t offset
)
120 UNAVAILABLE_ATTRIBUTE
;
122 // GC preflight for an app executable.
123 // 1: some slice requires GC
124 // 0: no slice requires GC
125 // -1: I/O or file format error
126 OBJC_EXPORT
int objc_appRequiresGC(int fd
)
127 __OSX_AVAILABLE(10.11)
128 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE
;
130 // Install missing-class callback. Used by the late unlamented ZeroLink.
131 OBJC_EXPORT
void _objc_setClassLoader(BOOL (*newClassLoader
)(const char *)) OBJC2_UNAVAILABLE
;
133 // Install handler for allocation failures.
134 // Handler may abort, or throw, or provide an object to return.
135 OBJC_EXPORT
void _objc_setBadAllocHandler(id (*newHandler
)(Class isa
))
136 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0);
138 // This can go away when AppKit stops calling it (rdar://7811851)
140 OBJC_EXPORT
void objc_setMultithreaded (BOOL flag
)
141 __OSX_DEPRECATED(10.0, 10.5, "multithreading is always available")
142 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE
;
145 // Used by ExceptionHandling.framework
147 OBJC_EXPORT
void _objc_error(id rcv
, const char *fmt
, va_list args
)
148 __attribute__((noreturn
))
149 __OSX_DEPRECATED(10.0, 10.5, "use other logging facilities instead")
150 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE
;
155 // Tagged pointer objects.
158 #define OBJC_HAVE_TAGGED_POINTERS 1
161 #if OBJC_HAVE_TAGGED_POINTERS
163 // Tagged pointer layout and usage is subject to change on different OS versions.
165 // Tag indexes 0..<7 have a 60-bit payload.
166 // Tag index 7 is reserved.
167 // Tag indexes 8..<264 have a 52-bit payload.
168 // Tag index 264 is reserved.
170 #if __has_feature(objc_fixed_enum) || __cplusplus >= 201103L
171 enum objc_tag_index_t
: uint16_t
173 typedef uint16_t objc_tag_index_t
;
179 OBJC_TAG_NSString
= 2,
180 OBJC_TAG_NSNumber
= 3,
181 OBJC_TAG_NSIndexPath
= 4,
182 OBJC_TAG_NSManagedObjectID
= 5,
184 OBJC_TAG_RESERVED_7
= 7,
186 OBJC_TAG_First60BitPayload
= 0,
187 OBJC_TAG_Last60BitPayload
= 6,
188 OBJC_TAG_First52BitPayload
= 8,
189 OBJC_TAG_Last52BitPayload
= 263,
191 OBJC_TAG_RESERVED_264
= 264
193 #if __has_feature(objc_fixed_enum) && !defined(__cplusplus)
194 typedef enum objc_tag_index_t objc_tag_index_t
;
198 // Returns true if tagged pointers are enabled.
199 // The other functions below must not be called if tagged pointers are disabled.
201 _objc_taggedPointersEnabled(void);
203 // Register a class for a tagged pointer tag.
204 // Aborts if the tag is invalid or already in use.
205 OBJC_EXPORT
void _objc_registerTaggedPointerClass(objc_tag_index_t tag
, Class cls
)
206 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
208 // Returns the registered class for the given tag.
209 // Returns nil if the tag is valid but has no registered class.
210 // Aborts if the tag is invalid.
211 OBJC_EXPORT Class
_objc_getClassForTag(objc_tag_index_t tag
)
212 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
214 // Create a tagged pointer object with the given tag and payload.
215 // Assumes the tag is valid.
216 // Assumes tagged pointers are enabled.
217 // The payload will be silently truncated to fit.
219 _objc_makeTaggedPointer(objc_tag_index_t tag
, uintptr_t payload
);
221 // Return true if ptr is a tagged pointer object.
222 // Does not check the validity of ptr's class.
224 _objc_isTaggedPointer(const void *ptr
);
226 // Extract the tag value from the given tagged pointer object.
227 // Assumes ptr is a valid tagged pointer object.
228 // Does not check the validity of ptr's tag.
229 static inline objc_tag_index_t
230 _objc_getTaggedPointerTag(const void *ptr
);
232 // Extract the payload from the given tagged pointer object.
233 // Assumes ptr is a valid tagged pointer object.
234 // The payload value is zero-extended.
235 static inline uintptr_t
236 _objc_getTaggedPointerValue(const void *ptr
);
238 // Extract the payload from the given tagged pointer object.
239 // Assumes ptr is a valid tagged pointer object.
240 // The payload value is sign-extended.
241 static inline intptr_t
242 _objc_getTaggedPointerSignedValue(const void *ptr
);
244 // Don't use the values below. Use the declarations above.
246 #if TARGET_OS_OSX && __x86_64__
247 // 64-bit Mac - tag bit is LSB
248 # define OBJC_MSB_TAGGED_POINTERS 0
250 // Everything else - tag bit is MSB
251 # define OBJC_MSB_TAGGED_POINTERS 1
254 #define _OBJC_TAG_INDEX_MASK 0x7
255 // array slot includes the tag bit itself
256 #define _OBJC_TAG_SLOT_COUNT 16
257 #define _OBJC_TAG_SLOT_MASK 0xf
259 #define _OBJC_TAG_EXT_INDEX_MASK 0xff
260 // array slot has no extra bits
261 #define _OBJC_TAG_EXT_SLOT_COUNT 256
262 #define _OBJC_TAG_EXT_SLOT_MASK 0xff
264 #if OBJC_MSB_TAGGED_POINTERS
265 # define _OBJC_TAG_MASK (1ULL<<63)
266 # define _OBJC_TAG_INDEX_SHIFT 60
267 # define _OBJC_TAG_SLOT_SHIFT 60
268 # define _OBJC_TAG_PAYLOAD_LSHIFT 4
269 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
270 # define _OBJC_TAG_EXT_MASK (0xfULL<<60)
271 # define _OBJC_TAG_EXT_INDEX_SHIFT 52
272 # define _OBJC_TAG_EXT_SLOT_SHIFT 52
273 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 12
274 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
276 # define _OBJC_TAG_MASK 1
277 # define _OBJC_TAG_INDEX_SHIFT 1
278 # define _OBJC_TAG_SLOT_SHIFT 0
279 # define _OBJC_TAG_PAYLOAD_LSHIFT 0
280 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
281 # define _OBJC_TAG_EXT_MASK 0xfULL
282 # define _OBJC_TAG_EXT_INDEX_SHIFT 4
283 # define _OBJC_TAG_EXT_SLOT_SHIFT 4
284 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 0
285 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
289 _objc_taggedPointersEnabled(void)
291 extern uintptr_t objc_debug_taggedpointer_mask
;
292 return (objc_debug_taggedpointer_mask
!= 0);
296 _objc_makeTaggedPointer(objc_tag_index_t tag
, uintptr_t value
)
298 // PAYLOAD_LSHIFT and PAYLOAD_RSHIFT are the payload extraction shifts.
299 // They are reversed here for payload insertion.
301 // assert(_objc_taggedPointersEnabled());
302 if (tag
<= OBJC_TAG_Last60BitPayload
) {
303 // assert(((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT) == value);
306 ((uintptr_t)tag
<< _OBJC_TAG_INDEX_SHIFT
) |
307 ((value
<< _OBJC_TAG_PAYLOAD_RSHIFT
) >> _OBJC_TAG_PAYLOAD_LSHIFT
));
309 // assert(tag >= OBJC_TAG_First52BitPayload);
310 // assert(tag <= OBJC_TAG_Last52BitPayload);
311 // assert(((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT) == value);
313 (_OBJC_TAG_EXT_MASK
|
314 ((uintptr_t)(tag
- OBJC_TAG_First52BitPayload
) << _OBJC_TAG_EXT_INDEX_SHIFT
) |
315 ((value
<< _OBJC_TAG_EXT_PAYLOAD_RSHIFT
) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT
));
320 _objc_isTaggedPointer(const void *ptr
)
322 return ((intptr_t)ptr
& _OBJC_TAG_MASK
) == _OBJC_TAG_MASK
;
325 static inline objc_tag_index_t
326 _objc_getTaggedPointerTag(const void *ptr
)
328 // assert(_objc_isTaggedPointer(ptr));
329 uintptr_t basicTag
= ((uintptr_t)ptr
>> _OBJC_TAG_INDEX_SHIFT
) & _OBJC_TAG_INDEX_MASK
;
330 uintptr_t extTag
= ((uintptr_t)ptr
>> _OBJC_TAG_EXT_INDEX_SHIFT
) & _OBJC_TAG_EXT_INDEX_MASK
;
331 if (basicTag
== _OBJC_TAG_INDEX_MASK
) {
332 return (objc_tag_index_t
)(extTag
+ OBJC_TAG_First52BitPayload
);
334 return (objc_tag_index_t
)basicTag
;
338 static inline uintptr_t
339 _objc_getTaggedPointerValue(const void *ptr
)
341 // assert(_objc_isTaggedPointer(ptr));
342 uintptr_t basicTag
= ((uintptr_t)ptr
>> _OBJC_TAG_INDEX_SHIFT
) & _OBJC_TAG_INDEX_MASK
;
343 if (basicTag
== _OBJC_TAG_INDEX_MASK
) {
344 return ((uintptr_t)ptr
<< _OBJC_TAG_EXT_PAYLOAD_LSHIFT
) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT
;
346 return ((uintptr_t)ptr
<< _OBJC_TAG_PAYLOAD_LSHIFT
) >> _OBJC_TAG_PAYLOAD_RSHIFT
;
350 static inline intptr_t
351 _objc_getTaggedPointerSignedValue(const void *ptr
)
353 // assert(_objc_isTaggedPointer(ptr));
354 uintptr_t basicTag
= ((uintptr_t)ptr
>> _OBJC_TAG_INDEX_SHIFT
) & _OBJC_TAG_INDEX_MASK
;
355 if (basicTag
== _OBJC_TAG_INDEX_MASK
) {
356 return ((intptr_t)ptr
<< _OBJC_TAG_EXT_PAYLOAD_LSHIFT
) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT
;
358 return ((intptr_t)ptr
<< _OBJC_TAG_PAYLOAD_LSHIFT
) >> _OBJC_TAG_PAYLOAD_RSHIFT
;
362 // OBJC_HAVE_TAGGED_POINTERS
367 * Returns the method implementation of an object.
369 * @param obj An Objective-C object.
370 * @param name An Objective-C selector.
372 * @return The IMP corresponding to the instance method implemented by
373 * the class of \e obj.
375 * @note Equivalent to:
377 * class_getMethodImplementation(object_getClass(obj), name);
379 OBJC_EXPORT IMP
object_getMethodImplementation(id obj
, SEL name
)
380 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
382 OBJC_EXPORT IMP
object_getMethodImplementation_stret(id obj
, SEL name
)
383 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0)
384 OBJC_ARM64_UNAVAILABLE
;
387 // Instance-specific instance variable layout.
389 OBJC_EXPORT
void _class_setIvarLayoutAccessor(Class cls_gen
, const uint8_t* (*accessor
) (id object
))
390 __OSX_AVAILABLE(10.7)
391 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE
;
392 OBJC_EXPORT
const uint8_t *_object_getIvarLayout(Class cls_gen
, id object
)
393 __OSX_AVAILABLE(10.7)
394 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE
;
397 "Unknown" includes non-object ivars and non-ARC non-__weak ivars
398 "Strong" includes ARC __strong ivars
399 "Weak" includes ARC and new MRC __weak ivars
400 "Unretained" includes ARC __unsafe_unretained and old GC+MRC __weak ivars
403 objc_ivar_memoryUnknown
, // unknown / unknown
404 objc_ivar_memoryStrong
, // direct access / objc_storeStrong
405 objc_ivar_memoryWeak
, // objc_loadWeak[Retained] / objc_storeWeak
406 objc_ivar_memoryUnretained
// direct access / direct access
407 } objc_ivar_memory_management_t
;
409 OBJC_EXPORT objc_ivar_memory_management_t
_class_getIvarMemoryManagement(Class cls
, Ivar ivar
)
410 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0);
412 OBJC_EXPORT BOOL
_class_isFutureClass(Class cls
)
413 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
416 // API to only be called by root classes like NSObject or NSProxy
420 _objc_rootRetain(id obj
)
421 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
425 _objc_rootRelease(id obj
)
426 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
430 _objc_rootReleaseWasZero(id obj
)
431 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
435 _objc_rootTryRetain(id obj
)
436 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
440 _objc_rootIsDeallocating(id obj
)
441 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
445 _objc_rootAutorelease(id obj
)
446 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
450 _objc_rootRetainCount(id obj
)
451 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
455 _objc_rootInit(id obj
)
456 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
460 _objc_rootAllocWithZone(Class cls
, malloc_zone_t
*zone
)
461 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
465 _objc_rootAlloc(Class cls
)
466 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
470 _objc_rootDealloc(id obj
)
471 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
475 _objc_rootFinalize(id obj
)
476 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
480 _objc_rootZone(id obj
)
481 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
485 _objc_rootHash(id obj
)
486 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
490 objc_autoreleasePoolPush(void)
491 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
495 objc_autoreleasePoolPop(void *context
)
496 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
499 OBJC_EXPORT id
objc_alloc(Class cls
)
500 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
502 OBJC_EXPORT id
objc_allocWithZone(Class cls
)
503 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0);
505 OBJC_EXPORT id
objc_retain(id obj
)
506 __asm__("_objc_retain")
507 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
509 OBJC_EXPORT
void objc_release(id obj
)
510 __asm__("_objc_release")
511 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
513 OBJC_EXPORT id
objc_autorelease(id obj
)
514 __asm__("_objc_autorelease")
515 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
517 // Prepare a value at +1 for return through a +0 autoreleasing convention.
520 objc_autoreleaseReturnValue(id obj
)
521 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
523 // Prepare a value at +0 for return through a +0 autoreleasing convention.
526 objc_retainAutoreleaseReturnValue(id obj
)
527 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
529 // Accept a value returned through a +0 autoreleasing convention for use at +1.
532 objc_retainAutoreleasedReturnValue(id obj
)
533 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
535 // Accept a value returned through a +0 autoreleasing convention for use at +0.
538 objc_unsafeClaimAutoreleasedReturnValue(id obj
)
539 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0);
543 objc_storeStrong(id
*location
, id obj
)
544 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
548 objc_retainAutorelease(id obj
)
549 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
552 OBJC_EXPORT id
objc_retain_autorelease(id obj
)
553 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
557 objc_loadWeakRetained(id
*location
)
558 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
562 objc_initWeak(id
*location
, id val
)
563 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
565 // Like objc_storeWeak, but stores nil if the new object is deallocating
566 // or the new object's class does not support weak references.
567 // Returns the value stored (either the new object or nil).
570 objc_storeWeakOrNil(id
*location
, id obj
)
571 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0);
573 // Like objc_initWeak, 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).
578 objc_initWeakOrNil(id
*location
, id val
)
579 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0);
583 objc_destroyWeak(id
*location
)
584 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
588 objc_copyWeak(id
*to
, id
*from
)
589 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
593 objc_moveWeak(id
*to
, id
*from
)
594 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
599 _objc_autoreleasePoolPrint(void)
600 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
602 OBJC_EXPORT BOOL
objc_should_deallocate(id object
)
603 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
605 OBJC_EXPORT
void objc_clear_deallocating(id object
)
606 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
609 // to make CF link for now
613 _objc_autoreleasePoolPush(void)
614 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
618 _objc_autoreleasePoolPop(void *context
)
619 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
622 // Extra @encode data for XPC, or NULL
623 OBJC_EXPORT
const char *_protocol_getMethodTypeEncoding(Protocol
*p
, SEL sel
, BOOL isRequiredMethod
, BOOL isInstanceMethod
)
624 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0);
627 // API to only be called by classes that provide their own reference count storage
631 _objc_deallocOnMainThreadHelper(void *context
)
632 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0);
634 // On async versus sync deallocation and the _dealloc2main flag
638 // If order matters, then code must always: [self dealloc].
639 // If order doesn't matter, then always async should be safe.
643 // The _dealloc2main bit is set for GUI objects that may be retained by other
644 // threads. Once deallocation begins on the main thread, doing more async
645 // deallocation will at best cause extra UI latency and at worst cause
646 // use-after-free bugs in unretained delegate style patterns. Yes, this is
647 // extremely fragile. Yes, in the long run, developers should switch to weak
650 // Note is NOT safe to do any equality check against the result of
651 // dispatch_get_current_queue(). The main thread can and does drain more than
652 // one dispatch queue. That is why we call pthread_main_np().
656 _OBJC_RESURRECT_OBJECT
= -1, /* _logicBlock has called -retain, and scheduled a -release for later. */
657 _OBJC_DEALLOC_OBJECT_NOW
= 1, /* call [self dealloc] immediately. */
658 _OBJC_DEALLOC_OBJECT_LATER
= 2 /* call [self dealloc] on the main queue. */
659 } _objc_object_disposition_t
;
661 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \
663 /* this will fail to compile if _rc_ivar is an unsigned type */ \
664 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
665 __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \
666 if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \
667 __builtin_trap(); /* BUG: retain of over-released ref */ \
671 -(oneway void)release { \
672 __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \
675 } else if (_prev < 0) { \
676 __builtin_trap(); /* BUG: over-release */ \
678 _objc_object_disposition_t fate = _logicBlock(self); \
679 if (fate == _OBJC_RESURRECT_OBJECT) { \
682 /* mark the object as deallocating. */ \
683 if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \
684 __builtin_trap(); /* BUG: dangling ref did a retain */ \
686 if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \
688 } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \
689 dispatch_barrier_async_f(dispatch_get_main_queue(), self, \
690 _objc_deallocOnMainThreadHelper); \
692 __builtin_trap(); /* BUG: bogus fate value */ \
695 -(NSUInteger)retainCount { \
696 return (_rc_ivar + 2) >> 1; \
698 -(BOOL)_tryRetain { \
699 __typeof__(_rc_ivar) _prev; \
704 } else if (_prev == -2) { \
706 } else if (_prev < -2) { \
707 __builtin_trap(); /* BUG: over-release elsewhere */ \
709 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
712 -(BOOL)_isDeallocating { \
713 if (_rc_ivar == -2) { \
715 } else if (_rc_ivar < -2) { \
716 __builtin_trap(); /* BUG: over-release elsewhere */ \
718 return _rc_ivar & 1; \
721 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
722 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
723 if (_dealloc2main && !pthread_main_np()) { \
724 return _OBJC_DEALLOC_OBJECT_LATER; \
726 return _OBJC_DEALLOC_OBJECT_NOW; \
730 #define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0)
731 #define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1)