]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-internal.h
objc4-818.2.tar.gz
[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 // Include NSObject.h only if we're ObjC. Module imports get unhappy
48 // otherwise.
49 #if __OBJC__
50 #include <objc/NSObject.h>
51 #endif
52
53 // Termination reasons in the OS_REASON_OBJC namespace.
54 #define OBJC_EXIT_REASON_UNSPECIFIED 1
55 #define OBJC_EXIT_REASON_GC_NOT_SUPPORTED 2
56
57 // This is the allocation size required for each of the class and the metaclass
58 // with objc_initializeClassPair() and objc_readClassPair().
59 // The runtime's class structure will never grow beyond this.
60 #define OBJC_MAX_CLASS_SIZE (32*sizeof(void*))
61
62 // Private objc_setAssociatedObject policy modifier. When an object is
63 // destroyed, associated objects attached to that object that are marked with
64 // this will be released after all associated objects not so marked.
65 //
66 // In addition, such associations are not removed when calling
67 // objc_removeAssociatedObjects.
68 //
69 // NOTE: This should be used sparingly. Performance will be poor when a single
70 // object has more than a few (deliberately vague) associated objects marked
71 // with this flag. If you're not sure if you should use this, you should not use
72 // this!
73 #define _OBJC_ASSOCIATION_SYSTEM_OBJECT (1 << 16)
74
75 __BEGIN_DECLS
76
77 // This symbol is exported only from debug builds of libobjc itself.
78 #if defined(OBJC_IS_DEBUG_BUILD)
79 OBJC_EXPORT void _objc_isDebugBuild(void);
80 #endif
81
82 // In-place construction of an Objective-C class.
83 // cls and metacls must each be OBJC_MAX_CLASS_SIZE bytes.
84 // Returns nil if a class with the same name already exists.
85 // Returns nil if the superclass is under construction.
86 // Call objc_registerClassPair() when you are done.
87 OBJC_EXPORT Class _Nullable
88 objc_initializeClassPair(Class _Nullable superclass, const char * _Nonnull name,
89 Class _Nonnull cls, Class _Nonnull metacls)
90 OBJC_AVAILABLE(10.6, 3.0, 9.0, 1.0, 2.0);
91
92 // Class and metaclass construction from a compiler-generated memory image.
93 // cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes.
94 // Extra bytes not used the the metadata must be zero.
95 // info is the same objc_image_info that would be emitted by a static compiler.
96 // Returns nil if a class with the same name already exists.
97 // Returns nil if the superclass is nil and the class is not marked as a root.
98 // Returns nil if the superclass is under construction.
99 // Do not call objc_registerClassPair().
100 #if __OBJC2__
101 struct objc_image_info;
102 OBJC_EXPORT Class _Nullable
103 objc_readClassPair(Class _Nonnull cls,
104 const struct objc_image_info * _Nonnull info)
105 OBJC_AVAILABLE(10.10, 8.0, 9.0, 1.0, 2.0);
106 #endif
107
108 // Batch object allocation using malloc_zone_batch_malloc().
109 OBJC_EXPORT unsigned
110 class_createInstances(Class _Nullable cls, size_t extraBytes,
111 id _Nonnull * _Nonnull results, unsigned num_requested)
112 OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0)
113 OBJC_ARC_UNAVAILABLE;
114
115 // Get the isa pointer written into objects just before being freed.
116 OBJC_EXPORT Class _Nonnull
117 _objc_getFreedObjectClass(void)
118 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
119
120 // env NSObjCMessageLoggingEnabled
121 OBJC_EXPORT void
122 instrumentObjcMessageSends(BOOL flag)
123 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
124
125 // Initializer called by libSystem
126 OBJC_EXPORT void
127 _objc_init(void)
128 #if __OBJC2__
129 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
130 #else
131 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
132 #endif
133
134 // fork() safety called by libSystem
135 OBJC_EXPORT void
136 _objc_atfork_prepare(void)
137 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
138
139 OBJC_EXPORT void
140 _objc_atfork_parent(void)
141 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
142
143 OBJC_EXPORT void
144 _objc_atfork_child(void)
145 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
146
147 // Return YES if GC is on and `object` is a GC allocation.
148 OBJC_EXPORT BOOL
149 objc_isAuto(id _Nullable object)
150 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.4, 10.8, "it always returns NO");
151
152 // GC debugging
153 OBJC_EXPORT BOOL
154 objc_dumpHeap(char * _Nonnull filename, unsigned long length)
155 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.4, 10.8, "it always returns NO");
156
157 // GC startup callback from Foundation
158 OBJC_EXPORT malloc_zone_t * _Nullable
159 objc_collect_init(int (* _Nonnull callback)(void))
160 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.4, 10.8, "it does nothing");
161
162 #if __OBJC2__
163 // Copies the list of currently realized classes
164 // intended for introspection only
165 // most users will want objc_copyClassList instead.
166 OBJC_EXPORT
167 Class _Nonnull * _Nullable
168 objc_copyRealizedClassList(unsigned int *_Nullable outCount)
169 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
170
171 typedef struct objc_imp_cache_entry {
172 SEL _Nonnull sel;
173 IMP _Nonnull imp;
174 } objc_imp_cache_entry;
175
176 OBJC_EXPORT
177 objc_imp_cache_entry *_Nullable
178 class_copyImpCache(Class _Nonnull cls, int * _Nullable outCount)
179 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
180
181 OBJC_EXPORT
182 unsigned long
183 sel_hash(SEL _Nullable sel)
184 OBJC_AVAILABLE(10.16, 14.0, 14.0, 7.0, 6.0);
185 #endif
186
187
188 // Plainly-implemented GC barriers. Rosetta used to use these.
189 OBJC_EXPORT id _Nullable
190 objc_assign_strongCast_generic(id _Nullable value, id _Nullable * _Nonnull dest)
191 UNAVAILABLE_ATTRIBUTE;
192
193 OBJC_EXPORT id _Nullable
194 objc_assign_global_generic(id _Nullable value, id _Nullable * _Nonnull dest)
195 UNAVAILABLE_ATTRIBUTE;
196
197 OBJC_EXPORT id _Nullable
198 objc_assign_threadlocal_generic(id _Nullable value,
199 id _Nullable * _Nonnull dest)
200 UNAVAILABLE_ATTRIBUTE;
201
202 OBJC_EXPORT id _Nullable
203 objc_assign_ivar_generic(id _Nullable value, id _Nonnull dest, ptrdiff_t offset)
204 UNAVAILABLE_ATTRIBUTE;
205
206 // GC preflight for an app executable.
207 // 1: some slice requires GC
208 // 0: no slice requires GC
209 // -1: I/O or file format error
210 OBJC_EXPORT int
211 objc_appRequiresGC(int fd)
212 __OSX_AVAILABLE(10.11)
213 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
214 __WATCHOS_UNAVAILABLE
215 #ifndef __APPLE_BLEACH_SDK__
216 __BRIDGEOS_UNAVAILABLE
217 #endif
218 ;
219
220 // Install missing-class callback. Used by the late unlamented ZeroLink.
221 OBJC_EXPORT void
222 _objc_setClassLoader(BOOL (* _Nonnull newClassLoader)(const char * _Nonnull))
223 OBJC2_UNAVAILABLE;
224
225 #if !(TARGET_OS_OSX && !TARGET_OS_MACCATALYST && __i386__)
226 // Add a class copy fixup handler. The name is a misnomer, as
227 // multiple calls will install multiple handlers. Older versions
228 // of the Swift runtime call it by name, and it's only used by Swift
229 // so it's not worth deprecating this name in favor of a better one.
230 OBJC_EXPORT void
231 _objc_setClassCopyFixupHandler(void (* _Nonnull newFixupHandler)
232 (Class _Nonnull oldClass, Class _Nonnull newClass))
233 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
234 #endif
235
236 // Install handler for allocation failures.
237 // Handler may abort, or throw, or provide an object to return.
238 OBJC_EXPORT void
239 _objc_setBadAllocHandler(id _Nullable (* _Nonnull newHandler)
240 (Class _Nullable isa))
241 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
242
243 // Used by ExceptionHandling.framework
244 #if !__OBJC2__
245 OBJC_EXPORT void
246 _objc_error(id _Nullable rcv, const char * _Nonnull fmt, va_list args)
247 __attribute__((noreturn, cold))
248 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.0, 10.5, "use other logging facilities instead");
249
250 #endif
251
252
253 /**
254 * Returns the names of all the classes within a library.
255 *
256 * @param image The mach header for library or framework you are inquiring about.
257 * @param outCount The number of class names returned.
258 *
259 * @return An array of C strings representing the class names.
260 */
261 OBJC_EXPORT const char * _Nonnull * _Nullable
262 objc_copyClassNamesForImageHeader(const struct mach_header * _Nonnull mh,
263 unsigned int * _Nullable outCount)
264 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
265
266 /**
267 * Returns the all the classes within a library.
268 *
269 * @param image The mach header for library or framework you are inquiring about.
270 * @param outCount The number of class names returned.
271 *
272 * @return An array of Class objects
273 */
274
275 OBJC_EXPORT Class _Nonnull * _Nullable
276 objc_copyClassesForImage(const char * _Nonnull image,
277 unsigned int * _Nullable outCount)
278 OBJC_AVAILABLE(10.16, 14.0, 14.0, 7.0, 4.0);
279
280
281 // Tagged pointer objects.
282
283 #if __LP64__
284 #define OBJC_HAVE_TAGGED_POINTERS 1
285 #endif
286
287 #if OBJC_HAVE_TAGGED_POINTERS
288
289 // Tagged pointer layout and usage is subject to change on different OS versions.
290
291 // Tag indexes 0..<7 have a 60-bit payload.
292 // Tag index 7 is reserved.
293 // Tag indexes 8..<264 have a 52-bit payload.
294 // Tag index 264 is reserved.
295
296 #if __has_feature(objc_fixed_enum) || __cplusplus >= 201103L
297 enum objc_tag_index_t : uint16_t
298 #else
299 typedef uint16_t objc_tag_index_t;
300 enum
301 #endif
302 {
303 // 60-bit payloads
304 OBJC_TAG_NSAtom = 0,
305 OBJC_TAG_1 = 1,
306 OBJC_TAG_NSString = 2,
307 OBJC_TAG_NSNumber = 3,
308 OBJC_TAG_NSIndexPath = 4,
309 OBJC_TAG_NSManagedObjectID = 5,
310 OBJC_TAG_NSDate = 6,
311
312 // 60-bit reserved
313 OBJC_TAG_RESERVED_7 = 7,
314
315 // 52-bit payloads
316 OBJC_TAG_Photos_1 = 8,
317 OBJC_TAG_Photos_2 = 9,
318 OBJC_TAG_Photos_3 = 10,
319 OBJC_TAG_Photos_4 = 11,
320 OBJC_TAG_XPC_1 = 12,
321 OBJC_TAG_XPC_2 = 13,
322 OBJC_TAG_XPC_3 = 14,
323 OBJC_TAG_XPC_4 = 15,
324 OBJC_TAG_NSColor = 16,
325 OBJC_TAG_UIColor = 17,
326 OBJC_TAG_CGColor = 18,
327 OBJC_TAG_NSIndexSet = 19,
328 OBJC_TAG_NSMethodSignature = 20,
329 OBJC_TAG_UTTypeRecord = 21,
330
331 // When using the split tagged pointer representation
332 // (OBJC_SPLIT_TAGGED_POINTERS), this is the first tag where
333 // the tag and payload are unobfuscated. All tags from here to
334 // OBJC_TAG_Last52BitPayload are unobfuscated. The shared cache
335 // builder is able to construct these as long as the low bit is
336 // not set (i.e. even-numbered tags).
337 OBJC_TAG_FirstUnobfuscatedSplitTag = 136, // 128 + 8, first ext tag with high bit set
338
339 OBJC_TAG_Constant_CFString = 136,
340
341 OBJC_TAG_First60BitPayload = 0,
342 OBJC_TAG_Last60BitPayload = 6,
343 OBJC_TAG_First52BitPayload = 8,
344 OBJC_TAG_Last52BitPayload = 263,
345
346 OBJC_TAG_RESERVED_264 = 264
347 };
348 #if __has_feature(objc_fixed_enum) && !defined(__cplusplus)
349 typedef enum objc_tag_index_t objc_tag_index_t;
350 #endif
351
352
353 // Returns true if tagged pointers are enabled.
354 // The other functions below must not be called if tagged pointers are disabled.
355 static inline bool
356 _objc_taggedPointersEnabled(void);
357
358 // Register a class for a tagged pointer tag.
359 // Aborts if the tag is invalid or already in use.
360 OBJC_EXPORT void
361 _objc_registerTaggedPointerClass(objc_tag_index_t tag, Class _Nonnull cls)
362 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
363
364 // Returns the registered class for the given tag.
365 // Returns nil if the tag is valid but has no registered class.
366 // Aborts if the tag is invalid.
367 OBJC_EXPORT Class _Nullable
368 _objc_getClassForTag(objc_tag_index_t tag)
369 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
370
371 // Create a tagged pointer object with the given tag and payload.
372 // Assumes the tag is valid.
373 // Assumes tagged pointers are enabled.
374 // The payload will be silently truncated to fit.
375 static inline void * _Nonnull
376 _objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t payload);
377
378 // Return true if ptr is a tagged pointer object.
379 // Does not check the validity of ptr's class.
380 static inline bool
381 _objc_isTaggedPointer(const void * _Nullable ptr);
382
383 // Extract the tag value from the given tagged pointer object.
384 // Assumes ptr is a valid tagged pointer object.
385 // Does not check the validity of ptr's tag.
386 static inline objc_tag_index_t
387 _objc_getTaggedPointerTag(const void * _Nullable ptr);
388
389 // Extract the payload from the given tagged pointer object.
390 // Assumes ptr is a valid tagged pointer object.
391 // The payload value is zero-extended.
392 static inline uintptr_t
393 _objc_getTaggedPointerValue(const void * _Nullable ptr);
394
395 // Extract the payload from the given tagged pointer object.
396 // Assumes ptr is a valid tagged pointer object.
397 // The payload value is sign-extended.
398 static inline intptr_t
399 _objc_getTaggedPointerSignedValue(const void * _Nullable ptr);
400
401 // Don't use the values below. Use the declarations above.
402
403 #if __arm64__
404 // ARM64 uses a new tagged pointer scheme where normal tags are in
405 // the low bits, extended tags are in the high bits, and half of the
406 // extended tag space is reserved for unobfuscated payloads.
407 # define OBJC_SPLIT_TAGGED_POINTERS 1
408 #else
409 # define OBJC_SPLIT_TAGGED_POINTERS 0
410 #endif
411
412 #if (TARGET_OS_OSX || TARGET_OS_MACCATALYST) && __x86_64__
413 // 64-bit Mac - tag bit is LSB
414 # define OBJC_MSB_TAGGED_POINTERS 0
415 #else
416 // Everything else - tag bit is MSB
417 # define OBJC_MSB_TAGGED_POINTERS 1
418 #endif
419
420 #define _OBJC_TAG_INDEX_MASK 0x7UL
421
422 #if OBJC_SPLIT_TAGGED_POINTERS
423 #define _OBJC_TAG_SLOT_COUNT 8
424 #define _OBJC_TAG_SLOT_MASK 0x7UL
425 #else
426 // array slot includes the tag bit itself
427 #define _OBJC_TAG_SLOT_COUNT 16
428 #define _OBJC_TAG_SLOT_MASK 0xfUL
429 #endif
430
431 #define _OBJC_TAG_EXT_INDEX_MASK 0xff
432 // array slot has no extra bits
433 #define _OBJC_TAG_EXT_SLOT_COUNT 256
434 #define _OBJC_TAG_EXT_SLOT_MASK 0xff
435
436 #if OBJC_SPLIT_TAGGED_POINTERS
437 # define _OBJC_TAG_MASK (1UL<<63)
438 # define _OBJC_TAG_INDEX_SHIFT 0
439 # define _OBJC_TAG_SLOT_SHIFT 0
440 # define _OBJC_TAG_PAYLOAD_LSHIFT 1
441 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
442 # define _OBJC_TAG_EXT_MASK (_OBJC_TAG_MASK | 0x7UL)
443 # define _OBJC_TAG_NO_OBFUSCATION_MASK ((1UL<<62) | _OBJC_TAG_EXT_MASK)
444 # define _OBJC_TAG_CONSTANT_POINTER_MASK \
445 ~(_OBJC_TAG_EXT_MASK | ((uintptr_t)_OBJC_TAG_EXT_SLOT_MASK << _OBJC_TAG_EXT_SLOT_SHIFT))
446 # define _OBJC_TAG_EXT_INDEX_SHIFT 55
447 # define _OBJC_TAG_EXT_SLOT_SHIFT 55
448 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 9
449 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
450 #elif OBJC_MSB_TAGGED_POINTERS
451 # define _OBJC_TAG_MASK (1UL<<63)
452 # define _OBJC_TAG_INDEX_SHIFT 60
453 # define _OBJC_TAG_SLOT_SHIFT 60
454 # define _OBJC_TAG_PAYLOAD_LSHIFT 4
455 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
456 # define _OBJC_TAG_EXT_MASK (0xfUL<<60)
457 # define _OBJC_TAG_EXT_INDEX_SHIFT 52
458 # define _OBJC_TAG_EXT_SLOT_SHIFT 52
459 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 12
460 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
461 #else
462 # define _OBJC_TAG_MASK 1UL
463 # define _OBJC_TAG_INDEX_SHIFT 1
464 # define _OBJC_TAG_SLOT_SHIFT 0
465 # define _OBJC_TAG_PAYLOAD_LSHIFT 0
466 # define _OBJC_TAG_PAYLOAD_RSHIFT 4
467 # define _OBJC_TAG_EXT_MASK 0xfUL
468 # define _OBJC_TAG_EXT_INDEX_SHIFT 4
469 # define _OBJC_TAG_EXT_SLOT_SHIFT 4
470 # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 0
471 # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
472 #endif
473
474 // Map of tags to obfuscated tags.
475 extern uintptr_t objc_debug_taggedpointer_obfuscator;
476
477 #if OBJC_SPLIT_TAGGED_POINTERS
478 extern uint8_t objc_debug_tag60_permutations[8];
479
480 static inline uintptr_t _objc_basicTagToObfuscatedTag(uintptr_t tag) {
481 return objc_debug_tag60_permutations[tag];
482 }
483
484 static inline uintptr_t _objc_obfuscatedTagToBasicTag(uintptr_t tag) {
485 for (unsigned i = 0; i < 7; i++)
486 if (objc_debug_tag60_permutations[i] == tag)
487 return i;
488 return 7;
489 }
490 #endif
491
492 static inline void * _Nonnull
493 _objc_encodeTaggedPointer(uintptr_t ptr)
494 {
495 uintptr_t value = (objc_debug_taggedpointer_obfuscator ^ ptr);
496 #if OBJC_SPLIT_TAGGED_POINTERS
497 if ((value & _OBJC_TAG_NO_OBFUSCATION_MASK) == _OBJC_TAG_NO_OBFUSCATION_MASK)
498 return (void *)ptr;
499 uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
500 uintptr_t permutedTag = _objc_basicTagToObfuscatedTag(basicTag);
501 value &= ~(_OBJC_TAG_INDEX_MASK << _OBJC_TAG_INDEX_SHIFT);
502 value |= permutedTag << _OBJC_TAG_INDEX_SHIFT;
503 #endif
504 return (void *)value;
505 }
506
507 static inline uintptr_t
508 _objc_decodeTaggedPointer_noPermute(const void * _Nullable ptr)
509 {
510 uintptr_t value = (uintptr_t)ptr;
511 #if OBJC_SPLIT_TAGGED_POINTERS
512 if ((value & _OBJC_TAG_NO_OBFUSCATION_MASK) == _OBJC_TAG_NO_OBFUSCATION_MASK)
513 return value;
514 #endif
515 return value ^ objc_debug_taggedpointer_obfuscator;
516 }
517
518 static inline uintptr_t
519 _objc_decodeTaggedPointer(const void * _Nullable ptr)
520 {
521 uintptr_t value = _objc_decodeTaggedPointer_noPermute(ptr);
522 #if OBJC_SPLIT_TAGGED_POINTERS
523 uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
524
525 value &= ~(_OBJC_TAG_INDEX_MASK << _OBJC_TAG_INDEX_SHIFT);
526 value |= _objc_obfuscatedTagToBasicTag(basicTag) << _OBJC_TAG_INDEX_SHIFT;
527 #endif
528 return value;
529 }
530
531 static inline bool
532 _objc_taggedPointersEnabled(void)
533 {
534 extern uintptr_t objc_debug_taggedpointer_mask;
535 return (objc_debug_taggedpointer_mask != 0);
536 }
537
538 static inline void * _Nonnull
539 _objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t value)
540 {
541 // PAYLOAD_LSHIFT and PAYLOAD_RSHIFT are the payload extraction shifts.
542 // They are reversed here for payload insertion.
543
544 // ASSERT(_objc_taggedPointersEnabled());
545 if (tag <= OBJC_TAG_Last60BitPayload) {
546 // ASSERT(((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT) == value);
547 uintptr_t result =
548 (_OBJC_TAG_MASK |
549 ((uintptr_t)tag << _OBJC_TAG_INDEX_SHIFT) |
550 ((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT));
551 return _objc_encodeTaggedPointer(result);
552 } else {
553 // ASSERT(tag >= OBJC_TAG_First52BitPayload);
554 // ASSERT(tag <= OBJC_TAG_Last52BitPayload);
555 // ASSERT(((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT) == value);
556 uintptr_t result =
557 (_OBJC_TAG_EXT_MASK |
558 ((uintptr_t)(tag - OBJC_TAG_First52BitPayload) << _OBJC_TAG_EXT_INDEX_SHIFT) |
559 ((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT));
560 return _objc_encodeTaggedPointer(result);
561 }
562 }
563
564 static inline bool
565 _objc_isTaggedPointer(const void * _Nullable ptr)
566 {
567 return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
568 }
569
570 static inline bool
571 _objc_isTaggedPointerOrNil(const void * _Nullable ptr)
572 {
573 // this function is here so that clang can turn this into
574 // a comparison with NULL when this is appropriate
575 // it turns out it's not able to in many cases without this
576 return !ptr || ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
577 }
578
579 static inline objc_tag_index_t
580 _objc_getTaggedPointerTag(const void * _Nullable ptr)
581 {
582 // ASSERT(_objc_isTaggedPointer(ptr));
583 uintptr_t value = _objc_decodeTaggedPointer(ptr);
584 uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
585 uintptr_t extTag = (value >> _OBJC_TAG_EXT_INDEX_SHIFT) & _OBJC_TAG_EXT_INDEX_MASK;
586 if (basicTag == _OBJC_TAG_INDEX_MASK) {
587 return (objc_tag_index_t)(extTag + OBJC_TAG_First52BitPayload);
588 } else {
589 return (objc_tag_index_t)basicTag;
590 }
591 }
592
593 static inline uintptr_t
594 _objc_getTaggedPointerValue(const void * _Nullable ptr)
595 {
596 // ASSERT(_objc_isTaggedPointer(ptr));
597 uintptr_t value = _objc_decodeTaggedPointer_noPermute(ptr);
598 uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
599 if (basicTag == _OBJC_TAG_INDEX_MASK) {
600 return (value << _OBJC_TAG_EXT_PAYLOAD_LSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
601 } else {
602 return (value << _OBJC_TAG_PAYLOAD_LSHIFT) >> _OBJC_TAG_PAYLOAD_RSHIFT;
603 }
604 }
605
606 static inline intptr_t
607 _objc_getTaggedPointerSignedValue(const void * _Nullable ptr)
608 {
609 // ASSERT(_objc_isTaggedPointer(ptr));
610 uintptr_t value = _objc_decodeTaggedPointer_noPermute(ptr);
611 uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
612 if (basicTag == _OBJC_TAG_INDEX_MASK) {
613 return ((intptr_t)value << _OBJC_TAG_EXT_PAYLOAD_LSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
614 } else {
615 return ((intptr_t)value << _OBJC_TAG_PAYLOAD_LSHIFT) >> _OBJC_TAG_PAYLOAD_RSHIFT;
616 }
617 }
618
619 # if OBJC_SPLIT_TAGGED_POINTERS
620 static inline void * _Nullable
621 _objc_getTaggedPointerRawPointerValue(const void * _Nullable ptr) {
622 return (void *)((uintptr_t)ptr & _OBJC_TAG_CONSTANT_POINTER_MASK);
623 }
624 # endif
625
626 // OBJC_HAVE_TAGGED_POINTERS
627 #endif
628
629
630 /**
631 * Returns the method implementation of an object.
632 *
633 * @param obj An Objective-C object.
634 * @param name An Objective-C selector.
635 *
636 * @return The IMP corresponding to the instance method implemented by
637 * the class of \e obj.
638 *
639 * @note Equivalent to:
640 *
641 * class_getMethodImplementation(object_getClass(obj), name);
642 */
643 OBJC_EXPORT IMP _Nonnull
644 object_getMethodImplementation(id _Nullable obj, SEL _Nonnull name)
645 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
646
647 OBJC_EXPORT IMP _Nonnull
648 object_getMethodImplementation_stret(id _Nullable obj, SEL _Nonnull name)
649 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0)
650 OBJC_ARM64_UNAVAILABLE;
651
652
653 /**
654 * Adds multiple methods to a class in bulk. This amortizes overhead that can be
655 * expensive when adding methods one by one with class_addMethod.
656 *
657 * @param cls The class to which to add the methods.
658 * @param names An array of selectors for the methods to add.
659 * @param imps An array of functions which implement the new methods.
660 * @param types An array of strings that describe the types of each method's
661 * arguments.
662 * @param count The number of items in the names, imps, and types arrays.
663 * @param outFiledCount Upon return, contains the number of failed selectors in
664 * the returned array.
665 *
666 * @return A NULL-terminated C array of selectors which could not be added. A
667 * method cannot be added when a method of that name already exists on that
668 * class. When no failures occur, the return value is \c NULL. When a non-NULL
669 * value is returned, the caller must free the array with \c free().
670 *
671 */
672 #if __OBJC2__
673 OBJC_EXPORT _Nullable SEL * _Nullable
674 class_addMethodsBulk(_Nullable Class cls, _Nonnull const SEL * _Nonnull names,
675 _Nonnull const IMP * _Nonnull imps,
676 const char * _Nonnull * _Nonnull types, uint32_t count,
677 uint32_t * _Nullable outFailedCount)
678 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
679 #endif
680
681 /**
682 * Replaces multiple methods in a class in bulk. This amortizes overhead that
683 * can be expensive when adding methods one by one with class_replaceMethod.
684 *
685 * @param cls The class to modify.
686 * @param names An array of selectors for the methods to replace.
687 * @param imps An array of functions will be the new method implementantations.
688 * @param types An array of strings that describe the types of each method's
689 * arguments.
690 * @param count The number of items in the names, imps, and types arrays.
691 */
692 #if __OBJC2__
693 OBJC_EXPORT void
694 class_replaceMethodsBulk(_Nullable Class cls,
695 _Nonnull const SEL * _Nonnull names,
696 _Nonnull const IMP * _Nonnull imps,
697 const char * _Nonnull * _Nonnull types,
698 uint32_t count)
699 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
700 #endif
701
702
703 // Instance-specific instance variable layout. This is no longer implemented.
704
705 OBJC_EXPORT void
706 _class_setIvarLayoutAccessor(Class _Nullable cls,
707 const uint8_t* _Nullable (* _Nonnull accessor)
708 (id _Nullable object))
709 UNAVAILABLE_ATTRIBUTE;
710
711 OBJC_EXPORT const uint8_t * _Nullable
712 _object_getIvarLayout(Class _Nullable cls, id _Nullable object)
713 UNAVAILABLE_ATTRIBUTE;
714
715
716 /*
717 "Unknown" includes non-object ivars and non-ARC non-__weak ivars
718 "Strong" includes ARC __strong ivars
719 "Weak" includes ARC and new MRC __weak ivars
720 "Unretained" includes ARC __unsafe_unretained and old GC+MRC __weak ivars
721 */
722 typedef enum {
723 objc_ivar_memoryUnknown, // unknown / unknown
724 objc_ivar_memoryStrong, // direct access / objc_storeStrong
725 objc_ivar_memoryWeak, // objc_loadWeak[Retained] / objc_storeWeak
726 objc_ivar_memoryUnretained // direct access / direct access
727 } objc_ivar_memory_management_t;
728
729 OBJC_EXPORT objc_ivar_memory_management_t
730 _class_getIvarMemoryManagement(Class _Nullable cls, Ivar _Nonnull ivar)
731 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
732
733 OBJC_EXPORT BOOL _class_isFutureClass(Class _Nullable cls)
734 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
735
736 /// Returns true if the class is an ABI stable Swift class. (Despite
737 /// the name, this does NOT return true for Swift classes built with
738 /// Swift versions prior to 5.0.)
739 OBJC_EXPORT BOOL _class_isSwift(Class _Nullable cls)
740 OBJC_AVAILABLE(10.16, 14.0, 14.0, 7.0, 5.0);
741
742 // API to only be called by root classes like NSObject or NSProxy
743
744 OBJC_EXPORT
745 id _Nonnull
746 _objc_rootRetain(id _Nonnull obj)
747 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
748
749 OBJC_EXPORT
750 void
751 _objc_rootRelease(id _Nonnull obj)
752 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
753
754 OBJC_EXPORT
755 bool
756 _objc_rootReleaseWasZero(id _Nonnull obj)
757 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
758
759 OBJC_EXPORT
760 bool
761 _objc_rootTryRetain(id _Nonnull obj)
762 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
763
764 OBJC_EXPORT
765 bool
766 _objc_rootIsDeallocating(id _Nonnull obj)
767 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
768
769 OBJC_EXPORT
770 id _Nonnull
771 _objc_rootAutorelease(id _Nonnull obj)
772 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
773
774 OBJC_EXPORT
775 uintptr_t
776 _objc_rootRetainCount(id _Nonnull obj)
777 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
778
779 OBJC_EXPORT
780 id _Nonnull
781 _objc_rootInit(id _Nonnull obj)
782 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
783
784 OBJC_EXPORT
785 id _Nullable
786 _objc_rootAllocWithZone(Class _Nonnull cls, malloc_zone_t * _Nullable zone)
787 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
788
789 OBJC_EXPORT
790 id _Nullable
791 _objc_rootAlloc(Class _Nonnull cls)
792 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
793
794 OBJC_EXPORT
795 void
796 _objc_rootDealloc(id _Nonnull obj)
797 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
798
799 OBJC_EXPORT
800 void
801 _objc_rootFinalize(id _Nonnull obj)
802 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
803
804 OBJC_EXPORT
805 malloc_zone_t * _Nonnull
806 _objc_rootZone(id _Nonnull obj)
807 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
808
809 OBJC_EXPORT
810 uintptr_t
811 _objc_rootHash(id _Nonnull obj)
812 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
813
814 OBJC_EXPORT
815 void * _Nonnull
816 objc_autoreleasePoolPush(void)
817 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
818
819 OBJC_EXPORT
820 void
821 objc_autoreleasePoolPop(void * _Nonnull context)
822 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
823
824
825 OBJC_EXPORT id _Nullable
826 objc_alloc(Class _Nullable cls)
827 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
828
829 OBJC_EXPORT id _Nullable
830 objc_allocWithZone(Class _Nullable cls)
831 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
832
833 OBJC_EXPORT id _Nullable
834 objc_alloc_init(Class _Nullable cls)
835 OBJC_AVAILABLE(10.14.4, 12.2, 12.2, 5.2, 3.2);
836
837 OBJC_EXPORT id _Nullable
838 objc_opt_new(Class _Nullable cls)
839 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
840
841 OBJC_EXPORT id _Nullable
842 objc_opt_self(id _Nullable obj)
843 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
844
845 OBJC_EXPORT Class _Nullable
846 objc_opt_class(id _Nullable obj)
847 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
848
849 OBJC_EXPORT BOOL
850 objc_opt_respondsToSelector(id _Nullable obj, SEL _Nullable sel)
851 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
852
853 OBJC_EXPORT BOOL
854 objc_opt_isKindOfClass(id _Nullable obj, Class _Nullable cls)
855 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
856
857
858 OBJC_EXPORT BOOL
859 objc_sync_try_enter(id _Nonnull obj)
860 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
861
862 OBJC_EXPORT id _Nullable
863 objc_retain(id _Nullable obj)
864 __asm__("_objc_retain")
865 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
866
867 OBJC_EXPORT void
868 objc_release(id _Nullable obj)
869 __asm__("_objc_release")
870 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
871
872 OBJC_EXPORT id _Nullable
873 objc_autorelease(id _Nullable obj)
874 __asm__("_objc_autorelease")
875 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
876
877 // Prepare a value at +1 for return through a +0 autoreleasing convention.
878 OBJC_EXPORT id _Nullable
879 objc_autoreleaseReturnValue(id _Nullable obj)
880 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
881
882 // Prepare a value at +0 for return through a +0 autoreleasing convention.
883 OBJC_EXPORT id _Nullable
884 objc_retainAutoreleaseReturnValue(id _Nullable obj)
885 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
886
887 // Accept a value returned through a +0 autoreleasing convention for use at +1.
888 OBJC_EXPORT id _Nullable
889 objc_retainAutoreleasedReturnValue(id _Nullable obj)
890 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
891
892 // Accept a value returned through a +0 autoreleasing convention for use at +0.
893 OBJC_EXPORT id _Nullable
894 objc_unsafeClaimAutoreleasedReturnValue(id _Nullable obj)
895 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
896
897 OBJC_EXPORT void
898 objc_storeStrong(id _Nullable * _Nonnull location, id _Nullable obj)
899 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
900
901 OBJC_EXPORT id _Nullable
902 objc_retainAutorelease(id _Nullable obj)
903 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
904
905 // obsolete.
906 OBJC_EXPORT id _Nullable
907 objc_retain_autorelease(id _Nullable obj)
908 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
909
910 OBJC_EXPORT id _Nullable
911 objc_loadWeakRetained(id _Nullable * _Nonnull location)
912 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
913
914 OBJC_EXPORT id _Nullable
915 objc_initWeak(id _Nullable * _Nonnull location, id _Nullable val)
916 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
917
918 // Like objc_storeWeak, but stores nil if the new object is deallocating
919 // or the new object's class does not support weak references.
920 // Returns the value stored (either the new object or nil).
921 OBJC_EXPORT id _Nullable
922 objc_storeWeakOrNil(id _Nullable * _Nonnull location, id _Nullable obj)
923 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
924
925 // Like objc_initWeak, but stores nil if the new object is deallocating
926 // or the new object's class does not support weak references.
927 // Returns the value stored (either the new object or nil).
928 OBJC_EXPORT id _Nullable
929 objc_initWeakOrNil(id _Nullable * _Nonnull location, id _Nullable val)
930 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
931
932 OBJC_EXPORT void
933 objc_destroyWeak(id _Nullable * _Nonnull location)
934 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
935
936 OBJC_EXPORT void
937 objc_copyWeak(id _Nullable * _Nonnull to, id _Nullable * _Nonnull from)
938 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
939
940 OBJC_EXPORT void
941 objc_moveWeak(id _Nullable * _Nonnull to, id _Nullable * _Nonnull from)
942 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
943
944
945 OBJC_EXPORT void
946 _objc_autoreleasePoolPrint(void)
947 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
948
949 OBJC_EXPORT BOOL
950 objc_should_deallocate(id _Nonnull object)
951 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
952
953 OBJC_EXPORT void
954 objc_clear_deallocating(id _Nonnull object)
955 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
956
957
958 // to make CF link for now
959
960 OBJC_EXPORT void * _Nonnull
961 _objc_autoreleasePoolPush(void)
962 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
963
964 OBJC_EXPORT void
965 _objc_autoreleasePoolPop(void * _Nonnull context)
966 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
967
968
969 /**
970 * Load a classref, which is a chunk of data containing a class
971 * pointer. May perform initialization and rewrite the classref to
972 * point to a new object, if needed. Returns the loaded Class.
973 *
974 * In particular, if the classref points to a stub class (indicated
975 * by setting the bottom bit of the class pointer to 1), then this
976 * will call the stub's initializer and then replace the classref
977 * value with the value returned by the initializer.
978 *
979 * @param clsref The classref to load.
980 * @return The loaded Class pointer.
981 */
982 #if __OBJC2__
983 OBJC_EXPORT _Nullable Class
984 objc_loadClassref(_Nullable Class * _Nonnull clsref)
985 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
986 #endif
987
988
989 // Extra @encode data for XPC, or NULL
990 OBJC_EXPORT const char * _Nullable
991 _protocol_getMethodTypeEncoding(Protocol * _Nonnull proto, SEL _Nonnull sel,
992 BOOL isRequiredMethod, BOOL isInstanceMethod)
993 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
994
995
996 /**
997 * Function type for a function that is called when a realized class
998 * is about to be initialized.
999 *
1000 * @param context The context pointer the function was registered with.
1001 * @param cls The class that's about to be initialized.
1002 */
1003 struct mach_header;
1004 typedef void (*_objc_func_willInitializeClass)(void * _Nullable context, Class _Nonnull cls);
1005
1006 /**
1007 * Add a function to be called when a realized class is about to be
1008 * initialized. The class can be queried and manipulated using runtime
1009 * functions. Don't message it.
1010 *
1011 * When adding a new function, that function is immediately called with all
1012 * realized classes that are already initialized or are in the process
1013 * of initialization.
1014 *
1015 * @param func The function to add.
1016 * @param context A context pointer that will be passed to the function when called.
1017 */
1018 #define OBJC_WILLINITIALIZECLASSFUNC_DEFINED 1
1019 OBJC_EXPORT void _objc_addWillInitializeClassFunc(_objc_func_willInitializeClass _Nonnull func, void * _Nullable context)
1020 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 4.0);
1021
1022 // Replicate the conditionals in objc-config.h for packed isa, indexed isa, and preopt caches
1023 #if __ARM_ARCH_7K__ >= 2 || (__arm64__ && !__LP64__) || \
1024 !(!__LP64__ || TARGET_OS_WIN32 || \
1025 (TARGET_OS_SIMULATOR && !TARGET_OS_MACCATALYST && !__arm64__))
1026 OBJC_EXPORT const uintptr_t _objc_has_weak_formation_callout;
1027 #define OBJC_WEAK_FORMATION_CALLOUT_DEFINED 1
1028 #else
1029 #define OBJC_WEAK_FORMATION_CALLOUT_DEFINED 0
1030 #endif
1031
1032 #if defined(__arm64__) && TARGET_OS_IOS && !TARGET_OS_SIMULATOR && !TARGET_OS_MACCATALYST
1033 #define CONFIG_USE_PREOPT_CACHES 1
1034 #else
1035 #define CONFIG_USE_PREOPT_CACHES 0
1036 #endif
1037
1038
1039 #if __OBJC2__
1040 // Helper function for objc4 tests only! Do not call this yourself
1041 // for any reason ever.
1042 OBJC_EXPORT void _method_setImplementationRawUnsafe(Method _Nonnull m, IMP _Nonnull imp)
1043 OBJC_AVAILABLE(10.16, 14.0, 14.0, 7.0, 5.0);
1044 #endif
1045
1046 // API to only be called by classes that provide their own reference count storage
1047
1048 OBJC_EXPORT void
1049 _objc_deallocOnMainThreadHelper(void * _Nullable context)
1050 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
1051
1052 #if __OBJC__
1053 // Declarations for internal methods used for custom weak reference
1054 // implementations. These declarations ensure that the compiler knows
1055 // to exclude these methods from NS_DIRECT_MEMBERS. Do NOT implement
1056 // these methods unless you really know what you're doing.
1057 @interface NSObject ()
1058 - (BOOL)_tryRetain;
1059 - (BOOL)_isDeallocating;
1060 @end
1061 #endif
1062
1063 // On async versus sync deallocation and the _dealloc2main flag
1064 //
1065 // Theory:
1066 //
1067 // If order matters, then code must always: [self dealloc].
1068 // If order doesn't matter, then always async should be safe.
1069 //
1070 // Practice:
1071 //
1072 // The _dealloc2main bit is set for GUI objects that may be retained by other
1073 // threads. Once deallocation begins on the main thread, doing more async
1074 // deallocation will at best cause extra UI latency and at worst cause
1075 // use-after-free bugs in unretained delegate style patterns. Yes, this is
1076 // extremely fragile. Yes, in the long run, developers should switch to weak
1077 // references.
1078 //
1079 // Note is NOT safe to do any equality check against the result of
1080 // dispatch_get_current_queue(). The main thread can and does drain more than
1081 // one dispatch queue. That is why we call pthread_main_np().
1082 //
1083
1084 typedef enum {
1085 _OBJC_RESURRECT_OBJECT = -1, /* _logicBlock has called -retain, and scheduled a -release for later. */
1086 _OBJC_DEALLOC_OBJECT_NOW = 1, /* call [self dealloc] immediately. */
1087 _OBJC_DEALLOC_OBJECT_LATER = 2 /* call [self dealloc] on the main queue. */
1088 } _objc_object_disposition_t;
1089
1090 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \
1091 -(id)retain { \
1092 /* this will fail to compile if _rc_ivar is an unsigned type */ \
1093 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
1094 __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \
1095 if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \
1096 __builtin_trap(); /* BUG: retain of over-released ref */ \
1097 } \
1098 return self; \
1099 } \
1100 -(oneway void)release { \
1101 __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \
1102 if (_prev > 0) { \
1103 return; \
1104 } else if (_prev < 0) { \
1105 __builtin_trap(); /* BUG: over-release */ \
1106 } \
1107 _objc_object_disposition_t fate = _logicBlock(self); \
1108 if (fate == _OBJC_RESURRECT_OBJECT) { \
1109 return; \
1110 } \
1111 /* mark the object as deallocating. */ \
1112 if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \
1113 __builtin_trap(); /* BUG: dangling ref did a retain */ \
1114 } \
1115 if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \
1116 [self dealloc]; \
1117 } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \
1118 dispatch_barrier_async_f(dispatch_get_main_queue(), self, \
1119 _objc_deallocOnMainThreadHelper); \
1120 } else { \
1121 __builtin_trap(); /* BUG: bogus fate value */ \
1122 } \
1123 } \
1124 -(NSUInteger)retainCount { \
1125 return (NSUInteger)(_rc_ivar + 2) >> 1; \
1126 } \
1127 -(BOOL)_tryRetain { \
1128 __typeof__(_rc_ivar) _prev; \
1129 do { \
1130 _prev = _rc_ivar; \
1131 if (_prev & 1) { \
1132 return 0; \
1133 } else if (_prev == -2) { \
1134 return 0; \
1135 } else if (_prev < -2) { \
1136 __builtin_trap(); /* BUG: over-release elsewhere */ \
1137 } \
1138 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
1139 return 1; \
1140 } \
1141 -(BOOL)_isDeallocating { \
1142 if (_rc_ivar == -2) { \
1143 return 1; \
1144 } else if (_rc_ivar < -2) { \
1145 __builtin_trap(); /* BUG: over-release elsewhere */ \
1146 } \
1147 return (_rc_ivar & 1) != 0; \
1148 }
1149
1150 #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
1151 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
1152 if ((_dealloc2main) && !pthread_main_np()) { \
1153 return _OBJC_DEALLOC_OBJECT_LATER; \
1154 } else { \
1155 return _OBJC_DEALLOC_OBJECT_NOW; \
1156 } \
1157 }))
1158
1159 #define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0)
1160 #define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1)
1161
1162
1163 // C cache_t wrappers for objcdt and the IMP caches test tool
1164 struct cache_t;
1165 struct bucket_t;
1166 struct preopt_cache_t;
1167 OBJC_EXPORT struct bucket_t * _Nonnull objc_cache_buckets(const struct cache_t * _Nonnull cache);
1168 OBJC_EXPORT size_t objc_cache_bytesForCapacity(uint32_t cap);
1169 OBJC_EXPORT uint32_t objc_cache_occupied(const struct cache_t * _Nonnull cache);
1170 OBJC_EXPORT unsigned objc_cache_capacity(const struct cache_t * _Nonnull cache);
1171
1172 #if CONFIG_USE_PREOPT_CACHES
1173
1174 OBJC_EXPORT bool objc_cache_isConstantOptimizedCache(const struct cache_t * _Nonnull cache, bool strict, uintptr_t empty_addr);
1175 OBJC_EXPORT unsigned objc_cache_preoptCapacity(const struct cache_t * _Nonnull cache);
1176 OBJC_EXPORT Class _Nonnull objc_cache_preoptFallbackClass(const struct cache_t * _Nonnull cache);
1177 OBJC_EXPORT const struct preopt_cache_t * _Nonnull objc_cache_preoptCache(const struct cache_t * _Nonnull cache);
1178
1179 #endif
1180
1181 __END_DECLS
1182
1183 #endif