]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-runtime-new.h
objc4-493.11.tar.gz
[apple/objc4.git] / runtime / objc-runtime-new.h
1 /*
2 * Copyright (c) 2005-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 #ifndef _OBJC_RUNTIME_NEW_H
25 #define _OBJC_RUNTIME_NEW_H
26
27 __BEGIN_DECLS
28
29 // Values for class_ro_t->flags
30 // These are emitted by the compiler and are part of the ABI.
31 // class is a metaclass
32 #define RO_META (1<<0)
33 // class is a root class
34 #define RO_ROOT (1<<1)
35 // class has .cxx_construct/destruct implementations
36 #define RO_HAS_CXX_STRUCTORS (1<<2)
37 // class has +load implementation
38 // #define RO_HAS_LOAD_METHOD (1<<3)
39 // class has visibility=hidden set
40 #define RO_HIDDEN (1<<4)
41 // class has attribute(objc_exception): OBJC_EHTYPE_$_ThisClass is non-weak
42 #define RO_EXCEPTION (1<<5)
43 // this bit is available for reassignment
44 // #define RO_REUSE_ME (1<<6)
45 // class compiled with -fobjc-arr (automatic retain/release)
46 #define RO_IS_ARR (1<<7)
47
48 // class is in an unloadable bundle - must never be set by compiler
49 #define RO_FROM_BUNDLE (1<<29)
50 // class is unrealized future class - must never be set by compiler
51 #define RO_FUTURE (1<<30)
52 // class is realized - must never be set by compiler
53 #define RO_REALIZED (1<<31)
54
55 // Values for class_rw_t->flags
56 // These are not emitted by the compiler and are never used in class_ro_t.
57 // Their presence should be considered in future ABI versions.
58 // class_t->data is class_rw_t, not class_ro_t
59 #define RW_REALIZED (1<<31)
60 // class is unresolved future class
61 #define RW_FUTURE (1<<30)
62 // class is initialized
63 #define RW_INITIALIZED (1<<29)
64 // class is initializing
65 #define RW_INITIALIZING (1<<28)
66 // class_rw_t->ro is heap copy of class_ro_t
67 #define RW_COPIED_RO (1<<27)
68 // class allocated but not yet registered
69 #define RW_CONSTRUCTING (1<<26)
70 // class allocated and registered
71 #define RW_CONSTRUCTED (1<<25)
72 // GC: class has unsafe finalize method
73 #define RW_FINALIZE_ON_MAIN_THREAD (1<<24)
74 // class +load has been called
75 #define RW_LOADED (1<<23)
76 // class does not share super's vtable
77 #define RW_SPECIALIZED_VTABLE (1<<22)
78 // class instances may have associative references
79 #define RW_INSTANCES_HAVE_ASSOCIATED_OBJECTS (1<<21)
80 // class or superclass has .cxx_construct/destruct implementations
81 #define RW_HAS_CXX_STRUCTORS (1<<20)
82 // class has instance-specific GC layout
83 #define RW_HAS_INSTANCE_SPECIFIC_LAYOUT (1 << 19)
84 // class or superclass has non-trivial .release_ivars implementation
85 #define RW_HAS_IVAR_RELEASER (1<<18)
86 // class or superclass has custom retain/release/autorelease/retainCount impl
87 #define RW_HAS_CUSTOM_RR (1<<17)
88
89 struct method_t {
90 SEL name;
91 const char *types;
92 IMP imp;
93
94 struct SortBySELAddress :
95 public std::binary_function<const method_t&,
96 const method_t&, bool>
97 {
98 bool operator() (const method_t& lhs,
99 const method_t& rhs)
100 { return lhs.name < rhs.name; }
101 };
102 };
103
104 typedef struct method_list_t {
105 uint32_t entsize_NEVER_USE; // high bits used for fixup markers
106 uint32_t count;
107 method_t first;
108
109 uint32_t getEntsize() const {
110 return entsize_NEVER_USE & ~(uint32_t)3;
111 }
112 uint32_t getCount() const {
113 return count;
114 }
115 method_t& get(uint32_t i) const {
116 return *(method_t *)((uint8_t *)&first + i*getEntsize());
117 }
118
119 // iterate methods, taking entsize into account
120 // fixme need a proper const_iterator
121 struct method_iterator {
122 uint32_t entsize;
123 uint32_t index; // keeping track of this saves a divide in operator-
124 method_t* method;
125
126 typedef std::random_access_iterator_tag iterator_category;
127 typedef method_t value_type;
128 typedef ptrdiff_t difference_type;
129 typedef method_t* pointer;
130 typedef method_t& reference;
131
132 method_iterator() { }
133
134 method_iterator(const method_list_t& mlist, uint32_t start = 0)
135 : entsize(mlist.getEntsize())
136 , index(start)
137 , method(&mlist.get(start))
138 { }
139
140 const method_iterator& operator += (ptrdiff_t count) {
141 method = (method_t*)((uint8_t *)method + count*entsize);
142 index += (int32_t)count;
143 return *this;
144 }
145 const method_iterator& operator -= (ptrdiff_t count) {
146 method = (method_t*)((uint8_t *)method - count*entsize);
147 index -= (int32_t)count;
148 return *this;
149 }
150 const method_iterator operator + (ptrdiff_t count) const {
151 return method_iterator(*this) += count;
152 }
153 const method_iterator operator - (ptrdiff_t count) const {
154 return method_iterator(*this) -= count;
155 }
156
157 method_iterator& operator ++ () { *this += 1; return *this; }
158 method_iterator& operator -- () { *this -= 1; return *this; }
159 method_iterator operator ++ (int) {
160 method_iterator result(*this); *this += 1; return result;
161 }
162 method_iterator operator -- (int) {
163 method_iterator result(*this); *this -= 1; return result;
164 }
165
166 ptrdiff_t operator - (const method_iterator& rhs) const {
167 return (ptrdiff_t)this->index - (ptrdiff_t)rhs.index;
168 }
169
170 method_t& operator * () const { return *method; }
171 method_t* operator -> () const { return method; }
172
173 operator method_t& () const { return *method; }
174
175 bool operator == (const method_iterator& rhs) {
176 return this->method == rhs.method;
177 }
178 bool operator != (const method_iterator& rhs) {
179 return this->method != rhs.method;
180 }
181
182 bool operator < (const method_iterator& rhs) {
183 return this->method < rhs.method;
184 }
185 bool operator > (const method_iterator& rhs) {
186 return this->method > rhs.method;
187 }
188 };
189
190 method_iterator begin() const { return method_iterator(*this, 0); }
191 method_iterator end() const { return method_iterator(*this, getCount()); }
192
193 } method_list_t;
194
195 typedef struct ivar_t {
196 // *offset is 64-bit by accident even though other
197 // fields restrict total instance size to 32-bit.
198 uintptr_t *offset;
199 const char *name;
200 const char *type;
201 // alignment is sometimes -1; use ivar_alignment() instead
202 uint32_t alignment __attribute__((deprecated));
203 uint32_t size;
204 } ivar_t;
205
206 typedef struct ivar_list_t {
207 uint32_t entsize;
208 uint32_t count;
209 ivar_t first;
210 } ivar_list_t;
211
212 typedef struct objc_property {
213 const char *name;
214 const char *attributes;
215 } property_t;
216
217 typedef struct property_list_t {
218 uint32_t entsize;
219 uint32_t count;
220 property_t first;
221 } property_list_t;
222
223 typedef uintptr_t protocol_ref_t; // protocol_t *, but unremapped
224
225 typedef struct protocol_t {
226 id isa;
227 const char *name;
228 struct protocol_list_t *protocols;
229 method_list_t *instanceMethods;
230 method_list_t *classMethods;
231 method_list_t *optionalInstanceMethods;
232 method_list_t *optionalClassMethods;
233 property_list_t *instanceProperties;
234 } protocol_t;
235
236 typedef struct protocol_list_t {
237 // count is 64-bit by accident.
238 uintptr_t count;
239 protocol_ref_t list[0]; // variable-size
240 } protocol_list_t;
241
242 typedef struct class_ro_t {
243 uint32_t flags;
244 uint32_t instanceStart;
245 uint32_t instanceSize;
246 #ifdef __LP64__
247 uint32_t reserved;
248 #endif
249
250 const uint8_t * ivarLayout;
251
252 const char * name;
253 const method_list_t * baseMethods;
254 const protocol_list_t * baseProtocols;
255 const ivar_list_t * ivars;
256
257 const uint8_t * weakIvarLayout;
258 const property_list_t *baseProperties;
259 } class_ro_t;
260
261 typedef struct class_rw_t {
262 uint32_t flags;
263 uint32_t version;
264
265 const class_ro_t *ro;
266
267 method_list_t **methods;
268 struct chained_property_list *properties;
269 const protocol_list_t ** protocols;
270
271 struct class_t *firstSubclass;
272 struct class_t *nextSiblingClass;
273 } class_rw_t;
274
275 // We cannot store flags in the low bits of the 'data' field until we work with
276 // the 'leaks' team to not think that objc is leaking memory. See radar 8955342
277 // for more info.
278 #define CLASS_FAST_FLAGS_VIA_RW_DATA 0
279
280 typedef struct class_t {
281 struct class_t *isa;
282 struct class_t *superclass;
283 Cache cache;
284 IMP *vtable;
285 uintptr_t data_NEVER_USE; // class_rw_t * plus flags
286
287 class_rw_t *data() const {
288 #if CLASS_FAST_FLAGS_VIA_RW_DATA
289 return (class_rw_t *)(data_NEVER_USE & ~3UL);
290 #else
291 return (class_rw_t *)data_NEVER_USE;
292 #endif
293 }
294 void setData(class_rw_t *newData) {
295 #if CLASS_FAST_FLAGS_VIA_RW_DATA
296 uintptr_t flags = (uintptr_t)data_NEVER_USE & 3UL;
297 data_NEVER_USE = (uintptr_t)newData | flags;
298 #else
299 data_NEVER_USE = (uintptr_t)newData;
300 #endif
301 }
302
303 bool hasCustomRR() const {
304 #if CLASS_FAST_FLAGS_VIA_RW_DATA
305 return data_NEVER_USE & 1UL;
306 #else
307 return (data()->flags & RW_HAS_CUSTOM_RR);
308 #endif
309 }
310 void setHasCustomRR();
311 void unsetHasCustomRR();
312
313 bool hasIvarReleaser() const {
314 return (data()->flags & RW_HAS_IVAR_RELEASER);
315 }
316 void setHasIvarReleaser();
317
318 bool isRootClass() const {
319 return superclass == NULL;
320 }
321 bool isRootMetaclass() const {
322 return isa == this;
323 }
324 } class_t;
325
326 typedef struct category_t {
327 const char *name;
328 struct class_t *cls;
329 struct method_list_t *instanceMethods;
330 struct method_list_t *classMethods;
331 struct protocol_list_t *protocols;
332 struct property_list_t *instanceProperties;
333 } category_t;
334
335 struct objc_super2 {
336 id receiver;
337 Class current_class;
338 };
339
340 typedef struct {
341 IMP imp;
342 SEL sel;
343 } message_ref_t;
344
345
346 __END_DECLS
347
348 #endif