Author: rfm Date: Tue Nov 8 11:21:00 2016 New Revision: 40196 URL: http://svn.gna.org/viewcvs/gnustep?rev=40196&view=rev Log: fix crash and other memory management tweaks
Modified: libs/base/trunk/ChangeLog libs/base/trunk/Source/NSObject.m Modified: libs/base/trunk/ChangeLog URL: http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/ChangeLog?rev=40196&r1=40195&r2=40196&view=diff ============================================================================== --- libs/base/trunk/ChangeLog (original) +++ libs/base/trunk/ChangeLog Tue Nov 8 11:21:00 2016 @@ -1,6 +1,13 @@ +2016-11-08 Richard Frith-Macdonald <r...@gnu.org> + + * Source/NSObject.m: Fix error in last mod ... was calculating opbject + layout incorrectly when fast-ARC moce used on 64bit system. + Also simplified by removing special case optimising for single-threaded + programs and use inline decrement to improve performance of release. + 2016-10-28 Niels Grewe <niels.gr...@halbordnung.de> - * Source/NSObject.m: Re-enable fast-ARC mode when memory layout + * Source/NSObject.m: Re-enable fast-ARC mode when memory layout and atomic operations support permit. This changes the size of the field where the reference count is stored to the size of a pointer in some configurations. Modified: libs/base/trunk/Source/NSObject.m URL: http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/NSObject.m?rev=40196&r1=40195&r2=40196&view=diff ============================================================================== --- libs/base/trunk/Source/NSObject.m (original) +++ libs/base/trunk/Source/NSObject.m Tue Nov 8 11:21:00 2016 @@ -113,11 +113,10 @@ - (id) initWithObject: (id)anObject; @end -/* - * allocationLock is needed when running multi-threaded for - * protecting the map table of zombie information. - */ -static NSLock *allocationLock; +/* allocationLock is needed when for protecting the map table of zombie + * information and if atomic operations are not available. + */ +static NSLock *allocationLock = nil; BOOL NSZombieEnabled = NO; BOOL NSDeallocateZombies = NO; @@ -187,8 +186,7 @@ #endif -/* - * Traditionally, GNUstep has been using a 32bit reference count in front +/* Traditionally, GNUstep has been using a 32bit reference count in front * of the object. The automatic reference counting implementation in * libobjc2 uses an intptr_t instead, so NSObject will only be compatible * with ARC if either of the following apply: @@ -374,8 +372,7 @@ #if !defined(GSATOMICREAD) -/* - * Having just one allocationLock for all leads to lock contention +/* Having just one allocationLock for all leads to lock contention * if there are lots of threads doing lots of retain/release calls. * To alleviate this, instead of a single * allocationLock for all objects, we divide the object space into @@ -421,7 +418,7 @@ * (before the start) in each object. */ typedef struct obj_layout_unpadded { - int32_t retained; + gsrefcount_t retained; } unp; #define UNP sizeof(unp) @@ -441,7 +438,7 @@ struct obj_layout { char padding[__BIGGEST_ALIGNMENT__ - ((UNP % __BIGGEST_ALIGNMENT__) ? (UNP % __BIGGEST_ALIGNMENT__) : __BIGGEST_ALIGNMENT__)]; - int32_t retained; + gsrefcount_t retained; }; typedef struct obj_layout *obj; @@ -452,7 +449,7 @@ * (and hence whether the extra reference count was decremented).<br /> * This function is used by the [NSObject-release] method. */ -BOOL +inline BOOL NSDecrementExtraRefCountWasZero(id anObject) { if (double_release_check_enabled) @@ -464,58 +461,45 @@ [NSException raise: NSGenericException format: @"Release would release object too many times."]; } - if (allocationLock != 0) - { + { #if defined(GSATOMICREAD) - gsrefcount_t result; - - result = GSAtomicDecrement((gsatomic_t)&(((obj)anObject)[-1].retained)); - if (result < 0) - { - if (result != -1) - { - [NSException raise: NSInternalInconsistencyException - format: @"NSDecrementExtraRefCount() decremented too far"]; - } - /* The counter has become negative so it must have been zero. - * We reset it and return YES ... in a correctly operating - * process we know we can safely reset back to zero without - * worrying about atomicity, since there can be no other - * thread accessing the object (or its reference count would - * have been greater than zero) - */ - (((obj)anObject)[-1].retained) = 0; - return YES; - } + gsrefcount_t result; + + result = GSAtomicDecrement((gsatomic_t)&(((obj)anObject)[-1].retained)); + if (result < 0) + { + if (result != -1) + { + [NSException raise: NSInternalInconsistencyException + format: @"NSDecrementExtraRefCount() decremented too far"]; + } + /* The counter has become negative so it must have been zero. + * We reset it and return YES ... in a correctly operating + * process we know we can safely reset back to zero without + * worrying about atomicity, since there can be no other + * thread accessing the object (or its reference count would + * have been greater than zero) + */ + (((obj)anObject)[-1].retained) = 0; + return YES; + } #else /* GSATOMICREAD */ - NSLock *theLock = GSAllocationLockForObject(anObject); - - [theLock lock]; - if (((obj)anObject)[-1].retained == 0) - { - [theLock unlock]; - return YES; - } - else - { - ((obj)anObject)[-1].retained--; - [theLock unlock]; - return NO; - } + NSLock *theLock = GSAllocationLockForObject(anObject); + + [theLock lock]; + if (((obj)anObject)[-1].retained == 0) + { + [theLock unlock]; + return YES; + } + else + { + ((obj)anObject)[-1].retained--; + [theLock unlock]; + return NO; + } #endif /* GSATOMICREAD */ - } - else - { - if (((obj)anObject)[-1].retained == 0) - { - return YES; - } - else - { - ((obj)anObject)[-1].retained--; - return NO; - } - } + } return NO; } @@ -539,42 +523,30 @@ inline void NSIncrementExtraRefCount(id anObject) { - if (allocationLock != 0) - { #if defined(GSATOMICREAD) - /* I've seen comments saying that some platforms only support up to - * 24 bits in atomic locking, so raise an exception if we try to - * go beyond 0xfffffe. - */ - if (GSAtomicIncrement((gsatomic_t)&(((obj)anObject)[-1].retained)) - > 0xfffffe) - { - [NSException raise: NSInternalInconsistencyException - format: @"NSIncrementExtraRefCount() asked to increment too far"]; - } + /* I've seen comments saying that some platforms only support up to + * 24 bits in atomic locking, so raise an exception if we try to + * go beyond 0xfffffe. + */ + if (GSAtomicIncrement((gsatomic_t)&(((obj)anObject)[-1].retained)) + > 0xfffffe) + { + [NSException raise: NSInternalInconsistencyException + format: @"NSIncrementExtraRefCount() asked to increment too far"]; + } #else /* GSATOMICREAD */ - NSLock *theLock = GSAllocationLockForObject(anObject); - - [theLock lock]; - if (((obj)anObject)[-1].retained > 0xfffffe) - { - [theLock unlock]; - [NSException raise: NSInternalInconsistencyException - format: @"NSIncrementExtraRefCount() asked to increment too far"]; - } - ((obj)anObject)[-1].retained++; + NSLock *theLock = GSAllocationLockForObject(anObject); + + [theLock lock]; + if (((obj)anObject)[-1].retained > 0xfffffe) + { [theLock unlock]; + [NSException raise: NSInternalInconsistencyException + format: @"NSIncrementExtraRefCount() asked to increment too far"]; + } + ((obj)anObject)[-1].retained++; + [theLock unlock]; #endif /* GSATOMICREAD */ - } - else - { - if (((obj)anObject)[-1].retained > 0xfffffe) - { - [NSException raise: NSInternalInconsistencyException - format: @"NSIncrementExtraRefCount() asked to increment too far"]; - } - ((obj)anObject)[-1].retained++; - } } #ifndef NDEBUG @@ -769,22 +741,6 @@ #if defined(GS_ARC_COMPATIBLE) - (void)_ARCCompliantRetainRelease {} #endif - -+ (void) _becomeMultiThreaded: (NSNotification *)aNotification -{ - if (allocationLock == 0) - { -#if !defined(GSATOMICREAD) - NSUInteger i; - - for (i = 0; i < LOCKCOUNT; i++) - { - allocationLocks[i] = [NSLock new]; - } -#endif - allocationLock = [NSLock new]; - } -} /** * Semi-private function in libobjc2 that initialises the classes used for @@ -882,6 +838,21 @@ # endif #endif + /* Create the lock for NSZombie and for allocation when atomic + * operations are not available. + */ + allocationLock = [NSLock new]; +#if !defined(GSATOMICREAD) + { + NSUInteger i; + + for (i = 0; i < LOCKCOUNT; i++) + { + allocationLocks[i] = [NSLock new]; + } + } +#endif + /* Create the global lock. * NB. Ths is one of the first things we do ... setting up a new lock * must not call any other Objective-C classes and must not involve @@ -930,15 +901,6 @@ * object, and that class hasn't been initialized yet ... */ zombieClass = objc_lookUpClass("NSZombie"); - - /* Now that we have a working autorelease system and working string - * classes we are able to set up notifications. - */ - [[NSNotificationCenter defaultCenter] - addObserver: self - selector: @selector(_becomeMultiThreaded:) - name: NSWillBecomeMultiThreadedNotification - object: nil]; } return; } _______________________________________________ Gnustep-cvs mailing list Gnustep-cvs@gna.org https://mail.gna.org/listinfo/gnustep-cvs