NSObject-internal.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright (c) 2019 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. #ifndef _NSOBJECT_INTERNAL_H
  24. #define _NSOBJECT_INTERNAL_H
  25. /*
  26. * WARNING DANGER HAZARD BEWARE EEK
  27. *
  28. * Everything in this file is for Apple Internal use only.
  29. * These will change in arbitrary OS updates and in unpredictable ways.
  30. * When your program breaks, you get to keep both pieces.
  31. */
  32. /*
  33. * NSObject-internal.h: Private SPI for use by other system frameworks.
  34. */
  35. /***********************************************************************
  36. Autorelease pool implementation
  37. A thread's autorelease pool is a stack of pointers.
  38. Each pointer is either an object to release, or POOL_BOUNDARY which is
  39. an autorelease pool boundary.
  40. A pool token is a pointer to the POOL_BOUNDARY for that pool. When
  41. the pool is popped, every object hotter than the sentinel is released.
  42. The stack is divided into a doubly-linked list of pages. Pages are added
  43. and deleted as necessary.
  44. Thread-local storage points to the hot page, where newly autoreleased
  45. objects are stored.
  46. **********************************************************************/
  47. // structure version number. Only bump if ABI compatability is broken
  48. #define AUTORELEASEPOOL_VERSION 1
  49. // Set this to 1 to mprotect() autorelease pool contents
  50. #define PROTECT_AUTORELEASEPOOL 0
  51. // Set this to 1 to validate the entire autorelease pool header all the time
  52. // (i.e. use check() instead of fastcheck() everywhere)
  53. #define CHECK_AUTORELEASEPOOL (DEBUG)
  54. #ifdef __cplusplus
  55. #include <string.h>
  56. #include <assert.h>
  57. #include <objc/objc.h>
  58. #include <pthread.h>
  59. #ifndef C_ASSERT
  60. #if __has_feature(cxx_static_assert)
  61. #define C_ASSERT(expr) static_assert(expr, "(" #expr ")!")
  62. #elif __has_feature(c_static_assert)
  63. #define C_ASSERT(expr) _Static_assert(expr, "(" #expr ")!")
  64. #else
  65. #define C_ASSERT(expr)
  66. #endif
  67. #endif
  68. // Make ASSERT work when objc-private.h hasn't been included.
  69. #ifndef ASSERT
  70. #define ASSERT(x) assert(x)
  71. #endif
  72. struct magic_t {
  73. static const uint32_t M0 = 0xA1A1A1A1;
  74. # define M1 "AUTORELEASE!"
  75. static const size_t M1_len = 12;
  76. uint32_t m[4];
  77. magic_t() {
  78. ASSERT(M1_len == strlen(M1));
  79. ASSERT(M1_len == 3 * sizeof(m[1]));
  80. m[0] = M0;
  81. strncpy((char *)&m[1], M1, M1_len);
  82. }
  83. ~magic_t() {
  84. // Clear magic before deallocation.
  85. // This prevents some false positives in memory debugging tools.
  86. // fixme semantically this should be memset_s(), but the
  87. // compiler doesn't optimize that at all (rdar://44856676).
  88. volatile uint64_t *p = (volatile uint64_t *)m;
  89. p[0] = 0; p[1] = 0;
  90. }
  91. bool check() const {
  92. return (m[0] == M0 && 0 == strncmp((char *)&m[1], M1, M1_len));
  93. }
  94. bool fastcheck() const {
  95. #if CHECK_AUTORELEASEPOOL
  96. return check();
  97. #else
  98. return (m[0] == M0);
  99. #endif
  100. }
  101. # undef M1
  102. };
  103. class AutoreleasePoolPage;
  104. struct AutoreleasePoolPageData
  105. {
  106. magic_t const magic;
  107. __unsafe_unretained id *next;
  108. pthread_t const thread;
  109. AutoreleasePoolPage * const parent;
  110. AutoreleasePoolPage *child;
  111. uint32_t const depth;
  112. uint32_t hiwat;
  113. AutoreleasePoolPageData(__unsafe_unretained id* _next, pthread_t _thread, AutoreleasePoolPage* _parent, uint32_t _depth, uint32_t _hiwat)
  114. : magic(), next(_next), thread(_thread),
  115. parent(_parent), child(nil),
  116. depth(_depth), hiwat(_hiwat)
  117. {
  118. }
  119. };
  120. struct thread_data_t
  121. {
  122. #ifdef __LP64__
  123. pthread_t const thread;
  124. uint32_t const hiwat;
  125. uint32_t const depth;
  126. #else
  127. pthread_t const thread;
  128. uint32_t const hiwat;
  129. uint32_t const depth;
  130. uint32_t padding;
  131. #endif
  132. };
  133. C_ASSERT(sizeof(thread_data_t) == 16);
  134. #undef C_ASSERT
  135. #endif
  136. #endif