OSDN Git Service

PR target/23424
[pf3gnuchains/gcc-fork.git] / libobjc / selector.c
index 11f75f0..223c710 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU Objective C Runtime selector related functions
-   Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004 Free Software Foundation, Inc.
    Contributed by Kresten Krab Thorup
 
 This file is part of GCC.
@@ -15,7 +15,7 @@ details.
 
 You should have received a copy of the GNU General Public License along with
 GCC; see the file COPYING.  If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* As a special exception, if you link this library with files compiled with
    GCC to produce an executable, this does not cause the resulting executable
@@ -23,9 +23,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
    however invalidate any other reasons why the executable file might be
    covered by the GNU General Public License.  */
 
-#include "runtime.h"
-#include "sarray.h"
-#include "encoding.h"
+#include "objc/runtime.h"
+#include "objc/sarray.h"
+#include "objc/encoding.h"
 
 /* Initial selector hash table size. Value doesn't matter much */
 #define SELECTOR_HASH_SIZE 128
@@ -35,19 +35,17 @@ static struct sarray *__objc_selector_array = 0; /* uid -> sel  !T:MUTEX */
 static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
 static cache_ptr      __objc_selector_hash  = 0; /* name -> uid !T:MUTEX */
 
-static void register_selectors_from_list (MethodList_t);
-
 /* Number of selectors stored in each of the above tables */
 unsigned int __objc_selector_max_index = 0;     /* !T:MUTEX */
 
-void __objc_init_selector_tables ()
+void __objc_init_selector_tables (void)
 {
   __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
   __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
   __objc_selector_hash
-    = hash_new (SELECTOR_HASH_SIZE,
-               (hash_func_type) hash_string,
-               (compare_func_type) compare_strings);
+    = objc_hash_new (SELECTOR_HASH_SIZE,
+                    (hash_func_type) objc_hash_string,
+                    (compare_func_type) objc_compare_strings);
 }  
 
 /* This routine is given a class and records all of the methods in its class
@@ -60,7 +58,7 @@ __objc_register_selectors_from_class (Class class)
   method_list = class->methods;
   while (method_list)
     {
-      register_selectors_from_list (method_list);
+      __objc_register_selectors_from_list (method_list);
       method_list = method_list->method_next;
     }
 }
@@ -70,21 +68,27 @@ __objc_register_selectors_from_class (Class class)
    the record table.  This is the routine that does the actual recording
    work.
 
-   This one is only called for Class objects.  For categories,
-   class_add_method_list is called.
+   The name and type pointers in the method list must be permanent and
+   immutable.
    */
-static void
-register_selectors_from_list (MethodList_t method_list)
+void
+__objc_register_selectors_from_list (MethodList_t method_list)
 {
   int i = 0;
+
+  objc_mutex_lock (__objc_runtime_mutex);
   while (i < method_list->method_count)
     {
       Method_t method = &method_list->method_list[i];
-      method->method_name 
-       = sel_register_typed_name ((const char *) method->method_name, 
-                                  method->method_types);
+      if (method->method_name)
+       {
+         method->method_name
+           = __sel_register_typed_name ((const char *) method->method_name,
+                                        method->method_types, 0, YES);
+       }
       i += 1;
     }
+  objc_mutex_unlock (__objc_runtime_mutex);
 }
 
 
@@ -148,6 +152,8 @@ void __objc_register_instance_methods_to_class (Class class)
       new_list->method_next = class->class_pointer->methods;
       class->class_pointer->methods = new_list;
     }
+  else
+    objc_free(new_list);
 
     __objc_update_dispatch_table_for_class (class->class_pointer);
 }
@@ -189,7 +195,7 @@ sel_get_typed_uid (const char *name, const char *types)
 
   objc_mutex_lock (__objc_runtime_mutex);
 
-  i = (sidx) hash_value_for_key (__objc_selector_hash, name);
+  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
   if (i == 0)
     {
       objc_mutex_unlock (__objc_runtime_mutex);
@@ -229,7 +235,7 @@ sel_get_any_typed_uid (const char *name)
 
   objc_mutex_lock (__objc_runtime_mutex);
 
-  i = (sidx) hash_value_for_key (__objc_selector_hash, name);
+  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
   if (i == 0)
     {
       objc_mutex_unlock (__objc_runtime_mutex);
@@ -260,7 +266,7 @@ sel_get_any_uid (const char *name)
 
   objc_mutex_lock (__objc_runtime_mutex);
 
-  i = (sidx) hash_value_for_key (__objc_selector_hash, name);
+  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
   if (soffset_decode (i) == 0)
     {
       objc_mutex_unlock (__objc_runtime_mutex);
@@ -318,6 +324,35 @@ const char *sel_get_type (SEL selector)
 /* The uninstalled dispatch table */
 extern struct sarray *__objc_uninstalled_dtable;
 
+/* __sel_register_typed_name allocates lots of struct objc_selector:s
+   of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the number
+   of malloc calls and memory lost to malloc overhead, we allocate
+   objc_selector:s in blocks here. This is only called from
+   __sel_register_typed_name, and __sel_register_typed_name may only be
+   called when __objc_runtime_mutex is locked.
+
+   Note that the objc_selector:s allocated from __sel_register_typed_name
+   are never freed.
+
+   62 because 62 * sizeof (struct objc_selector) = 496 (992). This should
+   let malloc add some overhead and use a nice, round 512 (1024) byte chunk.
+   */
+#define SELECTOR_POOL_SIZE 62
+static struct objc_selector *selector_pool;
+static int selector_pool_left;
+
+static struct objc_selector *
+pool_alloc_selector(void)
+{
+  if (!selector_pool_left)
+    {
+      selector_pool = objc_malloc (sizeof (struct objc_selector)
+                                  * SELECTOR_POOL_SIZE);
+      selector_pool_left = SELECTOR_POOL_SIZE;
+    }
+  return &selector_pool[--selector_pool_left];
+}
+
 /* Store the passed selector name in the selector record and return its
    selector value (value returned by sel_get_uid).
    Assumes that the calling function has locked down __objc_runtime_mutex. */
@@ -333,7 +368,7 @@ __sel_register_typed_name (const char *name, const char *types,
   sidx i;
   struct objc_list *l;
 
-  i = (sidx) hash_value_for_key (__objc_selector_hash, name);
+  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
   if (soffset_decode (i) != 0)
     {
       for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
@@ -367,7 +402,7 @@ __sel_register_typed_name (const char *name, const char *types,
       if (orig)
        j = orig;
       else
-       j = objc_malloc (sizeof (struct objc_selector));
+       j = pool_alloc_selector ();
 
       j->sel_id = (void *) i;
       /* Can we use the pointer or must copy types?  Don't copy if NULL */
@@ -386,7 +421,7 @@ __sel_register_typed_name (const char *name, const char *types,
       if (orig)
        j = orig;
       else
-       j = objc_malloc (sizeof (struct objc_selector));
+       j = pool_alloc_selector ();
        
       j->sel_id = (void *) i;
       /* Can we use the pointer or must copy types?  Don't copy if NULL */
@@ -400,7 +435,7 @@ __sel_register_typed_name (const char *name, const char *types,
     }
 
   DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types, 
-               soffset_decode (i));
+               (long) soffset_decode (i));
   
   {
     int is_new = (l == 0);
@@ -418,7 +453,7 @@ __sel_register_typed_name (const char *name, const char *types,
     sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
     sarray_at_put_safe (__objc_selector_array, i, (void *) l);
     if (is_new)
-      hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
+      objc_hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
   }
 
   sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
@@ -444,7 +479,7 @@ SEL
 sel_register_typed_name (const char *name, const char *type)
 {
   SEL ret;
-    
+
   objc_mutex_lock (__objc_runtime_mutex);
   /* Assume that name and type are not constant static memory and need to
      be copied before put into a runtime structure.  is_const == NO */