runtime.h
枚举时修改检测原理:
/**
* This function is inserted by the compiler when a mutation
* is detected during a foreach iteration. It gets called
* when a mutation occurs, and the enumerationMutationHandler
* is enacted if it is set up. A fatal error occurs if a handler is not set up.
* @param obj The object being mutated.
*/
OBJC_EXPORT void objc_enumerationMutation(id obj)
__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
weak原理:
/**
* This loads the object referenced by a weak pointer and returns it, after
* retaining and autoreleasing the object to ensure that it stays alive
* long enough for the caller to use it. This function would be used
* anywhere a __weak variable is used in an expression.
*/
OBJC_EXPORT id objc_loadWeak(id *location)
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
/**
* This function stores a new value into a __weak variable. It would
* be used anywhere a __weak variable is the target of an assignment.
*/
OBJC_EXPORT id objc_storeWeak(id *location, id obj)
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0);
所有load方法的执行过程
入口方法_objc_load_image
在objc-os.mm
里,prepare_load_methods
负责读section找出class和category的所有load,放到静态列表变量里,确保先放superclass的,call_load_methods
负责依次调用,先调class的,再调category的。
OBJC_EXPORT void _objc_load_image(HMODULE image, header_info *hinfo)
{
prepare_load_methods(hinfo);
call_load_methods();
}
void prepare_load_methods(const headerType *mhdr)
{
size_t count, i;
runtimeLock.assertWriting();
classref_t *classlist =
_getObjc2NonlazyClassList(mhdr, &count);
for (i = 0; i < count; i++) {
schedule_class_load(remapClass(classlist[i]));
}
category_t **categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
for (i = 0; i < count; i++) {
category_t *cat = categorylist[i];
Class cls = remapClass(cat->cls);
if (!cls) continue; // category for ignored weak-linked class
realizeClass(cls);
assert(cls->ISA()->isRealized());
add_category_to_loadable_list(cat);
}
}
GETSECT(_getObjc2NonlazyClassList, classref_t, "__objc_nlclslist");
GETSECT(_getObjc2NonlazyCategoryList, category_t *, "__objc_nlcatlist");
static void schedule_class_load(Class cls)
{
if (!cls) return;
assert(cls->isRealized()); // _read_images should realize
if (cls->data()->flags & RW_LOADED) return;
// Ensure superclass-first ordering
schedule_class_load(cls->superclass);
add_class_to_loadable_list(cls);
cls->setInfo(RW_LOADED);
}
void call_load_methods(void)
{
static bool loading = NO;
bool more_categories;
loadMethodLock.assertLocked();
// Re-entrant calls do nothing; the outermost call will finish the job.
if (loading) return;
loading = YES;
void *pool = objc_autoreleasePoolPush();
do {
// 1. Repeatedly call class +loads until there aren't any more
while (loadable_classes_used > 0) {
call_class_loads();
}
// 2. Call category +loads ONCE
more_categories = call_category_loads();
// 3. Run more +loads if there are classes OR more untried categories
} while (loadable_classes_used > 0 || more_categories);
objc_autoreleasePoolPop(pool);
loading = NO;
}
objc-lockdebug.h/.mm
一堆lockdebug前缀的锁方法,可以检测死锁、锁没用对,等等。
objc-object.h
retain/release的各种实现,包括SUPPORT_RETURN_AUTORELEASE
优化的黑技术。
static ALWAYS_INLINE bool
callerAcceptsOptimizedReturn(const void *ra)
{
// fd 03 1d aa mov fp, fp
if (*(uint32_t *)ra == 0xaa1d03fd) {
return true;
}
return false;
}
objc-private.h/.mm
class AssociationsHashMap : public unordered_map<disguised_ptr_t, ObjectAssociationMap *, DisguisedPointerHash, DisguisedPointerEqual, AssociationsHashMapAllocator> {
public:
void *operator new(size_t n) { return ::malloc(n); }
void operator delete(void *ptr) { ::free(ptr); }
};
AssociationsHashMap *AssociationsManager::_map = NULL;
记录所有association到obj的key-value对。
objc-runtime-new.h/.mm
struct objc_class : objc_object {
各种标志。
static NXHashTable *realized_class_hash = nil;
static NXHashTable *realizedClasses(void)
{
runtimeLock.assertLocked();
// allocated in _read_images
assert(realized_class_hash);
return realized_class_hash;
}
实现类。
objc-sel.mm
SEL
就是char*
。存在静态变量namedSelectors
里。
static NXMapTable *namedSelectors;
objc-sync.mm
@synchronized
的实现。
int objc_sync_enter(id obj)
int objc_sync_exit(id obj)
用了递归锁recursive_mutex_t
。