123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883 |
- /*
- * Copyright (c) 2009 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
- #ifndef _OBJC_INTERNAL_H
- #define _OBJC_INTERNAL_H
- /*
- * WARNING DANGER HAZARD BEWARE EEK
- *
- * Everything in this file is for Apple Internal use only.
- * These will change in arbitrary OS updates and in unpredictable ways.
- * When your program breaks, you get to keep both pieces.
- */
- /*
- * objc-internal.h: Private SPI for use by other system frameworks.
- */
- #include <objc/objc.h>
- #include <objc/runtime.h>
- #include <Availability.h>
- #include <malloc/malloc.h>
- #include <mach-o/loader.h>
- #include <dispatch/dispatch.h>
- // Termination reasons in the OS_REASON_OBJC namespace.
- #define OBJC_EXIT_REASON_UNSPECIFIED 1
- #define OBJC_EXIT_REASON_GC_NOT_SUPPORTED 2
- // This is the allocation size required for each of the class and the metaclass
- // with objc_initializeClassPair() and objc_readClassPair().
- // The runtime's class structure will never grow beyond this.
- #define OBJC_MAX_CLASS_SIZE (32*sizeof(void*))
- __BEGIN_DECLS
- // In-place construction of an Objective-C class.
- // cls and metacls must each be OBJC_MAX_CLASS_SIZE bytes.
- // Returns nil if a class with the same name already exists.
- // Returns nil if the superclass is under construction.
- // Call objc_registerClassPair() when you are done.
- OBJC_EXPORT Class _Nullable
- objc_initializeClassPair(Class _Nullable superclass, const char * _Nonnull name,
- Class _Nonnull cls, Class _Nonnull metacls)
- OBJC_AVAILABLE(10.6, 3.0, 9.0, 1.0, 2.0);
- // Class and metaclass construction from a compiler-generated memory image.
- // cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes.
- // Extra bytes not used the the metadata must be zero.
- // info is the same objc_image_info that would be emitted by a static compiler.
- // Returns nil if a class with the same name already exists.
- // Returns nil if the superclass is nil and the class is not marked as a root.
- // Returns nil if the superclass is under construction.
- // Do not call objc_registerClassPair().
- #if __OBJC2__
- struct objc_image_info;
- OBJC_EXPORT Class _Nullable
- objc_readClassPair(Class _Nonnull cls,
- const struct objc_image_info * _Nonnull info)
- OBJC_AVAILABLE(10.10, 8.0, 9.0, 1.0, 2.0);
- #endif
- // Batch object allocation using malloc_zone_batch_malloc().
- OBJC_EXPORT unsigned
- class_createInstances(Class _Nullable cls, size_t extraBytes,
- id _Nonnull * _Nonnull results, unsigned num_requested)
- OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0, 2.0)
- OBJC_ARC_UNAVAILABLE;
- // Get the isa pointer written into objects just before being freed.
- OBJC_EXPORT Class _Nonnull
- _objc_getFreedObjectClass(void)
- OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
- // env NSObjCMessageLoggingEnabled
- OBJC_EXPORT void
- instrumentObjcMessageSends(BOOL flag)
- OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);
- // Initializer called by libSystem
- OBJC_EXPORT void
- _objc_init(void)
- #if __OBJC2__
- OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
- #else
- OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
- #endif
- // fork() safety called by libSystem
- OBJC_EXPORT void
- _objc_atfork_prepare(void)
- OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
- OBJC_EXPORT void
- _objc_atfork_parent(void)
- OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
- OBJC_EXPORT void
- _objc_atfork_child(void)
- OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
- // Return YES if GC is on and `object` is a GC allocation.
- OBJC_EXPORT BOOL
- objc_isAuto(id _Nullable object)
- __OSX_DEPRECATED(10.4, 10.8, "it always returns NO")
- __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
- __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE;
- // GC debugging
- OBJC_EXPORT BOOL
- objc_dumpHeap(char * _Nonnull filename, unsigned long length)
- __OSX_DEPRECATED(10.4, 10.8, "it always returns NO")
- __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
- __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE;
- // GC startup callback from Foundation
- OBJC_EXPORT malloc_zone_t * _Nullable
- objc_collect_init(int (* _Nonnull callback)(void))
- __OSX_DEPRECATED(10.4, 10.8, "it does nothing")
- __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
- __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE;
- // Plainly-implemented GC barriers. Rosetta used to use these.
- OBJC_EXPORT id _Nullable
- objc_assign_strongCast_generic(id _Nullable value, id _Nullable * _Nonnull dest)
- UNAVAILABLE_ATTRIBUTE;
- OBJC_EXPORT id _Nullable
- objc_assign_global_generic(id _Nullable value, id _Nullable * _Nonnull dest)
- UNAVAILABLE_ATTRIBUTE;
- OBJC_EXPORT id _Nullable
- objc_assign_threadlocal_generic(id _Nullable value,
- id _Nullable * _Nonnull dest)
- UNAVAILABLE_ATTRIBUTE;
- OBJC_EXPORT id _Nullable
- objc_assign_ivar_generic(id _Nullable value, id _Nonnull dest, ptrdiff_t offset)
- UNAVAILABLE_ATTRIBUTE;
- // GC preflight for an app executable.
- // 1: some slice requires GC
- // 0: no slice requires GC
- // -1: I/O or file format error
- OBJC_EXPORT int
- objc_appRequiresGC(int fd)
- __OSX_AVAILABLE(10.11)
- __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
- __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE;
- // Install missing-class callback. Used by the late unlamented ZeroLink.
- OBJC_EXPORT void
- _objc_setClassLoader(BOOL (* _Nonnull newClassLoader)(const char * _Nonnull))
- OBJC2_UNAVAILABLE;
- #if !(TARGET_OS_OSX && !TARGET_OS_IOSMAC && __i386__)
- OBJC_EXPORT void
- _objc_setClassCopyFixupHandler(void (* _Nonnull newFixupHandler)
- (Class _Nonnull oldClass, Class _Nonnull newClass));
- // fixme work around bug in Swift
- // OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0)
- #endif
- // Install handler for allocation failures.
- // Handler may abort, or throw, or provide an object to return.
- OBJC_EXPORT void
- _objc_setBadAllocHandler(id _Nullable (* _Nonnull newHandler)
- (Class _Nullable isa))
- OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
- // Used by ExceptionHandling.framework
- #if !__OBJC2__
- OBJC_EXPORT void
- _objc_error(id _Nullable rcv, const char * _Nonnull fmt, va_list args)
- __attribute__((noreturn))
- __OSX_DEPRECATED(10.0, 10.5, "use other logging facilities instead")
- __IOS_UNAVAILABLE __TVOS_UNAVAILABLE
- __WATCHOS_UNAVAILABLE __BRIDGEOS_UNAVAILABLE;
- #endif
- /**
- * Returns the names of all the classes within a library.
- *
- * @param image The mach header for library or framework you are inquiring about.
- * @param outCount The number of class names returned.
- *
- * @return An array of C strings representing the class names.
- */
- OBJC_EXPORT const char * _Nonnull * _Nullable
- objc_copyClassNamesForImageHeader(const struct mach_header * _Nonnull mh,
- unsigned int * _Nullable outCount)
- OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
- // Tagged pointer objects.
- #if __LP64__
- #define OBJC_HAVE_TAGGED_POINTERS 1
- #endif
- #if OBJC_HAVE_TAGGED_POINTERS
- // Tagged pointer layout and usage is subject to change on different OS versions.
- // Tag indexes 0..<7 have a 60-bit payload.
- // Tag index 7 is reserved.
- // Tag indexes 8..<264 have a 52-bit payload.
- // Tag index 264 is reserved.
- #if __has_feature(objc_fixed_enum) || __cplusplus >= 201103L
- enum objc_tag_index_t : uint16_t
- #else
- typedef uint16_t objc_tag_index_t;
- enum
- #endif
- {
- // 60-bit payloads
- OBJC_TAG_NSAtom = 0,
- OBJC_TAG_1 = 1,
- OBJC_TAG_NSString = 2,
- OBJC_TAG_NSNumber = 3,
- OBJC_TAG_NSIndexPath = 4,
- OBJC_TAG_NSManagedObjectID = 5,
- OBJC_TAG_NSDate = 6,
- // 60-bit reserved
- OBJC_TAG_RESERVED_7 = 7,
- // 52-bit payloads
- OBJC_TAG_Photos_1 = 8,
- OBJC_TAG_Photos_2 = 9,
- OBJC_TAG_Photos_3 = 10,
- OBJC_TAG_Photos_4 = 11,
- OBJC_TAG_XPC_1 = 12,
- OBJC_TAG_XPC_2 = 13,
- OBJC_TAG_XPC_3 = 14,
- OBJC_TAG_XPC_4 = 15,
- OBJC_TAG_First60BitPayload = 0,
- OBJC_TAG_Last60BitPayload = 6,
- OBJC_TAG_First52BitPayload = 8,
- OBJC_TAG_Last52BitPayload = 263,
- OBJC_TAG_RESERVED_264 = 264
- };
- #if __has_feature(objc_fixed_enum) && !defined(__cplusplus)
- typedef enum objc_tag_index_t objc_tag_index_t;
- #endif
- // Returns true if tagged pointers are enabled.
- // The other functions below must not be called if tagged pointers are disabled.
- static inline bool
- _objc_taggedPointersEnabled(void);
- // Register a class for a tagged pointer tag.
- // Aborts if the tag is invalid or already in use.
- OBJC_EXPORT void
- _objc_registerTaggedPointerClass(objc_tag_index_t tag, Class _Nonnull cls)
- OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
- // Returns the registered class for the given tag.
- // Returns nil if the tag is valid but has no registered class.
- // Aborts if the tag is invalid.
- OBJC_EXPORT Class _Nullable
- _objc_getClassForTag(objc_tag_index_t tag)
- OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
- // Create a tagged pointer object with the given tag and payload.
- // Assumes the tag is valid.
- // Assumes tagged pointers are enabled.
- // The payload will be silently truncated to fit.
- static inline void * _Nonnull
- _objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t payload);
- // Return true if ptr is a tagged pointer object.
- // Does not check the validity of ptr's class.
- static inline bool
- _objc_isTaggedPointer(const void * _Nullable ptr);
- // Extract the tag value from the given tagged pointer object.
- // Assumes ptr is a valid tagged pointer object.
- // Does not check the validity of ptr's tag.
- static inline objc_tag_index_t
- _objc_getTaggedPointerTag(const void * _Nullable ptr);
- // Extract the payload from the given tagged pointer object.
- // Assumes ptr is a valid tagged pointer object.
- // The payload value is zero-extended.
- static inline uintptr_t
- _objc_getTaggedPointerValue(const void * _Nullable ptr);
- // Extract the payload from the given tagged pointer object.
- // Assumes ptr is a valid tagged pointer object.
- // The payload value is sign-extended.
- static inline intptr_t
- _objc_getTaggedPointerSignedValue(const void * _Nullable ptr);
- // Don't use the values below. Use the declarations above.
- #if (TARGET_OS_OSX || TARGET_OS_IOSMAC) && __x86_64__
- // 64-bit Mac - tag bit is LSB
- # define OBJC_MSB_TAGGED_POINTERS 0
- #else
- // Everything else - tag bit is MSB
- # define OBJC_MSB_TAGGED_POINTERS 1
- #endif
- #define _OBJC_TAG_INDEX_MASK 0x7
- // array slot includes the tag bit itself
- #define _OBJC_TAG_SLOT_COUNT 16
- #define _OBJC_TAG_SLOT_MASK 0xf
- #define _OBJC_TAG_EXT_INDEX_MASK 0xff
- // array slot has no extra bits
- #define _OBJC_TAG_EXT_SLOT_COUNT 256
- #define _OBJC_TAG_EXT_SLOT_MASK 0xff
- #if OBJC_MSB_TAGGED_POINTERS
- # define _OBJC_TAG_MASK (1UL<<63)
- # define _OBJC_TAG_INDEX_SHIFT 60
- # define _OBJC_TAG_SLOT_SHIFT 60
- # define _OBJC_TAG_PAYLOAD_LSHIFT 4
- # define _OBJC_TAG_PAYLOAD_RSHIFT 4
- # define _OBJC_TAG_EXT_MASK (0xfUL<<60)
- # define _OBJC_TAG_EXT_INDEX_SHIFT 52
- # define _OBJC_TAG_EXT_SLOT_SHIFT 52
- # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 12
- # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
- #else
- # define _OBJC_TAG_MASK 1UL
- # define _OBJC_TAG_INDEX_SHIFT 1
- # define _OBJC_TAG_SLOT_SHIFT 0
- # define _OBJC_TAG_PAYLOAD_LSHIFT 0
- # define _OBJC_TAG_PAYLOAD_RSHIFT 4
- # define _OBJC_TAG_EXT_MASK 0xfUL
- # define _OBJC_TAG_EXT_INDEX_SHIFT 4
- # define _OBJC_TAG_EXT_SLOT_SHIFT 4
- # define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 0
- # define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
- #endif
- extern uintptr_t objc_debug_taggedpointer_obfuscator;
- static inline void * _Nonnull
- _objc_encodeTaggedPointer(uintptr_t ptr)
- {
- return (void *)(objc_debug_taggedpointer_obfuscator ^ ptr);
- }
- static inline uintptr_t
- _objc_decodeTaggedPointer(const void * _Nullable ptr)
- {
- return (uintptr_t)ptr ^ objc_debug_taggedpointer_obfuscator;
- }
- static inline bool
- _objc_taggedPointersEnabled(void)
- {
- extern uintptr_t objc_debug_taggedpointer_mask;
- return (objc_debug_taggedpointer_mask != 0);
- }
- static inline void * _Nonnull
- _objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t value)
- {
- // PAYLOAD_LSHIFT and PAYLOAD_RSHIFT are the payload extraction shifts.
- // They are reversed here for payload insertion.
- // assert(_objc_taggedPointersEnabled());
- if (tag <= OBJC_TAG_Last60BitPayload) {
- // assert(((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT) == value);
- uintptr_t result =
- (_OBJC_TAG_MASK |
- ((uintptr_t)tag << _OBJC_TAG_INDEX_SHIFT) |
- ((value << _OBJC_TAG_PAYLOAD_RSHIFT) >> _OBJC_TAG_PAYLOAD_LSHIFT));
- return _objc_encodeTaggedPointer(result);
- } else {
- // assert(tag >= OBJC_TAG_First52BitPayload);
- // assert(tag <= OBJC_TAG_Last52BitPayload);
- // assert(((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT) == value);
- uintptr_t result =
- (_OBJC_TAG_EXT_MASK |
- ((uintptr_t)(tag - OBJC_TAG_First52BitPayload) << _OBJC_TAG_EXT_INDEX_SHIFT) |
- ((value << _OBJC_TAG_EXT_PAYLOAD_RSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_LSHIFT));
- return _objc_encodeTaggedPointer(result);
- }
- }
- static inline bool
- _objc_isTaggedPointer(const void * _Nullable ptr)
- {
- return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
- }
- static inline objc_tag_index_t
- _objc_getTaggedPointerTag(const void * _Nullable ptr)
- {
- // assert(_objc_isTaggedPointer(ptr));
- uintptr_t value = _objc_decodeTaggedPointer(ptr);
- uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
- uintptr_t extTag = (value >> _OBJC_TAG_EXT_INDEX_SHIFT) & _OBJC_TAG_EXT_INDEX_MASK;
- if (basicTag == _OBJC_TAG_INDEX_MASK) {
- return (objc_tag_index_t)(extTag + OBJC_TAG_First52BitPayload);
- } else {
- return (objc_tag_index_t)basicTag;
- }
- }
- static inline uintptr_t
- _objc_getTaggedPointerValue(const void * _Nullable ptr)
- {
- // assert(_objc_isTaggedPointer(ptr));
- uintptr_t value = _objc_decodeTaggedPointer(ptr);
- uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
- if (basicTag == _OBJC_TAG_INDEX_MASK) {
- return (value << _OBJC_TAG_EXT_PAYLOAD_LSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
- } else {
- return (value << _OBJC_TAG_PAYLOAD_LSHIFT) >> _OBJC_TAG_PAYLOAD_RSHIFT;
- }
- }
- static inline intptr_t
- _objc_getTaggedPointerSignedValue(const void * _Nullable ptr)
- {
- // assert(_objc_isTaggedPointer(ptr));
- uintptr_t value = _objc_decodeTaggedPointer(ptr);
- uintptr_t basicTag = (value >> _OBJC_TAG_INDEX_SHIFT) & _OBJC_TAG_INDEX_MASK;
- if (basicTag == _OBJC_TAG_INDEX_MASK) {
- return ((intptr_t)value << _OBJC_TAG_EXT_PAYLOAD_LSHIFT) >> _OBJC_TAG_EXT_PAYLOAD_RSHIFT;
- } else {
- return ((intptr_t)value << _OBJC_TAG_PAYLOAD_LSHIFT) >> _OBJC_TAG_PAYLOAD_RSHIFT;
- }
- }
- // OBJC_HAVE_TAGGED_POINTERS
- #endif
- /**
- * Returns the method implementation of an object.
- *
- * @param obj An Objective-C object.
- * @param name An Objective-C selector.
- *
- * @return The IMP corresponding to the instance method implemented by
- * the class of \e obj.
- *
- * @note Equivalent to:
- *
- * class_getMethodImplementation(object_getClass(obj), name);
- */
- OBJC_EXPORT IMP _Nonnull
- object_getMethodImplementation(id _Nullable obj, SEL _Nonnull name)
- OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT IMP _Nonnull
- object_getMethodImplementation_stret(id _Nullable obj, SEL _Nonnull name)
- OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0)
- OBJC_ARM64_UNAVAILABLE;
- /**
- * Adds multiple methods to a class in bulk. This amortizes overhead that can be
- * expensive when adding methods one by one with class_addMethod.
- *
- * @param cls The class to which to add the methods.
- * @param names An array of selectors for the methods to add.
- * @param imps An array of functions which implement the new methods.
- * @param types An array of strings that describe the types of each method's
- * arguments.
- * @param count The number of items in the names, imps, and types arrays.
- * @param outFiledCount Upon return, contains the number of failed selectors in
- * the returned array.
- *
- * @return A NULL-terminated C array of selectors which could not be added. A
- * method cannot be added when a method of that name already exists on that
- * class. When no failures occur, the return value is \c NULL. When a non-NULL
- * value is returned, the caller must free the array with \c free().
- *
- */
- #if __OBJC2__
- OBJC_EXPORT _Nullable SEL * _Nullable
- class_addMethodsBulk(_Nullable Class cls, _Nonnull const SEL * _Nonnull names,
- _Nonnull const IMP * _Nonnull imps,
- const char * _Nonnull * _Nonnull types, uint32_t count,
- uint32_t * _Nullable outFailedCount)
- OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
- #endif
- /**
- * Replaces multiple methods in a class in bulk. This amortizes overhead that
- * can be expensive when adding methods one by one with class_replaceMethod.
- *
- * @param cls The class to modify.
- * @param names An array of selectors for the methods to replace.
- * @param imps An array of functions will be the new method implementantations.
- * @param types An array of strings that describe the types of each method's
- * arguments.
- * @param count The number of items in the names, imps, and types arrays.
- */
- #if __OBJC2__
- OBJC_EXPORT void
- class_replaceMethodsBulk(_Nullable Class cls,
- _Nonnull const SEL * _Nonnull names,
- _Nonnull const IMP * _Nonnull imps,
- const char * _Nonnull * _Nonnull types,
- uint32_t count)
- OBJC_AVAILABLE(10.14, 12.0, 12.0, 5.0, 3.0);
- #endif
- // Instance-specific instance variable layout. This is no longer implemented.
- OBJC_EXPORT void
- _class_setIvarLayoutAccessor(Class _Nullable cls,
- const uint8_t* _Nullable (* _Nonnull accessor)
- (id _Nullable object))
- UNAVAILABLE_ATTRIBUTE;
- OBJC_EXPORT const uint8_t * _Nullable
- _object_getIvarLayout(Class _Nullable cls, id _Nullable object)
- UNAVAILABLE_ATTRIBUTE;
- /*
- "Unknown" includes non-object ivars and non-ARC non-__weak ivars
- "Strong" includes ARC __strong ivars
- "Weak" includes ARC and new MRC __weak ivars
- "Unretained" includes ARC __unsafe_unretained and old GC+MRC __weak ivars
- */
- typedef enum {
- objc_ivar_memoryUnknown, // unknown / unknown
- objc_ivar_memoryStrong, // direct access / objc_storeStrong
- objc_ivar_memoryWeak, // objc_loadWeak[Retained] / objc_storeWeak
- objc_ivar_memoryUnretained // direct access / direct access
- } objc_ivar_memory_management_t;
- OBJC_EXPORT objc_ivar_memory_management_t
- _class_getIvarMemoryManagement(Class _Nullable cls, Ivar _Nonnull ivar)
- OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0, 2.0);
- OBJC_EXPORT BOOL _class_isFutureClass(Class _Nullable cls)
- OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
- // API to only be called by root classes like NSObject or NSProxy
- OBJC_EXPORT
- id _Nonnull
- _objc_rootRetain(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- void
- _objc_rootRelease(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- bool
- _objc_rootReleaseWasZero(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- bool
- _objc_rootTryRetain(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- bool
- _objc_rootIsDeallocating(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- id _Nonnull
- _objc_rootAutorelease(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- uintptr_t
- _objc_rootRetainCount(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- id _Nonnull
- _objc_rootInit(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- id _Nullable
- _objc_rootAllocWithZone(Class _Nonnull cls, malloc_zone_t * _Nullable zone)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- id _Nullable
- _objc_rootAlloc(Class _Nonnull cls)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- void
- _objc_rootDealloc(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- void
- _objc_rootFinalize(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- malloc_zone_t * _Nonnull
- _objc_rootZone(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- uintptr_t
- _objc_rootHash(id _Nonnull obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- void * _Nonnull
- objc_autoreleasePoolPush(void)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT
- void
- objc_autoreleasePoolPop(void * _Nonnull context)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT id _Nullable
- objc_alloc(Class _Nullable cls)
- OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT id _Nullable
- objc_allocWithZone(Class _Nullable cls)
- OBJC_AVAILABLE(10.9, 7.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT id _Nullable
- objc_retain(id _Nullable obj)
- __asm__("_objc_retain")
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT void
- objc_release(id _Nullable obj)
- __asm__("_objc_release")
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT id _Nullable
- objc_autorelease(id _Nullable obj)
- __asm__("_objc_autorelease")
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- // Prepare a value at +1 for return through a +0 autoreleasing convention.
- OBJC_EXPORT id _Nullable
- objc_autoreleaseReturnValue(id _Nullable obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- // Prepare a value at +0 for return through a +0 autoreleasing convention.
- OBJC_EXPORT id _Nullable
- objc_retainAutoreleaseReturnValue(id _Nullable obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- // Accept a value returned through a +0 autoreleasing convention for use at +1.
- OBJC_EXPORT id _Nullable
- objc_retainAutoreleasedReturnValue(id _Nullable obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- // Accept a value returned through a +0 autoreleasing convention for use at +0.
- OBJC_EXPORT id _Nullable
- objc_unsafeClaimAutoreleasedReturnValue(id _Nullable obj)
- OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT void
- objc_storeStrong(id _Nullable * _Nonnull location, id _Nullable obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT id _Nullable
- objc_retainAutorelease(id _Nullable obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- // obsolete.
- OBJC_EXPORT id _Nullable
- objc_retain_autorelease(id _Nullable obj)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT id _Nullable
- objc_loadWeakRetained(id _Nullable * _Nonnull location)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT id _Nullable
- objc_initWeak(id _Nullable * _Nonnull location, id _Nullable val)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- // Like objc_storeWeak, but stores nil if the new object is deallocating
- // or the new object's class does not support weak references.
- // Returns the value stored (either the new object or nil).
- OBJC_EXPORT id _Nullable
- objc_storeWeakOrNil(id _Nullable * _Nonnull location, id _Nullable obj)
- OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
- // Like objc_initWeak, but stores nil if the new object is deallocating
- // or the new object's class does not support weak references.
- // Returns the value stored (either the new object or nil).
- OBJC_EXPORT id _Nullable
- objc_initWeakOrNil(id _Nullable * _Nonnull location, id _Nullable val)
- OBJC_AVAILABLE(10.11, 9.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT void
- objc_destroyWeak(id _Nullable * _Nonnull location)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT void
- objc_copyWeak(id _Nullable * _Nonnull to, id _Nullable * _Nonnull from)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT void
- objc_moveWeak(id _Nullable * _Nonnull to, id _Nullable * _Nonnull from)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT void
- _objc_autoreleasePoolPrint(void)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT BOOL
- objc_should_deallocate(id _Nonnull object)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT void
- objc_clear_deallocating(id _Nonnull object)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
-
- // to make CF link for now
- OBJC_EXPORT void * _Nonnull
- _objc_autoreleasePoolPush(void)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- OBJC_EXPORT void
- _objc_autoreleasePoolPop(void * _Nonnull context)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- // Extra @encode data for XPC, or NULL
- OBJC_EXPORT const char * _Nullable
- _protocol_getMethodTypeEncoding(Protocol * _Nonnull proto, SEL _Nonnull sel,
- BOOL isRequiredMethod, BOOL isInstanceMethod)
- OBJC_AVAILABLE(10.8, 6.0, 9.0, 1.0, 2.0);
- // API to only be called by classes that provide their own reference count storage
- OBJC_EXPORT void
- _objc_deallocOnMainThreadHelper(void * _Nullable context)
- OBJC_AVAILABLE(10.7, 5.0, 9.0, 1.0, 2.0);
- // On async versus sync deallocation and the _dealloc2main flag
- //
- // Theory:
- //
- // If order matters, then code must always: [self dealloc].
- // If order doesn't matter, then always async should be safe.
- //
- // Practice:
- //
- // The _dealloc2main bit is set for GUI objects that may be retained by other
- // threads. Once deallocation begins on the main thread, doing more async
- // deallocation will at best cause extra UI latency and at worst cause
- // use-after-free bugs in unretained delegate style patterns. Yes, this is
- // extremely fragile. Yes, in the long run, developers should switch to weak
- // references.
- //
- // Note is NOT safe to do any equality check against the result of
- // dispatch_get_current_queue(). The main thread can and does drain more than
- // one dispatch queue. That is why we call pthread_main_np().
- //
- typedef enum {
- _OBJC_RESURRECT_OBJECT = -1, /* _logicBlock has called -retain, and scheduled a -release for later. */
- _OBJC_DEALLOC_OBJECT_NOW = 1, /* call [self dealloc] immediately. */
- _OBJC_DEALLOC_OBJECT_LATER = 2 /* call [self dealloc] on the main queue. */
- } _objc_object_disposition_t;
- #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \
- -(id)retain { \
- /* this will fail to compile if _rc_ivar is an unsigned type */ \
- int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \
- __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \
- if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \
- __builtin_trap(); /* BUG: retain of over-released ref */ \
- } \
- return self; \
- } \
- -(oneway void)release { \
- __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \
- if (_prev > 0) { \
- return; \
- } else if (_prev < 0) { \
- __builtin_trap(); /* BUG: over-release */ \
- } \
- _objc_object_disposition_t fate = _logicBlock(self); \
- if (fate == _OBJC_RESURRECT_OBJECT) { \
- return; \
- } \
- /* mark the object as deallocating. */ \
- if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \
- __builtin_trap(); /* BUG: dangling ref did a retain */ \
- } \
- if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \
- [self dealloc]; \
- } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \
- dispatch_barrier_async_f(dispatch_get_main_queue(), self, \
- _objc_deallocOnMainThreadHelper); \
- } else { \
- __builtin_trap(); /* BUG: bogus fate value */ \
- } \
- } \
- -(NSUInteger)retainCount { \
- return (_rc_ivar + 2) >> 1; \
- } \
- -(BOOL)_tryRetain { \
- __typeof__(_rc_ivar) _prev; \
- do { \
- _prev = _rc_ivar; \
- if (_prev & 1) { \
- return 0; \
- } else if (_prev == -2) { \
- return 0; \
- } else if (_prev < -2) { \
- __builtin_trap(); /* BUG: over-release elsewhere */ \
- } \
- } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \
- return 1; \
- } \
- -(BOOL)_isDeallocating { \
- if (_rc_ivar == -2) { \
- return 1; \
- } else if (_rc_ivar < -2) { \
- __builtin_trap(); /* BUG: over-release elsewhere */ \
- } \
- return _rc_ivar & 1; \
- }
- #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \
- _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \
- if (_dealloc2main && !pthread_main_np()) { \
- return _OBJC_DEALLOC_OBJECT_LATER; \
- } else { \
- return _OBJC_DEALLOC_OBJECT_NOW; \
- } \
- }))
- #define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0)
- #define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1)
- __END_DECLS
- #endif
|