文档地址:http://www.opensource.apple.com/source/objc4/objc4-493.9/runtime/objc-internal.h
/* * 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 <Availability.h> #include <malloc/malloc.h> #include <dispatch/dispatch.h> __BEGIN_DECLS // In-place construction of an Objective-C instance. OBJC_EXPORT id objc_constructInstance(Class cls, void *bytes) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0) OBJC_ARC_UNAVAILABLE; OBJC_EXPORT void *objc_destructInstance(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0) OBJC_ARC_UNAVAILABLE; // In-place construction of an Objective-C class. OBJC_EXPORT Class objc_initializeClassPair(Class superclass_gen, const char *name, Class cls_gen, Class meta_gen) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0); #if __OBJC2__ && __LP64__ // Register a tagged pointer class. OBJC_EXPORT void _objc_insert_tagged_isa(unsigned char slotNumber, Class isa) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); #endif // Batch object allocation using malloc_zone_batch_malloc(). OBJC_EXPORT unsigned class_createInstances(Class cls, size_t extraBytes, id *results, unsigned num_requested) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3) OBJC_ARC_UNAVAILABLE; // Get the isa pointer written into objects just before being freed. OBJC_EXPORT Class _objc_getFreedObjectClass(void) __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); // Substitute receiver for messages to nil. // Not supported for all messages to nil. OBJC_EXPORT id _objc_setNilReceiver(id newNilReceiver) __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); OBJC_EXPORT id _objc_getNilReceiver(void) __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA); // Return NO if no instance of `cls` has ever owned an associative reference. OBJC_EXPORT BOOL class_instancesHaveAssociatedObjects(Class cls) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0); // Return YES if GC is on and `object` is a GC allocation. OBJC_EXPORT BOOL objc_isAuto(id object) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); // env NSObjCMessageLoggingEnabled OBJC_EXPORT void instrumentObjcMessageSends(BOOL flag) __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); // GC startup callback from Foundation OBJC_EXPORT malloc_zone_t *objc_collect_init(int (*callback)(void)) __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); // Plainly-implemented GC barriers. Rosetta used to use these. OBJC_EXPORT id objc_assign_strongCast_generic(id value, id *dest) UNAVAILABLE_ATTRIBUTE; OBJC_EXPORT id objc_assign_global_generic(id value, id *dest) UNAVAILABLE_ATTRIBUTE; OBJC_EXPORT id objc_assign_threadlocal_generic(id value, id *dest) UNAVAILABLE_ATTRIBUTE; OBJC_EXPORT id objc_assign_ivar_generic(id value, id dest, ptrdiff_t offset) UNAVAILABLE_ATTRIBUTE; // Install missing-class callback. Used by the late unlamented ZeroLink. OBJC_EXPORT void _objc_setClassLoader(BOOL (*newClassLoader)(const char *)) OBJC2_UNAVAILABLE; // This can go away when AppKit stops calling it (rdar://7811851) #if __OBJC2__ OBJC_EXPORT void objc_setMultithreaded (BOOL flag) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5, __IPHONE_NA,__IPHONE_NA); #endif // Used by ExceptionHandling.framework #if !__OBJC2__ OBJC_EXPORT void _objc_error(id rcv, const char *fmt, va_list args) __attribute__((noreturn)) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5, __IPHONE_NA,__IPHONE_NA); #endif // External Reference support. Used to support compaction. enum { OBJC_XREF_STRONG = 1, OBJC_XREF_WEAK = 2 }; typedef uintptr_t objc_xref_type_t; typedef uintptr_t objc_xref_t; OBJC_EXPORT objc_xref_t _object_addExternalReference(id object, objc_xref_type_t type) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); OBJC_EXPORT void _object_removeExternalReference(objc_xref_t xref) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); OBJC_EXPORT id _object_readExternalReference(objc_xref_t xref) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); OBJC_EXPORT uintptr_t _object_getExternalHash(id object) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); // Instance-specific instance variable layout. OBJC_EXPORT void _class_setIvarLayoutAccessor(Class cls_gen, const uint8_t* (*accessor) (id object)) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); OBJC_EXPORT const uint8_t *_object_getIvarLayout(Class cls_gen, id object) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); OBJC_EXPORT BOOL _class_usesAutomaticRetainRelease(Class cls) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); // API to only be called by root classes like NSObject or NSProxy OBJC_EXPORT id _objc_rootRetain(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void _objc_rootRelease(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT bool _objc_rootReleaseWasZero(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT bool _objc_rootTryRetain(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT bool _objc_rootIsDeallocating(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT id _objc_rootAutorelease(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT uintptr_t _objc_rootRetainCount(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT id _objc_rootInit(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT id _objc_rootAllocWithZone(Class cls, malloc_zone_t *zone) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT id _objc_rootAlloc(Class cls) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void _objc_rootDealloc(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void _objc_rootFinalize(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT malloc_zone_t * _objc_rootZone(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT uintptr_t _objc_rootHash(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void * objc_autoreleasePoolPush(void) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void objc_autoreleasePoolPop(void *context) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT id objc_retain(id obj) __asm__("_objc_retain") __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void objc_release(id obj) __asm__("_objc_release") __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT id objc_autorelease(id obj) __asm__("_objc_autorelease") __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); // wraps objc_autorelease(obj) in a useful way when used with return values OBJC_EXPORT id objc_autoreleaseReturnValue(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); // wraps objc_autorelease(objc_retain(obj)) in a useful way when used with return values OBJC_EXPORT id objc_retainAutoreleaseReturnValue(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); // called ONLY by ARR by callers to undo the autorelease (if possible), otherwise objc_retain OBJC_EXPORT id objc_retainAutoreleasedReturnValue(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void objc_storeStrong(id *location, id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT id objc_retainAutorelease(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); // obsolete. OBJC_EXPORT id objc_retain_autorelease(id obj) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT id objc_loadWeakRetained(id *location) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT id objc_initWeak(id *addr, id val) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void objc_destroyWeak(id *addr) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void objc_copyWeak(id *to, id *from) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void objc_moveWeak(id *to, id *from) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void _objc_autoreleasePoolPrint(void) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT BOOL objc_should_deallocate(id object) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void objc_clear_deallocating(id object) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); // to make CF link for now OBJC_EXPORT void * _objc_autoreleasePoolPush(void) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); OBJC_EXPORT void _objc_autoreleasePoolPop(void *context) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); // API to only be called by classes that provide their own reference count storage OBJC_EXPORT void _objc_deallocOnMainThreadHelper(void *context) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); #define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \ -(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 < 0) { \ __builtin_trap(); /* BUG: retain of dealloc'ed ref */ \ } \ return self; \ } \ -(oneway void)release { \ __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \ if (_prev == 0) { \ if (__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \ if (_dealloc2main) { \ dispatch_barrier_async_f(dispatch_get_main_queue(), \ self, _objc_deallocOnMainThreadHelper); \ } else { \ [self dealloc]; \ } \ } else { \ __builtin_trap(); /* BUG: dangling ref did a retain */ \ } \ } else if (_prev < 0) { \ __builtin_trap(); /* BUG: over-release */ \ } \ } \ -(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(_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