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