@ -629,9 +629,21 @@ namespace {
struct WeakRef
struct WeakRef
{
{
void *isa = &weakref_class;
void *isa = &weakref_class;
id obj = nullptr;
id object;
size_t weak_count = 1;
struct
WeakRef(id o) : obj(o) {}
{
size_t weak_count:((sizeof(size_t) * 8) - 1);
bool isDeleted:1;
};
id obj()
{
if (isDeleted)
{
return nil;
}
return object;
}
WeakRef(id o) : object(o), weak_count(1), isDeleted(false) {}
};
};
template<typename T>
template<typename T>
@ -709,7 +721,7 @@ static BOOL loadWeakPointer(id *addr, id *obj, WeakRef **ref)
if (classForObject(oldObj) == (Class)&weakref_class)
if (classForObject(oldObj) == (Class)&weakref_class)
{
{
*ref = (WeakRef*)oldObj;
*ref = (WeakRef*)oldObj;
*obj = (*ref)->obj;
*obj = (*ref)->obj() ;
return YES;
return YES;
}
}
*ref = NULL;
*ref = NULL;
@ -723,7 +735,7 @@ static inline BOOL weakRefRelease(WeakRef *ref)
ref->weak_count--;
ref->weak_count--;
if (ref->weak_count == 0)
if (ref->weak_count == 0)
{
{
weakRefs().erase(ref->obj);
weakRefs().erase(ref->object );
delete ref;
delete ref;
return YES;
return YES;
}
}
@ -786,7 +798,7 @@ WeakRef *incrementWeakRefCount(id obj)
}
}
else
else
{
{
assert(ref->obj == obj);
assert(ref->obj() == obj);
ref->weak_count++;
ref->weak_count++;
}
}
return ref;
return ref;
@ -862,7 +874,7 @@ extern "C" OBJC_PUBLIC BOOL objc_delete_weak_refs(id obj)
// accesses from loading from this. This must be done after
// accesses from loading from this. This must be done after
// removing the ref from the table, because the compare operation
// removing the ref from the table, because the compare operation
// tests the obj field.
// tests the obj field.
oldRef->obj = nil ;
oldRef->isDeleted = true ;
// If the weak reference count is zero, then we should have
// If the weak reference count is zero, then we should have
// already removed this.
// already removed this.
assert(oldRef->weak_count > 0);
assert(oldRef->weak_count > 0);