objc-private.h 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114
  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. #ifndef _OBJC_PRIVATE_H_
  28. #define _OBJC_PRIVATE_H_
  29. #include "objc-config.h"
  30. /* Isolate ourselves from the definitions of id and Class in the compiler
  31. * and public headers.
  32. */
  33. #ifdef _OBJC_OBJC_H_
  34. #error include objc-private.h before other headers
  35. #endif
  36. #define OBJC_TYPES_DEFINED 1
  37. #undef OBJC_OLD_DISPATCH_PROTOTYPES
  38. #define OBJC_OLD_DISPATCH_PROTOTYPES 0
  39. #include <cstddef> // for nullptr_t
  40. #include <stdint.h>
  41. #include <assert.h>
  42. // An assert that's disabled for release builds but still ensures the expression compiles.
  43. #ifdef NDEBUG
  44. #define ASSERT(x) (void)sizeof(!(x))
  45. #else
  46. #define ASSERT(x) assert(x)
  47. #endif
  48. struct objc_class;
  49. struct objc_object;
  50. typedef struct objc_class *Class;
  51. typedef struct objc_object *id;
  52. namespace {
  53. struct SideTable;
  54. };
  55. #include "isa.h"
  56. union isa_t {
  57. isa_t() { }
  58. isa_t(uintptr_t value) : bits(value) { }
  59. Class cls;
  60. uintptr_t bits;
  61. #if defined(ISA_BITFIELD)
  62. struct {
  63. ISA_BITFIELD; // defined in isa.h
  64. };
  65. #endif
  66. };
  67. struct objc_object {
  68. private:
  69. isa_t isa;
  70. public:
  71. // ISA() assumes this is NOT a tagged pointer object
  72. Class ISA();
  73. // rawISA() assumes this is NOT a tagged pointer object or a non pointer ISA
  74. Class rawISA();
  75. // getIsa() allows this to be a tagged pointer object
  76. Class getIsa();
  77. uintptr_t isaBits() const;
  78. // initIsa() should be used to init the isa of new objects only.
  79. // If this object already has an isa, use changeIsa() for correctness.
  80. // initInstanceIsa(): objects with no custom RR/AWZ
  81. // initClassIsa(): class objects
  82. // initProtocolIsa(): protocol objects
  83. // initIsa(): other objects
  84. void initIsa(Class cls /*nonpointer=false*/);
  85. void initClassIsa(Class cls /*nonpointer=maybe*/);
  86. void initProtocolIsa(Class cls /*nonpointer=maybe*/);
  87. void initInstanceIsa(Class cls, bool hasCxxDtor);
  88. // changeIsa() should be used to change the isa of existing objects.
  89. // If this is a new object, use initIsa() for performance.
  90. Class changeIsa(Class newCls);
  91. bool hasNonpointerIsa();
  92. bool isTaggedPointer();
  93. bool isBasicTaggedPointer();
  94. bool isExtTaggedPointer();
  95. bool isClass();
  96. // object may have associated objects?
  97. bool hasAssociatedObjects();
  98. void setHasAssociatedObjects();
  99. // object may be weakly referenced?
  100. bool isWeaklyReferenced();
  101. void setWeaklyReferenced_nolock();
  102. // object may have -.cxx_destruct implementation?
  103. bool hasCxxDtor();
  104. // Optimized calls to retain/release methods
  105. id retain();
  106. void release();
  107. id autorelease();
  108. // Implementations of retain/release methods
  109. id rootRetain();
  110. bool rootRelease();
  111. id rootAutorelease();
  112. bool rootTryRetain();
  113. bool rootReleaseShouldDealloc();
  114. uintptr_t rootRetainCount();
  115. // Implementation of dealloc methods
  116. bool rootIsDeallocating();
  117. void clearDeallocating();
  118. void rootDealloc();
  119. private:
  120. void initIsa(Class newCls, bool nonpointer, bool hasCxxDtor);
  121. // Slow paths for inline control
  122. id rootAutorelease2();
  123. uintptr_t overrelease_error();
  124. #if SUPPORT_NONPOINTER_ISA
  125. // Unified retain count manipulation for nonpointer isa
  126. id rootRetain(bool tryRetain, bool handleOverflow);
  127. bool rootRelease(bool performDealloc, bool handleUnderflow);
  128. id rootRetain_overflow(bool tryRetain);
  129. uintptr_t rootRelease_underflow(bool performDealloc);
  130. void clearDeallocating_slow();
  131. // Side table retain count overflow for nonpointer isa
  132. void sidetable_lock();
  133. void sidetable_unlock();
  134. void sidetable_moveExtraRC_nolock(size_t extra_rc, bool isDeallocating, bool weaklyReferenced);
  135. bool sidetable_addExtraRC_nolock(size_t delta_rc);
  136. size_t sidetable_subExtraRC_nolock(size_t delta_rc);
  137. size_t sidetable_getExtraRC_nolock();
  138. #endif
  139. // Side-table-only retain count
  140. bool sidetable_isDeallocating();
  141. void sidetable_clearDeallocating();
  142. bool sidetable_isWeaklyReferenced();
  143. void sidetable_setWeaklyReferenced_nolock();
  144. id sidetable_retain();
  145. id sidetable_retain_slow(SideTable& table);
  146. uintptr_t sidetable_release(bool performDealloc = true);
  147. uintptr_t sidetable_release_slow(SideTable& table, bool performDealloc = true);
  148. bool sidetable_tryRetain();
  149. uintptr_t sidetable_retainCount();
  150. #if DEBUG
  151. bool sidetable_present();
  152. #endif
  153. };
  154. #if __OBJC2__
  155. typedef struct method_t *Method;
  156. typedef struct ivar_t *Ivar;
  157. typedef struct category_t *Category;
  158. typedef struct property_t *objc_property_t;
  159. #else
  160. typedef struct old_method *Method;
  161. typedef struct old_ivar *Ivar;
  162. typedef struct old_category *Category;
  163. typedef struct old_property *objc_property_t;
  164. #endif
  165. // Public headers
  166. #include "objc.h"
  167. #include "runtime.h"
  168. #include "objc-os.h"
  169. #include "objc-abi.h"
  170. #include "objc-api.h"
  171. #include "objc-config.h"
  172. #include "objc-internal.h"
  173. #include "maptable.h"
  174. #include "hashtable2.h"
  175. /* Do not include message.h here. */
  176. /* #include "message.h" */
  177. #define __APPLE_API_PRIVATE
  178. #include "objc-gdb.h"
  179. #undef __APPLE_API_PRIVATE
  180. // Private headers
  181. #include "objc-ptrauth.h"
  182. #if __OBJC2__
  183. #include "objc-runtime-new.h"
  184. #else
  185. #include "objc-runtime-old.h"
  186. #endif
  187. #include "objc-references.h"
  188. #include "objc-initialize.h"
  189. #include "objc-loadmethod.h"
  190. #if SUPPORT_PREOPT && __cplusplus
  191. #include <objc-shared-cache.h>
  192. using objc_selopt_t = const objc_opt::objc_selopt_t;
  193. #else
  194. struct objc_selopt_t;
  195. #endif
  196. #define STRINGIFY(x) #x
  197. #define STRINGIFY2(x) STRINGIFY(x)
  198. __BEGIN_DECLS
  199. namespace objc {
  200. struct SafeRanges {
  201. private:
  202. struct Range {
  203. uintptr_t start;
  204. uintptr_t end;
  205. inline bool contains(uintptr_t ptr) const {
  206. uintptr_t m_start, m_end;
  207. #if __arm64__
  208. // <rdar://problem/48304934> Force the compiler to use ldp
  209. // we really don't want 2 loads and 2 jumps.
  210. __asm__(
  211. # if __LP64__
  212. "ldp %x[one], %x[two], [%x[src]]"
  213. # else
  214. "ldp %w[one], %w[two], [%x[src]]"
  215. # endif
  216. : [one] "=r" (m_start), [two] "=r" (m_end)
  217. : [src] "r" (this)
  218. );
  219. #else
  220. m_start = start;
  221. m_end = end;
  222. #endif
  223. return m_start <= ptr && ptr < m_end;
  224. }
  225. };
  226. struct Range *ranges;
  227. uint32_t count;
  228. uint32_t size : 31;
  229. uint32_t sorted : 1;
  230. public:
  231. inline bool contains(uint16_t witness, uintptr_t ptr) const {
  232. return witness < count && ranges[witness].contains(ptr);
  233. }
  234. bool find(uintptr_t ptr, uint32_t &pos);
  235. void add(uintptr_t start, uintptr_t end);
  236. void remove(uintptr_t start, uintptr_t end);
  237. };
  238. extern struct SafeRanges dataSegmentsRanges;
  239. } // objc
  240. struct header_info;
  241. // Split out the rw data from header info. For now put it in a huge array
  242. // that more than exceeds the space needed. In future we'll just allocate
  243. // this in the shared cache builder.
  244. typedef struct header_info_rw {
  245. bool getLoaded() const {
  246. return isLoaded;
  247. }
  248. void setLoaded(bool v) {
  249. isLoaded = v ? 1: 0;
  250. }
  251. bool getAllClassesRealized() const {
  252. return allClassesRealized;
  253. }
  254. void setAllClassesRealized(bool v) {
  255. allClassesRealized = v ? 1: 0;
  256. }
  257. header_info *getNext() const {
  258. return (header_info *)(next << 2);
  259. }
  260. void setNext(header_info *v) {
  261. next = ((uintptr_t)v) >> 2;
  262. }
  263. private:
  264. #ifdef __LP64__
  265. uintptr_t isLoaded : 1;
  266. uintptr_t allClassesRealized : 1;
  267. uintptr_t next : 62;
  268. #else
  269. uintptr_t isLoaded : 1;
  270. uintptr_t allClassesRealized : 1;
  271. uintptr_t next : 30;
  272. #endif
  273. } header_info_rw;
  274. struct header_info_rw* getPreoptimizedHeaderRW(const struct header_info *const hdr);
  275. typedef struct header_info {
  276. private:
  277. // Note, this is no longer a pointer, but instead an offset to a pointer
  278. // from this location.
  279. intptr_t mhdr_offset;
  280. // Note, this is no longer a pointer, but instead an offset to a pointer
  281. // from this location.
  282. intptr_t info_offset;
  283. // Do not add fields without editing ObjCModernAbstraction.hpp
  284. public:
  285. header_info_rw *getHeaderInfoRW() {
  286. header_info_rw *preopt =
  287. isPreoptimized() ? getPreoptimizedHeaderRW(this) : nil;
  288. if (preopt) return preopt;
  289. else return &rw_data[0];
  290. }
  291. const headerType *mhdr() const {
  292. return (const headerType *)(((intptr_t)&mhdr_offset) + mhdr_offset);
  293. }
  294. void setmhdr(const headerType *mhdr) {
  295. mhdr_offset = (intptr_t)mhdr - (intptr_t)&mhdr_offset;
  296. }
  297. const objc_image_info *info() const {
  298. return (const objc_image_info *)(((intptr_t)&info_offset) + info_offset);
  299. }
  300. void setinfo(const objc_image_info *info) {
  301. info_offset = (intptr_t)info - (intptr_t)&info_offset;
  302. }
  303. bool isLoaded() {
  304. return getHeaderInfoRW()->getLoaded();
  305. }
  306. void setLoaded(bool v) {
  307. getHeaderInfoRW()->setLoaded(v);
  308. }
  309. bool areAllClassesRealized() {
  310. return getHeaderInfoRW()->getAllClassesRealized();
  311. }
  312. void setAllClassesRealized(bool v) {
  313. getHeaderInfoRW()->setAllClassesRealized(v);
  314. }
  315. header_info *getNext() {
  316. return getHeaderInfoRW()->getNext();
  317. }
  318. void setNext(header_info *v) {
  319. getHeaderInfoRW()->setNext(v);
  320. }
  321. bool isBundle() {
  322. return mhdr()->filetype == MH_BUNDLE;
  323. }
  324. const char *fname() const {
  325. return dyld_image_path_containing_address(mhdr());
  326. }
  327. bool isPreoptimized() const;
  328. bool hasPreoptimizedSelectors() const;
  329. bool hasPreoptimizedClasses() const;
  330. bool hasPreoptimizedProtocols() const;
  331. #if !__OBJC2__
  332. struct old_protocol **proto_refs;
  333. struct objc_module *mod_ptr;
  334. size_t mod_count;
  335. # if TARGET_OS_WIN32
  336. struct objc_module **modules;
  337. size_t moduleCount;
  338. struct old_protocol **protocols;
  339. size_t protocolCount;
  340. void *imageinfo;
  341. size_t imageinfoBytes;
  342. SEL *selrefs;
  343. size_t selrefCount;
  344. struct objc_class **clsrefs;
  345. size_t clsrefCount;
  346. TCHAR *moduleName;
  347. # endif
  348. #endif
  349. private:
  350. // Images in the shared cache will have an empty array here while those
  351. // allocated at run time will allocate a single entry.
  352. header_info_rw rw_data[];
  353. } header_info;
  354. extern header_info *FirstHeader;
  355. extern header_info *LastHeader;
  356. extern void appendHeader(header_info *hi);
  357. extern void removeHeader(header_info *hi);
  358. extern objc_image_info *_getObjcImageInfo(const headerType *head, size_t *size);
  359. extern bool _hasObjcContents(const header_info *hi);
  360. // Mach-O segment and section names are 16 bytes and may be un-terminated.
  361. static inline bool segnameEquals(const char *lhs, const char *rhs) {
  362. return 0 == strncmp(lhs, rhs, 16);
  363. }
  364. static inline bool segnameStartsWith(const char *segname, const char *prefix) {
  365. return 0 == strncmp(segname, prefix, strlen(prefix));
  366. }
  367. static inline bool sectnameEquals(const char *lhs, const char *rhs) {
  368. return segnameEquals(lhs, rhs);
  369. }
  370. static inline bool sectnameStartsWith(const char *sectname, const char *prefix){
  371. return segnameStartsWith(sectname, prefix);
  372. }
  373. /* selectors */
  374. extern void sel_init(size_t selrefCount);
  375. extern SEL sel_registerNameNoLock(const char *str, bool copy);
  376. extern SEL SEL_cxx_construct;
  377. extern SEL SEL_cxx_destruct;
  378. /* preoptimization */
  379. extern void preopt_init(void);
  380. extern void disableSharedCacheOptimizations(void);
  381. extern bool isPreoptimized(void);
  382. extern bool noMissingWeakSuperclasses(void);
  383. extern header_info *preoptimizedHinfoForHeader(const headerType *mhdr);
  384. extern objc_selopt_t *preoptimizedSelectors(void);
  385. extern bool sharedCacheSupportsProtocolRoots(void);
  386. extern Protocol *getPreoptimizedProtocol(const char *name);
  387. extern Protocol *getSharedCachePreoptimizedProtocol(const char *name);
  388. extern unsigned getPreoptimizedClassUnreasonableCount();
  389. extern Class getPreoptimizedClass(const char *name);
  390. extern Class* copyPreoptimizedClasses(const char *name, int *outCount);
  391. extern Class _calloc_class(size_t size);
  392. /* method lookup */
  393. enum {
  394. LOOKUP_INITIALIZE = 1,
  395. LOOKUP_RESOLVER = 2,
  396. LOOKUP_CACHE = 4,
  397. LOOKUP_NIL = 8,
  398. };
  399. extern IMP lookUpImpOrForward(id obj, SEL, Class cls, int behavior);
  400. static inline IMP
  401. lookUpImpOrNil(id obj, SEL sel, Class cls, int behavior = 0)
  402. {
  403. return lookUpImpOrForward(obj, sel, cls, behavior | LOOKUP_CACHE | LOOKUP_NIL);
  404. }
  405. extern IMP lookupMethodInClassAndLoadCache(Class cls, SEL sel);
  406. extern BOOL class_respondsToSelector_inst(id inst, SEL sel, Class cls);
  407. extern Class class_initialize(Class cls, id inst);
  408. extern bool objcMsgLogEnabled;
  409. extern bool logMessageSend(bool isClassMethod,
  410. const char *objectsClass,
  411. const char *implementingClass,
  412. SEL selector);
  413. /* message dispatcher */
  414. #if !OBJC_OLD_DISPATCH_PROTOTYPES
  415. extern void _objc_msgForward_impcache(void);
  416. #else
  417. extern id _objc_msgForward_impcache(id, SEL, ...);
  418. #endif
  419. /* errors */
  420. extern id(*badAllocHandler)(Class);
  421. extern id _objc_callBadAllocHandler(Class cls) __attribute__((cold, noinline));
  422. extern void __objc_error(id, const char *, ...) __attribute__((cold, format (printf, 2, 3), noreturn));
  423. extern void _objc_inform(const char *fmt, ...) __attribute__((cold, format(printf, 1, 2)));
  424. extern void _objc_inform_on_crash(const char *fmt, ...) __attribute__((cold, format (printf, 1, 2)));
  425. extern void _objc_inform_now_and_on_crash(const char *fmt, ...) __attribute__((cold, format (printf, 1, 2)));
  426. extern void _objc_inform_deprecated(const char *oldname, const char *newname) __attribute__((cold, noinline));
  427. extern void inform_duplicate(const char *name, Class oldCls, Class cls);
  428. /* magic */
  429. extern Class _objc_getFreedObjectClass (void);
  430. /* map table additions */
  431. extern void *NXMapKeyCopyingInsert(NXMapTable *table, const void *key, const void *value);
  432. extern void *NXMapKeyFreeingRemove(NXMapTable *table, const void *key);
  433. /* hash table additions */
  434. extern unsigned _NXHashCapacity(NXHashTable *table);
  435. extern void _NXHashRehashToCapacity(NXHashTable *table, unsigned newCapacity);
  436. /* property attribute parsing */
  437. extern const char *copyPropertyAttributeString(const objc_property_attribute_t *attrs, unsigned int count);
  438. extern objc_property_attribute_t *copyPropertyAttributeList(const char *attrs, unsigned int *outCount);
  439. extern char *copyPropertyAttributeValue(const char *attrs, const char *name);
  440. /* locking */
  441. class monitor_locker_t : nocopy_t {
  442. monitor_t& lock;
  443. public:
  444. monitor_locker_t(monitor_t& newLock) : lock(newLock) { lock.enter(); }
  445. ~monitor_locker_t() { lock.leave(); }
  446. };
  447. class recursive_mutex_locker_t : nocopy_t {
  448. recursive_mutex_t& lock;
  449. public:
  450. recursive_mutex_locker_t(recursive_mutex_t& newLock)
  451. : lock(newLock) { lock.lock(); }
  452. ~recursive_mutex_locker_t() { lock.unlock(); }
  453. };
  454. /* Exceptions */
  455. struct alt_handler_list;
  456. extern void exception_init(void);
  457. extern void _destroyAltHandlerList(struct alt_handler_list *list);
  458. /* Class change notifications (gdb only for now) */
  459. #define OBJC_CLASS_ADDED (1<<0)
  460. #define OBJC_CLASS_REMOVED (1<<1)
  461. #define OBJC_CLASS_IVARS_CHANGED (1<<2)
  462. #define OBJC_CLASS_METHODS_CHANGED (1<<3)
  463. extern void gdb_objc_class_changed(Class cls, unsigned long changes, const char *classname)
  464. __attribute__((noinline));
  465. // Settings from environment variables
  466. #define OPTION(var, env, help) extern bool var;
  467. #include "objc-env.h"
  468. #undef OPTION
  469. extern void environ_init(void);
  470. extern void runtime_init(void);
  471. extern void logReplacedMethod(const char *className, SEL s, bool isMeta, const char *catName, IMP oldImp, IMP newImp);
  472. // objc per-thread storage
  473. typedef struct {
  474. struct _objc_initializing_classes *initializingClasses; // for +initialize
  475. struct SyncCache *syncCache; // for @synchronize
  476. struct alt_handler_list *handlerList; // for exception alt handlers
  477. char *printableNames[4]; // temporary demangled names for logging
  478. const char **classNameLookups; // for objc_getClass() hooks
  479. unsigned classNameLookupsAllocated;
  480. unsigned classNameLookupsUsed;
  481. // If you add new fields here, don't forget to update
  482. // _objc_pthread_destroyspecific()
  483. } _objc_pthread_data;
  484. extern _objc_pthread_data *_objc_fetch_pthread_data(bool create);
  485. extern void tls_init(void);
  486. // encoding.h
  487. extern unsigned int encoding_getNumberOfArguments(const char *typedesc);
  488. extern unsigned int encoding_getSizeOfArguments(const char *typedesc);
  489. extern unsigned int encoding_getArgumentInfo(const char *typedesc, unsigned int arg, const char **type, int *offset);
  490. extern void encoding_getReturnType(const char *t, char *dst, size_t dst_len);
  491. extern char * encoding_copyReturnType(const char *t);
  492. extern void encoding_getArgumentType(const char *t, unsigned int index, char *dst, size_t dst_len);
  493. extern char *encoding_copyArgumentType(const char *t, unsigned int index);
  494. // sync.h
  495. extern void _destroySyncCache(struct SyncCache *cache);
  496. // arr
  497. extern void arr_init(void);
  498. extern id objc_autoreleaseReturnValue(id obj);
  499. // block trampolines
  500. extern void _imp_implementationWithBlock_init(void);
  501. extern IMP _imp_implementationWithBlockNoCopy(id block);
  502. // layout.h
  503. typedef struct {
  504. uint8_t *bits;
  505. size_t bitCount;
  506. size_t bitsAllocated;
  507. bool weak;
  508. } layout_bitmap;
  509. extern layout_bitmap layout_bitmap_create(const unsigned char *layout_string, size_t layoutStringInstanceSize, size_t instanceSize, bool weak);
  510. extern layout_bitmap layout_bitmap_create_empty(size_t instanceSize, bool weak);
  511. extern void layout_bitmap_free(layout_bitmap bits);
  512. extern const unsigned char *layout_string_create(layout_bitmap bits);
  513. extern void layout_bitmap_set_ivar(layout_bitmap bits, const char *type, size_t offset);
  514. extern void layout_bitmap_grow(layout_bitmap *bits, size_t newCount);
  515. extern void layout_bitmap_slide(layout_bitmap *bits, size_t oldPos, size_t newPos);
  516. extern void layout_bitmap_slide_anywhere(layout_bitmap *bits, size_t oldPos, size_t newPos);
  517. extern bool layout_bitmap_splat(layout_bitmap dst, layout_bitmap src,
  518. size_t oldSrcInstanceSize);
  519. extern bool layout_bitmap_or(layout_bitmap dst, layout_bitmap src, const char *msg);
  520. extern bool layout_bitmap_clear(layout_bitmap dst, layout_bitmap src, const char *msg);
  521. extern void layout_bitmap_print(layout_bitmap bits);
  522. // fixme runtime
  523. extern bool MultithreadedForkChild;
  524. extern id objc_noop_imp(id self, SEL _cmd);
  525. extern Class look_up_class(const char *aClassName, bool includeUnconnected, bool includeClassHandler);
  526. extern "C" void map_images(unsigned count, const char * const paths[],
  527. const struct mach_header * const mhdrs[]);
  528. extern void map_images_nolock(unsigned count, const char * const paths[],
  529. const struct mach_header * const mhdrs[]);
  530. extern void load_images(const char *path, const struct mach_header *mh);
  531. extern void unmap_image(const char *path, const struct mach_header *mh);
  532. extern void unmap_image_nolock(const struct mach_header *mh);
  533. extern void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClass);
  534. extern void _unload_image(header_info *hi);
  535. extern const header_info *_headerForClass(Class cls);
  536. extern Class _class_remap(Class cls);
  537. extern Ivar _class_getVariable(Class cls, const char *name);
  538. extern unsigned _class_createInstancesFromZone(Class cls, size_t extraBytes, void *zone, id *results, unsigned num_requested);
  539. extern const char *_category_getName(Category cat);
  540. extern const char *_category_getClassName(Category cat);
  541. extern Class _category_getClass(Category cat);
  542. extern IMP _category_getLoadMethod(Category cat);
  543. enum {
  544. OBJECT_CONSTRUCT_NONE = 0,
  545. OBJECT_CONSTRUCT_FREE_ONFAILURE = 1,
  546. OBJECT_CONSTRUCT_CALL_BADALLOC = 2,
  547. };
  548. extern id object_cxxConstructFromClass(id obj, Class cls, int flags);
  549. extern void object_cxxDestruct(id obj);
  550. extern void fixupCopiedIvars(id newObject, id oldObject);
  551. extern Class _class_getClassForIvar(Class cls, Ivar ivar);
  552. #define OBJC_WARN_DEPRECATED \
  553. do { \
  554. static int warned = 0; \
  555. if (!warned) { \
  556. warned = 1; \
  557. _objc_inform_deprecated(__FUNCTION__, NULL); \
  558. } \
  559. } while (0) \
  560. __END_DECLS
  561. #ifndef STATIC_ASSERT
  562. # define STATIC_ASSERT(x) _STATIC_ASSERT2(x, __LINE__)
  563. # define _STATIC_ASSERT2(x, line) _STATIC_ASSERT3(x, line)
  564. # define _STATIC_ASSERT3(x, line) \
  565. typedef struct { \
  566. int _static_assert[(x) ? 0 : -1]; \
  567. } _static_assert_ ## line __attribute__((unavailable))
  568. #endif
  569. #define countof(arr) (sizeof(arr) / sizeof((arr)[0]))
  570. static __inline uint32_t _objc_strhash(const char *s) {
  571. uint32_t hash = 0;
  572. for (;;) {
  573. int a = *s++;
  574. if (0 == a) break;
  575. hash += (hash << 8) + a;
  576. }
  577. return hash;
  578. }
  579. #if __cplusplus
  580. template <typename T>
  581. static inline T log2u(T x) {
  582. return (x<2) ? 0 : log2u(x>>1)+1;
  583. }
  584. template <typename T>
  585. static inline T exp2u(T x) {
  586. return (1 << x);
  587. }
  588. template <typename T>
  589. static T exp2m1u(T x) {
  590. return (1 << x) - 1;
  591. }
  592. #endif
  593. // Misalignment-safe integer types
  594. __attribute__((aligned(1))) typedef uintptr_t unaligned_uintptr_t;
  595. __attribute__((aligned(1))) typedef intptr_t unaligned_intptr_t;
  596. __attribute__((aligned(1))) typedef uint64_t unaligned_uint64_t;
  597. __attribute__((aligned(1))) typedef int64_t unaligned_int64_t;
  598. __attribute__((aligned(1))) typedef uint32_t unaligned_uint32_t;
  599. __attribute__((aligned(1))) typedef int32_t unaligned_int32_t;
  600. __attribute__((aligned(1))) typedef uint16_t unaligned_uint16_t;
  601. __attribute__((aligned(1))) typedef int16_t unaligned_int16_t;
  602. // Global operator new and delete. We must not use any app overrides.
  603. // This ALSO REQUIRES each of these be in libobjc's unexported symbol list.
  604. #if __cplusplus
  605. #pragma clang diagnostic push
  606. #pragma clang diagnostic ignored "-Winline-new-delete"
  607. #include <new>
  608. inline void* operator new(std::size_t size) throw (std::bad_alloc) { return malloc(size); }
  609. inline void* operator new[](std::size_t size) throw (std::bad_alloc) { return malloc(size); }
  610. inline void* operator new(std::size_t size, const std::nothrow_t&) throw() { return malloc(size); }
  611. inline void* operator new[](std::size_t size, const std::nothrow_t&) throw() { return malloc(size); }
  612. inline void operator delete(void* p) throw() { free(p); }
  613. inline void operator delete[](void* p) throw() { free(p); }
  614. inline void operator delete(void* p, const std::nothrow_t&) throw() { free(p); }
  615. inline void operator delete[](void* p, const std::nothrow_t&) throw() { free(p); }
  616. #pragma clang diagnostic pop
  617. #endif
  618. class TimeLogger {
  619. uint64_t mStart;
  620. bool mRecord;
  621. public:
  622. TimeLogger(bool record = true)
  623. : mStart(nanoseconds())
  624. , mRecord(record)
  625. { }
  626. void log(const char *msg) {
  627. if (mRecord) {
  628. uint64_t end = nanoseconds();
  629. _objc_inform("%.2f ms: %s", (end - mStart) / 1000000.0, msg);
  630. mStart = nanoseconds();
  631. }
  632. }
  633. };
  634. enum { CacheLineSize = 64 };
  635. // StripedMap<T> is a map of void* -> T, sized appropriately
  636. // for cache-friendly lock striping.
  637. // For example, this may be used as StripedMap<spinlock_t>
  638. // or as StripedMap<SomeStruct> where SomeStruct stores a spin lock.
  639. template<typename T>
  640. class StripedMap {
  641. #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
  642. enum { StripeCount = 8 };
  643. #else
  644. enum { StripeCount = 64 };
  645. #endif
  646. struct PaddedT {
  647. T value alignas(CacheLineSize);
  648. };
  649. PaddedT array[StripeCount];
  650. static unsigned int indexForPointer(const void *p) {
  651. uintptr_t addr = reinterpret_cast<uintptr_t>(p);
  652. return ((addr >> 4) ^ (addr >> 9)) % StripeCount;
  653. }
  654. public:
  655. T& operator[] (const void *p) {
  656. return array[indexForPointer(p)].value;
  657. }
  658. const T& operator[] (const void *p) const {
  659. return const_cast<StripedMap<T>>(this)[p];
  660. }
  661. // Shortcuts for StripedMaps of locks.
  662. void lockAll() {
  663. for (unsigned int i = 0; i < StripeCount; i++) {
  664. array[i].value.lock();
  665. }
  666. }
  667. void unlockAll() {
  668. for (unsigned int i = 0; i < StripeCount; i++) {
  669. array[i].value.unlock();
  670. }
  671. }
  672. void forceResetAll() {
  673. for (unsigned int i = 0; i < StripeCount; i++) {
  674. array[i].value.forceReset();
  675. }
  676. }
  677. void defineLockOrder() {
  678. for (unsigned int i = 1; i < StripeCount; i++) {
  679. lockdebug_lock_precedes_lock(&array[i-1].value, &array[i].value);
  680. }
  681. }
  682. void precedeLock(const void *newlock) {
  683. // assumes defineLockOrder is also called
  684. lockdebug_lock_precedes_lock(&array[StripeCount-1].value, newlock);
  685. }
  686. void succeedLock(const void *oldlock) {
  687. // assumes defineLockOrder is also called
  688. lockdebug_lock_precedes_lock(oldlock, &array[0].value);
  689. }
  690. const void *getLock(int i) {
  691. if (i < StripeCount) return &array[i].value;
  692. else return nil;
  693. }
  694. #if DEBUG
  695. StripedMap() {
  696. // Verify alignment expectations.
  697. uintptr_t base = (uintptr_t)&array[0].value;
  698. uintptr_t delta = (uintptr_t)&array[1].value - base;
  699. ASSERT(delta % CacheLineSize == 0);
  700. ASSERT(base % CacheLineSize == 0);
  701. }
  702. #else
  703. constexpr StripedMap() {}
  704. #endif
  705. };
  706. // DisguisedPtr<T> acts like pointer type T*, except the
  707. // stored value is disguised to hide it from tools like `leaks`.
  708. // nil is disguised as itself so zero-filled memory works as expected,
  709. // which means 0x80..00 is also disguised as itself but we don't care.
  710. // Note that weak_entry_t knows about this encoding.
  711. template <typename T>
  712. class DisguisedPtr {
  713. uintptr_t value;
  714. static uintptr_t disguise(T* ptr) {
  715. return -(uintptr_t)ptr;
  716. }
  717. static T* undisguise(uintptr_t val) {
  718. return (T*)-val;
  719. }
  720. public:
  721. DisguisedPtr() { }
  722. DisguisedPtr(T* ptr)
  723. : value(disguise(ptr)) { }
  724. DisguisedPtr(const DisguisedPtr<T>& ptr)
  725. : value(ptr.value) { }
  726. DisguisedPtr<T>& operator = (T* rhs) {
  727. value = disguise(rhs);
  728. return *this;
  729. }
  730. DisguisedPtr<T>& operator = (const DisguisedPtr<T>& rhs) {
  731. value = rhs.value;
  732. return *this;
  733. }
  734. operator T* () const {
  735. return undisguise(value);
  736. }
  737. T* operator -> () const {
  738. return undisguise(value);
  739. }
  740. T& operator * () const {
  741. return *undisguise(value);
  742. }
  743. T& operator [] (size_t i) const {
  744. return undisguise(value)[i];
  745. }
  746. // pointer arithmetic operators omitted
  747. // because we don't currently use them anywhere
  748. };
  749. // fixme type id is weird and not identical to objc_object*
  750. static inline bool operator == (DisguisedPtr<objc_object> lhs, id rhs) {
  751. return lhs == (objc_object *)rhs;
  752. }
  753. static inline bool operator != (DisguisedPtr<objc_object> lhs, id rhs) {
  754. return lhs != (objc_object *)rhs;
  755. }
  756. // Storage for a thread-safe chained hook function.
  757. // get() returns the value for calling.
  758. // set() installs a new function and returns the old one for chaining.
  759. // More precisely, set() writes the old value to a variable supplied by
  760. // the caller. get() and set() use appropriate barriers so that the
  761. // old value is safely written to the variable before the new value is
  762. // called to use it.
  763. //
  764. // T1: store to old variable; store-release to hook variable
  765. // T2: load-acquire from hook variable; call it; called hook loads old variable
  766. template <typename Fn>
  767. class ChainedHookFunction {
  768. std::atomic<Fn> hook{nil};
  769. public:
  770. ChainedHookFunction(Fn f) : hook{f} { };
  771. Fn get() {
  772. return hook.load(std::memory_order_acquire);
  773. }
  774. void set(Fn newValue, Fn *oldVariable)
  775. {
  776. Fn oldValue = hook.load(std::memory_order_relaxed);
  777. do {
  778. *oldVariable = oldValue;
  779. } while (!hook.compare_exchange_weak(oldValue, newValue,
  780. std::memory_order_release,
  781. std::memory_order_relaxed));
  782. }
  783. };
  784. // A small vector for use as a global variable. Only supports appending and
  785. // iteration. Stores a single element inline, and multiple elements in a heap
  786. // allocation. There is no attempt to amortize reallocation cost; this is
  787. // intended to be used in situation where zero or one element is common, two
  788. // might happen, and three or more is very rare.
  789. //
  790. // This does not clean up its allocation, and thus cannot be used as a local
  791. // variable or member of something with limited lifetime.
  792. template <typename T, unsigned InlineCount>
  793. class GlobalSmallVector {
  794. static_assert(std::is_pod<T>::value, "SmallVector requires POD types");
  795. protected:
  796. unsigned count{0};
  797. union {
  798. T inlineElements[InlineCount];
  799. T *elements;
  800. };
  801. public:
  802. void append(const T &val) {
  803. if (count < InlineCount) {
  804. // We have space. Store the new value inline.
  805. inlineElements[count] = val;
  806. } else if (count == InlineCount) {
  807. // Inline storage is full. Switch to a heap allocation.
  808. T *newElements = (T *)malloc((count + 1) * sizeof(T));
  809. memcpy(newElements, inlineElements, count * sizeof(T));
  810. newElements[count] = val;
  811. elements = newElements;
  812. } else {
  813. // Resize the heap allocation and append.
  814. elements = (T *)realloc(elements, (count + 1) * sizeof(T));
  815. elements[count] = val;
  816. }
  817. count++;
  818. }
  819. const T *begin() const {
  820. return count <= InlineCount ? inlineElements : elements;
  821. }
  822. const T *end() const {
  823. return begin() + count;
  824. }
  825. };
  826. // A small vector that cleans up its internal memory allocation when destroyed.
  827. template <typename T, unsigned InlineCount>
  828. class SmallVector: public GlobalSmallVector<T, InlineCount> {
  829. public:
  830. ~SmallVector() {
  831. if (this->count > InlineCount)
  832. free(this->elements);
  833. }
  834. template <unsigned OtherCount>
  835. void initFrom(const GlobalSmallVector<T, OtherCount> &other) {
  836. ASSERT(this->count == 0);
  837. this->count = (unsigned)(other.end() - other.begin());
  838. if (this->count > InlineCount) {
  839. this->elements = (T *)memdup(other.begin(), this->count * sizeof(T));
  840. } else {
  841. memcpy(this->inlineElements, other.begin(), this->count * sizeof(T));
  842. }
  843. }
  844. };
  845. // Pointer hash function.
  846. // This is not a terrific hash, but it is fast
  847. // and not outrageously flawed for our purposes.
  848. // Based on principles from http://locklessinc.com/articles/fast_hash/
  849. // and evaluation ideas from http://floodyberry.com/noncryptohashzoo/
  850. #if __LP64__
  851. static inline uint32_t ptr_hash(uint64_t key)
  852. {
  853. key ^= key >> 4;
  854. key *= 0x8a970be7488fda55;
  855. key ^= __builtin_bswap64(key);
  856. return (uint32_t)key;
  857. }
  858. #else
  859. static inline uint32_t ptr_hash(uint32_t key)
  860. {
  861. key ^= key >> 4;
  862. key *= 0x5052acdb;
  863. key ^= __builtin_bswap32(key);
  864. return key;
  865. }
  866. #endif
  867. /*
  868. Higher-quality hash function. This is measurably slower in some workloads.
  869. #if __LP64__
  870. uint32_t ptr_hash(uint64_t key)
  871. {
  872. key -= __builtin_bswap64(key);
  873. key *= 0x8a970be7488fda55;
  874. key ^= __builtin_bswap64(key);
  875. key *= 0x8a970be7488fda55;
  876. key ^= __builtin_bswap64(key);
  877. return (uint32_t)key;
  878. }
  879. #else
  880. static uint32_t ptr_hash(uint32_t key)
  881. {
  882. key -= __builtin_bswap32(key);
  883. key *= 0x5052acdb;
  884. key ^= __builtin_bswap32(key);
  885. key *= 0x5052acdb;
  886. key ^= __builtin_bswap32(key);
  887. return key;
  888. }
  889. #endif
  890. */
  891. // Lock declarations
  892. #include "objc-locks.h"
  893. // Inlined parts of objc_object's implementation
  894. #include "objc-object.h"
  895. #endif /* _OBJC_PRIVATE_H_ */