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

Loading…
Cancel
Save