// 底层实现函数入口
id objc_initWeak(id *location, id newObj)
{
if (!newObj) {
*location = nil;
return nil;
}
return storeWeak<DontHaveOld, DoHaveNew, DoCrashIfDeallocating>
(location, (objc_object*)newObj);
}
可以看出,底层都是调用storeWeak方法,区别在于模板的第一个参数haveOld
进入storeWeak函数
template <HaveOld haveOld, HaveNew haveNew,
CrashIfDeallocating crashIfDeallocating>
static id
storeWeak(id *location, objc_object *newObj)
{
assert(haveOld || haveNew);
if (!haveNew) assert(newObj == nil);
Class previouslyInitializedClass = nil;
id oldObj;
SideTable *oldTable;
SideTable *newTable;
// Acquire locks for old and new values.
// Order by lock address to prevent lock ordering problems.
// Retry if the old value changes underneath us.
retry:
// 如果weak指针之前弱引用过一个obj,则将这个obj所对应的SideTable取出,赋值给oldTable
if (haveOld) {
oldObj = *location;
oldTable = &SideTables()[oldObj];
} else {
// 没有弱引用过,则oldTable = nil
oldTable = nil;
}
// 如果weak指针要弱引用一个新的obj,则将该obj对应的SideTable取出,赋值给newTable
if (haveNew) {
newTable = &SideTables()[newObj];
} else {
newTable = nil;
}
// 加锁操作,防止多线程中竞争冲突
SideTable::lockTwo<haveOld, haveNew>(oldTable, newTable);
// location 应该与 oldObj 保持一致,如果不同,说明当前的 location 已经处理过 oldObj 可是又被其他线程所修改
if (haveOld && *location != oldObj) {
SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable);
goto retry;
}
// Prevent a deadlock between the weak reference machinery
// and the +initialize machinery by ensuring that no
// weakly-referenced object has an un-+initialized isa.
if (haveNew && newObj) {
Class cls = newObj->getIsa();
// 如果cls还没有初始化,先初始化,再尝试设置弱引用
if (cls != previouslyInitializedClass &&
!((objc_class *)cls)->isInitialized())
{
SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable);
_class_initialize(_class_getNonMetaClass(cls, (id)newObj));
// 完成初始化后进行标记
previouslyInitializedClass = cls;
// newObj 初始化后,重新获取一遍newObj
goto retry;
}
}
// Clean up old value, if any.
// 如果weak指针之前弱引用过别的对象oldObj,则调用weak_unregister_no_lock,在oldObj的weak_entry_t中移除该weak指针地址
if (haveOld) {
weak_unregister_no_lock(&oldTable->weak_table, oldObj, location);
}
// Assign new value, if any.
// 如果weak指针需要弱引用新的对象newObj
if (haveNew) {
// 调用weak_register_no_lock方法,将weak指针的地址记录到newObj对应的weak_entry_t中
newObj = (objc_object *)
weak_register_no_lock(&newTable->weak_table, (id)newObj, location,
crashIfDeallocating);
// weak_register_no_lock returns nil if weak store should be rejected
// Set is-weakly-referenced bit in refcount table.
// 更新newObj的isa指针的weakly_referenced bit标志位
if (newObj && !newObj->isTaggedPointer()) {
newObj->setWeaklyReferenced_nolock();
}
// Do not set *location anywhere else. That would introduce a race.
// *location 赋值,也就是将weak指针直接指向了newObj,而且没有将newObj的引用计数+1
*location = (id)newObj;
}
else {
// No new value. The storage is not changed.
}
SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable);
return (id)newObj;
}
id
weak_register_no_lock(weak_table_t *weak_table, id referent_id,
id *referrer_id, bool crashIfDeallocating)
{
// 被弱引用的对象
objc_object *referent = (objc_object *)referent_id;
// 指向弱引用对象的指针
objc_object **referrer = (objc_object **)referrer_id;
// 如果被弱引用对象referent为nil 或者被弱引用对象采用了TaggedPointer计数方式,则直接返回
if (!referent || referent->isTaggedPointer()) return referent_id;
// ensure that the referenced object is viable
// 确保被引用的对象可用(没有在析构,同时应该支持weak弱引用)
bool deallocating;
if (!referent->ISA()->hasCustomRR()) {
deallocating = referent->rootIsDeallocating();
}
else {
BOOL (*allowsWeakReference)(objc_object *, SEL) =
(BOOL(*)(objc_object *, SEL))
object_getMethodImplementation((id)referent,
SEL_allowsWeakReference);
if ((IMP)allowsWeakReference == _objc_msgForward) {
return nil;
}
deallocating =
! (*allowsWeakReference)(referent, SEL_allowsWeakReference);
}
// 如果是正在析构的对象,那么不能够被弱引用
if (deallocating) {
if (crashIfDeallocating) {
_objc_fatal("Cannot form weak reference to instance (%p) of ""class %s. It is possible that this object was ""over-released, or is in the process of deallocation.",
(void*)referent, object_getClassName((id)referent));
} else {
return nil;
}
}
// now remember it and where it is being stored
// 在 weak_table 中找到被弱引用对象 referent 对应的 weak_entry,并将 referrer 加入到 weak_entry 中
weak_entry_t *entry;
if ((entry = weak_entry_for_referent(weak_table, referent))) {
// 如果能找到 weak_entry,则将 referrer 追加到 weak_entry 中
append_referrer(entry, referrer);
}
else {
// 如果找不到 weak_entry,就新建一个
weak_entry_t new_entry(referent, referrer);
// 判断weak_table的容量是否足够
weak_grow_maybe(weak_table);
// 把新建的entry插入到weak_table
weak_entry_insert(weak_table, &new_entry);
}
// Do not set *referrer. objc_storeWeak() requires that the
// value not change.
return referent_id;
}
id
object_dispose(id obj)
{
if (!obj) return nil;
objc_destructInstance(obj);
free(obj);
return nil;
}
void *objc_destructInstance(id obj)
{
if (obj) {
// Read all of the flags at once for performance.
bool cxx = obj->hasCxxDtor();
bool assoc = obj->hasAssociatedObjects();
// This order is important.
// 如果有C++析构函数,则从类中销毁C++析构函数
if (cxx) object_cxxDestruct(obj);
// 如果有关联对象,则移除所有的关联对象,并将其自身从Association Manager的map中移除
if (assoc) _object_remove_assocations(obj);
// 继续清理其它相关的引用
obj->clearDeallocating();
}
return obj;
}
inline void
objc_object::clearDeallocating()
{
if (slowpath(!isa.nonpointer)) {
// Slow path for raw pointer isa.
// 如果要释放的对象没有采用了优化过的isa引用计数
sidetable_clearDeallocating();
}
elseif (slowpath(isa.weakly_referenced || isa.has_sidetable_rc)) {
// Slow path for non-pointer isa with weak refs and/or side table data.
// 如果要释放的对象采用了优化过的isa引用计数,并且有弱引用或者使用了sideTable的辅助引用计数
clearDeallocating_slow();
}
assert(!sidetable_present());
}
这里分两种情况
释放的对象没有采用了优化过的isa引用计数
void
objc_object::sidetable_clearDeallocating()
{
// 在全局的SideTables中,获取当前对象对应的sidetable
SideTable& table = SideTables()[this];
// clear any weak table items
// clear extra retain count and deallocating bit
// (fixme warn or abort if extra retain count == 0 ?)
table.lock();
// 在散列表SideTable中找到对应的引用计数表RefcountMap,拿到要释放的对象的引用计数
RefcountMap::iterator it = table.refcnts.find(this);
if (it != table.refcnts.end()) {
// 如果要释放的对象被弱引用了,通过weak_clear_no_lock函数将指向该对象的弱引用指针置为nil
if (it->second & SIDE_TABLE_WEAKLY_REFERENCED) {
weak_clear_no_lock(&table.weak_table, (id)this);
}
// 从引用计数表中擦除该对象的引用计数
table.refcnts.erase(it);
}
table.unlock();
}
ALWAYS_INLINE bool
objc_object::rootRelease(bool performDealloc, bool handleUnderflow)
{
// 判断是否为 TaggedPointer 类型,如果是则返回错误,因为 TaggedPointer 类型没有引用计数
if (isTaggedPointer()) returnfalse;
bool sideTableLocked = false;
isa_t oldisa;
isa_t newisa;
retry:
do {
oldisa = LoadExclusive(&isa.bits); // 为 isa.bits 加锁
newisa = oldisa;
if (slowpath(!newisa.nonpointer)) { // 判断 isa 是否为纯指针实现
ClearExclusive(&isa.bits); // 解锁isa.bits
if (sideTableLocked) sidetable_unlock(); // sidetable解锁
return sidetable_release(performDealloc); // 通过 sidetable_release 为其解锁
}
uintptr_t carry;
newisa.bits = subc(newisa.bits, RC_ONE, 0, &carry); // extra_rc--
// 如果extra_rc==0,extra_rc--会是负数,carry=1
if (slowpath(carry)) { // 如果发现溢出的情况
goto underflow;
}
} while (slowpath(!StoreReleaseExclusive(&isa.bits,
oldisa.bits, newisa.bits)));
if (slowpath(sideTableLocked)) sidetable_unlock();
returnfalse;
underflow:
// newisa.extra_rc-- underflowed: borrow from side table or deallocate
// abandon newisa to undo the decrement
// newisa重新赋值
newisa = oldisa;
// 判断是否有引用计数
if (slowpath(newisa.has_sidetable_rc)) {
// 有借位保存,rootRelease_underflow重新进入函数
if (!handleUnderflow) {
ClearExclusive(&isa.bits);
return rootRelease_underflow(performDealloc);
}
// Transfer retain count from side table to inline storage.
// 一些锁的操作
if (!sideTableLocked) {
ClearExclusive(&isa.bits);
sidetable_lock();
sideTableLocked = true;
// Need to start over to avoid a race against
// the nonpointer -> raw pointer transition.
goto retry;
}
// 获取借位引用次数,(获取次数最大RC_HALF)
// Try to remove some retain counts from the side table.
size_t borrowed = sidetable_subExtraRC_nolock(RC_HALF);
// To avoid races, has_sidetable_rc must remain set
// even if the side table count is now zero.
// 如果 borrowed > 0 ,即是说散列表中有值
if (borrowed > 0) {
// Side table retain count decreased.
// Try to add them to the inline count.
// 保存,就是StoreExclusive
// 如果&isa.bits和oldisa.bits相等,那么就把newisa.bits的值赋给&isa.bits,并且返回true
newisa.extra_rc = borrowed - 1; // redo the original decrement too
// 存储更改后的 isa.bits
bool stored = StoreReleaseExclusive(&isa.bits,
oldisa.bits, newisa.bits);
if (!stored) {// 如果保存失败,则再次保存
// Inline update failed.
// Try it again right now. This prevents livelock on LL/SC
// architectures where the side table access itself may have
// dropped the reservation.
isa_t oldisa2 = LoadExclusive(&isa.bits);
isa_t newisa2 = oldisa2;
if (newisa2.nonpointer) {
uintptr_t overflow;
newisa2.bits =
addc(newisa2.bits, RC_ONE * (borrowed-1), 0, &overflow);
if (!overflow) {
stored = StoreReleaseExclusive(&isa.bits, oldisa2.bits,
newisa2.bits);
}
}
}
if (!stored) {
// 还是不成功,把次数放回SideTable,重试retry
// Inline update failed.
// Put the retains back in the side table.
sidetable_addExtraRC_nolock(borrowed);
goto retry;
}
// Decrement successful after borrowing from side table.
// This decrement cannot be the deallocating decrement - the side
// table lock and has_sidetable_rc bit ensure that if everyone
// else tried to -release while we worked, the last one would block.
sidetable_unlock();
returnfalse;
}
else {
// Side table is empty after all. Fall-through to the dealloc path.
// 其他情况就是散列表没值,直接往下走
}
}
// Really deallocate.
// 如果没有借位保存次数,来到这里
if (slowpath(newisa.deallocating)) {
// 如果对象已经正在释放,报错警告:多次release
ClearExclusive(&isa.bits);
if (sideTableLocked) sidetable_unlock();
return overrelease_error();
// does not actually return
}
newisa.deallocating = true;
// 保存bits
if (!StoreExclusive(&isa.bits, oldisa.bits, newisa.bits)) goto retry;
if (slowpath(sideTableLocked)) sidetable_unlock();
__sync_synchronize();
if (performDealloc) {
// 调用dealloc
((void(*)(objc_object *, SEL))objc_msgSend)(this, SEL_dealloc);
}
returntrue;
}
NEVER_INLINE
bool
objc_object::overrelease_error()
{
_objc_inform_now_and_on_crash("%s object %p overreleased while already deallocating; break on objc_overrelease_during_dealloc_error to debug", object_getClassName((id)this), this);
objc_overrelease_during_dealloc_error();
returnfalse; // allow rootRelease() to tail-call this
}
__sync_synchronize
__sync_synchronize 的作用是:
No memory operand will be moved across the operation, either forward or backward. Further, instructions will be issued as necessary to prevent the processor from speculating loads across the operation and from queuing stores after the operation.
简而言之就是,在这个方法调用之后,涉及到内存的运算符都被禁止操作了(因为要进行析构了)。