]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-runtime-old.h
b367c099c47de47b61e45d6d6a0a8bf734a9402a
[apple/objc4.git] / runtime / objc-runtime-old.h
1 /*
2 * Copyright (c) 1999-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_OLD_H
25 #define _OBJC_RUNTIME_OLD_H
26
27 #include "objc-private.h"
28
29 #define CLS_CLASS 0x1
30 #define CLS_META 0x2
31 #define CLS_INITIALIZED 0x4
32 #define CLS_POSING 0x8
33 #define CLS_MAPPED 0x10
34 #define CLS_FLUSH_CACHE 0x20
35 #define CLS_GROW_CACHE 0x40
36 #define CLS_NEED_BIND 0x80
37 #define CLS_METHOD_ARRAY 0x100
38 // the JavaBridge constructs classes with these markers
39 #define CLS_JAVA_HYBRID 0x200
40 #define CLS_JAVA_CLASS 0x400
41 // thread-safe +initialize
42 #define CLS_INITIALIZING 0x800
43 // bundle unloading
44 #define CLS_FROM_BUNDLE 0x1000
45 // C++ ivar support
46 #define CLS_HAS_CXX_STRUCTORS 0x2000
47 // Lazy method list arrays
48 #define CLS_NO_METHOD_ARRAY 0x4000
49 // +load implementation
50 #define CLS_HAS_LOAD_METHOD 0x8000
51 // objc_allocateClassPair API
52 #define CLS_CONSTRUCTING 0x10000
53 // visibility=hidden
54 #define CLS_HIDDEN 0x20000
55 // available for use; was CLS_FINALIZE_ON_MAIN_THREAD
56 #define CLS_40000 0x40000
57 // Lazy property list arrays
58 #define CLS_NO_PROPERTY_ARRAY 0x80000
59 // +load implementation
60 #define CLS_CONNECTED 0x100000
61 #define CLS_LOADED 0x200000
62 // objc_allocateClassPair API
63 #define CLS_CONSTRUCTED 0x400000
64 // class is leaf for cache flushing
65 #define CLS_LEAF 0x800000
66 // class instances may have associative references
67 #define CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS 0x1000000
68 // available for use; was CLS_HAS_INSTANCE_SPECIFIC_LAYOUT
69 #define CLS_2000000 0x2000000
70 // class compiled with ARC
71 #define CLS_IS_ARC 0x4000000
72 // class is not ARC but has ARC-style weak ivar layout
73 #define CLS_HAS_WEAK_WITHOUT_ARC 0x8000000
74
75
76 // Terminator for array of method lists
77 #define END_OF_METHODS_LIST ((struct old_method_list*)-1)
78
79 #define ISCLASS(cls) (((cls)->info & CLS_CLASS) != 0)
80 #define ISMETA(cls) (((cls)->info & CLS_META) != 0)
81 #define GETMETA(cls) (ISMETA(cls) ? (cls) : (cls)->ISA())
82
83
84 struct old_class_ext {
85 uint32_t size;
86 const uint8_t *weak_ivar_layout;
87 struct old_property_list **propertyLists;
88 };
89
90 struct old_category {
91 char *category_name;
92 char *class_name;
93 struct old_method_list *instance_methods;
94 struct old_method_list *class_methods;
95 struct old_protocol_list *protocols;
96 // Fields below this point are in version 7 or later only.
97 uint32_t size;
98 struct old_property_list *instance_properties;
99 // Check size for fields below this point.
100 struct old_property_list *class_properties;
101
102 bool hasClassPropertiesField() const {
103 return size >= offsetof(old_category, class_properties) + sizeof(class_properties);
104 }
105 };
106
107 struct old_ivar {
108 char *ivar_name;
109 char *ivar_type;
110 int ivar_offset;
111 #ifdef __LP64__
112 int space;
113 #endif
114 };
115
116 struct old_ivar_list {
117 int ivar_count;
118 #ifdef __LP64__
119 int space;
120 #endif
121 /* variable length structure */
122 struct old_ivar ivar_list[1];
123 };
124
125
126 struct old_method {
127 SEL method_name;
128 char *method_types;
129 IMP method_imp;
130 };
131
132 struct old_method_list {
133 void *obsolete;
134
135 int method_count;
136 #ifdef __LP64__
137 int space;
138 #endif
139 /* variable length structure */
140 struct old_method method_list[1];
141 };
142
143 struct old_protocol {
144 Class isa;
145 const char *protocol_name;
146 struct old_protocol_list *protocol_list;
147 struct objc_method_description_list *instance_methods;
148 struct objc_method_description_list *class_methods;
149 };
150
151 struct old_protocol_list {
152 struct old_protocol_list *next;
153 long count;
154 struct old_protocol *list[1];
155 };
156
157 struct old_protocol_ext {
158 uint32_t size;
159 struct objc_method_description_list *optional_instance_methods;
160 struct objc_method_description_list *optional_class_methods;
161 struct old_property_list *instance_properties;
162 const char **extendedMethodTypes;
163 struct old_property_list *class_properties;
164
165 bool hasClassPropertiesField() const {
166 return size >= offsetof(old_protocol_ext, class_properties) + sizeof(class_properties);
167 }
168 };
169
170
171 struct old_property {
172 const char *name;
173 const char *attributes;
174 };
175
176 struct old_property_list {
177 uint32_t entsize;
178 uint32_t count;
179 struct old_property first;
180 };
181
182
183 struct objc_class : objc_object {
184 Class superclass;
185 const char *name;
186 uint32_t version;
187 uint32_t info;
188 uint32_t instance_size;
189 struct old_ivar_list *ivars;
190 struct old_method_list **methodLists;
191 Cache cache;
192 struct old_protocol_list *protocols;
193 // CLS_EXT only
194 const uint8_t *ivar_layout;
195 struct old_class_ext *ext;
196
197 void setInfo(uint32_t set) {
198 OSAtomicOr32Barrier(set, (volatile uint32_t *)&info);
199 }
200
201 void clearInfo(uint32_t clear) {
202 OSAtomicXor32Barrier(clear, (volatile uint32_t *)&info);
203 }
204
205
206 // set and clear must not overlap
207 void changeInfo(uint32_t set, uint32_t clear) {
208 assert((set & clear) == 0);
209
210 uint32_t oldf, newf;
211 do {
212 oldf = this->info;
213 newf = (oldf | set) & ~clear;
214 } while (!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatile int32_t *)&info));
215 }
216
217 bool hasCxxCtor() {
218 // set_superclass propagates the flag from the superclass.
219 return info & CLS_HAS_CXX_STRUCTORS;
220 }
221
222 bool hasCxxDtor() {
223 return hasCxxCtor(); // one bit for both ctor and dtor
224 }
225
226 // Return YES if the class's ivars are managed by ARC,
227 // or the class is MRC but has ARC-style weak ivars.
228 bool hasAutomaticIvars() {
229 return info & (CLS_IS_ARC | CLS_HAS_WEAK_WITHOUT_ARC);
230 }
231
232 // Return YES if the class's ivars are managed by ARC.
233 bool isARC() {
234 return info & CLS_IS_ARC;
235 }
236
237 bool hasCustomRR() {
238 return true;
239 }
240 void setHasCustomRR(bool = false) { }
241 void setHasDefaultRR() { }
242 void printCustomRR(bool) { }
243
244 bool hasCustomAWZ() {
245 return true;
246 }
247 void setHasCustomAWZ(bool = false) { }
248 void setHasDefaultAWZ() { }
249 void printCustomAWZ(bool) { }
250
251 bool forbidsAssociatedObjects() {
252 // Old runtime doesn't support forbidding associated objects.
253 return false;
254 }
255
256 bool instancesHaveAssociatedObjects() {
257 return info & CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS;
258 }
259
260 void setInstancesHaveAssociatedObjects() {
261 setInfo(CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS);
262 }
263
264 bool shouldGrowCache() {
265 return info & CLS_GROW_CACHE;
266 }
267
268 void setShouldGrowCache(bool grow) {
269 if (grow) setInfo(CLS_GROW_CACHE);
270 else clearInfo(CLS_GROW_CACHE);
271 }
272
273 // +initialize bits are stored on the metaclass only
274 bool isInitializing() {
275 return getMeta()->info & CLS_INITIALIZING;
276 }
277
278 // +initialize bits are stored on the metaclass only
279 void setInitializing() {
280 getMeta()->setInfo(CLS_INITIALIZING);
281 }
282
283 // +initialize bits are stored on the metaclass only
284 bool isInitialized() {
285 return getMeta()->info & CLS_INITIALIZED;
286 }
287
288 // +initialize bits are stored on the metaclass only
289 void setInitialized() {
290 getMeta()->changeInfo(CLS_INITIALIZED, CLS_INITIALIZING);
291 }
292
293 bool isLoadable() {
294 // A class registered for +load is ready for +load to be called
295 // if it is connected.
296 return isConnected();
297 }
298
299 IMP getLoadMethod();
300
301 bool isFuture();
302
303 bool isConnected();
304
305 const char *mangledName() { return name; }
306 const char *demangledName() { return name; }
307 const char *nameForLogging() { return name; }
308
309 bool isRootClass() {
310 return superclass == nil;
311 }
312
313 bool isRootMetaclass() {
314 return ISA() == (Class)this;
315 }
316
317 bool isMetaClass() {
318 return info & CLS_META;
319 }
320
321 // NOT identical to this->ISA() when this is a metaclass
322 Class getMeta() {
323 if (isMetaClass()) return (Class)this;
324 else return this->ISA();
325 }
326
327 // May be unaligned depending on class's ivars.
328 uint32_t unalignedInstanceStart() {
329 // This is not simply superclass->instance_size.
330 // superclass->instance_size is padded to its sizeof() boundary,
331 // which may envelop one of this class's ivars.
332 // That in turn would break ARC-style ivar layouts.
333 // Instead, we use the address of this class's first ivar when possible.
334 if (!superclass) return 0;
335 if (!ivars || ivars->ivar_count == 0) return superclass->instance_size;
336 return ivars->ivar_list[0].ivar_offset;
337 }
338
339 // Class's instance start rounded up to a pointer-size boundary.
340 // This is used for ARC layout bitmaps.
341 uint32_t alignedInstanceStart() {
342 return word_align(unalignedInstanceStart());
343 }
344
345
346 // May be unaligned depending on class's ivars.
347 uint32_t unalignedInstanceSize() {
348 return instance_size;
349 }
350
351 // Class's ivar size rounded up to a pointer-size boundary.
352 uint32_t alignedInstanceSize() {
353 return word_align(unalignedInstanceSize());
354 }
355
356 size_t instanceSize(size_t extraBytes) {
357 size_t size = alignedInstanceSize() + extraBytes;
358 // CF requires all objects be at least 16 bytes.
359 if (size < 16) size = 16;
360 return size;
361 }
362
363 };
364
365
366 #include "hashtable2.h"
367
368 __BEGIN_DECLS
369
370 #define oldprotocol(proto) ((struct old_protocol *)proto)
371 #define oldmethod(meth) ((struct old_method *)meth)
372 #define oldcategory(cat) ((struct old_category *)cat)
373 #define oldivar(ivar) ((struct old_ivar *)ivar)
374 #define oldproperty(prop) ((struct old_property *)prop)
375
376 extern NXHashTable *class_hash;
377
378 extern void unload_class(Class cls);
379
380 extern IMP lookupNamedMethodInMethodList(struct old_method_list *mlist, const char *meth_name);
381 extern void _objc_insertMethods(Class cls, struct old_method_list *mlist, struct old_category *cat);
382 extern void _objc_removeMethods(Class cls, struct old_method_list *mlist);
383 extern void _objc_flush_caches (Class cls);
384 extern bool _class_addProperties(Class cls, struct old_property_list *additions);
385 extern bool _class_hasLoadMethod(Class cls);
386 extern void change_class_references(Class imposter, Class original, Class copy, bool changeSuperRefs);
387 extern void flush_marked_caches(void);
388 extern void set_superclass(Class cls, Class supercls, bool cls_is_new);
389 extern void try_free(const void *p);
390
391 extern struct old_property *property_list_nth(const struct old_property_list *plist, uint32_t i);
392 extern struct old_property **copyPropertyList(struct old_property_list *plist, unsigned int *outCount);
393
394 extern struct objc_method_description * lookup_protocol_method(struct old_protocol *proto, SEL aSel, bool isRequiredMethod, bool isInstanceMethod, bool recursive);
395
396 // used by flush_caches outside objc-cache.m
397 extern void _cache_flush(Class cls);
398 #ifdef OBJC_INSTRUMENTED
399 extern unsigned int LinearFlushCachesCount;
400 extern unsigned int LinearFlushCachesVisitedCount;
401 extern unsigned int MaxLinearFlushCachesVisitedCount;
402 extern unsigned int NonlinearFlushCachesCount;
403 extern unsigned int NonlinearFlushCachesClassCount;
404 extern unsigned int NonlinearFlushCachesVisitedCount;
405 extern unsigned int MaxNonlinearFlushCachesVisitedCount;
406 extern unsigned int IdealFlushCachesCount;
407 extern unsigned int MaxIdealFlushCachesCount;
408 #endif
409
410 __END_DECLS
411
412 #endif