Merge pull request #19 from gnustep/refcountrefactor

Refactor refcount usage.
This commit is contained in:
davidchisnall 2017-12-17 09:47:35 +00:00 committed by GitHub
commit 640972f2ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 94 additions and 22 deletions

View file

@ -125,6 +125,7 @@ BOOL NSDeallocateZombies = NO;
static Class zombieClass = Nil;
static NSMapTable *zombieMap = 0;
#ifndef OBJC_CAP_ARC
static void GSMakeZombie(NSObject *o, Class c)
{
object_setClass(o, zombieClass);
@ -135,6 +136,7 @@ static void GSMakeZombie(NSObject *o, Class c)
[allocationLock unlock];
}
}
#endif
static void GSLogZombie(id o, SEL sel)
{
@ -444,15 +446,8 @@ struct obj_layout {
};
typedef struct obj_layout *obj;
/**
* Examines the extra reference count for the object and, if non-zero
* decrements it, otherwise leaves it unchanged.<br />
* Returns a flag to say whether the count was zero
* (and hence whether the extra reference count was decremented).<br />
* This function is used by the [NSObject-release] method.
*/
inline BOOL
NSDecrementExtraRefCountWasZero(id anObject)
__attribute__((weak))
BOOL objc_release_fast_no_destroy_np(id anObject)
{
if (double_release_check_enabled)
{
@ -483,6 +478,9 @@ NSDecrementExtraRefCountWasZero(id anObject)
* have been greater than zero)
*/
(((obj)anObject)[-1].retained) = 0;
# ifdef OBJC_CAP_ARC
objc_delete_weak_refs(anObject);
# endif
return YES;
}
#else /* GSATOMICREAD */
@ -491,6 +489,9 @@ NSDecrementExtraRefCountWasZero(id anObject)
[theLock lock];
if (((obj)anObject)[-1].retained == 0)
{
# ifdef OBJC_CAP_ARC
objc_delete_weak_refs(anObject);
# endif
[theLock unlock];
return YES;
}
@ -505,6 +506,33 @@ NSDecrementExtraRefCountWasZero(id anObject)
return NO;
}
__attribute__((weak))
void objc_release_fast_np(id anObject)
{
if (objc_release_fast_no_destroy_np(anObject))
{
[anObject dealloc];
}
}
/**
* Examines the extra reference count for the object and, if non-zero
* decrements it, otherwise leaves it unchanged.<br />
* Returns a flag to say whether the count was zero
* (and hence whether the extra reference count was decremented).<br />
*/
inline BOOL
NSDecrementExtraRefCountWasZero(id anObject)
{
return objc_release_fast_no_destroy_np(anObject);
}
__attribute__((weak))
size_t object_getRetainCount_np(id anObject)
{
return ((obj)anObject)[-1].retained + 1;
}
/**
* Return the extra reference count of anObject (a value in the range
* from 0 to the maximum unsigned integer value minus one).<br />
@ -513,7 +541,7 @@ NSDecrementExtraRefCountWasZero(id anObject)
inline NSUInteger
NSExtraRefCount(id anObject)
{
return ((obj)anObject)[-1].retained;
return object_getRetainCount_np(anObject) - 1;
}
/**
@ -522,8 +550,8 @@ NSExtraRefCount(id anObject)
* would be incremented to too large a value.<br />
* This is used by the [NSObject-retain] method.
*/
inline void
NSIncrementExtraRefCount(id anObject)
__attribute__((weak))
id objc_retain_fast_np(id anObject)
{
BOOL tooFar = NO;
@ -586,6 +614,19 @@ NSIncrementExtraRefCount(id anObject)
@" for %@ - %@", base, anObject];
}
}
return anObject;
}
/**
* Increments the extra reference count for anObject.<br />
* The GNUstep version raises an exception if the reference count
* would be incremented to too large a value.<br />
* This is used by the [NSObject-retain] method.
*/
inline void
NSIncrementExtraRefCount(id anObject)
{
objc_retain_fast_np(anObject);
}
#ifndef NDEBUG
@ -596,6 +637,8 @@ NSIncrementExtraRefCount(id anObject)
#define AREM(c, o)
#endif
#ifndef OBJC_CAP_ARC
static SEL cxx_construct, cxx_destruct;
/**
@ -629,6 +672,7 @@ callCXXConstructors(Class aClass, id anObject)
}
return constructor;
}
#endif
/*
@ -642,6 +686,9 @@ callCXXConstructors(Class aClass, id anObject)
inline id
NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone)
{
#ifdef OBJC_CAP_ARC
return class_createInstance(aClass, extraBytes);
#else
id new;
int size;
@ -674,17 +721,21 @@ NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone)
callCXXConstructors(aClass, new);
return new;
#endif
}
inline void
NSDeallocateObject(id anObject)
{
Class aClass = object_getClass(anObject);
if ((anObject != nil) && !class_isMetaClass(aClass))
{
#ifndef OBJC_CAP_ARC
obj o = &((obj)anObject)[-1];
NSZone *z = NSZoneFromPointer(o);
#endif
/* Call the default finalizer to handle C++ destructors.
*/
@ -693,16 +744,37 @@ NSDeallocateObject(id anObject)
AREM(aClass, (id)anObject);
if (NSZombieEnabled == YES)
{
#ifdef OBJC_CAP_ARC
if (0 != zombieMap)
{
[allocationLock lock];
NSMapInsert(zombieMap, (void*)anObject, (void*)aClass);
[allocationLock unlock];
}
if (NSDeallocateZombies == YES)
{
object_dispose(anObject);
}
else
{
object_setClass(anObject, zombieClass);
}
#else
GSMakeZombie(anObject, aClass);
if (NSDeallocateZombies == YES)
{
NSZoneFree(z, o);
}
#endif
}
else
{
#ifdef OBJC_CAP_ARC
object_dispose(anObject);
#else
object_setClass((id)anObject, (Class)(void*)0xdeadface);
NSZoneFree(z, o);
#endif
}
}
return;
@ -1197,6 +1269,7 @@ static id gs_weak_load(id obj)
- (void) finalize
{
#ifndef OBJC_CAP_ARC
Class destructorClass = Nil;
IMP destructor = 0;
/*
@ -1251,6 +1324,7 @@ static id gs_weak_load(id obj)
}
}
return;
#endif
}
/**
@ -1893,13 +1967,7 @@ static id gs_weak_load(id obj)
*/
- (oneway void) release
{
if (NSDecrementExtraRefCountWasZero(self))
{
# ifdef OBJC_CAP_ARC
objc_delete_weak_refs(self);
# endif
[self dealloc];
}
objc_release_fast_np(self);
}
/**
@ -1958,8 +2026,7 @@ static id gs_weak_load(id obj)
*/
- (id) retain
{
NSIncrementExtraRefCount(self);
return self;
return objc_retain_fast_np(self);
}
/**
@ -1983,7 +2050,7 @@ static id gs_weak_load(id obj)
*/
- (NSUInteger) retainCount
{
return NSExtraRefCount(self) + 1;
return object_getRetainCount_np(self);
}
/**

View file

@ -1,6 +1,9 @@
#import "ObjectTesting.h"
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSProxy.h>
#if __has_include(<objc/capabilities.h>)
#include <objc/capabilities.h>
#endif
int main()
{
@ -24,8 +27,10 @@ int main()
obj1 = [NSProxy allocWithZone:testZone];
PASS(obj1 != nil, "%s has working allocWithZone:",prefix);
#ifndef OBJC_CAP_ARC
PASS(NSZoneFromPointer(obj1) == testZone, "%s uses zone for alloc",prefix);
PASS([obj1 zone] == testZone, "%s -zone works",prefix);
#endif
PASS([obj1 hash] != 0, "%s has working -hash",prefix);
PASS([obj1 isEqual:obj1] == YES, "%s has working -isEqual:",prefix);