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 "objc-private.h"
160 #include <objc/message.h>
163 /* overriding the default object allocation and error handling routines */
165 OBJC_EXPORT id (*_alloc)(Class, size_t);
166 OBJC_EXPORT id (*_copy)(id, size_t);
167 OBJC_EXPORT id (*_realloc)(id, size_t);
168 OBJC_EXPORT id (*_dealloc)(id);
169 OBJC_EXPORT id (*_zoneAlloc)(Class, size_t, void *);
170 OBJC_EXPORT id (*_zoneRealloc)(id, size_t, void *);
171 OBJC_EXPORT id (*_zoneCopy)(id, size_t, void *);
174 /***********************************************************************
175 * Function prototypes internal to this module.
176 **********************************************************************/
178 static IMP lookupMethodInClassAndLoadCache(Class cls, SEL sel);
179 static Method look_up_method(Class cls, SEL sel, BOOL withCache, BOOL withResolver);
182 /***********************************************************************
183 * Static data internal to this module.
184 **********************************************************************/
186 #if !TARGET_OS_WIN32 && !defined(__arm__)
187 # define MESSAGE_LOGGING
190 #if defined(MESSAGE_LOGGING)
191 // Method call logging
192 static int LogObjCMessageSend (BOOL isClassMethod, const char * objectsClass, const char * implementingClass, SEL selector);
193 typedef int (*ObjCLogProc)(BOOL, const char *, const char *, SEL);
195 static int objcMsgLogFD = (-1);
196 static ObjCLogProc objcMsgLogProc = &LogObjCMessageSend;
197 static int objcMsgLogEnabled = 0;
200 /***********************************************************************
201 * Information about multi-thread support:
203 * Since we do not lock many operations which walk the superclass, method
204 * and ivar chains, these chains must remain intact once a class is published
205 * by inserting it into the class hashtable. All modifications must be
206 * atomic so that someone walking these chains will always geta valid
208 ***********************************************************************/
212 /***********************************************************************
214 **********************************************************************/
215 Class object_getClass(id obj)
217 if (obj) return obj->isa;
222 /***********************************************************************
224 **********************************************************************/
225 Class object_setClass(id obj, Class cls)
231 } while (! OSAtomicCompareAndSwapPtrBarrier(old, cls, (void*)&obj->isa));
238 /***********************************************************************
239 * object_getClassName.
240 **********************************************************************/
241 const char *object_getClassName(id obj)
243 if (obj) return _class_getName(obj->isa);
247 /***********************************************************************
248 * object_getIndexedIvars.
249 **********************************************************************/
250 void *object_getIndexedIvars(id obj)
252 // ivars are tacked onto the end of the object
253 if (obj) return ((char *) obj) + _class_getInstanceSize(obj->isa);
258 Ivar object_setInstanceVariable(id obj, const char *name, void *value)
263 if ((ivar = class_getInstanceVariable(obj->isa, name))) {
264 objc_assign_ivar_internal(
267 ivar_getOffset(ivar));
273 Ivar object_getInstanceVariable(id obj, const char *name, void **value)
278 if ((ivar = class_getInstanceVariable(obj->isa, name))) {
279 ivaridx = (void **)((char *)obj + ivar_getOffset(ivar));
280 if (value) *value = *ivaridx;
284 if (value) *value = NULL;
289 void object_setIvar(id obj, Ivar ivar, id value)
292 objc_assign_ivar_internal(value, obj, ivar_getOffset(ivar));
297 id object_getIvar(id obj, Ivar ivar)
300 id *idx = (id *)((char *)obj + ivar_getOffset(ivar));
307 /***********************************************************************
308 * object_cxxDestructFromClass.
309 * Call C++ destructors on obj, starting with cls's
310 * dtor method (if any) followed by superclasses' dtors (if any),
311 * stopping at cls's dtor (if any).
312 * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
313 **********************************************************************/
314 static void object_cxxDestructFromClass(id obj, Class cls)
318 // Call cls's dtor first, then superclasses's dtors.
320 for ( ; cls != NULL; cls = _class_getSuperclass(cls)) {
321 if (!_class_hasCxxStructorsNoSuper(cls)) continue;
323 lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct);
324 if (dtor != (void(*)(id))&_objc_msgForward_internal) {
326 _objc_inform("CXX: calling C++ destructors for class %s",
327 _class_getName(cls));
335 /***********************************************************************
336 * object_cxxDestruct.
337 * Call C++ destructors on obj, if any.
338 * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
339 **********************************************************************/
340 __private_extern__ void object_cxxDestruct(id obj)
343 object_cxxDestructFromClass(obj, obj->isa);
347 /***********************************************************************
348 * object_cxxConstructFromClass.
349 * Recursively call C++ constructors on obj, starting with base class's
350 * ctor method (if any) followed by subclasses' ctors (if any), stopping
351 * at cls's ctor (if any).
352 * Returns YES if construction succeeded.
353 * Returns NO if some constructor threw an exception. The exception is
354 * caught and discarded. Any partial construction is destructed.
355 * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
357 * .cxx_construct returns id. This really means:
358 * return self: construction succeeded
359 * return nil: construction failed because a C++ constructor threw an exception
360 **********************************************************************/
361 static BOOL object_cxxConstructFromClass(id obj, Class cls)
364 Class supercls = _class_getSuperclass(cls);
366 // Call superclasses' ctors first, if any.
368 BOOL ok = object_cxxConstructFromClass(obj, supercls);
369 if (!ok) return NO; // some superclass's ctor failed - give up
372 // Find this class's ctor, if any.
373 if (!_class_hasCxxStructorsNoSuper(cls)) return YES; // no ctor - ok
374 ctor = (id(*)(id))lookupMethodInClassAndLoadCache(cls, SEL_cxx_construct);
375 if (ctor == (id(*)(id))&_objc_msgForward_internal) return YES; // no ctor - ok
377 // Call this class's ctor.
379 _objc_inform("CXX: calling C++ constructors for class %s", _class_getName(cls));
381 if ((*ctor)(obj)) return YES; // ctor called and succeeded - ok
383 // This class's ctor was called and failed.
384 // Call superclasses's dtors to clean up.
385 if (supercls) object_cxxDestructFromClass(obj, supercls);
390 /***********************************************************************
391 * object_cxxConstructFromClass.
392 * Call C++ constructors on obj, if any.
393 * Returns YES if construction succeeded.
394 * Returns NO if some constructor threw an exception. The exception is
395 * caught and discarded. Any partial construction is destructed.
396 * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
397 **********************************************************************/
398 __private_extern__ BOOL object_cxxConstruct(id obj)
400 if (!obj) return YES;
401 return object_cxxConstructFromClass(obj, obj->isa);
405 /***********************************************************************
406 * _class_resolveClassMethod
407 * Call +resolveClassMethod and return the method added or NULL.
408 * cls should be a metaclass.
409 * Assumes the method doesn't exist already.
410 **********************************************************************/
411 static Method _class_resolveClassMethod(Class cls, SEL sel)
417 if (!look_up_method(cls, SEL_resolveClassMethod,
418 YES /*cache*/, NO /*resolver*/))
423 // GrP fixme same hack as +initialize
424 if (strncmp(_class_getName(cls), "_%", 2) == 0) {
425 // Posee's meta's name is smashed and isn't in the class_hash,
426 // so objc_getClass doesn't work.
427 const char *baseName = strchr(_class_getName(cls), '%'); // get posee's real name
428 clsInstance = (Class)objc_getClass(baseName);
430 clsInstance = (Class)objc_getClass(_class_getName(cls));
433 resolved = ((BOOL(*)(id, SEL, SEL))objc_msgSend)((id)clsInstance, SEL_resolveClassMethod, sel);
436 // +resolveClassMethod adds to self->isa
437 meth = look_up_method(cls, sel, YES/*cache*/, NO/*resolver*/);
440 // Method resolver didn't add anything?
441 _objc_inform("+[%s resolveClassMethod:%s] returned YES, but "
442 "no new implementation of +[%s %s] was found",
455 /***********************************************************************
456 * _class_resolveInstanceMethod
457 * Call +resolveInstanceMethod and return the method added or NULL.
458 * cls should be a non-meta class.
459 * Assumes the method doesn't exist already.
460 **********************************************************************/
461 static Method _class_resolveInstanceMethod(Class cls, SEL sel)
466 if (!look_up_method(((id)cls)->isa, SEL_resolveInstanceMethod,
467 YES /*cache*/, NO /*resolver*/))
472 resolved = ((BOOL(*)(id, SEL, SEL))objc_msgSend)((id)cls, SEL_resolveInstanceMethod, sel);
475 // +resolveClassMethod adds to self
476 meth = look_up_method(cls, sel, YES/*cache*/, NO/*resolver*/);
479 // Method resolver didn't add anything?
480 _objc_inform("+[%s resolveInstanceMethod:%s] returned YES, but "
481 "no new implementation of %c[%s %s] was found",
484 class_isMetaClass(cls) ? '+' : '-',
495 /***********************************************************************
496 * _class_resolveMethod
497 * Call +resolveClassMethod or +resolveInstanceMethod and return
498 * the method added or NULL.
499 * Assumes the method doesn't exist already.
500 **********************************************************************/
501 __private_extern__ Method _class_resolveMethod(Class cls, SEL sel)
505 if (_class_isMetaClass(cls)) {
506 meth = _class_resolveClassMethod(cls, sel);
509 meth = _class_resolveInstanceMethod(cls, sel);
512 if (PrintResolving && meth) {
513 _objc_inform("RESOLVE: method %c[%s %s] dynamically resolved to %p",
514 class_isMetaClass(cls) ? '+' : '-',
515 class_getName(cls), sel_getName(sel),
516 method_getImplementation(meth));
523 /***********************************************************************
525 * Look up a method in the given class and its superclasses.
526 * If withCache==YES, look in the class's method cache too.
527 * If withResolver==YES, call +resolveClass/InstanceMethod too.
528 * Returns NULL if the method is not found.
529 * +forward:: entries are not returned.
530 **********************************************************************/
531 static Method look_up_method(Class cls, SEL sel,
532 BOOL withCache, BOOL withResolver)
537 meth = _cache_getMethod(cls, sel, &_objc_msgForward_internal);
538 if (meth == (Method)1) {
539 // Cache contains forward:: . Stop searching.
544 if (!meth) meth = _class_getMethod(cls, sel);
546 if (!meth && withResolver) meth = _class_resolveMethod(cls, sel);
552 /***********************************************************************
553 * class_getInstanceMethod. Return the instance method for the
554 * specified class and selector.
555 **********************************************************************/
556 Method class_getInstanceMethod(Class cls, SEL sel)
558 if (!cls || !sel) return NULL;
560 return look_up_method(cls, sel, YES/*cache*/, YES/*resolver*/);
563 /***********************************************************************
564 * class_getClassMethod. Return the class method for the specified
565 * class and selector.
566 **********************************************************************/
567 Method class_getClassMethod(Class cls, SEL sel)
569 if (!cls || !sel) return NULL;
571 return class_getInstanceMethod(_class_getMeta(cls), sel);
575 /***********************************************************************
576 * class_getInstanceVariable. Return the named instance variable.
577 **********************************************************************/
578 Ivar class_getInstanceVariable(Class cls, const char *name)
580 if (!cls || !name) return NULL;
582 return _class_getVariable(cls, name);
586 /***********************************************************************
587 * class_getClassVariable. Return the named class variable.
588 **********************************************************************/
589 Ivar class_getClassVariable(Class cls, const char *name)
591 if (!cls) return NULL;
593 return class_getInstanceVariable(((id)cls)->isa, name);
597 __private_extern__ Property
598 property_list_nth(const struct objc_property_list *plist, uint32_t i)
600 return (Property)(i*plist->entsize + (char *)&plist->first);
603 __private_extern__ size_t
604 property_list_size(const struct objc_property_list *plist)
606 return sizeof(struct objc_property_list) + (plist->count-1)*plist->entsize;
609 __private_extern__ Property *
610 copyPropertyList(struct objc_property_list *plist, unsigned int *outCount)
612 Property *result = NULL;
613 unsigned int count = 0;
616 count = plist->count;
621 result = malloc((count+1) * sizeof(Property));
623 for (i = 0; i < count; i++) {
624 result[i] = property_list_nth(plist, i);
629 if (outCount) *outCount = count;
633 const char *property_getName(Property prop)
639 const char *property_getAttributes(Property prop)
641 return prop->attributes;
645 /***********************************************************************
646 * gdb_objc_class_changed
647 * Tell gdb that a class changed. Currently used for OBJC2 ivar layouts only
648 **********************************************************************/
649 void gdb_objc_class_changed(Class cls, unsigned long changes, const char *classname)
651 // do nothing; gdb sets a breakpoint here to listen
660 /***********************************************************************
661 * _objc_flush_caches. Flush the caches of the specified class and any
662 * of its subclasses. If cls is a meta-class, only meta-class (i.e.
663 * class method) caches are flushed. If cls is an instance-class, both
664 * instance-class and meta-class caches are flushed.
665 **********************************************************************/
666 void _objc_flush_caches(Class cls)
668 flush_caches (cls, YES);
672 /***********************************************************************
673 * class_respondsToSelector.
674 **********************************************************************/
675 BOOL class_respondsToMethod(Class cls, SEL sel)
677 OBJC_WARN_DEPRECATED;
679 return class_respondsToSelector(cls, sel);
683 BOOL class_respondsToSelector(Class cls, SEL sel)
687 if (!sel || !cls) return NO;
689 // Avoids +initialize because it historically did so.
690 // We're not returning a callable IMP anyway.
691 imp = lookUpMethod(cls, sel, NO/*initialize*/, YES/*cache*/);
692 return (imp != (IMP)_objc_msgForward_internal) ? YES : NO;
696 /***********************************************************************
697 * class_getMethodImplementation.
698 * Returns the IMP that would be invoked if [obj sel] were sent,
699 * where obj is an instance of class cls.
700 **********************************************************************/
701 IMP class_lookupMethod(Class cls, SEL sel)
703 OBJC_WARN_DEPRECATED;
705 // No one responds to zero!
707 __objc_error((id)cls, "invalid selector (null)");
710 return class_getMethodImplementation(cls, sel);
713 IMP class_getMethodImplementation(Class cls, SEL sel)
717 if (!cls || !sel) return NULL;
719 imp = lookUpMethod(cls, sel, YES/*initialize*/, YES/*cache*/);
721 // Translate forwarding function to C-callable external version
722 if (imp == (IMP)&_objc_msgForward_internal) {
723 return (IMP)&_objc_msgForward;
730 IMP class_getMethodImplementation_stret(Class cls, SEL sel)
732 IMP imp = class_getMethodImplementation(cls, sel);
734 // Translate forwarding function to struct-returning version
735 if (imp == (IMP)&_objc_msgForward /* not _internal! */) {
736 return (IMP)&_objc_msgForward_stret;
742 // Ignored selectors get method->imp = &_objc_ignored_method
743 __private_extern__ id _objc_ignored_method(id self, SEL _cmd) { return self; }
746 /***********************************************************************
747 * instrumentObjcMessageSends/logObjcMessageSends.
748 **********************************************************************/
749 #if defined(MESSAGE_LOGGING)
750 static int LogObjCMessageSend (BOOL isClassMethod,
751 const char * objectsClass,
752 const char * implementingClass,
757 // Create/open the log file
758 if (objcMsgLogFD == (-1))
760 snprintf (buf, sizeof(buf), "/tmp/msgSends-%d", (int) getpid ());
761 objcMsgLogFD = secure_open (buf, O_WRONLY | O_CREAT, geteuid());
762 if (objcMsgLogFD < 0) {
763 // no log file - disable logging
764 objcMsgLogEnabled = 0;
770 // Make the log entry
771 snprintf(buf, sizeof(buf), "%c %s %s %s\n",
772 isClassMethod ? '+' : '-',
777 static OSSpinLock lock = OS_SPINLOCK_INIT;
778 OSSpinLockLock(&lock);
779 write (objcMsgLogFD, buf, strlen(buf));
780 OSSpinLockUnlock(&lock);
782 // Tell caller to not cache the method
786 void instrumentObjcMessageSends (BOOL flag)
788 int enabledValue = (flag) ? 1 : 0;
791 if (objcMsgLogEnabled == enabledValue)
794 // If enabling, flush all method caches so we get some traces
796 flush_caches (Nil, YES);
799 if (objcMsgLogFD != (-1))
800 fsync (objcMsgLogFD);
802 objcMsgLogEnabled = enabledValue;
805 __private_extern__ void logObjcMessageSends (ObjCLogProc logProc)
809 objcMsgLogProc = logProc;
810 objcMsgLogEnabled = 1;
814 objcMsgLogProc = logProc;
815 objcMsgLogEnabled = 0;
818 if (objcMsgLogFD != (-1))
819 fsync (objcMsgLogFD);
823 /***********************************************************************
825 * Log this method call. If the logger permits it, fill the method cache.
826 * cls is the method whose cache should be filled.
827 * implementer is the class that owns the implementation in question.
828 **********************************************************************/
829 __private_extern__ void
830 log_and_fill_cache(Class cls, Class implementer, Method meth, SEL sel)
832 #if defined(MESSAGE_LOGGING)
835 if (objcMsgLogEnabled) {
836 cacheIt = objcMsgLogProc (_class_isMetaClass(implementer) ? YES : NO,
838 _class_getName(implementer),
843 _cache_fill (cls, meth, sel);
847 /***********************************************************************
848 * _class_lookupMethodAndLoadCache.
849 * Method lookup for dispatchers ONLY. OTHER CODE SHOULD USE lookUpMethod().
850 * This lookup avoids optimistic cache scan because the dispatcher
851 * already tried that.
852 **********************************************************************/
853 __private_extern__ IMP _class_lookupMethodAndLoadCache(Class cls, SEL sel)
855 return lookUpMethod(cls, sel, YES/*initialize*/, NO/*cache*/);
859 /***********************************************************************
861 * The standard method lookup.
862 * initialize==NO tries to avoid +initialize (but sometimes fails)
863 * cache==NO skips optimistic unlocked lookup (but uses cache elsewhere)
864 * Most callers should use initialize==YES and cache==YES.
865 * May return _objc_msgForward_internal. IMPs destined for external use
866 * must be converted to _objc_msgForward or _objc_msgForward_stret.
867 **********************************************************************/
868 __private_extern__ IMP lookUpMethod(Class cls, SEL sel,
869 BOOL initialize, BOOL cache)
874 BOOL triedResolver = NO;
876 // Optimistic cache lookup
878 methodPC = _cache_getImp(cls, sel);
879 if (methodPC) return methodPC;
882 // realize, +initialize, and any special early exit
883 methodPC = prepareForMethodLookup(cls, sel, initialize);
884 if (methodPC) return methodPC;
887 // The lock is held to make method-lookup + cache-fill atomic
888 // with respect to method addition. Otherwise, a category could
889 // be added but ignored indefinitely because the cache was re-filled
890 // with the old value after the cache flush on behalf of the category.
892 lockForMethodLookup();
894 // Try this class's cache.
896 methodPC = _cache_getImp(cls, sel);
897 if (methodPC) goto done;
899 // Try this class's method lists.
901 meth = _class_getMethodNoSuper_nolock(cls, sel);
903 log_and_fill_cache(cls, cls, meth, sel);
904 methodPC = method_getImplementation(meth);
908 // Try superclass caches and method lists.
911 while ((curClass = _class_getSuperclass(curClass))) {
913 meth = _cache_getMethod(curClass, sel, &_objc_msgForward_internal);
915 if (meth != (Method)1) {
916 // Found the method in a superclass. Cache it in this class.
917 log_and_fill_cache(cls, curClass, meth, sel);
918 methodPC = method_getImplementation(meth);
922 // Found a forward:: entry in a superclass.
923 // Stop searching, but don't cache yet; call method
924 // resolver for this class first.
929 // Superclass method list.
930 meth = _class_getMethodNoSuper_nolock(curClass, sel);
932 log_and_fill_cache(cls, curClass, meth, sel);
933 methodPC = method_getImplementation(meth);
938 // No implementation found. Try method resolver once.
940 if (!triedResolver) {
941 unlockForMethodLookup();
942 _class_resolveMethod(cls, sel);
943 // Don't cache the result; we don't hold the lock so it may have
944 // changed already. Re-do the search from scratch instead.
949 // No implementation found, and method resolver didn't help.
952 _cache_addForwardEntry(cls, sel);
953 methodPC = &_objc_msgForward_internal;
956 unlockForMethodLookup();
958 // paranoia: look for ignored selectors with non-ignored implementations
959 assert(!(sel == (SEL)kIgnore && methodPC != (IMP)&_objc_ignored_method));
965 /***********************************************************************
966 * lookupMethodInClassAndLoadCache.
967 * Like _class_lookupMethodAndLoadCache, but does not search superclasses.
968 * Caches and returns objc_msgForward if the method is not found in the class.
969 **********************************************************************/
970 static IMP lookupMethodInClassAndLoadCache(Class cls, SEL sel)
975 // fixme this still has the method list vs method cache race
976 // because it doesn't hold a lock across lookup+cache_fill,
977 // but it's only used for .cxx_construct/destruct and we assume
978 // categories don't change them.
980 // Search cache first.
981 imp = _cache_getImp(cls, sel);
984 // Cache miss. Search method list.
986 meth = _class_getMethodNoSuper(cls, sel);
989 // Hit in method list. Cache it.
990 _cache_fill(cls, meth, sel);
991 return method_getImplementation(meth);
993 // Miss in method list. Cache objc_msgForward.
994 _cache_addForwardEntry(cls, sel);
995 return &_objc_msgForward_internal;
1000 /***********************************************************************
1001 * _objc_create_zone.
1002 **********************************************************************/
1004 void *_objc_create_zone(void)
1006 return malloc_default_zone();
1010 /***********************************************************************
1015 * _strdupcat_internal
1018 * Convenience functions for the internal malloc zone.
1019 **********************************************************************/
1020 __private_extern__ void *_malloc_internal(size_t size)
1022 return malloc_zone_malloc(_objc_internal_zone(), size);
1025 __private_extern__ void *_calloc_internal(size_t count, size_t size)
1027 return malloc_zone_calloc(_objc_internal_zone(), count, size);
1030 __private_extern__ void *_realloc_internal(void *ptr, size_t size)
1032 return malloc_zone_realloc(_objc_internal_zone(), ptr, size);
1035 __private_extern__ char *_strdup_internal(const char *str)
1039 if (!str) return NULL;
1041 dup = malloc_zone_malloc(_objc_internal_zone(), len + 1);
1042 memcpy(dup, str, len + 1);
1046 // allocate a new string that concatenates s1+s2.
1047 __private_extern__ char *_strdupcat_internal(const char *s1, const char *s2)
1049 size_t len1 = strlen(s1);
1050 size_t len2 = strlen(s2);
1051 char *dup = malloc_zone_malloc(_objc_internal_zone(), len1 + len2 + 1);
1052 memcpy(dup, s1, len1);
1053 memcpy(dup + len1, s2, len2 + 1);
1057 __private_extern__ void *_memdup_internal(const void *mem, size_t len)
1059 void *dup = malloc_zone_malloc(_objc_internal_zone(), len);
1060 memcpy(dup, mem, len);
1064 __private_extern__ void _free_internal(void *ptr)
1066 malloc_zone_free(_objc_internal_zone(), ptr);
1070 __private_extern__ Class _calloc_class(size_t size)
1073 if (UseGC) return (Class) malloc_zone_calloc(gc_zone, 1, size);
1075 return (Class) _calloc_internal(1, size);
1079 const char *class_getName(Class cls)
1081 return _class_getName(cls);
1084 Class class_getSuperclass(Class cls)
1086 return _class_getSuperclass(cls);
1089 BOOL class_isMetaClass(Class cls)
1091 return _class_isMetaClass(cls);
1095 size_t class_getInstanceSize(Class cls)
1097 return _class_getInstanceSize(cls);
1101 /***********************************************************************
1102 * method_getNumberOfArguments.
1103 **********************************************************************/
1104 unsigned int method_getNumberOfArguments(Method m)
1107 return encoding_getNumberOfArguments(method_getTypeEncoding(m));
1111 unsigned int method_getSizeOfArguments(Method m)
1113 OBJC_WARN_DEPRECATED;
1115 return encoding_getSizeOfArguments(method_getTypeEncoding(m));
1119 unsigned int method_getArgumentInfo(Method m, int arg,
1120 const char **type, int *offset)
1122 OBJC_WARN_DEPRECATED;
1124 return encoding_getArgumentInfo(method_getTypeEncoding(m),
1129 void method_getReturnType(Method m, char *dst, size_t dst_len)
1131 encoding_getReturnType(method_getTypeEncoding(m), dst, dst_len);
1135 char * method_copyReturnType(Method m)
1137 return encoding_copyReturnType(method_getTypeEncoding(m));
1141 void method_getArgumentType(Method m, unsigned int index,
1142 char *dst, size_t dst_len)
1144 encoding_getArgumentType(method_getTypeEncoding(m),
1145 index, dst, dst_len);
1149 char * method_copyArgumentType(Method m, unsigned int index)
1151 return encoding_copyArgumentType(method_getTypeEncoding(m), index);
1155 /***********************************************************************
1156 * objc_constructInstance
1157 * Creates an instance of `cls` at the location pointed to by `bytes`.
1158 * `bytes` must point to at least class_getInstanceSize(cls) bytes of
1159 * well-aligned zero-filled memory.
1160 * The new object's isa is set. Any C++ constructors are called.
1161 * Returns `bytes` if successful. Returns nil if `cls` or `bytes` is
1162 * NULL, or if C++ constructors fail.
1163 **********************************************************************/
1164 id objc_constructInstance(Class cls, void *bytes)
1168 if (!cls || !bytes) return nil;
1171 // Set the isa pointer
1174 // Call C++ constructors, if any.
1175 if (!object_cxxConstruct(obj)) {
1176 // Some C++ constructor threw an exception.
1184 /***********************************************************************
1185 * objc_destructInstance
1186 * Destroys an instance without freeing memory.
1187 * Any C++ destructors are called. Any associative references are removed.
1188 * Returns `obj`. Does nothing if `obj` is nil.
1189 **********************************************************************/
1190 void *objc_destructInstance(id obj)
1193 object_cxxDestruct(obj);
1195 // don't call this if the class has never had associative references.
1196 if (_class_instancesHaveAssociatedObjects(obj->isa)) {
1197 _object_remove_assocations(obj);
1205 /***********************************************************************
1206 * _internal_class_createInstanceFromZone. Allocate an instance of the
1207 * specified class with the specified number of bytes for indexed
1208 * variables, in the specified zone. The isa field is set to the
1209 * class, C++ default constructors are called, and all other fields are zeroed.
1210 **********************************************************************/
1211 __private_extern__ id
1212 _internal_class_createInstanceFromZone(Class cls, size_t extraBytes,
1219 // Can't create something for nothing
1220 if (!cls) return nil;
1222 // Allocate and initialize
1223 size = _class_getInstanceSize(cls) + extraBytes;
1225 // CF requires all objects be at least 16 bytes.
1226 if (size < 16) size = 16;
1230 bytes = auto_zone_allocate_object(gc_zone, size,
1231 AUTO_OBJECT_SCANNED, 0, 1);
1235 bytes = malloc_zone_calloc (zone, 1, size);
1237 bytes = calloc(1, size);
1239 if (!bytes) return nil;
1241 obj = objc_constructInstance(cls, bytes);
1245 auto_zone_retain(gc_zone, bytes); // gc free expects rc==1
1256 __private_extern__ id
1257 _internal_object_dispose(id anObject)
1259 if (anObject==nil) return nil;
1261 objc_destructInstance(anObject);
1265 auto_zone_retain(gc_zone, anObject); // gc free expects rc==1
1270 // only clobber isa for non-gc
1271 anObject->isa = _objc_getFreedObjectClass ();
1279 /***********************************************************************
1280 * inform_duplicate. Complain about duplicate class implementations.
1281 **********************************************************************/
1282 __private_extern__ void
1283 inform_duplicate(const char *name, Class oldCls, Class cls)
1286 _objc_inform ("Class %s is implemented in two different images.", name);
1288 const header_info *oldHeader = _headerForClass(oldCls);
1289 const header_info *newHeader = _headerForClass(cls);
1290 const char *oldName = oldHeader ? _nameForHeader(oldHeader->mhdr) : "??";
1291 const char *newName = newHeader ? _nameForHeader(newHeader->mhdr) : "??";
1293 _objc_inform ("Class %s is implemented in both %s and %s. "
1294 "One of the two will be used. "
1295 "Which one is undefined.",
1296 name, oldName, newName);