xref: /netbsd-src/external/gpl3/gcc.old/dist/libobjc/selector.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
136ac495dSmrg /* GNU Objective C Runtime selector related functions
2*8feb0f0bSmrg    Copyright (C) 1993-2020 Free Software Foundation, Inc.
336ac495dSmrg    Contributed by Kresten Krab Thorup
436ac495dSmrg 
536ac495dSmrg This file is part of GCC.
636ac495dSmrg 
736ac495dSmrg GCC is free software; you can redistribute it and/or modify it under the
836ac495dSmrg terms of the GNU General Public License as published by the Free Software
936ac495dSmrg Foundation; either version 3, or (at your option) any later version.
1036ac495dSmrg 
1136ac495dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1236ac495dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1336ac495dSmrg FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
1436ac495dSmrg details.
1536ac495dSmrg 
1636ac495dSmrg Under Section 7 of GPL version 3, you are granted additional
1736ac495dSmrg permissions described in the GCC Runtime Library Exception, version
1836ac495dSmrg 3.1, as published by the Free Software Foundation.
1936ac495dSmrg 
2036ac495dSmrg You should have received a copy of the GNU General Public License and
2136ac495dSmrg a copy of the GCC Runtime Library Exception along with this program;
2236ac495dSmrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2336ac495dSmrg <http://www.gnu.org/licenses/>.  */
2436ac495dSmrg 
2536ac495dSmrg #include "objc-private/common.h"
2636ac495dSmrg #include "objc/runtime.h"
2736ac495dSmrg #include "objc/thr.h"
2836ac495dSmrg #include "objc-private/hash.h"
2936ac495dSmrg #include "objc-private/objc-list.h"
3036ac495dSmrg #include "objc-private/module-abi-8.h"
3136ac495dSmrg #include "objc-private/runtime.h"
3236ac495dSmrg #include "objc-private/sarray.h"
3336ac495dSmrg #include "objc-private/selector.h"
3436ac495dSmrg #include <stdlib.h>                    /* For malloc.  */
3536ac495dSmrg 
3636ac495dSmrg /* Initial selector hash table size. Value doesn't matter much.  */
3736ac495dSmrg #define SELECTOR_HASH_SIZE 128
3836ac495dSmrg 
3936ac495dSmrg /* Tables mapping selector names to uid and opposite.  */
4036ac495dSmrg static struct sarray *__objc_selector_array = 0; /* uid -> sel  !T:MUTEX */
4136ac495dSmrg static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
4236ac495dSmrg static cache_ptr      __objc_selector_hash  = 0; /* name -> uid !T:MUTEX */
4336ac495dSmrg 
4436ac495dSmrg /* Number of selectors stored in each of the above tables.  */
4536ac495dSmrg unsigned int __objc_selector_max_index = 0;     /* !T:MUTEX */
4636ac495dSmrg 
4736ac495dSmrg /* Forward-declare an internal function.  */
4836ac495dSmrg static SEL
4936ac495dSmrg __sel_register_typed_name (const char *name, const char *types,
5036ac495dSmrg 			   struct objc_selector *orig, BOOL is_const);
5136ac495dSmrg 
__objc_init_selector_tables(void)5236ac495dSmrg void __objc_init_selector_tables (void)
5336ac495dSmrg {
5436ac495dSmrg   __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
5536ac495dSmrg   __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
5636ac495dSmrg   __objc_selector_hash
5736ac495dSmrg     = objc_hash_new (SELECTOR_HASH_SIZE,
5836ac495dSmrg 		     (hash_func_type) objc_hash_string,
5936ac495dSmrg 		     (compare_func_type) objc_compare_strings);
6036ac495dSmrg }
6136ac495dSmrg 
6236ac495dSmrg /* Register a bunch of selectors from the table of selectors in a
6336ac495dSmrg    module.  'selectors' should not be NULL.  The list is terminated by
6436ac495dSmrg    a selectors with a NULL sel_id.  The selectors are assumed to
6536ac495dSmrg    contain the 'name' in the sel_id field; this is replaced with the
6636ac495dSmrg    final selector id after they are registered.  */
6736ac495dSmrg void
__objc_register_selectors_from_module(struct objc_selector * selectors)6836ac495dSmrg __objc_register_selectors_from_module (struct objc_selector *selectors)
6936ac495dSmrg {
7036ac495dSmrg   int i;
7136ac495dSmrg 
7236ac495dSmrg   for (i = 0; selectors[i].sel_id; ++i)
7336ac495dSmrg     {
7436ac495dSmrg       const char *name, *type;
7536ac495dSmrg       name = (char *) selectors[i].sel_id;
7636ac495dSmrg       type = (char *) selectors[i].sel_types;
7736ac495dSmrg       /* Constructors are constant static data and we can safely store
7836ac495dSmrg 	 pointers to them in the runtime structures, so we set
7936ac495dSmrg 	 is_const == YES.  */
8036ac495dSmrg       __sel_register_typed_name (name, type, (struct objc_selector *) &(selectors[i]),
8136ac495dSmrg 				 /* is_const */ YES);
8236ac495dSmrg     }
8336ac495dSmrg }
8436ac495dSmrg 
8536ac495dSmrg /* This routine is given a class and records all of the methods in its
8636ac495dSmrg    class structure in the record table.  */
8736ac495dSmrg void
__objc_register_selectors_from_class(Class class)8836ac495dSmrg __objc_register_selectors_from_class (Class class)
8936ac495dSmrg {
9036ac495dSmrg   struct objc_method_list * method_list;
9136ac495dSmrg 
9236ac495dSmrg   method_list = class->methods;
9336ac495dSmrg   while (method_list)
9436ac495dSmrg     {
9536ac495dSmrg       __objc_register_selectors_from_list (method_list);
9636ac495dSmrg       method_list = method_list->method_next;
9736ac495dSmrg     }
9836ac495dSmrg }
9936ac495dSmrg 
10036ac495dSmrg 
10136ac495dSmrg /* This routine is given a list of methods and records each of the
10236ac495dSmrg    methods in the record table.  This is the routine that does the
10336ac495dSmrg    actual recording work.
10436ac495dSmrg 
10536ac495dSmrg    The name and type pointers in the method list must be permanent and
10636ac495dSmrg    immutable.  */
10736ac495dSmrg void
__objc_register_selectors_from_list(struct objc_method_list * method_list)10836ac495dSmrg __objc_register_selectors_from_list (struct objc_method_list *method_list)
10936ac495dSmrg {
11036ac495dSmrg   int i = 0;
11136ac495dSmrg 
11236ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
11336ac495dSmrg   while (i < method_list->method_count)
11436ac495dSmrg     {
11536ac495dSmrg       Method method = &method_list->method_list[i];
11636ac495dSmrg       if (method->method_name)
11736ac495dSmrg 	{
11836ac495dSmrg 	  method->method_name
11936ac495dSmrg 	    = __sel_register_typed_name ((const char *) method->method_name,
12036ac495dSmrg 					 method->method_types, 0, YES);
12136ac495dSmrg 	}
12236ac495dSmrg       i += 1;
12336ac495dSmrg     }
12436ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
12536ac495dSmrg }
12636ac495dSmrg 
12736ac495dSmrg /* The same as __objc_register_selectors_from_list, but works on a
12836ac495dSmrg    struct objc_method_description_list* instead of a struct
12936ac495dSmrg    objc_method_list*.  This is only used for protocols, which have
13036ac495dSmrg    lists of method descriptions, not methods.  */
13136ac495dSmrg void
__objc_register_selectors_from_description_list(struct objc_method_description_list * method_list)13236ac495dSmrg __objc_register_selectors_from_description_list
13336ac495dSmrg (struct objc_method_description_list *method_list)
13436ac495dSmrg {
13536ac495dSmrg   int i = 0;
13636ac495dSmrg 
13736ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
13836ac495dSmrg   while (i < method_list->count)
13936ac495dSmrg     {
14036ac495dSmrg       struct objc_method_description *method = &method_list->list[i];
14136ac495dSmrg       if (method->name)
14236ac495dSmrg 	{
14336ac495dSmrg 	  method->name
14436ac495dSmrg 	    = __sel_register_typed_name ((const char *) method->name,
14536ac495dSmrg 					 method->types, 0, YES);
14636ac495dSmrg 	}
14736ac495dSmrg       i += 1;
14836ac495dSmrg     }
14936ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
15036ac495dSmrg }
15136ac495dSmrg 
15236ac495dSmrg /* Register instance methods as class methods for root classes.  */
__objc_register_instance_methods_to_class(Class class)15336ac495dSmrg void __objc_register_instance_methods_to_class (Class class)
15436ac495dSmrg {
15536ac495dSmrg   struct objc_method_list *method_list;
15636ac495dSmrg   struct objc_method_list *class_method_list;
15736ac495dSmrg   int max_methods_no = 16;
15836ac495dSmrg   struct objc_method_list *new_list;
15936ac495dSmrg   Method curr_method;
16036ac495dSmrg 
16136ac495dSmrg   /* Only if a root class. */
16236ac495dSmrg   if (class->super_class)
16336ac495dSmrg     return;
16436ac495dSmrg 
16536ac495dSmrg   /* Allocate a method list to hold the new class methods.  */
16636ac495dSmrg   new_list = objc_calloc (sizeof (struct objc_method_list)
16736ac495dSmrg 			  + sizeof (struct objc_method[max_methods_no]), 1);
16836ac495dSmrg   method_list = class->methods;
16936ac495dSmrg   class_method_list = class->class_pointer->methods;
17036ac495dSmrg   curr_method = &new_list->method_list[0];
17136ac495dSmrg 
17236ac495dSmrg   /* Iterate through the method lists for the class.  */
17336ac495dSmrg   while (method_list)
17436ac495dSmrg     {
17536ac495dSmrg       int i;
17636ac495dSmrg 
17736ac495dSmrg       /* Iterate through the methods from this method list.  */
17836ac495dSmrg       for (i = 0; i < method_list->method_count; i++)
17936ac495dSmrg 	{
18036ac495dSmrg 	  Method mth = &method_list->method_list[i];
18136ac495dSmrg 	  if (mth->method_name
18236ac495dSmrg 	      && ! search_for_method_in_list (class_method_list,
18336ac495dSmrg 					      mth->method_name))
18436ac495dSmrg 	    {
18536ac495dSmrg 	      /* This instance method isn't a class method.  Add it
18636ac495dSmrg 		 into the new_list. */
18736ac495dSmrg 	      *curr_method = *mth;
18836ac495dSmrg 
18936ac495dSmrg 	      /* Reallocate the method list if necessary.  */
19036ac495dSmrg 	      if (++new_list->method_count == max_methods_no)
19136ac495dSmrg 		new_list =
19236ac495dSmrg 		  objc_realloc (new_list, sizeof (struct objc_method_list)
19336ac495dSmrg 				+ sizeof (struct
19436ac495dSmrg 					  objc_method[max_methods_no += 16]));
19536ac495dSmrg 	      curr_method = &new_list->method_list[new_list->method_count];
19636ac495dSmrg 	    }
19736ac495dSmrg 	}
19836ac495dSmrg 
19936ac495dSmrg       method_list = method_list->method_next;
20036ac495dSmrg     }
20136ac495dSmrg 
20236ac495dSmrg   /* If we created any new class methods then attach the method list
20336ac495dSmrg      to the class.  */
20436ac495dSmrg   if (new_list->method_count)
20536ac495dSmrg     {
20636ac495dSmrg       new_list =
20736ac495dSmrg  	objc_realloc (new_list, sizeof (struct objc_method_list)
20836ac495dSmrg 		      + sizeof (struct objc_method[new_list->method_count]));
20936ac495dSmrg       new_list->method_next = class->class_pointer->methods;
21036ac495dSmrg       class->class_pointer->methods = new_list;
21136ac495dSmrg     }
21236ac495dSmrg   else
21336ac495dSmrg     objc_free(new_list);
21436ac495dSmrg 
21536ac495dSmrg   __objc_update_dispatch_table_for_class (class->class_pointer);
21636ac495dSmrg }
21736ac495dSmrg 
21836ac495dSmrg BOOL
sel_isEqual(SEL s1,SEL s2)21936ac495dSmrg sel_isEqual (SEL s1, SEL s2)
22036ac495dSmrg {
22136ac495dSmrg   if (s1 == 0 || s2 == 0)
22236ac495dSmrg     return s1 == s2;
22336ac495dSmrg   else
22436ac495dSmrg     return s1->sel_id == s2->sel_id;
22536ac495dSmrg }
22636ac495dSmrg 
22736ac495dSmrg /* Return YES iff t1 and t2 have same method types.  Ignore the
22836ac495dSmrg    argframe layout.  */
22936ac495dSmrg static BOOL
sel_types_match(const char * t1,const char * t2)23036ac495dSmrg sel_types_match (const char *t1, const char *t2)
23136ac495dSmrg {
23236ac495dSmrg   if (! t1 || ! t2)
23336ac495dSmrg     return NO;
23436ac495dSmrg   while (*t1 && *t2)
23536ac495dSmrg     {
23636ac495dSmrg       if (*t1 == '+') t1++;
23736ac495dSmrg       if (*t2 == '+') t2++;
23836ac495dSmrg       while (isdigit ((unsigned char) *t1)) t1++;
23936ac495dSmrg       while (isdigit ((unsigned char) *t2)) t2++;
24036ac495dSmrg       /* xxx Remove these next two lines when qualifiers are put in
24136ac495dSmrg 	 all selectors, not just Protocol selectors.  */
24236ac495dSmrg       t1 = objc_skip_type_qualifiers (t1);
24336ac495dSmrg       t2 = objc_skip_type_qualifiers (t2);
24436ac495dSmrg       if (! *t1 && ! *t2)
24536ac495dSmrg 	return YES;
24636ac495dSmrg       if (*t1 != *t2)
24736ac495dSmrg 	return NO;
24836ac495dSmrg       t1++;
24936ac495dSmrg       t2++;
25036ac495dSmrg     }
25136ac495dSmrg   return NO;
25236ac495dSmrg }
25336ac495dSmrg 
25436ac495dSmrg /* Return selector representing name.  */
25536ac495dSmrg SEL
sel_get_any_uid(const char * name)25636ac495dSmrg sel_get_any_uid (const char *name)
25736ac495dSmrg {
25836ac495dSmrg   struct objc_list *l;
25936ac495dSmrg   sidx i;
26036ac495dSmrg 
26136ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
26236ac495dSmrg 
26336ac495dSmrg   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
26436ac495dSmrg   if (soffset_decode (i) == 0)
26536ac495dSmrg     {
26636ac495dSmrg       objc_mutex_unlock (__objc_runtime_mutex);
26736ac495dSmrg       return 0;
26836ac495dSmrg     }
26936ac495dSmrg 
27036ac495dSmrg   l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
27136ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
27236ac495dSmrg 
27336ac495dSmrg   if (l == 0)
27436ac495dSmrg     return 0;
27536ac495dSmrg 
27636ac495dSmrg   return (SEL) l->head;
27736ac495dSmrg }
27836ac495dSmrg 
27936ac495dSmrg SEL
sel_getTypedSelector(const char * name)28036ac495dSmrg sel_getTypedSelector (const char *name)
28136ac495dSmrg {
28236ac495dSmrg   sidx i;
28336ac495dSmrg 
28436ac495dSmrg   if (name == NULL)
28536ac495dSmrg     return NULL;
28636ac495dSmrg 
28736ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
28836ac495dSmrg 
28936ac495dSmrg   /* Look for a typed selector.  */
29036ac495dSmrg   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
29136ac495dSmrg   if (i != 0)
29236ac495dSmrg     {
29336ac495dSmrg       struct objc_list *l;
29436ac495dSmrg       SEL returnValue = NULL;
29536ac495dSmrg 
29636ac495dSmrg       for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
29736ac495dSmrg 	   l; l = l->tail)
29836ac495dSmrg 	{
29936ac495dSmrg 	  SEL s = (SEL) l->head;
30036ac495dSmrg 	  if (s->sel_types)
30136ac495dSmrg 	    {
30236ac495dSmrg 	      if (returnValue == NULL)
30336ac495dSmrg 		{
30436ac495dSmrg 		  /* First typed selector that we find.  Keep it in
30536ac495dSmrg 		     returnValue, but keep checking as we want to
30636ac495dSmrg 		     detect conflicts.  */
30736ac495dSmrg 		  returnValue = s;
30836ac495dSmrg 		}
30936ac495dSmrg 	      else
31036ac495dSmrg 		{
31136ac495dSmrg 		  /* We had already found a typed selectors, so we
31236ac495dSmrg 		     have multiple ones.  Double-check that they have
31336ac495dSmrg 		     different types, just in case for some reason we
31436ac495dSmrg 		     got duplicates with the same types.  If so, it's
31536ac495dSmrg 		     OK, we'll ignore the duplicate.  */
31636ac495dSmrg 		  if (returnValue->sel_types == s->sel_types)
31736ac495dSmrg 		    continue;
31836ac495dSmrg 		  else if (sel_types_match (returnValue->sel_types, s->sel_types))
31936ac495dSmrg 		    continue;
32036ac495dSmrg 		  else
32136ac495dSmrg 		    {
32236ac495dSmrg 		      /* The types of the two selectors are different;
32336ac495dSmrg 			 it's a conflict.  Too bad.  Return NULL.  */
32436ac495dSmrg 		      objc_mutex_unlock (__objc_runtime_mutex);
32536ac495dSmrg 		      return NULL;
32636ac495dSmrg 		    }
32736ac495dSmrg 		}
32836ac495dSmrg 	    }
32936ac495dSmrg 	}
33036ac495dSmrg 
33136ac495dSmrg       if (returnValue != NULL)
33236ac495dSmrg 	{
33336ac495dSmrg 	  objc_mutex_unlock (__objc_runtime_mutex);
33436ac495dSmrg 	  return returnValue;
33536ac495dSmrg 	}
33636ac495dSmrg     }
33736ac495dSmrg 
33836ac495dSmrg   /* No typed selector found.  Return NULL.  */
33936ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
34036ac495dSmrg   return 0;
34136ac495dSmrg }
34236ac495dSmrg 
34336ac495dSmrg SEL *
sel_copyTypedSelectorList(const char * name,unsigned int * numberOfReturnedSelectors)34436ac495dSmrg sel_copyTypedSelectorList (const char *name, unsigned int *numberOfReturnedSelectors)
34536ac495dSmrg {
34636ac495dSmrg   unsigned int count = 0;
34736ac495dSmrg   SEL *returnValue = NULL;
34836ac495dSmrg   sidx i;
34936ac495dSmrg 
35036ac495dSmrg   if (name == NULL)
35136ac495dSmrg     {
35236ac495dSmrg       if (numberOfReturnedSelectors)
35336ac495dSmrg 	*numberOfReturnedSelectors = 0;
35436ac495dSmrg       return NULL;
35536ac495dSmrg     }
35636ac495dSmrg 
35736ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
35836ac495dSmrg 
35936ac495dSmrg   /* Count how many selectors we have.  */
36036ac495dSmrg   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
36136ac495dSmrg   if (i != 0)
36236ac495dSmrg     {
36336ac495dSmrg       struct objc_list *selector_list = NULL;
36436ac495dSmrg       selector_list = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
36536ac495dSmrg 
36636ac495dSmrg       /* Count how many selectors we have.  */
36736ac495dSmrg       {
36836ac495dSmrg 	struct objc_list *l;
36936ac495dSmrg 	for (l = selector_list; l; l = l->tail)
37036ac495dSmrg 	  count++;
37136ac495dSmrg       }
37236ac495dSmrg 
37336ac495dSmrg       if (count != 0)
37436ac495dSmrg 	{
37536ac495dSmrg 	  /* Allocate enough memory to hold them.  */
37636ac495dSmrg 	  returnValue = (SEL *)(malloc (sizeof (SEL) * (count + 1)));
37736ac495dSmrg 
37836ac495dSmrg 	  /* Copy the selectors.  */
37936ac495dSmrg 	  {
38036ac495dSmrg 	    unsigned int j;
38136ac495dSmrg 	    for (j = 0; j < count; j++)
38236ac495dSmrg 	      {
38336ac495dSmrg 		returnValue[j] = (SEL)(selector_list->head);
38436ac495dSmrg 		selector_list = selector_list->tail;
38536ac495dSmrg 	      }
38636ac495dSmrg 	    returnValue[j] = NULL;
38736ac495dSmrg 	  }
38836ac495dSmrg 	}
38936ac495dSmrg     }
39036ac495dSmrg 
39136ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
39236ac495dSmrg 
39336ac495dSmrg   if (numberOfReturnedSelectors)
39436ac495dSmrg     *numberOfReturnedSelectors = count;
39536ac495dSmrg 
39636ac495dSmrg   return returnValue;
39736ac495dSmrg }
39836ac495dSmrg 
39936ac495dSmrg /* Get the name of a selector.  If the selector is unknown, the empty
40036ac495dSmrg    string "" is returned.  */
sel_getName(SEL selector)40136ac495dSmrg const char *sel_getName (SEL selector)
40236ac495dSmrg {
40336ac495dSmrg   const char *ret;
40436ac495dSmrg 
40536ac495dSmrg   if (selector == NULL)
40636ac495dSmrg     return "<null selector>";
40736ac495dSmrg 
40836ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
40936ac495dSmrg   if ((soffset_decode ((sidx)selector->sel_id) > 0)
41036ac495dSmrg       && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
41136ac495dSmrg     ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
41236ac495dSmrg   else
41336ac495dSmrg     ret = 0;
41436ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
41536ac495dSmrg   return ret;
41636ac495dSmrg }
41736ac495dSmrg 
41836ac495dSmrg BOOL
sel_is_mapped(SEL selector)41936ac495dSmrg sel_is_mapped (SEL selector)
42036ac495dSmrg {
42136ac495dSmrg   unsigned int idx = soffset_decode ((sidx)selector->sel_id);
42236ac495dSmrg   return ((idx > 0) && (idx <= __objc_selector_max_index));
42336ac495dSmrg }
42436ac495dSmrg 
sel_getTypeEncoding(SEL selector)42536ac495dSmrg const char *sel_getTypeEncoding (SEL selector)
42636ac495dSmrg {
42736ac495dSmrg   if (selector)
42836ac495dSmrg     return selector->sel_types;
42936ac495dSmrg   else
43036ac495dSmrg     return 0;
43136ac495dSmrg }
43236ac495dSmrg 
43336ac495dSmrg /* The uninstalled dispatch table.  */
43436ac495dSmrg extern struct sarray *__objc_uninstalled_dtable;
43536ac495dSmrg 
43636ac495dSmrg /* __sel_register_typed_name allocates lots of struct objc_selector:s
43736ac495dSmrg    of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the
43836ac495dSmrg    number of malloc calls and memory lost to malloc overhead, we
43936ac495dSmrg    allocate objc_selector:s in blocks here. This is only called from
44036ac495dSmrg    __sel_register_typed_name, and __sel_register_typed_name may only
44136ac495dSmrg    be called when __objc_runtime_mutex is locked.
44236ac495dSmrg 
44336ac495dSmrg    Note that the objc_selector:s allocated from
44436ac495dSmrg    __sel_register_typed_name are never freed.
44536ac495dSmrg 
44636ac495dSmrg    62 because 62 * sizeof (struct objc_selector) = 496 (992). This
44736ac495dSmrg    should let malloc add some overhead and use a nice, round 512
44836ac495dSmrg    (1024) byte chunk.  */
44936ac495dSmrg #define SELECTOR_POOL_SIZE 62
45036ac495dSmrg static struct objc_selector *selector_pool;
45136ac495dSmrg static int selector_pool_left;
45236ac495dSmrg 
45336ac495dSmrg static struct objc_selector *
pool_alloc_selector(void)45436ac495dSmrg pool_alloc_selector(void)
45536ac495dSmrg {
45636ac495dSmrg   if (!selector_pool_left)
45736ac495dSmrg     {
45836ac495dSmrg       selector_pool = objc_malloc (sizeof (struct objc_selector)
45936ac495dSmrg 				   * SELECTOR_POOL_SIZE);
46036ac495dSmrg       selector_pool_left = SELECTOR_POOL_SIZE;
46136ac495dSmrg     }
46236ac495dSmrg   return &selector_pool[--selector_pool_left];
46336ac495dSmrg }
46436ac495dSmrg 
46536ac495dSmrg /* Store the passed selector name in the selector record and return
46636ac495dSmrg    its selector value (value returned by sel_get_uid).  Assume that
46736ac495dSmrg    the calling function has locked down __objc_runtime_mutex.  The
46836ac495dSmrg    'is_const' parameter tells us if the name and types parameters are
46936ac495dSmrg    really constant or not.  If YES then they are constant and we can
47036ac495dSmrg    just store the pointers.  If NO then we need to copy name and types
47136ac495dSmrg    because the pointers may disappear later on.  If the 'orig'
47236ac495dSmrg    parameter is not NULL, then we are registering a selector from a
47336ac495dSmrg    module, and 'orig' is that selector.  In this case, we can put the
47436ac495dSmrg    selector in the tables if needed, and orig->sel_id is updated with
47536ac495dSmrg    the selector ID of the registered selector, and 'orig' is
47636ac495dSmrg    returned.  */
47736ac495dSmrg static SEL
__sel_register_typed_name(const char * name,const char * types,struct objc_selector * orig,BOOL is_const)47836ac495dSmrg __sel_register_typed_name (const char *name, const char *types,
47936ac495dSmrg 			   struct objc_selector *orig, BOOL is_const)
48036ac495dSmrg {
48136ac495dSmrg   struct objc_selector *j;
48236ac495dSmrg   sidx i;
48336ac495dSmrg   struct objc_list *l;
48436ac495dSmrg 
48536ac495dSmrg   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
48636ac495dSmrg   if (soffset_decode (i) != 0)
48736ac495dSmrg     {
48836ac495dSmrg       /* There are already selectors with that name.  Examine them to
48936ac495dSmrg 	 see if the one we're registering already exists.  */
49036ac495dSmrg       for (l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
49136ac495dSmrg 	   l; l = l->tail)
49236ac495dSmrg 	{
49336ac495dSmrg 	  SEL s = (SEL)l->head;
49436ac495dSmrg 	  if (types == 0 || s->sel_types == 0)
49536ac495dSmrg 	    {
49636ac495dSmrg 	      if (s->sel_types == types)
49736ac495dSmrg 		{
49836ac495dSmrg 		  if (orig)
49936ac495dSmrg 		    {
50036ac495dSmrg 		      orig->sel_id = (void *)i;
50136ac495dSmrg 		      return orig;
50236ac495dSmrg 		    }
50336ac495dSmrg 		  else
50436ac495dSmrg 		    return s;
50536ac495dSmrg 		}
50636ac495dSmrg 	    }
50736ac495dSmrg 	  else if (sel_types_match (s->sel_types, types))
50836ac495dSmrg 	    {
50936ac495dSmrg 	      if (orig)
51036ac495dSmrg 		{
51136ac495dSmrg 		  orig->sel_id = (void *)i;
51236ac495dSmrg 		  return orig;
51336ac495dSmrg 		}
51436ac495dSmrg 	      else
51536ac495dSmrg 		return s;
51636ac495dSmrg 	    }
51736ac495dSmrg 	}
51836ac495dSmrg       /* A selector with this specific name/type combination does not
51936ac495dSmrg 	 exist yet.  We need to register it.  */
52036ac495dSmrg       if (orig)
52136ac495dSmrg 	j = orig;
52236ac495dSmrg       else
52336ac495dSmrg 	j = pool_alloc_selector ();
52436ac495dSmrg 
52536ac495dSmrg       j->sel_id = (void *)i;
52636ac495dSmrg       /* Can we use the pointer or must we copy types ?  Don't copy if
52736ac495dSmrg 	 NULL.  */
52836ac495dSmrg       if ((is_const) || (types == 0))
52936ac495dSmrg 	j->sel_types = types;
53036ac495dSmrg       else
53136ac495dSmrg 	{
53236ac495dSmrg 	  j->sel_types = (char *)objc_malloc (strlen (types) + 1);
53336ac495dSmrg 	  strcpy ((char *)j->sel_types, types);
53436ac495dSmrg 	}
53536ac495dSmrg       l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
53636ac495dSmrg     }
53736ac495dSmrg   else
53836ac495dSmrg     {
53936ac495dSmrg       /* There are no other selectors with this name registered in the
54036ac495dSmrg 	 runtime tables.  */
54136ac495dSmrg       const char *new_name;
54236ac495dSmrg 
54336ac495dSmrg       /* Determine i.  */
54436ac495dSmrg       __objc_selector_max_index += 1;
54536ac495dSmrg       i = soffset_encode (__objc_selector_max_index);
54636ac495dSmrg 
54736ac495dSmrg       /* Prepare the selector.  */
54836ac495dSmrg       if (orig)
54936ac495dSmrg 	j = orig;
55036ac495dSmrg       else
55136ac495dSmrg 	j = pool_alloc_selector ();
55236ac495dSmrg 
55336ac495dSmrg       j->sel_id = (void *)i;
55436ac495dSmrg       /* Can we use the pointer or must we copy types ?  Don't copy if
55536ac495dSmrg 	 NULL.  */
55636ac495dSmrg       if (is_const || (types == 0))
55736ac495dSmrg 	j->sel_types = types;
55836ac495dSmrg       else
55936ac495dSmrg 	{
56036ac495dSmrg 	  j->sel_types = (char *)objc_malloc (strlen (types) + 1);
56136ac495dSmrg 	  strcpy ((char *)j->sel_types, types);
56236ac495dSmrg 	}
56336ac495dSmrg 
56436ac495dSmrg       /* Since this is the first selector with this name, we need to
56536ac495dSmrg 	 register the correspondence between 'i' (the sel_id) and
56636ac495dSmrg 	 'name' (the actual string) in __objc_selector_names and
56736ac495dSmrg 	 __objc_selector_hash.  */
56836ac495dSmrg 
56936ac495dSmrg       /* Can we use the pointer or must we copy name ?  Don't copy if
57036ac495dSmrg 	 NULL.  (FIXME: Can the name really be NULL here ?)  */
57136ac495dSmrg       if (is_const || (name == 0))
57236ac495dSmrg 	new_name = name;
57336ac495dSmrg       else
57436ac495dSmrg 	{
57536ac495dSmrg 	  new_name = (char *)objc_malloc (strlen (name) + 1);
57636ac495dSmrg 	  strcpy ((char *)new_name, name);
57736ac495dSmrg 	}
57836ac495dSmrg 
57936ac495dSmrg       /* This maps the sel_id to the name.  */
58036ac495dSmrg       sarray_at_put_safe (__objc_selector_names, i, (void *)new_name);
58136ac495dSmrg 
58236ac495dSmrg       /* This maps the name to the sel_id.  */
58336ac495dSmrg       objc_hash_add (&__objc_selector_hash, (void *)new_name, (void *)i);
58436ac495dSmrg 
58536ac495dSmrg       l = 0;
58636ac495dSmrg     }
58736ac495dSmrg 
58836ac495dSmrg   DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
58936ac495dSmrg 		(long)soffset_decode (i));
59036ac495dSmrg 
59136ac495dSmrg   /* Now add the selector to the list of selectors with that id.  */
59236ac495dSmrg   l = list_cons ((void *)j, l);
59336ac495dSmrg   sarray_at_put_safe (__objc_selector_array, i, (void *)l);
59436ac495dSmrg 
59536ac495dSmrg   sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
59636ac495dSmrg 
59736ac495dSmrg   return (SEL)j;
59836ac495dSmrg }
59936ac495dSmrg 
60036ac495dSmrg SEL
sel_registerName(const char * name)60136ac495dSmrg sel_registerName (const char *name)
60236ac495dSmrg {
60336ac495dSmrg   SEL ret;
60436ac495dSmrg 
60536ac495dSmrg   if (name == NULL)
60636ac495dSmrg     return NULL;
60736ac495dSmrg 
60836ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
60936ac495dSmrg   /* Assume that name is not constant static memory and needs to be
61036ac495dSmrg      copied before put into a runtime structure.  is_const == NO.  */
61136ac495dSmrg   ret = __sel_register_typed_name (name, 0, 0, NO);
61236ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
61336ac495dSmrg 
61436ac495dSmrg   return ret;
61536ac495dSmrg }
61636ac495dSmrg 
61736ac495dSmrg SEL
sel_registerTypedName(const char * name,const char * type)61836ac495dSmrg sel_registerTypedName (const char *name, const char *type)
61936ac495dSmrg {
62036ac495dSmrg   SEL ret;
62136ac495dSmrg 
62236ac495dSmrg   if (name == NULL)
62336ac495dSmrg     return NULL;
62436ac495dSmrg 
62536ac495dSmrg   objc_mutex_lock (__objc_runtime_mutex);
62636ac495dSmrg   /* Assume that name and type are not constant static memory and need
62736ac495dSmrg      to be copied before put into a runtime structure.  is_const ==
62836ac495dSmrg      NO.  */
62936ac495dSmrg   ret = __sel_register_typed_name (name, type, 0, NO);
63036ac495dSmrg   objc_mutex_unlock (__objc_runtime_mutex);
63136ac495dSmrg 
63236ac495dSmrg   return ret;
63336ac495dSmrg }
63436ac495dSmrg 
63536ac495dSmrg /* Return the selector representing name.  */
63636ac495dSmrg SEL
sel_getUid(const char * name)63736ac495dSmrg sel_getUid (const char *name)
63836ac495dSmrg {
63936ac495dSmrg   return sel_registerTypedName (name, 0);
64036ac495dSmrg }
641