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 <Availability.h>
42 #include <malloc/malloc.h>
43 #include <dispatch/dispatch.h>
47 // In-place construction of an Objective-C class.
48 OBJC_EXPORT Class
objc_initializeClassPair(Class superclass_gen
, const char *name
, Class cls_gen
, Class meta_gen
)
49 __OSX_AVAILABLE_STARTING(__MAC_10_6
, __IPHONE_3_0
);
51 #if __OBJC2__ && __LP64__
52 // Register a tagged pointer class.
53 OBJC_EXPORT
void _objc_insert_tagged_isa(unsigned char slotNumber
, Class isa
)
54 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_4_3
);
57 // Batch object allocation using malloc_zone_batch_malloc().
58 OBJC_EXPORT
unsigned class_createInstances(Class cls
, size_t extraBytes
,
59 id
*results
, unsigned num_requested
)
60 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_4_3
)
63 // Get the isa pointer written into objects just before being freed.
64 OBJC_EXPORT Class
_objc_getFreedObjectClass(void)
65 __OSX_AVAILABLE_STARTING(__MAC_10_0
, __IPHONE_2_0
);
67 // Substitute receiver for messages to nil.
68 // Not supported for all messages to nil.
69 OBJC_EXPORT id
_objc_setNilReceiver(id newNilReceiver
)
70 __OSX_AVAILABLE_STARTING(__MAC_10_3
, __IPHONE_NA
);
71 OBJC_EXPORT id
_objc_getNilReceiver(void)
72 __OSX_AVAILABLE_STARTING(__MAC_10_3
, __IPHONE_NA
);
74 // Return NO if no instance of `cls` has ever owned an associative reference.
75 OBJC_EXPORT BOOL
class_instancesHaveAssociatedObjects(Class cls
)
76 __OSX_AVAILABLE_STARTING(__MAC_10_6
, __IPHONE_3_0
);
78 // Return YES if GC is on and `object` is a GC allocation.
79 OBJC_EXPORT BOOL
objc_isAuto(id object
)
80 __OSX_AVAILABLE_STARTING(__MAC_10_4
, __IPHONE_NA
);
82 // env NSObjCMessageLoggingEnabled
83 OBJC_EXPORT
void instrumentObjcMessageSends(BOOL flag
)
84 __OSX_AVAILABLE_STARTING(__MAC_10_0
, __IPHONE_2_0
);
86 // Initializer called by libSystem
88 OBJC_EXPORT
void _objc_init(void)
89 __OSX_AVAILABLE_STARTING(__MAC_10_8
, __IPHONE_6_0
);
92 // GC startup callback from Foundation
93 OBJC_EXPORT malloc_zone_t
*objc_collect_init(int (*callback
)(void))
94 __OSX_AVAILABLE_STARTING(__MAC_10_4
, __IPHONE_NA
);
96 // Plainly-implemented GC barriers. Rosetta used to use these.
97 OBJC_EXPORT id
objc_assign_strongCast_generic(id value
, id
*dest
)
98 UNAVAILABLE_ATTRIBUTE
;
99 OBJC_EXPORT id
objc_assign_global_generic(id value
, id
*dest
)
100 UNAVAILABLE_ATTRIBUTE
;
101 OBJC_EXPORT id
objc_assign_threadlocal_generic(id value
, id
*dest
)
102 UNAVAILABLE_ATTRIBUTE
;
103 OBJC_EXPORT id
objc_assign_ivar_generic(id value
, id dest
, ptrdiff_t offset
)
104 UNAVAILABLE_ATTRIBUTE
;
106 // Install missing-class callback. Used by the late unlamented ZeroLink.
107 OBJC_EXPORT
void _objc_setClassLoader(BOOL (*newClassLoader
)(const char *)) OBJC2_UNAVAILABLE
;
109 // Install handler for allocation failures.
110 // Handler may abort, or throw, or provide an object to return.
111 OBJC_EXPORT
void _objc_setBadAllocHandler(id (*newHandler
)(Class isa
))
112 __OSX_AVAILABLE_STARTING(__MAC_10_8
, __IPHONE_6_0
);
114 // This can go away when AppKit stops calling it (rdar://7811851)
116 OBJC_EXPORT
void objc_setMultithreaded (BOOL flag
)
117 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0
,__MAC_10_5
, __IPHONE_NA
,__IPHONE_NA
);
120 // Used by ExceptionHandling.framework
122 OBJC_EXPORT
void _objc_error(id rcv
, const char *fmt
, va_list args
)
123 __attribute__((noreturn
))
124 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0
,__MAC_10_5
, __IPHONE_NA
,__IPHONE_NA
);
128 // External Reference support. Used to support compaction.
131 OBJC_XREF_STRONG
= 1,
134 typedef uintptr_t objc_xref_type_t
;
135 typedef uintptr_t objc_xref_t
;
137 OBJC_EXPORT objc_xref_t
_object_addExternalReference(id object
, objc_xref_type_t type
)
138 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_4_3
);
139 OBJC_EXPORT
void _object_removeExternalReference(objc_xref_t xref
)
140 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_4_3
);
141 OBJC_EXPORT id
_object_readExternalReference(objc_xref_t xref
)
142 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_4_3
);
144 OBJC_EXPORT
uintptr_t _object_getExternalHash(id object
)
145 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
147 // Instance-specific instance variable layout.
149 OBJC_EXPORT
void _class_setIvarLayoutAccessor(Class cls_gen
, const uint8_t* (*accessor
) (id object
))
150 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_NA
);
151 OBJC_EXPORT
const uint8_t *_object_getIvarLayout(Class cls_gen
, id object
)
152 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_NA
);
154 OBJC_EXPORT BOOL
_class_usesAutomaticRetainRelease(Class cls
)
155 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
157 // Obsolete ARC conversions.
159 // hack - remove and reinstate objc.h's definitions
160 #undef objc_retainedObject
161 #undef objc_unretainedObject
162 #undef objc_unretainedPointer
163 OBJC_EXPORT id
objc_retainedObject(objc_objectptr_t pointer
)
164 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
165 OBJC_EXPORT id
objc_unretainedObject(objc_objectptr_t pointer
)
166 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
167 OBJC_EXPORT objc_objectptr_t
objc_unretainedPointer(id object
)
168 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
169 #if __has_feature(objc_arc)
170 # define objc_retainedObject(o) ((__bridge_transfer id)(objc_objectptr_t)(o))
171 # define objc_unretainedObject(o) ((__bridge id)(objc_objectptr_t)(o))
172 # define objc_unretainedPointer(o) ((__bridge objc_objectptr_t)(id)(o))
174 # define objc_retainedObject(o) ((id)(objc_objectptr_t)(o))
175 # define objc_unretainedObject(o) ((id)(objc_objectptr_t)(o))
176 # define objc_unretainedPointer(o) ((objc_objectptr_t)(id)(o))
179 // API to only be called by root classes like NSObject or NSProxy
183 _objc_rootRetain(id obj
)
184 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
188 _objc_rootRelease(id obj
)
189 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
193 _objc_rootReleaseWasZero(id obj
)
194 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
198 _objc_rootTryRetain(id obj
)
199 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
203 _objc_rootIsDeallocating(id obj
)
204 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
208 _objc_rootAutorelease(id obj
)
209 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
213 _objc_rootRetainCount(id obj
)
214 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
218 _objc_rootInit(id obj
)
219 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
223 _objc_rootAllocWithZone(Class cls
, malloc_zone_t
*zone
)
224 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
228 _objc_rootAlloc(Class cls
)
229 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
233 _objc_rootDealloc(id obj
)
234 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
238 _objc_rootFinalize(id obj
)
239 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
243 _objc_rootZone(id obj
)
244 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
248 _objc_rootHash(id obj
)
249 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
253 objc_autoreleasePoolPush(void)
254 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
258 objc_autoreleasePoolPop(void *context
)
259 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
262 OBJC_EXPORT id
objc_retain(id obj
)
263 __asm__("_objc_retain")
264 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
266 OBJC_EXPORT
void objc_release(id obj
)
267 __asm__("_objc_release")
268 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
270 OBJC_EXPORT id
objc_autorelease(id obj
)
271 __asm__("_objc_autorelease")
272 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
274 // wraps objc_autorelease(obj) in a useful way when used with return values
277 objc_autoreleaseReturnValue(id obj
)
278 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
280 // wraps objc_autorelease(objc_retain(obj)) in a useful way when used with return values
283 objc_retainAutoreleaseReturnValue(id obj
)
284 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
286 // called ONLY by ARR by callers to undo the autorelease (if possible), otherwise objc_retain
289 objc_retainAutoreleasedReturnValue(id obj
)
290 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
294 objc_storeStrong(id
*location
, id obj
)
295 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
299 objc_retainAutorelease(id obj
)
300 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
303 OBJC_EXPORT id
objc_retain_autorelease(id obj
)
304 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
308 objc_loadWeakRetained(id
*location
)
309 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
313 objc_initWeak(id
*addr
, id val
)
314 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
318 objc_destroyWeak(id
*addr
)
319 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
323 objc_copyWeak(id
*to
, id
*from
)
324 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
328 objc_moveWeak(id
*to
, id
*from
)
329 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
334 _objc_autoreleasePoolPrint(void)
335 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
337 OBJC_EXPORT BOOL
objc_should_deallocate(id object
)
338 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
340 OBJC_EXPORT
void objc_clear_deallocating(id object
)
341 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
344 // to make CF link for now
348 _objc_autoreleasePoolPush(void)
349 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
353 _objc_autoreleasePoolPop(void *context
)
354 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
357 // Extra @encode data for XPC, or NULL
358 OBJC_EXPORT
const char *_protocol_getMethodTypeEncoding(Protocol
*p
, SEL sel
, BOOL isRequiredMethod
, BOOL isInstanceMethod
)
359 __OSX_AVAILABLE_STARTING(__MAC_10_8
, __IPHONE_6_0
);
362 // API to only be called by classes that provide their own reference count storage
366 _objc_deallocOnMainThreadHelper(void *context
)
367 __OSX_AVAILABLE_STARTING(__MAC_10_7
, __IPHONE_5_0
);
369 // On async versus sync deallocation and the _dealloc2main flag
373 // If order matters, then code must always: [self dealloc].
374 // If order doesn't matter, then always async should be safe.
378 // The _dealloc2main bit is set for GUI objects that may be retained by other
379 // threads. Once deallocation begins on the main thread, doing more async
380 // deallocation will at best cause extra UI latency and at worst cause
381 // use-after-free bugs in unretained delegate style patterns. Yes, this is
382 // extremely fragile. Yes, in the long run, developers should switch to weak
385 // Note is NOT safe to do any equality check against the result of
386 // dispatch_get_current_queue(). The main thread can and does drain more than
387 // one dispatch queue. That is why we call pthread_main_np().
391 _OBJC_RESURRECT_OBJECT
= -1, /* _logicBlock has called -retain, and scheduled a -release for later. */
392 _OBJC_DEALLOC_OBJECT_NOW
= 1, /* call [self dealloc] immediately. */
393 _OBJC_DEALLOC_OBJECT_LATER
= 2 /* call [self dealloc] on the main queue. */
394 } _objc_object_disposition_t
;
396 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \
398 /* this will fail to compile if _rc_ivar is an unsigned type */ \
399 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
400 __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \
401 if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \
402 __builtin_trap(); /* BUG: retain of over-released ref */ \
406 -(oneway void)release { \
407 __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \
410 } else if (_prev < 0) { \
411 __builtin_trap(); /* BUG: over-release */ \
413 _objc_object_disposition_t fate = _logicBlock(self); \
414 if (fate == _OBJC_RESURRECT_OBJECT) { \
417 /* mark the object as deallocating. */ \
418 if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \
419 __builtin_trap(); /* BUG: dangling ref did a retain */ \
421 if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \
423 } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \
424 dispatch_barrier_async_f(dispatch_get_main_queue(), self, \
425 _objc_deallocOnMainThreadHelper); \
427 __builtin_trap(); /* BUG: bogus fate value */ \
430 -(NSUInteger)retainCount { \
431 return (_rc_ivar + 2) >> 1; \
433 -(BOOL)_tryRetain { \
434 __typeof__(_rc_ivar) _prev; \
439 } else if (_prev == -2) { \
441 } else if (_prev < -2) { \
442 __builtin_trap(); /* BUG: over-release elsewhere */ \
444 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
447 -(BOOL)_isDeallocating { \
448 if (_rc_ivar == -2) { \
450 } else if (_rc_ivar < -2) { \
451 __builtin_trap(); /* BUG: over-release elsewhere */ \
453 return _rc_ivar & 1; \
456 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
457 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
458 if (_dealloc2main && !pthread_main_np()) { \
459 return _OBJC_DEALLOC_OBJECT_LATER; \
461 return _OBJC_DEALLOC_OBJECT_NOW; \
465 #define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0)
466 #define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1)