OSDN Git Service

Add brackets around AC_TRY_COMPILE alternative.
[pf3gnuchains/gcc-fork.git] / libobjc / selector.c
index 83c70e4..226ef7d 100644 (file)
@@ -1,53 +1,51 @@
 /* GNU Objective C Runtime selector related functions
-   Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004, 2009 Free Software Foundation, Inc.
    Contributed by Kresten Krab Thorup
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify it under the
+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 2, or (at your option) any later version.
+Foundation; either version 3, or (at your option) any later version.
 
-GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
+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.
 
-You should have received a copy of the GNU General Public License along with
-GNU CC; see the file COPYING.  If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+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.
 
-/* 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
-   to be covered by the GNU General Public License. This exception does not
-   however invalidate any other reasons why the executable file might be
-   covered by the GNU General Public License.  */
+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 "runtime.h"
+
+#include "objc/runtime.h"
 #include "objc/sarray.h"
-#include "encoding.h"
+#include "objc/encoding.h"
 
 /* Initial selector hash table size. Value doesn't matter much */
 #define SELECTOR_HASH_SIZE 128
 
 /* Tables mapping selector names to uid and opposite */
-static struct sarray__objc_selector_array = 0; /* uid -> sel  !T:MUTEX */
-static struct sarray__objc_selector_names = 0; /* uid -> name !T:MUTEX */
+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 */
-int __objc_selector_max_index = 0;              /* !T:MUTEX */
+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,26 +68,32 @@ __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);
 }
 
 
 /* Register instance methods as class methods for root classes */
-void __objc_register_instance_methods_to_class(Class class)
+void __objc_register_instance_methods_to_class (Class class)
 {
   MethodList_t method_list;
   MethodList_t class_method_list;
@@ -98,12 +102,12 @@ void __objc_register_instance_methods_to_class(Class class)
   Method_t curr_method;
 
   /* Only if a root class. */
-  if(class->super_class)
+  if (class->super_class)
     return;
 
   /* Allocate a method list to hold the new class methods */
-  new_list = objc_calloc(sizeof(struct objc_method_list)
-                           + sizeof(struct objc_method[max_methods_no]), 1);
+  new_list = objc_calloc (sizeof (struct objc_method_list)
+                           + sizeof (struct objc_method[max_methods_no]), 1);
   method_list = class->methods;
   class_method_list = class->class_pointer->methods;
   curr_method = &new_list->method_list[0];
@@ -118,7 +122,7 @@ void __objc_register_instance_methods_to_class(Class class)
        {
          Method_t mth = &method_list->method_list[i];
          if (mth->method_name
-             && !search_for_method_in_list (class_method_list,
+             && ! search_for_method_in_list (class_method_list,
                                              mth->method_name))
            {
              /* This instance method isn't a class method. 
@@ -126,10 +130,10 @@ void __objc_register_instance_methods_to_class(Class class)
              *curr_method = *mth;
   
              /* Reallocate the method list if necessary */
-             if(++new_list->method_count == max_methods_no)
+             if (++new_list->method_count == max_methods_no)
                new_list =
-                 objc_realloc(new_list, sizeof(struct objc_method_list)
-                               + sizeof(struct 
+                 objc_realloc (new_list, sizeof (struct objc_method_list)
+                               + sizeof (struct 
                                        objc_method[max_methods_no += 16]));
              curr_method = &new_list->method_list[new_list->method_count];
            }
@@ -143,11 +147,13 @@ void __objc_register_instance_methods_to_class(Class class)
   if (new_list->method_count)
     {
       new_list =
-       objc_realloc(new_list, sizeof(struct objc_method_list)
-                    + sizeof(struct objc_method[new_list->method_count]));
+       objc_realloc (new_list, sizeof (struct objc_method_list)
+                    + sizeof (struct objc_method[new_list->method_count]));
       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);
 }
@@ -156,21 +162,21 @@ void __objc_register_instance_methods_to_class(Class class)
 /* Returns YES iff t1 and t2 have same method types, but we ignore
    the argframe layout */
 BOOL
-sel_types_match (const char* t1, const char* t2)
+sel_types_match (const char *t1, const char *t2)
 {
-  if (!t1 || !t2)
+  if (! t1 || ! t2)
     return NO;
   while (*t1 && *t2)
     {
       if (*t1 == '+') t1++;
       if (*t2 == '+') t2++;
-      while (isdigit(*t1)) t1++;
-      while (isdigit(*t2)) t2++;
+      while (isdigit ((unsigned char) *t1)) t1++;
+      while (isdigit ((unsigned char) *t2)) t2++;
       /* xxx Remove these next two lines when qualifiers are put in
         all selectors, not just Protocol selectors. */
-      t1 = objc_skip_type_qualifiers(t1);
-      t2 = objc_skip_type_qualifiers(t2);
-      if (!*t1 && !*t2)
+      t1 = objc_skip_type_qualifiers (t1);
+      t2 = objc_skip_type_qualifiers (t2);
+      if (! *t1 && ! *t2)
        return YES;
       if (*t1 != *t2)
        return NO;
@@ -187,35 +193,35 @@ sel_get_typed_uid (const char *name, const char *types)
   struct objc_list *l;
   sidx i;
 
-  objc_mutex_lock(__objc_runtime_mutex);
+  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);
+      objc_mutex_unlock (__objc_runtime_mutex);
       return 0;
     }
 
-  for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
+  for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
        l; l = l->tail)
     {
-      SEL s = (SEL)l->head;
+      SEL s = (SEL) l->head;
       if (types == 0 || s->sel_types == 0)
        {
          if (s->sel_types == types)
            {
-             objc_mutex_unlock(__objc_runtime_mutex);
+             objc_mutex_unlock (__objc_runtime_mutex);
              return s;
            }
        }
       else if (sel_types_match (s->sel_types, types))
        {
-         objc_mutex_unlock(__objc_runtime_mutex);
+         objc_mutex_unlock (__objc_runtime_mutex);
          return s;
        }
     }
 
-  objc_mutex_unlock(__objc_runtime_mutex);
+  objc_mutex_unlock (__objc_runtime_mutex);
   return 0;
 }
 
@@ -227,27 +233,27 @@ sel_get_any_typed_uid (const char *name)
   sidx i;
   SEL s = NULL;
 
-  objc_mutex_lock(__objc_runtime_mutex);
+  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);
+      objc_mutex_unlock (__objc_runtime_mutex);
       return 0;
     }
 
-  for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
+  for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
        l; l = l->tail)
     {
       s = (SEL) l->head;
       if (s->sel_types)
        {
-           objc_mutex_unlock(__objc_runtime_mutex);
+           objc_mutex_unlock (__objc_runtime_mutex);
            return s;
        }
     }
 
-  objc_mutex_unlock(__objc_runtime_mutex);
+  objc_mutex_unlock (__objc_runtime_mutex);
   return s;
 }
 
@@ -258,22 +264,22 @@ sel_get_any_uid (const char *name)
   struct objc_list *l;
   sidx i;
 
-  objc_mutex_lock(__objc_runtime_mutex);
+  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);
+      objc_mutex_unlock (__objc_runtime_mutex);
       return 0;
     }
 
-  l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
-  objc_mutex_unlock(__objc_runtime_mutex);
+  l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
+  objc_mutex_unlock (__objc_runtime_mutex);
 
   if (l == 0)
     return 0;
 
-  return (SEL)l->head;
+  return (SEL) l->head;
 }
 
 /* return selector representing name */
@@ -285,18 +291,17 @@ sel_get_uid (const char *name)
 
 /* Get name of selector.  If selector is unknown, the empty string "" 
    is returned */ 
-const char*
-sel_get_name (SEL selector)
+const char *sel_get_name (SEL selector)
 {
   const char *ret;
 
-  objc_mutex_lock(__objc_runtime_mutex);
-  if ((soffset_decode((sidx)selector->sel_id) > 0)
-      && (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index))
+  objc_mutex_lock (__objc_runtime_mutex);
+  if ((soffset_decode ((sidx)selector->sel_id) > 0)
+      && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
     ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
   else
     ret = 0;
-  objc_mutex_unlock(__objc_runtime_mutex);
+  objc_mutex_unlock (__objc_runtime_mutex);
   return ret;
 }
 
@@ -308,8 +313,7 @@ sel_is_mapped (SEL selector)
 }
 
 
-const char*
-sel_get_type (SEL selector)
+const char *sel_get_type (SEL selector)
 {
   if (selector)
     return selector->sel_types;
@@ -318,7 +322,36 @@ sel_get_type (SEL selector)
 }
 
 /* The uninstalled dispatch table */
-extern struct sarray* __objc_uninstalled_dtable;
+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).
@@ -331,35 +364,35 @@ SEL
 __sel_register_typed_name (const char *name, const char *types, 
                           struct objc_selector *orig, BOOL is_const)
 {
-  struct objc_selectorj;
+  struct objc_selector *j;
   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);
+      for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
           l; l = l->tail)
        {
-         SEL s = (SEL)l->head;
+         SEL s = (SEL) l->head;
          if (types == 0 || s->sel_types == 0)
            {
              if (s->sel_types == types)
                {
                  if (orig)
                    {
-                     orig->sel_id = (void*)i;
+                     orig->sel_id = (void *) i;
                      return orig;
                    }
                  else
                    return s;
                }
            }
-         else if (!strcmp (s->sel_types, types))
+         else if (! strcmp (s->sel_types, types))
            {
              if (orig)
                {
-                 orig->sel_id = (void*)i;
+                 orig->sel_id = (void *) i;
                  return orig;
                }
              else
@@ -369,40 +402,40 @@ __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;
+      j->sel_id = (void *) i;
       /* Can we use the pointer or must copy types?  Don't copy if NULL */
       if ((is_const) || (types == 0))
-       j->sel_types = (const char*)types;
+       j->sel_types = (const char *) types;
       else {
-       j->sel_types = (char *) objc_malloc(strlen(types)+1);
-       strcpy((char *)j->sel_types, types);
+       j->sel_types = (char *) objc_malloc (strlen (types) + 1);
+       strcpy ((char *) j->sel_types, types);
       }
-      l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
+      l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
     }
   else
     {
       __objc_selector_max_index += 1;
-      i = soffset_encode(__objc_selector_max_index);
+      i = soffset_encode (__objc_selector_max_index);
       if (orig)
        j = orig;
       else
-       j = objc_malloc (sizeof (struct objc_selector));
+       j = pool_alloc_selector ();
        
-      j->sel_id = (void*)i;
+      j->sel_id = (void *) i;
       /* Can we use the pointer or must copy types?  Don't copy if NULL */
       if ((is_const) || (types == 0))
-       j->sel_types = (const char*)types;
+       j->sel_types = (const char *) types;
       else {
-       j->sel_types = (char *) objc_malloc(strlen(types)+1);
-       strcpy((char *)j->sel_types, types);
+       j->sel_types = (char *) objc_malloc (strlen (types) + 1);
+       strcpy ((char *) j->sel_types, types);
       }
       l = 0;
     }
 
   DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types, 
-               soffset_decode (i));
+               (long) soffset_decode (i));
   
   {
     int is_new = (l == 0);
@@ -412,18 +445,18 @@ __sel_register_typed_name (const char *name, const char *types,
     if ((is_const) || (name == 0))
       new_name = name;
     else {
-      new_name = (char *) objc_malloc(strlen(name)+1);
-      strcpy((char *)new_name, name);
+      new_name = (char *) objc_malloc (strlen (name) + 1);
+      strcpy ((char *) new_name, name);
     }
 
-    l = list_cons ((void*)j, l);
+    l = list_cons ((void *) j, l);
     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);
+  sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
 
   return (SEL) j;
 }
@@ -433,11 +466,11 @@ sel_register_name (const char *name)
 {
   SEL ret;
     
-  objc_mutex_lock(__objc_runtime_mutex);
+  objc_mutex_lock (__objc_runtime_mutex);
   /* Assume that name is not constant static memory and needs to be
      copied before put into a runtime structure.  is_const == NO */
   ret = __sel_register_typed_name (name, 0, 0, NO);
-  objc_mutex_unlock(__objc_runtime_mutex);
+  objc_mutex_unlock (__objc_runtime_mutex);
   
   return ret;
 }
@@ -446,13 +479,12 @@ SEL
 sel_register_typed_name (const char *name, const char *type)
 {
   SEL ret;
-    
-  objc_mutex_lock(__objc_runtime_mutex);
+
+  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 */
   ret = __sel_register_typed_name (name, type, 0, NO);
-  objc_mutex_unlock(__objc_runtime_mutex);
+  objc_mutex_unlock (__objc_runtime_mutex);
   
   return ret;
 }
-