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
;
59 #if (!SUPPORT_NONPOINTER_ISA && !SUPPORT_PACKED_ISA && !SUPPORT_INDEXED_ISA) ||\
60 ( SUPPORT_NONPOINTER_ISA && SUPPORT_PACKED_ISA && !SUPPORT_INDEXED_ISA) ||\
61 ( SUPPORT_NONPOINTER_ISA && !SUPPORT_PACKED_ISA && SUPPORT_INDEXED_ISA)
71 isa_t(uintptr_t value
) : bits(value
) { }
76 #if SUPPORT_PACKED_ISA
78 // extra_rc must be the MSB-most field (so it matches carry/overflow flags)
79 // nonpointer must be the LSB (fixme or get rid of it)
80 // shiftcls must occupy the same bits that a real class pointer would
81 // bits + RC_ONE is equivalent to extra_rc + 1
82 // RC_HALF is the high bit of extra_rc (i.e. half of its range)
85 // uintptr_t fast_rr : 1; // no r/r overrides
86 // uintptr_t lock : 2; // lock for atomic property, @synch
87 // uintptr_t extraBytes : 1; // allocated with extra bytes
90 # define ISA_MASK 0x0000000ffffffff8ULL
91 # define ISA_MAGIC_MASK 0x000003f000000001ULL
92 # define ISA_MAGIC_VALUE 0x000001a000000001ULL
94 uintptr_t nonpointer
: 1;
95 uintptr_t has_assoc
: 1;
96 uintptr_t has_cxx_dtor
: 1;
97 uintptr_t shiftcls
: 33; // MACH_VM_MAX_ADDRESS 0x1000000000
99 uintptr_t weakly_referenced
: 1;
100 uintptr_t deallocating
: 1;
101 uintptr_t has_sidetable_rc
: 1;
102 uintptr_t extra_rc
: 19;
103 # define RC_ONE (1ULL<<45)
104 # define RC_HALF (1ULL<<18)
108 # define ISA_MASK 0x00007ffffffffff8ULL
109 # define ISA_MAGIC_MASK 0x001f800000000001ULL
110 # define ISA_MAGIC_VALUE 0x001d800000000001ULL
112 uintptr_t nonpointer
: 1;
113 uintptr_t has_assoc
: 1;
114 uintptr_t has_cxx_dtor
: 1;
115 uintptr_t shiftcls
: 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000
117 uintptr_t weakly_referenced
: 1;
118 uintptr_t deallocating
: 1;
119 uintptr_t has_sidetable_rc
: 1;
120 uintptr_t extra_rc
: 8;
121 # define RC_ONE (1ULL<<56)
122 # define RC_HALF (1ULL<<7)
126 # error unknown architecture for packed isa
129 // SUPPORT_PACKED_ISA
133 #if SUPPORT_INDEXED_ISA
135 # if __ARM_ARCH_7K__ >= 2
137 # define ISA_INDEX_IS_NPI 1
138 # define ISA_INDEX_MASK 0x0001FFFC
139 # define ISA_INDEX_SHIFT 2
140 # define ISA_INDEX_BITS 15
141 # define ISA_INDEX_COUNT (1 << ISA_INDEX_BITS)
142 # define ISA_INDEX_MAGIC_MASK 0x001E0001
143 # define ISA_INDEX_MAGIC_VALUE 0x001C0001
145 uintptr_t nonpointer
: 1;
146 uintptr_t has_assoc
: 1;
147 uintptr_t indexcls
: 15;
149 uintptr_t has_cxx_dtor
: 1;
150 uintptr_t weakly_referenced
: 1;
151 uintptr_t deallocating
: 1;
152 uintptr_t has_sidetable_rc
: 1;
153 uintptr_t extra_rc
: 7;
154 # define RC_ONE (1ULL<<25)
155 # define RC_HALF (1ULL<<6)
159 # error unknown architecture for indexed isa
162 // SUPPORT_INDEXED_ISA
174 // ISA() assumes this is NOT a tagged pointer object
177 // getIsa() allows this to be a tagged pointer object
180 // initIsa() should be used to init the isa of new objects only.
181 // If this object already has an isa, use changeIsa() for correctness.
182 // initInstanceIsa(): objects with no custom RR/AWZ
183 // initClassIsa(): class objects
184 // initProtocolIsa(): protocol objects
185 // initIsa(): other objects
186 void initIsa(Class cls
/*nonpointer=false*/);
187 void initClassIsa(Class cls
/*nonpointer=maybe*/);
188 void initProtocolIsa(Class cls
/*nonpointer=maybe*/);
189 void initInstanceIsa(Class cls
, bool hasCxxDtor
);
191 // changeIsa() should be used to change the isa of existing objects.
192 // If this is a new object, use initIsa() for performance.
193 Class
changeIsa(Class newCls
);
195 bool hasNonpointerIsa();
196 bool isTaggedPointer();
197 bool isBasicTaggedPointer();
198 bool isExtTaggedPointer();
201 // object may have associated objects?
202 bool hasAssociatedObjects();
203 void setHasAssociatedObjects();
205 // object may be weakly referenced?
206 bool isWeaklyReferenced();
207 void setWeaklyReferenced_nolock();
209 // object may have -.cxx_destruct implementation?
212 // Optimized calls to retain/release methods
217 // Implementations of retain/release methods
220 id
rootAutorelease();
221 bool rootTryRetain();
222 bool rootReleaseShouldDealloc();
223 uintptr_t rootRetainCount();
225 // Implementation of dealloc methods
226 bool rootIsDeallocating();
227 void clearDeallocating();
231 void initIsa(Class newCls
, bool nonpointer
, bool hasCxxDtor
);
233 // Slow paths for inline control
234 id
rootAutorelease2();
235 bool overrelease_error();
237 #if SUPPORT_NONPOINTER_ISA
238 // Unified retain count manipulation for nonpointer isa
239 id
rootRetain(bool tryRetain
, bool handleOverflow
);
240 bool rootRelease(bool performDealloc
, bool handleUnderflow
);
241 id
rootRetain_overflow(bool tryRetain
);
242 bool rootRelease_underflow(bool performDealloc
);
244 void clearDeallocating_slow();
246 // Side table retain count overflow for nonpointer isa
247 void sidetable_lock();
248 void sidetable_unlock();
250 void sidetable_moveExtraRC_nolock(size_t extra_rc
, bool isDeallocating
, bool weaklyReferenced
);
251 bool sidetable_addExtraRC_nolock(size_t delta_rc
);
252 size_t sidetable_subExtraRC_nolock(size_t delta_rc
);
253 size_t sidetable_getExtraRC_nolock();
256 // Side-table-only retain count
257 bool sidetable_isDeallocating();
258 void sidetable_clearDeallocating();
260 bool sidetable_isWeaklyReferenced();
261 void sidetable_setWeaklyReferenced_nolock();
263 id
sidetable_retain();
264 id
sidetable_retain_slow(SideTable
& table
);
266 uintptr_t sidetable_release(bool performDealloc
= true);
267 uintptr_t sidetable_release_slow(SideTable
& table
, bool performDealloc
= true);
269 bool sidetable_tryRetain();
271 uintptr_t sidetable_retainCount();
273 bool sidetable_present();
279 typedef struct method_t
*Method
;
280 typedef struct ivar_t
*Ivar
;
281 typedef struct category_t
*Category
;
282 typedef struct property_t
*objc_property_t
;
284 typedef struct old_method
*Method
;
285 typedef struct old_ivar
*Ivar
;
286 typedef struct old_category
*Category
;
287 typedef struct old_property
*objc_property_t
;
295 #include "objc-abi.h"
296 #include "objc-api.h"
297 #include "objc-config.h"
298 #include "objc-internal.h"
299 #include "maptable.h"
300 #include "hashtable2.h"
302 /* Do not include message.h here. */
303 /* #include "message.h" */
305 #define __APPLE_API_PRIVATE
306 #include "objc-gdb.h"
307 #undef __APPLE_API_PRIVATE
313 #include "objc-runtime-new.h"
315 #include "objc-runtime-old.h"
318 #include "objc-references.h"
319 #include "objc-initialize.h"
320 #include "objc-loadmethod.h"
323 #if SUPPORT_PREOPT && __cplusplus
324 #include <objc-shared-cache.h>
325 using objc_selopt_t
= const objc_opt::objc_selopt_t
;
327 struct objc_selopt_t
;
331 #define STRINGIFY(x) #x
332 #define STRINGIFY2(x) STRINGIFY(x)
338 // Split out the rw data from header info. For now put it in a huge array
339 // that more than exceeds the space needed. In future we'll just allocate
340 // this in the shared cache builder.
341 typedef struct header_info_rw
{
343 bool getLoaded() const {
347 void setLoaded(bool v
) {
351 bool getAllClassesRealized() const {
352 return allClassesRealized
;
355 void setAllClassesRealized(bool v
) {
356 allClassesRealized
= v
? 1: 0;
359 header_info
*getNext() const {
360 return (header_info
*)(next
<< 2);
363 void setNext(header_info
*v
) {
364 next
= ((uintptr_t)v
) >> 2;
369 uintptr_t isLoaded
: 1;
370 uintptr_t allClassesRealized
: 1;
373 uintptr_t isLoaded
: 1;
374 uintptr_t allClassesRealized
: 1;
379 struct header_info_rw
* getPreoptimizedHeaderRW(const struct header_info
*const hdr
);
381 typedef struct header_info
{
383 // Note, this is no longer a pointer, but instead an offset to a pointer
384 // from this location.
385 intptr_t mhdr_offset
;
387 // Note, this is no longer a pointer, but instead an offset to a pointer
388 // from this location.
389 intptr_t info_offset
;
391 // Do not add fields without editing ObjCModernAbstraction.hpp
394 header_info_rw
*getHeaderInfoRW() {
395 header_info_rw
*preopt
=
396 isPreoptimized() ? getPreoptimizedHeaderRW(this) : nil
;
397 if (preopt
) return preopt
;
398 else return &rw_data
[0];
401 const headerType
*mhdr() const {
402 return (const headerType
*)(((intptr_t)&mhdr_offset
) + mhdr_offset
);
405 void setmhdr(const headerType
*mhdr
) {
406 mhdr_offset
= (intptr_t)mhdr
- (intptr_t)&mhdr_offset
;
409 const objc_image_info
*info() const {
410 return (const objc_image_info
*)(((intptr_t)&info_offset
) + info_offset
);
413 void setinfo(const objc_image_info
*info
) {
414 info_offset
= (intptr_t)info
- (intptr_t)&info_offset
;
418 return getHeaderInfoRW()->getLoaded();
421 void setLoaded(bool v
) {
422 getHeaderInfoRW()->setLoaded(v
);
425 bool areAllClassesRealized() {
426 return getHeaderInfoRW()->getAllClassesRealized();
429 void setAllClassesRealized(bool v
) {
430 getHeaderInfoRW()->setAllClassesRealized(v
);
433 header_info
*getNext() {
434 return getHeaderInfoRW()->getNext();
437 void setNext(header_info
*v
) {
438 getHeaderInfoRW()->setNext(v
);
442 return mhdr()->filetype
== MH_BUNDLE
;
445 const char *fname() const {
446 return dyld_image_path_containing_address(mhdr());
449 bool isPreoptimized() const;
452 struct old_protocol
**proto_refs
;
453 struct objc_module
*mod_ptr
;
456 struct objc_module
**modules
;
458 struct old_protocol
**protocols
;
459 size_t protocolCount
;
461 size_t imageinfoBytes
;
464 struct objc_class
**clsrefs
;
471 // Images in the shared cache will have an empty array here while those
472 // allocated at run time will allocate a single entry.
473 header_info_rw rw_data
[];
476 extern header_info
*FirstHeader
;
477 extern header_info
*LastHeader
;
478 extern int HeaderCount
;
480 extern void appendHeader(header_info
*hi
);
481 extern void removeHeader(header_info
*hi
);
483 extern objc_image_info
*_getObjcImageInfo(const headerType
*head
, size_t *size
);
484 extern bool _hasObjcContents(const header_info
*hi
);
487 // Mach-O segment and section names are 16 bytes and may be un-terminated.
489 static inline bool segnameEquals(const char *lhs
, const char *rhs
) {
490 return 0 == strncmp(lhs
, rhs
, 16);
493 static inline bool segnameStartsWith(const char *segname
, const char *prefix
) {
494 return 0 == strncmp(segname
, prefix
, strlen(prefix
));
497 static inline bool sectnameEquals(const char *lhs
, const char *rhs
) {
498 return segnameEquals(lhs
, rhs
);
501 static inline bool sectnameStartsWith(const char *sectname
, const char *prefix
){
502 return segnameStartsWith(sectname
, prefix
);
507 extern void sel_init(size_t selrefCount
);
508 extern SEL
sel_registerNameNoLock(const char *str
, bool copy
);
509 extern void sel_lock(void);
510 extern void sel_unlock(void);
513 extern SEL SEL_initialize
;
514 extern SEL SEL_resolveClassMethod
;
515 extern SEL SEL_resolveInstanceMethod
;
516 extern SEL SEL_cxx_construct
;
517 extern SEL SEL_cxx_destruct
;
518 extern SEL SEL_retain
;
519 extern SEL SEL_release
;
520 extern SEL SEL_autorelease
;
521 extern SEL SEL_retainCount
;
522 extern SEL SEL_alloc
;
523 extern SEL SEL_allocWithZone
;
524 extern SEL SEL_dealloc
;
527 extern SEL SEL_forwardInvocation
;
528 extern SEL SEL_tryRetain
;
529 extern SEL SEL_isDeallocating
;
530 extern SEL SEL_retainWeakReference
;
531 extern SEL SEL_allowsWeakReference
;
533 /* preoptimization */
534 extern void preopt_init(void);
535 extern void disableSharedCacheOptimizations(void);
536 extern bool isPreoptimized(void);
537 extern bool noMissingWeakSuperclasses(void);
538 extern header_info
*preoptimizedHinfoForHeader(const headerType
*mhdr
);
540 extern objc_selopt_t
*preoptimizedSelectors(void);
542 extern Protocol
*getPreoptimizedProtocol(const char *name
);
544 extern Class
getPreoptimizedClass(const char *name
);
545 extern Class
* copyPreoptimizedClasses(const char *name
, int *outCount
);
547 extern Class
_calloc_class(size_t size
);
550 extern IMP
lookUpImpOrNil(Class
, SEL
, id obj
, bool initialize
, bool cache
, bool resolver
);
551 extern IMP
lookUpImpOrForward(Class
, SEL
, id obj
, bool initialize
, bool cache
, bool resolver
);
553 extern IMP
lookupMethodInClassAndLoadCache(Class cls
, SEL sel
);
554 extern bool class_respondsToSelector_inst(Class cls
, SEL sel
, id inst
);
556 extern bool objcMsgLogEnabled
;
557 extern bool logMessageSend(bool isClassMethod
,
558 const char *objectsClass
,
559 const char *implementingClass
,
562 /* message dispatcher */
563 extern IMP
_class_lookupMethodAndLoadCache3(id
, SEL
, Class
);
565 #if !OBJC_OLD_DISPATCH_PROTOTYPES
566 extern void _objc_msgForward_impcache(void);
568 extern id
_objc_msgForward_impcache(id
, SEL
, ...);
572 extern void __objc_error(id
, const char *, ...) __attribute__((format (printf
, 2, 3), noreturn
));
573 extern void _objc_inform(const char *fmt
, ...) __attribute__((format (printf
, 1, 2)));
574 extern void _objc_inform_on_crash(const char *fmt
, ...) __attribute__((format (printf
, 1, 2)));
575 extern void _objc_inform_now_and_on_crash(const char *fmt
, ...) __attribute__((format (printf
, 1, 2)));
576 extern void _objc_inform_deprecated(const char *oldname
, const char *newname
) __attribute__((noinline
));
577 extern void inform_duplicate(const char *name
, Class oldCls
, Class cls
);
580 extern Class
_objc_getFreedObjectClass (void);
582 /* map table additions */
583 extern void *NXMapKeyCopyingInsert(NXMapTable
*table
, const void *key
, const void *value
);
584 extern void *NXMapKeyFreeingRemove(NXMapTable
*table
, const void *key
);
586 /* hash table additions */
587 extern unsigned _NXHashCapacity(NXHashTable
*table
);
588 extern void _NXHashRehashToCapacity(NXHashTable
*table
, unsigned newCapacity
);
590 /* property attribute parsing */
591 extern const char *copyPropertyAttributeString(const objc_property_attribute_t
*attrs
, unsigned int count
);
592 extern objc_property_attribute_t
*copyPropertyAttributeList(const char *attrs
, unsigned int *outCount
);
593 extern char *copyPropertyAttributeValue(const char *attrs
, const char *name
);
596 extern void lock_init(void);
597 extern rwlock_t selLock
;
598 extern mutex_t cacheUpdateLock
;
599 extern recursive_mutex_t loadMethodLock
;
601 extern rwlock_t runtimeLock
;
603 extern mutex_t classLock
;
604 extern mutex_t methodListLock
;
607 class monitor_locker_t
: nocopy_t
{
610 monitor_locker_t(monitor_t
& newLock
) : lock(newLock
) { lock
.enter(); }
611 ~monitor_locker_t() { lock
.leave(); }
614 class mutex_locker_t
: nocopy_t
{
617 mutex_locker_t(mutex_t
& newLock
)
618 : lock(newLock
) { lock
.lock(); }
619 ~mutex_locker_t() { lock
.unlock(); }
622 class recursive_mutex_locker_t
: nocopy_t
{
623 recursive_mutex_t
& lock
;
625 recursive_mutex_locker_t(recursive_mutex_t
& newLock
)
626 : lock(newLock
) { lock
.lock(); }
627 ~recursive_mutex_locker_t() { lock
.unlock(); }
630 class rwlock_reader_t
: nocopy_t
{
633 rwlock_reader_t(rwlock_t
& newLock
) : lock(newLock
) { lock
.read(); }
634 ~rwlock_reader_t() { lock
.unlockRead(); }
637 class rwlock_writer_t
: nocopy_t
{
640 rwlock_writer_t(rwlock_t
& newLock
) : lock(newLock
) { lock
.write(); }
641 ~rwlock_writer_t() { lock
.unlockWrite(); }
646 struct alt_handler_list
;
647 extern void exception_init(void);
648 extern void _destroyAltHandlerList(struct alt_handler_list
*list
);
650 /* Class change notifications (gdb only for now) */
651 #define OBJC_CLASS_ADDED (1<<0)
652 #define OBJC_CLASS_REMOVED (1<<1)
653 #define OBJC_CLASS_IVARS_CHANGED (1<<2)
654 #define OBJC_CLASS_METHODS_CHANGED (1<<3)
655 extern void gdb_objc_class_changed(Class cls
, unsigned long changes
, const char *classname
)
656 __attribute__((noinline
));
659 // Settings from environment variables
660 #define OPTION(var, env, help) extern bool var;
661 #include "objc-env.h"
664 extern void environ_init(void);
666 extern void logReplacedMethod(const char *className
, SEL s
, bool isMeta
, const char *catName
, IMP oldImp
, IMP newImp
);
669 // objc per-thread storage
671 struct _objc_initializing_classes
*initializingClasses
; // for +initialize
672 struct SyncCache
*syncCache
; // for @synchronize
673 struct alt_handler_list
*handlerList
; // for exception alt handlers
674 char *printableNames
[4]; // temporary demangled names for logging
676 // If you add new fields here, don't forget to update
677 // _objc_pthread_destroyspecific()
679 } _objc_pthread_data
;
681 extern _objc_pthread_data
*_objc_fetch_pthread_data(bool create
);
682 extern void tls_init(void);
685 extern unsigned int encoding_getNumberOfArguments(const char *typedesc
);
686 extern unsigned int encoding_getSizeOfArguments(const char *typedesc
);
687 extern unsigned int encoding_getArgumentInfo(const char *typedesc
, unsigned int arg
, const char **type
, int *offset
);
688 extern void encoding_getReturnType(const char *t
, char *dst
, size_t dst_len
);
689 extern char * encoding_copyReturnType(const char *t
);
690 extern void encoding_getArgumentType(const char *t
, unsigned int index
, char *dst
, size_t dst_len
);
691 extern char *encoding_copyArgumentType(const char *t
, unsigned int index
);
694 extern void _destroySyncCache(struct SyncCache
*cache
);
697 extern void arr_init(void);
698 extern id
objc_autoreleaseReturnValue(id obj
);
701 extern IMP
_imp_implementationWithBlockNoCopy(id block
);
707 size_t bitsAllocated
;
710 extern layout_bitmap
layout_bitmap_create(const unsigned char *layout_string
, size_t layoutStringInstanceSize
, size_t instanceSize
, bool weak
);
711 extern layout_bitmap
layout_bitmap_create_empty(size_t instanceSize
, bool weak
);
712 extern void layout_bitmap_free(layout_bitmap bits
);
713 extern const unsigned char *layout_string_create(layout_bitmap bits
);
714 extern void layout_bitmap_set_ivar(layout_bitmap bits
, const char *type
, size_t offset
);
715 extern void layout_bitmap_grow(layout_bitmap
*bits
, size_t newCount
);
716 extern void layout_bitmap_slide(layout_bitmap
*bits
, size_t oldPos
, size_t newPos
);
717 extern void layout_bitmap_slide_anywhere(layout_bitmap
*bits
, size_t oldPos
, size_t newPos
);
718 extern bool layout_bitmap_splat(layout_bitmap dst
, layout_bitmap src
,
719 size_t oldSrcInstanceSize
);
720 extern bool layout_bitmap_or(layout_bitmap dst
, layout_bitmap src
, const char *msg
);
721 extern bool layout_bitmap_clear(layout_bitmap dst
, layout_bitmap src
, const char *msg
);
722 extern void layout_bitmap_print(layout_bitmap bits
);
726 extern Class
look_up_class(const char *aClassName
, bool includeUnconnected
, bool includeClassHandler
);
727 extern "C" void map_2_images(unsigned count
, const char * const paths
[],
728 const struct mach_header
* const mhdrs
[]);
729 extern void map_images_nolock(unsigned count
, const char * const paths
[],
730 const struct mach_header
* const mhdrs
[]);
731 extern void load_images(const char *path
, const struct mach_header
*mh
);
732 extern void unmap_image(const char *path
, const struct mach_header
*mh
);
733 extern void unmap_image_nolock(const struct mach_header
*mh
);
734 extern void _read_images(header_info
**hList
, uint32_t hCount
, int totalClasses
, int unoptimizedTotalClass
);
735 extern void _unload_image(header_info
*hi
);
736 extern const char ** _objc_copyClassNamesForImage(header_info
*hi
, unsigned int *outCount
);
739 extern const header_info
*_headerForClass(Class cls
);
741 extern Class
_class_remap(Class cls
);
742 extern Class
_class_getNonMetaClass(Class cls
, id obj
);
743 extern Ivar
_class_getVariable(Class cls
, const char *name
);
745 extern unsigned _class_createInstancesFromZone(Class cls
, size_t extraBytes
, void *zone
, id
*results
, unsigned num_requested
);
746 extern id
_objc_constructOrFree(id bytes
, Class cls
);
748 extern const char *_category_getName(Category cat
);
749 extern const char *_category_getClassName(Category cat
);
750 extern Class
_category_getClass(Category cat
);
751 extern IMP
_category_getLoadMethod(Category cat
);
753 extern id
object_cxxConstructFromClass(id obj
, Class cls
);
754 extern void object_cxxDestruct(id obj
);
756 extern void _class_resolveMethod(Class cls
, SEL sel
, id inst
);
758 extern void fixupCopiedIvars(id newObject
, id oldObject
);
759 extern Class
_class_getClassForIvar(Class cls
, Ivar ivar
);
762 #define OBJC_WARN_DEPRECATED \
764 static int warned = 0; \
767 _objc_inform_deprecated(__FUNCTION__, NULL); \
774 #ifndef STATIC_ASSERT
775 # define STATIC_ASSERT(x) _STATIC_ASSERT2(x, __LINE__)
776 # define _STATIC_ASSERT2(x, line) _STATIC_ASSERT3(x, line)
777 # define _STATIC_ASSERT3(x, line) \
779 int _static_assert[(x) ? 0 : -1]; \
780 } _static_assert_ ## line __attribute__((unavailable))
783 #define countof(arr) (sizeof(arr) / sizeof((arr)[0]))
786 static __inline
uint32_t _objc_strhash(const char *s
) {
791 hash
+= (hash
<< 8) + a
;
798 template <typename T
>
799 static inline T
log2u(T x
) {
800 return (x
<2) ? 0 : log2u(x
>>1)+1;
803 template <typename T
>
804 static inline T
exp2u(T x
) {
808 template <typename T
>
809 static T
exp2m1u(T x
) {
815 // Misalignment-safe integer types
816 __attribute__((aligned(1))) typedef uintptr_t unaligned_uintptr_t
;
817 __attribute__((aligned(1))) typedef intptr_t unaligned_intptr_t
;
818 __attribute__((aligned(1))) typedef uint64_t unaligned_uint64_t
;
819 __attribute__((aligned(1))) typedef int64_t unaligned_int64_t
;
820 __attribute__((aligned(1))) typedef uint32_t unaligned_uint32_t
;
821 __attribute__((aligned(1))) typedef int32_t unaligned_int32_t
;
822 __attribute__((aligned(1))) typedef uint16_t unaligned_uint16_t
;
823 __attribute__((aligned(1))) typedef int16_t unaligned_int16_t
;
826 // Global operator new and delete. We must not use any app overrides.
827 // This ALSO REQUIRES each of these be in libobjc's unexported symbol list.
829 #pragma clang diagnostic push
830 #pragma clang diagnostic ignored "-Winline-new-delete"
832 inline void* operator new(std::size_t size
) throw (std::bad_alloc
) { return malloc(size
); }
833 inline void* operator new[](std::size_t size
) throw (std::bad_alloc
) { return malloc(size
); }
834 inline void* operator new(std::size_t size
, const std::nothrow_t
&) throw() { return malloc(size
); }
835 inline void* operator new[](std::size_t size
, const std::nothrow_t
&) throw() { return malloc(size
); }
836 inline void operator delete(void* p
) throw() { free(p
); }
837 inline void operator delete[](void* p
) throw() { free(p
); }
838 inline void operator delete(void* p
, const std::nothrow_t
&) throw() { free(p
); }
839 inline void operator delete[](void* p
, const std::nothrow_t
&) throw() { free(p
); }
840 #pragma clang diagnostic pop
848 TimeLogger(bool record
= true)
849 : mStart(nanoseconds())
853 void log(const char *msg
) {
855 uint64_t end
= nanoseconds();
856 _objc_inform("%.2f ms: %s", (end
- mStart
) / 1000000.0, msg
);
857 mStart
= nanoseconds();
863 // StripedMap<T> is a map of void* -> T, sized appropriately
864 // for cache-friendly lock striping.
865 // For example, this may be used as StripedMap<spinlock_t>
866 // or as StripedMap<SomeStruct> where SomeStruct stores a spin lock.
870 enum { CacheLineSize
= 64 };
872 #if TARGET_OS_EMBEDDED
873 enum { StripeCount
= 8 };
875 enum { StripeCount
= 64 };
879 T value
alignas(CacheLineSize
);
882 PaddedT array
[StripeCount
];
884 static unsigned int indexForPointer(const void *p
) {
885 uintptr_t addr
= reinterpret_cast<uintptr_t>(p
);
886 return ((addr
>> 4) ^ (addr
>> 9)) % StripeCount
;
890 T
& operator[] (const void *p
) {
891 return array
[indexForPointer(p
)].value
;
893 const T
& operator[] (const void *p
) const {
894 return const_cast<StripedMap
<T
>>(this)[p
];
899 // Verify alignment expectations.
900 uintptr_t base
= (uintptr_t)&array
[0].value
;
901 uintptr_t delta
= (uintptr_t)&array
[1].value
- base
;
902 assert(delta
% CacheLineSize
== 0);
903 assert(base
% CacheLineSize
== 0);
909 // DisguisedPtr<T> acts like pointer type T*, except the
910 // stored value is disguised to hide it from tools like `leaks`.
911 // nil is disguised as itself so zero-filled memory works as expected,
912 // which means 0x80..00 is also disguised as itself but we don't care.
913 // Note that weak_entry_t knows about this encoding.
914 template <typename T
>
918 static uintptr_t disguise(T
* ptr
) {
919 return -(uintptr_t)ptr
;
922 static T
* undisguise(uintptr_t val
) {
929 : value(disguise(ptr
)) { }
930 DisguisedPtr(const DisguisedPtr
<T
>& ptr
)
931 : value(ptr
.value
) { }
933 DisguisedPtr
<T
>& operator = (T
* rhs
) {
934 value
= disguise(rhs
);
937 DisguisedPtr
<T
>& operator = (const DisguisedPtr
<T
>& rhs
) {
942 operator T
* () const {
943 return undisguise(value
);
945 T
* operator -> () const {
946 return undisguise(value
);
948 T
& operator * () const {
949 return *undisguise(value
);
951 T
& operator [] (size_t i
) const {
952 return undisguise(value
)[i
];
955 // pointer arithmetic operators omitted
956 // because we don't currently use them anywhere
959 // fixme type id is weird and not identical to objc_object*
960 static inline bool operator == (DisguisedPtr
<objc_object
> lhs
, id rhs
) {
961 return lhs
== (objc_object
*)rhs
;
963 static inline bool operator != (DisguisedPtr
<objc_object
> lhs
, id rhs
) {
964 return lhs
!= (objc_object
*)rhs
;
968 // Pointer hash function.
969 // This is not a terrific hash, but it is fast
970 // and not outrageously flawed for our purposes.
972 // Based on principles from http://locklessinc.com/articles/fast_hash/
973 // and evaluation ideas from http://floodyberry.com/noncryptohashzoo/
975 static inline uint32_t ptr_hash(uint64_t key
)
978 key
*= 0x8a970be7488fda55;
979 key
^= __builtin_bswap64(key
);
980 return (uint32_t)key
;
983 static inline uint32_t ptr_hash(uint32_t key
)
987 key
^= __builtin_bswap32(key
);
993 Higher-quality hash function. This is measurably slower in some workloads.
995 uint32_t ptr_hash(uint64_t key)
997 key -= __builtin_bswap64(key);
998 key *= 0x8a970be7488fda55;
999 key ^= __builtin_bswap64(key);
1000 key *= 0x8a970be7488fda55;
1001 key ^= __builtin_bswap64(key);
1002 return (uint32_t)key;
1005 static uint32_t ptr_hash(uint32_t key)
1007 key -= __builtin_bswap32(key);
1009 key ^= __builtin_bswap32(key);
1011 key ^= __builtin_bswap32(key);
1018 // Inlined parts of objc_object's implementation
1019 #include "objc-object.h"
1021 #endif /* _OBJC_PRIVATE_H_ */