]>
Commit | Line | Data |
---|---|---|
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) | |
79 | OBJC_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 |
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); | |
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__ | |
101 | struct objc_image_info; | |
4a109af3 A |
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); | |
8070259c A |
106 | #endif |
107 | ||
8972963c | 108 | // Batch object allocation using malloc_zone_batch_malloc(). |
4a109af3 A |
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) | |
8972963c A |
113 | OBJC_ARC_UNAVAILABLE; |
114 | ||
115 | // Get the isa pointer written into objects just before being freed. | |
4a109af3 A |
116 | OBJC_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 |
121 | OBJC_EXPORT void |
122 | instrumentObjcMessageSends(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 |
126 | OBJC_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 |
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); | |
bd8dfcfc | 146 | |
c1e772c4 | 147 | // Return YES if GC is on and `object` is a GC allocation. |
4a109af3 A |
148 | OBJC_EXPORT BOOL |
149 | objc_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 |
153 | OBJC_EXPORT BOOL | |
154 | objc_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 |
158 | OBJC_EXPORT malloc_zone_t * _Nullable |
159 | objc_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. | |
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); | |
34d5b5e8 A |
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); | |
1807f628 | 185 | #endif |
8972963c | 186 | |
34d5b5e8 | 187 | |
8972963c | 188 | // Plainly-implemented GC barriers. Rosetta used to use these. |
4a109af3 A |
189 | OBJC_EXPORT id _Nullable |
190 | objc_assign_strongCast_generic(id _Nullable value, id _Nullable * _Nonnull dest) | |
8972963c | 191 | UNAVAILABLE_ATTRIBUTE; |
4a109af3 A |
192 | |
193 | OBJC_EXPORT id _Nullable | |
194 | objc_assign_global_generic(id _Nullable value, id _Nullable * _Nonnull dest) | |
8972963c | 195 | UNAVAILABLE_ATTRIBUTE; |
4a109af3 A |
196 | |
197 | OBJC_EXPORT id _Nullable | |
198 | objc_assign_threadlocal_generic(id _Nullable value, | |
199 | id _Nullable * _Nonnull dest) | |
8972963c | 200 | UNAVAILABLE_ATTRIBUTE; |
4a109af3 A |
201 | |
202 | OBJC_EXPORT id _Nullable | |
203 | objc_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 |
210 | OBJC_EXPORT int |
211 | objc_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 |
221 | OBJC_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 |
230 | OBJC_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 |
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); | |
cd5f04f5 | 242 | |
8972963c A |
243 | // Used by ExceptionHandling.framework |
244 | #if !__OBJC2__ | |
4a109af3 A |
245 | OBJC_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 | */ | |
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 | ||
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 | ||
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 | ||
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 | 297 | enum objc_tag_index_t : uint16_t |
7257e56c | 298 | #else |
c1e772c4 | 299 | typedef uint16_t objc_tag_index_t; |
7257e56c A |
300 | enum |
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) | |
349 | typedef 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 | 355 | static 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 |
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); | |
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 |
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); | |
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 | 375 | static 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 | 380 | static 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 | 386 | static 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 | 392 | static 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 | 398 | static 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 |
475 | extern uintptr_t objc_debug_taggedpointer_obfuscator; |
476 | ||
34d5b5e8 A |
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 | ||
66799735 A |
492 | static 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 | ||
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; | |
66799735 A |
516 | } |
517 | ||
518 | static 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 | 531 | static 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 | 538 | static 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 | ||
564 | static 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 |
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 | ||
7257e56c | 579 | static 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 | ||
593 | static 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 | ||
606 | static 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 |
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 | ||
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 |
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); | |
7257e56c | 646 | |
4a109af3 A |
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) | |
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__ | |
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. | |
8972963c | 704 | |
4a109af3 A |
705 | OBJC_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 | |
711 | OBJC_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 | */ | |
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 | ||
4a109af3 A |
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); | |
8972963c | 732 | |
4a109af3 A |
733 | OBJC_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.) | |
739 | OBJC_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 | ||
744 | OBJC_EXPORT | |
4a109af3 A |
745 | id _Nonnull |
746 | _objc_rootRetain(id _Nonnull obj) | |
747 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
748 | |
749 | OBJC_EXPORT | |
750 | void | |
4a109af3 A |
751 | _objc_rootRelease(id _Nonnull obj) |
752 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
753 | |
754 | OBJC_EXPORT | |
755 | bool | |
4a109af3 A |
756 | _objc_rootReleaseWasZero(id _Nonnull obj) |
757 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
758 | |
759 | OBJC_EXPORT | |
760 | bool | |
4a109af3 A |
761 | _objc_rootTryRetain(id _Nonnull obj) |
762 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
763 | |
764 | OBJC_EXPORT | |
765 | bool | |
4a109af3 A |
766 | _objc_rootIsDeallocating(id _Nonnull obj) |
767 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
768 | |
769 | OBJC_EXPORT | |
4a109af3 A |
770 | id _Nonnull |
771 | _objc_rootAutorelease(id _Nonnull obj) | |
772 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
773 | |
774 | OBJC_EXPORT | |
775 | uintptr_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 | |
779 | OBJC_EXPORT | |
4a109af3 A |
780 | id _Nonnull |
781 | _objc_rootInit(id _Nonnull obj) | |
782 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
783 | |
784 | OBJC_EXPORT | |
4a109af3 A |
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); | |
8972963c A |
788 | |
789 | OBJC_EXPORT | |
4a109af3 A |
790 | id _Nullable |
791 | _objc_rootAlloc(Class _Nonnull cls) | |
792 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
793 | |
794 | OBJC_EXPORT | |
795 | void | |
4a109af3 A |
796 | _objc_rootDealloc(id _Nonnull obj) |
797 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
798 | |
799 | OBJC_EXPORT | |
800 | void | |
4a109af3 A |
801 | _objc_rootFinalize(id _Nonnull obj) |
802 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
803 | |
804 | OBJC_EXPORT | |
4a109af3 A |
805 | malloc_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 | |
809 | OBJC_EXPORT | |
810 | uintptr_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 | |
814 | OBJC_EXPORT | |
4a109af3 | 815 | void * _Nonnull |
8972963c | 816 | objc_autoreleasePoolPush(void) |
4a109af3 | 817 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); |
8972963c A |
818 | |
819 | OBJC_EXPORT | |
820 | void | |
4a109af3 A |
821 | objc_autoreleasePoolPop(void * _Nonnull context) |
822 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
823 | |
824 | ||
4a109af3 A |
825 | OBJC_EXPORT id _Nullable |
826 | objc_alloc(Class _Nullable cls) | |
827 | OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0); | |
7257e56c | 828 | |
4a109af3 A |
829 | OBJC_EXPORT id _Nullable |
830 | objc_allocWithZone(Class _Nullable cls) | |
831 | OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0); | |
7257e56c | 832 | |
13ba007e A |
833 | OBJC_EXPORT id _Nullable |
834 | objc_alloc_init(Class _Nullable cls) | |
1807f628 A |
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); | |
13ba007e | 861 | |
4a109af3 A |
862 | OBJC_EXPORT id _Nullable |
863 | objc_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 |
867 | OBJC_EXPORT void |
868 | objc_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 |
872 | OBJC_EXPORT id _Nullable |
873 | objc_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 |
878 | OBJC_EXPORT id _Nullable |
879 | objc_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 |
883 | OBJC_EXPORT id _Nullable |
884 | objc_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 |
888 | OBJC_EXPORT id _Nullable |
889 | objc_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 |
893 | OBJC_EXPORT id _Nullable |
894 | objc_unsafeClaimAutoreleasedReturnValue(id _Nullable obj) | |
895 | OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0); | |
31875a97 | 896 | |
4a109af3 A |
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); | |
8972963c | 900 | |
4a109af3 A |
901 | OBJC_EXPORT id _Nullable |
902 | objc_retainAutorelease(id _Nullable obj) | |
903 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c A |
904 | |
905 | // obsolete. | |
4a109af3 A |
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); | |
8972963c | 909 | |
4a109af3 A |
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); | |
8972963c | 913 | |
4a109af3 A |
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); | |
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 |
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); | |
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 |
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); | |
31875a97 | 931 | |
4a109af3 A |
932 | OBJC_EXPORT void |
933 | objc_destroyWeak(id _Nullable * _Nonnull location) | |
934 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c | 935 | |
4a109af3 A |
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); | |
8972963c | 939 | |
4a109af3 A |
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); | |
8972963c A |
943 | |
944 | ||
4a109af3 | 945 | OBJC_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 |
949 | OBJC_EXPORT BOOL |
950 | objc_should_deallocate(id _Nonnull object) | |
951 | OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0); | |
8972963c | 952 | |
4a109af3 A |
953 | OBJC_EXPORT void |
954 | objc_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 | 960 | OBJC_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 |
964 | OBJC_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__ | |
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 | ||
cd5f04f5 | 989 | // Extra @encode data for XPC, or NULL |
4a109af3 A |
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); | |
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 | */ | |
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 | ||
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__)) | |
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 | ||
8972963c A |
1046 | // API to only be called by classes that provide their own reference count storage |
1047 | ||
4a109af3 A |
1048 | OBJC_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 | ||
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 */ \ | |
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 | |
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 | ||
8972963c | 1181 | __END_DECLS |
13d88034 | 1182 | |
13d88034 | 1183 | #endif |