Optimise some ARC functions a little bit.

The calls to objc_storeWeak were not being inlined, so we were not
benefiting from optimisations based on the invariants.
main
David Chisnall 7 years ago
parent 722a2c3b0d
commit f0d7fd4165

95
arc.m

@ -695,17 +695,8 @@ static inline BOOL weakRefRelease(WeakRef *ref)
void* block_load_weak(void *block); void* block_load_weak(void *block);
OBJC_PUBLIC id objc_storeWeak(id *addr, id obj) static BOOL setObjectHasWeakRefs(id obj)
{
LOCK_FOR_SCOPE(&weakRefLock);
WeakRef *oldRef;
id old;
loadWeakPointer(addr, &old, &oldRef);
// If the old and new values are the same, then we don't need to do anything.
if (old == obj)
{ {
return obj;
}
BOOL isGlobalObject = isPersistentObject(obj); BOOL isGlobalObject = isPersistentObject(obj);
Class cls = isGlobalObject ? Nil : obj->isa; Class cls = isGlobalObject ? Nil : obj->isa;
if (obj && cls && objc_test_class_flag(cls, objc_class_flag_fast_arc)) if (obj && cls && objc_test_class_flag(cls, objc_class_flag_fast_arc))
@ -746,6 +737,40 @@ OBJC_PUBLIC id objc_storeWeak(id *addr, id obj)
} while (newVal != refCountVal); } while (newVal != refCountVal);
} }
} }
return isGlobalObject;
}
WeakRef *incrementWeakRefCount(id obj)
{
WeakRef *ref = weak_ref_table_get(weakRefs, obj);
if (ref == NULL)
{
ref = calloc(1, sizeof(WeakRef));
ref->isa = (Class)&weakref_class;
ref->obj = obj;
ref->weak_count = 1;
weak_ref_insert(weakRefs, ref);
}
else
{
assert(ref->obj == obj);
ref->weak_count++;
}
return ref;
}
OBJC_PUBLIC id objc_storeWeak(id *addr, id obj)
{
LOCK_FOR_SCOPE(&weakRefLock);
WeakRef *oldRef;
id old;
loadWeakPointer(addr, &old, &oldRef);
// If the old and new values are the same, then we don't need to do anything.
if (old == obj)
{
return obj;
}
BOOL isGlobalObject = setObjectHasWeakRefs(obj);
// If we old ref exists, decrement its reference count. This may also // If we old ref exists, decrement its reference count. This may also
// delete the weak reference control block. // delete the weak reference control block.
if (oldRef != NULL) if (oldRef != NULL)
@ -767,21 +792,7 @@ OBJC_PUBLIC id objc_storeWeak(id *addr, id obj)
} }
if (nil != obj) if (nil != obj)
{ {
WeakRef *ref = weak_ref_table_get(weakRefs, obj); *addr = (id)incrementWeakRefCount(obj);
if (ref == NULL)
{
ref = calloc(1, sizeof(WeakRef));
ref->isa = (Class)&weakref_class;
ref->obj = obj;
ref->weak_count = 1;
weak_ref_insert(weakRefs, ref);
}
else
{
assert(ref->obj == obj);
ref->weak_count++;
}
*addr = (id)ref;
} }
return obj; return obj;
} }
@ -903,11 +914,37 @@ OBJC_PUBLIC void objc_moveWeak(id *dest, id *src)
OBJC_PUBLIC void objc_destroyWeak(id* obj) OBJC_PUBLIC void objc_destroyWeak(id* obj)
{ {
objc_storeWeak(obj, nil); LOCK_FOR_SCOPE(&weakRefLock);
WeakRef *oldRef;
id old;
loadWeakPointer(obj, &old, &oldRef);
// If the old ref exists, decrement its reference count. This may also
// delete the weak reference control block.
if (oldRef != NULL)
{
weakRefRelease(oldRef);
}
} }
OBJC_PUBLIC id objc_initWeak(id *object, id value) OBJC_PUBLIC id objc_initWeak(id *addr, id obj)
{
if (obj == nil)
{
*addr = nil;
return nil;
}
LOCK_FOR_SCOPE(&weakRefLock);
BOOL isGlobalObject = setObjectHasWeakRefs(obj);
if (isGlobalObject)
{ {
*object = nil; // If this is a global object, it's never deallocated, so secretly make
return objc_storeWeak(object, value); // this a strong reference.
*addr = obj;
return obj;
}
if (nil != obj)
{
*(WeakRef**)addr = incrementWeakRefCount(obj);
}
return obj;
} }

Loading…
Cancel
Save