]> git.saurik.com Git - apple/objc4.git/blame - runtime/objc-internal.h
objc4-818.2.tar.gz
[apple/objc4.git] / runtime / objc-internal.h
CommitLineData
13d88034 1/*
8972963c 2 * Copyright (c) 2009 Apple Inc. All Rights Reserved.
13d88034 3 *
b3962a83 4 * @APPLE_LICENSE_HEADER_START@
390d5862
A
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.
13d88034
A
12 *
13 * The Original Code and all software distributed under the License are
390d5862 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
13d88034
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
390d5862
A
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.
13d88034
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
7af964d1
A
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.
13d88034
A
34 */
35
8972963c
A
36/*
37 * objc-internal.h: Private SPI for use by other system frameworks.
38 */
39
7af964d1 40#include <objc/objc.h>
7257e56c 41#include <objc/runtime.h>
7af964d1 42#include <Availability.h>
8972963c 43#include <malloc/malloc.h>
66799735 44#include <mach-o/loader.h>
8972963c 45#include <dispatch/dispatch.h>
7af964d1 46
34d5b5e8
A
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
8972963c 52
c1e772c4
A
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
8070259c
A
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
34d5b5e8
A
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)
66799735
A
74
75__BEGIN_DECLS
76
13ba007e
A
77// This symbol is exported only from debug builds of libobjc itself.
78#if defined(OBJC_IS_DEBUG_BUILD)
79OBJC_EXPORT void _objc_isDebugBuild(void);
80#endif
81
8972963c 82// In-place construction of an Objective-C class.
8070259c
A
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.
4a109af3
A
87OBJC_EXPORT Class _Nullable
88objc_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);
8972963c 91
8070259c
A
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__
101struct objc_image_info;
4a109af3
A
102OBJC_EXPORT Class _Nullable
103objc_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);
8070259c
A
106#endif
107
8972963c 108// Batch object allocation using malloc_zone_batch_malloc().
4a109af3
A
109OBJC_EXPORT unsigned
110class_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)
8972963c
A
113 OBJC_ARC_UNAVAILABLE;
114
115// Get the isa pointer written into objects just before being freed.
4a109af3
A
116OBJC_EXPORT Class _Nonnull
117_objc_getFreedObjectClass(void)
118 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
8972963c
A
119
120// env NSObjCMessageLoggingEnabled
4a109af3
A
121OBJC_EXPORT void
122instrumentObjcMessageSends(BOOL flag)
123 OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
8972963c 124
cd5f04f5 125// Initializer called by libSystem
4a109af3
A
126OBJC_EXPORT void
127_objc_init(void)
c1e772c4 128#if __OBJC2__
4a109af3 129 OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
c1e772c4 130#else
4a109af3 131 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
cd5f04f5
A
132#endif
133
bd8dfcfc 134// fork() safety called by libSystem
4a109af3
A
135OBJC_EXPORT void
136_objc_atfork_prepare(void)
137 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
138
139OBJC_EXPORT void
140_objc_atfork_parent(void)
141 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
142
143OBJC_EXPORT void
144_objc_atfork_child(void)
145 OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
bd8dfcfc 146
c1e772c4 147// Return YES if GC is on and `object` is a GC allocation.
4a109af3
A
148OBJC_EXPORT BOOL
149objc_isAuto(id _Nullable object)
1807f628 150 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.4, 10.8, "it always returns NO");
c1e772c4 151
66799735
A
152// GC debugging
153OBJC_EXPORT BOOL
154objc_dumpHeap(char * _Nonnull filename, unsigned long length)
1807f628 155 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.4, 10.8, "it always returns NO");
66799735 156
8972963c 157// GC startup callback from Foundation
4a109af3
A
158OBJC_EXPORT malloc_zone_t * _Nullable
159objc_collect_init(int (* _Nonnull callback)(void))
1807f628
A
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.
166OBJC_EXPORT
167Class _Nonnull * _Nullable
168objc_copyRealizedClassList(unsigned int *_Nullable outCount)
169 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
170
171typedef struct objc_imp_cache_entry {
172 SEL _Nonnull sel;
173 IMP _Nonnull imp;
174} objc_imp_cache_entry;
175
176OBJC_EXPORT
177objc_imp_cache_entry *_Nullable
178class_copyImpCache(Class _Nonnull cls, int * _Nullable outCount)
179 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
34d5b5e8
A
180
181OBJC_EXPORT
182unsigned long
183sel_hash(SEL _Nullable sel)
184 OBJC_AVAILABLE(10.16, 14.0, 14.0, 7.0, 6.0);
1807f628 185#endif
8972963c 186
34d5b5e8 187
8972963c 188// Plainly-implemented GC barriers. Rosetta used to use these.
4a109af3
A
189OBJC_EXPORT id _Nullable
190objc_assign_strongCast_generic(id _Nullable value, id _Nullable * _Nonnull dest)
8972963c 191 UNAVAILABLE_ATTRIBUTE;
4a109af3
A
192
193OBJC_EXPORT id _Nullable
194objc_assign_global_generic(id _Nullable value, id _Nullable * _Nonnull dest)
8972963c 195 UNAVAILABLE_ATTRIBUTE;
4a109af3
A
196
197OBJC_EXPORT id _Nullable
198objc_assign_threadlocal_generic(id _Nullable value,
199 id _Nullable * _Nonnull dest)
8972963c 200 UNAVAILABLE_ATTRIBUTE;
4a109af3
A
201
202OBJC_EXPORT id _Nullable
203objc_assign_ivar_generic(id _Nullable value, id _Nonnull dest, ptrdiff_t offset)
8972963c
A
204 UNAVAILABLE_ATTRIBUTE;
205
c1e772c4
A
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
4a109af3
A
210OBJC_EXPORT int
211objc_appRequiresGC(int fd)
c1e772c4 212 __OSX_AVAILABLE(10.11)
4a109af3 213 __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
1807f628
A
214 __WATCHOS_UNAVAILABLE
215#ifndef __APPLE_BLEACH_SDK__
216 __BRIDGEOS_UNAVAILABLE
217#endif
218;
c1e772c4 219
8972963c 220// Install missing-class callback. Used by the late unlamented ZeroLink.
4a109af3
A
221OBJC_EXPORT void
222_objc_setClassLoader(BOOL (* _Nonnull newClassLoader)(const char * _Nonnull))
223 OBJC2_UNAVAILABLE;
8972963c 224
34d5b5e8 225#if !(TARGET_OS_OSX && !TARGET_OS_MACCATALYST && __i386__)
1807f628
A
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.
66799735
A
230OBJC_EXPORT void
231_objc_setClassCopyFixupHandler(void (* _Nonnull newFixupHandler)
1807f628
A
232 (Class _Nonnull oldClass, Class _Nonnull newClass))
233 OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
66799735
A
234#endif
235
cd5f04f5
A
236// Install handler for allocation failures.
237// Handler may abort, or throw, or provide an object to return.
4a109af3
A
238OBJC_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);
cd5f04f5 242
8972963c
A
243// Used by ExceptionHandling.framework
244#if !__OBJC2__
4a109af3
A
245OBJC_EXPORT void
246_objc_error(id _Nullable rcv, const char * _Nonnull fmt, va_list args)
1807f628
A
247 __attribute__((noreturn, cold))
248 OBJC_OSX_DEPRECATED_OTHERS_UNAVAILABLE(10.0, 10.5, "use other logging facilities instead");
8972963c
A
249
250#endif
251
7257e56c 252
66799735
A
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 */
261OBJC_EXPORT const char * _Nonnull * _Nullable
262objc_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
34d5b5e8
A
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
275OBJC_EXPORT Class _Nonnull * _Nullable
276objc_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
7257e56c
A
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
c1e772c4
A
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.
7257e56c
A
295
296#if __has_feature(objc_fixed_enum) || __cplusplus >= 201103L
c1e772c4 297enum objc_tag_index_t : uint16_t
7257e56c 298#else
c1e772c4 299typedef uint16_t objc_tag_index_t;
7257e56c
A
300enum
301#endif
302{
66799735 303 // 60-bit payloads
7257e56c
A
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,
66799735
A
310 OBJC_TAG_NSDate = 6,
311
312 // 60-bit reserved
c1e772c4
A
313 OBJC_TAG_RESERVED_7 = 7,
314
66799735
A
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,
1807f628
A
324 OBJC_TAG_NSColor = 16,
325 OBJC_TAG_UIColor = 17,
326 OBJC_TAG_CGColor = 18,
327 OBJC_TAG_NSIndexSet = 19,
bc4fafce
A
328 OBJC_TAG_NSMethodSignature = 20,
329 OBJC_TAG_UTTypeRecord = 21,
66799735 330
34d5b5e8
A
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
c1e772c4
A
341 OBJC_TAG_First60BitPayload = 0,
342 OBJC_TAG_Last60BitPayload = 6,
343 OBJC_TAG_First52BitPayload = 8,
34d5b5e8 344 OBJC_TAG_Last52BitPayload = 263,
c1e772c4
A
345
346 OBJC_TAG_RESERVED_264 = 264
7257e56c
A
347};
348#if __has_feature(objc_fixed_enum) && !defined(__cplusplus)
349typedef enum objc_tag_index_t objc_tag_index_t;
350#endif
351
7257e56c 352
c1e772c4
A
353// Returns true if tagged pointers are enabled.
354// The other functions below must not be called if tagged pointers are disabled.
7257e56c 355static inline bool
c1e772c4 356_objc_taggedPointersEnabled(void);
7257e56c 357
c1e772c4
A
358// Register a class for a tagged pointer tag.
359// Aborts if the tag is invalid or already in use.
4a109af3
A
360OBJC_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);
c1e772c4
A
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.
4a109af3
A
367OBJC_EXPORT Class _Nullable
368_objc_getClassForTag(objc_tag_index_t tag)
369 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
8070259c 370
c1e772c4
A
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.
4a109af3 375static inline void * _Nonnull
c1e772c4 376_objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t payload);
8070259c 377
c1e772c4
A
378// Return true if ptr is a tagged pointer object.
379// Does not check the validity of ptr's class.
8070259c 380static inline bool
4a109af3 381_objc_isTaggedPointer(const void * _Nullable ptr);
8070259c 382
c1e772c4
A
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.
8070259c 386static inline objc_tag_index_t
4a109af3 387_objc_getTaggedPointerTag(const void * _Nullable ptr);
8070259c 388
c1e772c4
A
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.
8070259c 392static inline uintptr_t
4a109af3 393_objc_getTaggedPointerValue(const void * _Nullable ptr);
8070259c 394
c1e772c4
A
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.
8070259c 398static inline intptr_t
4a109af3 399_objc_getTaggedPointerSignedValue(const void * _Nullable ptr);
8070259c 400
c1e772c4
A
401// Don't use the values below. Use the declarations above.
402
34d5b5e8
A
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__
c1e772c4
A
413 // 64-bit Mac - tag bit is LSB
414# define OBJC_MSB_TAGGED_POINTERS 0
8070259c 415#else
c1e772c4
A
416 // Everything else - tag bit is MSB
417# define OBJC_MSB_TAGGED_POINTERS 1
418#endif
419
34d5b5e8
A
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
c1e772c4
A
426// array slot includes the tag bit itself
427#define _OBJC_TAG_SLOT_COUNT 16
34d5b5e8
A
428#define _OBJC_TAG_SLOT_MASK 0xfUL
429#endif
c1e772c4
A
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
34d5b5e8
A
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
4a109af3 451# define _OBJC_TAG_MASK (1UL<<63)
c1e772c4
A
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
4a109af3 456# define _OBJC_TAG_EXT_MASK (0xfUL<<60)
c1e772c4
A
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
4a109af3 462# define _OBJC_TAG_MASK 1UL
c1e772c4
A
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
4a109af3 467# define _OBJC_TAG_EXT_MASK 0xfUL
c1e772c4
A
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
34d5b5e8 474// Map of tags to obfuscated tags.
66799735
A
475extern uintptr_t objc_debug_taggedpointer_obfuscator;
476
34d5b5e8
A
477#if OBJC_SPLIT_TAGGED_POINTERS
478extern uint8_t objc_debug_tag60_permutations[8];
479
480static inline uintptr_t _objc_basicTagToObfuscatedTag(uintptr_t tag) {
481 return objc_debug_tag60_permutations[tag];
482}
483
484static 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
66799735
A
492static inline void * _Nonnull
493_objc_encodeTaggedPointer(uintptr_t ptr)
494{
34d5b5e8
A
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
507static 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;
66799735
A
516}
517
518static inline uintptr_t
519_objc_decodeTaggedPointer(const void * _Nullable ptr)
520{
34d5b5e8
A
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;
66799735
A
529}
530
34d5b5e8 531static inline bool
c1e772c4
A
532_objc_taggedPointersEnabled(void)
533{
534 extern uintptr_t objc_debug_taggedpointer_mask;
535 return (objc_debug_taggedpointer_mask != 0);
536}
8070259c 537
4a109af3 538static inline void * _Nonnull
7257e56c
A
539_objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t value)
540{
c1e772c4
A
541 // PAYLOAD_LSHIFT and PAYLOAD_RSHIFT are the payload extraction shifts.
542 // They are reversed here for payload insertion.
543
1807f628 544 // ASSERT(_objc_taggedPointersEnabled());
c1e772c4 545 if (tag <= OBJC_TAG_Last60BitPayload) {
1807f628 546 // ASSERT(((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT) == value);
66799735 547 uintptr_t result =
c1e772c4
A
548 (_OBJC_TAG_MASK |
549 ((uintptr_t)tag << _OBJC_TAG_INDEX_SHIFT) |
550 ((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT));
66799735 551 return _objc_encodeTaggedPointer(result);
c1e772c4 552 } else {
1807f628
A
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);
66799735 556 uintptr_t result =
c1e772c4
A
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));
66799735 560 return _objc_encodeTaggedPointer(result);
c1e772c4 561 }
7257e56c
A
562}
563
564static inline bool
66799735 565_objc_isTaggedPointer(const void * _Nullable ptr)
7257e56c 566{
4a109af3 567 return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
7257e56c
A
568}
569
34d5b5e8
A
570static 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
7257e56c 579static inline objc_tag_index_t
4a109af3 580_objc_getTaggedPointerTag(const void * _Nullable ptr)
7257e56c 581{
1807f628 582 // ASSERT(_objc_isTaggedPointer(ptr));
66799735
A
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;
c1e772c4
A
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 }
7257e56c
A
591}
592
593static inline uintptr_t
4a109af3 594_objc_getTaggedPointerValue(const void * _Nullable ptr)
7257e56c 595{
1807f628 596 // ASSERT(_objc_isTaggedPointer(ptr));
34d5b5e8 597 uintptr_t value = _objc_decodeTaggedPointer_noPermute(ptr);
66799735 598 uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
c1e772c4 599 if (basicTag == _OBJC_TAG_INDEX_MASK) {
66799735 600 return (value << _OBJC_TAG_EXT_PAYLOAD_LSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
c1e772c4 601 } else {
66799735 602 return (value << _OBJC_TAG_PAYLOAD_LSHIFT) >> _OBJC_TAG_PAYLOAD_RSHIFT;
c1e772c4 603 }
7257e56c
A
604}
605
606static inline intptr_t
4a109af3 607_objc_getTaggedPointerSignedValue(const void * _Nullable ptr)
7257e56c 608{
1807f628 609 // ASSERT(_objc_isTaggedPointer(ptr));
34d5b5e8 610 uintptr_t value = _objc_decodeTaggedPointer_noPermute(ptr);
66799735 611 uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
c1e772c4 612 if (basicTag == _OBJC_TAG_INDEX_MASK) {
66799735 613 return ((intptr_t)value << _OBJC_TAG_EXT_PAYLOAD_LSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
c1e772c4 614 } else {
66799735 615 return ((intptr_t)value << _OBJC_TAG_PAYLOAD_LSHIFT) >> _OBJC_TAG_PAYLOAD_RSHIFT;
c1e772c4 616 }
7257e56c
A
617}
618
34d5b5e8
A
619# if OBJC_SPLIT_TAGGED_POINTERS
620static 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
c1e772c4 626// OBJC_HAVE_TAGGED_POINTERS
8070259c
A
627#endif
628
7257e56c 629
7257e56c
A
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 */
4a109af3
A
643OBJC_EXPORT IMP _Nonnull
644object_getMethodImplementation(id _Nullable obj, SEL _Nonnull name)
645 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
7257e56c 646
4a109af3
A
647OBJC_EXPORT IMP _Nonnull
648object_getMethodImplementation_stret(id _Nullable obj, SEL _Nonnull name)
649 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0)
8070259c 650 OBJC_ARM64_UNAVAILABLE;
7257e56c
A
651
652
66799735
A
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__
673OBJC_EXPORT _Nullable SEL * _Nullable
674class_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__
693OBJC_EXPORT void
694class_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.
8972963c 704
4a109af3
A
705OBJC_EXPORT void
706_class_setIvarLayoutAccessor(Class _Nullable cls,
707 const uint8_t* _Nullable (* _Nonnull accessor)
708 (id _Nullable object))
66799735 709 UNAVAILABLE_ATTRIBUTE;
4a109af3
A
710
711OBJC_EXPORT const uint8_t * _Nullable
712_object_getIvarLayout(Class _Nullable cls, id _Nullable object)
66799735
A
713 UNAVAILABLE_ATTRIBUTE;
714
8972963c 715
c1e772c4
A
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*/
722typedef 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
4a109af3
A
729OBJC_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);
8972963c 732
4a109af3
A
733OBJC_EXPORT BOOL _class_isFutureClass(Class _Nullable cls)
734 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
c1e772c4 735
34d5b5e8
A
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.)
739OBJC_EXPORT BOOL _class_isSwift(Class _Nullable cls)
740 OBJC_AVAILABLE(10.16, 14.0, 14.0, 7.0, 5.0);
cd5f04f5 741
8972963c
A
742// API to only be called by root classes like NSObject or NSProxy
743
744OBJC_EXPORT
4a109af3
A
745id _Nonnull
746_objc_rootRetain(id _Nonnull obj)
747 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
748
749OBJC_EXPORT
750void
4a109af3
A
751_objc_rootRelease(id _Nonnull obj)
752 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
753
754OBJC_EXPORT
755bool
4a109af3
A
756_objc_rootReleaseWasZero(id _Nonnull obj)
757 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
758
759OBJC_EXPORT
760bool
4a109af3
A
761_objc_rootTryRetain(id _Nonnull obj)
762 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
763
764OBJC_EXPORT
765bool
4a109af3
A
766_objc_rootIsDeallocating(id _Nonnull obj)
767 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
768
769OBJC_EXPORT
4a109af3
A
770id _Nonnull
771_objc_rootAutorelease(id _Nonnull obj)
772 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
773
774OBJC_EXPORT
775uintptr_t
4a109af3
A
776_objc_rootRetainCount(id _Nonnull obj)
777 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
778
779OBJC_EXPORT
4a109af3
A
780id _Nonnull
781_objc_rootInit(id _Nonnull obj)
782 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
783
784OBJC_EXPORT
4a109af3
A
785id _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);
8972963c
A
788
789OBJC_EXPORT
4a109af3
A
790id _Nullable
791_objc_rootAlloc(Class _Nonnull cls)
792 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
793
794OBJC_EXPORT
795void
4a109af3
A
796_objc_rootDealloc(id _Nonnull obj)
797 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
798
799OBJC_EXPORT
800void
4a109af3
A
801_objc_rootFinalize(id _Nonnull obj)
802 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
803
804OBJC_EXPORT
4a109af3
A
805malloc_zone_t * _Nonnull
806_objc_rootZone(id _Nonnull obj)
807 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
808
809OBJC_EXPORT
810uintptr_t
4a109af3
A
811_objc_rootHash(id _Nonnull obj)
812 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
813
814OBJC_EXPORT
4a109af3 815void * _Nonnull
8972963c 816objc_autoreleasePoolPush(void)
4a109af3 817 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
818
819OBJC_EXPORT
820void
4a109af3
A
821objc_autoreleasePoolPop(void * _Nonnull context)
822 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
823
824
4a109af3
A
825OBJC_EXPORT id _Nullable
826objc_alloc(Class _Nullable cls)
827 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
7257e56c 828
4a109af3
A
829OBJC_EXPORT id _Nullable
830objc_allocWithZone(Class _Nullable cls)
831 OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
7257e56c 832
13ba007e
A
833OBJC_EXPORT id _Nullable
834objc_alloc_init(Class _Nullable cls)
1807f628
A
835 OBJC_AVAILABLE(10.14.4, 12.2, 12.2, 5.2, 3.2);
836
837OBJC_EXPORT id _Nullable
838objc_opt_new(Class _Nullable cls)
839 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
840
841OBJC_EXPORT id _Nullable
842objc_opt_self(id _Nullable obj)
843 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
844
845OBJC_EXPORT Class _Nullable
846objc_opt_class(id _Nullable obj)
847 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
848
849OBJC_EXPORT BOOL
850objc_opt_respondsToSelector(id _Nullable obj, SEL _Nullable sel)
851 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
852
853OBJC_EXPORT BOOL
854objc_opt_isKindOfClass(id _Nullable obj, Class _Nullable cls)
855 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
856
857
858OBJC_EXPORT BOOL
859objc_sync_try_enter(id _Nonnull obj)
860 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
13ba007e 861
4a109af3
A
862OBJC_EXPORT id _Nullable
863objc_retain(id _Nullable obj)
8972963c 864 __asm__("_objc_retain")
4a109af3 865 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 866
4a109af3
A
867OBJC_EXPORT void
868objc_release(id _Nullable obj)
8972963c 869 __asm__("_objc_release")
4a109af3 870 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 871
4a109af3
A
872OBJC_EXPORT id _Nullable
873objc_autorelease(id _Nullable obj)
8972963c 874 __asm__("_objc_autorelease")
4a109af3 875 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 876
31875a97 877// Prepare a value at +1 for return through a +0 autoreleasing convention.
4a109af3
A
878OBJC_EXPORT id _Nullable
879objc_autoreleaseReturnValue(id _Nullable obj)
880 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 881
31875a97 882// Prepare a value at +0 for return through a +0 autoreleasing convention.
4a109af3
A
883OBJC_EXPORT id _Nullable
884objc_retainAutoreleaseReturnValue(id _Nullable obj)
885 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 886
31875a97 887// Accept a value returned through a +0 autoreleasing convention for use at +1.
4a109af3
A
888OBJC_EXPORT id _Nullable
889objc_retainAutoreleasedReturnValue(id _Nullable obj)
890 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 891
31875a97 892// Accept a value returned through a +0 autoreleasing convention for use at +0.
4a109af3
A
893OBJC_EXPORT id _Nullable
894objc_unsafeClaimAutoreleasedReturnValue(id _Nullable obj)
895 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
31875a97 896
4a109af3
A
897OBJC_EXPORT void
898objc_storeStrong(id _Nullable * _Nonnull location, id _Nullable obj)
899 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 900
4a109af3
A
901OBJC_EXPORT id _Nullable
902objc_retainAutorelease(id _Nullable obj)
903 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
904
905// obsolete.
4a109af3
A
906OBJC_EXPORT id _Nullable
907objc_retain_autorelease(id _Nullable obj)
908 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 909
4a109af3
A
910OBJC_EXPORT id _Nullable
911objc_loadWeakRetained(id _Nullable * _Nonnull location)
912 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 913
4a109af3
A
914OBJC_EXPORT id _Nullable
915objc_initWeak(id _Nullable * _Nonnull location, id _Nullable val)
916 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 917
31875a97
A
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).
4a109af3
A
921OBJC_EXPORT id _Nullable
922objc_storeWeakOrNil(id _Nullable * _Nonnull location, id _Nullable obj)
923 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
31875a97
A
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).
4a109af3
A
928OBJC_EXPORT id _Nullable
929objc_initWeakOrNil(id _Nullable * _Nonnull location, id _Nullable val)
930 OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
31875a97 931
4a109af3
A
932OBJC_EXPORT void
933objc_destroyWeak(id _Nullable * _Nonnull location)
934 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 935
4a109af3
A
936OBJC_EXPORT void
937objc_copyWeak(id _Nullable * _Nonnull to, id _Nullable * _Nonnull from)
938 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 939
4a109af3
A
940OBJC_EXPORT void
941objc_moveWeak(id _Nullable * _Nonnull to, id _Nullable * _Nonnull from)
942 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
943
944
4a109af3 945OBJC_EXPORT void
8972963c 946_objc_autoreleasePoolPrint(void)
4a109af3 947 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 948
4a109af3
A
949OBJC_EXPORT BOOL
950objc_should_deallocate(id _Nonnull object)
951 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 952
4a109af3
A
953OBJC_EXPORT void
954objc_clear_deallocating(id _Nonnull object)
955 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
956
957
958// to make CF link for now
959
4a109af3 960OBJC_EXPORT void * _Nonnull
8972963c 961_objc_autoreleasePoolPush(void)
4a109af3 962 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 963
4a109af3
A
964OBJC_EXPORT void
965_objc_autoreleasePoolPop(void * _Nonnull context)
966 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c
A
967
968
1807f628
A
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__
983OBJC_EXPORT _Nullable Class
984objc_loadClassref(_Nullable Class * _Nonnull clsref)
985 OBJC_AVAILABLE(10.15, 13.0, 13.0, 6.0, 5.0);
986#endif
987
988
cd5f04f5 989// Extra @encode data for XPC, or NULL
4a109af3
A
990OBJC_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);
cd5f04f5 994
8972963c 995
1807f628
A
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 */
1003struct mach_header;
1004typedef 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
1019OBJC_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
34d5b5e8
A
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__))
1026OBJC_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.
1042OBJC_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
8972963c
A
1046// API to only be called by classes that provide their own reference count storage
1047
4a109af3
A
1048OBJC_EXPORT void
1049_objc_deallocOnMainThreadHelper(void * _Nullable context)
1050 OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
8972963c 1051
34d5b5e8
A
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
cd5f04f5
A
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
1084typedef 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 */ \
8972963c 1093 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
cd5f04f5
A
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 { \
bc4fafce 1125 return (NSUInteger)(_rc_ivar + 2) >> 1; \
cd5f04f5
A
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 } \
8972963c 1138 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
cd5f04f5
A
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 } \
bc4fafce 1147 return (_rc_ivar & 1) != 0; \
8972963c
A
1148 }
1149
cd5f04f5
A
1150#define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
1151 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
bc4fafce 1152 if ((_dealloc2main) && !pthread_main_np()) { \
cd5f04f5
A
1153 return _OBJC_DEALLOC_OBJECT_LATER; \
1154 } else { \
1155 return _OBJC_DEALLOC_OBJECT_NOW; \
1156 } \
1157 }))
1158
8972963c
A
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
34d5b5e8
A
1162
1163// C cache_t wrappers for objcdt and the IMP caches test tool
1164struct cache_t;
1165struct bucket_t;
1166struct preopt_cache_t;
1167OBJC_EXPORT struct bucket_t * _Nonnull objc_cache_buckets(const struct cache_t * _Nonnull cache);
1168OBJC_EXPORT size_t objc_cache_bytesForCapacity(uint32_t cap);
1169OBJC_EXPORT uint32_t objc_cache_occupied(const struct cache_t * _Nonnull cache);
1170OBJC_EXPORT unsigned objc_cache_capacity(const struct cache_t * _Nonnull cache);
1171
1172#if CONFIG_USE_PREOPT_CACHES
1173
1174OBJC_EXPORT bool objc_cache_isConstantOptimizedCache(const struct cache_t * _Nonnull cache, bool strict, uintptr_t empty_addr);
1175OBJC_EXPORT unsigned objc_cache_preoptCapacity(const struct cache_t * _Nonnull cache);
1176OBJC_EXPORT Class _Nonnull objc_cache_preoptFallbackClass(const struct cache_t * _Nonnull cache);
1177OBJC_EXPORT const struct preopt_cache_t * _Nonnull objc_cache_preoptCache(const struct cache_t * _Nonnull cache);
1178
1179#endif
1180
8972963c 1181__END_DECLS
13d88034 1182
13d88034 1183#endif