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

Reply via email to