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 // 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)
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)
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)
94 struct SortBySELAddress
:
95 public std::binary_function
<const method_t
&,
96 const method_t
&, bool>
98 bool operator() (const method_t
& lhs
,
100 { return lhs
.name
< rhs
.name
; }
104 typedef struct method_list_t
{
105 uint32_t entsize_NEVER_USE
; // high bits used for fixup markers
109 uint32_t getEntsize() const {
110 return entsize_NEVER_USE
& ~(uint32_t)3;
112 uint32_t getCount() const {
115 method_t
& get(uint32_t i
) const {
116 return *(method_t
*)((uint8_t *)&first
+ i
*getEntsize());
119 // iterate methods, taking entsize into account
120 // fixme need a proper const_iterator
121 struct method_iterator
{
123 uint32_t index
; // keeping track of this saves a divide in operator-
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
;
132 method_iterator() { }
134 method_iterator(const method_list_t
& mlist
, uint32_t start
= 0)
135 : entsize(mlist
.getEntsize())
137 , method(&mlist
.get(start
))
140 const method_iterator
& operator += (ptrdiff_t count
) {
141 method
= (method_t
*)((uint8_t *)method
+ count
*entsize
);
142 index
+= (int32_t)count
;
145 const method_iterator
& operator -= (ptrdiff_t count
) {
146 method
= (method_t
*)((uint8_t *)method
- count
*entsize
);
147 index
-= (int32_t)count
;
150 const method_iterator
operator + (ptrdiff_t count
) const {
151 return method_iterator(*this) += count
;
153 const method_iterator
operator - (ptrdiff_t count
) const {
154 return method_iterator(*this) -= count
;
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
;
162 method_iterator
operator -- (int) {
163 method_iterator
result(*this); *this -= 1; return result
;
166 ptrdiff_t operator - (const method_iterator
& rhs
) const {
167 return (ptrdiff_t)this->index
- (ptrdiff_t)rhs
.index
;
170 method_t
& operator * () const { return *method
; }
171 method_t
* operator -> () const { return method
; }
173 operator method_t
& () const { return *method
; }
175 bool operator == (const method_iterator
& rhs
) {
176 return this->method
== rhs
.method
;
178 bool operator != (const method_iterator
& rhs
) {
179 return this->method
!= rhs
.method
;
182 bool operator < (const method_iterator
& rhs
) {
183 return this->method
< rhs
.method
;
185 bool operator > (const method_iterator
& rhs
) {
186 return this->method
> rhs
.method
;
190 method_iterator
begin() const { return method_iterator(*this, 0); }
191 method_iterator
end() const { return method_iterator(*this, getCount()); }
195 typedef struct ivar_t
{
196 // *offset is 64-bit by accident even though other
197 // fields restrict total instance size to 32-bit.
201 // alignment is sometimes -1; use ivar_alignment() instead
202 uint32_t alignment
__attribute__((deprecated
));
206 typedef struct ivar_list_t
{
212 typedef struct objc_property
{
214 const char *attributes
;
217 typedef struct property_list_t
{
223 typedef uintptr_t protocol_ref_t
; // protocol_t *, but unremapped
225 typedef struct protocol_t
{
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
;
236 typedef struct protocol_list_t
{
237 // count is 64-bit by accident.
239 protocol_ref_t list
[0]; // variable-size
242 typedef struct class_ro_t
{
244 uint32_t instanceStart
;
245 uint32_t instanceSize
;
250 const uint8_t * ivarLayout
;
253 const method_list_t
* baseMethods
;
254 const protocol_list_t
* baseProtocols
;
255 const ivar_list_t
* ivars
;
257 const uint8_t * weakIvarLayout
;
258 const property_list_t
*baseProperties
;
261 typedef struct class_rw_t
{
265 const class_ro_t
*ro
;
267 method_list_t
**methods
;
268 struct chained_property_list
*properties
;
269 const protocol_list_t
** protocols
;
271 struct class_t
*firstSubclass
;
272 struct class_t
*nextSiblingClass
;
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
278 #define CLASS_FAST_FLAGS_VIA_RW_DATA 0
280 typedef struct class_t
{
282 struct class_t
*superclass
;
285 uintptr_t data_NEVER_USE
; // class_rw_t * plus flags
287 class_rw_t
*data() const {
288 #if CLASS_FAST_FLAGS_VIA_RW_DATA
289 return (class_rw_t
*)(data_NEVER_USE
& ~3UL);
291 return (class_rw_t
*)data_NEVER_USE
;
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
;
299 data_NEVER_USE
= (uintptr_t)newData
;
303 bool hasCustomRR() const {
304 #if CLASS_FAST_FLAGS_VIA_RW_DATA
305 return data_NEVER_USE
& 1UL;
307 return (data()->flags
& RW_HAS_CUSTOM_RR
);
310 void setHasCustomRR();
311 void unsetHasCustomRR();
313 bool hasIvarReleaser() const {
314 return (data()->flags
& RW_HAS_IVAR_RELEASER
);
316 void setHasIvarReleaser();
318 bool isRootClass() const {
319 return superclass
== NULL
;
321 bool isRootMetaclass() const {
326 typedef struct category_t
{
329 struct method_list_t
*instanceMethods
;
330 struct method_list_t
*classMethods
;
331 struct protocol_list_t
*protocols
;
332 struct property_list_t
*instanceProperties
;