]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-internal.h
a3e0feed59e23f80515f2f4021fb07a919ca2e61
[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 <mach-o/loader.h>
45 #include <dispatch/dispatch.h>
46
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
58 __BEGIN_DECLS
59
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);
63 #endif
64
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);
74
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().
83 #if __OBJC2__
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);
89 #endif
90
91 // Batch object allocation using malloc_zone_batch_malloc().
92 OBJC_EXPORT unsigned
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)
96 OBJC_ARC_UNAVAILABLE;
97
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);
102
103 // env NSObjCMessageLoggingEnabled
104 OBJC_EXPORT void
105 instrumentObjcMessageSends(BOOL flag)
106 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
107
108 // Initializer called by libSystem
109 OBJC_EXPORT void
110 _objc_init(void)
111 #if __OBJC2__
112 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
113 #else
114 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
115 #endif
116
117 // fork() safety called by libSystem
118 OBJC_EXPORT void
119 _objc_atfork_prepare(void)
120 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
121
122 OBJC_EXPORT void
123 _objc_atfork_parent(void)
124 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
125
126 OBJC_EXPORT void
127 _objc_atfork_child(void)
128 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
129
130 // Return YES if GC is on and `object` is a GC allocation.
131 OBJC_EXPORT BOOL
132 objc_isAuto(id _Nullable object)
133 __OSX_DEPRECATED(10.4, 10.8, "it always returns NO")
134 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
135 __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE;
136
137 // GC debugging
138 OBJC_EXPORT BOOL
139 objc_dumpHeap(char * _Nonnull filename, unsigned long length)
140 __OSX_DEPRECATED(10.4, 10.8, "it always returns NO")
141 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
142 __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE;
143
144 // GC startup callback from Foundation
145 OBJC_EXPORT malloc_zone_t * _Nullable
146 objc_collect_init(int (* _Nonnull callback)(void))
147 __OSX_DEPRECATED(10.4, 10.8, "it does nothing")
148 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
149 __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE;
150
151 // Plainly-implemented GC barriers. Rosetta used to use these.
152 OBJC_EXPORT id _Nullable
153 objc_assign_strongCast_generic(id _Nullable value, id _Nullable * _Nonnull dest)
154 UNAVAILABLE_ATTRIBUTE;
155
156 OBJC_EXPORT id _Nullable
157 objc_assign_global_generic(id _Nullable value, id _Nullable * _Nonnull dest)
158 UNAVAILABLE_ATTRIBUTE;
159
160 OBJC_EXPORT id _Nullable
161 objc_assign_threadlocal_generic(id _Nullable value,
162 id _Nullable * _Nonnull dest)
163 UNAVAILABLE_ATTRIBUTE;
164
165 OBJC_EXPORT id _Nullable
166 objc_assign_ivar_generic(id _Nullable value, id _Nonnull dest, ptrdiff_t offset)
167 UNAVAILABLE_ATTRIBUTE;
168
169 // GC preflight for an app executable.
170 // 1: some slice requires GC
171 // 0: no slice requires GC
172 // -1: I/O or file format error
173 OBJC_EXPORT int
174 objc_appRequiresGC(int fd)
175 __OSX_AVAILABLE(10.11)
176 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
177 __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE;
178
179 // Install missing-class callback. Used by the late unlamented ZeroLink.
180 OBJC_EXPORT void
181 _objc_setClassLoader(BOOL (* _Nonnull newClassLoader)(const char * _Nonnull))
182 OBJC2_UNAVAILABLE;
183
184 #if !(TARGET_OS_OSX && !TARGET_OS_IOSMAC && __i386__)
185 OBJC_EXPORT void
186 _objc_setClassCopyFixupHandler(void (* _Nonnull newFixupHandler)
187 (Class _Nonnull oldClass, Class _Nonnull newClass));
188 // fixme work around bug in Swift
189 // OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0)
190 #endif
191
192 // Install handler for allocation failures.
193 // Handler may abort, or throw, or provide an object to return.
194 OBJC_EXPORT void
195 _objc_setBadAllocHandler(id _Nullable (* _Nonnull newHandler)
196 (Class _Nullable isa))
197 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
198
199 // Used by ExceptionHandling.framework
200 #if !__OBJC2__
201 OBJC_EXPORT void
202 _objc_error(id _Nullable rcv, const char * _Nonnull fmt, va_list args)
203 __attribute__((noreturn))
204 __OSX_DEPRECATED(10.0, 10.5, "use other logging facilities instead")
205 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
206 __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE;
207
208 #endif
209
210
211 /**
212 * Returns the names of all the classes within a library.
213 *
214 * @param image The mach header for library or framework you are inquiring about.
215 * @param outCount The number of class names returned.
216 *
217 * @return An array of C strings representing the class names.
218 */
219 OBJC_EXPORT const char * _Nonnull * _Nullable
220 objc_copyClassNamesForImageHeader(const struct mach_header * _Nonnull mh,
221 unsigned int * _Nullable outCount)
222 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
223
224 // Tagged pointer objects.
225
226 #if __LP64__
227 #define OBJC_HAVE_TAGGED_POINTERS 1
228 #endif
229
230 #if OBJC_HAVE_TAGGED_POINTERS
231
232 // Tagged pointer layout and usage is subject to change on different OS versions.
233
234 // Tag indexes 0..<7 have a 60-bit payload.
235 // Tag index 7 is reserved.
236 // Tag indexes 8..<264 have a 52-bit payload.
237 // Tag index 264 is reserved.
238
239 #if __has_feature(objc_fixed_enum) || __cplusplus >= 201103L
240 enum objc_tag_index_t : uint16_t
241 #else
242 typedef uint16_t objc_tag_index_t;
243 enum
244 #endif
245 {
246 // 60-bit payloads
247 OBJC_TAG_NSAtom = 0,
248 OBJC_TAG_1 = 1,
249 OBJC_TAG_NSString = 2,
250 OBJC_TAG_NSNumber = 3,
251 OBJC_TAG_NSIndexPath = 4,
252 OBJC_TAG_NSManagedObjectID = 5,
253 OBJC_TAG_NSDate = 6,
254
255 // 60-bit reserved
256 OBJC_TAG_RESERVED_7 = 7,
257
258 // 52-bit payloads
259 OBJC_TAG_Photos_1 = 8,
260 OBJC_TAG_Photos_2 = 9,
261 OBJC_TAG_Photos_3 = 10,
262 OBJC_TAG_Photos_4 = 11,
263 OBJC_TAG_XPC_1 = 12,
264 OBJC_TAG_XPC_2 = 13,
265 OBJC_TAG_XPC_3 = 14,
266 OBJC_TAG_XPC_4 = 15,
267
268 OBJC_TAG_First60BitPayload = 0,
269 OBJC_TAG_Last60BitPayload = 6,
270 OBJC_TAG_First52BitPayload = 8,
271 OBJC_TAG_Last52BitPayload = 263,
272
273 OBJC_TAG_RESERVED_264 = 264
274 };
275 #if __has_feature(objc_fixed_enum) && !defined(__cplusplus)
276 typedef enum objc_tag_index_t objc_tag_index_t;
277 #endif
278
279
280 // Returns true if tagged pointers are enabled.
281 // The other functions below must not be called if tagged pointers are disabled.
282 static inline bool
283 _objc_taggedPointersEnabled(void);
284
285 // Register a class for a tagged pointer tag.
286 // Aborts if the tag is invalid or already in use.
287 OBJC_EXPORT void
288 _objc_registerTaggedPointerClass(objc_tag_index_t tag, Class _Nonnull cls)
289 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
290
291 // Returns the registered class for the given tag.
292 // Returns nil if the tag is valid but has no registered class.
293 // Aborts if the tag is invalid.
294 OBJC_EXPORT Class _Nullable
295 _objc_getClassForTag(objc_tag_index_t tag)
296 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
297
298 // Create a tagged pointer object with the given tag and payload.
299 // Assumes the tag is valid.
300 // Assumes tagged pointers are enabled.
301 // The payload will be silently truncated to fit.
302 static inline void * _Nonnull
303 _objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t payload);
304
305 // Return true if ptr is a tagged pointer object.
306 // Does not check the validity of ptr's class.
307 static inline bool
308 _objc_isTaggedPointer(const void * _Nullable ptr);
309
310 // Extract the tag value from the given tagged pointer object.
311 // Assumes ptr is a valid tagged pointer object.
312 // Does not check the validity of ptr's tag.
313 static inline objc_tag_index_t
314 _objc_getTaggedPointerTag(const void * _Nullable ptr);
315
316 // Extract the payload from the given tagged pointer object.
317 // Assumes ptr is a valid tagged pointer object.
318 // The payload value is zero-extended.
319 static inline uintptr_t
320 _objc_getTaggedPointerValue(const void * _Nullable ptr);
321
322 // Extract the payload from the given tagged pointer object.
323 // Assumes ptr is a valid tagged pointer object.
324 // The payload value is sign-extended.
325 static inline intptr_t
326 _objc_getTaggedPointerSignedValue(const void * _Nullable ptr);
327
328 // Don't use the values below. Use the declarations above.
329
330 #if (TARGET_OS_OSX || TARGET_OS_IOSMAC) && __x86_64__
331 // 64-bit Mac - tag bit is LSB
332 # define OBJC_MSB_TAGGED_POINTERS 0
333 #else
334 // Everything else - tag bit is MSB
335 # define OBJC_MSB_TAGGED_POINTERS 1
336 #endif
337
338 #define _OBJC_TAG_INDEX_MASK 0x7
339 // array slot includes the tag bit itself
340 #define _OBJC_TAG_SLOT_COUNT 16
341 #define _OBJC_TAG_SLOT_MASK 0xf
342
343 #define _OBJC_TAG_EXT_INDEX_MASK 0xff
344 // array slot has no extra bits
345 #define _OBJC_TAG_EXT_SLOT_COUNT 256
346 #define _OBJC_TAG_EXT_SLOT_MASK 0xff
347
348 #if OBJC_MSB_TAGGED_POINTERS
349 # define _OBJC_TAG_MASK (1UL<<63)
350 # define _OBJC_TAG_INDEX_SHIFT 60
351 # define _OBJC_TAG_SLOT_SHIFT 60
352 # define _OBJC_TAG_PAYLOAD_LSHIFT 4
353 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
354 # define _OBJC_TAG_EXT_MASK (0xfUL<<60)
355 # define _OBJC_TAG_EXT_INDEX_SHIFT 52
356 # define _OBJC_TAG_EXT_SLOT_SHIFT 52
357 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 12
358 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
359 #else
360 # define _OBJC_TAG_MASK 1UL
361 # define _OBJC_TAG_INDEX_SHIFT 1
362 # define _OBJC_TAG_SLOT_SHIFT 0
363 # define _OBJC_TAG_PAYLOAD_LSHIFT 0
364 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
365 # define _OBJC_TAG_EXT_MASK 0xfUL
366 # define _OBJC_TAG_EXT_INDEX_SHIFT 4
367 # define _OBJC_TAG_EXT_SLOT_SHIFT 4
368 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 0
369 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
370 #endif
371
372 extern uintptr_t objc_debug_taggedpointer_obfuscator;
373
374 static inline void * _Nonnull
375 _objc_encodeTaggedPointer(uintptr_t ptr)
376 {
377 return (void *)(objc_debug_taggedpointer_obfuscator ^ ptr);
378 }
379
380 static inline uintptr_t
381 _objc_decodeTaggedPointer(const void * _Nullable ptr)
382 {
383 return (uintptr_t)ptr ^ objc_debug_taggedpointer_obfuscator;
384 }
385
386 static inline bool
387 _objc_taggedPointersEnabled(void)
388 {
389 extern uintptr_t objc_debug_taggedpointer_mask;
390 return (objc_debug_taggedpointer_mask != 0);
391 }
392
393 static inline void * _Nonnull
394 _objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t value)
395 {
396 // PAYLOAD_LSHIFT and PAYLOAD_RSHIFT are the payload extraction shifts.
397 // They are reversed here for payload insertion.
398
399 // assert(_objc_taggedPointersEnabled());
400 if (tag <= OBJC_TAG_Last60BitPayload) {
401 // assert(((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT) == value);
402 uintptr_t result =
403 (_OBJC_TAG_MASK |
404 ((uintptr_t)tag << _OBJC_TAG_INDEX_SHIFT) |
405 ((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT));
406 return _objc_encodeTaggedPointer(result);
407 } else {
408 // assert(tag >= OBJC_TAG_First52BitPayload);
409 // assert(tag <= OBJC_TAG_Last52BitPayload);
410 // assert(((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT) == value);
411 uintptr_t result =
412 (_OBJC_TAG_EXT_MASK |
413 ((uintptr_t)(tag - OBJC_TAG_First52BitPayload) << _OBJC_TAG_EXT_INDEX_SHIFT) |
414 ((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT));
415 return _objc_encodeTaggedPointer(result);
416 }
417 }
418
419 static inline bool
420 _objc_isTaggedPointer(const void * _Nullable ptr)
421 {
422 return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
423 }
424
425 static inline objc_tag_index_t
426 _objc_getTaggedPointerTag(const void * _Nullable ptr)
427 {
428 // assert(_objc_isTaggedPointer(ptr));
429 uintptr_t value = _objc_decodeTaggedPointer(ptr);
430 uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
431 uintptr_t extTag = (value >> _OBJC_TAG_EXT_INDEX_SHIFT) & _OBJC_TAG_EXT_INDEX_MASK;
432 if (basicTag == _OBJC_TAG_INDEX_MASK) {
433 return (objc_tag_index_t)(extTag + OBJC_TAG_First52BitPayload);
434 } else {
435 return (objc_tag_index_t)basicTag;
436 }
437 }
438
439 static inline uintptr_t
440 _objc_getTaggedPointerValue(const void * _Nullable ptr)
441 {
442 // assert(_objc_isTaggedPointer(ptr));
443 uintptr_t value = _objc_decodeTaggedPointer(ptr);
444 uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
445 if (basicTag == _OBJC_TAG_INDEX_MASK) {
446 return (value << _OBJC_TAG_EXT_PAYLOAD_LSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
447 } else {
448 return (value << _OBJC_TAG_PAYLOAD_LSHIFT) >> _OBJC_TAG_PAYLOAD_RSHIFT;
449 }
450 }
451
452 static inline intptr_t
453 _objc_getTaggedPointerSignedValue(const void * _Nullable ptr)
454 {
455 // assert(_objc_isTaggedPointer(ptr));
456 uintptr_t value = _objc_decodeTaggedPointer(ptr);
457 uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
458 if (basicTag == _OBJC_TAG_INDEX_MASK) {
459 return ((intptr_t)value << _OBJC_TAG_EXT_PAYLOAD_LSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
460 } else {
461 return ((intptr_t)value << _OBJC_TAG_PAYLOAD_LSHIFT) >> _OBJC_TAG_PAYLOAD_RSHIFT;
462 }
463 }
464
465 // OBJC_HAVE_TAGGED_POINTERS
466 #endif
467
468
469 /**
470 * Returns the method implementation of an object.
471 *
472 * @param obj An Objective-C object.
473 * @param name An Objective-C selector.
474 *
475 * @return The IMP corresponding to the instance method implemented by
476 * the class of \e obj.
477 *
478 * @note Equivalent to:
479 *
480 * class_getMethodImplementation(object_getClass(obj), name);
481 */
482 OBJC_EXPORT IMP _Nonnull
483 object_getMethodImplementation(id _Nullable obj, SEL _Nonnull name)
484 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
485
486 OBJC_EXPORT IMP _Nonnull
487 object_getMethodImplementation_stret(id _Nullable obj, SEL _Nonnull name)
488 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0)
489 OBJC_ARM64_UNAVAILABLE;
490
491
492 /**
493 * Adds multiple methods to a class in bulk. This amortizes overhead that can be
494 * expensive when adding methods one by one with class_addMethod.
495 *
496 * @param cls The class to which to add the methods.
497 * @param names An array of selectors for the methods to add.
498 * @param imps An array of functions which implement the new methods.
499 * @param types An array of strings that describe the types of each method's
500 * arguments.
501 * @param count The number of items in the names, imps, and types arrays.
502 * @param outFiledCount Upon return, contains the number of failed selectors in
503 * the returned array.
504 *
505 * @return A NULL-terminated C array of selectors which could not be added. A
506 * method cannot be added when a method of that name already exists on that
507 * class. When no failures occur, the return value is \c NULL. When a non-NULL
508 * value is returned, the caller must free the array with \c free().
509 *
510 */
511 #if __OBJC2__
512 OBJC_EXPORT _Nullable SEL * _Nullable
513 class_addMethodsBulk(_Nullable Class cls, _Nonnull const SEL * _Nonnull names,
514 _Nonnull const IMP * _Nonnull imps,
515 const char * _Nonnull * _Nonnull types, uint32_t count,
516 uint32_t * _Nullable outFailedCount)
517 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
518 #endif
519
520 /**
521 * Replaces multiple methods in a class in bulk. This amortizes overhead that
522 * can be expensive when adding methods one by one with class_replaceMethod.
523 *
524 * @param cls The class to modify.
525 * @param names An array of selectors for the methods to replace.
526 * @param imps An array of functions will be the new method implementantations.
527 * @param types An array of strings that describe the types of each method's
528 * arguments.
529 * @param count The number of items in the names, imps, and types arrays.
530 */
531 #if __OBJC2__
532 OBJC_EXPORT void
533 class_replaceMethodsBulk(_Nullable Class cls,
534 _Nonnull const SEL * _Nonnull names,
535 _Nonnull const IMP * _Nonnull imps,
536 const char * _Nonnull * _Nonnull types,
537 uint32_t count)
538 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
539 #endif
540
541
542 // Instance-specific instance variable layout. This is no longer implemented.
543
544 OBJC_EXPORT void
545 _class_setIvarLayoutAccessor(Class _Nullable cls,
546 const uint8_t* _Nullable (* _Nonnull accessor)
547 (id _Nullable object))
548 UNAVAILABLE_ATTRIBUTE;
549
550 OBJC_EXPORT const uint8_t * _Nullable
551 _object_getIvarLayout(Class _Nullable cls, id _Nullable object)
552 UNAVAILABLE_ATTRIBUTE;
553
554
555 /*
556 "Unknown" includes non-object ivars and non-ARC non-__weak ivars
557 "Strong" includes ARC __strong ivars
558 "Weak" includes ARC and new MRC __weak ivars
559 "Unretained" includes ARC __unsafe_unretained and old GC+MRC __weak ivars
560 */
561 typedef enum {
562 objc_ivar_memoryUnknown, // unknown / unknown
563 objc_ivar_memoryStrong, // direct access / objc_storeStrong
564 objc_ivar_memoryWeak, // objc_loadWeak[Retained] / objc_storeWeak
565 objc_ivar_memoryUnretained // direct access / direct access
566 } objc_ivar_memory_management_t;
567
568 OBJC_EXPORT objc_ivar_memory_management_t
569 _class_getIvarMemoryManagement(Class _Nullable cls, Ivar _Nonnull ivar)
570 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
571
572 OBJC_EXPORT BOOL _class_isFutureClass(Class _Nullable cls)
573 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
574
575
576 // API to only be called by root classes like NSObject or NSProxy
577
578 OBJC_EXPORT
579 id _Nonnull
580 _objc_rootRetain(id _Nonnull obj)
581 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
582
583 OBJC_EXPORT
584 void
585 _objc_rootRelease(id _Nonnull obj)
586 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
587
588 OBJC_EXPORT
589 bool
590 _objc_rootReleaseWasZero(id _Nonnull obj)
591 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
592
593 OBJC_EXPORT
594 bool
595 _objc_rootTryRetain(id _Nonnull obj)
596 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
597
598 OBJC_EXPORT
599 bool
600 _objc_rootIsDeallocating(id _Nonnull obj)
601 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
602
603 OBJC_EXPORT
604 id _Nonnull
605 _objc_rootAutorelease(id _Nonnull obj)
606 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
607
608 OBJC_EXPORT
609 uintptr_t
610 _objc_rootRetainCount(id _Nonnull obj)
611 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
612
613 OBJC_EXPORT
614 id _Nonnull
615 _objc_rootInit(id _Nonnull obj)
616 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
617
618 OBJC_EXPORT
619 id _Nullable
620 _objc_rootAllocWithZone(Class _Nonnull cls, malloc_zone_t * _Nullable zone)
621 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
622
623 OBJC_EXPORT
624 id _Nullable
625 _objc_rootAlloc(Class _Nonnull cls)
626 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
627
628 OBJC_EXPORT
629 void
630 _objc_rootDealloc(id _Nonnull obj)
631 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
632
633 OBJC_EXPORT
634 void
635 _objc_rootFinalize(id _Nonnull obj)
636 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
637
638 OBJC_EXPORT
639 malloc_zone_t * _Nonnull
640 _objc_rootZone(id _Nonnull obj)
641 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
642
643 OBJC_EXPORT
644 uintptr_t
645 _objc_rootHash(id _Nonnull obj)
646 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
647
648 OBJC_EXPORT
649 void * _Nonnull
650 objc_autoreleasePoolPush(void)
651 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
652
653 OBJC_EXPORT
654 void
655 objc_autoreleasePoolPop(void * _Nonnull context)
656 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
657
658
659 OBJC_EXPORT id _Nullable
660 objc_alloc(Class _Nullable cls)
661 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
662
663 OBJC_EXPORT id _Nullable
664 objc_allocWithZone(Class _Nullable cls)
665 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
666
667 OBJC_EXPORT id _Nullable
668 objc_alloc_init(Class _Nullable cls)
669 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
670 // rdar://44986431 fixme correct availability for objc_alloc_init()
671
672 OBJC_EXPORT id _Nullable
673 objc_retain(id _Nullable obj)
674 __asm__("_objc_retain")
675 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
676
677 OBJC_EXPORT void
678 objc_release(id _Nullable obj)
679 __asm__("_objc_release")
680 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
681
682 OBJC_EXPORT id _Nullable
683 objc_autorelease(id _Nullable obj)
684 __asm__("_objc_autorelease")
685 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
686
687 // Prepare a value at +1 for return through a +0 autoreleasing convention.
688 OBJC_EXPORT id _Nullable
689 objc_autoreleaseReturnValue(id _Nullable obj)
690 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
691
692 // Prepare a value at +0 for return through a +0 autoreleasing convention.
693 OBJC_EXPORT id _Nullable
694 objc_retainAutoreleaseReturnValue(id _Nullable obj)
695 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
696
697 // Accept a value returned through a +0 autoreleasing convention for use at +1.
698 OBJC_EXPORT id _Nullable
699 objc_retainAutoreleasedReturnValue(id _Nullable obj)
700 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
701
702 // Accept a value returned through a +0 autoreleasing convention for use at +0.
703 OBJC_EXPORT id _Nullable
704 objc_unsafeClaimAutoreleasedReturnValue(id _Nullable obj)
705 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
706
707 OBJC_EXPORT void
708 objc_storeStrong(id _Nullable * _Nonnull location, id _Nullable obj)
709 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
710
711 OBJC_EXPORT id _Nullable
712 objc_retainAutorelease(id _Nullable obj)
713 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
714
715 // obsolete.
716 OBJC_EXPORT id _Nullable
717 objc_retain_autorelease(id _Nullable obj)
718 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
719
720 OBJC_EXPORT id _Nullable
721 objc_loadWeakRetained(id _Nullable * _Nonnull location)
722 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
723
724 OBJC_EXPORT id _Nullable
725 objc_initWeak(id _Nullable * _Nonnull location, id _Nullable val)
726 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
727
728 // Like objc_storeWeak, but stores nil if the new object is deallocating
729 // or the new object's class does not support weak references.
730 // Returns the value stored (either the new object or nil).
731 OBJC_EXPORT id _Nullable
732 objc_storeWeakOrNil(id _Nullable * _Nonnull location, id _Nullable obj)
733 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
734
735 // Like objc_initWeak, but stores nil if the new object is deallocating
736 // or the new object's class does not support weak references.
737 // Returns the value stored (either the new object or nil).
738 OBJC_EXPORT id _Nullable
739 objc_initWeakOrNil(id _Nullable * _Nonnull location, id _Nullable val)
740 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
741
742 OBJC_EXPORT void
743 objc_destroyWeak(id _Nullable * _Nonnull location)
744 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
745
746 OBJC_EXPORT void
747 objc_copyWeak(id _Nullable * _Nonnull to, id _Nullable * _Nonnull from)
748 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
749
750 OBJC_EXPORT void
751 objc_moveWeak(id _Nullable * _Nonnull to, id _Nullable * _Nonnull from)
752 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
753
754
755 OBJC_EXPORT void
756 _objc_autoreleasePoolPrint(void)
757 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
758
759 OBJC_EXPORT BOOL
760 objc_should_deallocate(id _Nonnull object)
761 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
762
763 OBJC_EXPORT void
764 objc_clear_deallocating(id _Nonnull object)
765 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
766
767
768 // to make CF link for now
769
770 OBJC_EXPORT void * _Nonnull
771 _objc_autoreleasePoolPush(void)
772 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
773
774 OBJC_EXPORT void
775 _objc_autoreleasePoolPop(void * _Nonnull context)
776 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
777
778
779 // Extra @encode data for XPC, or NULL
780 OBJC_EXPORT const char * _Nullable
781 _protocol_getMethodTypeEncoding(Protocol * _Nonnull proto, SEL _Nonnull sel,
782 BOOL isRequiredMethod, BOOL isInstanceMethod)
783 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
784
785
786 // API to only be called by classes that provide their own reference count storage
787
788 OBJC_EXPORT void
789 _objc_deallocOnMainThreadHelper(void * _Nullable context)
790 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
791
792 // On async versus sync deallocation and the _dealloc2main flag
793 //
794 // Theory:
795 //
796 // If order matters, then code must always: [self dealloc].
797 // If order doesn't matter, then always async should be safe.
798 //
799 // Practice:
800 //
801 // The _dealloc2main bit is set for GUI objects that may be retained by other
802 // threads. Once deallocation begins on the main thread, doing more async
803 // deallocation will at best cause extra UI latency and at worst cause
804 // use-after-free bugs in unretained delegate style patterns. Yes, this is
805 // extremely fragile. Yes, in the long run, developers should switch to weak
806 // references.
807 //
808 // Note is NOT safe to do any equality check against the result of
809 // dispatch_get_current_queue(). The main thread can and does drain more than
810 // one dispatch queue. That is why we call pthread_main_np().
811 //
812
813 typedef enum {
814 _OBJC_RESURRECT_OBJECT = -1, /* _logicBlock has called -retain, and scheduled a -release for later. */
815 _OBJC_DEALLOC_OBJECT_NOW = 1, /* call [self dealloc] immediately. */
816 _OBJC_DEALLOC_OBJECT_LATER = 2 /* call [self dealloc] on the main queue. */
817 } _objc_object_disposition_t;
818
819 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \
820 -(id)retain { \
821 /* this will fail to compile if _rc_ivar is an unsigned type */ \
822 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
823 __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \
824 if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \
825 __builtin_trap(); /* BUG: retain of over-released ref */ \
826 } \
827 return self; \
828 } \
829 -(oneway void)release { \
830 __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \
831 if (_prev > 0) { \
832 return; \
833 } else if (_prev < 0) { \
834 __builtin_trap(); /* BUG: over-release */ \
835 } \
836 _objc_object_disposition_t fate = _logicBlock(self); \
837 if (fate == _OBJC_RESURRECT_OBJECT) { \
838 return; \
839 } \
840 /* mark the object as deallocating. */ \
841 if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \
842 __builtin_trap(); /* BUG: dangling ref did a retain */ \
843 } \
844 if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \
845 [self dealloc]; \
846 } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \
847 dispatch_barrier_async_f(dispatch_get_main_queue(), self, \
848 _objc_deallocOnMainThreadHelper); \
849 } else { \
850 __builtin_trap(); /* BUG: bogus fate value */ \
851 } \
852 } \
853 -(NSUInteger)retainCount { \
854 return (_rc_ivar + 2) >> 1; \
855 } \
856 -(BOOL)_tryRetain { \
857 __typeof__(_rc_ivar) _prev; \
858 do { \
859 _prev = _rc_ivar; \
860 if (_prev & 1) { \
861 return 0; \
862 } else if (_prev == -2) { \
863 return 0; \
864 } else if (_prev < -2) { \
865 __builtin_trap(); /* BUG: over-release elsewhere */ \
866 } \
867 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
868 return 1; \
869 } \
870 -(BOOL)_isDeallocating { \
871 if (_rc_ivar == -2) { \
872 return 1; \
873 } else if (_rc_ivar < -2) { \
874 __builtin_trap(); /* BUG: over-release elsewhere */ \
875 } \
876 return _rc_ivar & 1; \
877 }
878
879 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
880 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
881 if (_dealloc2main && !pthread_main_np()) { \
882 return _OBJC_DEALLOC_OBJECT_LATER; \
883 } else { \
884 return _OBJC_DEALLOC_OBJECT_NOW; \
885 } \
886 }))
887
888 #define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0)
889 #define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1)
890
891 __END_DECLS
892
893 #endif