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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 739 jeremybenn
/* GNU Objective C Runtime class related functions
2
   Copyright (C) 1993, 1995, 1996, 1997, 2001, 2002, 2009, 2010
3
     Free Software Foundation, Inc.
4
   Contributed by Kresten Krab Thorup and Dennis Glatting.
5
 
6
   Lock-free class table code designed and written from scratch by
7
   Nicola Pero, 2001.
8
 
9
This file is part of GCC.
10
 
11
GCC is free software; you can redistribute it and/or modify it under the
12
terms of the GNU General Public License as published by the Free Software
13
Foundation; either version 3, or (at your option) any later version.
14
 
15
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18
details.
19
 
20
Under Section 7 of GPL version 3, you are granted additional
21
permissions described in the GCC Runtime Library Exception, version
22
3.1, as published by the Free Software Foundation.
23
 
24
You should have received a copy of the GNU General Public License and
25
a copy of the GCC Runtime Library Exception along with this program;
26
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
27
<http://www.gnu.org/licenses/>.  */
28
 
29
/* The code in this file critically affects class method invocation
30
  speed.  This long preamble comment explains why, and the issues
31
  involved.
32
 
33
  One of the traditional weaknesses of the GNU Objective-C runtime is
34
  that class method invocations are slow.  The reason is that when you
35
  write
36
 
37
  array = [NSArray new];
38
 
39
  this gets basically compiled into the equivalent of
40
 
41
  array = [(objc_get_class ("NSArray")) new];
42
 
43
  objc_get_class returns the class pointer corresponding to the string
44
  `NSArray'; and because of the lookup, the operation is more
45
  complicated and slow than a simple instance method invocation.
46
 
47
  Most high performance Objective-C code (using the GNU Objc runtime)
48
  I had the opportunity to read (or write) work around this problem by
49
  caching the class pointer:
50
 
51
  Class arrayClass = [NSArray class];
52
 
53
  ... later on ...
54
 
55
  array = [arrayClass new];
56
  array = [arrayClass new];
57
  array = [arrayClass new];
58
 
59
  In this case, you always perform a class lookup (the first one), but
60
  then all the [arrayClass new] methods run exactly as fast as an
61
  instance method invocation.  It helps if you have many class method
62
  invocations to the same class.
63
 
64
  The long-term solution to this problem would be to modify the
65
  compiler to output tables of class pointers corresponding to all the
66
  class method invocations, and to add code to the runtime to update
67
  these tables - that should in the end allow class method invocations
68
  to perform precisely as fast as instance method invocations, because
69
  no class lookup would be involved.  I think the Apple Objective-C
70
  runtime uses this technique.  Doing this involves synchronized
71
  modifications in the runtime and in the compiler.
72
 
73
  As a first medicine to the problem, I [NP] have redesigned and
74
  rewritten the way the runtime is performing class lookup.  This
75
  doesn't give as much speed as the other (definitive) approach, but
76
  at least a class method invocation now takes approximately 4.5 times
77
  an instance method invocation on my machine (it would take approx 12
78
  times before the rewriting), which is a lot better.
79
 
80
  One of the main reason the new class lookup is so faster is because
81
  I implemented it in a way that can safely run multithreaded without
82
  using locks - a so-called `lock-free' data structure.  The atomic
83
  operation is pointer assignment.  The reason why in this problem
84
  lock-free data structures work so well is that you never remove
85
  classes from the table - and the difficult thing with lock-free data
86
  structures is freeing data when is removed from the structures.  */
87
 
88
#include "objc-private/common.h"
89
#include "objc-private/error.h"
90
#include "objc/runtime.h"
91
#include "objc/thr.h"
92
#include "objc-private/module-abi-8.h"  /* For CLS_ISCLASS and similar.  */
93
#include "objc-private/runtime.h"       /* the kitchen sink */
94
#include "objc-private/sarray.h"        /* For sarray_put_at_safe.  */
95
#include "objc-private/selector.h"      /* For sarray_put_at_safe.  */
96
#include <string.h>                     /* For memset */
97
 
98
/* We use a table which maps a class name to the corresponding class
99
   pointer.  The first part of this file defines this table, and
100
   functions to do basic operations on the table.  The second part of
101
   the file implements some higher level Objective-C functionality for
102
   classes by using the functions provided in the first part to manage
103
   the table. */
104
 
105
/**
106
 ** Class Table Internals
107
 **/
108
 
109
/* A node holding a class */
110
typedef struct class_node
111
{
112
  struct class_node *next;      /* Pointer to next entry on the list.
113
                                   NULL indicates end of list. */
114
 
115
  const char *name;             /* The class name string */
116
  int length;                   /* The class name string length */
117
  Class pointer;                /* The Class pointer */
118
 
119
} *class_node_ptr;
120
 
121
/* A table containing classes is a class_node_ptr (pointing to the
122
   first entry in the table - if it is NULL, then the table is
123
   empty). */
124
 
125
/* We have 1024 tables.  Each table contains all class names which
126
   have the same hash (which is a number between 0 and 1023).  To look
127
   up a class_name, we compute its hash, and get the corresponding
128
   table.  Once we have the table, we simply compare strings directly
129
   till we find the one which we want (using the length first).  The
130
   number of tables is quite big on purpose (a normal big application
131
   has less than 1000 classes), so that you shouldn't normally get any
132
   collisions, and get away with a single comparison (which we can't
133
   avoid since we need to know that you have got the right thing).  */
134
#define CLASS_TABLE_SIZE 1024
135
#define CLASS_TABLE_MASK 1023
136
 
137
static class_node_ptr class_table_array[CLASS_TABLE_SIZE];
138
 
139
/* The table writing mutex - we lock on writing to avoid conflicts
140
   between different writers, but we read without locks.  That is
141
   possible because we assume pointer assignment to be an atomic
142
   operation.  TODO: This is only true under certain circumstances,
143
   which should be clarified.  */
144
static objc_mutex_t __class_table_lock = NULL;
145
 
146
/* CLASS_TABLE_HASH is how we compute the hash of a class name.  It is
147
   a macro - *not* a function - arguments *are* modified directly.
148
 
149
   INDEX should be a variable holding an int;
150
   HASH should be a variable holding an int;
151
   CLASS_NAME should be a variable holding a (char *) to the class_name.
152
 
153
   After the macro is executed, INDEX contains the length of the
154
   string, and HASH the computed hash of the string; CLASS_NAME is
155
   untouched.  */
156
 
157
#define CLASS_TABLE_HASH(INDEX, HASH, CLASS_NAME)          \
158
  HASH = 0;                                                  \
159
  for (INDEX = 0; CLASS_NAME[INDEX] != '\0'; INDEX++)        \
160
    {                                                        \
161
      HASH = (HASH << 4) ^ (HASH >> 28) ^ CLASS_NAME[INDEX]; \
162
    }                                                        \
163
                                                             \
164
  HASH = (HASH ^ (HASH >> 10) ^ (HASH >> 20)) & CLASS_TABLE_MASK;
165
 
166
/* Setup the table.  */
167
static void
168
class_table_setup (void)
169
{
170
  /* Start - nothing in the table.  */
171
  memset (class_table_array, 0, sizeof (class_node_ptr) * CLASS_TABLE_SIZE);
172
 
173
  /* The table writing mutex.  */
174
  __class_table_lock = objc_mutex_allocate ();
175
}
176
 
177
 
178
/* Insert a class in the table (used when a new class is
179
   registered).  */
180
static void
181
class_table_insert (const char *class_name, Class class_pointer)
182
{
183
  int hash, length;
184
  class_node_ptr new_node;
185
 
186
  /* Find out the class name's hash and length.  */
187
  CLASS_TABLE_HASH (length, hash, class_name);
188
 
189
  /* Prepare the new node holding the class.  */
190
  new_node = objc_malloc (sizeof (struct class_node));
191
  new_node->name = class_name;
192
  new_node->length = length;
193
  new_node->pointer = class_pointer;
194
 
195
  /* Lock the table for modifications.  */
196
  objc_mutex_lock (__class_table_lock);
197
 
198
  /* Insert the new node in the table at the beginning of the table at
199
     class_table_array[hash].  */
200
  new_node->next = class_table_array[hash];
201
  class_table_array[hash] = new_node;
202
 
203
  objc_mutex_unlock (__class_table_lock);
204
}
205
 
206
/* Get a class from the table.  This does not need mutex protection.
207
   Currently, this function is called each time you call a static
208
   method, this is why it must be very fast.  */
209
static inline Class
210
class_table_get_safe (const char *class_name)
211
{
212
  class_node_ptr node;
213
  int length, hash;
214
 
215
  /* Compute length and hash.  */
216
  CLASS_TABLE_HASH (length, hash, class_name);
217
 
218
  node = class_table_array[hash];
219
 
220
  if (node != NULL)
221
    {
222
      do
223
        {
224
          if (node->length == length)
225
            {
226
              /* Compare the class names.  */
227
              int i;
228
 
229
              for (i = 0; i < length; i++)
230
                {
231
                  if ((node->name)[i] != class_name[i])
232
                    break;
233
                }
234
 
235
              if (i == length)
236
                {
237
                  /* They are equal!  */
238
                  return node->pointer;
239
                }
240
            }
241
        }
242
      while ((node = node->next) != NULL);
243
    }
244
 
245
  return Nil;
246
}
247
 
248
/* Enumerate over the class table.  */
249
struct class_table_enumerator
250
{
251
  int hash;
252
  class_node_ptr node;
253
};
254
 
255
 
256
static Class
257
class_table_next (struct class_table_enumerator **e)
258
{
259
  struct class_table_enumerator *enumerator = *e;
260
  class_node_ptr next;
261
 
262
  if (enumerator == NULL)
263
    {
264
       *e = objc_malloc (sizeof (struct class_table_enumerator));
265
      enumerator = *e;
266
      enumerator->hash = 0;
267
      enumerator->node = NULL;
268
 
269
      next = class_table_array[enumerator->hash];
270
    }
271
  else
272
    next = enumerator->node->next;
273
 
274
  if (next != NULL)
275
    {
276
      enumerator->node = next;
277
      return enumerator->node->pointer;
278
    }
279
  else
280
    {
281
      enumerator->hash++;
282
 
283
      while (enumerator->hash < CLASS_TABLE_SIZE)
284
        {
285
          next = class_table_array[enumerator->hash];
286
          if (next != NULL)
287
            {
288
              enumerator->node = next;
289
              return enumerator->node->pointer;
290
            }
291
          enumerator->hash++;
292
        }
293
 
294
      /* Ok - table finished - done.  */
295
      objc_free (enumerator);
296
      return Nil;
297
    }
298
}
299
 
300
#if 0 /* DEBUGGING FUNCTIONS */
301
/* Debugging function - print the class table.  */
302
void
303
class_table_print (void)
304
{
305
  int i;
306
 
307
  for (i = 0; i < CLASS_TABLE_SIZE; i++)
308
    {
309
      class_node_ptr node;
310
 
311
      printf ("%d:\n", i);
312
      node = class_table_array[i];
313
 
314
      while (node != NULL)
315
        {
316
          printf ("\t%s\n", node->name);
317
          node = node->next;
318
        }
319
    }
320
}
321
 
322
/* Debugging function - print an histogram of number of classes in
323
   function of hash key values.  Useful to evaluate the hash function
324
   in real cases.  */
325
void
326
class_table_print_histogram (void)
327
{
328
  int i, j;
329
  int counter = 0;
330
 
331
  for (i = 0; i < CLASS_TABLE_SIZE; i++)
332
    {
333
      class_node_ptr node;
334
 
335
      node = class_table_array[i];
336
 
337
      while (node != NULL)
338
        {
339
          counter++;
340
          node = node->next;
341
        }
342
      if (((i + 1) % 50) == 0)
343
        {
344
          printf ("%4d:", i + 1);
345
          for (j = 0; j < counter; j++)
346
            printf ("X");
347
 
348
          printf ("\n");
349
          counter = 0;
350
        }
351
    }
352
  printf ("%4d:", i + 1);
353
  for (j = 0; j < counter; j++)
354
    printf ("X");
355
 
356
  printf ("\n");
357
}
358
#endif /* DEBUGGING FUNCTIONS */
359
 
360
/**
361
 ** Objective-C runtime functions
362
 **/
363
 
364
/* From now on, the only access to the class table data structure
365
   should be via the class_table_* functions.  */
366
 
367
/* This is a hook which is called by objc_get_class and
368
   objc_lookup_class if the runtime is not able to find the class.
369
   This may e.g. try to load in the class using dynamic loading.
370
 
371
   This hook was a public, global variable in the Traditional GNU
372
   Objective-C Runtime API (objc/objc-api.h).  The modern GNU
373
   Objective-C Runtime API (objc/runtime.h) provides the
374
   objc_setGetUnknownClassHandler() function instead.
375
*/
376
Class (*_objc_lookup_class) (const char *name) = 0;      /* !T:SAFE */
377
 
378
/* The handler currently in use.  PS: if both
379
   __obj_get_unknown_class_handler and _objc_lookup_class are defined,
380
   __objc_get_unknown_class_handler is called first.  */
381
static objc_get_unknown_class_handler
382
__objc_get_unknown_class_handler = NULL;
383
 
384
objc_get_unknown_class_handler
385
objc_setGetUnknownClassHandler (objc_get_unknown_class_handler
386
                                new_handler)
387
{
388
  objc_get_unknown_class_handler old_handler
389
    = __objc_get_unknown_class_handler;
390
  __objc_get_unknown_class_handler = new_handler;
391
  return old_handler;
392
}
393
 
394
 
395
/* True when class links has been resolved.  */
396
BOOL __objc_class_links_resolved = NO;                  /* !T:UNUSED */
397
 
398
 
399
void
400
__objc_init_class_tables (void)
401
{
402
  /* Allocate the class hash table.  */
403
 
404
  if (__class_table_lock)
405
    return;
406
 
407
  objc_mutex_lock (__objc_runtime_mutex);
408
 
409
  class_table_setup ();
410
 
411
  objc_mutex_unlock (__objc_runtime_mutex);
412
}
413
 
414
/* This function adds a class to the class hash table, and assigns the
415
   class a number, unless it's already known.  Return 'YES' if the
416
   class was added.  Return 'NO' if the class was already known.  */
417
BOOL
418
__objc_add_class_to_hash (Class class)
419
{
420
  Class existing_class;
421
 
422
  objc_mutex_lock (__objc_runtime_mutex);
423
 
424
  /* Make sure the table is there.  */
425
  assert (__class_table_lock);
426
 
427
  /* Make sure it's not a meta class.  */
428
  assert (CLS_ISCLASS (class));
429
 
430
  /* Check to see if the class is already in the hash table.  */
431
  existing_class = class_table_get_safe (class->name);
432
 
433
  if (existing_class)
434
    {
435
      objc_mutex_unlock (__objc_runtime_mutex);
436
      return NO;
437
    }
438
  else
439
    {
440
      /* The class isn't in the hash table.  Add the class and assign
441
         a class number.  */
442
      static unsigned int class_number = 1;
443
 
444
      CLS_SETNUMBER (class, class_number);
445
      CLS_SETNUMBER (class->class_pointer, class_number);
446
 
447
      ++class_number;
448
      class_table_insert (class->name, class);
449
 
450
      objc_mutex_unlock (__objc_runtime_mutex);
451
      return YES;
452
    }
453
}
454
 
455
Class
456
objc_getClass (const char *name)
457
{
458
  Class class;
459
 
460
  if (name == NULL)
461
    return Nil;
462
 
463
  class = class_table_get_safe (name);
464
 
465
  if (class)
466
    return class;
467
 
468
  if (__objc_get_unknown_class_handler)
469
    return (*__objc_get_unknown_class_handler) (name);
470
 
471
  if (_objc_lookup_class)
472
    return (*_objc_lookup_class) (name);
473
 
474
  return Nil;
475
}
476
 
477
Class
478
objc_lookUpClass (const char *name)
479
{
480
  if (name == NULL)
481
    return Nil;
482
  else
483
    return class_table_get_safe (name);
484
}
485
 
486
Class
487
objc_getMetaClass (const char *name)
488
{
489
  Class class = objc_getClass (name);
490
 
491
  if (class)
492
    return class->class_pointer;
493
  else
494
    return Nil;
495
}
496
 
497
Class
498
objc_getRequiredClass (const char *name)
499
{
500
  Class class = objc_getClass (name);
501
 
502
  if (class)
503
    return class;
504
  else
505
    _objc_abort ("objc_getRequiredClass ('%s') failed: class not found\n", name);
506
}
507
 
508
int
509
objc_getClassList (Class *returnValue, int maxNumberOfClassesToReturn)
510
{
511
  /* Iterate over all entries in the table.  */
512
  int hash, count = 0;
513
 
514
  for (hash = 0; hash < CLASS_TABLE_SIZE; hash++)
515
    {
516
      class_node_ptr node = class_table_array[hash];
517
 
518
      while (node != NULL)
519
        {
520
          if (returnValue)
521
            {
522
              if (count < maxNumberOfClassesToReturn)
523
                returnValue[count] = node->pointer;
524
              else
525
                return count;
526
            }
527
          count++;
528
          node = node->next;
529
        }
530
    }
531
 
532
  return count;
533
}
534
 
535
Class
536
objc_allocateClassPair (Class super_class, const char *class_name, size_t extraBytes)
537
{
538
  Class new_class;
539
  Class new_meta_class;
540
 
541
  if (class_name == NULL)
542
    return Nil;
543
 
544
  if (objc_getClass (class_name))
545
    return Nil;
546
 
547
  if (super_class)
548
    {
549
      /* If you want to build a hierarchy of classes, you need to
550
         build and register them one at a time.  The risk is that you
551
         are able to cause confusion by registering a subclass before
552
         the superclass or similar.  */
553
      if (CLS_IS_IN_CONSTRUCTION (super_class))
554
        return Nil;
555
    }
556
 
557
  /* Technically, we should create the metaclass first, then use
558
     class_createInstance() to create the class.  That complication
559
     would be relevant if we had class variables, but we don't, so we
560
     just ignore it and create everything directly and assume all
561
     classes have the same size.  */
562
  new_class = objc_calloc (1, sizeof (struct objc_class) + extraBytes);
563
  new_meta_class = objc_calloc (1, sizeof (struct objc_class) + extraBytes);
564
 
565
  /* We create an unresolved class, similar to one generated by the
566
     compiler.  It will be resolved later when we register it.
567
 
568
     Note how the metaclass details are not that important; when the
569
     class is resolved, the ones that matter will be fixed up.  */
570
  new_class->class_pointer = new_meta_class;
571
  new_meta_class->class_pointer = 0;
572
 
573
  if (super_class)
574
    {
575
      /* Force the name of the superclass in place of the link to the
576
         actual superclass, which will be put there when the class is
577
         resolved.  */
578
      const char *super_class_name = class_getName (super_class);
579
      new_class->super_class = (void *)super_class_name;
580
      new_meta_class->super_class = (void *)super_class_name;
581
    }
582
  else
583
    {
584
      new_class->super_class = (void *)0;
585
      new_meta_class->super_class = (void *)0;
586
    }
587
 
588
  new_class->name = objc_malloc (strlen (class_name) + 1);
589
  strcpy ((char*)new_class->name, class_name);
590
  new_meta_class->name = new_class->name;
591
 
592
  new_class->version = 0;
593
  new_meta_class->version = 0;
594
 
595
  new_class->info = _CLS_CLASS | _CLS_IN_CONSTRUCTION;
596
  new_meta_class->info = _CLS_META | _CLS_IN_CONSTRUCTION;
597
 
598
  if (super_class)
599
    new_class->instance_size = super_class->instance_size;
600
  else
601
    new_class->instance_size = 0;
602
  new_meta_class->instance_size = sizeof (struct objc_class);
603
 
604
  return new_class;
605
}
606
 
607
void
608
objc_registerClassPair (Class class_)
609
{
610
  if (class_ == Nil)
611
    return;
612
 
613
  if ((! CLS_ISCLASS (class_)) || (! CLS_IS_IN_CONSTRUCTION (class_)))
614
    return;
615
 
616
  if ((! CLS_ISMETA (class_->class_pointer)) || (! CLS_IS_IN_CONSTRUCTION (class_->class_pointer)))
617
    return;
618
 
619
  objc_mutex_lock (__objc_runtime_mutex);
620
 
621
  if (objc_getClass (class_->name))
622
    {
623
      objc_mutex_unlock (__objc_runtime_mutex);
624
      return;
625
    }
626
 
627
  CLS_SET_NOT_IN_CONSTRUCTION (class_);
628
  CLS_SET_NOT_IN_CONSTRUCTION (class_->class_pointer);
629
 
630
  __objc_init_class (class_);
631
 
632
  /* Resolve class links immediately.  No point in waiting.  */
633
  __objc_resolve_class_links ();
634
 
635
  objc_mutex_unlock (__objc_runtime_mutex);
636
}
637
 
638
void
639
objc_disposeClassPair (Class class_)
640
{
641
  if (class_ == Nil)
642
    return;
643
 
644
  if ((! CLS_ISCLASS (class_)) || (! CLS_IS_IN_CONSTRUCTION (class_)))
645
    return;
646
 
647
  if ((! CLS_ISMETA (class_->class_pointer)) || (! CLS_IS_IN_CONSTRUCTION (class_->class_pointer)))
648
    return;
649
 
650
  /* Undo any class_addIvar().  */
651
  if (class_->ivars)
652
    {
653
      int i;
654
      for (i = 0; i < class_->ivars->ivar_count; i++)
655
        {
656
          struct objc_ivar *ivar = &(class_->ivars->ivar_list[i]);
657
 
658
          objc_free ((char *)ivar->ivar_name);
659
          objc_free ((char *)ivar->ivar_type);
660
        }
661
 
662
      objc_free (class_->ivars);
663
    }
664
 
665
  /* Undo any class_addMethod().  */
666
  if (class_->methods)
667
    {
668
      struct objc_method_list *list = class_->methods;
669
      while (list)
670
        {
671
          int i;
672
          struct objc_method_list *next = list->method_next;
673
 
674
          for (i = 0; i < list->method_count; i++)
675
            {
676
              struct objc_method *method = &(list->method_list[i]);
677
 
678
              objc_free ((char *)method->method_name);
679
              objc_free ((char *)method->method_types);
680
            }
681
 
682
          objc_free (list);
683
          list = next;
684
        }
685
    }
686
 
687
  /* Undo any class_addProtocol().  */
688
  if (class_->protocols)
689
    {
690
      struct objc_protocol_list *list = class_->protocols;
691
      while (list)
692
        {
693
          struct objc_protocol_list *next = list->next;
694
 
695
          objc_free (list);
696
          list = next;
697
        }
698
    }
699
 
700
  /* Undo any class_addMethod() on the meta-class.  */
701
  if (class_->class_pointer->methods)
702
    {
703
      struct objc_method_list *list = class_->class_pointer->methods;
704
      while (list)
705
        {
706
          int i;
707
          struct objc_method_list *next = list->method_next;
708
 
709
          for (i = 0; i < list->method_count; i++)
710
            {
711
              struct objc_method *method = &(list->method_list[i]);
712
 
713
              objc_free ((char *)method->method_name);
714
              objc_free ((char *)method->method_types);
715
            }
716
 
717
          objc_free (list);
718
          list = next;
719
        }
720
    }
721
 
722
  /* Undo objc_allocateClassPair().  */
723
  objc_free ((char *)(class_->name));
724
  objc_free (class_->class_pointer);
725
  objc_free (class_);
726
}
727
 
728
/* Traditional GNU Objective-C Runtime API.  Important: this method is
729
   called automatically by the compiler while messaging (if using the
730
   traditional ABI), so it is worth keeping it fast; don't make it
731
   just a wrapper around objc_getClass().  */
732
/* Note that this is roughly equivalent to objc_getRequiredClass().  */
733
/* Get the class object for the class named NAME.  If NAME does not
734
   identify a known class, the hook _objc_lookup_class is called.  If
735
   this fails, an error message is issued and the system aborts.  */
736
Class
737
objc_get_class (const char *name)
738
{
739
  Class class;
740
 
741
  class = class_table_get_safe (name);
742
 
743
  if (class)
744
    return class;
745
 
746
  if (__objc_get_unknown_class_handler)
747
    class = (*__objc_get_unknown_class_handler) (name);
748
 
749
  if ((!class)  &&  _objc_lookup_class)
750
    class = (*_objc_lookup_class) (name);
751
 
752
  if (class)
753
    return class;
754
 
755
  _objc_abort ("objc runtime: cannot find class %s\n", name);
756
 
757
  return 0;
758
}
759
 
760
/* This is used by the compiler too.  */
761
Class
762
objc_get_meta_class (const char *name)
763
{
764
  return objc_get_class (name)->class_pointer;
765
}
766
 
767
/* This is not used by GCC, but the clang compiler seems to use it
768
   when targetting the GNU runtime.  That's wrong, but we have it to
769
   be compatible.  */
770
Class
771
objc_lookup_class (const char *name)
772
{
773
  return objc_getClass (name);
774
}
775
 
776
/* This is used when the implementation of a method changes.  It goes
777
   through all classes, looking for the ones that have these methods
778
   (either method_a or method_b; method_b can be NULL), and reloads
779
   the implementation for these.  You should call this with the
780
   runtime mutex already locked.  */
781
void
782
__objc_update_classes_with_methods (struct objc_method *method_a, struct objc_method *method_b)
783
{
784
  int hash;
785
 
786
  /* Iterate over all classes.  */
787
  for (hash = 0; hash < CLASS_TABLE_SIZE; hash++)
788
    {
789
      class_node_ptr node = class_table_array[hash];
790
 
791
      while (node != NULL)
792
        {
793
          /* We execute this loop twice: the first time, we iterate
794
             over all methods in the class (instance methods), while
795
             the second time we iterate over all methods in the meta
796
             class (class methods).  */
797
          Class class = Nil;
798
          BOOL done = NO;
799
 
800
          while (done == NO)
801
            {
802
              struct objc_method_list * method_list;
803
 
804
              if (class == Nil)
805
                {
806
                  /* The first time, we work on the class.  */
807
                  class = node->pointer;
808
                }
809
              else
810
                {
811
                  /* The second time, we work on the meta class.  */
812
                  class = class->class_pointer;
813
                  done = YES;
814
                }
815
 
816
              method_list = class->methods;
817
 
818
              while (method_list)
819
                {
820
                  int i;
821
 
822
                  for (i = 0; i < method_list->method_count; ++i)
823
                    {
824
                      struct objc_method *method = &method_list->method_list[i];
825
 
826
                      /* If the method is one of the ones we are
827
                         looking for, update the implementation.  */
828
                      if (method == method_a)
829
                        sarray_at_put_safe (class->dtable,
830
                                            (sidx) method_a->method_name->sel_id,
831
                                            method_a->method_imp);
832
 
833
                      if (method == method_b)
834
                        {
835
                          if (method_b != NULL)
836
                            sarray_at_put_safe (class->dtable,
837
                                                (sidx) method_b->method_name->sel_id,
838
                                                method_b->method_imp);
839
                        }
840
                    }
841
 
842
                  method_list = method_list->method_next;
843
                }
844
            }
845
          node = node->next;
846
        }
847
    }
848
}
849
 
850
/* Resolve super/subclass links for all classes.  The only thing we
851
   can be sure of is that the class_pointer for class objects point to
852
   the right meta class objects.  */
853
void
854
__objc_resolve_class_links (void)
855
{
856
  struct class_table_enumerator *es = NULL;
857
  Class object_class = objc_get_class ("Object");
858
  Class class1;
859
 
860
  assert (object_class);
861
 
862
  objc_mutex_lock (__objc_runtime_mutex);
863
 
864
  /* Assign subclass links.  */
865
  while ((class1 = class_table_next (&es)))
866
    {
867
      /* Make sure we have what we think we have.  */
868
      assert (CLS_ISCLASS (class1));
869
      assert (CLS_ISMETA (class1->class_pointer));
870
 
871
      /* The class_pointer of all meta classes point to Object's meta
872
         class.  */
873
      class1->class_pointer->class_pointer = object_class->class_pointer;
874
 
875
      if (! CLS_ISRESOLV (class1))
876
        {
877
          CLS_SETRESOLV (class1);
878
          CLS_SETRESOLV (class1->class_pointer);
879
 
880
          if (class1->super_class)
881
            {
882
              Class a_super_class
883
                = objc_get_class ((char *) class1->super_class);
884
 
885
              assert (a_super_class);
886
 
887
              DEBUG_PRINTF ("making class connections for: %s\n",
888
                            class1->name);
889
 
890
              /* Assign subclass links for superclass.  */
891
              class1->sibling_class = a_super_class->subclass_list;
892
              a_super_class->subclass_list = class1;
893
 
894
              /* Assign subclass links for meta class of superclass.  */
895
              if (a_super_class->class_pointer)
896
                {
897
                  class1->class_pointer->sibling_class
898
                    = a_super_class->class_pointer->subclass_list;
899
                  a_super_class->class_pointer->subclass_list
900
                    = class1->class_pointer;
901
                }
902
            }
903
          else /* A root class, make its meta object be a subclass of
904
                  Object.  */
905
            {
906
              class1->class_pointer->sibling_class
907
                = object_class->subclass_list;
908
              object_class->subclass_list = class1->class_pointer;
909
            }
910
        }
911
    }
912
 
913
  /* Assign superclass links.  */
914
   es = NULL;
915
   while ((class1 = class_table_next (&es)))
916
    {
917
      Class sub_class;
918
      for (sub_class = class1->subclass_list; sub_class;
919
           sub_class = sub_class->sibling_class)
920
        {
921
          sub_class->super_class = class1;
922
          if (CLS_ISCLASS (sub_class))
923
            sub_class->class_pointer->super_class = class1->class_pointer;
924
        }
925
    }
926
 
927
  objc_mutex_unlock (__objc_runtime_mutex);
928
}
929
 
930
const char *
931
class_getName (Class class_)
932
{
933
  if (class_ == Nil)
934
    return "nil";
935
 
936
  return class_->name;
937
}
938
 
939
BOOL
940
class_isMetaClass (Class class_)
941
{
942
  /* CLS_ISMETA includes the check for Nil class_.  */
943
  return CLS_ISMETA (class_);
944
}
945
 
946
/* Even inside libobjc it may be worth using class_getSuperclass
947
   instead of accessing class_->super_class directly because it
948
   resolves the class links if needed.  If you access
949
   class_->super_class directly, make sure to deal with the situation
950
   where the class is not resolved yet!  */
951
Class
952
class_getSuperclass (Class class_)
953
{
954
  if (class_ == Nil)
955
    return Nil;
956
 
957
  /* Classes that are in construction are not resolved, and still have
958
     the class name (instead of a class pointer) in the
959
     class_->super_class field.  In that case we need to lookup the
960
     superclass name to return the superclass.  We can not resolve the
961
     class until it is registered.  */
962
  if (CLS_IS_IN_CONSTRUCTION (class_))
963
    {
964
      if (CLS_ISMETA (class_))
965
        return object_getClass ((id)objc_lookUpClass ((const char *)(class_->super_class)));
966
      else
967
        return objc_lookUpClass ((const char *)(class_->super_class));
968
    }
969
 
970
  /* If the class is not resolved yet, super_class would point to a
971
     string (the name of the super class) as opposed to the actual
972
     super class.  In that case, we need to resolve the class links
973
     before we can return super_class.  */
974
  if (! CLS_ISRESOLV (class_))
975
    __objc_resolve_class_links ();
976
 
977
  return class_->super_class;
978
}
979
 
980
int
981
class_getVersion (Class class_)
982
{
983
  if (class_ == Nil)
984
    return 0;
985
 
986
  return (int)(class_->version);
987
}
988
 
989
void
990
class_setVersion (Class class_, int version)
991
{
992
  if (class_ == Nil)
993
    return;
994
 
995
  class_->version = version;
996
}
997
 
998
size_t
999
class_getInstanceSize (Class class_)
1000
{
1001
  if (class_ == Nil)
1002
    return 0;
1003
 
1004
  return class_->instance_size;
1005
}
1006
 

powered by: WebSVN 2.1.0

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