2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 /***********************************************************************
26 * Copyright 1988-1997, Apple Computer, Inc.
28 **********************************************************************/
30 /***********************************************************************
32 **********************************************************************/
34 #import <mach/mach_interface.h>
35 #include <mach-o/ldsyms.h>
36 #include <mach-o/dyld.h>
38 #include <sys/types.h>
42 #include <sys/fcntl.h>
44 #import "objc-class.h"
46 #import <objc/Object.h>
47 #import <objc/objc-runtime.h>
48 #import "objc-private.h"
49 #import "hashtable2.h"
52 #include <sys/types.h>
54 #include <CoreFoundation/CFDictionary.h>
56 // Needed functions not in any header file
57 size_t malloc_size (const void * ptr);
59 // Needed kernel interface
61 #import <mach/thread_status.h>
64 /***********************************************************************
66 **********************************************************************/
68 // Define PRELOAD_SUPERCLASS_CACHES to cause method lookups to add the
69 // method the appropriate superclass caches, in addition to the normal
70 // encaching in the subclass where the method was messaged. Doing so
71 // will speed up messaging the same method from instances of the
72 // superclasses, but also uses up valuable cache space for a speculative
74 // See radar 2364264 about incorrectly propogating _objc_forward entries
75 // and double freeing them, first, before turning this on!
76 //#define PRELOAD_SUPERCLASS_CACHES
78 /***********************************************************************
80 **********************************************************************/
82 #ifdef OBJC_INSTRUMENTED
84 CACHE_HISTOGRAM_SIZE = 512
87 unsigned int CacheHitHistogram [CACHE_HISTOGRAM_SIZE];
88 unsigned int CacheMissHistogram [CACHE_HISTOGRAM_SIZE];
91 /***********************************************************************
92 * Constants and macros internal to this module.
93 **********************************************************************/
95 // INIT_CACHE_SIZE and INIT_META_CACHE_SIZE must be a power of two
97 INIT_CACHE_SIZE_LOG2 = 2,
98 INIT_META_CACHE_SIZE_LOG2 = 2,
99 INIT_CACHE_SIZE = (1 << INIT_CACHE_SIZE_LOG2),
100 INIT_META_CACHE_SIZE = (1 << INIT_META_CACHE_SIZE_LOG2)
103 // Amount of space required for count hash table buckets, knowing that
104 // one entry is embedded in the cache structure itself
105 #define TABLE_SIZE(count) ((count - 1) * sizeof(Method))
108 #define ISCLASS(cls) ((((struct objc_class *) cls)->info & CLS_CLASS) != 0)
109 #define ISMETA(cls) ((((struct objc_class *) cls)->info & CLS_META) != 0)
110 #define GETMETA(cls) (ISMETA(cls) ? ((struct objc_class *) cls) : ((struct objc_class *) cls)->isa)
111 #define ISINITIALIZED(cls) ((GETMETA(cls)->info & CLS_INITIALIZED) != 0)
112 #define MARKINITIALIZED(cls) (GETMETA(cls)->info |= CLS_INITIALIZED)
114 /***********************************************************************
115 * Types internal to this module.
116 **********************************************************************/
118 #ifdef OBJC_INSTRUMENTED
119 struct CacheInstrumentation
121 unsigned int hitCount; // cache lookup success tally
122 unsigned int hitProbes; // sum entries checked to hit
123 unsigned int maxHitProbes; // max entries checked to hit
124 unsigned int missCount; // cache lookup no-find tally
125 unsigned int missProbes; // sum entries checked to miss
126 unsigned int maxMissProbes; // max entries checked to miss
127 unsigned int flushCount; // cache flush tally
128 unsigned int flushedEntries; // sum cache entries flushed
129 unsigned int maxFlushedEntries; // max cache entries flushed
131 typedef struct CacheInstrumentation CacheInstrumentation;
133 // Cache instrumentation data follows table, so it is most compatible
134 #define CACHE_INSTRUMENTATION(cache) (CacheInstrumentation *) &cache->buckets[cache->mask + 1];
137 /***********************************************************************
138 * Function prototypes internal to this module.
139 **********************************************************************/
141 static Ivar class_getVariable (Class cls, const char * name);
142 static void flush_caches (Class cls, BOOL flush_meta);
143 static void addClassToOriginalClass (Class posingClass, Class originalClass);
144 static void _objc_addOrigClass (Class origClass);
145 static void _freedHandler (id self, SEL sel);
146 static void _nonexistentHandler (id self, SEL sel);
147 static void class_initialize (Class clsDesc);
148 static void * objc_malloc (int byteCount);
149 static Cache _cache_expand (Class cls);
150 static int LogObjCMessageSend (BOOL isClassMethod, const char * objectsClass, const char * implementingClass, SEL selector);
151 static void _cache_fill (Class cls, Method smt, SEL sel);
152 static void _cache_flush (Class cls);
153 static Method _class_lookupMethod (Class cls, SEL sel);
154 static int SubtypeUntil (const char * type, char end);
155 static const char * SkipFirstType (const char * type);
157 #ifdef OBJC_COLLECTING_CACHE
158 static unsigned long _get_pc_for_thread (mach_port_t thread);
159 static int _collecting_in_critical (void);
160 static void _garbage_make_room (void);
161 static void _cache_collect_free (void * data, BOOL tryCollect);
164 static void _cache_print (Cache cache);
165 static unsigned int log2 (unsigned int x);
166 static void PrintCacheHeader (void);
167 #ifdef OBJC_INSTRUMENTED
168 static void PrintCacheHistogram (char * title, unsigned int * firstEntry, unsigned int entryCount);
171 /***********************************************************************
172 * Static data internal to this module.
173 **********************************************************************/
175 // When _class_uncache is non-zero, cache growth copies the existing
176 // entries into the new (larger) cache. When this flag is zero, new
177 // (larger) caches start out empty.
178 static int _class_uncache = 1;
180 // When _class_slow_grow is non-zero, any given cache is actually grown
181 // only on the odd-numbered times it becomes full; on the even-numbered
182 // times, it is simply emptied and re-used. When this flag is zero,
183 // caches are grown every time.
184 static int _class_slow_grow = 1;
186 // Locks for cache access
187 #ifdef OBJC_COLLECTING_CACHE
188 // Held when adding an entry to the cache
189 static OBJC_DECLARE_LOCK(cacheUpdateLock);
191 // Held when freeing memory from garbage
192 static OBJC_DECLARE_LOCK(cacheCollectionLock);
195 // Held when looking in, adding to, or freeing the cache.
196 #ifdef OBJC_COLLECTING_CACHE
197 // For speed, messageLock is not held by the method dispatch code.
198 // Instead the cache freeing code checks thread PCs to ensure no
199 // one is dispatching. messageLock is held, though, during less
200 // time critical operations.
202 OBJC_DECLARE_LOCK(messageLock);
204 CFMutableDictionaryRef _classIMPTables = NULL;
206 // When traceDuplicates is non-zero, _cacheFill checks whether the method
207 // being encached is already there. The number of times it finds a match
208 // is tallied in cacheFillDuplicates. When traceDuplicatesVerbose is
209 // non-zero, each duplication is logged when found in this way.
210 #ifdef OBJC_COLLECTING_CACHE
211 static int traceDuplicates = 0;
212 static int traceDuplicatesVerbose = 0;
213 static int cacheFillDuplicates = 0;
216 #ifdef OBJC_INSTRUMENTED
218 static unsigned int LinearFlushCachesCount = 0;
219 static unsigned int LinearFlushCachesVisitedCount = 0;
220 static unsigned int MaxLinearFlushCachesVisitedCount = 0;
221 static unsigned int NonlinearFlushCachesCount = 0;
222 static unsigned int NonlinearFlushCachesClassCount = 0;
223 static unsigned int NonlinearFlushCachesVisitedCount = 0;
224 static unsigned int MaxNonlinearFlushCachesVisitedCount = 0;
225 static unsigned int IdealFlushCachesCount = 0;
226 static unsigned int MaxIdealFlushCachesCount = 0;
229 // Method call logging
230 typedef int (*ObjCLogProc)(BOOL, const char *, const char *, SEL);
232 static int totalCacheFills = 0;
233 static int objcMsgLogFD = (-1);
234 static ObjCLogProc objcMsgLogProc = &LogObjCMessageSend;
235 static int objcMsgLogEnabled = 0;
239 _errNoMem[] = "failed -- out of memory(%s, %u)",
240 _errAllocNil[] = "allocating nil object",
241 _errFreedObject[] = "message %s sent to freed object=0x%lx",
242 _errNonExistentObject[] = "message %s sent to non-existent object=0x%lx",
243 _errBadSel[] = "invalid selector %s",
244 _errNotSuper[] = "[%s poseAs:%s]: target not immediate superclass",
245 _errNewVars[] = "[%s poseAs:%s]: %s defines new instance variables";
247 /***********************************************************************
248 * Information about multi-thread support:
250 * Since we do not lock many operations which walk the superclass, method
251 * and ivar chains, these chains must remain intact once a class is published
252 * by inserting it into the class hashtable. All modifications must be
253 * atomic so that someone walking these chains will always geta valid
255 ***********************************************************************/
256 /***********************************************************************
257 * A static empty cache. All classes initially point at this cache.
258 * When the first message is sent it misses in the cache, and when
259 * the cache is grown it checks for this case and uses malloc rather
260 * than realloc. This avoids the need to check for NULL caches in the
262 ***********************************************************************/
264 const struct objc_cache emptyCache =
271 // Freed objects have their isa set to point to this dummy class.
272 // This avoids the need to check for Nil classes in the messenger.
273 static const struct objc_class freedObjectClass =
283 (Cache) &emptyCache, // cache
287 static const struct objc_class nonexistentObjectClass =
291 "NONEXISTENT(id)", // name
297 (Cache) &emptyCache, // cache
301 /***********************************************************************
302 * object_getClassName.
303 **********************************************************************/
304 const char * object_getClassName (id obj)
306 // Even nil objects have a class name, sort of
310 // Retrieve name from object's class
311 return ((struct objc_class *) obj->isa)->name;
314 /***********************************************************************
315 * object_getIndexedIvars.
316 **********************************************************************/
317 void * object_getIndexedIvars (id obj)
319 // ivars are tacked onto the end of the object
320 return ((char *) obj) + ((struct objc_class *) obj->isa)->instance_size;
324 /***********************************************************************
325 * _internal_class_createInstanceFromZone. Allocate an instance of the
326 * specified class with the specified number of bytes for indexed
327 * variables, in the specified zone. The isa field is set to the
328 * class, all other fields are zeroed.
329 **********************************************************************/
330 static id _internal_class_createInstanceFromZone (Class aClass,
335 register unsigned byteCount;
337 // Can't create something for nothing
340 __objc_error ((id) aClass, _errAllocNil, 0);
344 // Allocate and initialize
345 byteCount = ((struct objc_class *) aClass)->instance_size + nIvarBytes;
346 obj = (id) malloc_zone_calloc (z, 1, byteCount);
349 __objc_error ((id) aClass, _errNoMem, ((struct objc_class *) aClass)->name, nIvarBytes);
353 // Set the isa pointer
358 /***********************************************************************
359 * _internal_class_createInstance. Allocate an instance of the specified
360 * class with the specified number of bytes for indexed variables, in
361 * the default zone, using _internal_class_createInstanceFromZone.
362 **********************************************************************/
363 static id _internal_class_createInstance (Class aClass,
366 return _internal_class_createInstanceFromZone (aClass,
368 malloc_default_zone ());
371 id (*_poseAs)() = (id (*)())class_poseAs;
372 id (*_alloc)(Class, unsigned) = _internal_class_createInstance;
373 id (*_zoneAlloc)(Class, unsigned, void *) = _internal_class_createInstanceFromZone;
375 /***********************************************************************
376 * class_createInstanceFromZone. Allocate an instance of the specified
377 * class with the specified number of bytes for indexed variables, in
378 * the specified zone, using _zoneAlloc.
379 **********************************************************************/
380 id class_createInstanceFromZone (Class aClass,
384 // _zoneAlloc can be overridden, but is initially set to
385 // _internal_class_createInstanceFromZone
386 return (*_zoneAlloc) (aClass, nIvarBytes, z);
389 /***********************************************************************
390 * class_createInstance. Allocate an instance of the specified class with
391 * the specified number of bytes for indexed variables, using _alloc.
392 **********************************************************************/
393 id class_createInstance (Class aClass,
396 // _alloc can be overridden, but is initially set to
397 // _internal_class_createInstance
398 return (*_alloc) (aClass, nIvarBytes);
401 /***********************************************************************
402 * class_setVersion. Record the specified version with the class.
403 **********************************************************************/
404 void class_setVersion (Class aClass,
407 ((struct objc_class *) aClass)->version = version;
410 /***********************************************************************
411 * class_getVersion. Return the version recorded with the class.
412 **********************************************************************/
413 int class_getVersion (Class aClass)
415 return ((struct objc_class *) aClass)->version;
418 static void _addListIMPsToTable(CFMutableDictionaryRef table, struct objc_method_list *mlist, Class cls, void **iterator) {
420 struct objc_method_list *new_mlist;
422 /* Work from end of list so that categories override */
423 new_mlist = _class_inlinedNextMethodList(cls, iterator);
424 _addListIMPsToTable(table, new_mlist, cls, iterator);
425 for (i = 0; i < mlist->method_count; i++) {
426 CFDictionarySetValue(table, mlist->method_list[i].method_name, mlist->method_list[i].method_imp);
430 static void _addClassIMPsToTable(CFMutableDictionaryRef table, Class cls) {
431 struct objc_method_list *mlist;
433 #ifdef INCLUDE_SUPER_IMPS_IN_IMP_TABLE
434 if (cls->super_class) { /* Do superclass first so subclass overrides */
435 CFMutableDictionaryRef super_table = CFDictionaryGetValue(_classIMPTables, cls->super_class);
438 const void **keys, **values, *buffer1[128], *buffer2[128];
439 cnt = CFDictionaryGetCount(super_table);
440 keys = (cnt <= 128) ? buffer1 : CFAllocatorAllocate(NULL, cnt * sizeof(void *), 0);
441 values = (cnt <= 128) ? buffer2 : CFAllocatorAllocate(NULL, cnt * sizeof(void *), 0);
442 CFDictionaryGetKeysAndValues(super_table, keys, values);
444 CFDictionarySetValue(table, keys[cnt], values[cnt]);
446 if (keys != buffer1) CFAllocatorDeallocate(NULL, keys);
447 if (values != buffer2) CFAllocatorDeallocate(NULL, values);
449 _addClassIMPsToTable(table, cls->super_class);
453 mlist = _class_inlinedNextMethodList(cls, &iterator);
454 _addListIMPsToTable(table, mlist, cls, &iterator);
457 CFMutableDictionaryRef _getClassIMPTable(Class cls) {
458 CFMutableDictionaryRef table;
459 if (NULL == _classIMPTables) {
460 // maps Classes to mutable dictionaries
461 _classIMPTables = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
463 table = (CFMutableDictionaryRef)CFDictionaryGetValue(_classIMPTables, cls);
464 // IMP table maps SELs to IMPS
466 table = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
467 _addClassIMPsToTable(table, cls);
468 CFDictionaryAddValue(_classIMPTables, cls, table);
473 static inline Method _findNamedMethodInList(struct objc_method_list * mlist, const char *meth_name) {
475 if (!mlist) return NULL;
476 for (i = 0; i < mlist->method_count; i++) {
477 Method m = &mlist->method_list[i];
478 if (*((const char *)m->method_name) == *meth_name && 0 == strcmp((const char *)(m->method_name), meth_name)) {
485 /* These next three functions are the heart of ObjC method lookup. */
486 static inline Method _findMethodInList(struct objc_method_list * mlist, SEL sel) {
488 if (!mlist) return NULL;
489 for (i = 0; i < mlist->method_count; i++) {
490 Method m = &mlist->method_list[i];
491 if (m->method_name == sel) {
498 static inline Method _findMethodInClass(Class cls, SEL sel) {
499 struct objc_method_list *mlist;
501 while ((mlist = _class_inlinedNextMethodList(cls, &iterator))) {
502 Method m = _findMethodInList(mlist, sel);
508 static inline Method _getMethod(Class cls, SEL sel) {
509 for (; cls; cls = cls->super_class) {
510 Method m = _findMethodInClass(cls, sel);
517 /***********************************************************************
518 * class_getInstanceMethod. Return the instance method for the
519 * specified class and selector.
520 **********************************************************************/
521 Method class_getInstanceMethod (Class aClass,
524 // Need both a class and a selector
525 if (!aClass || !aSelector)
529 return _getMethod (aClass, aSelector);
532 /***********************************************************************
533 * class_getClassMethod. Return the class method for the specified
534 * class and selector.
535 **********************************************************************/
536 Method class_getClassMethod (Class aClass,
539 // Need both a class and a selector
540 if (!aClass || !aSelector)
543 // Go to the class or isa
544 return _getMethod (GETMETA(aClass), aSelector);
547 /***********************************************************************
548 * class_getVariable. Return the named instance variable.
549 **********************************************************************/
550 static Ivar class_getVariable (Class cls,
553 struct objc_class * thisCls;
555 // Outer loop - search the class and its superclasses
556 for (thisCls = cls; thisCls != Nil; thisCls = ((struct objc_class *) thisCls)->super_class)
561 // Skip class having no ivars
565 // Inner loop - search the given class
566 thisIvar = &thisCls->ivars->ivar_list[0];
567 for (index = 0; index < thisCls->ivars->ivar_count; index += 1)
569 // Check this ivar's name. Be careful because the
570 // compiler generates ivar entries with NULL ivar_name
571 // (e.g. for anonymous bit fields).
572 if ((thisIvar->ivar_name) &&
573 (strcmp (name, thisIvar->ivar_name) == 0))
585 /***********************************************************************
586 * class_getInstanceVariable. Return the named instance variable.
588 * Someday add class_getClassVariable ().
589 **********************************************************************/
590 Ivar class_getInstanceVariable (Class aClass,
593 // Must have a class and a name
594 if (!aClass || !name)
598 return class_getVariable (aClass, name);
601 /***********************************************************************
602 * flush_caches. Flush the instance and optionally class method caches
603 * of cls and all its subclasses.
605 * Specifying Nil for the class "all classes."
606 **********************************************************************/
607 static void flush_caches (Class cls,
610 int numClasses = 0, newNumClasses;
611 struct objc_class * * classes = NULL;
613 struct objc_class * clsObject;
614 #ifdef OBJC_INSTRUMENTED
615 unsigned int classesVisited;
616 unsigned int subclassCount;
619 // Do nothing if class has no cache
620 if (cls && !((struct objc_class *) cls)->cache)
623 newNumClasses = objc_getClassList((Class *)NULL, 0);
624 while (numClasses < newNumClasses) {
625 numClasses = newNumClasses;
626 classes = realloc(classes, sizeof(Class) * numClasses);
627 newNumClasses = objc_getClassList((Class *)classes, numClasses);
629 numClasses = newNumClasses;
631 // Handle nil and root instance class specially: flush all
632 // instance and class method caches. Nice that this
633 // loop is linear vs the N-squared loop just below.
634 if (!cls || !((struct objc_class *) cls)->super_class)
636 #ifdef OBJC_INSTRUMENTED
637 LinearFlushCachesCount += 1;
641 // Traverse all classes in the hash table
642 for (i = 0; i < numClasses; i++)
644 struct objc_class * metaClsObject;
645 #ifdef OBJC_INSTRUMENTED
648 clsObject = classes[i];
650 // Skip class that is known not to be a subclass of this root
651 // (the isa pointer of any meta class points to the meta class
653 // NOTE: When is an isa pointer of a hash tabled class ever nil?
654 metaClsObject = ((struct objc_class *) clsObject)->isa;
655 if (cls && metaClsObject && (((struct objc_class *) metaClsObject)->isa != ((struct objc_class *) metaClsObject)->isa))
658 #ifdef OBJC_INSTRUMENTED
662 // Be careful of classes that do not yet have caches
663 if (((struct objc_class *) clsObject)->cache)
664 _cache_flush (clsObject);
665 if (flush_meta && metaClsObject && ((struct objc_class *) metaClsObject)->cache)
666 _cache_flush (((struct objc_class *) clsObject)->isa);
668 #ifdef OBJC_INSTRUMENTED
669 LinearFlushCachesVisitedCount += classesVisited;
670 if (classesVisited > MaxLinearFlushCachesVisitedCount)
671 MaxLinearFlushCachesVisitedCount = classesVisited;
672 IdealFlushCachesCount += subclassCount;
673 if (subclassCount > MaxIdealFlushCachesCount)
674 MaxIdealFlushCachesCount = subclassCount;
681 // Outer loop - flush any cache that could now get a method from
682 // cls (i.e. the cache associated with cls and any of its subclasses).
683 #ifdef OBJC_INSTRUMENTED
684 NonlinearFlushCachesCount += 1;
688 for (i = 0; i < numClasses; i++)
690 struct objc_class * clsIter;
692 #ifdef OBJC_INSTRUMENTED
693 NonlinearFlushCachesClassCount += 1;
695 clsObject = classes[i];
697 // Inner loop - Process a given class
702 #ifdef OBJC_INSTRUMENTED
705 // Flush clsObject instance method cache if
706 // clsObject is a subclass of cls, or is cls itself
707 // Flush the class method cache if that was asked for
710 #ifdef OBJC_INSTRUMENTED
713 _cache_flush (clsObject);
715 _cache_flush (clsObject->isa);
721 // Flush clsObject class method cache if cls is
722 // the meta class of clsObject or of one
723 // of clsObject's superclasses
724 else if (clsIter->isa == cls)
726 #ifdef OBJC_INSTRUMENTED
729 _cache_flush (clsObject->isa);
733 // Move up superclass chain
734 else if (ISINITIALIZED(clsIter))
735 clsIter = clsIter->super_class;
737 // clsIter is not initialized, so its cache
738 // must be empty. This happens only when
739 // clsIter == clsObject, because
740 // superclasses are initialized before
741 // subclasses, and this loop traverses
742 // from sub- to super- classes.
747 #ifdef OBJC_INSTRUMENTED
748 NonlinearFlushCachesVisitedCount += classesVisited;
749 if (classesVisited > MaxNonlinearFlushCachesVisitedCount)
750 MaxNonlinearFlushCachesVisitedCount = classesVisited;
751 IdealFlushCachesCount += subclassCount;
752 if (subclassCount > MaxIdealFlushCachesCount)
753 MaxIdealFlushCachesCount = subclassCount;
756 // Relinquish access to class hash table
760 /***********************************************************************
761 * _objc_flush_caches. Flush the caches of the specified class and any
762 * of its subclasses. If cls is a meta-class, only meta-class (i.e.
763 * class method) caches are flushed. If cls is an instance-class, both
764 * instance-class and meta-class caches are flushed.
765 **********************************************************************/
766 void _objc_flush_caches (Class cls)
768 flush_caches (cls, YES);
771 /***********************************************************************
772 * do_not_remove_this_dummy_function.
773 **********************************************************************/
774 void do_not_remove_this_dummy_function (void)
776 (void) class_nextMethodList (NULL, NULL);
779 /***********************************************************************
780 * class_nextMethodList.
783 * void * iterator = 0;
784 * while (class_nextMethodList (cls, &iterator)) {...}
785 **********************************************************************/
786 OBJC_EXPORT struct objc_method_list * class_nextMethodList (Class cls,
789 return _class_inlinedNextMethodList(cls, it);
792 /***********************************************************************
794 **********************************************************************/
797 (void) class_nextMethodList (Nil, NULL);
800 /***********************************************************************
803 * Formerly class_addInstanceMethods ()
804 **********************************************************************/
805 void class_addMethods (Class cls,
806 struct objc_method_list * meths)
808 // Insert atomically.
809 _objc_insertMethods (meths, &((struct objc_class *) cls)->methodLists);
811 // Must flush when dynamically adding methods. No need to flush
812 // all the class method caches. If cls is a meta class, though,
813 // this will still flush it and any of its sub-meta classes.
814 flush_caches (cls, NO);
817 /***********************************************************************
818 * class_addClassMethods.
820 * Obsolete (for binary compatibility only).
821 **********************************************************************/
822 void class_addClassMethods (Class cls,
823 struct objc_method_list * meths)
825 class_addMethods (((struct objc_class *) cls)->isa, meths);
828 /***********************************************************************
829 * class_removeMethods.
830 **********************************************************************/
831 void class_removeMethods (Class cls,
832 struct objc_method_list * meths)
834 // Remove atomically.
835 _objc_removeMethods (meths, &((struct objc_class *) cls)->methodLists);
837 // Must flush when dynamically removing methods. No need to flush
838 // all the class method caches. If cls is a meta class, though,
839 // this will still flush it and any of its sub-meta classes.
840 flush_caches (cls, NO);
843 /***********************************************************************
844 * addClassToOriginalClass. Add to a hash table of classes involved in
845 * a posing situation. We use this when we need to get to the "original"
846 * class for some particular name through the function objc_getOrigClass.
847 * For instance, the implementation of [super ...] will use this to be
848 * sure that it gets hold of the correct super class, so that no infinite
849 * loops will occur if the class it appears in is involved in posing.
851 * We use the classLock to guard the hash table.
853 * See tracker bug #51856.
854 **********************************************************************/
856 static NXMapTable * posed_class_hash = NULL;
857 static NXMapTable * posed_class_to_original_class_hash = NULL;
859 static void addClassToOriginalClass (Class posingClass,
862 // Install hash table when it is first needed
863 if (!posed_class_to_original_class_hash)
865 posed_class_to_original_class_hash =
866 NXCreateMapTableFromZone (NXPtrValueMapPrototype,
868 _objc_create_zone ());
871 // Add pose to hash table
872 NXMapInsert (posed_class_to_original_class_hash,
877 /***********************************************************************
878 * getOriginalClassForPosingClass.
879 **********************************************************************/
880 Class getOriginalClassForPosingClass (Class posingClass)
882 return NXMapGet (posed_class_to_original_class_hash, posingClass);
885 /***********************************************************************
887 **********************************************************************/
888 Class objc_getOrigClass (const char * name)
890 struct objc_class * ret;
892 // Look for class among the posers
894 OBJC_LOCK(&classLock);
895 if (posed_class_hash)
896 ret = (Class) NXMapGet (posed_class_hash, name);
897 OBJC_UNLOCK(&classLock);
901 // Not a poser. Do a normal lookup.
902 ret = objc_getClass (name);
904 _objc_inform ("class `%s' not linked into application", name);
909 /***********************************************************************
910 * _objc_addOrigClass. This function is only used from class_poseAs.
911 * Registers the original class names, before they get obscured by
912 * posing, so that [super ..] will work correctly from categories
913 * in posing classes and in categories in classes being posed for.
914 **********************************************************************/
915 static void _objc_addOrigClass (Class origClass)
917 OBJC_LOCK(&classLock);
919 // Create the poser's hash table on first use
920 if (!posed_class_hash)
922 posed_class_hash = NXCreateMapTableFromZone (NXStrValueMapPrototype,
924 _objc_create_zone ());
927 // Add the named class iff it is not already there (or collides?)
928 if (NXMapGet (posed_class_hash, ((struct objc_class *)origClass)->name) == 0)
929 NXMapInsert (posed_class_hash, ((struct objc_class *)origClass)->name, origClass);
931 OBJC_UNLOCK(&classLock);
934 /***********************************************************************
937 * !!! class_poseAs () does not currently flush any caches.
938 **********************************************************************/
939 Class class_poseAs (Class imposter,
942 struct objc_class * clsObject;
943 char imposterName[256];
944 char * imposterNamePtr;
945 NXHashTable * class_hash;
947 struct objc_class * copy;
948 #ifdef OBJC_CLASS_REFS
952 // Trivial case is easy
953 if (imposter == original)
956 // Imposter must be an immediate subclass of the original
957 if (((struct objc_class *)imposter)->super_class != original) {
959 __objc_error(imposter, _errNotSuper, ((struct objc_class *)imposter)->name, ((struct objc_class *)original)->name);
962 // Can't pose when you have instance variables (how could it work?)
963 if (((struct objc_class *)imposter)->ivars) {
965 __objc_error(imposter, _errNewVars, ((struct objc_class *)imposter)->name, ((struct objc_class *)original)->name, ((struct objc_class *)imposter)->name);
968 // Build a string to use to replace the name of the original class.
969 strcpy (imposterName, "_%");
970 strcat (imposterName, ((struct objc_class *)original)->name);
971 imposterNamePtr = objc_malloc (strlen (imposterName)+1);
972 strcpy (imposterNamePtr, imposterName);
974 // We lock the class hashtable, so we are thread safe with respect to
975 // calls to objc_getClass (). However, the class names are not
976 // changed atomically, nor are all of the subclasses updated
977 // atomically. I have ordered the operations so that you will
978 // never crash, but you may get inconsistent results....
980 // Register the original class so that [super ..] knows
981 // exactly which classes are the "original" classes.
982 _objc_addOrigClass (original);
983 _objc_addOrigClass (imposter);
985 OBJC_LOCK(&classLock);
987 class_hash = objc_getClasses ();
989 // Remove both the imposter and the original class.
990 NXHashRemove (class_hash, imposter);
991 NXHashRemove (class_hash, original);
993 // Copy the imposter, so that the imposter can continue
994 // its normal life in addition to changing the behavior of
995 // the original. As a hack we don't bother to copy the metaclass.
996 // For some reason we modify the original rather than the copy.
997 copy = (*_zoneAlloc)(imposter->isa, sizeof(struct objc_class), _objc_create_zone());
998 memmove(copy, imposter, sizeof(struct objc_class));
1000 NXHashInsert (class_hash, copy);
1001 addClassToOriginalClass (imposter, copy);
1003 // Mark the imposter as such
1004 CLS_SETINFO(((struct objc_class *)imposter), CLS_POSING);
1005 CLS_SETINFO(((struct objc_class *)imposter)->isa, CLS_POSING);
1007 // Change the name of the imposter to that of the original class.
1008 ((struct objc_class *)imposter)->name = ((struct objc_class *)original)->name;
1009 ((struct objc_class *)imposter)->isa->name = ((struct objc_class *)original)->isa->name;
1011 // Also copy the version field to avoid archiving problems.
1012 ((struct objc_class *)imposter)->version = ((struct objc_class *)original)->version;
1014 // Change all subclasses of the original to point to the imposter.
1015 state = NXInitHashState (class_hash);
1016 while (NXNextHashState (class_hash, &state, (void **) &clsObject))
1018 while ((clsObject) && (clsObject != imposter) &&
1019 (clsObject != copy))
1021 if (clsObject->super_class == original)
1023 clsObject->super_class = imposter;
1024 clsObject->isa->super_class = ((struct objc_class *)imposter)->isa;
1025 // We must flush caches here!
1029 clsObject = clsObject->super_class;
1033 #ifdef OBJC_CLASS_REFS
1034 // Replace the original with the imposter in all class refs
1035 // Major loop - process all headers
1036 for (hInfo = _objc_headerStart(); hInfo != NULL; hInfo = hInfo->next)
1039 unsigned int refCount;
1042 // Get refs associated with this header
1043 cls_refs = (Class *) _getObjcClassRefs ((headerType *) hInfo->mhdr, &refCount);
1044 if (!cls_refs || !refCount)
1047 // Minor loop - process this header's refs
1048 cls_refs = (Class *) ((unsigned long) cls_refs + hInfo->image_slide);
1049 for (index = 0; index < refCount; index += 1)
1051 if (cls_refs[index] == original)
1052 cls_refs[index] = imposter;
1055 #endif // OBJC_CLASS_REFS
1057 // Change the name of the original class.
1058 ((struct objc_class *)original)->name = imposterNamePtr + 1;
1059 ((struct objc_class *)original)->isa->name = imposterNamePtr;
1061 // Restore the imposter and the original class with their new names.
1062 NXHashInsert (class_hash, imposter);
1063 NXHashInsert (class_hash, original);
1065 OBJC_UNLOCK(&classLock);
1070 /***********************************************************************
1072 **********************************************************************/
1073 static void _freedHandler (id self,
1076 __objc_error (self, _errFreedObject, SELNAME(sel), self);
1079 /***********************************************************************
1080 * _nonexistentHandler.
1081 **********************************************************************/
1082 static void _nonexistentHandler (id self,
1085 __objc_error (self, _errNonExistentObject, SELNAME(sel), self);
1088 /***********************************************************************
1089 * class_initialize. Send the '+initialize' message on demand to any
1090 * uninitialized class. Force initialization of superclasses first.
1092 * Called only from _class_lookupMethodAndLoadCache (or itself).
1094 * #ifdef OBJC_COLLECTING_CACHE
1095 * The messageLock can be in either state.
1097 * The messageLock is already assumed to be taken out.
1098 * It is temporarily released while the initialize method is sent.
1100 **********************************************************************/
1101 static void class_initialize (Class clsDesc)
1103 struct objc_class * super;
1105 // Skip if someone else beat us to it
1106 if (ISINITIALIZED(((struct objc_class *)clsDesc)))
1109 // Force initialization of superclasses first
1110 super = ((struct objc_class *)clsDesc)->super_class;
1111 if ((super != Nil) && (!ISINITIALIZED(super)))
1112 class_initialize (super);
1114 // Initializing the super class might have initialized us,
1115 // or another thread might have initialized us during this time.
1116 if (ISINITIALIZED(((struct objc_class *)clsDesc)))
1120 // bind the module in - if it came from a bundle or dynamic library
1121 if (((struct objc_class *)clsDesc)->info & CLS_NEED_BIND) {
1122 ((struct objc_class *)clsDesc)->info &= ~CLS_NEED_BIND;
1123 _objc_bindModuleContainingClass(clsDesc);
1126 // by loading things we might get initialized (maybe) ((paranoia))
1127 if (ISINITIALIZED(((struct objc_class *)clsDesc)))
1130 // chain on the categories and bind them if necessary
1131 _objc_resolve_categories_for_class(clsDesc);
1133 // by loading things we might get initialized (maybe) ((paranoia))
1134 if (ISINITIALIZED(((struct objc_class *)clsDesc)))
1137 // Mark the class initialized so it can receive the "initialize"
1138 // message. This solution to the catch-22 is the source of a
1139 // bug: the class is able to receive messages *from anyone* now
1140 // that it is marked, even though initialization is not complete.
1142 MARKINITIALIZED(((struct objc_class *)clsDesc));
1143 // But the simple solution is to ask if this class itself implements
1144 // initialize (!) and only send it then!!
1146 #ifndef OBJC_COLLECTING_CACHE
1147 // Release the message lock so that messages can be sent.
1148 OBJC_UNLOCK(&messageLock);
1151 // Send the initialize method.
1152 // Of course, if this class doesn't implement initialize but
1153 // the super class does, we send initialize to the super class
1155 [(id)clsDesc initialize];
1157 #ifndef OBJC_COLLECTING_CACHE
1158 // Re-acquire the lock
1159 OBJC_LOCK(&messageLock);
1165 /***********************************************************************
1166 * _class_install_relationships. Fill in the class pointers of a class
1167 * that was loaded before some or all of the classes it needs to point to.
1168 * The deal here is that the class pointer fields have been usurped to
1169 * hold the string name of the pertinent class. Our job is to look up
1170 * the real thing based on those stored names.
1171 **********************************************************************/
1172 void _class_install_relationships (Class cls,
1175 struct objc_class * meta;
1176 struct objc_class * clstmp;
1178 // Get easy access to meta class structure
1179 meta = ((struct objc_class *)cls)->isa;
1181 // Set version in meta class strucure
1182 meta->version = version;
1184 // Install superclass based on stored name. No name iff
1185 // cls is a root class.
1186 if (((struct objc_class *)cls)->super_class)
1188 clstmp = objc_getClass ((const char *) ((struct objc_class *)cls)->super_class);
1191 _objc_inform("failed objc_getClass(%s) for %s->super_class", (const char *)((struct objc_class *)cls)->super_class, ((struct objc_class *)cls)->name);
1195 ((struct objc_class *)cls)->super_class = clstmp;
1198 // Install meta's isa based on stored name. Meta class isa
1199 // pointers always point to the meta class of the root class
1200 // (root meta class, too, it points to itself!).
1201 clstmp = objc_getClass ((const char *) meta->isa);
1204 _objc_inform("failed objc_getClass(%s) for %s->isa->isa", (const char *) meta->isa, ((struct objc_class *)cls)->name);
1208 meta->isa = clstmp->isa;
1210 // Install meta's superclass based on stored name. No name iff
1211 // cls is a root class.
1212 if (meta->super_class)
1214 // Locate instance class of super class
1215 clstmp = objc_getClass ((const char *) meta->super_class);
1218 _objc_inform("failed objc_getClass(%s) for %s->isa->super_class", (const char *)meta->super_class, ((struct objc_class *)cls)->name);
1222 // Store meta class of super class
1223 meta->super_class = clstmp->isa;
1226 // cls is root, so `tie' the (root) meta class down to its
1227 // instance class. This way, class methods can come from
1228 // the root instance class.
1230 ((struct objc_class *)meta)->super_class = cls;
1232 // Use common static empty cache instead of NULL
1233 if (((struct objc_class *)cls)->cache == NULL)
1234 ((struct objc_class *)cls)->cache = (Cache) &emptyCache;
1235 if (((struct objc_class *)meta)->cache == NULL)
1236 ((struct objc_class *)meta)->cache = (Cache) &emptyCache;
1241 _objc_fatal ("please link appropriate classes in your program");
1244 /***********************************************************************
1246 **********************************************************************/
1247 static void * objc_malloc (int byteCount)
1251 space = malloc_zone_malloc (_objc_create_zone (), byteCount);
1252 if (!space && byteCount)
1253 _objc_fatal ("unable to allocate space");
1259 /***********************************************************************
1260 * class_respondsToMethod.
1262 * Called from -[Object respondsTo:] and +[Object instancesRespondTo:]
1263 **********************************************************************/
1264 BOOL class_respondsToMethod (Class cls,
1267 struct objc_class * thisCls;
1273 // No one responds to zero!
1277 // Synchronize access to caches
1278 OBJC_LOCK(&messageLock);
1280 // Look in the cache of the specified class
1281 mask = ((struct objc_class *)cls)->cache->mask;
1282 buckets = ((struct objc_class *)cls)->cache->buckets;
1283 index = ((uarith_t) sel & mask);
1284 while (CACHE_BUCKET_VALID(buckets[index])) {
1285 if (CACHE_BUCKET_NAME(buckets[index]) == sel) {
1286 if (CACHE_BUCKET_IMP(buckets[index]) == &_objc_msgForward) {
1287 OBJC_UNLOCK(&messageLock);
1290 OBJC_UNLOCK(&messageLock);
1299 // Handle cache miss
1300 meth = _getMethod(cls, sel);
1302 OBJC_UNLOCK(&messageLock);
1303 _cache_fill (cls, meth, sel);
1307 // Not implememted. Use _objc_msgForward.
1311 smt = malloc_zone_malloc (_objc_create_zone(), sizeof(struct objc_method));
1312 smt->method_name = sel;
1313 smt->method_types = "";
1314 smt->method_imp = &_objc_msgForward;
1315 _cache_fill (cls, smt, sel);
1318 OBJC_UNLOCK(&messageLock);
1324 /***********************************************************************
1325 * class_lookupMethod.
1327 * Called from -[Object methodFor:] and +[Object instanceMethodFor:]
1328 **********************************************************************/
1330 IMP class_lookupMethod (Class cls,
1338 // No one responds to zero!
1341 __objc_error(cls, _errBadSel, sel);
1344 // Synchronize access to caches
1345 OBJC_LOCK(&messageLock);
1348 mask = ((struct objc_class *)cls)->cache->mask;
1349 buckets = ((struct objc_class *)cls)->cache->buckets;
1350 index = ((unsigned int) sel & mask);
1351 while (CACHE_BUCKET_VALID(buckets[index]))
1353 if (CACHE_BUCKET_NAME(buckets[index]) == sel)
1355 result = CACHE_BUCKET_IMP(buckets[index]);
1356 OBJC_UNLOCK(&messageLock);
1364 // Handle cache miss
1365 result = _class_lookupMethodAndLoadCache (cls, sel);
1366 OBJC_UNLOCK(&messageLock);
1370 /***********************************************************************
1371 * class_lookupMethodInMethodList.
1373 * Called from objc-load.m and _objc_callLoads ()
1374 **********************************************************************/
1375 IMP class_lookupMethodInMethodList (struct objc_method_list * mlist,
1378 Method m = _findMethodInList(mlist, sel);
1379 return (m ? m->method_imp : NULL);
1382 IMP class_lookupNamedMethodInMethodList(struct objc_method_list *mlist,
1383 const char *meth_name)
1385 Method m = meth_name ? _findNamedMethodInList(mlist, meth_name) : NULL;
1386 return (m ? m->method_imp : NULL);
1389 /***********************************************************************
1392 * Called from _cache_expand () and objc_addClass ()
1393 **********************************************************************/
1394 Cache _cache_create (Class cls)
1400 // Select appropriate size
1401 slotCount = (ISMETA(cls)) ? INIT_META_CACHE_SIZE : INIT_CACHE_SIZE;
1403 // Allocate table (why not check for failure?)
1404 #ifdef OBJC_INSTRUMENTED
1405 new_cache = malloc_zone_malloc (_objc_create_zone(),
1406 sizeof(struct objc_cache) + TABLE_SIZE(slotCount)
1407 + sizeof(CacheInstrumentation));
1409 new_cache = malloc_zone_malloc (_objc_create_zone(),
1410 sizeof(struct objc_cache) + TABLE_SIZE(slotCount));
1413 // Invalidate all the buckets
1414 for (index = 0; index < slotCount; index += 1)
1415 CACHE_BUCKET_VALID(new_cache->buckets[index]) = NULL;
1417 // Zero the valid-entry counter
1418 new_cache->occupied = 0;
1420 // Set the mask so indexing wraps at the end-of-table
1421 new_cache->mask = slotCount - 1;
1423 #ifdef OBJC_INSTRUMENTED
1425 CacheInstrumentation * cacheData;
1427 // Zero out the cache dynamic instrumention data
1428 cacheData = CACHE_INSTRUMENTATION(new_cache);
1429 bzero ((char *) cacheData, sizeof(CacheInstrumentation));
1433 // Install the cache
1434 ((struct objc_class *)cls)->cache = new_cache;
1436 // Clear the cache flush flag so that we will not flush this cache
1437 // before expanding it for the first time.
1438 ((struct objc_class * )cls)->info &= ~(CLS_FLUSH_CACHE);
1440 // Clear the grow flag so that we will re-use the current storage,
1441 // rather than actually grow the cache, when expanding the cache
1442 // for the first time
1443 if (_class_slow_grow)
1444 ((struct objc_class * )cls)->info &= ~(CLS_GROW_CACHE);
1446 // Return our creation
1450 /***********************************************************************
1453 * #ifdef OBJC_COLLECTING_CACHE
1454 * The cacheUpdateLock is assumed to be taken at this point.
1457 * Called from _cache_fill ()
1458 **********************************************************************/
1459 static Cache _cache_expand (Class cls)
1463 unsigned int slotCount;
1466 // First growth goes from emptyCache to a real one
1467 old_cache = ((struct objc_class *)cls)->cache;
1468 if (old_cache == &emptyCache)
1469 return _cache_create (cls);
1471 // iff _class_slow_grow, trade off actual cache growth with re-using
1472 // the current one, so that growth only happens every odd time
1473 if (_class_slow_grow)
1475 // CLS_GROW_CACHE controls every-other-time behavior. If it
1476 // is non-zero, let the cache grow this time, but clear the
1477 // flag so the cache is reused next time
1478 if ((((struct objc_class * )cls)->info & CLS_GROW_CACHE) != 0)
1479 ((struct objc_class * )cls)->info &= ~CLS_GROW_CACHE;
1481 // Reuse the current cache storage this time
1484 // Clear the valid-entry counter
1485 old_cache->occupied = 0;
1487 // Invalidate all the cache entries
1488 for (index = 0; index < old_cache->mask + 1; index += 1)
1490 // Remember what this entry was, so we can possibly
1491 // deallocate it after the bucket has been invalidated
1492 Method oldEntry = old_cache->buckets[index];
1493 // Skip invalid entry
1494 if (!CACHE_BUCKET_VALID(old_cache->buckets[index]))
1497 // Invalidate this entry
1498 CACHE_BUCKET_VALID(old_cache->buckets[index]) = NULL;
1500 // Deallocate "forward::" entry
1501 if (CACHE_BUCKET_IMP(oldEntry) == &_objc_msgForward)
1503 #ifdef OBJC_COLLECTING_CACHE
1504 _cache_collect_free (oldEntry, NO);
1506 malloc_zone_free (_objc_create_zone(), oldEntry);
1511 // Set the slow growth flag so the cache is next grown
1512 ((struct objc_class * )cls)->info |= CLS_GROW_CACHE;
1514 // Return the same old cache, freshly emptied
1520 // Double the cache size
1521 slotCount = (old_cache->mask + 1) << 1;
1523 // Allocate a new cache table
1524 #ifdef OBJC_INSTRUMENTED
1525 new_cache = malloc_zone_malloc (_objc_create_zone(),
1526 sizeof(struct objc_cache) + TABLE_SIZE(slotCount)
1527 + sizeof(CacheInstrumentation));
1529 new_cache = malloc_zone_malloc (_objc_create_zone(),
1530 sizeof(struct objc_cache) + TABLE_SIZE(slotCount));
1533 // Zero out the new cache
1534 new_cache->mask = slotCount - 1;
1535 new_cache->occupied = 0;
1536 for (index = 0; index < slotCount; index += 1)
1537 CACHE_BUCKET_VALID(new_cache->buckets[index]) = NULL;
1539 #ifdef OBJC_INSTRUMENTED
1540 // Propagate the instrumentation data
1542 CacheInstrumentation * oldCacheData;
1543 CacheInstrumentation * newCacheData;
1545 oldCacheData = CACHE_INSTRUMENTATION(old_cache);
1546 newCacheData = CACHE_INSTRUMENTATION(new_cache);
1547 bcopy ((const char *)oldCacheData, (char *)newCacheData, sizeof(CacheInstrumentation));
1551 // iff _class_uncache, copy old cache entries into the new cache
1552 if (_class_uncache == 0)
1556 newMask = new_cache->mask;
1558 // Look at all entries in the old cache
1559 for (index = 0; index < old_cache->mask + 1; index += 1)
1563 // Skip invalid entry
1564 if (!CACHE_BUCKET_VALID(old_cache->buckets[index]))
1567 // Hash the old entry into the new table
1568 index2 = ((unsigned int) CACHE_BUCKET_NAME(old_cache->buckets[index]) & newMask);
1570 // Find an available spot, at or following the hashed spot;
1571 // Guaranteed to not infinite loop, because table has grown
1574 if (!CACHE_BUCKET_VALID(new_cache->buckets[index2]))
1576 new_cache->buckets[index2] = old_cache->buckets[index];
1584 // Account for the addition
1585 new_cache->occupied += 1;
1588 // Set the cache flush flag so that we will flush this cache
1589 // before expanding it again.
1590 ((struct objc_class * )cls)->info |= CLS_FLUSH_CACHE;
1593 // Deallocate "forward::" entries from the old cache
1596 for (index = 0; index < old_cache->mask + 1; index += 1)
1598 if (CACHE_BUCKET_VALID(old_cache->buckets[index]) &&
1599 CACHE_BUCKET_IMP(old_cache->buckets[index]) == &_objc_msgForward)
1601 #ifdef OBJC_COLLECTING_CACHE
1602 _cache_collect_free (old_cache->buckets[index], NO);
1604 malloc_zone_free (_objc_create_zone(), old_cache->buckets[index]);
1610 // Install new cache
1611 ((struct objc_class *)cls)->cache = new_cache;
1613 // Deallocate old cache, try freeing all the garbage
1614 #ifdef OBJC_COLLECTING_CACHE
1615 _cache_collect_free (old_cache, YES);
1617 malloc_zone_free (_objc_create_zone(), old_cache);
1622 /***********************************************************************
1623 * instrumentObjcMessageSends/logObjcMessageSends.
1624 **********************************************************************/
1625 static int LogObjCMessageSend (BOOL isClassMethod,
1626 const char * objectsClass,
1627 const char * implementingClass,
1632 // Create/open the log file
1633 if (objcMsgLogFD == (-1))
1635 sprintf (buf, "/tmp/msgSends-%d", (int) getpid ());
1636 objcMsgLogFD = open (buf, O_WRONLY | O_CREAT, 0666);
1639 // Make the log entry
1640 sprintf(buf, "%c %s %s %s\n",
1641 isClassMethod ? '+' : '-',
1646 write (objcMsgLogFD, buf, strlen(buf));
1648 // Tell caller to not cache the method
1652 void instrumentObjcMessageSends (BOOL flag)
1654 int enabledValue = (flag) ? 1 : 0;
1657 if (objcMsgLogEnabled == enabledValue)
1660 // If enabling, flush all method caches so we get some traces
1662 flush_caches (Nil, YES);
1664 // Sync our log file
1665 if (objcMsgLogFD != (-1))
1666 fsync (objcMsgLogFD);
1668 objcMsgLogEnabled = enabledValue;
1671 void logObjcMessageSends (ObjCLogProc logProc)
1675 objcMsgLogProc = logProc;
1676 objcMsgLogEnabled = 1;
1680 objcMsgLogProc = logProc;
1681 objcMsgLogEnabled = 0;
1684 if (objcMsgLogFD != (-1))
1685 fsync (objcMsgLogFD);
1688 /***********************************************************************
1689 * _cache_fill. Add the specified method to the specified class' cache.
1691 * Called only from _class_lookupMethodAndLoadCache and
1692 * class_respondsToMethod.
1694 * #ifdef OBJC_COLLECTING_CACHE
1695 * It doesn't matter if someone has the messageLock when we enter this
1696 * function. This function will fail to do the update if someone else
1697 * is already updating the cache, i.e. they have the cacheUpdateLock.
1699 * The messageLock is already assumed to be taken out.
1701 **********************************************************************/
1703 static void _cache_fill (Class cls,
1712 unsigned int newOccupied;
1714 // Keep tally of cache additions
1715 totalCacheFills += 1;
1717 #ifdef OBJC_COLLECTING_CACHE
1718 // Make sure only one thread is updating the cache at a time, but don't
1719 // wait for concurrent updater to finish, because it might be a while, or
1720 // a deadlock! Instead, just leave the method out of the cache until
1721 // next time. This is nasty given that cacheUpdateLock is per task!
1722 if (!OBJC_TRYLOCK(&cacheUpdateLock))
1725 // Set up invariants for cache traversals
1726 cache = ((struct objc_class *)cls)->cache;
1728 buckets = cache->buckets;
1730 // Check for duplicate entries, if we're in the mode
1731 if (traceDuplicates)
1736 for (index2 = 0; index2 < mask + 1; index2 += 1)
1738 // Skip invalid or non-duplicate entry
1739 if ((!CACHE_BUCKET_VALID(buckets[index2])) ||
1740 (strcmp ((char *) CACHE_BUCKET_NAME(buckets[index2]), (char *) smt->method_name) != 0))
1743 // Tally duplication, but report iff wanted
1744 cacheFillDuplicates += 1;
1745 if (traceDuplicatesVerbose)
1747 _objc_inform ("Cache fill duplicate #%d: found %x adding %x: %s\n",
1748 cacheFillDuplicates,
1749 (unsigned int) CACHE_BUCKET_NAME(buckets[index2]),
1750 (unsigned int) smt->method_name,
1751 (char *) smt->method_name);
1756 // Do nothing if entry is already placed. This re-check is needed
1757 // only in the OBJC_COLLECTING_CACHE code, because the probe is
1759 index = ((unsigned int) sel & mask);
1760 while (CACHE_BUCKET_VALID(buckets[index]))
1762 if (CACHE_BUCKET_NAME(buckets[index]) == sel)
1764 OBJC_UNLOCK(&cacheUpdateLock);
1772 #else // not OBJC_COLLECTING_CACHE
1773 cache = ((struct objc_class *)cls)->cache;
1777 // Use the cache as-is if it is less than 3/4 full
1778 newOccupied = cache->occupied + 1;
1779 if ((newOccupied * 4) <= (mask + 1) * 3)
1780 cache->occupied = newOccupied;
1782 // Cache is getting full
1786 if ((((struct objc_class * )cls)->info & CLS_FLUSH_CACHE) != 0)
1792 cache = _cache_expand (cls);
1796 // Account for the addition
1797 cache->occupied += 1;
1800 // Insert the new entry. This can be done by either:
1801 // (a) Scanning for the first unused spot. Easy!
1802 // (b) Opening up an unused spot by sliding existing
1803 // entries down by one. The benefit of this
1804 // extra work is that it puts the most recently
1805 // loaded entries closest to where the selector
1806 // hash starts the search.
1808 // The loop is a little more complicated because there
1809 // are two kinds of entries, so there have to be two ways
1811 buckets = cache->buckets;
1812 index = ((unsigned int) sel & mask);
1815 // Slide existing entries down by one
1818 // Copy current entry to a local
1819 saveMethod = buckets[index];
1821 // Copy previous entry (or new entry) to current slot
1822 buckets[index] = smt;
1824 // Done if current slot had been invalid
1825 if (saveMethod == NULL)
1828 // Prepare to copy saved value into next slot
1831 // Move on to next slot
1836 #ifdef OBJC_COLLECTING_CACHE
1837 OBJC_UNLOCK(&cacheUpdateLock);
1841 /***********************************************************************
1842 * _cache_flush. Invalidate all valid entries in the given class' cache,
1843 * and clear the CLS_FLUSH_CACHE in the cls->info.
1845 * Called from flush_caches ().
1846 **********************************************************************/
1847 static void _cache_flush (Class cls)
1852 // Locate cache. Ignore unused cache.
1853 cache = ((struct objc_class *)cls)->cache;
1854 if (cache == &emptyCache)
1857 #ifdef OBJC_INSTRUMENTED
1859 CacheInstrumentation * cacheData;
1862 cacheData = CACHE_INSTRUMENTATION(cache);
1863 cacheData->flushCount += 1;
1864 cacheData->flushedEntries += cache->occupied;
1865 if (cache->occupied > cacheData->maxFlushedEntries)
1866 cacheData->maxFlushedEntries = cache->occupied;
1870 // Traverse the cache
1871 for (index = 0; index <= cache->mask; index += 1)
1873 // Remember what this entry was, so we can possibly
1874 // deallocate it after the bucket has been invalidated
1875 Method oldEntry = cache->buckets[index];
1877 // Invalidate this entry
1878 CACHE_BUCKET_VALID(cache->buckets[index]) = NULL;
1880 // Deallocate "forward::" entry
1881 if (oldEntry && oldEntry->method_imp == &_objc_msgForward)
1882 #ifdef OBJC_COLLECTING_CACHE
1883 _cache_collect_free (oldEntry, NO);
1885 malloc_zone_free (_objc_create_zone(), oldEntry);
1889 // Clear the valid-entry counter
1890 cache->occupied = 0;
1892 // Clear the cache flush flag so that we will not flush this cache
1893 // before expanding it again.
1894 ((struct objc_class * )cls)->info &= ~CLS_FLUSH_CACHE;
1897 /***********************************************************************
1898 * _objc_getFreedObjectClass. Return a pointer to the dummy freed
1899 * object class. Freed objects get their isa pointers replaced with
1900 * a pointer to the freedObjectClass, so that we can catch usages of
1902 **********************************************************************/
1903 Class _objc_getFreedObjectClass (void)
1905 return (Class) &freedObjectClass;
1908 /***********************************************************************
1909 * _objc_getNonexistentClass. Return a pointer to the dummy nonexistent
1910 * object class. This is used when, for example, mapping the class
1911 * refs for an image, and the class can not be found, so that we can
1912 * catch later uses of the non-existent class.
1913 **********************************************************************/
1914 Class _objc_getNonexistentClass (void)
1916 return (Class) &nonexistentObjectClass;
1919 /***********************************************************************
1920 * _class_lookupMethodAndLoadCache.
1922 * Called only from objc_msgSend, objc_msgSendSuper and class_lookupMethod.
1923 **********************************************************************/
1924 IMP _class_lookupMethodAndLoadCache (Class cls,
1927 struct objc_class * curClass;
1929 BOOL calledSingleThreaded;
1932 trace(0xb300, 0, 0, 0);
1934 // Check for freed class
1935 if (cls == &freedObjectClass)
1936 return (IMP) _freedHandler;
1938 // Check for nonexistent class
1939 if (cls == &nonexistentObjectClass)
1940 return (IMP) _nonexistentHandler;
1942 #ifndef OBJC_COLLECTING_CACHE
1943 // Control can get here via the single-threaded message dispatcher,
1944 // but class_initialize can cause application to go multithreaded. Notice
1945 // whether this is the case, so we can leave the messageLock unlocked
1946 // on the way out, just as the single-threaded message dispatcher
1947 // expects. Note that the messageLock locking in classinitialize is
1948 // appropriate in this case, because there are more than one thread now.
1949 calledSingleThreaded = (_objc_multithread_mask != 0);
1952 trace(0xb301, 0, 0, 0);
1954 // Lazy initialization. This unlocks and relocks messageLock,
1955 // so cache information we might already have becomes invalid.
1956 if (!ISINITIALIZED(cls))
1957 class_initialize (objc_getClass (((struct objc_class *)cls)->name));
1959 trace(0xb302, 0, 0, 0);
1961 // Outer loop - search the caches and method lists of the
1962 // class and its super-classes
1964 for (curClass = cls; curClass; curClass = ((struct objc_class * )curClass)->super_class)
1969 arith_t methodCount;
1970 struct objc_method_list *mlist;
1972 #ifdef PRELOAD_SUPERCLASS_CACHES
1973 struct objc_class * curClass2;
1976 trace(0xb303, 0, 0, 0);
1978 mask = curClass->cache->mask;
1979 buckets = curClass->cache->buckets;
1981 // Minor loop #1 - check cache of given class
1982 for (idx = ((uarith_t) sel & mask);
1983 CACHE_BUCKET_VALID(buckets[idx]);
1984 idx = (++idx & mask))
1986 // Skip entries until selector matches
1987 if (CACHE_BUCKET_NAME(buckets[idx]) != sel)
1990 // Found the method. Add it to the cache(s)
1991 // unless it was found in the cache of the
1992 // class originally being messaged.
1994 // NOTE: The method is usually not found
1995 // the original class' cache, because
1996 // objc_msgSend () has already looked.
1997 // BUT, if sending this method resulted in
1998 // a +initialize on the class, and +initialize
1999 // sends the same method, the method will
2000 // indeed now be in the cache. Calling
2001 // _cache_fill with a buckets[idx] from the
2002 // cache being filled results in a crash
2003 // if the cache has to grow, because the
2004 // buckets[idx] address is no longer valid.
2005 if (curClass != cls)
2007 #ifdef PRELOAD_SUPERCLASS_CACHES
2008 for (curClass2 = cls; curClass2 != curClass; curClass2 = curClass2->super_class)
2009 _cache_fill (curClass2, buckets[idx], sel);
2010 _cache_fill (curClass, buckets[idx], sel);
2012 _cache_fill (cls, buckets[idx], sel);
2016 // Return the implementation address
2017 methodPC = CACHE_BUCKET_IMP(buckets[idx]);
2021 trace(0xb304, (int)methodPC, 0, 0);
2023 // Done if that found it
2027 smt = _findMethodInClass(curClass, sel);
2030 // If logging is enabled, log the message send and let
2031 // the logger decide whether to encache the method.
2032 if ((objcMsgLogEnabled == 0) ||
2033 (objcMsgLogProc (CLS_GETINFO(((struct objc_class * )curClass),CLS_META) ? YES : NO,
2034 ((struct objc_class *)cls)->name,
2035 curClass->name, sel)))
2037 // Cache the method implementation
2038 #ifdef PRELOAD_SUPERCLASS_CACHES
2039 for (curClass2 = cls; curClass2 != curClass; curClass2 = curClass2->super_class)
2040 _cache_fill (curClass2, smt, sel);
2041 _cache_fill (curClass, smt, sel);
2043 _cache_fill (cls, smt, sel);
2046 // Return the implementation
2047 methodPC = smt->method_imp;
2050 trace(0xb305, (int)methodPC, 0, 0);
2052 // Done if that found it
2057 trace(0xb306, (int)methodPC, 0, 0);
2059 if (methodPC == NULL)
2061 // Class and superclasses do not respond -- use forwarding
2062 smt = malloc_zone_malloc (_objc_create_zone(), sizeof(struct objc_method));
2063 smt->method_name = sel;
2064 smt->method_types = "";
2065 smt->method_imp = &_objc_msgForward;
2066 _cache_fill (cls, smt, sel);
2067 methodPC = &_objc_msgForward;
2070 #ifndef OBJC_COLLECTING_CACHE
2072 if (calledSingleThreaded)
2073 OBJC_UNLOCK(&messageLock);
2076 trace(0xb30f, (int)methodPC, 0, 0);
2081 /***********************************************************************
2085 **********************************************************************/
2086 static int SubtypeUntil (const char * type,
2090 const char * head = type;
2095 if (!*type || (!level && (*type == end)))
2096 return (int)(type - head);
2100 case ']': case '}': case ')': level--; break;
2101 case '[': case '{': case '(': level += 1; break;
2107 _objc_fatal ("Object: SubtypeUntil: end of type encountered prematurely\n");
2111 /***********************************************************************
2113 **********************************************************************/
2114 static const char * SkipFirstType (const char * type)
2120 case 'O': /* bycopy */
2123 case 'N': /* inout */
2124 case 'r': /* const */
2125 case 'V': /* oneway */
2126 case '^': /* pointers */
2131 while ((*type >= '0') && (*type <= '9'))
2133 return type + SubtypeUntil (type, ']') + 1;
2137 return type + SubtypeUntil (type, '}') + 1;
2141 return type + SubtypeUntil (type, ')') + 1;
2150 /***********************************************************************
2151 * method_getNumberOfArguments.
2152 **********************************************************************/
2153 unsigned method_getNumberOfArguments (Method method)
2155 const char * typedesc;
2158 // First, skip the return type
2159 typedesc = method->method_types;
2160 typedesc = SkipFirstType (typedesc);
2162 // Next, skip stack size
2163 while ((*typedesc >= '0') && (*typedesc <= '9'))
2166 // Now, we have the arguments - count how many
2170 // Traverse argument type
2171 typedesc = SkipFirstType (typedesc);
2173 // Traverse (possibly negative) argument offset
2174 if (*typedesc == '-')
2176 while ((*typedesc >= '0') && (*typedesc <= '9'))
2179 // Made it past an argument
2186 /***********************************************************************
2187 * method_getSizeOfArguments.
2188 **********************************************************************/
2190 unsigned method_getSizeOfArguments (Method method)
2192 const char * typedesc;
2193 unsigned stack_size;
2194 #if defined(__ppc__) || defined(ppc)
2195 unsigned trueBaseOffset;
2196 unsigned foundBaseOffset;
2199 // Get our starting points
2201 typedesc = method->method_types;
2203 // Skip the return type
2204 #if defined (__ppc__) || defined(ppc)
2205 // Struct returns cause the parameters to be bumped
2206 // by a register, so the offset to the receiver is
2207 // 4 instead of the normal 0.
2208 trueBaseOffset = (*typedesc == '{') ? 4 : 0;
2210 typedesc = SkipFirstType (typedesc);
2212 // Convert ASCII number string to integer
2213 while ((*typedesc >= '0') && (*typedesc <= '9'))
2214 stack_size = (stack_size * 10) + (*typedesc++ - '0');
2215 #if defined (__ppc__) || defined(ppc)
2216 // NOTE: This is a temporary measure pending a compiler fix.
2217 // Work around PowerPC compiler bug wherein the method argument
2218 // string contains an incorrect value for the "stack size."
2219 // Generally, the size is reported 4 bytes too small, so we apply
2220 // that fudge factor. Unfortunately, there is at least one case
2221 // where the error is something other than -4: when the last
2222 // parameter is a double, the reported stack is much too high
2223 // (about 32 bytes). We do not attempt to detect that case.
2224 // The result of returning a too-high value is that objc_msgSendv
2225 // can bus error if the destination of the marg_list copying
2226 // butts up against excluded memory.
2227 // This fix disables itself when it sees a correctly built
2228 // type string (i.e. the offset for the Id is correct). This
2229 // keeps us out of lockstep with the compiler.
2231 // skip the '@' marking the Id field
2232 typedesc = SkipFirstType (typedesc);
2234 // pick up the offset for the Id field
2235 foundBaseOffset = 0;
2236 while ((*typedesc >= '0') && (*typedesc <= '9'))
2237 foundBaseOffset = (foundBaseOffset * 10) + (*typedesc++ - '0');
2239 // add fudge factor iff the Id field offset was wrong
2240 if (foundBaseOffset != trueBaseOffset)
2248 // XXX Getting the size of a type is done all over the place
2249 // (Here, Foundation, remote project)! - Should unify
2251 unsigned int getSizeOfType (const char * type, unsigned int * alignPtr);
2253 unsigned method_getSizeOfArguments (Method method)
2260 unsigned stack_size;
2263 nargs = method_getNumberOfArguments (method);
2264 stack_size = (*method->method_types == '{') ? sizeof(void *) : 0;
2266 for (index = 0; index < nargs; index += 1)
2268 (void) method_getArgumentInfo (method, index, &type, &offset);
2269 size = getSizeOfType (type, &align);
2270 stack_size += ((size + 7) & ~7);
2277 /***********************************************************************
2278 * method_getArgumentInfo.
2279 **********************************************************************/
2280 unsigned method_getArgumentInfo (Method method,
2285 const char * typedesc = method->method_types;
2287 unsigned self_offset = 0;
2288 BOOL offset_is_negative = NO;
2290 // First, skip the return type
2291 typedesc = SkipFirstType (typedesc);
2293 // Next, skip stack size
2294 while ((*typedesc >= '0') && (*typedesc <= '9'))
2297 // Now, we have the arguments - position typedesc to the appropriate argument
2298 while (*typedesc && nargs != arg)
2301 // Skip argument type
2302 typedesc = SkipFirstType (typedesc);
2306 // Skip negative sign in offset
2307 if (*typedesc == '-')
2309 offset_is_negative = YES;
2313 offset_is_negative = NO;
2315 while ((*typedesc >= '0') && (*typedesc <= '9'))
2316 self_offset = self_offset * 10 + (*typedesc++ - '0');
2317 if (offset_is_negative)
2318 self_offset = -(self_offset);
2324 // Skip (possibly negative) argument offset
2325 if (*typedesc == '-')
2327 while ((*typedesc >= '0') && (*typedesc <= '9'))
2336 unsigned arg_offset = 0;
2339 typedesc = SkipFirstType (typedesc);
2344 *offset = -sizeof(id);
2352 // Pick up (possibly negative) argument offset
2353 if (*typedesc == '-')
2355 offset_is_negative = YES;
2359 offset_is_negative = NO;
2361 while ((*typedesc >= '0') && (*typedesc <= '9'))
2362 arg_offset = arg_offset * 10 + (*typedesc++ - '0');
2363 if (offset_is_negative)
2364 arg_offset = - arg_offset;
2367 // For stacks which grow up, since margs points
2368 // to the top of the stack or the END of the args,
2369 // the first offset is at -sizeof(id) rather than 0.
2370 self_offset += sizeof(id);
2372 *offset = arg_offset - self_offset;
2386 /***********************************************************************
2387 * _objc_create_zone.
2388 **********************************************************************/
2390 void * _objc_create_zone (void)
2392 static void *_objc_z = (void *)0xffffffff;
2393 if ( _objc_z == (void *)0xffffffff ) {
2394 char *s = getenv("OBJC_USE_OBJC_ZONE");
2396 if ( (*s == '1') || (*s == 'y') || (*s == 'Y') ) {
2397 _objc_z = malloc_create_zone(vm_page_size, 0);
2398 malloc_set_zone_name(_objc_z, "ObjC");
2401 if ( _objc_z == (void *)0xffffffff ) {
2402 _objc_z = malloc_default_zone();
2408 /***********************************************************************
2410 **********************************************************************/
2411 #ifdef OBJC_COLLECTING_CACHE
2413 static unsigned long _get_pc_for_thread (mach_port_t thread)
2416 struct hp_pa_frame_thread_state state;
2417 unsigned int count = HPPA_FRAME_THREAD_STATE_COUNT;
2418 thread_get_state (thread, HPPA_FRAME_THREAD_STATE, (thread_state_t)&state, &count);
2419 return state.ts_pcoq_front;
2421 #elif defined(sparc)
2423 struct sparc_thread_state_regs state;
2424 unsigned int count = SPARC_THREAD_STATE_REGS_COUNT;
2425 thread_get_state (thread, SPARC_THREAD_STATE_REGS, (thread_state_t)&state, &count);
2426 return state.regs.r_pc;
2428 #elif defined(__i386__) || defined(i386)
2430 i386_thread_state_t state;
2431 unsigned int count = i386_THREAD_STATE_COUNT;
2432 thread_get_state (thread, i386_THREAD_STATE, (thread_state_t)&state, &count);
2437 struct m68k_thread_state_regs state;
2438 unsigned int count = M68K_THREAD_STATE_REGS_COUNT;
2439 thread_get_state (thread, M68K_THREAD_STATE_REGS, (thread_state_t)&state, &count);
2442 #elif defined(__ppc__) || defined(ppc)
2444 struct ppc_thread_state state;
2445 unsigned int count = PPC_THREAD_STATE_COUNT;
2446 thread_get_state (thread, PPC_THREAD_STATE, (thread_state_t)&state, &count);
2451 #error _get_pc_for_thread () not implemented for this architecture
2455 /***********************************************************************
2456 * _collecting_in_critical.
2457 **********************************************************************/
2458 OBJC_EXPORT unsigned long objc_entryPoints[];
2459 OBJC_EXPORT unsigned long objc_exitPoints[];
2461 static int _collecting_in_critical (void)
2463 thread_act_port_array_t threads;
2468 mach_port_t mythread = pthread_mach_thread_np(pthread_self());
2470 // Get a list of all the threads in the current task
2471 ret = task_threads (mach_task_self (), &threads, &number);
2472 if (ret != KERN_SUCCESS)
2474 _objc_inform ("objc: task_thread failed\n");
2478 // Check whether any thread is in the cache lookup code
2480 for (count = 0; !result && (count < number); count += 1)
2485 // Don't bother checking ourselves
2486 if (threads[count] == mythread)
2489 // Find out where thread is executing
2490 pc = _get_pc_for_thread (threads[count]);
2492 // Check whether it is in the cache lookup code
2493 for (region = 0; !result && (objc_entryPoints[region] != 0); region += 1)
2495 if ((pc >= objc_entryPoints[region]) &&
2496 (pc <= objc_exitPoints[region]))
2500 // Deallocate the port rights for the threads
2501 for (count = 0; count < number; count++) {
2502 mach_port_deallocate(mach_task_self (), threads[count]);
2505 // Deallocate the thread list
2506 vm_deallocate (mach_task_self (), (vm_address_t) threads, sizeof(threads) * number);
2508 // Return our finding
2512 /***********************************************************************
2513 * _garbage_make_room. Ensure that there is enough room for at least
2514 * one more ref in the garbage.
2515 **********************************************************************/
2517 // amount of memory represented by all refs in the garbage
2518 static int garbage_byte_size = 0;
2520 // do not empty the garbage until garbage_byte_size gets at least this big
2521 static int garbage_threshold = 1024;
2523 // table of refs to free
2524 static void **garbage_refs = 0;
2526 // current number of refs in garbage_refs
2527 static int garbage_count = 0;
2529 // capacity of current garbage_refs
2530 static int garbage_max = 0;
2532 // capacity of initial garbage_refs
2534 INIT_GARBAGE_COUNT = 128
2537 static void _garbage_make_room (void)
2539 static int first = 1;
2540 volatile void * tempGarbage;
2542 // Create the collection table the first time it is needed
2546 garbage_refs = malloc_zone_malloc (_objc_create_zone(),
2547 INIT_GARBAGE_COUNT * sizeof(void *));
2548 garbage_max = INIT_GARBAGE_COUNT;
2551 // Double the table if it is full
2552 else if (garbage_count == garbage_max)
2554 tempGarbage = malloc_zone_realloc ((void *) _objc_create_zone(),
2555 (void *) garbage_refs,
2556 (size_t) garbage_max * 2 * sizeof(void *));
2557 garbage_refs = (void **) tempGarbage;
2562 /***********************************************************************
2563 * _cache_collect_free. Add the specified malloc'd memory to the list
2564 * of them to free at some later point.
2565 **********************************************************************/
2566 static void _cache_collect_free (void * data,
2569 static char *report_garbage = (char *)0xffffffff;
2571 if ((char *)0xffffffff == report_garbage) {
2572 // Check whether to log our activity
2573 report_garbage = getenv ("OBJC_REPORT_GARBAGE");
2577 OBJC_LOCK(&cacheCollectionLock);
2579 // Insert new element in garbage list
2580 // Note that we do this even if we end up free'ing everything
2581 _garbage_make_room ();
2582 garbage_byte_size += malloc_size (data);
2583 garbage_refs[garbage_count++] = data;
2586 if (tryCollect && report_garbage)
2587 _objc_inform ("total of %d bytes of garbage ...", garbage_byte_size);
2589 // Done if caller says not to empty or the garbage is not full
2590 if (!tryCollect || (garbage_byte_size < garbage_threshold))
2592 OBJC_UNLOCK(&cacheCollectionLock);
2593 if (tryCollect && report_garbage)
2594 _objc_inform ("below threshold\n");
2599 // Synchronize garbage collection with messageLock holders
2600 if (OBJC_TRYLOCK(&messageLock))
2602 // Synchronize garbage collection with cache lookers
2603 if (!_collecting_in_critical ())
2606 if (tryCollect && report_garbage)
2607 _objc_inform ("collecting!\n");
2609 // Dispose all refs now in the garbage
2610 while (garbage_count)
2611 free (garbage_refs[--garbage_count]);
2613 // Clear the total size indicator
2614 garbage_byte_size = 0;
2617 // Someone is actively looking in the cache
2618 else if (tryCollect && report_garbage)
2619 _objc_inform ("in critical region\n");
2621 OBJC_UNLOCK(&messageLock);
2624 // Someone already holds messageLock
2625 else if (tryCollect && report_garbage)
2626 _objc_inform ("messageLock taken\n");
2628 OBJC_UNLOCK(&cacheCollectionLock);
2630 #endif // OBJC_COLLECTING_CACHE
2633 /***********************************************************************
2635 **********************************************************************/
2636 static void _cache_print (Cache cache)
2641 count = cache->mask + 1;
2642 for (index = 0; index < count; index += 1)
2643 if (CACHE_BUCKET_VALID(cache->buckets[index]))
2645 if (CACHE_BUCKET_IMP(cache->buckets[index]) == &_objc_msgForward)
2646 printf ("does not recognize: \n");
2647 printf ("%s\n", (const char *) CACHE_BUCKET_NAME(cache->buckets[index]));
2651 /***********************************************************************
2652 * _class_printMethodCaches.
2653 **********************************************************************/
2654 void _class_printMethodCaches (Class cls)
2656 if (((struct objc_class *)cls)->cache == &emptyCache)
2657 printf ("no instance-method cache for class %s\n", ((struct objc_class *)cls)->name);
2661 printf ("instance-method cache for class %s:\n", ((struct objc_class *)cls)->name);
2662 _cache_print (((struct objc_class *)cls)->cache);
2665 if (((struct objc_class * )((struct objc_class * )cls)->isa)->cache == &emptyCache)
2666 printf ("no class-method cache for class %s\n", ((struct objc_class *)cls)->name);
2670 printf ("class-method cache for class %s:\n", ((struct objc_class *)cls)->name);
2671 _cache_print (((struct objc_class * )((struct objc_class * )cls)->isa)->cache);
2675 /***********************************************************************
2677 **********************************************************************/
2678 static unsigned int log2 (unsigned int x)
2689 /***********************************************************************
2690 * _class_printDuplicateCacheEntries.
2691 **********************************************************************/
2692 void _class_printDuplicateCacheEntries (BOOL detail)
2694 NXHashTable * class_hash;
2696 struct objc_class * cls;
2697 unsigned int duplicates;
2698 unsigned int index1;
2699 unsigned int index2;
2702 unsigned int isMeta;
2706 printf ("Checking for duplicate cache entries \n");
2708 // Outermost loop - iterate over all classes
2709 class_hash = objc_getClasses ();
2710 state = NXInitHashState (class_hash);
2712 while (NXNextHashState (class_hash, &state, (void **) &cls))
2714 // Control loop - do given class' cache, then its isa's cache
2715 for (isMeta = 0; isMeta <= 1; isMeta += 1)
2717 // Select cache of interest and make sure it exists
2718 cache = isMeta ? cls->isa->cache : ((struct objc_class *)cls)->cache;
2719 if (cache == &emptyCache)
2722 // Middle loop - check each entry in the given cache
2725 for (index1 = 0; index1 < count; index1 += 1)
2727 // Skip invalid entry
2728 if (!CACHE_BUCKET_VALID(cache->buckets[index1]))
2731 // Inner loop - check that given entry matches no later entry
2732 for (index2 = index1 + 1; index2 < count; index2 += 1)
2734 // Skip invalid entry
2735 if (!CACHE_BUCKET_VALID(cache->buckets[index2]))
2738 // Check for duplication by method name comparison
2739 if (strcmp ((char *) CACHE_BUCKET_NAME(cache->buckets[index1]),
2740 (char *) CACHE_BUCKET_NAME(cache->buckets[index2])) == 0)
2743 printf ("%s %s\n", ((struct objc_class *)cls)->name, (char *) CACHE_BUCKET_NAME(cache->buckets[index1]));
2753 printf ("duplicates = %d\n", duplicates);
2754 printf ("total cache fills = %d\n", totalCacheFills);
2757 /***********************************************************************
2759 **********************************************************************/
2760 static void PrintCacheHeader (void)
2762 #ifdef OBJC_INSTRUMENTED
2763 printf ("Cache Cache Slots Avg Max AvgS MaxS AvgS MaxS TotalD AvgD MaxD TotalD AvgD MaxD TotD AvgD MaxD\n");
2764 printf ("Size Count Used Used Used Hit Hit Miss Miss Hits Prbs Prbs Misses Prbs Prbs Flsh Flsh Flsh\n");
2765 printf ("----- ----- ----- ----- ---- ---- ---- ---- ---- ------- ---- ---- ------- ---- ---- ---- ---- ----\n");
2767 printf ("Cache Cache Slots Avg Max AvgS MaxS AvgS MaxS\n");
2768 printf ("Size Count Used Used Used Hit Hit Miss Miss\n");
2769 printf ("----- ----- ----- ----- ---- ---- ---- ---- ----\n");
2773 /***********************************************************************
2775 **********************************************************************/
2776 static void PrintCacheInfo (unsigned int cacheSize,
2777 unsigned int cacheCount,
2778 unsigned int slotsUsed,
2780 unsigned int maxUsed,
2782 unsigned int maxSHit,
2784 unsigned int maxSMiss
2785 #ifdef OBJC_INSTRUMENTED
2786 , unsigned int totDHits,
2788 unsigned int maxDHit,
2789 unsigned int totDMisses,
2791 unsigned int maxDMiss,
2792 unsigned int totDFlsh,
2794 unsigned int maxDFlsh
2798 #ifdef OBJC_INSTRUMENTED
2799 printf ("%5u %5u %5u %5.1f %4u %4.1f %4u %4.1f %4u %7u %4.1f %4u %7u %4.1f %4u %4u %4.1f %4u\n",
2801 printf ("%5u %5u %5u %5.1f %4u %4.1f %4u %4.1f %4u\n",
2803 cacheSize, cacheCount, slotsUsed, avgUsed, maxUsed, avgSHit, maxSHit, avgSMiss, maxSMiss
2804 #ifdef OBJC_INSTRUMENTED
2805 , totDHits, avgDHit, maxDHit, totDMisses, avgDMiss, maxDMiss, totDFlsh, avgDFlsh, maxDFlsh
2811 #ifdef OBJC_INSTRUMENTED
2812 /***********************************************************************
2813 * PrintCacheHistogram. Show the non-zero entries from the specified
2815 **********************************************************************/
2816 static void PrintCacheHistogram (char * title,
2817 unsigned int * firstEntry,
2818 unsigned int entryCount)
2821 unsigned int * thisEntry;
2823 printf ("%s\n", title);
2824 printf (" Probes Tally\n");
2825 printf (" ------ -----\n");
2826 for (index = 0, thisEntry = firstEntry;
2828 index += 1, thisEntry += 1)
2830 if (*thisEntry == 0)
2833 printf (" %6d %5d\n", index, *thisEntry);
2838 /***********************************************************************
2839 * _class_printMethodCacheStatistics.
2840 **********************************************************************/
2842 #define MAX_LOG2_SIZE 32
2843 #define MAX_CHAIN_SIZE 100
2845 void _class_printMethodCacheStatistics (void)
2847 unsigned int isMeta;
2849 NXHashTable * class_hash;
2851 struct objc_class * cls;
2852 unsigned int totalChain;
2853 unsigned int totalMissChain;
2854 unsigned int maxChain;
2855 unsigned int maxMissChain;
2856 unsigned int classCount;
2857 unsigned int negativeEntryCount;
2858 unsigned int cacheExpandCount;
2859 unsigned int cacheCountBySize[2][MAX_LOG2_SIZE] = {{0}};
2860 unsigned int totalEntriesBySize[2][MAX_LOG2_SIZE] = {{0}};
2861 unsigned int maxEntriesBySize[2][MAX_LOG2_SIZE] = {{0}};
2862 unsigned int totalChainBySize[2][MAX_LOG2_SIZE] = {{0}};
2863 unsigned int totalMissChainBySize[2][MAX_LOG2_SIZE] = {{0}};
2864 unsigned int totalMaxChainBySize[2][MAX_LOG2_SIZE] = {{0}};
2865 unsigned int totalMaxMissChainBySize[2][MAX_LOG2_SIZE] = {{0}};
2866 unsigned int maxChainBySize[2][MAX_LOG2_SIZE] = {{0}};
2867 unsigned int maxMissChainBySize[2][MAX_LOG2_SIZE] = {{0}};
2868 unsigned int chainCount[MAX_CHAIN_SIZE] = {0};
2869 unsigned int missChainCount[MAX_CHAIN_SIZE] = {0};
2870 #ifdef OBJC_INSTRUMENTED
2871 unsigned int hitCountBySize[2][MAX_LOG2_SIZE] = {{0}};
2872 unsigned int hitProbesBySize[2][MAX_LOG2_SIZE] = {{0}};
2873 unsigned int maxHitProbesBySize[2][MAX_LOG2_SIZE] = {{0}};
2874 unsigned int missCountBySize[2][MAX_LOG2_SIZE] = {{0}};
2875 unsigned int missProbesBySize[2][MAX_LOG2_SIZE] = {{0}};
2876 unsigned int maxMissProbesBySize[2][MAX_LOG2_SIZE] = {{0}};
2877 unsigned int flushCountBySize[2][MAX_LOG2_SIZE] = {{0}};
2878 unsigned int flushedEntriesBySize[2][MAX_LOG2_SIZE] = {{0}};
2879 unsigned int maxFlushedEntriesBySize[2][MAX_LOG2_SIZE] = {{0}};
2882 printf ("Printing cache statistics\n");
2884 // Outermost loop - iterate over all classes
2885 class_hash = objc_getClasses ();
2886 state = NXInitHashState (class_hash);
2888 negativeEntryCount = 0;
2889 cacheExpandCount = 0;
2890 while (NXNextHashState (class_hash, &state, (void **) &cls))
2895 // Control loop - do given class' cache, then its isa's cache
2896 for (isMeta = 0; isMeta <= 1; isMeta += 1)
2900 unsigned int log2Size;
2901 unsigned int entryCount;
2903 // Select cache of interest
2904 cache = isMeta ? cls->isa->cache : ((struct objc_class *)cls)->cache;
2906 // Ignore empty cache... should we?
2907 if (cache == &emptyCache)
2910 // Middle loop - do each entry in the given cache
2917 for (index = 0; index < mask + 1; index += 1)
2922 uarith_t methodChain;
2923 uarith_t methodMissChain;
2926 // If entry is invalid, the only item of
2927 // interest is that future insert hashes
2928 // to this entry can use it directly.
2929 buckets = cache->buckets;
2930 if (!CACHE_BUCKET_VALID(buckets[index]))
2932 missChainCount[0] += 1;
2936 method = buckets[index];
2938 // Tally valid entries
2941 // Tally "forward::" entries
2942 if (CACHE_BUCKET_IMP(method) == &_objc_msgForward)
2943 negativeEntryCount += 1;
2945 // Calculate search distance (chain length) for this method
2946 hash = (uarith_t) CACHE_BUCKET_NAME(method);
2947 methodChain = ((index - hash) & mask);
2949 // Tally chains of this length
2950 if (methodChain < MAX_CHAIN_SIZE)
2951 chainCount[methodChain] += 1;
2953 // Keep sum of all chain lengths
2954 totalChain += methodChain;
2956 // Record greatest chain length
2957 if (methodChain > maxChain)
2958 maxChain = methodChain;
2960 // Calculate search distance for miss that hashes here
2962 while (CACHE_BUCKET_VALID(buckets[index2]))
2967 methodMissChain = ((index2 - index) & mask);
2969 // Tally miss chains of this length
2970 if (methodMissChain < MAX_CHAIN_SIZE)
2971 missChainCount[methodMissChain] += 1;
2973 // Keep sum of all miss chain lengths in this class
2974 totalMissChain += methodMissChain;
2976 // Record greatest miss chain length
2977 if (methodMissChain > maxMissChain)
2978 maxMissChain = methodMissChain;
2981 // Factor this cache into statistics about caches of the same
2982 // type and size (all caches are a power of two in size)
2983 log2Size = log2 (mask + 1);
2984 cacheCountBySize[isMeta][log2Size] += 1;
2985 totalEntriesBySize[isMeta][log2Size] += entryCount;
2986 if (entryCount > maxEntriesBySize[isMeta][log2Size])
2987 maxEntriesBySize[isMeta][log2Size] = entryCount;
2988 totalChainBySize[isMeta][log2Size] += totalChain;
2989 totalMissChainBySize[isMeta][log2Size] += totalMissChain;
2990 totalMaxChainBySize[isMeta][log2Size] += maxChain;
2991 totalMaxMissChainBySize[isMeta][log2Size] += maxMissChain;
2992 if (maxChain > maxChainBySize[isMeta][log2Size])
2993 maxChainBySize[isMeta][log2Size] = maxChain;
2994 if (maxMissChain > maxMissChainBySize[isMeta][log2Size])
2995 maxMissChainBySize[isMeta][log2Size] = maxMissChain;
2996 #ifdef OBJC_INSTRUMENTED
2998 CacheInstrumentation * cacheData;
3000 cacheData = CACHE_INSTRUMENTATION(cache);
3001 hitCountBySize[isMeta][log2Size] += cacheData->hitCount;
3002 hitProbesBySize[isMeta][log2Size] += cacheData->hitProbes;
3003 if (cacheData->maxHitProbes > maxHitProbesBySize[isMeta][log2Size])
3004 maxHitProbesBySize[isMeta][log2Size] = cacheData->maxHitProbes;
3005 missCountBySize[isMeta][log2Size] += cacheData->missCount;
3006 missProbesBySize[isMeta][log2Size] += cacheData->missProbes;
3007 if (cacheData->maxMissProbes > maxMissProbesBySize[isMeta][log2Size])
3008 maxMissProbesBySize[isMeta][log2Size] = cacheData->maxMissProbes;
3009 flushCountBySize[isMeta][log2Size] += cacheData->flushCount;
3010 flushedEntriesBySize[isMeta][log2Size] += cacheData->flushedEntries;
3011 if (cacheData->maxFlushedEntries > maxFlushedEntriesBySize[isMeta][log2Size])
3012 maxFlushedEntriesBySize[isMeta][log2Size] = cacheData->maxFlushedEntries;
3015 // Caches start with a power of two number of entries, and grow by doubling, so
3016 // we can calculate the number of times this cache has expanded
3018 cacheExpandCount += log2Size - INIT_META_CACHE_SIZE_LOG2;
3020 cacheExpandCount += log2Size - INIT_CACHE_SIZE_LOG2;
3026 unsigned int cacheCountByType[2] = {0};
3027 unsigned int totalCacheCount = 0;
3028 unsigned int totalEntries = 0;
3029 unsigned int maxEntries = 0;
3030 unsigned int totalSlots = 0;
3031 #ifdef OBJC_INSTRUMENTED
3032 unsigned int totalHitCount = 0;
3033 unsigned int totalHitProbes = 0;
3034 unsigned int maxHitProbes = 0;
3035 unsigned int totalMissCount = 0;
3036 unsigned int totalMissProbes = 0;
3037 unsigned int maxMissProbes = 0;
3038 unsigned int totalFlushCount = 0;
3039 unsigned int totalFlushedEntries = 0;
3040 unsigned int maxFlushedEntries = 0;
3048 // Sum information over all caches
3049 for (isMeta = 0; isMeta <= 1; isMeta += 1)
3051 for (index = 0; index < MAX_LOG2_SIZE; index += 1)
3053 cacheCountByType[isMeta] += cacheCountBySize[isMeta][index];
3054 totalEntries += totalEntriesBySize[isMeta][index];
3055 totalSlots += cacheCountBySize[isMeta][index] * (1 << index);
3056 totalChain += totalChainBySize[isMeta][index];
3057 if (maxEntriesBySize[isMeta][index] > maxEntries)
3058 maxEntries = maxEntriesBySize[isMeta][index];
3059 if (maxChainBySize[isMeta][index] > maxChain)
3060 maxChain = maxChainBySize[isMeta][index];
3061 totalMissChain += totalMissChainBySize[isMeta][index];
3062 if (maxMissChainBySize[isMeta][index] > maxMissChain)
3063 maxMissChain = maxMissChainBySize[isMeta][index];
3064 #ifdef OBJC_INSTRUMENTED
3065 totalHitCount += hitCountBySize[isMeta][index];
3066 totalHitProbes += hitProbesBySize[isMeta][index];
3067 if (maxHitProbesBySize[isMeta][index] > maxHitProbes)
3068 maxHitProbes = maxHitProbesBySize[isMeta][index];
3069 totalMissCount += missCountBySize[isMeta][index];
3070 totalMissProbes += missProbesBySize[isMeta][index];
3071 if (maxMissProbesBySize[isMeta][index] > maxMissProbes)
3072 maxMissProbes = maxMissProbesBySize[isMeta][index];
3073 totalFlushCount += flushCountBySize[isMeta][index];
3074 totalFlushedEntries += flushedEntriesBySize[isMeta][index];
3075 if (maxFlushedEntriesBySize[isMeta][index] > maxFlushedEntries)
3076 maxFlushedEntries = maxFlushedEntriesBySize[isMeta][index];
3080 totalCacheCount += cacheCountByType[isMeta];
3084 printf ("There are %u classes\n", classCount);
3086 for (isMeta = 0; isMeta <= 1; isMeta += 1)
3088 // Number of this type of class
3089 printf ("\nThere are %u %s-method caches, broken down by size (slot count):\n",
3090 cacheCountByType[isMeta],
3091 isMeta ? "class" : "instance");
3094 PrintCacheHeader ();
3096 // Keep format consistent even if there are caches of this kind
3097 if (cacheCountByType[isMeta] == 0)
3099 printf ("(none)\n");
3103 // Usage information by cache size
3104 for (index = 0; index < MAX_LOG2_SIZE; index += 1)
3106 unsigned int cacheCount;
3107 unsigned int cacheSlotCount;
3108 unsigned int cacheEntryCount;
3110 // Get number of caches of this type and size
3111 cacheCount = cacheCountBySize[isMeta][index];
3112 if (cacheCount == 0)
3115 // Get the cache slot count and the total number of valid entries
3116 cacheSlotCount = (1 << index);
3117 cacheEntryCount = totalEntriesBySize[isMeta][index];
3119 // Give the analysis
3120 PrintCacheInfo (cacheSlotCount,
3123 (float) cacheEntryCount / (float) cacheCount,
3124 maxEntriesBySize[isMeta][index],
3125 (float) totalChainBySize[isMeta][index] / (float) cacheEntryCount,
3126 maxChainBySize[isMeta][index],
3127 (float) totalMissChainBySize[isMeta][index] / (float) (cacheCount * cacheSlotCount),
3128 maxMissChainBySize[isMeta][index]
3129 #ifdef OBJC_INSTRUMENTED
3130 , hitCountBySize[isMeta][index],
3131 hitCountBySize[isMeta][index] ?
3132 (float) hitProbesBySize[isMeta][index] / (float) hitCountBySize[isMeta][index] : 0.0,
3133 maxHitProbesBySize[isMeta][index],
3134 missCountBySize[isMeta][index],
3135 missCountBySize[isMeta][index] ?
3136 (float) missProbesBySize[isMeta][index] / (float) missCountBySize[isMeta][index] : 0.0,
3137 maxMissProbesBySize[isMeta][index],
3138 flushCountBySize[isMeta][index],
3139 flushCountBySize[isMeta][index] ?
3140 (float) flushedEntriesBySize[isMeta][index] / (float) flushCountBySize[isMeta][index] : 0.0,
3141 maxFlushedEntriesBySize[isMeta][index]
3147 // Give overall numbers
3148 printf ("\nCumulative:\n");
3149 PrintCacheHeader ();
3150 PrintCacheInfo (totalSlots,
3153 (float) totalEntries / (float) totalCacheCount,
3155 (float) totalChain / (float) totalEntries,
3157 (float) totalMissChain / (float) totalSlots,
3159 #ifdef OBJC_INSTRUMENTED
3162 (float) totalHitProbes / (float) totalHitCount : 0.0,
3166 (float) totalMissProbes / (float) totalMissCount : 0.0,
3170 (float) totalFlushedEntries / (float) totalFlushCount : 0.0,
3175 printf ("\nNumber of \"forward::\" entries: %d\n", negativeEntryCount);
3176 printf ("Number of cache expansions: %d\n", cacheExpandCount);
3177 #ifdef OBJC_INSTRUMENTED
3178 printf ("flush_caches: total calls total visits average visits max visits total classes visits/class\n");
3179 printf (" ----------- ------------ -------------- ---------- ------------- -------------\n");
3180 printf (" linear %11u %12u %14.1f %10u %13u %12.2f\n",
3181 LinearFlushCachesCount,
3182 LinearFlushCachesVisitedCount,
3183 LinearFlushCachesCount ?
3184 (float) LinearFlushCachesVisitedCount / (float) LinearFlushCachesCount : 0.0,
3185 MaxLinearFlushCachesVisitedCount,
3186 LinearFlushCachesVisitedCount,
3188 printf (" nonlinear %11u %12u %14.1f %10u %13u %12.2f\n",
3189 NonlinearFlushCachesCount,
3190 NonlinearFlushCachesVisitedCount,
3191 NonlinearFlushCachesCount ?
3192 (float) NonlinearFlushCachesVisitedCount / (float) NonlinearFlushCachesCount : 0.0,
3193 MaxNonlinearFlushCachesVisitedCount,
3194 NonlinearFlushCachesClassCount,
3195 NonlinearFlushCachesClassCount ?
3196 (float) NonlinearFlushCachesVisitedCount / (float) NonlinearFlushCachesClassCount : 0.0);
3197 printf (" ideal %11u %12u %14.1f %10u %13u %12.2f\n",
3198 LinearFlushCachesCount + NonlinearFlushCachesCount,
3199 IdealFlushCachesCount,
3200 LinearFlushCachesCount + NonlinearFlushCachesCount ?
3201 (float) IdealFlushCachesCount / (float) (LinearFlushCachesCount + NonlinearFlushCachesCount) : 0.0,
3202 MaxIdealFlushCachesCount,
3203 LinearFlushCachesVisitedCount + NonlinearFlushCachesClassCount,
3204 LinearFlushCachesVisitedCount + NonlinearFlushCachesClassCount ?
3205 (float) IdealFlushCachesCount / (float) (LinearFlushCachesVisitedCount + NonlinearFlushCachesClassCount) : 0.0);
3207 PrintCacheHistogram ("\nCache hit histogram:", &CacheHitHistogram[0], CACHE_HISTOGRAM_SIZE);
3208 PrintCacheHistogram ("\nCache miss histogram:", &CacheMissHistogram[0], CACHE_HISTOGRAM_SIZE);
3212 printf ("\nLookup chains:");
3213 for (index = 0; index < MAX_CHAIN_SIZE; index += 1)
3215 if (chainCount[index] != 0)
3216 printf (" %u:%u", index, chainCount[index]);
3219 printf ("\nMiss chains:");
3220 for (index = 0; index < MAX_CHAIN_SIZE; index += 1)
3222 if (missChainCount[index] != 0)
3223 printf (" %u:%u", index, missChainCount[index]);
3226 printf ("\nTotal memory usage for cache data structures: %lu bytes\n",
3227 totalCacheCount * (sizeof(struct objc_cache) - sizeof(Method)) +
3228 totalSlots * sizeof(Method) +
3229 negativeEntryCount * sizeof(struct objc_method));
3234 /***********************************************************************
3236 **********************************************************************/
3237 void checkUniqueness (SEL s1,
3243 if (s1 && s2 && (strcmp ((const char *) s1, (const char *) s2) == 0))
3244 _objc_inform ("%p != %p but !strcmp (%s, %s)\n", s1, s2, (char *) s1, (char *) s2);