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,19 +522,19 @@ 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; if (oldSuper == newSuper) { return newSuper; }
}
safe_remove_from_subclass_list(cls); safe_remove_from_subclass_list(cls);
objc_resolve_class(newSuper); objc_resolve_class(newSuper);
Class oldSuper = cls->super_class;
cls->super_class = newSuper; cls->super_class = newSuper;
// 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.
@ -561,18 +561,14 @@ Class class_setSuperclass(Class cls, Class newSuper)
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);
UNLOCK_RUNTIME();
return oldSuper; 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);

Loading…
Cancel
Save