~ubuntu-branches/ubuntu/edgy/sope/edgy

« back to all changes in this revision

Viewing changes to gnustep-objc/gc.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Ley
  • Date: 2005-08-19 16:53:31 UTC
  • Revision ID: james.westby@ubuntu.com-20050819165331-hs683wz1osm708pw
Tags: upstream-4.4rc.2
ImportĀ upstreamĀ versionĀ 4.4rc.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Basic data types for Objective C.
 
2
   Copyright (C) 1998 Free Software Foundation, Inc.
 
3
   Contributed by Ovidiu Predescu.
 
4
 
 
5
This file is part of GNU CC.
 
6
 
 
7
GNU CC is free software; you can redistribute it and/or modify
 
8
it under the terms of the GNU General Public License as published by
 
9
the Free Software Foundation; either version 2, or (at your option)
 
10
any later version.
 
11
 
 
12
GNU CC is distributed in the hope that it will be useful,
 
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with GNU CC; see the file COPYING.  If not, write to
 
19
the Free Software Foundation, 59 Temple Place - Suite 330,
 
20
Boston, MA 02111-1307, USA.  */
 
21
 
 
22
/* As a special exception, if you link this library with files
 
23
   compiled with GCC to produce an executable, this does not cause
 
24
   the resulting executable to be covered by the GNU General Public License.
 
25
   This exception does not however invalidate any other reasons why
 
26
   the executable file might be covered by the GNU General Public License.  */
 
27
 
 
28
#include "compiler-info.h"
 
29
#include "objc.h"
 
30
#include "encoding.h"
 
31
#include "objc-api.h"
 
32
 
 
33
#include <assert.h>
 
34
#include <string.h>
 
35
 
 
36
#if OBJC_WITH_GC
 
37
 
 
38
#include "gc/gc.h"
 
39
 
 
40
/* gc_typed.h uses the following but doesn't declare them */
 
41
typedef GC_word word;
 
42
typedef GC_signed_word signed_word;
 
43
 
 
44
#if BITS_PER_WORD == 32
 
45
# define LOGWL  5
 
46
# define modWORDSZ(n) ((n) & 0x1f)        /* n mod size of word     */
 
47
#endif
 
48
 
 
49
#if BITS_PER_WORD == 64
 
50
# define LOGWL 6
 
51
# define modWORDSZ(n) ((n) & 0x3f)        /* n mod size of word     */
 
52
#endif
 
53
 
 
54
#define divWORDSZ(n) ((n) >> LOGWL)        /* divide n by size of word      */
 
55
 
 
56
#include "gc/gc_typed.h"
 
57
 
 
58
/* The following functions set up in `mask` the corresponding pointers.
 
59
   The offset is incremented with the size of the type.  */
 
60
 
 
61
#define ROUND(V, A) \
 
62
  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
 
63
     __a*((__v+__a-1)/__a); })
 
64
 
 
65
#define SET_BIT_FOR_OFFSET(mask, offset) \
 
66
  GC_set_bit(mask, offset / sizeof (void*))
 
67
 
 
68
/* Some prototypes */
 
69
static void
 
70
__objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset);
 
71
static void
 
72
__objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
 
73
 
 
74
 
 
75
static void
 
76
__objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
 
77
{
 
78
  register int i, len;
 
79
 
 
80
  if (type == NULL) {
 
81
    printf("WARNING: %s got NULL type.\n", __PRETTY_FUNCTION__);
 
82
    return;
 
83
  }
 
84
 
 
85
  len = atoi(type + 1);
 
86
 
 
87
  while (isdigit(*++type))
 
88
    /* do nothing */;           /* skip the size of the array */
 
89
 
 
90
  switch (*type) {
 
91
  case _C_ARY_B:
 
92
    for (i = 0; i < len; i++)
 
93
      __objc_gc_setup_array (mask, type, offset);
 
94
    break;
 
95
 
 
96
  case _C_STRUCT_B:
 
97
    for (i = 0; i < len; i++)
 
98
      __objc_gc_setup_struct (mask, type, offset);
 
99
    break;
 
100
 
 
101
  case _C_UNION_B:
 
102
    for (i = 0; i < len; i++)
 
103
      __objc_gc_setup_union (mask, type, offset);
 
104
    break;
 
105
 
 
106
  default:
 
107
    break;
 
108
  }
 
109
}
 
110
 
 
111
static void
 
112
__objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset)
 
113
{
 
114
  struct objc_struct_layout layout;
 
115
  unsigned int position;
 
116
  const char *mtype;
 
117
 
 
118
  if (type == NULL) {
 
119
    printf("WARNING: %s got NULL type.\n", __PRETTY_FUNCTION__);
 
120
    return;
 
121
  }
 
122
 
 
123
  objc_layout_structure (type, &layout);
 
124
 
 
125
  while (objc_layout_structure_next_member (&layout))
 
126
    {
 
127
      BOOL gc_invisible = NO;
 
128
 
 
129
      objc_layout_structure_get_info (&layout, &position, NULL, &mtype);
 
130
 
 
131
      /* Skip the variable name */
 
132
      if (*mtype == '"')
 
133
        {
 
134
          for (mtype++; *mtype++ != '"';)
 
135
            /* do nothing */;
 
136
        }
 
137
 
 
138
      if (*mtype == _C_GCINVISIBLE)
 
139
        {
 
140
          gc_invisible = YES;
 
141
          mtype++;
 
142
        }
 
143
 
 
144
      /* Add to position the offset of this structure */
 
145
      position += offset;
 
146
 
 
147
      switch (*mtype) {
 
148
      case _C_ID:
 
149
      case _C_CLASS:
 
150
      case _C_SEL:
 
151
      case _C_PTR:
 
152
      case _C_CHARPTR:
 
153
      case _C_ATOM:
 
154
        if (!gc_invisible)
 
155
          SET_BIT_FOR_OFFSET(mask, position);
 
156
        break;
 
157
 
 
158
      case _C_ARY_B:
 
159
        __objc_gc_setup_array (mask, mtype, position);
 
160
        break;
 
161
 
 
162
      case _C_STRUCT_B:
 
163
        __objc_gc_setup_struct (mask, mtype, position);
 
164
        break;
 
165
 
 
166
      case _C_UNION_B:
 
167
        __objc_gc_setup_union (mask, mtype, position);
 
168
        break;
 
169
 
 
170
      default:
 
171
        break;
 
172
      }
 
173
    }
 
174
}
 
175
 
 
176
static void
 
177
__objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
 
178
{
 
179
  /* Sub-optimal, quick implementation: assume the union is made of
 
180
     pointers, set up the mask accordingly. */
 
181
 
 
182
  int i, size, align;
 
183
 
 
184
  if (type == NULL) {
 
185
    printf("WARNING: %s got NULL type.\n", __PRETTY_FUNCTION__);
 
186
    return;
 
187
  }
 
188
 
 
189
  /* Skip the variable name */
 
190
  if (*type == '"')
 
191
    {
 
192
      for (type++; *type++ != '"';)
 
193
        /* do nothing */;
 
194
    }
 
195
 
 
196
  size = objc_sizeof_type (type);
 
197
  align = objc_alignof_type (type);
 
198
 
 
199
  offset = ROUND(offset, align);
 
200
  for (i = 0; i < size; i += sizeof (void*))
 
201
    {
 
202
      SET_BIT_FOR_OFFSET(mask, offset);
 
203
      offset += sizeof (void*);
 
204
    }
 
205
}
 
206
 
 
207
 
 
208
/* Iterates over the types in the structure that represents the class
 
209
   encoding and sets the bits in mask according to each ivar type.  */
 
210
static void
 
211
__objc_gc_type_description_from_type (GC_bitmap mask, const char *type)
 
212
{
 
213
  struct objc_struct_layout layout;
 
214
  unsigned int offset, align;
 
215
  const char   *ivar_type;
 
216
 
 
217
  if (type == NULL) {
 
218
    printf("WARNING: %s got NULL type.\n", __PRETTY_FUNCTION__);
 
219
    return;
 
220
  }
 
221
 
 
222
  objc_layout_structure (type, &layout);
 
223
 
 
224
  while (objc_layout_structure_next_member (&layout)) {
 
225
    BOOL gc_invisible = NO;
 
226
 
 
227
    objc_layout_structure_get_info (&layout, &offset, &align, &ivar_type);
 
228
 
 
229
    /* Skip the variable name */
 
230
    if (*ivar_type == '"') {
 
231
      for (ivar_type++; *ivar_type++ != '"';)
 
232
        /* do nothing */;
 
233
    }
 
234
 
 
235
    if (*ivar_type == _C_GCINVISIBLE) {
 
236
      gc_invisible = YES;
 
237
      ivar_type++;
 
238
    }
 
239
 
 
240
    switch (*ivar_type) {
 
241
      case _C_ID:
 
242
      case _C_CLASS:
 
243
      case _C_SEL:
 
244
      case _C_PTR:
 
245
      case _C_CHARPTR:
 
246
        if (!gc_invisible)
 
247
          SET_BIT_FOR_OFFSET(mask, offset);
 
248
        break;
 
249
 
 
250
      case _C_ARY_B:
 
251
        __objc_gc_setup_array (mask, ivar_type, offset);
 
252
        break;
 
253
 
 
254
      case _C_STRUCT_B:
 
255
        __objc_gc_setup_struct (mask, ivar_type, offset);
 
256
        break;
 
257
 
 
258
      case _C_UNION_B:
 
259
        __objc_gc_setup_union (mask, ivar_type, offset);
 
260
        break;
 
261
 
 
262
      default:
 
263
        break;
 
264
    }
 
265
  }
 
266
}
 
267
 
 
268
/* Computes in *type the full type encoding of this class including
 
269
   its super classes. '*size' gives the total number of bytes allocated
 
270
   into *type, '*current' the number of bytes used so far by the
 
271
   encoding. */
 
272
static void
 
273
__objc_class_structure_encoding (Class class, char **type, int *size,
 
274
                                 int *current)
 
275
{
 
276
  int i, ivar_count;
 
277
  struct objc_ivar_list* ivars;
 
278
 
 
279
  if (class == Nil) {
 
280
    // Root class, add '{'
 
281
    strcat (*type, "{");
 
282
    *current++;
 
283
    return;
 
284
  }
 
285
 
 
286
  /* Add the type encodings of the super classes */
 
287
  __objc_class_structure_encoding (class->super_class, type, size, current);
 
288
 
 
289
  ivars = class->ivars;
 
290
  if (!ivars)
 
291
    return;
 
292
 
 
293
  ivar_count = ivars->ivar_count;
 
294
 
 
295
  for (i = 0; i < ivar_count; i++) {
 
296
    struct objc_ivar *ivar = &(ivars->ivar_list[i]);
 
297
    const char *ivar_type = ivar->ivar_type;
 
298
    int len = strlen (ivar_type);
 
299
 
 
300
    if (*current + len + 1 >= *size)
 
301
      {
 
302
        /* Increase the size of the encoding string so that it
 
303
           contains this ivar's type. */
 
304
        *size = ROUND(*current + len + 1, 10);
 
305
        *type = objc_realloc (*type, *size);
 
306
      }
 
307
    strcat (*type + *current, ivar_type);
 
308
    *current += len;
 
309
  }
 
310
}
 
311
 
 
312
 
 
313
/* Allocates the memory that will hold the type description for class
 
314
   and calls the __objc_class_structure_encoding that generates this
 
315
   value. */
 
316
void __objc_generate_gc_type_description (Class class)
 
317
{
 
318
  GC_bitmap mask                  = NULL;
 
319
  int       bits_no, size;
 
320
  int       type_size             = 800;
 
321
  int       current               = 0;
 
322
  char      *class_structure_type = NULL;
 
323
 
 
324
  if (!CLS_ISCLASS(class))
 
325
    return;
 
326
 
 
327
  /* We have to create a mask in which each bit counts for a pointer member.
 
328
     We take into consideration all the non-pointer instance variables and we
 
329
     round them up to the alignment. */
 
330
 
 
331
  //class_structure_type = objc_atomic_malloc (type_size);
 
332
  class_structure_type = GC_MALLOC_ATOMIC(1024);
 
333
  class_structure_type[0] = '\0';
 
334
  __objc_class_structure_encoding (class,
 
335
                                   &class_structure_type,
 
336
                                   &type_size,
 
337
                                   &current);
 
338
  //if (current + 1 == type_size)
 
339
  //  class_structure_type = objc_realloc (class_structure_type, ++type_size);
 
340
  // add root class suffix
 
341
  strcat (class_structure_type + current, "}");
 
342
 
 
343
  if (class_structure_type[0] != '{') {
 
344
    printf("ERROR: invalid class type '%s'",
 
345
           class_structure_type ? class_structure_type : "<NULL>");
 
346
    abort();
 
347
  }
 
348
  if (class_structure_type[strlen(class_structure_type) - 1] != '}') {
 
349
    printf("ERROR: invalid class type '%s'",
 
350
           class_structure_type ? class_structure_type : "<NULL>");
 
351
    abort();
 
352
  }
 
353
 
 
354
#if DEBUG_OBJC_GC
 
355
  printf ("type description for '%s' is %s\n",
 
356
          class->name ? class->name : "<NULL>",
 
357
          class_structure_type ? class_structure_type : "<NULL>");
 
358
#endif
 
359
 
 
360
  if (class_structure_type == NULL) {
 
361
    printf("WARNING: %s got NULL type for class %s.\n",
 
362
           __PRETTY_FUNCTION__, class->name ? class->name : "<NULL>");
 
363
    abort();
 
364
  }
 
365
 
 
366
  /* The number of bits in the mask is the size of an instance in bytes divided
 
367
     by the size of a pointer. */
 
368
  bits_no = (ROUND(class_get_instance_size (class), sizeof(void*))
 
369
             / sizeof (void*));
 
370
  size = ROUND(bits_no, BITS_PER_WORD) / BITS_PER_WORD;
 
371
  mask = GC_MALLOC_ATOMIC(size * sizeof (int));
 
372
  memset(mask, 0, size * sizeof (int));
 
373
  
 
374
  __objc_gc_type_description_from_type (mask, class_structure_type);
 
375
  class_structure_type = NULL;
 
376
 
 
377
#if DEBUG_OBJC_GC
 
378
  printf ("  mask for '%s', type '%s' (bits %d, mask size %d) is:",
 
379
          class_structure_type ? class_structure_type : "<NULL>",
 
380
          class->name ? class->name : "<NULL>",
 
381
          bits_no, size);
 
382
  {
 
383
    int i;
 
384
    for (i = 0; i < size; i++)
 
385
      printf (" %lx", mask[i]);
 
386
  }
 
387
  puts ("");
 
388
#endif
 
389
 
 
390
  class->gc_object_type = (void*)GC_make_descriptor (mask, bits_no);
 
391
}
 
392
 
 
393
 
 
394
/* Returns YES if type denotes a pointer type, NO otherwise */
 
395
static __inline__ BOOL __objc_ivar_pointer (register const char *type)
 
396
{
 
397
  type = objc_skip_type_qualifiers (type);
 
398
 
 
399
  return (*type == _C_ID
 
400
          || *type == _C_CLASS
 
401
          || *type == _C_SEL
 
402
          || *type == _C_PTR
 
403
          || *type == _C_CHARPTR
 
404
          || *type == _C_ATOM);
 
405
}
 
406
 
 
407
 
 
408
/* Mark the instance variable whose name is given by ivarname as a
 
409
   weak pointer (a pointer hidden to the garbage collector) if
 
410
   gc_invisible is true. If gc_invisible is false it unmarks the
 
411
   instance variable and makes it a normal pointer, visible to the
 
412
   garbage collector.
 
413
 
 
414
   This operation only makes sense on instance variables that are
 
415
   pointers.  */
 
416
void
 
417
class_ivar_set_gcinvisible (Class class, const char* ivarname,
 
418
                            BOOL gc_invisible)
 
419
{
 
420
  int i, ivar_count;
 
421
  struct objc_ivar_list* ivars;
 
422
 
 
423
  if (!class || !ivarname)
 
424
    return;
 
425
 
 
426
  ivars = class->ivars;
 
427
  if (!ivars)
 
428
    return;
 
429
 
 
430
  ivar_count = ivars->ivar_count;
 
431
 
 
432
  for (i = 0; i < ivar_count; i++)
 
433
    {
 
434
      struct objc_ivar *ivar = &(ivars->ivar_list[i]);
 
435
      const char *type;
 
436
 
 
437
      if (!ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
 
438
        continue;
 
439
 
 
440
      assert (ivar->ivar_type);
 
441
      type = ivar->ivar_type;
 
442
 
 
443
      /* Skip the variable name */
 
444
      if (*type == '"')
 
445
        {
 
446
          for (type++; *type++ != '"';)
 
447
            /* do nothing */;
 
448
        }
 
449
 
 
450
      if (*type == _C_GCINVISIBLE)
 
451
        {
 
452
          char *new_type;
 
453
 
 
454
          if (gc_invisible || !__objc_ivar_pointer (type))
 
455
            return;     /* The type of the variable already matches the
 
456
                           requested gc_invisible type */
 
457
 
 
458
          /* The variable is gc_invisible and we have to reverse it */
 
459
          new_type = objc_atomic_malloc (strlen (ivar->ivar_type));
 
460
          strncpy (new_type, ivar->ivar_type,
 
461
                   (size_t)(type - ivar->ivar_type));
 
462
          strcat (new_type, type + 1);
 
463
          ivar->ivar_type = new_type;
 
464
        }
 
465
      else
 
466
        {
 
467
          char *new_type;
 
468
 
 
469
          if (!gc_invisible || !__objc_ivar_pointer (type))
 
470
            return;     /* The type of the variable already matches the
 
471
                           requested gc_invisible type */
 
472
 
 
473
          /* The variable is gc visible and we have to make it gc_invisible */
 
474
          new_type = objc_malloc (strlen (ivar->ivar_type) + 2);
 
475
          strncpy (new_type, ivar->ivar_type,
 
476
                   (size_t)(type - ivar->ivar_type));
 
477
          strcat (new_type, "!");
 
478
          strcat (new_type, type);
 
479
          ivar->ivar_type = new_type;
 
480
        }
 
481
 
 
482
      __objc_generate_gc_type_description (class);
 
483
      return;
 
484
    }
 
485
 
 
486
  /* Search the instance variable in the superclasses */
 
487
  class_ivar_set_gcinvisible (class->super_class, ivarname, gc_invisible);
 
488
}
 
489
 
 
490
BOOL objc_ignore_leaks = YES;
 
491
void (*objc_report_atomic_leak_func)(void *ptr, unsigned size) = NULL;
 
492
void (*objc_report_composite_leak_func)(void *ptr, unsigned size) = NULL;
 
493
 
 
494
void objc_report_atomic_leak(void *ptr, unsigned size) {
 
495
  const unsigned char *t;
 
496
  unsigned char buffer[128];
 
497
 
 
498
  if (objc_ignore_leaks) return;
 
499
  if (objc_report_atomic_leak_func) {
 
500
    objc_report_atomic_leak_func(ptr, size);
 
501
    return;
 
502
  }
 
503
  
 
504
  /*
 
505
  if (object_is_class(ptr))
 
506
    t = "class";
 
507
  else if (object_is_instance(ptr))
 
508
    t = "object";
 
509
  else
 
510
  */
 
511
  t = "unknown";
 
512
 
 
513
  buffer[0] = 0;
 
514
  if (size < 120) {
 
515
    int i;
 
516
    unsigned char c;
 
517
 
 
518
    for (i = 0; i < size; i++) {
 
519
      c = ((unsigned char *)ptr)[i];
 
520
      if (c == '\0') break;
 
521
      if (!((c > 31) && (c < 128)))
 
522
        break;
 
523
    }
 
524
 
 
525
    if (i < size) {
 
526
      if (c == '\0')
 
527
        strcpy(buffer, ptr);
 
528
    }
 
529
  }
 
530
  
 
531
  fprintf(stderr, "LEAK(atomic): %s 0x%08X %d bytes(%s)\n",
 
532
          t ? t : "<NULL>",
 
533
          (unsigned)ptr, size,
 
534
          buffer ? buffer : "<NULL>");
 
535
}
 
536
void objc_report_composite_leak(void *ptr, unsigned size) {
 
537
  const char *t;
 
538
  unsigned char buffer[128];
 
539
 
 
540
  if (objc_ignore_leaks) return;
 
541
  if (objc_report_composite_leak_func) {
 
542
    objc_report_composite_leak_func(ptr, size);
 
543
    return;
 
544
  }
 
545
  
 
546
  /*
 
547
  if (object_is_class(ptr))
 
548
    t = "class";
 
549
  else if (object_is_instance(ptr))
 
550
    t = "object";
 
551
  else
 
552
  */
 
553
  t = "unknown";
 
554
 
 
555
  buffer[0] = 0;
 
556
  if (size < 120) {
 
557
    int i;
 
558
    unsigned char c;
 
559
 
 
560
    for (i = 0; i < size; i++) {
 
561
      c = ((unsigned char *)ptr)[i];
 
562
      if (c == '\0') break;
 
563
      if (!((c > 31) && (c < 128)))
 
564
        break;
 
565
    }
 
566
 
 
567
    if (i < size) {
 
568
      if (c == '\0')
 
569
        strcpy(buffer, ptr);
 
570
    }
 
571
  }
 
572
  
 
573
  fprintf(stderr, "LEAK(composite): %s 0x%08X %d bytes(%s)\n",
 
574
          t ? t : "<NULL>",
 
575
          (unsigned)ptr, size,
 
576
          buffer ? buffer : "<NULL>");
 
577
}
 
578
 
 
579
#else /* !OBJC_WITH_GC */
 
580
 
 
581
void
 
582
__objc_generate_gc_type_description (Class class)
 
583
{
 
584
}
 
585
 
 
586
void class_ivar_set_gcinvisible (Class class,
 
587
                                 const char* ivarname,
 
588
                                 BOOL gc_invisible)
 
589
{
 
590
}
 
591
 
 
592
#endif /* OBJC_WITH_GC */