Index: accessors.m
===================================================================
--- accessors.m	(revision 0)
+++ accessors.m	(revision 0)
@@ -0,0 +1,279 @@
+/* GNU Objective C Runtime accessors functions
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by Nicola Pero
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 3, or (at your option) any later version.
+
+GCC 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 General Public License for more
+details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "objc-private/common.h"
+#include "objc/objc.h"
+#include "objc/thr.h"
+#include <string.h>                    /* For memcpy */
+
+/* This file contains functions that the compiler uses when
+   synthesizing accessors (getters/setters) for properties.  The
+   functions are part of the ABI, but are meant to be used by the
+   compiler and not by users; for this reason, they are not declared
+   in public header files.  The compiler automatically generates
+   declarations for these functions.  */
+
+/* Properties can be "atomic", which requires protecting them from
+   concurrency issues using a lock.  Unfortunately, we can't have a
+   lock for each property, so we'll go with a small pool of locks.
+   Any time a property is accessed in an "atomic" way, we pick a
+   random lock from the pool (random, but always the same one for the
+   same property of the same object) and use it to protect access to
+   the property.
+
+   The size of the pool is currently 16.  A bigger pool can help
+   reduce contention, ie, reduce the chances that two threads,
+   operating on unrelated properties, will have to wait for each other
+   because the properties use the same lock.  16 seems big enough at
+   the moment.  */
+#define ACCESSORS_NUMBER_OF_LOCKS 16
+
+#define ACCESSORS_HASH(POINTER) ((((size_t)POINTER >> 8) ^ (size_t)POINTER) & (ACCESSORS_NUMBER_OF_LOCKS - 1))
+
+static objc_mutex_t accessors_locks[ACCESSORS_NUMBER_OF_LOCKS];
+
+/* This is called at startup to setup the locks.  */
+void
+__objc_accessors_init (void)
+{
+  int i;
+
+  for (i = 0; i < ACCESSORS_NUMBER_OF_LOCKS; i++)
+    accessors_locks[i] = objc_mutex_allocate ();
+}
+
+/* The property accessors automatically call various methods from the
+   Foundation library (eg, GNUstep-base).  These methods are not
+   implemented here, but we need to declare them so we can compile the
+   runtime.  The Foundation library will need to provide
+   implementations of these methods (most likely in the root class,
+   eg, NSObject) as the accessors only work with objects of classes
+   that implement these methods.  */
+@interface _libobjcNSObject
+- (id) copyWithZone: (void *)zone;
+- (id) mutableCopyWithZone: (void *)zone;
+@end
+#define COPY(X)         [((_libobjcNSObject *)(X)) copyWithZone: NULL]
+#define MUTABLE_COPY(X) [((_libobjcNSObject *)(X)) mutableCopyWithZone: NULL]
+
+
+#if OBJC_WITH_GC
+
+#  define AUTORELEASE(X)  (X)
+#  define RELEASE(X)
+#  define RETAIN(X)       (X)
+
+#else
+
+@interface _libobjcNSObject (RetainReleaseMethods)
+- (id) autorelease;
+- (oneway void) release;
+- (id) retain;
+@end
+#  define AUTORELEASE(X)  [((_libobjcNSObject *)(X)) autorelease]
+#  define RELEASE(X)      [((_libobjcNSObject *)(X)) release]
+#  define RETAIN(X)       [((_libobjcNSObject *)(X)) retain]
+
+#endif
+
+/* The compiler uses this function when implementing some synthesized
+   getters for properties of type 'id'.  */
+id
+objc_getProperty (id self, SEL __attribute__((unused)) _cmd, ptrdiff_t offset, BOOL is_atomic)
+{
+  if (self != nil)
+    {
+      id *pointer_to_ivar = (id *)((char *)self + offset);
+
+      if (is_atomic == NO)
+	return AUTORELEASE (RETAIN (*pointer_to_ivar));
+      else
+	{
+	  objc_mutex_t lock = accessors_locks[ACCESSORS_HASH (pointer_to_ivar)];
+	  id result;
+	  
+	  objc_mutex_lock (lock);
+	  result = RETAIN (*(pointer_to_ivar));
+	  objc_mutex_unlock (lock);
+	  
+	  return AUTORELEASE (result);
+	}
+    }
+
+  return nil;
+}
+
+/* The compiler uses this function when implementing some synthesized
+   setters for properties of type 'id'.
+
+   PS: Note how 'should_copy' is declared 'BOOL' but then actually
+   takes values from 0 to 2.  This hack was introduced by Apple; we
+   do the same for compatibility reasons.  */
+void
+objc_setProperty (id self, SEL __attribute__((unused)) _cmd, ptrdiff_t offset, id new_value, BOOL is_atomic, BOOL should_copy)
+{
+  if (self != nil)
+    {
+      id *pointer_to_ivar = (id *)((char *)self + offset);
+      id retained_value;
+#if !OBJC_WITH_GC
+      id old_value;
+#endif
+
+      switch (should_copy)
+	{
+	case 0: /* retain */
+	  {
+	    if (*pointer_to_ivar == new_value)
+	      return;
+	    retained_value = RETAIN (new_value);
+	    break;
+	  }
+	case 2: /* mutable copy */
+	  {
+	    retained_value = MUTABLE_COPY (new_value);
+	    break;
+	  }
+	case 1: /* copy */
+	default:
+	  {
+	    retained_value = COPY (new_value);
+	    break;
+	  }
+	}
+
+      if (is_atomic == NO)
+	{
+#if !OBJC_WITH_GC
+	  old_value = *pointer_to_ivar;
+#endif
+	  *pointer_to_ivar = retained_value;
+	}
+      else
+	{
+	  objc_mutex_t lock = accessors_locks[ACCESSORS_HASH (pointer_to_ivar)];
+
+	  objc_mutex_lock (lock);
+#if !OBJC_WITH_GC
+	  old_value = *pointer_to_ivar;
+#endif
+	  *pointer_to_ivar = retained_value;
+	  objc_mutex_unlock (lock);
+	}
+#if !OBJC_WITH_GC
+      RELEASE (old_value);
+#endif
+    }
+}
+
+/* The compiler uses this function when implementing some synthesized
+   getters for properties of arbitrary C types.  The data is just
+   copied.  Compatibility Note: this function does not exist in the
+   Apple/NeXT runtime.  */
+void
+objc_getPropertyStruct (void *destination, const void *source, ptrdiff_t size, BOOL is_atomic, BOOL __attribute__((unused)) has_strong)
+{
+  if (is_atomic == NO)
+    memcpy (destination, source, size);
+  else
+    {
+      objc_mutex_t lock = accessors_locks[ACCESSORS_HASH (source)];
+
+      objc_mutex_lock (lock);
+      memcpy (destination, source, size);
+      objc_mutex_unlock (lock);
+    }
+}
+
+/* The compiler uses this function when implementing some synthesized
+   setters for properties of arbitrary C types.  The data is just
+   copied.  Compatibility Note: this function does not exist in the
+   Apple/NeXT runtime.  */
+void
+objc_setPropertyStruct (void *destination, const void *source, ptrdiff_t size, BOOL is_atomic, BOOL __attribute__((unused)) has_strong)
+{
+  if (is_atomic == NO)
+    memcpy (destination, source, size);
+  else
+    {
+      objc_mutex_t lock = accessors_locks[ACCESSORS_HASH (destination)];
+
+      objc_mutex_lock (lock);
+      memcpy (destination, source, size);
+      objc_mutex_unlock (lock);
+    }
+}
+
+/* This is the function that the Apple/NeXT runtime has instead of
+   objc_getPropertyStruct and objc_setPropertyStruct.  We include it
+   for API compatibility (just for people who may have used
+   objc_copyStruct on the NeXT runtime thinking it was a public API);
+   the compiler never generates calls to it with the GNU runtime.
+   This function is clumsy because it requires two locks instead of
+   one.  */
+void
+objc_copyStruct (void *destination, const void *source, ptrdiff_t size, BOOL is_atomic, BOOL __attribute__((unused)) has_strong)
+{
+  if (is_atomic == NO)
+    memcpy (destination, source, size);
+  else
+    {
+      /* We don't know which one is the property, so we have to lock
+	 both.  One of them is most likely a temporary buffer in the
+	 local stack and we really wouldn't want to lock it (our
+	 objc_getPropertyStruct and objc_setPropertyStruct functions
+	 don't lock it).  Note that if we're locking more than one
+	 accessor lock at once, we need to always lock them in the
+	 same order to avoid deadlocks.  */
+      objc_mutex_t first_lock;
+      objc_mutex_t second_lock;
+
+      if (ACCESSORS_HASH (source) == ACCESSORS_HASH (destination))
+	{
+	  /* A lucky collision.  */
+	  first_lock = accessors_locks[ACCESSORS_HASH (source)];
+	  objc_mutex_lock (first_lock);
+	  memcpy (destination, source, size);
+	  objc_mutex_unlock (first_lock);
+	  return;
+	}
+
+      if (ACCESSORS_HASH (source) > ACCESSORS_HASH (destination))
+	{
+	  first_lock = accessors_locks[ACCESSORS_HASH (source)];
+	  second_lock = accessors_locks[ACCESSORS_HASH (destination)];
+	}
+      else
+	{
+	  first_lock = accessors_locks[ACCESSORS_HASH (destination)];
+	  second_lock = accessors_locks[ACCESSORS_HASH (source)];	  
+	}
+
+      objc_mutex_lock (first_lock);
+      objc_mutex_lock (second_lock);
+      memcpy (destination, source, size);
+      objc_mutex_unlock (second_lock);
+      objc_mutex_unlock (first_lock);
+    }
+}
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 165900)
+++ Makefile.in	(working copy)
@@ -163,6 +163,7 @@ OBJC_SOURCE_FILES = \
    NXConstStr.m \
    Object.m \
    Protocol.m \
+   accessors.m \
    linking.m
 
 # C source files to compile
Index: init.c
===================================================================
--- init.c	(revision 165900)
+++ init.c	(working copy)
@@ -35,6 +35,7 @@ see the files COPYING3 and COPYING.RUNTIME respect
 #include "objc-private/protocols.h" /* For __objc_protocols_init(),
 				       __objc_protocols_add_protocol()
 				       __objc_protocols_register_selectors() */
+#include "objc-private/accessors.h" /* For __objc_accessors_init() */
 
 /* The version number of this runtime.  This must match the number 
    defined in gcc (objc-act.c).  */
@@ -582,6 +583,7 @@ __objc_exec_class (Module_t module)
 					   (hash_func_type)objc_hash_ptr,
 					   objc_compare_ptrs);
       __objc_protocols_init ();
+      __objc_accessors_init ();
       __objc_sync_init ();
       previous_constructors = 1;
     }
Index: objc-private/accessors.h
===================================================================
--- objc-private/accessors.h	(revision 0)
+++ objc-private/accessors.h	(revision 0)
@@ -0,0 +1,40 @@
+/* GNU Objective C Runtime accessors - Private Declarations
+   Copyright (C) 2010 Free Software Foundation, Inc.
+   Contributed by Nicola Pero <nicola.pero@meta-innovation.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 3, or (at your option) any later version.
+
+GCC 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 General Public License for more
+details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef __objc_private_accessors_INCLUDE_GNU
+#define __objc_private_accessors_INCLUDE_GNU
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* This function needs to be called at startup by init.c.  */
+void
+__objc_accessors_init (void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* not __objc_private_accessors_INCLUDE_GNU */
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 165900)
+++ ChangeLog	(working copy)
@@ -1,3 +1,11 @@
+2010-10-24  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* Makefile.in (OBJC_SOURCE_FILES): Added accessors.m.
+	* accessors.m: New.
+	* init.c: Include objc-private/accessors.h.
+	(__objc_exec_class): Call __objc_accessors_init.
+	* objc-private/accessors.h: New.
+
 2010-10-17  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* objc/message.h: Moved initial includes outside of extern "C".
