1/* 2 * Copyright (c) 1999-2007 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 * objc-private.h 25 * Copyright 1988-1996, NeXT Software, Inc. 26 */ 27 28#ifndef _OBJC_PRIVATE_H_ 29#define _OBJC_PRIVATE_H_ 30 31#include "objc-config.h" 32 33/* Isolate ourselves from the definitions of id and Class in the compiler 34 * and public headers. 35 */ 36 37#ifdef _OBJC_OBJC_H_ 38#error include objc-private.h before other headers 39#endif 40 41#define OBJC_TYPES_DEFINED 1 42#define OBJC_OLD_DISPATCH_PROTOTYPES 0 43 44#include <cstddef> // for nullptr_t 45#include <stdint.h> 46#include <assert.h> 47 48struct objc_class; 49struct objc_object; 50 51typedef struct objc_class *Class; 52typedef struct objc_object *id; 53 54namespace { 55 class SideTable; 56}; 57 58 59union isa_t 60{ 61 isa_t() { } 62 isa_t(uintptr_t value) : bits(value) { } 63 64 Class cls; 65 uintptr_t bits; 66 67#if SUPPORT_NONPOINTER_ISA 68 69 // extra_rc must be the MSB-most field (so it matches carry/overflow flags) 70 // indexed must be the LSB (fixme or get rid of it) 71 // shiftcls must occupy the same bits that a real class pointer would 72 // bits + RC_ONE is equivalent to extra_rc + 1 73 // RC_HALF is the high bit of extra_rc (i.e. half of its range) 74 75 // future expansion: 76 // uintptr_t fast_rr : 1; // no r/r overrides 77 // uintptr_t lock : 2; // lock for atomic property, @synch 78 // uintptr_t extraBytes : 1; // allocated with extra bytes 79 80# if __arm64__ 81# define ISA_MASK 0x00000001fffffff8ULL 82# define ISA_MAGIC_MASK 0x000003fe00000001ULL 83# define ISA_MAGIC_VALUE 0x000001a400000001ULL 84 struct { 85 uintptr_t indexed : 1; 86 uintptr_t has_assoc : 1; 87 uintptr_t has_cxx_dtor : 1; 88 uintptr_t shiftcls : 30; // MACH_VM_MAX_ADDRESS 0x1a0000000 89 uintptr_t magic : 9; 90 uintptr_t weakly_referenced : 1; 91 uintptr_t deallocating : 1; 92 uintptr_t has_sidetable_rc : 1; 93 uintptr_t extra_rc : 19; 94# define RC_ONE (1ULL<<45) 95# define RC_HALF (1ULL<<18) 96 }; 97 98# elif __x86_64__ 99# define ISA_MASK 0x00007ffffffffff8ULL 100# define ISA_MAGIC_MASK 0x0000000000000001ULL 101# define ISA_MAGIC_VALUE 0x0000000000000001ULL 102 struct { 103 uintptr_t indexed : 1; 104 uintptr_t has_assoc : 1; 105 uintptr_t has_cxx_dtor : 1; 106 uintptr_t shiftcls : 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000 107 uintptr_t weakly_referenced : 1; 108 uintptr_t deallocating : 1; 109 uintptr_t has_sidetable_rc : 1; 110 uintptr_t extra_rc : 14; 111# define RC_ONE (1ULL<<50) 112# define RC_HALF (1ULL<<13) 113 }; 114 115# else 116 // Available bits in isa field are architecture-specific. 117# error unknown architecture 118# endif 119 120// SUPPORT_NONPOINTER_ISA 121#endif 122 123}; 124 125 126struct objc_object { 127private: 128 isa_t isa; 129 130public: 131 132 // ISA() assumes this is NOT a tagged pointer object 133 Class ISA(); 134 135 // getIsa() allows this to be a tagged pointer object 136 Class getIsa(); 137 138 // initIsa() should be used to init the isa of new objects only. 139 // If this object already has an isa, use changeIsa() for correctness. 140 // initInstanceIsa(): objects with no custom RR/AWZ 141 // initClassIsa(): class objects 142 // initProtocolIsa(): protocol objects 143 // initIsa(): other objects 144 void initIsa(Class cls /*indexed=false*/); 145 void initClassIsa(Class cls /*indexed=maybe*/); 146 void initProtocolIsa(Class cls /*indexed=maybe*/); 147 void initInstanceIsa(Class cls, bool hasCxxDtor); 148 149 // changeIsa() should be used to change the isa of existing objects. 150 // If this is a new object, use initIsa() for performance. 151 Class changeIsa(Class newCls); 152 153 bool hasIndexedIsa(); 154 bool isTaggedPointer(); 155 bool isClass(); 156 157 // object may have associated objects? 158 bool hasAssociatedObjects(); 159 void setHasAssociatedObjects(); 160 161 // object may be weakly referenced? 162 bool isWeaklyReferenced(); 163 void setWeaklyReferenced_nolock(); 164 165 // object may have -.cxx_destruct implementation? 166 bool hasCxxDtor(); 167 168 // Optimized calls to retain/release methods 169 id retain(); 170 void release(); 171 id autorelease(); 172 173 // Implementations of retain/release methods 174 id rootRetain(); 175 bool rootRelease(); 176 id rootAutorelease(); 177 bool rootTryRetain(); 178 bool rootReleaseShouldDealloc(); 179 uintptr_t rootRetainCount(); 180 181 // Implementation of dealloc methods 182 bool rootIsDeallocating(); 183 void clearDeallocating(); 184 void rootDealloc(); 185 186private: 187 void initIsa(Class newCls, bool indexed, bool hasCxxDtor); 188 189 // Slow paths for inline control 190 id rootAutorelease2(); 191 bool overrelease_error(); 192 193#if SUPPORT_NONPOINTER_ISA 194 // Unified retain count manipulation for nonpointer isa 195 id rootRetain(bool tryRetain, bool handleOverflow); 196 bool rootRelease(bool performDealloc, bool handleUnderflow); 197 id rootRetain_overflow(bool tryRetain); 198 bool rootRelease_underflow(bool performDealloc); 199 200 void clearDeallocating_weak(); 201 202 // Side table retain count overflow for nonpointer isa 203 void sidetable_lock(); 204 void sidetable_unlock(); 205 206 void sidetable_moveExtraRC_nolock(size_t extra_rc, bool isDeallocating, bool weaklyReferenced); 207 bool sidetable_addExtraRC_nolock(size_t delta_rc); 208 bool sidetable_subExtraRC_nolock(size_t delta_rc); 209 size_t sidetable_getExtraRC_nolock(); 210#endif 211 212 // Side-table-only retain count 213 bool sidetable_isDeallocating(); 214 void sidetable_clearDeallocating(); 215 216 bool sidetable_isWeaklyReferenced(); 217 void sidetable_setWeaklyReferenced_nolock(); 218 219 id sidetable_retain(); 220 id sidetable_retain_slow(SideTable *table); 221 222 bool sidetable_release(bool performDealloc = true); 223 bool sidetable_release_slow(SideTable *table, bool performDealloc = true); 224 225 bool sidetable_tryRetain(); 226 227 uintptr_t sidetable_retainCount(); 228#if !NDEBUG 229 bool sidetable_present(); 230#endif 231}; 232 233 234#if __OBJC2__ 235typedef struct method_t *Method; 236typedef struct ivar_t *Ivar; 237typedef struct category_t *Category; 238typedef struct property_t *objc_property_t; 239#else 240typedef struct old_method *Method; 241typedef struct old_ivar *Ivar; 242typedef struct old_category *Category; 243typedef struct old_property *objc_property_t; 244#endif 245 246// Public headers 247 248#include "objc.h" 249#include "runtime.h" 250#include "objc-os.h" 251#include "objc-abi.h" 252#include "objc-api.h" 253#include "objc-auto.h" 254#include "objc-config.h" 255#include "objc-internal.h" 256#include "maptable.h" 257#include "hashtable2.h" 258 259/* Do not include message.h here. */ 260/* #include "message.h" */ 261 262#define __APPLE_API_PRIVATE 263#include "objc-gdb.h" 264#undef __APPLE_API_PRIVATE 265 266 267// Private headers 268 269#if __OBJC2__ 270#include "objc-runtime-new.h" 271#else 272#include "objc-runtime-old.h" 273#endif 274 275#include "objc-references.h" 276#include "objc-initialize.h" 277#include "objc-loadmethod.h" 278 279 280__BEGIN_DECLS 281 282 283#if (defined(OBJC_NO_GC) && SUPPORT_GC) || \ 284 (!defined(OBJC_NO_GC) && !SUPPORT_GC) 285# error OBJC_NO_GC and SUPPORT_GC inconsistent 286#endif 287 288#if SUPPORT_GC 289# include <auto_zone.h> 290 // PRIVATE_EXTERN is needed to help the compiler know "how" extern these are 291 PRIVATE_EXTERN extern int8_t UseGC; // equivalent to calling objc_collecting_enabled() 292 PRIVATE_EXTERN extern auto_zone_t *gc_zone; // the GC zone, or NULL if no GC 293 extern void objc_addRegisteredClass(Class c); 294 extern void objc_removeRegisteredClass(Class c); 295#else 296# define UseGC NO 297# define gc_zone NULL 298# define objc_addRegisteredClass(c) do {} while(0) 299# define objc_removeRegisteredClass(c) do {} while(0) 300 /* Uses of the following must be protected with UseGC. */ 301 extern id gc_unsupported_dont_call(); 302# define auto_zone_allocate_object gc_unsupported_dont_call 303# define auto_zone_retain gc_unsupported_dont_call 304# define auto_zone_release gc_unsupported_dont_call 305# define auto_zone_is_valid_pointer gc_unsupported_dont_call 306# define auto_zone_write_barrier_memmove gc_unsupported_dont_call 307# define AUTO_OBJECT_SCANNED 0 308#endif 309 310 311#define _objcHeaderIsReplacement(h) ((h)->info && ((h)->info->flags & OBJC_IMAGE_IS_REPLACEMENT)) 312 313/* OBJC_IMAGE_IS_REPLACEMENT: 314 Don't load any classes 315 Don't load any categories 316 Do fix up selector refs (@selector points to them) 317 Do fix up class refs (@class and objc_msgSend points to them) 318 Do fix up protocols (@protocol points to them) 319 Do fix up superclass pointers in classes ([super ...] points to them) 320 Future: do load new classes? 321 Future: do load new categories? 322 Future: do insert new methods on existing classes? 323 Future: do insert new methods on existing categories? 324*/ 325 326#define _objcInfoSupportsGC(info) (((info)->flags & OBJC_IMAGE_SUPPORTS_GC) ? 1 : 0) 327#define _objcInfoRequiresGC(info) (((info)->flags & OBJC_IMAGE_REQUIRES_GC) ? 1 : 0) 328#define _objcHeaderSupportsGC(h) ((h)->info && _objcInfoSupportsGC((h)->info)) 329#define _objcHeaderRequiresGC(h) ((h)->info && _objcInfoRequiresGC((h)->info)) 330 331/* OBJC_IMAGE_SUPPORTS_GC: 332 was compiled with -fobjc-gc flag, regardless of whether write-barriers were issued 333 if executable image compiled this way, then all subsequent libraries etc. must also be this way 334*/ 335 336#define _objcHeaderOptimizedByDyld(h) ((h)->info && ((h)->info->flags & OBJC_IMAGE_OPTIMIZED_BY_DYLD)) 337 338/* OBJC_IMAGE_OPTIMIZED_BY_DYLD: 339 Assorted metadata precooked in the dyld shared cache. 340 Never set for images outside the shared cache file itself. 341*/ 342 343 344typedef struct _header_info { 345 struct _header_info *next; 346 const headerType *mhdr; 347 const objc_image_info *info; 348 const char *fname; // same as Dl_info.dli_fname 349 bool loaded; 350 bool inSharedCache; 351 bool allClassesRealized; 352 353 // Do not add fields without editing ObjCModernAbstraction.hpp 354 355#if !__OBJC2__ 356 struct old_protocol **proto_refs; 357 struct objc_module *mod_ptr; 358 size_t mod_count; 359# if TARGET_OS_WIN32 360 struct objc_module **modules; 361 size_t moduleCount; 362 struct old_protocol **protocols; 363 size_t protocolCount; 364 void *imageinfo; 365 size_t imageinfoBytes; 366 SEL *selrefs; 367 size_t selrefCount; 368 struct objc_class **clsrefs; 369 size_t clsrefCount; 370 TCHAR *moduleName; 371# endif 372#endif 373} header_info; 374 375extern header_info *FirstHeader; 376extern header_info *LastHeader; 377extern int HeaderCount; 378 379extern uint32_t AppSDKVersion; // X.Y.Z is 0xXXXXYYZZ 380 381extern void appendHeader(header_info *hi); 382extern void removeHeader(header_info *hi); 383 384extern objc_image_info *_getObjcImageInfo(const headerType *head, size_t *size); 385extern BOOL _hasObjcContents(const header_info *hi); 386 387 388/* selectors */ 389extern void sel_init(BOOL gc, size_t selrefCount); 390extern SEL sel_registerNameNoLock(const char *str, BOOL copy); 391extern void sel_lock(void); 392extern void sel_unlock(void); 393extern BOOL sel_preoptimizationValid(const header_info *hi); 394 395extern SEL SEL_load; 396extern SEL SEL_initialize; 397extern SEL SEL_resolveClassMethod; 398extern SEL SEL_resolveInstanceMethod; 399extern SEL SEL_cxx_construct; 400extern SEL SEL_cxx_destruct; 401extern SEL SEL_retain; 402extern SEL SEL_release; 403extern SEL SEL_autorelease; 404extern SEL SEL_retainCount; 405extern SEL SEL_alloc; 406extern SEL SEL_allocWithZone; 407extern SEL SEL_dealloc; 408extern SEL SEL_copy; 409extern SEL SEL_new; 410extern SEL SEL_finalize; 411extern SEL SEL_forwardInvocation; 412extern SEL SEL_tryRetain; 413extern SEL SEL_isDeallocating; 414extern SEL SEL_retainWeakReference; 415extern SEL SEL_allowsWeakReference; 416 417/* preoptimization */ 418extern void preopt_init(void); 419extern void disableSharedCacheOptimizations(void); 420extern bool isPreoptimized(void); 421extern header_info *preoptimizedHinfoForHeader(const headerType *mhdr); 422 423#if SUPPORT_PREOPT && __cplusplus 424#include <objc-shared-cache.h> 425using objc_selopt_t = const objc_opt::objc_selopt_t; 426#else 427struct objc_selopt_t; 428#endif 429 430extern objc_selopt_t *preoptimizedSelectors(void); 431extern Class getPreoptimizedClass(const char *name); 432extern Class* copyPreoptimizedClasses(const char *name, int *outCount); 433 434 435/* optional malloc zone for runtime data */ 436extern malloc_zone_t *_objc_internal_zone(void); 437extern void *_malloc_internal(size_t size); 438extern void *_calloc_internal(size_t count, size_t size); 439extern void *_realloc_internal(void *ptr, size_t size); 440extern char *_strdup_internal(const char *str); 441extern char *_strdupcat_internal(const char *s1, const char *s2); 442extern uint8_t *_ustrdup_internal(const uint8_t *str); 443extern void *_memdup_internal(const void *mem, size_t size); 444extern void _free_internal(void *ptr); 445extern size_t _malloc_size_internal(void *ptr); 446 447extern Class _calloc_class(size_t size); 448 449/* method lookup */ 450extern IMP lookUpImpOrNil(Class, SEL, id obj, bool initialize, bool cache, bool resolver); 451extern IMP lookUpImpOrForward(Class, SEL, id obj, bool initialize, bool cache, bool resolver); 452 453extern IMP lookupMethodInClassAndLoadCache(Class cls, SEL sel); 454extern BOOL class_respondsToSelector_inst(Class cls, SEL sel, id inst); 455 456extern bool objcMsgLogEnabled; 457extern bool logMessageSend(bool isClassMethod, 458 const char *objectsClass, 459 const char *implementingClass, 460 SEL selector); 461 462/* message dispatcher */ 463extern IMP _class_lookupMethodAndLoadCache3(id, SEL, Class); 464 465#if !OBJC_OLD_DISPATCH_PROTOTYPES 466extern void _objc_msgForward_impcache(void); 467extern void _objc_ignored_method(void); 468extern void _objc_msgSend_uncached_impcache(void); 469#else 470extern id _objc_msgForward_impcache(id, SEL, ...); 471extern id _objc_ignored_method(id, SEL, ...); 472extern id _objc_msgSend_uncached_impcache(id, SEL, ...); 473#endif 474 475/* errors */ 476extern void __objc_error(id, const char *, ...) __attribute__((format (printf, 2, 3), noreturn)); 477extern void _objc_inform(const char *fmt, ...) __attribute__((format (printf, 1, 2))); 478extern void _objc_inform_on_crash(const char *fmt, ...) __attribute__((format (printf, 1, 2))); 479extern void _objc_inform_now_and_on_crash(const char *fmt, ...) __attribute__((format (printf, 1, 2))); 480extern void _objc_inform_deprecated(const char *oldname, const char *newname) __attribute__((noinline)); 481extern void inform_duplicate(const char *name, Class oldCls, Class cls); 482extern bool crashlog_header_name(header_info *hi); 483extern bool crashlog_header_name_string(const char *name); 484 485/* magic */ 486extern Class _objc_getFreedObjectClass (void); 487 488/* map table additions */ 489extern void *NXMapKeyCopyingInsert(NXMapTable *table, const void *key, const void *value); 490extern void *NXMapKeyFreeingRemove(NXMapTable *table, const void *key); 491 492/* hash table additions */ 493extern unsigned _NXHashCapacity(NXHashTable *table); 494extern void _NXHashRehashToCapacity(NXHashTable *table, unsigned newCapacity); 495 496/* property attribute parsing */ 497extern const char *copyPropertyAttributeString(const objc_property_attribute_t *attrs, unsigned int count); 498extern objc_property_attribute_t *copyPropertyAttributeList(const char *attrs, unsigned int *outCount); 499extern char *copyPropertyAttributeValue(const char *attrs, const char *name); 500 501/* locking */ 502extern void lock_init(void); 503extern rwlock_t selLock; 504extern mutex_t cacheUpdateLock; 505extern recursive_mutex_t loadMethodLock; 506#if __OBJC2__ 507extern rwlock_t runtimeLock; 508#else 509extern mutex_t classLock; 510extern mutex_t methodListLock; 511#endif 512 513/* Lock debugging */ 514#if defined(NDEBUG) || TARGET_OS_WIN32 515 516#define mutex_lock(m) _mutex_lock_nodebug(m) 517#define mutex_try_lock(m) _mutex_try_lock_nodebug(m) 518#define mutex_unlock(m) _mutex_unlock_nodebug(m) 519#define mutex_assert_locked(m) do { } while (0) 520#define mutex_assert_unlocked(m) do { } while (0) 521 522#define recursive_mutex_lock(m) _recursive_mutex_lock_nodebug(m) 523#define recursive_mutex_try_lock(m) _recursive_mutex_try_lock_nodebug(m) 524#define recursive_mutex_unlock(m) _recursive_mutex_unlock_nodebug(m) 525#define recursive_mutex_assert_locked(m) do { } while (0) 526#define recursive_mutex_assert_unlocked(m) do { } while (0) 527 528#define monitor_enter(m) _monitor_enter_nodebug(m) 529#define monitor_exit(m) _monitor_exit_nodebug(m) 530#define monitor_wait(m) _monitor_wait_nodebug(m) 531#define monitor_assert_locked(m) do { } while (0) 532#define monitor_assert_unlocked(m) do { } while (0) 533 534#define rwlock_read(m) _rwlock_read_nodebug(m) 535#define rwlock_write(m) _rwlock_write_nodebug(m) 536#define rwlock_try_read(m) _rwlock_try_read_nodebug(m) 537#define rwlock_try_write(m) _rwlock_try_write_nodebug(m) 538#define rwlock_unlock_read(m) _rwlock_unlock_read_nodebug(m) 539#define rwlock_unlock_write(m) _rwlock_unlock_write_nodebug(m) 540#define rwlock_assert_reading(m) do { } while (0) 541#define rwlock_assert_writing(m) do { } while (0) 542#define rwlock_assert_locked(m) do { } while (0) 543#define rwlock_assert_unlocked(m) do { } while (0) 544 545#else 546 547extern int _mutex_lock_debug(mutex_t *lock, const char *name); 548extern int _mutex_try_lock_debug(mutex_t *lock, const char *name); 549extern int _mutex_unlock_debug(mutex_t *lock, const char *name); 550extern void _mutex_assert_locked_debug(mutex_t *lock, const char *name); 551extern void _mutex_assert_unlocked_debug(mutex_t *lock, const char *name); 552 553extern int _recursive_mutex_lock_debug(recursive_mutex_t *lock, const char *name); 554extern int _recursive_mutex_try_lock_debug(recursive_mutex_t *lock, const char *name); 555extern int _recursive_mutex_unlock_debug(recursive_mutex_t *lock, const char *name); 556extern void _recursive_mutex_assert_locked_debug(recursive_mutex_t *lock, const char *name); 557extern void _recursive_mutex_assert_unlocked_debug(recursive_mutex_t *lock, const char *name); 558 559extern int _monitor_enter_debug(monitor_t *lock, const char *name); 560extern int _monitor_exit_debug(monitor_t *lock, const char *name); 561extern int _monitor_wait_debug(monitor_t *lock, const char *name); 562extern void _monitor_assert_locked_debug(monitor_t *lock, const char *name); 563extern void _monitor_assert_unlocked_debug(monitor_t *lock, const char *name); 564 565extern void _rwlock_read_debug(rwlock_t *l, const char *name); 566extern void _rwlock_write_debug(rwlock_t *l, const char *name); 567extern int _rwlock_try_read_debug(rwlock_t *l, const char *name); 568extern int _rwlock_try_write_debug(rwlock_t *l, const char *name); 569extern void _rwlock_unlock_read_debug(rwlock_t *l, const char *name); 570extern void _rwlock_unlock_write_debug(rwlock_t *l, const char *name); 571extern void _rwlock_assert_reading_debug(rwlock_t *l, const char *name); 572extern void _rwlock_assert_writing_debug(rwlock_t *l, const char *name); 573extern void _rwlock_assert_locked_debug(rwlock_t *l, const char *name); 574extern void _rwlock_assert_unlocked_debug(rwlock_t *l, const char *name); 575 576#define mutex_lock(m) _mutex_lock_debug (m, #m) 577#define mutex_try_lock(m) _mutex_try_lock_debug (m, #m) 578#define mutex_unlock(m) _mutex_unlock_debug (m, #m) 579#define mutex_assert_locked(m) _mutex_assert_locked_debug (m, #m) 580#define mutex_assert_unlocked(m) _mutex_assert_unlocked_debug (m, #m) 581 582#define recursive_mutex_lock(m) _recursive_mutex_lock_debug (m, #m) 583#define recursive_mutex_try_lock(m) _recursive_mutex_try_lock_debug (m, #m) 584#define recursive_mutex_unlock(m) _recursive_mutex_unlock_debug (m, #m) 585#define recursive_mutex_assert_locked(m) _recursive_mutex_assert_locked_debug (m, #m) 586#define recursive_mutex_assert_unlocked(m) _recursive_mutex_assert_unlocked_debug (m, #m) 587 588#define monitor_enter(m) _monitor_enter_debug(m, #m) 589#define monitor_exit(m) _monitor_exit_debug(m, #m) 590#define monitor_wait(m) _monitor_wait_debug(m, #m) 591#define monitor_assert_locked(m) _monitor_assert_locked_debug(m, #m) 592#define monitor_assert_unlocked(m) _monitor_assert_unlocked_debug(m, #m) 593 594#define rwlock_read(m) _rwlock_read_debug(m, #m) 595#define rwlock_write(m) _rwlock_write_debug(m, #m) 596#define rwlock_try_read(m) _rwlock_try_read_debug(m, #m) 597#define rwlock_try_write(m) _rwlock_try_write_debug(m, #m) 598#define rwlock_unlock_read(m) _rwlock_unlock_read_debug(m, #m) 599#define rwlock_unlock_write(m) _rwlock_unlock_write_debug(m, #m) 600#define rwlock_assert_reading(m) _rwlock_assert_reading_debug(m, #m) 601#define rwlock_assert_writing(m) _rwlock_assert_writing_debug(m, #m) 602#define rwlock_assert_locked(m) _rwlock_assert_locked_debug(m, #m) 603#define rwlock_assert_unlocked(m) _rwlock_assert_unlocked_debug(m, #m) 604 605#endif 606 607#define rwlock_unlock(m, s) \ 608 do { \ 609 if ((s) == RDONLY) rwlock_unlock_read(m); \ 610 else if ((s) == RDWR) rwlock_unlock_write(m); \ 611 } while (0) 612 613 614/* ignored selector support */ 615 616/* Non-GC: no ignored selectors 617 GC (i386 Mac): some selectors ignored, remapped to kIgnore 618 GC (others): some selectors ignored, but not remapped 619*/ 620 621static inline int ignoreSelector(SEL sel) 622{ 623#if !SUPPORT_GC 624 return NO; 625#elif SUPPORT_IGNORED_SELECTOR_CONSTANT 626 return UseGC && sel == (SEL)kIgnore; 627#else 628 return UseGC && 629 (sel == @selector(retain) || 630 sel == @selector(release) || 631 sel == @selector(autorelease) || 632 sel == @selector(retainCount) || 633 sel == @selector(dealloc)); 634#endif 635} 636 637static inline int ignoreSelectorNamed(const char *sel) 638{ 639#if !SUPPORT_GC 640 return NO; 641#else 642 // release retain retainCount dealloc autorelease 643 return (UseGC && 644 ( (sel[0] == 'r' && sel[1] == 'e' && 645 (strcmp(&sel[2], "lease") == 0 || 646 strcmp(&sel[2], "tain") == 0 || 647 strcmp(&sel[2], "tainCount") == 0 )) 648 || 649 (strcmp(sel, "dealloc") == 0) 650 || 651 (sel[0] == 'a' && sel[1] == 'u' && 652 strcmp(&sel[2], "torelease") == 0))); 653#endif 654} 655 656/* GC startup */ 657extern void gc_init(BOOL wantsGC); 658extern void gc_init2(void); 659 660/* Exceptions */ 661struct alt_handler_list; 662extern void exception_init(void); 663extern void _destroyAltHandlerList(struct alt_handler_list *list); 664 665/* Class change notifications (gdb only for now) */ 666#define OBJC_CLASS_ADDED (1<<0) 667#define OBJC_CLASS_REMOVED (1<<1) 668#define OBJC_CLASS_IVARS_CHANGED (1<<2) 669#define OBJC_CLASS_METHODS_CHANGED (1<<3) 670extern void gdb_objc_class_changed(Class cls, unsigned long changes, const char *classname) 671 __attribute__((noinline)); 672 673#if SUPPORT_GC 674 675/* Write barrier implementations */ 676extern id objc_getAssociatedObject_non_gc(id object, const void *key); 677extern void objc_setAssociatedObject_non_gc(id object, const void *key, id value, objc_AssociationPolicy policy); 678 679extern id objc_getAssociatedObject_gc(id object, const void *key); 680extern void objc_setAssociatedObject_gc(id object, const void *key, id value, objc_AssociationPolicy policy); 681 682/* xrefs */ 683extern objc_xref_t _object_addExternalReference_non_gc(id obj, objc_xref_t type); 684extern id _object_readExternalReference_non_gc(objc_xref_t ref); 685extern void _object_removeExternalReference_non_gc(objc_xref_t ref); 686 687extern objc_xref_t _object_addExternalReference_gc(id obj, objc_xref_t type); 688extern id _object_readExternalReference_gc(objc_xref_t ref); 689extern void _object_removeExternalReference_gc(objc_xref_t ref); 690 691/* GC weak reference fixup. */ 692extern void gc_fixup_weakreferences(id newObject, id oldObject); 693 694/* GC datasegment registration. */ 695extern void gc_register_datasegment(uintptr_t base, size_t size); 696extern void gc_unregister_datasegment(uintptr_t base, size_t size); 697 698/* objc_dumpHeap implementation */ 699extern BOOL _objc_dumpHeap(auto_zone_t *zone, const char *filename); 700 701#endif 702 703 704// Settings from environment variables 705#define OPTION(var, env, help) extern bool var; 706#include "objc-env.h" 707#undef OPTION 708 709extern void environ_init(void); 710 711extern void logReplacedMethod(const char *className, SEL s, BOOL isMeta, const char *catName, IMP oldImp, IMP newImp); 712 713static __inline uint32_t _objc_strhash(const char *s) { 714 uint32_t hash = 0; 715 for (;;) { 716 int a = *s++; 717 if (0 == a) break; 718 hash += (hash << 8) + a; 719 } 720 return hash; 721} 722 723 724// objc per-thread storage 725typedef struct { 726 struct _objc_initializing_classes *initializingClasses; // for +initialize 727 struct SyncCache *syncCache; // for @synchronize 728 struct alt_handler_list *handlerList; // for exception alt handlers 729 char *printableNames[4]; // temporary demangled names for logging 730 731 // If you add new fields here, don't forget to update 732 // _objc_pthread_destroyspecific() 733 734} _objc_pthread_data; 735 736extern _objc_pthread_data *_objc_fetch_pthread_data(BOOL create); 737extern void tls_init(void); 738 739// encoding.h 740extern unsigned int encoding_getNumberOfArguments(const char *typedesc); 741extern unsigned int encoding_getSizeOfArguments(const char *typedesc); 742extern unsigned int encoding_getArgumentInfo(const char *typedesc, unsigned int arg, const char **type, int *offset); 743extern void encoding_getReturnType(const char *t, char *dst, size_t dst_len); 744extern char * encoding_copyReturnType(const char *t); 745extern void encoding_getArgumentType(const char *t, unsigned int index, char *dst, size_t dst_len); 746extern char *encoding_copyArgumentType(const char *t, unsigned int index); 747 748// sync.h 749extern void _destroySyncCache(struct SyncCache *cache); 750 751// arr 752extern void arr_init(void); 753extern id objc_autoreleaseReturnValue(id obj); 754 755// block trampolines 756extern IMP _imp_implementationWithBlockNoCopy(id block); 757 758// layout.h 759typedef struct { 760 uint8_t *bits; 761 size_t bitCount; 762 size_t bitsAllocated; 763 BOOL weak; 764} layout_bitmap; 765extern layout_bitmap layout_bitmap_create(const unsigned char *layout_string, size_t layoutStringInstanceSize, size_t instanceSize, BOOL weak); 766extern layout_bitmap layout_bitmap_create_empty(size_t instanceSize, BOOL weak); 767extern void layout_bitmap_free(layout_bitmap bits); 768extern const unsigned char *layout_string_create(layout_bitmap bits); 769extern void layout_bitmap_set_ivar(layout_bitmap bits, const char *type, size_t offset); 770extern void layout_bitmap_grow(layout_bitmap *bits, size_t newCount); 771extern void layout_bitmap_slide(layout_bitmap *bits, size_t oldPos, size_t newPos); 772extern void layout_bitmap_slide_anywhere(layout_bitmap *bits, size_t oldPos, size_t newPos); 773extern BOOL layout_bitmap_splat(layout_bitmap dst, layout_bitmap src, 774 size_t oldSrcInstanceSize); 775extern BOOL layout_bitmap_or(layout_bitmap dst, layout_bitmap src, const char *msg); 776extern BOOL layout_bitmap_clear(layout_bitmap dst, layout_bitmap src, const char *msg); 777extern void layout_bitmap_print(layout_bitmap bits); 778 779 780// fixme runtime 781extern Class look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includeClassHandler); 782extern const char *map_images(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info infoList[]); 783extern const char *map_images_nolock(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info infoList[]); 784extern const char * load_images(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info infoList[]); 785extern BOOL load_images_nolock(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info infoList[]); 786extern void unmap_image(const struct mach_header *mh, intptr_t vmaddr_slide); 787extern void unmap_image_nolock(const struct mach_header *mh); 788extern void _read_images(header_info **hList, uint32_t hCount); 789extern void prepare_load_methods(header_info *hi); 790extern void _unload_image(header_info *hi); 791extern const char ** _objc_copyClassNamesForImage(header_info *hi, unsigned int *outCount); 792 793 794extern const header_info *_headerForClass(Class cls); 795 796extern Class _class_remap(Class cls); 797extern Class _class_getNonMetaClass(Class cls, id obj); 798extern Ivar _class_getVariable(Class cls, const char *name, Class *memberOf); 799extern BOOL _class_usesAutomaticRetainRelease(Class cls); 800extern uint32_t _class_getInstanceStart(Class cls); 801 802extern unsigned _class_createInstancesFromZone(Class cls, size_t extraBytes, void *zone, id *results, unsigned num_requested); 803extern id _objc_constructOrFree(id bytes, Class cls); 804 805extern const char *_category_getName(Category cat); 806extern const char *_category_getClassName(Category cat); 807extern Class _category_getClass(Category cat); 808extern IMP _category_getLoadMethod(Category cat); 809 810extern id object_cxxConstructFromClass(id obj, Class cls); 811extern void object_cxxDestruct(id obj); 812 813extern void _class_resolveMethod(Class cls, SEL sel, id inst); 814 815#define OBJC_WARN_DEPRECATED \ 816 do { \ 817 static int warned = 0; \ 818 if (!warned) { \ 819 warned = 1; \ 820 _objc_inform_deprecated(__FUNCTION__, NULL); \ 821 } \ 822 } while (0) \ 823 824__END_DECLS 825 826 827#ifndef STATIC_ASSERT 828# define STATIC_ASSERT(x) _STATIC_ASSERT2(x, __LINE__) 829# define _STATIC_ASSERT2(x, line) _STATIC_ASSERT3(x, line) 830# define _STATIC_ASSERT3(x, line) \ 831 typedef struct { \ 832 int _static_assert[(x) ? 0 : -1]; \ 833 } _static_assert_ ## line __attribute__((unavailable)) 834#endif 835 836#define countof(arr) (sizeof(arr) / sizeof((arr)[0])) 837 838 839// Global operator new and delete. We must not use any app overrides. 840// This ALSO REQUIRES each of these be in libobjc's unexported symbol list. 841#if __cplusplus 842#pragma clang diagnostic push 843#pragma clang diagnostic ignored "-Winline-new-delete" 844#include <new> 845inline void* operator new(std::size_t size) throw (std::bad_alloc) { return _malloc_internal(size); } 846inline void* operator new[](std::size_t size) throw (std::bad_alloc) { return _malloc_internal(size); } 847inline void* operator new(std::size_t size, const std::nothrow_t&) throw() { return _malloc_internal(size); } 848inline void* operator new[](std::size_t size, const std::nothrow_t&) throw() { return _malloc_internal(size); } 849inline void operator delete(void* p) throw() { _free_internal(p); } 850inline void operator delete[](void* p) throw() { _free_internal(p); } 851inline void operator delete(void* p, const std::nothrow_t&) throw() { _free_internal(p); } 852inline void operator delete[](void* p, const std::nothrow_t&) throw() { _free_internal(p); } 853#pragma clang diagnostic pop 854#endif 855 856 857// DisguisedPtr<T> acts like pointer type T*, except the 858// stored value is disguised to hide it from tools like `leaks`. 859// nil is disguised as itself so zero-filled memory works as expected, 860// which means 0x80..00 is also diguised as itself but we don't care 861template <typename T> 862class DisguisedPtr { 863 uintptr_t value; 864 865 static uintptr_t disguise(T* ptr) { 866 return -(uintptr_t)ptr; 867 } 868 869 static T* undisguise(uintptr_t val) { 870 return (T*)-val; 871 } 872 873 public: 874 DisguisedPtr() { } 875 DisguisedPtr(T* ptr) 876 : value(disguise(ptr)) { } 877 DisguisedPtr(const DisguisedPtr<T>& ptr) 878 : value(ptr.value) { } 879 880 DisguisedPtr<T>& operator = (T* rhs) { 881 value = disguise(rhs); 882 return *this; 883 } 884 DisguisedPtr<T>& operator = (const DisguisedPtr<T>& rhs) { 885 value = rhs.value; 886 return *this; 887 } 888 889 operator T* () const { 890 return undisguise(value); 891 } 892 T* operator -> () const { 893 return undisguise(value); 894 } 895 T& operator * () const { 896 return *undisguise(value); 897 } 898 T& operator [] (size_t i) const { 899 return undisguise(value)[i]; 900 } 901 902 // pointer arithmetic operators omitted 903 // because we don't currently use them anywhere 904}; 905 906 907// Pointer hash function. 908// This is not a terrific hash, but it is fast 909// and not outrageously flawed for our purposes. 910 911// Based on principles from http://locklessinc.com/articles/fast_hash/ 912// and evaluation ideas from http://floodyberry.com/noncryptohashzoo/ 913#if __LP64__ 914static inline uint32_t ptr_hash(uint64_t key) 915{ 916 key ^= key >> 4; 917 key *= 0x8a970be7488fda55; 918 key ^= __builtin_bswap64(key); 919 return (uint32_t)key; 920} 921#else 922static inline uint32_t ptr_hash(uint32_t key) 923{ 924 key ^= key >> 4; 925 key *= 0x5052acdb; 926 key ^= __builtin_bswap32(key); 927 return key; 928} 929#endif 930 931/* 932 Higher-quality hash function. This is measurably slower in some workloads. 933#if __LP64__ 934 uint32_t ptr_hash(uint64_t key) 935{ 936 key -= __builtin_bswap64(key); 937 key *= 0x8a970be7488fda55; 938 key ^= __builtin_bswap64(key); 939 key *= 0x8a970be7488fda55; 940 key ^= __builtin_bswap64(key); 941 return (uint32_t)key; 942} 943#else 944static uint32_t ptr_hash(uint32_t key) 945{ 946 key -= __builtin_bswap32(key); 947 key *= 0x5052acdb; 948 key ^= __builtin_bswap32(key); 949 key *= 0x5052acdb; 950 key ^= __builtin_bswap32(key); 951 return key; 952} 953#endif 954*/ 955 956 957// Inlined parts of objc_object's implementation 958#include "objc-object.h" 959 960#endif /* _OBJC_PRIVATE_H_ */ 961 962