1/* GNU Objective C Runtime selector related functions
2   Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004, 2009 Free Software Foundation, Inc.
3   Contributed by Kresten Krab Thorup
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under the
8terms of the GNU General Public License as published by the Free Software
9Foundation; either version 3, or (at your option) any later version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14details.
15
16Under Section 7 of GPL version 3, you are granted additional
17permissions described in the GCC Runtime Library Exception, version
183.1, as published by the Free Software Foundation.
19
20You should have received a copy of the GNU General Public License and
21a copy of the GCC Runtime Library Exception along with this program;
22see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23<http://www.gnu.org/licenses/>.  */
24
25
26#include "objc/runtime.h"
27#include "objc/sarray.h"
28#include "objc/encoding.h"
29
30/* Initial selector hash table size. Value doesn't matter much */
31#define SELECTOR_HASH_SIZE 128
32
33/* Tables mapping selector names to uid and opposite */
34static struct sarray *__objc_selector_array = 0; /* uid -> sel  !T:MUTEX */
35static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
36static cache_ptr      __objc_selector_hash  = 0; /* name -> uid !T:MUTEX */
37
38/* Number of selectors stored in each of the above tables */
39unsigned int __objc_selector_max_index = 0;     /* !T:MUTEX */
40
41void __objc_init_selector_tables (void)
42{
43  __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
44  __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
45  __objc_selector_hash
46    = objc_hash_new (SELECTOR_HASH_SIZE,
47		     (hash_func_type) objc_hash_string,
48		     (compare_func_type) objc_compare_strings);
49}
50
51/* This routine is given a class and records all of the methods in its class
52   structure in the record table.  */
53void
54__objc_register_selectors_from_class (Class class)
55{
56  MethodList_t method_list;
57
58  method_list = class->methods;
59  while (method_list)
60    {
61      __objc_register_selectors_from_list (method_list);
62      method_list = method_list->method_next;
63    }
64}
65
66
67/* This routine is given a list of methods and records each of the methods in
68   the record table.  This is the routine that does the actual recording
69   work.
70
71   The name and type pointers in the method list must be permanent and
72   immutable.
73   */
74void
75__objc_register_selectors_from_list (MethodList_t method_list)
76{
77  int i = 0;
78
79  objc_mutex_lock (__objc_runtime_mutex);
80  while (i < method_list->method_count)
81    {
82      Method_t method = &method_list->method_list[i];
83      if (method->method_name)
84	{
85	  method->method_name
86	    = __sel_register_typed_name ((const char *) method->method_name,
87					 method->method_types, 0, YES);
88	}
89      i += 1;
90    }
91  objc_mutex_unlock (__objc_runtime_mutex);
92}
93
94
95/* Register instance methods as class methods for root classes */
96void __objc_register_instance_methods_to_class (Class class)
97{
98  MethodList_t method_list;
99  MethodList_t class_method_list;
100  int max_methods_no = 16;
101  MethodList_t new_list;
102  Method_t curr_method;
103
104  /* Only if a root class. */
105  if (class->super_class)
106    return;
107
108  /* Allocate a method list to hold the new class methods */
109  new_list = objc_calloc (sizeof (struct objc_method_list)
110			    + sizeof (struct objc_method[max_methods_no]), 1);
111  method_list = class->methods;
112  class_method_list = class->class_pointer->methods;
113  curr_method = &new_list->method_list[0];
114
115  /* Iterate through the method lists for the class */
116  while (method_list)
117    {
118      int i;
119
120      /* Iterate through the methods from this method list */
121      for (i = 0; i < method_list->method_count; i++)
122	{
123	  Method_t mth = &method_list->method_list[i];
124	  if (mth->method_name
125	      && ! search_for_method_in_list (class_method_list,
126					      mth->method_name))
127	    {
128	      /* This instance method isn't a class method.
129		  Add it into the new_list. */
130	      *curr_method = *mth;
131
132	      /* Reallocate the method list if necessary */
133	      if (++new_list->method_count == max_methods_no)
134		new_list =
135		  objc_realloc (new_list, sizeof (struct objc_method_list)
136				+ sizeof (struct
137					objc_method[max_methods_no += 16]));
138	      curr_method = &new_list->method_list[new_list->method_count];
139	    }
140	}
141
142      method_list = method_list->method_next;
143    }
144
145  /* If we created any new class methods
146     then attach the method list to the class */
147  if (new_list->method_count)
148    {
149      new_list =
150 	objc_realloc (new_list, sizeof (struct objc_method_list)
151		     + sizeof (struct objc_method[new_list->method_count]));
152      new_list->method_next = class->class_pointer->methods;
153      class->class_pointer->methods = new_list;
154    }
155  else
156    objc_free(new_list);
157
158    __objc_update_dispatch_table_for_class (class->class_pointer);
159}
160
161
162/* Returns YES iff t1 and t2 have same method types, but we ignore
163   the argframe layout */
164BOOL
165sel_types_match (const char *t1, const char *t2)
166{
167  if (! t1 || ! t2)
168    return NO;
169  while (*t1 && *t2)
170    {
171      if (*t1 == '+') t1++;
172      if (*t2 == '+') t2++;
173      while (isdigit ((unsigned char) *t1)) t1++;
174      while (isdigit ((unsigned char) *t2)) t2++;
175      /* xxx Remove these next two lines when qualifiers are put in
176	 all selectors, not just Protocol selectors. */
177      t1 = objc_skip_type_qualifiers (t1);
178      t2 = objc_skip_type_qualifiers (t2);
179      if (! *t1 && ! *t2)
180	return YES;
181      if (*t1 != *t2)
182	return NO;
183      t1++;
184      t2++;
185    }
186  return NO;
187}
188
189/* return selector representing name */
190SEL
191sel_get_typed_uid (const char *name, const char *types)
192{
193  struct objc_list *l;
194  sidx i;
195
196  objc_mutex_lock (__objc_runtime_mutex);
197
198  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
199  if (i == 0)
200    {
201      objc_mutex_unlock (__objc_runtime_mutex);
202      return 0;
203    }
204
205  for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
206       l; l = l->tail)
207    {
208      SEL s = (SEL) l->head;
209      if (types == 0 || s->sel_types == 0)
210	{
211	  if (s->sel_types == types)
212	    {
213	      objc_mutex_unlock (__objc_runtime_mutex);
214	      return s;
215	    }
216	}
217      else if (sel_types_match (s->sel_types, types))
218	{
219	  objc_mutex_unlock (__objc_runtime_mutex);
220	  return s;
221	}
222    }
223
224  objc_mutex_unlock (__objc_runtime_mutex);
225  return 0;
226}
227
228/* Return selector representing name; prefer a selector with non-NULL type */
229SEL
230sel_get_any_typed_uid (const char *name)
231{
232  struct objc_list *l;
233  sidx i;
234  SEL s = NULL;
235
236  objc_mutex_lock (__objc_runtime_mutex);
237
238  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
239  if (i == 0)
240    {
241      objc_mutex_unlock (__objc_runtime_mutex);
242      return 0;
243    }
244
245  for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
246       l; l = l->tail)
247    {
248      s = (SEL) l->head;
249      if (s->sel_types)
250	{
251	    objc_mutex_unlock (__objc_runtime_mutex);
252	    return s;
253	}
254    }
255
256  objc_mutex_unlock (__objc_runtime_mutex);
257  return s;
258}
259
260/* return selector representing name */
261SEL
262sel_get_any_uid (const char *name)
263{
264  struct objc_list *l;
265  sidx i;
266
267  objc_mutex_lock (__objc_runtime_mutex);
268
269  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
270  if (soffset_decode (i) == 0)
271    {
272      objc_mutex_unlock (__objc_runtime_mutex);
273      return 0;
274    }
275
276  l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
277  objc_mutex_unlock (__objc_runtime_mutex);
278
279  if (l == 0)
280    return 0;
281
282  return (SEL) l->head;
283}
284
285/* return selector representing name */
286SEL
287sel_get_uid (const char *name)
288{
289  return sel_register_typed_name (name, 0);
290}
291
292/* Get name of selector.  If selector is unknown, the empty string ""
293   is returned */
294const char *sel_get_name (SEL selector)
295{
296  const char *ret;
297
298  objc_mutex_lock (__objc_runtime_mutex);
299  if ((soffset_decode ((sidx)selector->sel_id) > 0)
300      && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
301    ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
302  else
303    ret = 0;
304  objc_mutex_unlock (__objc_runtime_mutex);
305  return ret;
306}
307
308BOOL
309sel_is_mapped (SEL selector)
310{
311  unsigned int idx = soffset_decode ((sidx)selector->sel_id);
312  return ((idx > 0) && (idx <= __objc_selector_max_index));
313}
314
315
316const char *sel_get_type (SEL selector)
317{
318  if (selector)
319    return selector->sel_types;
320  else
321    return 0;
322}
323
324/* The uninstalled dispatch table */
325extern struct sarray *__objc_uninstalled_dtable;
326
327/* __sel_register_typed_name allocates lots of struct objc_selector:s
328   of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the number
329   of malloc calls and memory lost to malloc overhead, we allocate
330   objc_selector:s in blocks here. This is only called from
331   __sel_register_typed_name, and __sel_register_typed_name may only be
332   called when __objc_runtime_mutex is locked.
333
334   Note that the objc_selector:s allocated from __sel_register_typed_name
335   are never freed.
336
337   62 because 62 * sizeof (struct objc_selector) = 496 (992). This should
338   let malloc add some overhead and use a nice, round 512 (1024) byte chunk.
339   */
340#define SELECTOR_POOL_SIZE 62
341static struct objc_selector *selector_pool;
342static int selector_pool_left;
343
344static struct objc_selector *
345pool_alloc_selector(void)
346{
347  if (!selector_pool_left)
348    {
349      selector_pool = objc_malloc (sizeof (struct objc_selector)
350				   * SELECTOR_POOL_SIZE);
351      selector_pool_left = SELECTOR_POOL_SIZE;
352    }
353  return &selector_pool[--selector_pool_left];
354}
355
356/* Store the passed selector name in the selector record and return its
357   selector value (value returned by sel_get_uid).
358   Assumes that the calling function has locked down __objc_runtime_mutex. */
359/* is_const parameter tells us if the name and types parameters
360   are really constant or not.  If YES then they are constant and
361   we can just store the pointers.  If NO then we need to copy
362   name and types because the pointers may disappear later on. */
363SEL
364__sel_register_typed_name (const char *name, const char *types,
365			   struct objc_selector *orig, BOOL is_const)
366{
367  struct objc_selector *j;
368  sidx i;
369  struct objc_list *l;
370
371  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
372  if (soffset_decode (i) != 0)
373    {
374      for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
375	   l; l = l->tail)
376	{
377	  SEL s = (SEL) l->head;
378	  if (types == 0 || s->sel_types == 0)
379	    {
380	      if (s->sel_types == types)
381		{
382		  if (orig)
383		    {
384		      orig->sel_id = (void *) i;
385		      return orig;
386		    }
387		  else
388		    return s;
389		}
390	    }
391	  else if (! strcmp (s->sel_types, types))
392	    {
393	      if (orig)
394		{
395		  orig->sel_id = (void *) i;
396		  return orig;
397		}
398	      else
399		return s;
400	    }
401	}
402      if (orig)
403	j = orig;
404      else
405	j = pool_alloc_selector ();
406
407      j->sel_id = (void *) i;
408      /* Can we use the pointer or must copy types?  Don't copy if NULL */
409      if ((is_const) || (types == 0))
410	j->sel_types = (const char *) types;
411      else {
412	j->sel_types = (char *) objc_malloc (strlen (types) + 1);
413	strcpy ((char *) j->sel_types, types);
414      }
415      l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
416    }
417  else
418    {
419      __objc_selector_max_index += 1;
420      i = soffset_encode (__objc_selector_max_index);
421      if (orig)
422	j = orig;
423      else
424	j = pool_alloc_selector ();
425
426      j->sel_id = (void *) i;
427      /* Can we use the pointer or must copy types?  Don't copy if NULL */
428      if ((is_const) || (types == 0))
429	j->sel_types = (const char *) types;
430      else {
431	j->sel_types = (char *) objc_malloc (strlen (types) + 1);
432	strcpy ((char *) j->sel_types, types);
433      }
434      l = 0;
435    }
436
437  DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
438		(long) soffset_decode (i));
439
440  {
441    int is_new = (l == 0);
442    const char *new_name;
443
444    /* Can we use the pointer or must copy name?  Don't copy if NULL */
445    if ((is_const) || (name == 0))
446      new_name = name;
447    else {
448      new_name = (char *) objc_malloc (strlen (name) + 1);
449      strcpy ((char *) new_name, name);
450    }
451
452    l = list_cons ((void *) j, l);
453    sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
454    sarray_at_put_safe (__objc_selector_array, i, (void *) l);
455    if (is_new)
456      objc_hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
457  }
458
459  sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
460
461  return (SEL) j;
462}
463
464SEL
465sel_register_name (const char *name)
466{
467  SEL ret;
468
469  objc_mutex_lock (__objc_runtime_mutex);
470  /* Assume that name is not constant static memory and needs to be
471     copied before put into a runtime structure.  is_const == NO */
472  ret = __sel_register_typed_name (name, 0, 0, NO);
473  objc_mutex_unlock (__objc_runtime_mutex);
474
475  return ret;
476}
477
478SEL
479sel_register_typed_name (const char *name, const char *type)
480{
481  SEL ret;
482
483  objc_mutex_lock (__objc_runtime_mutex);
484  /* Assume that name and type are not constant static memory and need to
485     be copied before put into a runtime structure.  is_const == NO */
486  ret = __sel_register_typed_name (name, type, 0, NO);
487  objc_mutex_unlock (__objc_runtime_mutex);
488
489  return ret;
490}
491