mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-17 19:09:56 +00:00
470 lines
18 KiB
C
470 lines
18 KiB
C
/*
|
|
* 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 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);
|
|
|
|
// Initializer called by libSystem
|
|
#if __OBJC2__
|
|
OBJC_EXPORT void _objc_init(void)
|
|
__OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
|
|
#endif
|
|
|
|
// 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;
|
|
|
|
// Install handler for allocation failures.
|
|
// Handler may abort, or throw, or provide an object to return.
|
|
OBJC_EXPORT void _objc_setBadAllocHandler(id (*newHandler)(Class isa))
|
|
__OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
|
|
|
|
// 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);
|
|
|
|
// Obsolete ARC conversions.
|
|
|
|
// hack - remove and reinstate objc.h's definitions
|
|
#undef objc_retainedObject
|
|
#undef objc_unretainedObject
|
|
#undef objc_unretainedPointer
|
|
OBJC_EXPORT id objc_retainedObject(objc_objectptr_t pointer)
|
|
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
|
|
OBJC_EXPORT id objc_unretainedObject(objc_objectptr_t pointer)
|
|
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
|
|
OBJC_EXPORT objc_objectptr_t objc_unretainedPointer(id object)
|
|
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
|
|
#if __has_feature(objc_arc)
|
|
# define objc_retainedObject(o) ((__bridge_transfer id)(objc_objectptr_t)(o))
|
|
# define objc_unretainedObject(o) ((__bridge id)(objc_objectptr_t)(o))
|
|
# define objc_unretainedPointer(o) ((__bridge objc_objectptr_t)(id)(o))
|
|
#else
|
|
# define objc_retainedObject(o) ((id)(objc_objectptr_t)(o))
|
|
# define objc_unretainedObject(o) ((id)(objc_objectptr_t)(o))
|
|
# define objc_unretainedPointer(o) ((objc_objectptr_t)(id)(o))
|
|
#endif
|
|
|
|
// 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);
|
|
|
|
|
|
// Extra @encode data for XPC, or NULL
|
|
OBJC_EXPORT const char *_protocol_getMethodTypeEncoding(Protocol *p, SEL sel, BOOL isRequiredMethod, BOOL isInstanceMethod)
|
|
__OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_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);
|
|
|
|
// 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
|