OSDN Git Service

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