Author: paullanders Date: Fri Nov 11 19:19:32 2016 New Revision: 40217 URL: http://svn.gna.org/viewcvs/gnustep?rev=40217&view=rev Log: Merge NSObject changes from trunk instead of my previous commit. Fixes retain and release compatibility with libobjc2 in a platform safe way.
Modified: libs/base/branches/gnustep_testplant_branch/Source/NSObject.m Modified: libs/base/branches/gnustep_testplant_branch/Source/NSObject.m URL: http://svn.gna.org/viewcvs/gnustep/libs/base/branches/gnustep_testplant_branch/Source/NSObject.m?rev=40217&r1=40216&r2=40217&view=diff ============================================================================== --- libs/base/branches/gnustep_testplant_branch/Source/NSObject.m (original) +++ libs/base/branches/gnustep_testplant_branch/Source/NSObject.m Fri Nov 11 19:19:32 2016 @@ -1,26 +1,20 @@ /** Implementation of NSObject for GNUStep Copyright (C) 1994-2010 Free Software Foundation, Inc. - Written by: Andrew Kachites McCallum <mccal...@gnu.ai.mit.edu> Date: August 1994 - This file is part of the GNUstep Base Library. - This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. - <title>NSObject class reference</title> $Date$ $Revision$ */ @@ -113,11 +107,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,15 +180,28 @@ #endif +/* 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: + * + * a) sizeof(intptr_t) == sizeof(int32_t) + * b) we can provide atomic operations on pointer sized values, allowing + * us to extend the refcount to intptr_t. + */ +#ifdef GS_ARC_COMPATIBLE +#undef GS_ARC_COMPATIBLE +#endif #if defined(__llvm__) || (defined(USE_ATOMIC_BUILTINS) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))) /* Use the GCC atomic operations with recent GCC versions */ -typedef int32_t volatile *gsatomic_t; +typedef intptr_t volatile *gsatomic_t; +typedef intptr_t gsrefcount_t; #define GSATOMICREAD(X) (*(X)) #define GSAtomicIncrement(X) __sync_add_and_fetch(X, 1) #define GSAtomicDecrement(X) __sync_sub_and_fetch(X, 1) - +#define GS_ARC_COMPATIBLE 1 #elif defined(_WIN32) @@ -203,7 +209,7 @@ */ typedef int32_t volatile *gsatomic_t; - +typedef int32_t gsrefcount_t; #ifndef _WIN64 #undef InterlockedIncrement #undef InterlockedDecrement @@ -221,6 +227,7 @@ */ typedef int32_t volatile *gsatomic_t; +typedef int32_t gsrefcount_t; #define GSATOMICREAD(X) (*(X)) @@ -254,6 +261,7 @@ #elif defined(__PPC__) || defined(__POWERPC__) typedef int32_t volatile *gsatomic_t; +typedef int32_t gsrefcount_t; #define GSATOMICREAD(X) (*(X)) @@ -292,6 +300,7 @@ #elif defined(__m68k__) typedef int32_t volatile *gsatomic_t; +typedef int32_t gsrefcount_t; #define GSATOMICREAD(X) (*(X)) @@ -316,6 +325,7 @@ #elif defined(__mips__) typedef int32_t volatile *gsatomic_t; +typedef int32_t gsrefcount_t; #define GSATOMICREAD(X) (*(X)) @@ -356,8 +366,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 @@ -382,6 +391,17 @@ #endif +#ifndef GS_ARC_COMPATIBLE +/* + * If we haven't previously declared that we can work in fast-ARC mode, + * check whether a point is 32bit (4 bytes) wide, which also enables ARC + * integration. + */ +# if __SIZEOF_POINTER__ == 4 +# define GS_ARC_COMPATIBLE 1 +# endif +#endif + #if defined(__GNUC__) && __GNUC__ < 4 #define __builtin_offsetof(s, f) (uintptr_t)(&(((s*)0)->f)) #endif @@ -392,7 +412,7 @@ * (before the start) in each object. */ typedef struct obj_layout_unpadded { - uintptr_t retained; + gsrefcount_t retained; } unp; #define UNP sizeof(unp) @@ -412,7 +432,7 @@ struct obj_layout { char padding[__BIGGEST_ALIGNMENT__ - ((UNP % __BIGGEST_ALIGNMENT__) ? (UNP % __BIGGEST_ALIGNMENT__) : __BIGGEST_ALIGNMENT__)]; - uintptr_t retained; + gsrefcount_t retained; }; typedef struct obj_layout *obj; @@ -423,7 +443,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) @@ -435,58 +455,45 @@ [NSException raise: NSGenericException format: @"Release would release object too many times."]; } - if (allocationLock != 0) - { + { #if defined(GSATOMICREAD) - int32_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; } @@ -510,42 +517,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 @@ -597,6 +592,8 @@ * the start of each object. */ +// FIXME rewrite object allocation to use class_createInstance when we +// are using libobjc2. inline id NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone) { @@ -735,23 +732,9 @@ * </p> */ @implementation NSObject +#if defined(GS_ARC_COMPATIBLE) - (void)_ARCCompliantRetainRelease {} - -+ (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]; - } -} +#endif /** * Semi-private function in libobjc2 that initialises the classes used for @@ -849,6 +832,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 @@ -897,15 +895,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