2 * Copyright (c) 1999-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@
23 /***********************************************************************
25 * Copyright 1988-1997, Apple Computer, Inc.
27 **********************************************************************/
30 /***********************************************************************
31 * Lazy method list arrays and method list locking (2004-10-19)
33 * cls->methodLists may be in one of three forms:
34 * 1. NULL: The class has no methods.
35 * 2. non-NULL, with CLS_NO_METHOD_ARRAY set: cls->methodLists points
36 * to a single method list, which is the class's only method list.
37 * 3. non-NULL, with CLS_NO_METHOD_ARRAY clear: cls->methodLists points to
38 * an array of method list pointers. The end of the array's block
39 * is set to -1. If the actual number of method lists is smaller
40 * than that, the rest of the array is NULL.
42 * Attaching categories and adding and removing classes may change
43 * the form of the class list. In addition, individual method lists
44 * may be reallocated when fixed up.
46 * Classes are initially read as #1 or #2. If a category is attached
47 * or other methods added, the class is changed to #3. Once in form #3,
48 * the class is never downgraded to #1 or #2, even if methods are removed.
49 * Classes added with objc_addClass are initially either #1 or #3.
51 * Accessing and manipulating a class's method lists are synchronized,
52 * to prevent races when one thread restructures the list. However,
53 * if the class is not yet in use (i.e. not in class_hash), then the
54 * thread loading the class may access its method lists without locking.
56 * The following functions acquire methodListLock:
57 * class_getInstanceMethod
58 * class_getClassMethod
59 * class_nextMethodList
62 * class_respondsToMethod
63 * _class_lookupMethodAndLoadCache
64 * lookupMethodInClassAndLoadCache
65 * _objc_add_category_flush_caches
67 * The following functions don't acquire methodListLock because they
68 * only access method lists during class load and unload:
69 * _objc_register_category
70 * _resolve_categories_for_class (calls _objc_add_category)
71 * add_class_to_loadable_list
73 * _objc_remove_classes_in_image
75 * The following functions use method lists without holding methodListLock.
76 * The caller must either hold methodListLock, or be loading the class.
77 * _getMethod (called by class_getInstanceMethod, class_getClassMethod,
78 * and class_respondsToMethod)
79 * _findMethodInClass (called by _class_lookupMethodAndLoadCache,
80 * lookupMethodInClassAndLoadCache, _getMethod)
81 * _findMethodInList (called by _findMethodInClass)
82 * nextMethodList (called by _findMethodInClass and class_nextMethodList
83 * fixupSelectorsInMethodList (called by nextMethodList)
84 * _objc_add_category (called by _objc_add_category_flush_caches,
85 * resolve_categories_for_class and _objc_register_category)
86 * _objc_insertMethods (called by class_addMethods and _objc_add_category)
87 * _objc_removeMethods (called by class_removeMethods)
88 * _objcTweakMethodListPointerForClass (called by _objc_insertMethods)
89 * get_base_method_list (called by add_class_to_loadable_list)
90 * lookupNamedMethodInMethodList (called by add_class_to_loadable_list)
91 ***********************************************************************/
93 /***********************************************************************
94 * Thread-safety of class info bits (2004-10-19)
96 * Some class info bits are used to store mutable runtime state.
97 * Modifications of the info bits at particular times need to be
98 * synchronized to prevent races.
100 * Three thread-safe modification functions are provided:
101 * _class_setInfo() // atomically sets some bits
102 * _class_clearInfo() // atomically clears some bits
103 * _class_changeInfo() // atomically sets some bits and clears others
104 * These replace CLS_SETINFO() for the multithreaded cases.
106 * Three modification windows are defined:
108 * - class construction or image load (before +load) in one thread
109 * - multi-threaded messaging and method caches
111 * Info bit modification at compile time and class construction do not
112 * need to be locked, because only one thread is manipulating the class.
113 * Info bit modification during messaging needs to be locked, because
114 * there may be other threads simultaneously messaging or otherwise
115 * manipulating the class.
117 * Modification windows for each flag:
119 * CLS_CLASS: compile-time and class load
120 * CLS_META: compile-time and class load
121 * CLS_INITIALIZED: +initialize
122 * CLS_POSING: messaging
123 * CLS_MAPPED: compile-time
124 * CLS_FLUSH_CACHE: class load and messaging
125 * CLS_GROW_CACHE: messaging
126 * CLS_NEED_BIND: unused
127 * CLS_METHOD_ARRAY: unused
128 * CLS_JAVA_HYBRID: JavaBridge only
129 * CLS_JAVA_CLASS: JavaBridge only
130 * CLS_INITIALIZING: messaging
131 * CLS_FROM_BUNDLE: class load
132 * CLS_HAS_CXX_STRUCTORS: compile-time and class load
133 * CLS_NO_METHOD_ARRAY: class load and messaging
134 * CLS_HAS_LOAD_METHOD: class load
136 * CLS_INITIALIZED and CLS_INITIALIZING have additional thread-safety
137 * constraints to support thread-safe +initialize. See "Thread safety
138 * during class initialization" for details.
140 * CLS_JAVA_HYBRID and CLS_JAVA_CLASS are set immediately after JavaBridge
141 * calls objc_addClass(). The JavaBridge does not use an atomic update,
142 * but the modification counts as "class construction" unless some other
143 * thread quickly finds the class via the class list. This race is
144 * small and unlikely in well-behaved code.
146 * Most info bits that may be modified during messaging are also never
147 * read without a lock. There is no general read lock for the info bits.
148 * CLS_INITIALIZED: classInitLock
149 * CLS_FLUSH_CACHE: cacheUpdateLock
150 * CLS_GROW_CACHE: cacheUpdateLock
151 * CLS_NO_METHOD_ARRAY: methodListLock
152 * CLS_INITIALIZING: classInitLock
153 ***********************************************************************/
155 /***********************************************************************
157 **********************************************************************/
159 #include <mach/mach.h>
160 #include <mach/thread_status.h>
161 #include <mach-o/ldsyms.h>
162 #include <mach-o/dyld.h>
163 #include <sys/types.h>
167 #include <sys/fcntl.h>
168 #include <sys/mman.h>
172 #import "objc-private.h"
173 #import "hashtable2.h"
175 #import "objc-initialize.h"
176 #import "objc-auto.h"
179 /* overriding the default object allocation and error handling routines */
181 OBJC_EXPORT id (*_alloc)(Class, size_t);
182 OBJC_EXPORT id (*_copy)(id, size_t);
183 OBJC_EXPORT id (*_realloc)(id, size_t);
184 OBJC_EXPORT id (*_dealloc)(id);
185 OBJC_EXPORT id (*_zoneAlloc)(Class, size_t, void *);
186 OBJC_EXPORT id (*_zoneRealloc)(id, size_t, void *);
187 OBJC_EXPORT id (*_zoneCopy)(id, size_t, void *);
190 /***********************************************************************
191 * Function prototypes internal to this module.
192 **********************************************************************/
194 static void _freedHandler (id self, SEL sel);
195 static void _nonexistentHandler (id self, SEL sel);
196 static int LogObjCMessageSend (BOOL isClassMethod, const char * objectsClass, const char * implementingClass, SEL selector);
197 static IMP lookupMethodInClassAndLoadCache(Class cls, SEL sel);
198 static Method look_up_method(Class cls, SEL sel, BOOL withCache, BOOL withResolver);
201 /***********************************************************************
202 * Static data internal to this module.
203 **********************************************************************/
205 // Method call logging
206 typedef int (*ObjCLogProc)(BOOL, const char *, const char *, SEL);
208 static int objcMsgLogFD = (-1);
209 static ObjCLogProc objcMsgLogProc = &LogObjCMessageSend;
210 static int objcMsgLogEnabled = 0;
212 /***********************************************************************
213 * Information about multi-thread support:
215 * Since we do not lock many operations which walk the superclass, method
216 * and ivar chains, these chains must remain intact once a class is published
217 * by inserting it into the class hashtable. All modifications must be
218 * atomic so that someone walking these chains will always geta valid
220 ***********************************************************************/
224 /***********************************************************************
226 **********************************************************************/
227 Class object_getClass(id obj)
229 if (obj) return obj->isa;
234 /***********************************************************************
236 **********************************************************************/
237 Class object_setClass(id obj, Class cls)
239 // fixme could check obj's block size vs. cls's instance size
241 Class old = obj->isa;
249 /***********************************************************************
250 * object_getClassName.
251 **********************************************************************/
252 const char *object_getClassName(id obj)
254 if (obj) return _class_getName(obj->isa);
258 /***********************************************************************
259 * object_getIndexedIvars.
260 **********************************************************************/
261 void *object_getIndexedIvars(id obj)
263 // ivars are tacked onto the end of the object
264 if (obj) return ((char *) obj) + _class_getInstanceSize(obj->isa);
269 Ivar object_setInstanceVariable(id obj, const char *name, void *value)
274 if ((ivar = class_getInstanceVariable(obj->isa, name))) {
275 objc_assign_ivar_internal(
278 ivar_getOffset(ivar));
284 Ivar object_getInstanceVariable(id obj, const char *name, void **value)
289 if ((ivar = class_getInstanceVariable(obj->isa, name))) {
290 ivaridx = (void **)((char *)obj + ivar_getOffset(ivar));
291 if (value) *value = *ivaridx;
295 if (value) *value = NULL;
300 void object_setIvar(id obj, Ivar ivar, id value)
303 objc_assign_ivar_internal(value, obj, ivar_getOffset(ivar));
308 id object_getIvar(id obj, Ivar ivar)
311 id *idx = (id *)((char *)obj + ivar_getOffset(ivar));
318 /***********************************************************************
319 * object_cxxDestructFromClass.
320 * Call C++ destructors on obj, starting with cls's
321 * dtor method (if any) followed by superclasses' dtors (if any),
322 * stopping at cls's dtor (if any).
323 * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
324 **********************************************************************/
325 static void object_cxxDestructFromClass(id obj, Class cls)
329 // Call cls's dtor first, then superclasses's dtors.
331 for ( ; cls != NULL; cls = _class_getSuperclass(cls)) {
332 if (!_class_hasCxxStructorsNoSuper(cls)) continue;
334 lookupMethodInClassAndLoadCache(cls, cxx_destruct_sel);
335 if (dtor != (void(*)(id))&_objc_msgForward) {
337 _objc_inform("CXX: calling C++ destructors for class %s",
338 _class_getName(cls));
346 /***********************************************************************
347 * object_cxxDestruct.
348 * Call C++ destructors on obj, if any.
349 * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
350 **********************************************************************/
351 __private_extern__ void object_cxxDestruct(id obj)
354 object_cxxDestructFromClass(obj, obj->isa);
358 /***********************************************************************
359 * object_cxxConstructFromClass.
360 * Recursively call C++ constructors on obj, starting with base class's
361 * ctor method (if any) followed by subclasses' ctors (if any), stopping
362 * at cls's ctor (if any).
363 * Returns YES if construction succeeded.
364 * Returns NO if some constructor threw an exception. The exception is
365 * caught and discarded. Any partial construction is destructed.
366 * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
368 * .cxx_construct returns id. This really means:
369 * return self: construction succeeded
370 * return nil: construction failed because a C++ constructor threw an exception
371 **********************************************************************/
372 static BOOL object_cxxConstructFromClass(id obj, Class cls)
375 Class supercls = _class_getSuperclass(cls);
377 // Call superclasses' ctors first, if any.
379 BOOL ok = object_cxxConstructFromClass(obj, supercls);
380 if (!ok) return NO; // some superclass's ctor failed - give up
383 // Find this class's ctor, if any.
384 if (!_class_hasCxxStructorsNoSuper(cls)) return YES; // no ctor - ok
385 ctor = (id(*)(id))lookupMethodInClassAndLoadCache(cls, cxx_construct_sel);
386 if (ctor == (id(*)(id))&_objc_msgForward) return YES; // no ctor - ok
388 // Call this class's ctor.
390 _objc_inform("CXX: calling C++ constructors for class %s", _class_getName(cls));
392 if ((*ctor)(obj)) return YES; // ctor called and succeeded - ok
394 // This class's ctor was called and failed.
395 // Call superclasses's dtors to clean up.
396 if (supercls) object_cxxDestructFromClass(obj, supercls);
401 /***********************************************************************
402 * object_cxxConstructFromClass.
403 * Call C++ constructors on obj, if any.
404 * Returns YES if construction succeeded.
405 * Returns NO if some constructor threw an exception. The exception is
406 * caught and discarded. Any partial construction is destructed.
407 * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
408 **********************************************************************/
409 __private_extern__ BOOL object_cxxConstruct(id obj)
411 if (!obj) return YES;
412 return object_cxxConstructFromClass(obj, obj->isa);
416 @interface objc_resolver
417 +(BOOL)resolveClassMethod:(SEL)sel;
418 +(BOOL)resolveInstanceMethod:(SEL)sel;
421 /***********************************************************************
422 * _class_resolveClassMethod
423 * Call +resolveClassMethod and return the method added or NULL.
424 * cls should be a metaclass.
425 * Assumes the method doesn't exist already.
426 **********************************************************************/
427 static Method _class_resolveClassMethod(Class cls, SEL sel)
433 if (!look_up_method(cls, @selector(resolveClassMethod:),
434 YES /*cache*/, NO /*resolver*/))
439 // GrP fixme same hack as +initialize
440 if (strncmp(_class_getName(cls), "_%", 2) == 0) {
441 // Posee's meta's name is smashed and isn't in the class_hash,
442 // so objc_getClass doesn't work.
443 char *baseName = strchr(_class_getName(cls), '%'); // get posee's real name
444 clsInstance = objc_getClass(baseName);
446 clsInstance = objc_getClass(_class_getName(cls));
449 resolved = [clsInstance resolveClassMethod:sel];
452 // +resolveClassMethod adds to self->isa
453 meth = look_up_method(cls, sel, YES/*cache*/, NO/*resolver*/);
456 // Method resolver didn't add anything?
457 _objc_inform("+[%s resolveClassMethod:%s] returned YES, but "
458 "no new implementation of +[%s %s] was found",
471 /***********************************************************************
472 * _class_resolveInstanceMethod
473 * Call +resolveInstanceMethod and return the method added or NULL.
474 * cls should be a non-meta class.
475 * Assumes the method doesn't exist already.
476 **********************************************************************/
477 static Method _class_resolveInstanceMethod(Class cls, SEL sel)
482 if (!look_up_method(((id)cls)->isa, @selector(resolveInstanceMethod:),
483 YES /*cache*/, NO /*resolver*/))
488 resolved = [cls resolveInstanceMethod:sel];
491 // +resolveClassMethod adds to self
492 meth = look_up_method(cls, sel, YES/*cache*/, NO/*resolver*/);
495 // Method resolver didn't add anything?
496 _objc_inform("+[%s resolveInstanceMethod:%s] returned YES, but "
497 "no new implementation of %c[%s %s] was found",
500 class_isMetaClass(cls) ? '+' : '-',
511 /***********************************************************************
512 * _class_resolveMethod
513 * Call +resolveClassMethod or +resolveInstanceMethod and return
514 * the method added or NULL.
515 * Assumes the method doesn't exist already.
516 **********************************************************************/
517 static Method _class_resolveMethod(Class cls, SEL sel)
521 if (_class_isMetaClass(cls)) {
522 meth = _class_resolveClassMethod(cls, sel);
525 meth = _class_resolveInstanceMethod(cls, sel);
528 if (PrintResolving && meth) {
529 _objc_inform("RESOLVE: method %c[%s %s] dynamically resolved to %p",
530 class_isMetaClass(cls) ? '+' : '-',
531 class_getName(cls), sel_getName(sel),
532 method_getImplementation(meth));
539 /***********************************************************************
541 * Look up a method in the given class and its superclasses.
542 * If withCache==YES, look in the class's method cache too.
543 * If withResolver==YES, call +resolveClass/InstanceMethod too.
544 * Returns NULL if the method is not found.
545 * +forward:: entries are not returned.
546 **********************************************************************/
547 static Method look_up_method(Class cls, SEL sel,
548 BOOL withCache, BOOL withResolver)
553 meth = _cache_getMethod(cls, sel, &_objc_msgForward);
554 if (!meth && (IMP)_objc_msgForward == _cache_getImp(cls, sel)) {
555 // Cache contains forward:: . Stop searching.
560 if (!meth) meth = _class_getMethod(cls, sel);
562 if (!meth && withResolver) meth = _class_resolveMethod(cls, sel);
568 /***********************************************************************
569 * class_getInstanceMethod. Return the instance method for the
570 * specified class and selector.
571 **********************************************************************/
572 Method class_getInstanceMethod(Class cls, SEL sel)
574 if (!cls || !sel) return NULL;
576 /* Cache is not used because historically it wasn't. */
577 return look_up_method(cls, sel, NO/*cache*/, YES/*resolver*/);
580 /***********************************************************************
581 * class_getClassMethod. Return the class method for the specified
582 * class and selector.
583 **********************************************************************/
584 Method class_getClassMethod(Class cls, SEL sel)
586 if (!cls || !sel) return NULL;
588 return class_getInstanceMethod(_class_getMeta(cls), sel);
592 /***********************************************************************
593 * class_getInstanceVariable. Return the named instance variable.
594 **********************************************************************/
595 Ivar class_getInstanceVariable(Class cls, const char *name)
597 if (!cls || !name) return NULL;
599 return _class_getVariable(cls, name);
603 /***********************************************************************
604 * class_getClassVariable. Return the named class variable.
605 **********************************************************************/
606 Ivar class_getClassVariable(Class cls, const char *name)
608 if (!cls) return NULL;
610 return class_getInstanceVariable(((id)cls)->isa, name);
614 __private_extern__ Property
615 property_list_nth(const struct objc_property_list *plist, uint32_t i)
617 return (Property)(i*plist->entsize + (char *)&plist->first);
620 __private_extern__ size_t
621 property_list_size(const struct objc_property_list *plist)
623 return sizeof(struct objc_property_list) + (plist->count-1)*plist->entsize;
626 __private_extern__ Property *
627 copyPropertyList(struct objc_property_list *plist, unsigned int *outCount)
629 Property *result = NULL;
630 unsigned int count = 0;
633 count = plist->count;
638 result = malloc((count+1) * sizeof(Property));
640 for (i = 0; i < count; i++) {
641 result[i] = property_list_nth(plist, i);
646 if (outCount) *outCount = count;
650 const char *property_getName(Property prop)
656 const char *property_getAttributes(Property prop)
658 return prop->attributes;
662 /***********************************************************************
663 * _objc_flush_caches. Flush the caches of the specified class and any
664 * of its subclasses. If cls is a meta-class, only meta-class (i.e.
665 * class method) caches are flushed. If cls is an instance-class, both
666 * instance-class and meta-class caches are flushed.
667 **********************************************************************/
668 void _objc_flush_caches(Class cls)
670 flush_caches (cls, YES);
674 /***********************************************************************
676 **********************************************************************/
677 static void _freedHandler(id obj, SEL sel)
679 __objc_error (obj, "message %s sent to freed object=%p",
680 sel_getName(sel), obj);
683 /***********************************************************************
684 * _nonexistentHandler.
685 **********************************************************************/
686 static void _nonexistentHandler(id obj, SEL sel)
688 __objc_error (obj, "message %s sent to non-existent object=%p",
689 sel_getName(sel), obj);
693 /***********************************************************************
694 * class_respondsToSelector.
695 **********************************************************************/
696 BOOL class_respondsToMethod(Class cls, SEL sel)
698 OBJC_WARN_DEPRECATED;
700 return class_respondsToSelector(cls, sel);
704 BOOL class_respondsToSelector(Class cls, SEL sel)
708 if (!sel || !cls) return NO;
710 meth = look_up_method(cls, sel, YES/*cache*/, YES/*resolver*/);
712 _cache_fill(cls, meth, sel);
715 // Cache negative result
716 _cache_addForwardEntry(cls, sel);
722 /***********************************************************************
723 * class_getMethodImplementation.
724 * Returns the IMP that would be invoked if [obj sel] were sent,
725 * where obj is an instance of class cls.
726 **********************************************************************/
727 IMP class_lookupMethod(Class cls, SEL sel)
729 OBJC_WARN_DEPRECATED;
731 // No one responds to zero!
733 __objc_error(cls, "invalid selector (null)");
736 return class_getMethodImplementation(cls, sel);
739 IMP class_getMethodImplementation(Class cls, SEL sel)
743 if (!cls || !sel) return NULL;
745 // fixme _objc_msgForward does not conform to ABI and cannot be
748 imp = _cache_getImp(cls, sel);
751 imp = _class_lookupMethodAndLoadCache (cls, sel);
757 IMP class_getMethodImplementation_stret(Class cls, SEL sel)
759 IMP imp = class_getMethodImplementation(cls, sel);
760 // fixme check for forwarding and use stret forwarder instead
765 // Ignored selectors get method->imp = &_objc_ignored_method
766 __private_extern__ id _objc_ignored_method(id self, SEL _cmd) { return self; }
769 /***********************************************************************
770 * instrumentObjcMessageSends/logObjcMessageSends.
771 **********************************************************************/
772 static int LogObjCMessageSend (BOOL isClassMethod,
773 const char * objectsClass,
774 const char * implementingClass,
779 // Create/open the log file
780 if (objcMsgLogFD == (-1))
782 snprintf (buf, sizeof(buf), "/tmp/msgSends-%d", (int) getpid ());
783 objcMsgLogFD = secure_open (buf, O_WRONLY | O_CREAT, geteuid());
784 if (objcMsgLogFD < 0) {
785 // no log file - disable logging
786 objcMsgLogEnabled = 0;
792 // Make the log entry
793 snprintf(buf, sizeof(buf), "%c %s %s %s\n",
794 isClassMethod ? '+' : '-',
799 write (objcMsgLogFD, buf, strlen(buf));
801 // Tell caller to not cache the method
805 void instrumentObjcMessageSends (BOOL flag)
807 int enabledValue = (flag) ? 1 : 0;
810 if (objcMsgLogEnabled == enabledValue)
813 // If enabling, flush all method caches so we get some traces
815 flush_caches (Nil, YES);
818 if (objcMsgLogFD != (-1))
819 fsync (objcMsgLogFD);
821 objcMsgLogEnabled = enabledValue;
824 __private_extern__ void logObjcMessageSends (ObjCLogProc logProc)
828 objcMsgLogProc = logProc;
829 objcMsgLogEnabled = 1;
833 objcMsgLogProc = logProc;
834 objcMsgLogEnabled = 0;
837 if (objcMsgLogFD != (-1))
838 fsync (objcMsgLogFD);
842 /***********************************************************************
844 * Log this method call. If the logger permits it, fill the method cache.
845 * cls is the method whose cache should be filled.
846 * implementer is the class that owns the implementation in question.
847 **********************************************************************/
849 log_and_fill_cache(Class cls, Class implementer, Method meth, SEL sel)
853 if (objcMsgLogEnabled) {
854 cacheIt = objcMsgLogProc (_class_isMetaClass(implementer) ? YES : NO,
856 _class_getName(implementer),
860 _cache_fill (cls, meth, sel);
865 /***********************************************************************
866 * _class_lookupMethodAndLoadCache.
868 * Called only from objc_msgSend, objc_msgSendSuper and class_lookupMethod.
869 **********************************************************************/
870 __private_extern__ IMP _class_lookupMethodAndLoadCache(Class cls, SEL sel)
875 // Check for freed class
876 if (cls == _class_getFreedObjectClass())
877 return (IMP) _freedHandler;
879 // Check for nonexistent class
880 if (cls == _class_getNonexistentObjectClass())
881 return (IMP) _nonexistentHandler;
888 if (!_class_isInitialized(cls)) {
889 _class_initialize (cls);
890 // If sel == initialize, _class_initialize will send +initialize and
891 // then the messenger will send +initialize again after this
892 // procedure finishes. Of course, if this is not being called
893 // from the messenger then it won't happen. 2778172
896 // Outer loop - search the caches and method lists of the
897 // class and its super-classes
898 for (curClass = cls; curClass; curClass = _class_getSuperclass(curClass))
900 // Beware of thread-unsafety and double-freeing of forward::
901 // entries here! See note in "Method cache locking" above.
902 // The upshot is that _cache_getMethod() will return NULL
903 // instead of returning a forward:: entry.
904 Method meth = _cache_getMethod(curClass, sel, &_objc_msgForward);
906 // Found the method in this class or a superclass.
907 // Cache the method in this class, unless we just found it in
908 // this class's cache.
909 if (curClass != cls) {
910 _cache_fill (cls, meth, sel);
913 methodPC = method_getImplementation(meth);
917 // Cache scan failed. Search method list.
919 meth = _class_getMethodNoSuper(curClass, sel);
921 log_and_fill_cache(cls, curClass, meth, sel);
922 methodPC = method_getImplementation(meth);
927 if (methodPC == NULL) {
928 // Class and superclasses do not respond -- try resolve handler
929 Method meth = _class_resolveMethod(cls, sel);
931 // GrP fixme this isn't quite right
932 log_and_fill_cache(cls, cls, meth, sel);
933 methodPC = method_getImplementation(meth);
937 if (methodPC == NULL) {
938 // Class and superclasses do not respond and
939 // resolve handler didn't help -- use forwarding
940 _cache_addForwardEntry(cls, sel);
941 methodPC = &_objc_msgForward;
948 /***********************************************************************
949 * lookupMethodInClassAndLoadCache.
950 * Like _class_lookupMethodAndLoadCache, but does not search superclasses.
951 * Caches and returns objc_msgForward if the method is not found in the class.
952 **********************************************************************/
953 static IMP lookupMethodInClassAndLoadCache(Class cls, SEL sel)
958 // Search cache first.
959 imp = _cache_getImp(cls, sel);
962 // Cache miss. Search method list.
964 meth = _class_getMethodNoSuper(cls, sel);
967 // Hit in method list. Cache it.
968 _cache_fill(cls, meth, sel);
969 return method_getImplementation(meth);
971 // Miss in method list. Cache objc_msgForward.
972 _cache_addForwardEntry(cls, sel);
973 return &_objc_msgForward;
978 /***********************************************************************
980 **********************************************************************/
982 void * _objc_create_zone (void)
984 return malloc_default_zone();
988 /***********************************************************************
989 * _objc_internal_zone.
990 * Malloc zone for internal runtime data.
991 * By default this is the default malloc zone, but a dedicated zone is
992 * used if environment variable OBJC_USE_INTERNAL_ZONE is set.
993 **********************************************************************/
994 __private_extern__ malloc_zone_t *_objc_internal_zone(void)
996 static malloc_zone_t *z = (malloc_zone_t *)-1;
997 if (z == (malloc_zone_t *)-1) {
998 if (UseInternalZone) {
999 z = malloc_create_zone(vm_page_size, 0);
1000 malloc_set_zone_name(z, "ObjC");
1002 z = malloc_default_zone();
1009 /***********************************************************************
1014 * _strdupcat_internal
1017 * Convenience functions for the internal malloc zone.
1018 **********************************************************************/
1019 __private_extern__ void *_malloc_internal(size_t size)
1021 return malloc_zone_malloc(_objc_internal_zone(), size);
1024 __private_extern__ void *_calloc_internal(size_t count, size_t size)
1026 return malloc_zone_calloc(_objc_internal_zone(), count, size);
1029 __private_extern__ void *_realloc_internal(void *ptr, size_t size)
1031 return malloc_zone_realloc(_objc_internal_zone(), ptr, size);
1034 __private_extern__ char *_strdup_internal(const char *str)
1036 if (!str) return NULL;
1037 size_t len = strlen(str);
1038 char *dup = malloc_zone_malloc(_objc_internal_zone(), len + 1);
1039 memcpy(dup, str, len + 1);
1043 // allocate a new string that concatenates s1+s2.
1044 __private_extern__ char *_strdupcat_internal(const char *s1, const char *s2)
1046 size_t len1 = strlen(s1);
1047 size_t len2 = strlen(s2);
1048 char *dup = malloc_zone_malloc(_objc_internal_zone(), len1 + len2 + 1);
1049 memcpy(dup, s1, len1);
1050 memcpy(dup + len1, s2, len2 + 1);
1054 __private_extern__ void *_memdup_internal(const void *mem, size_t len)
1056 void *dup = malloc_zone_malloc(_objc_internal_zone(), len);
1057 memcpy(dup, mem, len);
1061 __private_extern__ void _free_internal(void *ptr)
1063 malloc_zone_free(_objc_internal_zone(), ptr);
1067 const char *class_getName(Class cls)
1069 return _class_getName(cls);
1072 Class class_getSuperclass(Class cls)
1074 return _class_getSuperclass(cls);
1077 BOOL class_isMetaClass(Class cls)
1079 return _class_isMetaClass(cls);
1083 size_t class_getInstanceSize(Class cls)
1085 return _class_getInstanceSize(cls);
1088 void method_exchangeImplementations(Method m1, Method m2)
1090 // fixme thread safe
1092 if (!m1 || !m2) return;
1093 m1_imp = method_getImplementation(m1);
1094 method_setImplementation(m1, method_setImplementation(m2, m1_imp));
1098 /***********************************************************************
1099 * method_getNumberOfArguments.
1100 **********************************************************************/
1101 unsigned int method_getNumberOfArguments(Method m)
1104 return encoding_getNumberOfArguments(method_getTypeEncoding(m));
1108 unsigned int method_getSizeOfArguments(Method m)
1110 OBJC_WARN_DEPRECATED;
1112 return encoding_getSizeOfArguments(method_getTypeEncoding(m));
1116 unsigned int method_getArgumentInfo(Method m, int arg,
1117 const char **type, int *offset)
1119 OBJC_WARN_DEPRECATED;
1121 return encoding_getArgumentInfo(method_getTypeEncoding(m),
1126 void method_getReturnType(Method m, char *dst, size_t dst_len)
1128 return encoding_getReturnType(method_getTypeEncoding(m), dst, dst_len);
1132 char * method_copyReturnType(Method m)
1134 return encoding_copyReturnType(method_getTypeEncoding(m));
1138 void method_getArgumentType(Method m, unsigned int index,
1139 char *dst, size_t dst_len)
1141 return encoding_getArgumentType(method_getTypeEncoding(m),
1142 index, dst, dst_len);
1146 char * method_copyArgumentType(Method m, unsigned int index)
1148 return encoding_copyArgumentType(method_getTypeEncoding(m), index);
1152 /***********************************************************************
1153 * _internal_class_createInstanceFromZone. Allocate an instance of the
1154 * specified class with the specified number of bytes for indexed
1155 * variables, in the specified zone. The isa field is set to the
1156 * class, C++ default constructors are called, and all other fields are zeroed.
1157 **********************************************************************/
1158 __private_extern__ id
1159 _internal_class_createInstanceFromZone(Class cls, size_t extraBytes,
1165 // Can't create something for nothing
1166 if (!cls) return nil;
1168 // Allocate and initialize
1169 size = _class_getInstanceSize(cls) + extraBytes;
1171 obj = (id) auto_zone_allocate_object(gc_zone, size,
1172 AUTO_OBJECT_SCANNED, false, true);
1174 obj = (id) malloc_zone_calloc (zone, 1, size);
1176 obj = (id) calloc(1, size);
1178 if (!obj) return nil;
1180 // Set the isa pointer
1183 // Call C++ constructors, if any.
1184 if (!object_cxxConstruct(obj)) {
1185 // Some C++ constructor threw an exception.
1187 auto_zone_retain(gc_zone, obj); // gc free expects retain count==1
1197 __private_extern__ id
1198 _internal_object_dispose(id anObject)
1200 if (anObject==nil) return nil;
1201 object_cxxDestruct(anObject);
1203 auto_zone_retain(gc_zone, anObject); // gc free expects retain count==1
1205 // only clobber isa for non-gc
1206 anObject->isa = _objc_getFreedObjectClass ();