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