2 * Copyright (c) 2005-2007 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #ifndef _OBJC_RUNTIME_NEW_H
25 #define _OBJC_RUNTIME_NEW_H
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
32 #define CLASS_FAST_FLAGS_VIA_RW_DATA 0
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)
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)
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)
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)
100 // classref_t is unremapped class_t*
101 typedef struct classref
* classref_t
;
108 struct SortBySELAddress
:
109 public std::binary_function
<const method_t
&,
110 const method_t
&, bool>
112 bool operator() (const method_t
& lhs
,
114 { return lhs
.name
< rhs
.name
; }
118 typedef struct method_list_t
{
119 uint32_t entsize_NEVER_USE
; // high bits used for fixup markers
123 uint32_t getEntsize() const {
124 return entsize_NEVER_USE
& ~(uint32_t)3;
126 uint32_t getCount() const {
129 method_t
& get(uint32_t i
) const {
130 return *(method_t
*)((uint8_t *)&first
+ i
*getEntsize());
133 // iterate methods, taking entsize into account
134 // fixme need a proper const_iterator
135 struct method_iterator
{
137 uint32_t index
; // keeping track of this saves a divide in operator-
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
;
146 method_iterator() { }
148 method_iterator(const method_list_t
& mlist
, uint32_t start
= 0)
149 : entsize(mlist
.getEntsize())
151 , method(&mlist
.get(start
))
154 const method_iterator
& operator += (ptrdiff_t delta
) {
155 method
= (method_t
*)((uint8_t *)method
+ delta
*entsize
);
156 index
+= (int32_t)delta
;
159 const method_iterator
& operator -= (ptrdiff_t delta
) {
160 method
= (method_t
*)((uint8_t *)method
- delta
*entsize
);
161 index
-= (int32_t)delta
;
164 const method_iterator
operator + (ptrdiff_t delta
) const {
165 return method_iterator(*this) += delta
;
167 const method_iterator
operator - (ptrdiff_t delta
) const {
168 return method_iterator(*this) -= delta
;
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
;
176 method_iterator
operator -- (int) {
177 method_iterator
result(*this); *this -= 1; return result
;
180 ptrdiff_t operator - (const method_iterator
& rhs
) const {
181 return (ptrdiff_t)this->index
- (ptrdiff_t)rhs
.index
;
184 method_t
& operator * () const { return *method
; }
185 method_t
* operator -> () const { return method
; }
187 operator method_t
& () const { return *method
; }
189 bool operator == (const method_iterator
& rhs
) {
190 return this->method
== rhs
.method
;
192 bool operator != (const method_iterator
& rhs
) {
193 return this->method
!= rhs
.method
;
196 bool operator < (const method_iterator
& rhs
) {
197 return this->method
< rhs
.method
;
199 bool operator > (const method_iterator
& rhs
) {
200 return this->method
> rhs
.method
;
204 method_iterator
begin() const { return method_iterator(*this, 0); }
205 method_iterator
end() const { return method_iterator(*this, getCount()); }
209 typedef struct ivar_t
{
210 // *offset is 64-bit by accident even though other
211 // fields restrict total instance size to 32-bit.
215 // alignment is sometimes -1; use ivar_alignment() instead
216 uint32_t alignment
__attribute__((deprecated
));
220 typedef struct ivar_list_t
{
226 typedef struct objc_property
{
228 const char *attributes
;
231 typedef struct property_list_t
{
237 typedef uintptr_t protocol_ref_t
; // protocol_t *, but unremapped
239 typedef struct protocol_t
{
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)
250 const char **extendedMethodTypes
;
252 bool hasExtendedMethodTypesField() const {
253 return size
>= (offsetof(protocol_t
, extendedMethodTypes
)
254 + sizeof(extendedMethodTypes
));
256 bool hasExtendedMethodTypes() const {
257 return hasExtendedMethodTypesField() && extendedMethodTypes
;
261 typedef struct protocol_list_t
{
262 // count is 64-bit by accident.
264 protocol_ref_t list
[0]; // variable-size
267 typedef struct class_ro_t
{
269 uint32_t instanceStart
;
270 uint32_t instanceSize
;
275 const uint8_t * ivarLayout
;
278 const method_list_t
* baseMethods
;
279 const protocol_list_t
* baseProtocols
;
280 const ivar_list_t
* ivars
;
282 const uint8_t * weakIvarLayout
;
283 const property_list_t
*baseProperties
;
286 typedef struct class_rw_t
{
290 const class_ro_t
*ro
;
293 method_list_t
**method_lists
; // RW_METHOD_ARRAY == 1
294 method_list_t
*method_list
; // RW_METHOD_ARRAY == 0
296 struct chained_property_list
*properties
;
297 const protocol_list_t
** protocols
;
299 struct class_t
*firstSubclass
;
300 struct class_t
*nextSiblingClass
;
303 typedef struct class_t
{
305 struct class_t
*superclass
;
308 uintptr_t data_NEVER_USE
; // class_rw_t * plus custom rr/alloc flags
310 class_rw_t
*data() const {
311 return (class_rw_t
*)(data_NEVER_USE
& ~(uintptr_t)3);
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
;
318 bool hasCustomRR() const {
319 #if CLASS_FAST_FLAGS_VIA_RW_DATA
320 return data_NEVER_USE
& (uintptr_t)1;
322 return data()->flags
& RW_HAS_CUSTOM_RR
;
325 void setHasCustomRR(bool inherited
= false);
327 bool hasCustomAWZ() const {
328 #if CLASS_FAST_FLAGS_VIA_RW_DATA
329 return data_NEVER_USE
& (uintptr_t)2;
331 return data()->flags
& RW_HAS_CUSTOM_AWZ
;
334 void setHasCustomAWZ(bool inherited
= false);
336 bool isRootClass() const {
337 return superclass
== NULL
;
339 bool isRootMetaclass() const {
344 typedef struct category_t
{
347 struct method_list_t
*instanceMethods
;
348 struct method_list_t
*classMethods
;
349 struct protocol_list_t
*protocols
;
350 struct property_list_t
*instanceProperties
;