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