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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libobjc/] [selector.c] - Blame information for rev 19

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* GNU Objective C Runtime selector related functions
2
   Copyright (C) 1993, 1995, 1996, 1997, 2002, 2004 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 2, 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
You should have received a copy of the GNU General Public License along with
17
GCC; see the file COPYING.  If not, write to the Free Software
18
Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
19
 
20
/* As a special exception, if you link this library with files compiled with
21
   GCC to produce an executable, this does not cause the resulting executable
22
   to be covered by the GNU General Public License. This exception does not
23
   however invalidate any other reasons why the executable file might be
24
   covered by the GNU General Public License.  */
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 */
34
static struct sarray *__objc_selector_array = 0; /* uid -> sel  !T:MUTEX */
35
static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
36
static cache_ptr      __objc_selector_hash  = 0; /* name -> uid !T:MUTEX */
37
 
38
/* Number of selectors stored in each of the above tables */
39
unsigned int __objc_selector_max_index = 0;     /* !T:MUTEX */
40
 
41
void __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.  */
53
void
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
   */
74
void
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 */
96
void __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 */
164
BOOL
165
sel_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 */
190
SEL
191
sel_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 */
229
SEL
230
sel_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 */
261
SEL
262
sel_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 */
286
SEL
287
sel_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 */
294
const 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
 
308
BOOL
309
sel_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
 
316
const 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 */
325
extern 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
341
static struct objc_selector *selector_pool;
342
static int selector_pool_left;
343
 
344
static struct objc_selector *
345
pool_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. */
363
SEL
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
 
464
SEL
465
sel_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
 
478
SEL
479
sel_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
}

powered by: WebSVN 2.1.0

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