OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libobjc/] [selector.c] - Blame information for rev 739

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 739 jeremybenn
/* GNU Objective C Runtime selector related functions
2
   Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004, 2009, 2010
3
   Free Software Foundation, Inc.
4
   Contributed by Kresten Krab Thorup
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify it under the
9
terms of the GNU General Public License as published by the Free Software
10
Foundation; either version 3, or (at your option) any later version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15
details.
16
 
17
Under Section 7 of GPL version 3, you are granted additional
18
permissions described in the GCC Runtime Library Exception, version
19
3.1, as published by the Free Software Foundation.
20
 
21
You should have received a copy of the GNU General Public License and
22
a copy of the GCC Runtime Library Exception along with this program;
23
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24
<http://www.gnu.org/licenses/>.  */
25
 
26
#include "objc-private/common.h"
27
#include "objc/runtime.h"
28
#include "objc/thr.h"
29
#include "objc-private/hash.h"
30
#include "objc-private/objc-list.h"
31
#include "objc-private/module-abi-8.h"
32
#include "objc-private/runtime.h"
33
#include "objc-private/sarray.h"
34
#include "objc-private/selector.h"
35
#include <stdlib.h>                    /* For malloc.  */
36
 
37
/* Initial selector hash table size. Value doesn't matter much.  */
38
#define SELECTOR_HASH_SIZE 128
39
 
40
/* Tables mapping selector names to uid and opposite.  */
41
static struct sarray *__objc_selector_array = 0; /* uid -> sel  !T:MUTEX */
42
static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
43
static cache_ptr      __objc_selector_hash  = 0; /* name -> uid !T:MUTEX */
44
 
45
/* Number of selectors stored in each of the above tables.  */
46
unsigned int __objc_selector_max_index = 0;     /* !T:MUTEX */
47
 
48
/* Forward-declare an internal function.  */
49
static SEL
50
__sel_register_typed_name (const char *name, const char *types,
51
                           struct objc_selector *orig, BOOL is_const);
52
 
53
void __objc_init_selector_tables (void)
54
{
55
  __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
56
  __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
57
  __objc_selector_hash
58
    = objc_hash_new (SELECTOR_HASH_SIZE,
59
                     (hash_func_type) objc_hash_string,
60
                     (compare_func_type) objc_compare_strings);
61
}
62
 
63
/* Register a bunch of selectors from the table of selectors in a
64
   module.  'selectors' should not be NULL.  The list is terminated by
65
   a selectors with a NULL sel_id.  The selectors are assumed to
66
   contain the 'name' in the sel_id field; this is replaced with the
67
   final selector id after they are registered.  */
68
void
69
__objc_register_selectors_from_module (struct objc_selector *selectors)
70
{
71
  int i;
72
 
73
  for (i = 0; selectors[i].sel_id; ++i)
74
    {
75
      const char *name, *type;
76
      name = (char *) selectors[i].sel_id;
77
      type = (char *) selectors[i].sel_types;
78
      /* Constructors are constant static data and we can safely store
79
         pointers to them in the runtime structures, so we set
80
         is_const == YES.  */
81
      __sel_register_typed_name (name, type, (struct objc_selector *) &(selectors[i]),
82
                                 /* is_const */ YES);
83
    }
84
}
85
 
86
/* This routine is given a class and records all of the methods in its
87
   class structure in the record table.  */
88
void
89
__objc_register_selectors_from_class (Class class)
90
{
91
  struct objc_method_list * method_list;
92
 
93
  method_list = class->methods;
94
  while (method_list)
95
    {
96
      __objc_register_selectors_from_list (method_list);
97
      method_list = method_list->method_next;
98
    }
99
}
100
 
101
 
102
/* This routine is given a list of methods and records each of the
103
   methods in the record table.  This is the routine that does the
104
   actual recording work.
105
 
106
   The name and type pointers in the method list must be permanent and
107
   immutable.  */
108
void
109
__objc_register_selectors_from_list (struct objc_method_list *method_list)
110
{
111
  int i = 0;
112
 
113
  objc_mutex_lock (__objc_runtime_mutex);
114
  while (i < method_list->method_count)
115
    {
116
      Method method = &method_list->method_list[i];
117
      if (method->method_name)
118
        {
119
          method->method_name
120
            = __sel_register_typed_name ((const char *) method->method_name,
121
                                         method->method_types, 0, YES);
122
        }
123
      i += 1;
124
    }
125
  objc_mutex_unlock (__objc_runtime_mutex);
126
}
127
 
128
/* The same as __objc_register_selectors_from_list, but works on a
129
   struct objc_method_description_list* instead of a struct
130
   objc_method_list*.  This is only used for protocols, which have
131
   lists of method descriptions, not methods.  */
132
void
133
__objc_register_selectors_from_description_list
134
(struct objc_method_description_list *method_list)
135
{
136
  int i = 0;
137
 
138
  objc_mutex_lock (__objc_runtime_mutex);
139
  while (i < method_list->count)
140
    {
141
      struct objc_method_description *method = &method_list->list[i];
142
      if (method->name)
143
        {
144
          method->name
145
            = __sel_register_typed_name ((const char *) method->name,
146
                                         method->types, 0, YES);
147
        }
148
      i += 1;
149
    }
150
  objc_mutex_unlock (__objc_runtime_mutex);
151
}
152
 
153
/* Register instance methods as class methods for root classes.  */
154
void __objc_register_instance_methods_to_class (Class class)
155
{
156
  struct objc_method_list *method_list;
157
  struct objc_method_list *class_method_list;
158
  int max_methods_no = 16;
159
  struct objc_method_list *new_list;
160
  Method curr_method;
161
 
162
  /* Only if a root class. */
163
  if (class->super_class)
164
    return;
165
 
166
  /* Allocate a method list to hold the new class methods.  */
167
  new_list = objc_calloc (sizeof (struct objc_method_list)
168
                          + sizeof (struct objc_method[max_methods_no]), 1);
169
  method_list = class->methods;
170
  class_method_list = class->class_pointer->methods;
171
  curr_method = &new_list->method_list[0];
172
 
173
  /* Iterate through the method lists for the class.  */
174
  while (method_list)
175
    {
176
      int i;
177
 
178
      /* Iterate through the methods from this method list.  */
179
      for (i = 0; i < method_list->method_count; i++)
180
        {
181
          Method mth = &method_list->method_list[i];
182
          if (mth->method_name
183
              && ! search_for_method_in_list (class_method_list,
184
                                              mth->method_name))
185
            {
186
              /* This instance method isn't a class method.  Add it
187
                 into the new_list. */
188
              *curr_method = *mth;
189
 
190
              /* Reallocate the method list if necessary.  */
191
              if (++new_list->method_count == max_methods_no)
192
                new_list =
193
                  objc_realloc (new_list, sizeof (struct objc_method_list)
194
                                + sizeof (struct
195
                                          objc_method[max_methods_no += 16]));
196
              curr_method = &new_list->method_list[new_list->method_count];
197
            }
198
        }
199
 
200
      method_list = method_list->method_next;
201
    }
202
 
203
  /* If we created any new class methods then attach the method list
204
     to the class.  */
205
  if (new_list->method_count)
206
    {
207
      new_list =
208
        objc_realloc (new_list, sizeof (struct objc_method_list)
209
                      + sizeof (struct objc_method[new_list->method_count]));
210
      new_list->method_next = class->class_pointer->methods;
211
      class->class_pointer->methods = new_list;
212
    }
213
  else
214
    objc_free(new_list);
215
 
216
  __objc_update_dispatch_table_for_class (class->class_pointer);
217
}
218
 
219
BOOL
220
sel_isEqual (SEL s1, SEL s2)
221
{
222
  if (s1 == 0 || s2 == 0)
223
    return s1 == s2;
224
  else
225
    return s1->sel_id == s2->sel_id;
226
}
227
 
228
/* Return YES iff t1 and t2 have same method types.  Ignore the
229
   argframe layout.  */
230
static BOOL
231
sel_types_match (const char *t1, const char *t2)
232
{
233
  if (! t1 || ! t2)
234
    return NO;
235
  while (*t1 && *t2)
236
    {
237
      if (*t1 == '+') t1++;
238
      if (*t2 == '+') t2++;
239
      while (isdigit ((unsigned char) *t1)) t1++;
240
      while (isdigit ((unsigned char) *t2)) t2++;
241
      /* xxx Remove these next two lines when qualifiers are put in
242
         all selectors, not just Protocol selectors.  */
243
      t1 = objc_skip_type_qualifiers (t1);
244
      t2 = objc_skip_type_qualifiers (t2);
245
      if (! *t1 && ! *t2)
246
        return YES;
247
      if (*t1 != *t2)
248
        return NO;
249
      t1++;
250
      t2++;
251
    }
252
  return NO;
253
}
254
 
255
/* Return selector representing name.  */
256
SEL
257
sel_get_any_uid (const char *name)
258
{
259
  struct objc_list *l;
260
  sidx i;
261
 
262
  objc_mutex_lock (__objc_runtime_mutex);
263
 
264
  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
265
  if (soffset_decode (i) == 0)
266
    {
267
      objc_mutex_unlock (__objc_runtime_mutex);
268
      return 0;
269
    }
270
 
271
  l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
272
  objc_mutex_unlock (__objc_runtime_mutex);
273
 
274
  if (l == 0)
275
    return 0;
276
 
277
  return (SEL) l->head;
278
}
279
 
280
SEL
281
sel_getTypedSelector (const char *name)
282
{
283
  sidx i;
284
 
285
  if (name == NULL)
286
    return NULL;
287
 
288
  objc_mutex_lock (__objc_runtime_mutex);
289
 
290
  /* Look for a typed selector.  */
291
  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
292
  if (i != 0)
293
    {
294
      struct objc_list *l;
295
      SEL returnValue = NULL;
296
 
297
      for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
298
           l; l = l->tail)
299
        {
300
          SEL s = (SEL) l->head;
301
          if (s->sel_types)
302
            {
303
              if (returnValue == NULL)
304
                {
305
                  /* First typed selector that we find.  Keep it in
306
                     returnValue, but keep checking as we want to
307
                     detect conflicts.  */
308
                  returnValue = s;
309
                }
310
              else
311
                {
312
                  /* We had already found a typed selectors, so we
313
                     have multiple ones.  Double-check that they have
314
                     different types, just in case for some reason we
315
                     got duplicates with the same types.  If so, it's
316
                     OK, we'll ignore the duplicate.  */
317
                  if (returnValue->sel_types == s->sel_types)
318
                    continue;
319
                  else if (sel_types_match (returnValue->sel_types, s->sel_types))
320
                    continue;
321
                  else
322
                    {
323
                      /* The types of the two selectors are different;
324
                         it's a conflict.  Too bad.  Return NULL.  */
325
                      objc_mutex_unlock (__objc_runtime_mutex);
326
                      return NULL;
327
                    }
328
                }
329
            }
330
        }
331
 
332
      if (returnValue != NULL)
333
        {
334
          objc_mutex_unlock (__objc_runtime_mutex);
335
          return returnValue;
336
        }
337
    }
338
 
339
  /* No typed selector found.  Return NULL.  */
340
  objc_mutex_unlock (__objc_runtime_mutex);
341
  return 0;
342
}
343
 
344
SEL *
345
sel_copyTypedSelectorList (const char *name, unsigned int *numberOfReturnedSelectors)
346
{
347
  unsigned int count = 0;
348
  SEL *returnValue = NULL;
349
  sidx i;
350
 
351
  if (name == NULL)
352
    {
353
      if (numberOfReturnedSelectors)
354
        *numberOfReturnedSelectors = 0;
355
      return NULL;
356
    }
357
 
358
  objc_mutex_lock (__objc_runtime_mutex);
359
 
360
  /* Count how many selectors we have.  */
361
  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
362
  if (i != 0)
363
    {
364
      struct objc_list *selector_list = NULL;
365
      selector_list = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
366
 
367
      /* Count how many selectors we have.  */
368
      {
369
        struct objc_list *l;
370
        for (l = selector_list; l; l = l->tail)
371
          count++;
372
      }
373
 
374
      if (count != 0)
375
        {
376
          /* Allocate enough memory to hold them.  */
377
          returnValue = (SEL *)(malloc (sizeof (SEL) * (count + 1)));
378
 
379
          /* Copy the selectors.  */
380
          {
381
            unsigned int j;
382
            for (j = 0; j < count; j++)
383
              {
384
                returnValue[j] = (SEL)(selector_list->head);
385
                selector_list = selector_list->tail;
386
              }
387
            returnValue[j] = NULL;
388
          }
389
        }
390
    }
391
 
392
  objc_mutex_unlock (__objc_runtime_mutex);
393
 
394
  if (numberOfReturnedSelectors)
395
    *numberOfReturnedSelectors = count;
396
 
397
  return returnValue;
398
}
399
 
400
/* Get the name of a selector.  If the selector is unknown, the empty
401
   string "" is returned.  */
402
const char *sel_getName (SEL selector)
403
{
404
  const char *ret;
405
 
406
  if (selector == NULL)
407
    return "<null selector>";
408
 
409
  objc_mutex_lock (__objc_runtime_mutex);
410
  if ((soffset_decode ((sidx)selector->sel_id) > 0)
411
      && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
412
    ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
413
  else
414
    ret = 0;
415
  objc_mutex_unlock (__objc_runtime_mutex);
416
  return ret;
417
}
418
 
419
BOOL
420
sel_is_mapped (SEL selector)
421
{
422
  unsigned int idx = soffset_decode ((sidx)selector->sel_id);
423
  return ((idx > 0) && (idx <= __objc_selector_max_index));
424
}
425
 
426
const char *sel_getTypeEncoding (SEL selector)
427
{
428
  if (selector)
429
    return selector->sel_types;
430
  else
431
    return 0;
432
}
433
 
434
/* The uninstalled dispatch table.  */
435
extern struct sarray *__objc_uninstalled_dtable;
436
 
437
/* __sel_register_typed_name allocates lots of struct objc_selector:s
438
   of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the
439
   number of malloc calls and memory lost to malloc overhead, we
440
   allocate objc_selector:s in blocks here. This is only called from
441
   __sel_register_typed_name, and __sel_register_typed_name may only
442
   be called when __objc_runtime_mutex is locked.
443
 
444
   Note that the objc_selector:s allocated from
445
   __sel_register_typed_name are never freed.
446
 
447
   62 because 62 * sizeof (struct objc_selector) = 496 (992). This
448
   should let malloc add some overhead and use a nice, round 512
449
   (1024) byte chunk.  */
450
#define SELECTOR_POOL_SIZE 62
451
static struct objc_selector *selector_pool;
452
static int selector_pool_left;
453
 
454
static struct objc_selector *
455
pool_alloc_selector(void)
456
{
457
  if (!selector_pool_left)
458
    {
459
      selector_pool = objc_malloc (sizeof (struct objc_selector)
460
                                   * SELECTOR_POOL_SIZE);
461
      selector_pool_left = SELECTOR_POOL_SIZE;
462
    }
463
  return &selector_pool[--selector_pool_left];
464
}
465
 
466
/* Store the passed selector name in the selector record and return
467
   its selector value (value returned by sel_get_uid).  Assume that
468
   the calling function has locked down __objc_runtime_mutex.  The
469
   'is_const' parameter tells us if the name and types parameters are
470
   really constant or not.  If YES then they are constant and we can
471
   just store the pointers.  If NO then we need to copy name and types
472
   because the pointers may disappear later on.  If the 'orig'
473
   parameter is not NULL, then we are registering a selector from a
474
   module, and 'orig' is that selector.  In this case, we can put the
475
   selector in the tables if needed, and orig->sel_id is updated with
476
   the selector ID of the registered selector, and 'orig' is
477
   returned.  */
478
static SEL
479
__sel_register_typed_name (const char *name, const char *types,
480
                           struct objc_selector *orig, BOOL is_const)
481
{
482
  struct objc_selector *j;
483
  sidx i;
484
  struct objc_list *l;
485
 
486
  i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
487
  if (soffset_decode (i) != 0)
488
    {
489
      /* There are already selectors with that name.  Examine them to
490
         see if the one we're registering already exists.  */
491
      for (l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
492
           l; l = l->tail)
493
        {
494
          SEL s = (SEL)l->head;
495
          if (types == 0 || s->sel_types == 0)
496
            {
497
              if (s->sel_types == types)
498
                {
499
                  if (orig)
500
                    {
501
                      orig->sel_id = (void *)i;
502
                      return orig;
503
                    }
504
                  else
505
                    return s;
506
                }
507
            }
508
          else if (sel_types_match (s->sel_types, types))
509
            {
510
              if (orig)
511
                {
512
                  orig->sel_id = (void *)i;
513
                  return orig;
514
                }
515
              else
516
                return s;
517
            }
518
        }
519
      /* A selector with this specific name/type combination does not
520
         exist yet.  We need to register it.  */
521
      if (orig)
522
        j = orig;
523
      else
524
        j = pool_alloc_selector ();
525
 
526
      j->sel_id = (void *)i;
527
      /* Can we use the pointer or must we copy types ?  Don't copy if
528
         NULL.  */
529
      if ((is_const) || (types == 0))
530
        j->sel_types = types;
531
      else
532
        {
533
          j->sel_types = (char *)objc_malloc (strlen (types) + 1);
534
          strcpy ((char *)j->sel_types, types);
535
        }
536
      l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
537
    }
538
  else
539
    {
540
      /* There are no other selectors with this name registered in the
541
         runtime tables.  */
542
      const char *new_name;
543
 
544
      /* Determine i.  */
545
      __objc_selector_max_index += 1;
546
      i = soffset_encode (__objc_selector_max_index);
547
 
548
      /* Prepare the selector.  */
549
      if (orig)
550
        j = orig;
551
      else
552
        j = pool_alloc_selector ();
553
 
554
      j->sel_id = (void *)i;
555
      /* Can we use the pointer or must we copy types ?  Don't copy if
556
         NULL.  */
557
      if (is_const || (types == 0))
558
        j->sel_types = types;
559
      else
560
        {
561
          j->sel_types = (char *)objc_malloc (strlen (types) + 1);
562
          strcpy ((char *)j->sel_types, types);
563
        }
564
 
565
      /* Since this is the first selector with this name, we need to
566
         register the correspondence between 'i' (the sel_id) and
567
         'name' (the actual string) in __objc_selector_names and
568
         __objc_selector_hash.  */
569
 
570
      /* Can we use the pointer or must we copy name ?  Don't copy if
571
         NULL.  (FIXME: Can the name really be NULL here ?)  */
572
      if (is_const || (name == 0))
573
        new_name = name;
574
      else
575
        {
576
          new_name = (char *)objc_malloc (strlen (name) + 1);
577
          strcpy ((char *)new_name, name);
578
        }
579
 
580
      /* This maps the sel_id to the name.  */
581
      sarray_at_put_safe (__objc_selector_names, i, (void *)new_name);
582
 
583
      /* This maps the name to the sel_id.  */
584
      objc_hash_add (&__objc_selector_hash, (void *)new_name, (void *)i);
585
 
586
      l = 0;
587
    }
588
 
589
  DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
590
                (long)soffset_decode (i));
591
 
592
  /* Now add the selector to the list of selectors with that id.  */
593
  l = list_cons ((void *)j, l);
594
  sarray_at_put_safe (__objc_selector_array, i, (void *)l);
595
 
596
  sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
597
 
598
  return (SEL)j;
599
}
600
 
601
SEL
602
sel_registerName (const char *name)
603
{
604
  SEL ret;
605
 
606
  if (name == NULL)
607
    return NULL;
608
 
609
  objc_mutex_lock (__objc_runtime_mutex);
610
  /* Assume that name is not constant static memory and needs to be
611
     copied before put into a runtime structure.  is_const == NO.  */
612
  ret = __sel_register_typed_name (name, 0, 0, NO);
613
  objc_mutex_unlock (__objc_runtime_mutex);
614
 
615
  return ret;
616
}
617
 
618
SEL
619
sel_registerTypedName (const char *name, const char *type)
620
{
621
  SEL ret;
622
 
623
  if (name == NULL)
624
    return NULL;
625
 
626
  objc_mutex_lock (__objc_runtime_mutex);
627
  /* Assume that name and type are not constant static memory and need
628
     to be copied before put into a runtime structure.  is_const ==
629
     NO.  */
630
  ret = __sel_register_typed_name (name, type, 0, NO);
631
  objc_mutex_unlock (__objc_runtime_mutex);
632
 
633
  return ret;
634
}
635
 
636
/* Return the selector representing name.  */
637
SEL
638
sel_getUid (const char *name)
639
{
640
  return sel_registerTypedName (name, 0);
641
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.