1/* 2 * Copyright (c) 2009 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 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. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 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. 34 */ 35 36/* 37 * objc-internal.h: Private SPI for use by other system frameworks. 38 */ 39 40#include <objc/objc.h> 41#include <objc/runtime.h> 42#include <Availability.h> 43#include <malloc/malloc.h> 44#include <dispatch/dispatch.h> 45 46__BEGIN_DECLS 47 48// This is the allocation size required for each of the class and the metaclass 49// with objc_initializeClassPair() and objc_readClassPair(). 50// The runtime's class structure will never grow beyond this. 51#define OBJC_MAX_CLASS_SIZE (32*sizeof(void*)) 52 53// In-place construction of an Objective-C class. 54// cls and metacls must each be OBJC_MAX_CLASS_SIZE bytes. 55// Returns nil if a class with the same name already exists. 56// Returns nil if the superclass is under construction. 57// Call objc_registerClassPair() when you are done. 58OBJC_EXPORT Class objc_initializeClassPair(Class superclass, const char *name, Class cls, Class metacls) 59 __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0); 60 61// Class and metaclass construction from a compiler-generated memory image. 62// cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes. 63// Extra bytes not used the the metadata must be zero. 64// info is the same objc_image_info that would be emitted by a static compiler. 65// Returns nil if a class with the same name already exists. 66// Returns nil if the superclass is nil and the class is not marked as a root. 67// Returns nil if the superclass is under construction. 68// Do not call objc_registerClassPair(). 69#if __OBJC2__ 70struct objc_image_info; 71OBJC_EXPORT Class objc_readClassPair(Class cls, 72 const struct objc_image_info *info) 73 __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); 74#endif 75 76// Batch object allocation using malloc_zone_batch_malloc(). 77OBJC_EXPORT unsigned class_createInstances(Class cls, size_t extraBytes, 78 id *results, unsigned num_requested) 79 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3) 80 OBJC_ARC_UNAVAILABLE; 81 82// Get the isa pointer written into objects just before being freed. 83OBJC_EXPORT Class _objc_getFreedObjectClass(void) 84 __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 85 86// Return YES if GC is on and `object` is a GC allocation. 87OBJC_EXPORT BOOL objc_isAuto(id object) 88 __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); 89 90// env NSObjCMessageLoggingEnabled 91OBJC_EXPORT void instrumentObjcMessageSends(BOOL flag) 92 __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 93 94// Initializer called by libSystem 95#if __OBJC2__ 96OBJC_EXPORT void _objc_init(void) 97 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0); 98#endif 99 100// GC startup callback from Foundation 101OBJC_EXPORT malloc_zone_t *objc_collect_init(int (*callback)(void)) 102 __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_NA); 103 104// Plainly-implemented GC barriers. Rosetta used to use these. 105OBJC_EXPORT id objc_assign_strongCast_generic(id value, id *dest) 106 UNAVAILABLE_ATTRIBUTE; 107OBJC_EXPORT id objc_assign_global_generic(id value, id *dest) 108 UNAVAILABLE_ATTRIBUTE; 109OBJC_EXPORT id objc_assign_threadlocal_generic(id value, id *dest) 110 UNAVAILABLE_ATTRIBUTE; 111OBJC_EXPORT id objc_assign_ivar_generic(id value, id dest, ptrdiff_t offset) 112 UNAVAILABLE_ATTRIBUTE; 113 114// Install missing-class callback. Used by the late unlamented ZeroLink. 115OBJC_EXPORT void _objc_setClassLoader(BOOL (*newClassLoader)(const char *)) OBJC2_UNAVAILABLE; 116 117// Install handler for allocation failures. 118// Handler may abort, or throw, or provide an object to return. 119OBJC_EXPORT void _objc_setBadAllocHandler(id (*newHandler)(Class isa)) 120 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0); 121 122// This can go away when AppKit stops calling it (rdar://7811851) 123#if __OBJC2__ 124OBJC_EXPORT void objc_setMultithreaded (BOOL flag) 125 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5, __IPHONE_NA,__IPHONE_NA); 126#endif 127 128// Used by ExceptionHandling.framework 129#if !__OBJC2__ 130OBJC_EXPORT void _objc_error(id rcv, const char *fmt, va_list args) 131 __attribute__((noreturn)) 132 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5, __IPHONE_NA,__IPHONE_NA); 133 134#endif 135 136 137// Tagged pointer objects. 138 139#if __LP64__ 140#define OBJC_HAVE_TAGGED_POINTERS 1 141#endif 142 143#if OBJC_HAVE_TAGGED_POINTERS 144 145// Tagged pointer layout and usage is subject to change 146// on different OS versions. The current layout is: 147// (MSB) 148// 60 bits payload 149// 3 bits tag index 150// 1 bit 1 for tagged pointer objects, 0 for ordinary objects 151// (LSB) 152 153#if __has_feature(objc_fixed_enum) || __cplusplus >= 201103L 154enum objc_tag_index_t : uint8_t 155#else 156typedef uint8_t objc_tag_index_t; 157enum 158#endif 159{ 160 OBJC_TAG_NSAtom = 0, 161 OBJC_TAG_1 = 1, 162 OBJC_TAG_NSString = 2, 163 OBJC_TAG_NSNumber = 3, 164 OBJC_TAG_NSIndexPath = 4, 165 OBJC_TAG_NSManagedObjectID = 5, 166 OBJC_TAG_NSDate = 6, 167 OBJC_TAG_7 = 7 168}; 169#if __has_feature(objc_fixed_enum) && !defined(__cplusplus) 170typedef enum objc_tag_index_t objc_tag_index_t; 171#endif 172 173OBJC_EXPORT void _objc_registerTaggedPointerClass(objc_tag_index_t tag, Class cls) 174 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); 175 176OBJC_EXPORT Class _objc_getClassForTag(objc_tag_index_t tag) 177 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); 178 179static inline bool 180_objc_taggedPointersEnabled(void) 181{ 182 extern uintptr_t objc_debug_taggedpointer_mask; 183 return (objc_debug_taggedpointer_mask != 0); 184} 185 186#if TARGET_OS_IPHONE 187// tagged pointer marker is MSB 188 189static inline void * 190_objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t value) 191{ 192 // assert(_objc_taggedPointersEnabled()); 193 // assert((unsigned int)tag < 8); 194 // assert(((value << 4) >> 4) == value); 195 return (void*)((1UL << 63) | ((uintptr_t)tag << 60) | (value & ~(0xFUL << 60))); 196} 197 198static inline bool 199_objc_isTaggedPointer(const void *ptr) 200{ 201 return (intptr_t)ptr < 0; // a.k.a. ptr & 0x8000000000000000 202} 203 204static inline objc_tag_index_t 205_objc_getTaggedPointerTag(const void *ptr) 206{ 207 // assert(_objc_isTaggedPointer(ptr)); 208 return (objc_tag_index_t)(((uintptr_t)ptr >> 60) & 0x7); 209} 210 211static inline uintptr_t 212_objc_getTaggedPointerValue(const void *ptr) 213{ 214 // assert(_objc_isTaggedPointer(ptr)); 215 return (uintptr_t)ptr & 0x0fffffffffffffff; 216} 217 218static inline intptr_t 219_objc_getTaggedPointerSignedValue(const void *ptr) 220{ 221 // assert(_objc_isTaggedPointer(ptr)); 222 return ((intptr_t)ptr << 4) >> 4; 223} 224 225// TARGET_OS_IPHONE 226#else 227// not TARGET_OS_IPHONE 228// tagged pointer marker is LSB 229 230static inline void * 231_objc_makeTaggedPointer(objc_tag_index_t tag, uintptr_t value) 232{ 233 // assert(_objc_taggedPointersEnabled()); 234 // assert((unsigned int)tag < 8); 235 // assert(((value << 4) >> 4) == value); 236 return (void *)((value << 4) | ((uintptr_t)tag << 1) | 1); 237} 238 239static inline bool 240_objc_isTaggedPointer(const void *ptr) 241{ 242 return (uintptr_t)ptr & 1; 243} 244 245static inline objc_tag_index_t 246_objc_getTaggedPointerTag(const void *ptr) 247{ 248 // assert(_objc_isTaggedPointer(ptr)); 249 return (objc_tag_index_t)(((uintptr_t)ptr & 0xe) >> 1); 250} 251 252static inline uintptr_t 253_objc_getTaggedPointerValue(const void *ptr) 254{ 255 // assert(_objc_isTaggedPointer(ptr)); 256 return (uintptr_t)ptr >> 4; 257} 258 259static inline intptr_t 260_objc_getTaggedPointerSignedValue(const void *ptr) 261{ 262 // assert(_objc_isTaggedPointer(ptr)); 263 return (intptr_t)ptr >> 4; 264} 265 266// not TARGET_OS_IPHONE 267#endif 268 269 270OBJC_EXPORT void _objc_insert_tagged_isa(unsigned char slotNumber, Class isa) 271 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7,__MAC_10_9, __IPHONE_4_3,__IPHONE_7_0); 272 273#endif 274 275 276// External Reference support. Used to support compaction. 277 278enum { 279 OBJC_XREF_STRONG = 1, 280 OBJC_XREF_WEAK = 2 281}; 282typedef uintptr_t objc_xref_type_t; 283typedef uintptr_t objc_xref_t; 284 285OBJC_EXPORT objc_xref_t _object_addExternalReference(id object, objc_xref_type_t type) 286 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); 287OBJC_EXPORT void _object_removeExternalReference(objc_xref_t xref) 288 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); 289OBJC_EXPORT id _object_readExternalReference(objc_xref_t xref) 290 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); 291 292OBJC_EXPORT uintptr_t _object_getExternalHash(id object) 293 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 294 295/** 296 * Returns the method implementation of an object. 297 * 298 * @param obj An Objective-C object. 299 * @param name An Objective-C selector. 300 * 301 * @return The IMP corresponding to the instance method implemented by 302 * the class of \e obj. 303 * 304 * @note Equivalent to: 305 * 306 * class_getMethodImplementation(object_getClass(obj), name); 307 */ 308OBJC_EXPORT IMP object_getMethodImplementation(id obj, SEL name) 309 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); 310 311OBJC_EXPORT IMP object_getMethodImplementation_stret(id obj, SEL name) 312 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0) 313 OBJC_ARM64_UNAVAILABLE; 314 315 316// Instance-specific instance variable layout. 317 318OBJC_EXPORT void _class_setIvarLayoutAccessor(Class cls_gen, const uint8_t* (*accessor) (id object)) 319 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); 320OBJC_EXPORT const uint8_t *_object_getIvarLayout(Class cls_gen, id object) 321 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); 322 323OBJC_EXPORT BOOL _class_usesAutomaticRetainRelease(Class cls) 324 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 325 326OBJC_EXPORT BOOL _class_isFutureClass(Class cls) 327 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); 328 329 330// Obsolete ARC conversions. 331 332// hack - remove and reinstate objc.h's definitions 333#undef objc_retainedObject 334#undef objc_unretainedObject 335#undef objc_unretainedPointer 336OBJC_EXPORT id objc_retainedObject(objc_objectptr_t pointer) 337 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 338OBJC_EXPORT id objc_unretainedObject(objc_objectptr_t pointer) 339 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 340OBJC_EXPORT objc_objectptr_t objc_unretainedPointer(id object) 341 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 342#if __has_feature(objc_arc) 343# define objc_retainedObject(o) ((__bridge_transfer id)(objc_objectptr_t)(o)) 344# define objc_unretainedObject(o) ((__bridge id)(objc_objectptr_t)(o)) 345# define objc_unretainedPointer(o) ((__bridge objc_objectptr_t)(id)(o)) 346#else 347# define objc_retainedObject(o) ((id)(objc_objectptr_t)(o)) 348# define objc_unretainedObject(o) ((id)(objc_objectptr_t)(o)) 349# define objc_unretainedPointer(o) ((objc_objectptr_t)(id)(o)) 350#endif 351 352// API to only be called by root classes like NSObject or NSProxy 353 354OBJC_EXPORT 355id 356_objc_rootRetain(id obj) 357 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 358 359OBJC_EXPORT 360void 361_objc_rootRelease(id obj) 362 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 363 364OBJC_EXPORT 365bool 366_objc_rootReleaseWasZero(id obj) 367 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 368 369OBJC_EXPORT 370bool 371_objc_rootTryRetain(id obj) 372__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 373 374OBJC_EXPORT 375bool 376_objc_rootIsDeallocating(id obj) 377__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 378 379OBJC_EXPORT 380id 381_objc_rootAutorelease(id obj) 382 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 383 384OBJC_EXPORT 385uintptr_t 386_objc_rootRetainCount(id obj) 387 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 388 389OBJC_EXPORT 390id 391_objc_rootInit(id obj) 392 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 393 394OBJC_EXPORT 395id 396_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone) 397 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 398 399OBJC_EXPORT 400id 401_objc_rootAlloc(Class cls) 402 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 403 404OBJC_EXPORT 405void 406_objc_rootDealloc(id obj) 407 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 408 409OBJC_EXPORT 410void 411_objc_rootFinalize(id obj) 412 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 413 414OBJC_EXPORT 415malloc_zone_t * 416_objc_rootZone(id obj) 417 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 418 419OBJC_EXPORT 420uintptr_t 421_objc_rootHash(id obj) 422 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 423 424OBJC_EXPORT 425void * 426objc_autoreleasePoolPush(void) 427 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 428 429OBJC_EXPORT 430void 431objc_autoreleasePoolPop(void *context) 432 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 433 434 435OBJC_EXPORT id objc_alloc(Class cls) 436 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); 437 438OBJC_EXPORT id objc_allocWithZone(Class cls) 439 __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); 440 441OBJC_EXPORT id objc_retain(id obj) 442 __asm__("_objc_retain") 443 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 444 445OBJC_EXPORT void objc_release(id obj) 446 __asm__("_objc_release") 447 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 448 449OBJC_EXPORT id objc_autorelease(id obj) 450 __asm__("_objc_autorelease") 451 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 452 453// wraps objc_autorelease(obj) in a useful way when used with return values 454OBJC_EXPORT 455id 456objc_autoreleaseReturnValue(id obj) 457 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 458 459// wraps objc_autorelease(objc_retain(obj)) in a useful way when used with return values 460OBJC_EXPORT 461id 462objc_retainAutoreleaseReturnValue(id obj) 463 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 464 465// called ONLY by ARR by callers to undo the autorelease (if possible), otherwise objc_retain 466OBJC_EXPORT 467id 468objc_retainAutoreleasedReturnValue(id obj) 469 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 470 471OBJC_EXPORT 472void 473objc_storeStrong(id *location, id obj) 474 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 475 476OBJC_EXPORT 477id 478objc_retainAutorelease(id obj) 479 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 480 481// obsolete. 482OBJC_EXPORT id objc_retain_autorelease(id obj) 483 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 484 485OBJC_EXPORT 486id 487objc_loadWeakRetained(id *location) 488 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 489 490OBJC_EXPORT 491id 492objc_initWeak(id *addr, id val) 493 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 494 495OBJC_EXPORT 496void 497objc_destroyWeak(id *addr) 498 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 499 500OBJC_EXPORT 501void 502objc_copyWeak(id *to, id *from) 503 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 504 505OBJC_EXPORT 506void 507objc_moveWeak(id *to, id *from) 508 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 509 510 511OBJC_EXPORT 512void 513_objc_autoreleasePoolPrint(void) 514 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 515 516OBJC_EXPORT BOOL objc_should_deallocate(id object) 517 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 518 519OBJC_EXPORT void objc_clear_deallocating(id object) 520 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 521 522 523// to make CF link for now 524 525OBJC_EXPORT 526void * 527_objc_autoreleasePoolPush(void) 528 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 529 530OBJC_EXPORT 531void 532_objc_autoreleasePoolPop(void *context) 533 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 534 535 536// Extra @encode data for XPC, or NULL 537OBJC_EXPORT const char *_protocol_getMethodTypeEncoding(Protocol *p, SEL sel, BOOL isRequiredMethod, BOOL isInstanceMethod) 538 __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0); 539 540 541// API to only be called by classes that provide their own reference count storage 542 543OBJC_EXPORT 544void 545_objc_deallocOnMainThreadHelper(void *context) 546 __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0); 547 548// On async versus sync deallocation and the _dealloc2main flag 549// 550// Theory: 551// 552// If order matters, then code must always: [self dealloc]. 553// If order doesn't matter, then always async should be safe. 554// 555// Practice: 556// 557// The _dealloc2main bit is set for GUI objects that may be retained by other 558// threads. Once deallocation begins on the main thread, doing more async 559// deallocation will at best cause extra UI latency and at worst cause 560// use-after-free bugs in unretained delegate style patterns. Yes, this is 561// extremely fragile. Yes, in the long run, developers should switch to weak 562// references. 563// 564// Note is NOT safe to do any equality check against the result of 565// dispatch_get_current_queue(). The main thread can and does drain more than 566// one dispatch queue. That is why we call pthread_main_np(). 567// 568 569typedef enum { 570 _OBJC_RESURRECT_OBJECT = -1, /* _logicBlock has called -retain, and scheduled a -release for later. */ 571 _OBJC_DEALLOC_OBJECT_NOW = 1, /* call [self dealloc] immediately. */ 572 _OBJC_DEALLOC_OBJECT_LATER = 2 /* call [self dealloc] on the main queue. */ 573} _objc_object_disposition_t; 574 575#define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, _logicBlock) \ 576 -(id)retain { \ 577 /* this will fail to compile if _rc_ivar is an unsigned type */ \ 578 int _retain_count_ivar_must_not_be_unsigned[0L - (__typeof__(_rc_ivar))-1] __attribute__((unused)); \ 579 __typeof__(_rc_ivar) _prev = __sync_fetch_and_add(&_rc_ivar, 2); \ 580 if (_prev < -2) { /* specifically allow resurrection from logical 0. */ \ 581 __builtin_trap(); /* BUG: retain of over-released ref */ \ 582 } \ 583 return self; \ 584 } \ 585 -(oneway void)release { \ 586 __typeof__(_rc_ivar) _prev = __sync_fetch_and_sub(&_rc_ivar, 2); \ 587 if (_prev > 0) { \ 588 return; \ 589 } else if (_prev < 0) { \ 590 __builtin_trap(); /* BUG: over-release */ \ 591 } \ 592 _objc_object_disposition_t fate = _logicBlock(self); \ 593 if (fate == _OBJC_RESURRECT_OBJECT) { \ 594 return; \ 595 } \ 596 /* mark the object as deallocating. */ \ 597 if (!__sync_bool_compare_and_swap(&_rc_ivar, -2, 1)) { \ 598 __builtin_trap(); /* BUG: dangling ref did a retain */ \ 599 } \ 600 if (fate == _OBJC_DEALLOC_OBJECT_NOW) { \ 601 [self dealloc]; \ 602 } else if (fate == _OBJC_DEALLOC_OBJECT_LATER) { \ 603 dispatch_barrier_async_f(dispatch_get_main_queue(), self, \ 604 _objc_deallocOnMainThreadHelper); \ 605 } else { \ 606 __builtin_trap(); /* BUG: bogus fate value */ \ 607 } \ 608 } \ 609 -(NSUInteger)retainCount { \ 610 return (_rc_ivar + 2) >> 1; \ 611 } \ 612 -(BOOL)_tryRetain { \ 613 __typeof__(_rc_ivar) _prev; \ 614 do { \ 615 _prev = _rc_ivar; \ 616 if (_prev & 1) { \ 617 return 0; \ 618 } else if (_prev == -2) { \ 619 return 0; \ 620 } else if (_prev < -2) { \ 621 __builtin_trap(); /* BUG: over-release elsewhere */ \ 622 } \ 623 } while ( ! __sync_bool_compare_and_swap(&_rc_ivar, _prev, _prev + 2)); \ 624 return 1; \ 625 } \ 626 -(BOOL)_isDeallocating { \ 627 if (_rc_ivar == -2) { \ 628 return 1; \ 629 } else if (_rc_ivar < -2) { \ 630 __builtin_trap(); /* BUG: over-release elsewhere */ \ 631 } \ 632 return _rc_ivar & 1; \ 633 } 634 635#define _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, _dealloc2main) \ 636 _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC_BLOCK(_rc_ivar, (^(id _self_ __attribute__((unused))) { \ 637 if (_dealloc2main && !pthread_main_np()) { \ 638 return _OBJC_DEALLOC_OBJECT_LATER; \ 639 } else { \ 640 return _OBJC_DEALLOC_OBJECT_NOW; \ 641 } \ 642 })) 643 644#define _OBJC_SUPPORTED_INLINE_REFCNT(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 0) 645#define _OBJC_SUPPORTED_INLINE_REFCNT_WITH_DEALLOC2MAIN(_rc_ivar) _OBJC_SUPPORTED_INLINE_REFCNT_LOGIC(_rc_ivar, 1) 646 647__END_DECLS 648 649#endif 650