2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Copyright 1988-1996, NeXT Software, Inc.
28 #ifndef _OBJC_PRIVATE_H_
29 #define _OBJC_PRIVATE_H_
31 #include "objc-config.h"
33 /* Isolate ourselves from the definitions of id and Class in the compiler
38 #error include objc-private.h before other headers
41 #define OBJC_TYPES_DEFINED 1
42 #define OBJC_OLD_DISPATCH_PROTOTYPES 0
44 #include <cstddef> // for nullptr_t
51 typedef struct objc_class
*Class
;
52 typedef struct objc_object
*id
;
62 isa_t(uintptr_t value
) : bits(value
) { }
67 #if SUPPORT_NONPOINTER_ISA
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)
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
81 # define ISA_MASK 0x00000001fffffff8ULL
82 # define ISA_MAGIC_MASK 0x000003fe00000001ULL
83 # define ISA_MAGIC_VALUE 0x000001a400000001ULL
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
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)
99 # define ISA_MASK 0x00007ffffffffff8ULL
100 # define ISA_MAGIC_MASK 0x0000000000000001ULL
101 # define ISA_MAGIC_VALUE 0x0000000000000001ULL
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)
116 // Available bits in isa field are architecture-specific.
117 # error unknown architecture
120 // SUPPORT_NONPOINTER_ISA
132 // ISA() assumes this is NOT a tagged pointer object
135 // getIsa() allows this to be a tagged pointer object
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
);
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
);
153 bool hasIndexedIsa();
154 bool isTaggedPointer();
157 // object may have associated objects?
158 bool hasAssociatedObjects();
159 void setHasAssociatedObjects();
161 // object may be weakly referenced?
162 bool isWeaklyReferenced();
163 void setWeaklyReferenced_nolock();
165 // object may have -.cxx_destruct implementation?
168 // Optimized calls to retain/release methods
173 // Implementations of retain/release methods
176 id
rootAutorelease();
177 bool rootTryRetain();
178 bool rootReleaseShouldDealloc();
179 uintptr_t rootRetainCount();
181 // Implementation of dealloc methods
182 bool rootIsDeallocating();
183 void clearDeallocating();
187 void initIsa(Class newCls
, bool indexed
, bool hasCxxDtor
);
189 // Slow paths for inline control
190 id
rootAutorelease2();
191 bool overrelease_error();
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
);
200 void clearDeallocating_weak();
202 // Side table retain count overflow for nonpointer isa
203 void sidetable_lock();
204 void sidetable_unlock();
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();
212 // Side-table-only retain count
213 bool sidetable_isDeallocating();
214 void sidetable_clearDeallocating();
216 bool sidetable_isWeaklyReferenced();
217 void sidetable_setWeaklyReferenced_nolock();
219 id
sidetable_retain();
220 id
sidetable_retain_slow(SideTable
*table
);
222 bool sidetable_release(bool performDealloc
= true);
223 bool sidetable_release_slow(SideTable
*table
, bool performDealloc
= true);
225 bool sidetable_tryRetain();
227 uintptr_t sidetable_retainCount();
229 bool sidetable_present();
235 typedef struct method_t
*Method
;
236 typedef struct ivar_t
*Ivar
;
237 typedef struct category_t
*Category
;
238 typedef struct property_t
*objc_property_t
;
240 typedef struct old_method
*Method
;
241 typedef struct old_ivar
*Ivar
;
242 typedef struct old_category
*Category
;
243 typedef struct old_property
*objc_property_t
;
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"
259 /* Do not include message.h here. */
260 /* #include "message.h" */
262 #define __APPLE_API_PRIVATE
263 #include "objc-gdb.h"
264 #undef __APPLE_API_PRIVATE
270 #include "objc-runtime-new.h"
272 #include "objc-runtime-old.h"
275 #include "objc-references.h"
276 #include "objc-initialize.h"
277 #include "objc-loadmethod.h"
283 #if (defined(OBJC_NO_GC) && SUPPORT_GC) || \
284 (!defined(OBJC_NO_GC) && !SUPPORT_GC)
285 # error OBJC_NO_GC and SUPPORT_GC inconsistent
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
);
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
311 #define _objcHeaderIsReplacement(h) ((h)->info && ((h)->info->flags & OBJC_IMAGE_IS_REPLACEMENT))
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?
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))
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
336 #define _objcHeaderOptimizedByDyld(h) ((h)->info && ((h)->info->flags & OBJC_IMAGE_OPTIMIZED_BY_DYLD))
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.
344 typedef 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
351 bool allClassesRealized
;
353 // Do not add fields without editing ObjCModernAbstraction.hpp
356 struct old_protocol
**proto_refs
;
357 struct objc_module
*mod_ptr
;
360 struct objc_module
**modules
;
362 struct old_protocol
**protocols
;
363 size_t protocolCount
;
365 size_t imageinfoBytes
;
368 struct objc_class
**clsrefs
;
375 extern header_info
*FirstHeader
;
376 extern header_info
*LastHeader
;
377 extern int HeaderCount
;
379 extern uint32_t AppSDKVersion
; // X.Y.Z is 0xXXXXYYZZ
381 extern void appendHeader(header_info
*hi
);
382 extern void removeHeader(header_info
*hi
);
384 extern objc_image_info
*_getObjcImageInfo(const headerType
*head
, size_t *size
);
385 extern BOOL
_hasObjcContents(const header_info
*hi
);
389 extern void sel_init(BOOL gc
, size_t selrefCount
);
390 extern SEL
sel_registerNameNoLock(const char *str
, BOOL copy
);
391 extern void sel_lock(void);
392 extern void sel_unlock(void);
393 extern BOOL
sel_preoptimizationValid(const header_info
*hi
);
396 extern SEL SEL_initialize
;
397 extern SEL SEL_resolveClassMethod
;
398 extern SEL SEL_resolveInstanceMethod
;
399 extern SEL SEL_cxx_construct
;
400 extern SEL SEL_cxx_destruct
;
401 extern SEL SEL_retain
;
402 extern SEL SEL_release
;
403 extern SEL SEL_autorelease
;
404 extern SEL SEL_retainCount
;
405 extern SEL SEL_alloc
;
406 extern SEL SEL_allocWithZone
;
407 extern SEL SEL_dealloc
;
410 extern SEL SEL_finalize
;
411 extern SEL SEL_forwardInvocation
;
412 extern SEL SEL_tryRetain
;
413 extern SEL SEL_isDeallocating
;
414 extern SEL SEL_retainWeakReference
;
415 extern SEL SEL_allowsWeakReference
;
417 /* preoptimization */
418 extern void preopt_init(void);
419 extern void disableSharedCacheOptimizations(void);
420 extern bool isPreoptimized(void);
421 extern header_info
*preoptimizedHinfoForHeader(const headerType
*mhdr
);
423 #if SUPPORT_PREOPT && __cplusplus
424 #include <objc-shared-cache.h>
425 using objc_selopt_t
= const objc_opt::objc_selopt_t
;
427 struct objc_selopt_t
;
430 extern objc_selopt_t
*preoptimizedSelectors(void);
431 extern Class
getPreoptimizedClass(const char *name
);
432 extern Class
* copyPreoptimizedClasses(const char *name
, int *outCount
);
435 /* optional malloc zone for runtime data */
436 extern malloc_zone_t
*_objc_internal_zone(void);
437 extern void *_malloc_internal(size_t size
);
438 extern void *_calloc_internal(size_t count
, size_t size
);
439 extern void *_realloc_internal(void *ptr
, size_t size
);
440 extern char *_strdup_internal(const char *str
);
441 extern char *_strdupcat_internal(const char *s1
, const char *s2
);
442 extern uint8_t *_ustrdup_internal(const uint8_t *str
);
443 extern void *_memdup_internal(const void *mem
, size_t size
);
444 extern void _free_internal(void *ptr
);
445 extern size_t _malloc_size_internal(void *ptr
);
447 extern Class
_calloc_class(size_t size
);
450 extern IMP
lookUpImpOrNil(Class
, SEL
, id obj
, bool initialize
, bool cache
, bool resolver
);
451 extern IMP
lookUpImpOrForward(Class
, SEL
, id obj
, bool initialize
, bool cache
, bool resolver
);
453 extern IMP
lookupMethodInClassAndLoadCache(Class cls
, SEL sel
);
454 extern BOOL
class_respondsToSelector_inst(Class cls
, SEL sel
, id inst
);
456 extern bool objcMsgLogEnabled
;
457 extern bool logMessageSend(bool isClassMethod
,
458 const char *objectsClass
,
459 const char *implementingClass
,
462 /* message dispatcher */
463 extern IMP
_class_lookupMethodAndLoadCache3(id
, SEL
, Class
);
465 #if !OBJC_OLD_DISPATCH_PROTOTYPES
466 extern void _objc_msgForward_impcache(void);
467 extern void _objc_ignored_method(void);
468 extern void _objc_msgSend_uncached_impcache(void);
470 extern id
_objc_msgForward_impcache(id
, SEL
, ...);
471 extern id
_objc_ignored_method(id
, SEL
, ...);
472 extern id
_objc_msgSend_uncached_impcache(id
, SEL
, ...);
476 extern void __objc_error(id
, const char *, ...) __attribute__((format (printf
, 2, 3), noreturn
));
477 extern void _objc_inform(const char *fmt
, ...) __attribute__((format (printf
, 1, 2)));
478 extern void _objc_inform_on_crash(const char *fmt
, ...) __attribute__((format (printf
, 1, 2)));
479 extern void _objc_inform_now_and_on_crash(const char *fmt
, ...) __attribute__((format (printf
, 1, 2)));
480 extern void _objc_inform_deprecated(const char *oldname
, const char *newname
) __attribute__((noinline
));
481 extern void inform_duplicate(const char *name
, Class oldCls
, Class cls
);
482 extern bool crashlog_header_name(header_info
*hi
);
483 extern bool crashlog_header_name_string(const char *name
);
486 extern Class
_objc_getFreedObjectClass (void);
488 /* map table additions */
489 extern void *NXMapKeyCopyingInsert(NXMapTable
*table
, const void *key
, const void *value
);
490 extern void *NXMapKeyFreeingRemove(NXMapTable
*table
, const void *key
);
492 /* hash table additions */
493 extern unsigned _NXHashCapacity(NXHashTable
*table
);
494 extern void _NXHashRehashToCapacity(NXHashTable
*table
, unsigned newCapacity
);
496 /* property attribute parsing */
497 extern const char *copyPropertyAttributeString(const objc_property_attribute_t
*attrs
, unsigned int count
);
498 extern objc_property_attribute_t
*copyPropertyAttributeList(const char *attrs
, unsigned int *outCount
);
499 extern char *copyPropertyAttributeValue(const char *attrs
, const char *name
);
502 extern void lock_init(void);
503 extern rwlock_t selLock
;
504 extern mutex_t cacheUpdateLock
;
505 extern recursive_mutex_t loadMethodLock
;
507 extern rwlock_t runtimeLock
;
509 extern mutex_t classLock
;
510 extern mutex_t methodListLock
;
514 #if defined(NDEBUG) || TARGET_OS_WIN32
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)
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)
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)
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)
547 extern int _mutex_lock_debug(mutex_t
*lock
, const char *name
);
548 extern int _mutex_try_lock_debug(mutex_t
*lock
, const char *name
);
549 extern int _mutex_unlock_debug(mutex_t
*lock
, const char *name
);
550 extern void _mutex_assert_locked_debug(mutex_t
*lock
, const char *name
);
551 extern void _mutex_assert_unlocked_debug(mutex_t
*lock
, const char *name
);
553 extern int _recursive_mutex_lock_debug(recursive_mutex_t
*lock
, const char *name
);
554 extern int _recursive_mutex_try_lock_debug(recursive_mutex_t
*lock
, const char *name
);
555 extern int _recursive_mutex_unlock_debug(recursive_mutex_t
*lock
, const char *name
);
556 extern void _recursive_mutex_assert_locked_debug(recursive_mutex_t
*lock
, const char *name
);
557 extern void _recursive_mutex_assert_unlocked_debug(recursive_mutex_t
*lock
, const char *name
);
559 extern int _monitor_enter_debug(monitor_t
*lock
, const char *name
);
560 extern int _monitor_exit_debug(monitor_t
*lock
, const char *name
);
561 extern int _monitor_wait_debug(monitor_t
*lock
, const char *name
);
562 extern void _monitor_assert_locked_debug(monitor_t
*lock
, const char *name
);
563 extern void _monitor_assert_unlocked_debug(monitor_t
*lock
, const char *name
);
565 extern void _rwlock_read_debug(rwlock_t
*l
, const char *name
);
566 extern void _rwlock_write_debug(rwlock_t
*l
, const char *name
);
567 extern int _rwlock_try_read_debug(rwlock_t
*l
, const char *name
);
568 extern int _rwlock_try_write_debug(rwlock_t
*l
, const char *name
);
569 extern void _rwlock_unlock_read_debug(rwlock_t
*l
, const char *name
);
570 extern void _rwlock_unlock_write_debug(rwlock_t
*l
, const char *name
);
571 extern void _rwlock_assert_reading_debug(rwlock_t
*l
, const char *name
);
572 extern void _rwlock_assert_writing_debug(rwlock_t
*l
, const char *name
);
573 extern void _rwlock_assert_locked_debug(rwlock_t
*l
, const char *name
);
574 extern void _rwlock_assert_unlocked_debug(rwlock_t
*l
, const char *name
);
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)
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)
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)
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)
607 #define rwlock_unlock(m, s) \
609 if ((s) == RDONLY) rwlock_unlock_read(m); \
610 else if ((s) == RDWR) rwlock_unlock_write(m); \
614 /* ignored selector support */
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
621 static inline int ignoreSelector(SEL sel
)
625 #elif SUPPORT_IGNORED_SELECTOR_CONSTANT
626 return UseGC
&& sel
== (SEL
)kIgnore
;
629 (sel
== @
selector(retain
) ||
630 sel
== @
selector(release
) ||
631 sel
== @
selector(autorelease
) ||
632 sel
== @
selector(retainCount
) ||
633 sel
== @
selector(dealloc
));
637 static inline int ignoreSelectorNamed(const char *sel
)
642 // release retain retainCount dealloc autorelease
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 ))
649 (strcmp(sel
, "dealloc") == 0)
651 (sel
[0] == 'a' && sel
[1] == 'u' &&
652 strcmp(&sel
[2], "torelease") == 0)));
657 extern void gc_init(BOOL wantsGC
);
658 extern void gc_init2(void);
661 struct alt_handler_list
;
662 extern void exception_init(void);
663 extern void _destroyAltHandlerList(struct alt_handler_list
*list
);
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)
670 extern void gdb_objc_class_changed(Class cls
, unsigned long changes
, const char *classname
)
671 __attribute__((noinline
));
675 /* Write barrier implementations */
676 extern id
objc_getAssociatedObject_non_gc(id object
, const void *key
);
677 extern void objc_setAssociatedObject_non_gc(id object
, const void *key
, id value
, objc_AssociationPolicy policy
);
679 extern id
objc_getAssociatedObject_gc(id object
, const void *key
);
680 extern void objc_setAssociatedObject_gc(id object
, const void *key
, id value
, objc_AssociationPolicy policy
);
683 extern objc_xref_t
_object_addExternalReference_non_gc(id obj
, objc_xref_t type
);
684 extern id
_object_readExternalReference_non_gc(objc_xref_t ref
);
685 extern void _object_removeExternalReference_non_gc(objc_xref_t ref
);
687 extern objc_xref_t
_object_addExternalReference_gc(id obj
, objc_xref_t type
);
688 extern id
_object_readExternalReference_gc(objc_xref_t ref
);
689 extern void _object_removeExternalReference_gc(objc_xref_t ref
);
691 /* GC weak reference fixup. */
692 extern void gc_fixup_weakreferences(id newObject
, id oldObject
);
694 /* GC datasegment registration. */
695 extern void gc_register_datasegment(uintptr_t base
, size_t size
);
696 extern void gc_unregister_datasegment(uintptr_t base
, size_t size
);
698 /* objc_dumpHeap implementation */
699 extern BOOL
_objc_dumpHeap(auto_zone_t
*zone
, const char *filename
);
704 // Settings from environment variables
705 #define OPTION(var, env, help) extern bool var;
706 #include "objc-env.h"
709 extern void environ_init(void);
711 extern void logReplacedMethod(const char *className
, SEL s
, BOOL isMeta
, const char *catName
, IMP oldImp
, IMP newImp
);
713 static __inline
uint32_t _objc_strhash(const char *s
) {
718 hash
+= (hash
<< 8) + a
;
724 // objc per-thread storage
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
731 // If you add new fields here, don't forget to update
732 // _objc_pthread_destroyspecific()
734 } _objc_pthread_data
;
736 extern _objc_pthread_data
*_objc_fetch_pthread_data(BOOL create
);
737 extern void tls_init(void);
740 extern unsigned int encoding_getNumberOfArguments(const char *typedesc
);
741 extern unsigned int encoding_getSizeOfArguments(const char *typedesc
);
742 extern unsigned int encoding_getArgumentInfo(const char *typedesc
, unsigned int arg
, const char **type
, int *offset
);
743 extern void encoding_getReturnType(const char *t
, char *dst
, size_t dst_len
);
744 extern char * encoding_copyReturnType(const char *t
);
745 extern void encoding_getArgumentType(const char *t
, unsigned int index
, char *dst
, size_t dst_len
);
746 extern char *encoding_copyArgumentType(const char *t
, unsigned int index
);
749 extern void _destroySyncCache(struct SyncCache
*cache
);
752 extern void arr_init(void);
753 extern id
objc_autoreleaseReturnValue(id obj
);
756 extern IMP
_imp_implementationWithBlockNoCopy(id block
);
762 size_t bitsAllocated
;
765 extern layout_bitmap
layout_bitmap_create(const unsigned char *layout_string
, size_t layoutStringInstanceSize
, size_t instanceSize
, BOOL weak
);
766 extern layout_bitmap
layout_bitmap_create_empty(size_t instanceSize
, BOOL weak
);
767 extern void layout_bitmap_free(layout_bitmap bits
);
768 extern const unsigned char *layout_string_create(layout_bitmap bits
);
769 extern void layout_bitmap_set_ivar(layout_bitmap bits
, const char *type
, size_t offset
);
770 extern void layout_bitmap_grow(layout_bitmap
*bits
, size_t newCount
);
771 extern void layout_bitmap_slide(layout_bitmap
*bits
, size_t oldPos
, size_t newPos
);
772 extern void layout_bitmap_slide_anywhere(layout_bitmap
*bits
, size_t oldPos
, size_t newPos
);
773 extern BOOL
layout_bitmap_splat(layout_bitmap dst
, layout_bitmap src
,
774 size_t oldSrcInstanceSize
);
775 extern BOOL
layout_bitmap_or(layout_bitmap dst
, layout_bitmap src
, const char *msg
);
776 extern BOOL
layout_bitmap_clear(layout_bitmap dst
, layout_bitmap src
, const char *msg
);
777 extern void layout_bitmap_print(layout_bitmap bits
);
781 extern Class
look_up_class(const char *aClassName
, BOOL includeUnconnected
, BOOL includeClassHandler
);
782 extern const char *map_images(enum dyld_image_states state
, uint32_t infoCount
, const struct dyld_image_info infoList
[]);
783 extern const char *map_images_nolock(enum dyld_image_states state
, uint32_t infoCount
, const struct dyld_image_info infoList
[]);
784 extern const char * load_images(enum dyld_image_states state
, uint32_t infoCount
, const struct dyld_image_info infoList
[]);
785 extern BOOL
load_images_nolock(enum dyld_image_states state
, uint32_t infoCount
, const struct dyld_image_info infoList
[]);
786 extern void unmap_image(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
787 extern void unmap_image_nolock(const struct mach_header
*mh
);
788 extern void _read_images(header_info
**hList
, uint32_t hCount
);
789 extern void prepare_load_methods(header_info
*hi
);
790 extern void _unload_image(header_info
*hi
);
791 extern const char ** _objc_copyClassNamesForImage(header_info
*hi
, unsigned int *outCount
);
794 extern const header_info
*_headerForClass(Class cls
);
796 extern Class
_class_remap(Class cls
);
797 extern Class
_class_getNonMetaClass(Class cls
, id obj
);
798 extern Ivar
_class_getVariable(Class cls
, const char *name
, Class
*memberOf
);
799 extern BOOL
_class_usesAutomaticRetainRelease(Class cls
);
800 extern uint32_t _class_getInstanceStart(Class cls
);
802 extern unsigned _class_createInstancesFromZone(Class cls
, size_t extraBytes
, void *zone
, id
*results
, unsigned num_requested
);
803 extern id
_objc_constructOrFree(id bytes
, Class cls
);
805 extern const char *_category_getName(Category cat
);
806 extern const char *_category_getClassName(Category cat
);
807 extern Class
_category_getClass(Category cat
);
808 extern IMP
_category_getLoadMethod(Category cat
);
810 extern id
object_cxxConstructFromClass(id obj
, Class cls
);
811 extern void object_cxxDestruct(id obj
);
813 extern void _class_resolveMethod(Class cls
, SEL sel
, id inst
);
815 #define OBJC_WARN_DEPRECATED \
817 static int warned = 0; \
820 _objc_inform_deprecated(__FUNCTION__, NULL); \
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) \
832 int _static_assert[(x) ? 0 : -1]; \
833 } _static_assert_ ## line __attribute__((unavailable))
836 #define countof(arr) (sizeof(arr) / sizeof((arr)[0]))
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.
842 #pragma clang diagnostic push
843 #pragma clang diagnostic ignored "-Winline-new-delete"
845 inline void* operator new(std::size_t size
) throw (std::bad_alloc
) { return _malloc_internal(size
); }
846 inline void* operator new[](std::size_t size
) throw (std::bad_alloc
) { return _malloc_internal(size
); }
847 inline void* operator new(std::size_t size
, const std::nothrow_t
&) throw() { return _malloc_internal(size
); }
848 inline void* operator new[](std::size_t size
, const std::nothrow_t
&) throw() { return _malloc_internal(size
); }
849 inline void operator delete(void* p
) throw() { _free_internal(p
); }
850 inline void operator delete[](void* p
) throw() { _free_internal(p
); }
851 inline void operator delete(void* p
, const std::nothrow_t
&) throw() { _free_internal(p
); }
852 inline void operator delete[](void* p
, const std::nothrow_t
&) throw() { _free_internal(p
); }
853 #pragma clang diagnostic pop
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
861 template <typename T
>
865 static uintptr_t disguise(T
* ptr
) {
866 return -(uintptr_t)ptr
;
869 static T
* undisguise(uintptr_t val
) {
876 : value(disguise(ptr
)) { }
877 DisguisedPtr(const DisguisedPtr
<T
>& ptr
)
878 : value(ptr
.value
) { }
880 DisguisedPtr
<T
>& operator = (T
* rhs
) {
881 value
= disguise(rhs
);
884 DisguisedPtr
<T
>& operator = (const DisguisedPtr
<T
>& rhs
) {
889 operator T
* () const {
890 return undisguise(value
);
892 T
* operator -> () const {
893 return undisguise(value
);
895 T
& operator * () const {
896 return *undisguise(value
);
898 T
& operator [] (size_t i
) const {
899 return undisguise(value
)[i
];
902 // pointer arithmetic operators omitted
903 // because we don't currently use them anywhere
907 // Pointer hash function.
908 // This is not a terrific hash, but it is fast
909 // and not outrageously flawed for our purposes.
911 // Based on principles from http://locklessinc.com/articles/fast_hash/
912 // and evaluation ideas from http://floodyberry.com/noncryptohashzoo/
914 static inline uint32_t ptr_hash(uint64_t key
)
917 key
*= 0x8a970be7488fda55;
918 key
^= __builtin_bswap64(key
);
919 return (uint32_t)key
;
922 static inline uint32_t ptr_hash(uint32_t key
)
926 key
^= __builtin_bswap32(key
);
932 Higher-quality hash function. This is measurably slower in some workloads.
934 uint32_t ptr_hash(uint64_t key)
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;
944 static uint32_t ptr_hash(uint32_t key)
946 key -= __builtin_bswap32(key);
948 key ^= __builtin_bswap32(key);
950 key ^= __builtin_bswap32(key);
957 // Inlined parts of objc_object's implementation
958 #include "objc-object.h"
960 #endif /* _OBJC_PRIVATE_H_ */