diff --git a/arc.m b/arc.m index d12a044..397265e 100644 --- a/arc.m +++ b/arc.m @@ -802,7 +802,24 @@ id objc_loadWeak(id* object) void objc_copyWeak(id *dest, id *src) { - objc_release(objc_initWeak(dest, objc_loadWeakRetained(src))); + // Don't retain or release. While the weak ref lock is held, we know that + // the object can't be deallocated, so we just move the value and update + // the weak reference table entry to indicate the new address. + LOCK_FOR_SCOPE(&weakRefLock); + id obj; + WeakRef *srcRef; + WeakRef *dstRef; + loadWeakPointer(dest, &obj, &dstRef); + loadWeakPointer(src, &obj, &srcRef); + *dest = *src; + if (srcRef) + { + srcRef->weak_count++; + } + if (dstRef) + { + weakRefRelease(dstRef); + } } void objc_moveWeak(id *dest, id *src) @@ -811,10 +828,16 @@ void objc_moveWeak(id *dest, id *src) // the object can't be deallocated, so we just move the value and update // the weak reference table entry to indicate the new address. LOCK_FOR_SCOPE(&weakRefLock); - WeakRef *oldRef = weak_ref_table_get(weakRefs, *dest); + id obj; + WeakRef *oldRef; + // If the destination is a weak ref, free it. + loadWeakPointer(dest, &obj, &oldRef); *dest = *src; *src = nil; - weakRefRelease(oldRef); + if (oldRef != NULL) + { + weakRefRelease(oldRef); + } } void objc_destroyWeak(id* obj)