Improve copying and moving weak refs.
Fixes a bug introduced (replacing a similar bug) in the last rewrite of
objc_moveWeak.  This version should now be correct.
objc_copyWeak was implemented in a naive way, which had a lot more
overhead than required.
@@ -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,11 +828,17 @@ 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;
+ if (oldRef != NULL)
+ {
weakRefRelease(oldRef);
}
+}
void objc_destroyWeak(id* obj)
{
