Refactor locking in setSuperclass.

Now all lock ownership is tied to scopes, so will be released correctly
in all return paths.
main
David Chisnall 8 years ago
parent 00d23b0013
commit a4f97f7563

@ -522,58 +522,54 @@ Class class_setSuperclass(Class cls, Class newSuper)
{ {
CHECK_ARG(cls); CHECK_ARG(cls);
CHECK_ARG(newSuper); CHECK_ARG(newSuper);
Class oldSuper;
if (Nil == cls) { return Nil; } if (Nil == cls) { return Nil; }
LOCK_RUNTIME(); {
LOCK_RUNTIME_FOR_SCOPE();
if (cls->super_class == newSuper) { oldSuper = cls->super_class;
UNLOCK_RUNTIME();
return newSuper;
}
safe_remove_from_subclass_list(cls); if (oldSuper == newSuper) { return newSuper; }
objc_resolve_class(newSuper);
Class oldSuper = cls->super_class; safe_remove_from_subclass_list(cls);
cls->super_class = newSuper; objc_resolve_class(newSuper);
// The super class's subclass list is used in certain method resolution scenarios. cls->super_class = newSuper;
cls->sibling_class = cls->super_class->subclass_list;
cls->super_class->subclass_list = cls;
if (UNLIKELY(class_isMetaClass(cls))) // The super class's subclass list is used in certain method resolution scenarios.
{ cls->sibling_class = cls->super_class->subclass_list;
// newSuper is presumably a metaclass. Its isa will therefore be the appropriate root metaclass. cls->super_class->subclass_list = cls;
cls->isa = newSuper->isa;
} if (UNLIKELY(class_isMetaClass(cls)))
else {
{ // newSuper is presumably a metaclass. Its isa will therefore be the appropriate root metaclass.
Class meta = cls->isa, newSuperMeta = newSuper->isa; cls->isa = newSuper->isa;
// Update the metaclass's superclass. }
safe_remove_from_subclass_list(meta); else
objc_resolve_class(newSuperMeta); {
Class meta = cls->isa, newSuperMeta = newSuper->isa;
// Update the metaclass's superclass.
safe_remove_from_subclass_list(meta);
objc_resolve_class(newSuperMeta);
meta->super_class = newSuperMeta; meta->super_class = newSuperMeta;
meta->isa = newSuperMeta->isa; meta->isa = newSuperMeta->isa;
// The super class's subclass list is used in certain method resolution scenarios. // The super class's subclass list is used in certain method resolution scenarios.
meta->sibling_class = newSuperMeta->subclass_list; meta->sibling_class = newSuperMeta->subclass_list;
newSuperMeta->subclass_list = meta; newSuperMeta->subclass_list = meta;
} }
LOCK(&initialize_lock); LOCK_FOR_SCOPE(&initialize_lock);
if (!objc_test_class_flag(cls, objc_class_flag_initialized)) if (!objc_test_class_flag(cls, objc_class_flag_initialized))
{ {
// Uninitialized classes don't have dtables to update // Uninitialized classes don't have dtables to update
// and don't need their superclasses initialized. // and don't need their superclasses initialized.
UNLOCK(&initialize_lock); return oldSuper;
UNLOCK_RUNTIME(); }
return oldSuper;
} }
UNLOCK(&initialize_lock);
UNLOCK_RUNTIME();
objc_send_initialize((id)newSuper); // also initializes the metaclass objc_send_initialize((id)newSuper); // also initializes the metaclass
objc_update_dtable_for_new_superclass(cls->isa, newSuper->isa); objc_update_dtable_for_new_superclass(cls->isa, newSuper->isa);
objc_update_dtable_for_new_superclass(cls, newSuper); objc_update_dtable_for_new_superclass(cls, newSuper);

Loading…
Cancel
Save