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// GC:  class has unsafe finalize method
56#define CLS_FINALIZE_ON_MAIN_THREAD 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// class has instance-specific GC layout
69#define CLS_HAS_INSTANCE_SPECIFIC_LAYOUT 0x2000000
70
71
72// Terminator for array of method lists
73#define END_OF_METHODS_LIST ((struct old_method_list*)-1)
74
75#define ISCLASS(cls)		(((cls)->info & CLS_CLASS) != 0)
76#define ISMETA(cls)		(((cls)->info & CLS_META) != 0)
77#define GETMETA(cls)		(ISMETA(cls) ? (cls) : (cls)->ISA())
78
79
80struct objc_class : objc_object {
81    Class superclass;
82    const char *name;
83    uint32_t version;
84    uint32_t info;
85    uint32_t instance_size;
86    struct old_ivar_list *ivars;
87    struct old_method_list **methodLists;
88    Cache cache;
89    struct old_protocol_list *protocols;
90    // CLS_EXT only
91    const uint8_t *ivar_layout;
92    struct old_class_ext *ext;
93
94    void setInfo(uint32_t set) {
95        OSAtomicOr32Barrier(set, (volatile uint32_t *)&info);
96    }
97
98    void clearInfo(uint32_t clear) {
99        OSAtomicXor32Barrier(clear, (volatile uint32_t *)&info);
100    }
101
102
103    // set and clear must not overlap
104    void changeInfo(uint32_t set, uint32_t clear) {
105        assert((set & clear) == 0);
106
107        uint32_t oldf, newf;
108        do {
109            oldf = this->info;
110            newf = (oldf | set) & ~clear;
111        } while (!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatile int32_t *)&info));
112    }
113
114    bool hasCxxCtor() {
115        // set_superclass propagates the flag from the superclass.
116        return info & CLS_HAS_CXX_STRUCTORS;
117    }
118
119    bool hasCxxDtor() {
120        return hasCxxCtor();  // one bit for both ctor and dtor
121    }
122
123    bool instancesHaveAssociatedObjects() {
124        return info & CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS;
125    }
126
127    void setInstancesHaveAssociatedObjects() {
128        setInfo(CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS);
129    }
130
131    bool shouldGrowCache() {
132        return info & CLS_GROW_CACHE;
133    }
134
135    void setShouldGrowCache(bool grow) {
136        if (grow) setInfo(CLS_GROW_CACHE);
137        else clearInfo(CLS_GROW_CACHE);
138    }
139
140    bool shouldFinalizeOnMainThread() {
141        return info & CLS_FINALIZE_ON_MAIN_THREAD;
142    }
143
144    void setShouldFinalizeOnMainThread() {
145        setInfo(CLS_FINALIZE_ON_MAIN_THREAD);
146    }
147
148    // +initialize bits are stored on the metaclass only
149    bool isInitializing() {
150        return getMeta()->info & CLS_INITIALIZING;
151    }
152
153    // +initialize bits are stored on the metaclass only
154    void setInitializing() {
155        getMeta()->setInfo(CLS_INITIALIZING);
156    }
157
158    // +initialize bits are stored on the metaclass only
159    bool isInitialized() {
160        return getMeta()->info & CLS_INITIALIZED;
161    }
162
163    // +initialize bits are stored on the metaclass only
164    void setInitialized() {
165        getMeta()->changeInfo(CLS_INITIALIZED, CLS_INITIALIZING);
166    }
167
168    bool isLoadable() {
169        // A class registered for +load is ready for +load to be called
170        // if it is connected.
171        return isConnected();
172    }
173
174    IMP getLoadMethod();
175
176    bool isConnected();
177
178    const char *getName() { return name; }
179
180    bool isMetaClass() {
181        return info & CLS_META;
182    }
183
184    // NOT identical to this->ISA() when this is a metaclass
185    Class getMeta() {
186        if (isMetaClass()) return (Class)this;
187        else return this->ISA();
188    }
189
190    // May be unaligned depending on class's ivars.
191    uint32_t unalignedInstanceSize() {
192        return instance_size;
193    }
194
195    // Class's ivar size rounded up to a pointer-size boundary.
196    uint32_t alignedInstanceSize() {
197        return (unalignedInstanceSize() + WORD_MASK) & ~WORD_MASK;
198    }
199
200};
201
202struct old_class_ext {
203    uint32_t size;
204    const uint8_t *weak_ivar_layout;
205    struct old_property_list **propertyLists;
206};
207
208struct old_category {
209    char *category_name;
210    char *class_name;
211    struct old_method_list *instance_methods;
212    struct old_method_list *class_methods;
213    struct old_protocol_list *protocols;
214    uint32_t size;
215    struct old_property_list *instance_properties;
216};
217
218struct old_ivar {
219    char *ivar_name;
220    char *ivar_type;
221    int ivar_offset;
222#ifdef __LP64__
223    int space;
224#endif
225};
226
227struct old_ivar_list {
228    int ivar_count;
229#ifdef __LP64__
230    int space;
231#endif
232    /* variable length structure */
233    struct old_ivar ivar_list[1];
234};
235
236
237struct old_method {
238    SEL method_name;
239    char *method_types;
240    IMP method_imp;
241};
242
243struct old_method_list {
244    void *obsolete;
245
246    int method_count;
247#ifdef __LP64__
248    int space;
249#endif
250    /* variable length structure */
251    struct old_method method_list[1];
252};
253
254struct old_protocol {
255    Class isa;
256    const char *protocol_name;
257    struct old_protocol_list *protocol_list;
258    struct objc_method_description_list *instance_methods;
259    struct objc_method_description_list *class_methods;
260};
261
262struct old_protocol_list {
263    struct old_protocol_list *next;
264    long count;
265    struct old_protocol *list[1];
266};
267
268struct old_protocol_ext {
269    uint32_t size;
270    struct objc_method_description_list *optional_instance_methods;
271    struct objc_method_description_list *optional_class_methods;
272    struct old_property_list *instance_properties;
273    const char **extendedMethodTypes;
274};
275
276
277struct old_property {
278    const char *name;
279    const char *attributes;
280};
281
282struct old_property_list {
283    uint32_t entsize;
284    uint32_t count;
285    struct old_property first;
286};
287
288
289#include "hashtable2.h"
290
291__BEGIN_DECLS
292
293#define oldprotocol(proto) ((struct old_protocol *)proto)
294#define oldmethod(meth) ((struct old_method *)meth)
295#define oldcategory(cat) ((struct old_category *)cat)
296#define oldivar(ivar) ((struct old_ivar *)ivar)
297#define oldproperty(prop) ((struct old_property *)prop)
298
299extern NXHashTable *class_hash;
300
301extern void unload_class(Class cls);
302
303extern IMP lookupNamedMethodInMethodList(struct old_method_list *mlist, const char *meth_name);
304extern void _objc_insertMethods(Class cls, struct old_method_list *mlist, struct old_category *cat);
305extern void _objc_removeMethods(Class cls, struct old_method_list *mlist);
306extern void _objc_flush_caches (Class cls);
307extern BOOL _class_addProperties(Class cls, struct old_property_list *additions);
308extern BOOL _class_hasLoadMethod(Class cls);
309extern void change_class_references(Class imposter, Class original, Class copy, BOOL changeSuperRefs);
310extern void flush_marked_caches(void);
311extern void set_superclass(Class cls, Class supercls, BOOL cls_is_new);
312extern void try_free(const void *p);
313
314extern struct old_property *property_list_nth(const struct old_property_list *plist, uint32_t i);
315extern struct old_property **copyPropertyList(struct old_property_list *plist, unsigned int *outCount);
316
317extern struct objc_method_description * lookup_protocol_method(struct old_protocol *proto, SEL aSel, BOOL isRequiredMethod, BOOL isInstanceMethod, BOOL recursive);
318
319// used by flush_caches outside objc-cache.m
320extern void _cache_flush(Class cls);
321#ifdef OBJC_INSTRUMENTED
322extern unsigned int LinearFlushCachesCount;
323extern unsigned int LinearFlushCachesVisitedCount;
324extern unsigned int MaxLinearFlushCachesVisitedCount;
325extern unsigned int NonlinearFlushCachesCount;
326extern unsigned int NonlinearFlushCachesClassCount;
327extern unsigned int NonlinearFlushCachesVisitedCount;
328extern unsigned int MaxNonlinearFlushCachesVisitedCount;
329extern unsigned int IdealFlushCachesCount;
330extern unsigned int MaxIdealFlushCachesCount;
331#endif
332
333__END_DECLS
334
335#endif
336