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