OSDN Git Service

PR ada/60703
[pf3gnuchains/gcc-fork.git] / libobjc / gc.c
1 /* Basic data types for Objective C.
2    Copyright (C) 1998, 2002, 2004, 2005, 2006, 2009, 2010
3    Free Software Foundation, Inc.
4    Contributed by Ovidiu Predescu.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
21
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 <http://www.gnu.org/licenses/>.  */
26
27 #include "objc-private/common.h"
28 #include "objc/objc.h"
29
30 #if OBJC_WITH_GC
31
32 #include "tconfig.h"
33 #include <assert.h>
34 #include <ctype.h> /* For isdigit.  */
35 #include <string.h>
36 #include <stdlib.h>
37 #include "objc/runtime.h"
38 #include "objc-private/module-abi-8.h"
39
40 #include <gc.h>
41 #include <limits.h>
42
43 /* gc_typed.h uses the following but doesn't declare them */
44 typedef GC_word word;
45 typedef GC_signed_word signed_word;
46 #define BITS_PER_WORD (CHAR_BIT * sizeof (word))
47
48 #include <gc_typed.h>
49
50 /* The following functions set up in `mask` the corresponding pointers.
51    The offset is incremented with the size of the type.  */
52
53 #define ROUND(V, A) \
54   ({ typeof (V) __v = (V); typeof (A) __a = (A); \
55      __a * ((__v+__a - 1)/__a); })
56
57 #define SET_BIT_FOR_OFFSET(mask, offset) \
58   GC_set_bit (mask, offset / sizeof (void *))
59
60 /* Some prototypes */
61 static void
62 __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset);
63 static void
64 __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
65
66
67 static void
68 __objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
69 {
70   int i, len = atoi (type + 1);
71
72   while (isdigit (*++type))
73     /* do nothing */;           /* skip the size of the array */
74
75   switch (*type) {
76   case _C_ARY_B:
77     for (i = 0; i < len; i++)
78       __objc_gc_setup_array (mask, type, offset);
79     break;
80
81   case _C_STRUCT_B:
82     for (i = 0; i < len; i++)
83       __objc_gc_setup_struct (mask, type, offset);
84     break;
85
86   case _C_UNION_B:
87     for (i = 0; i < len; i++)
88       __objc_gc_setup_union (mask, type, offset);
89     break;
90
91   default:
92     break;
93   }
94 }
95
96 static void
97 __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset)
98 {
99   struct objc_struct_layout layout;
100   unsigned int position;
101   const char *mtype;
102
103   objc_layout_structure (type, &layout);
104
105   while (objc_layout_structure_next_member (&layout))
106     {
107       BOOL gc_invisible = NO;
108
109       objc_layout_structure_get_info (&layout, &position, NULL, &mtype);
110
111       /* Skip the variable name */
112       if (*mtype == '"')
113         {
114           for (mtype++; *mtype++ != '"';)
115             /* do nothing */;
116         }
117
118       if (*mtype == _C_GCINVISIBLE)
119         {
120           gc_invisible = YES;
121           mtype++;
122         }
123
124       /* Add to position the offset of this structure */
125       position += offset;
126
127       switch (*mtype) {
128       case _C_ID:
129       case _C_CLASS:
130       case _C_SEL:
131       case _C_PTR:
132       case _C_CHARPTR:
133       case _C_ATOM:
134         if (! gc_invisible)
135           SET_BIT_FOR_OFFSET (mask, position);
136         break;
137
138       case _C_ARY_B:
139         __objc_gc_setup_array (mask, mtype, position);
140         break;
141
142       case _C_STRUCT_B:
143         __objc_gc_setup_struct (mask, mtype, position);
144         break;
145
146       case _C_UNION_B:
147         __objc_gc_setup_union (mask, mtype, position);
148         break;
149
150       default:
151         break;
152       }
153     }
154 }
155
156 static void
157 __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
158 {
159   /* Sub-optimal, quick implementation: assume the union is made of
160      pointers, set up the mask accordingly. */
161
162   int i, size, align;
163
164   /* Skip the variable name */
165   if (*type == '"')
166     {
167       for (type++; *type++ != '"';)
168         /* do nothing */;
169     }
170
171   size = objc_sizeof_type (type);
172   align = objc_alignof_type (type);
173
174   offset = ROUND (offset, align);
175   for (i = 0; i < size; i += sizeof (void *))
176     {
177       SET_BIT_FOR_OFFSET (mask, offset);
178       offset += sizeof (void *);
179     }
180 }
181
182
183 /* Iterates over the types in the structure that represents the class
184    encoding and sets the bits in mask according to each ivar type.  */
185 static void
186 __objc_gc_type_description_from_type (GC_bitmap mask, const char *type)
187 {
188   struct objc_struct_layout layout;
189   unsigned int offset, align;
190   const char *ivar_type;
191
192   objc_layout_structure (type, &layout);
193
194   while (objc_layout_structure_next_member (&layout))
195     {
196       BOOL gc_invisible = NO;
197
198       objc_layout_structure_get_info (&layout, &offset, &align, &ivar_type);
199
200       /* Skip the variable name */
201       if (*ivar_type == '"')
202         {
203           for (ivar_type++; *ivar_type++ != '"';)
204             /* do nothing */;
205         }
206
207       if (*ivar_type == _C_GCINVISIBLE)
208         {
209           gc_invisible = YES;
210           ivar_type++;
211         }
212
213       switch (*ivar_type) {
214       case _C_ID:
215       case _C_CLASS:
216       case _C_SEL:
217       case _C_PTR:
218       case _C_CHARPTR:
219         if (! gc_invisible)
220           SET_BIT_FOR_OFFSET (mask, offset);
221         break;
222
223       case _C_ARY_B:
224         __objc_gc_setup_array (mask, ivar_type, offset);
225         break;
226
227       case _C_STRUCT_B:
228         __objc_gc_setup_struct (mask, ivar_type, offset);
229         break;
230
231       case _C_UNION_B:
232         __objc_gc_setup_union (mask, ivar_type, offset);
233         break;
234
235       default:
236         break;
237       }
238     }
239 }
240
241 /* Computes in *type the full type encoding of this class including
242    its super classes. '*size' gives the total number of bytes allocated
243    into *type, '*current' the number of bytes used so far by the
244    encoding. */
245 static void
246 __objc_class_structure_encoding (Class class, char **type, int *size,
247                                  int *current)
248 {
249   int i, ivar_count;
250   struct objc_ivar_list *ivars;
251
252   if (! class)
253     {
254       strcat (*type, "{");
255       (*current)++;
256       return;
257     }
258
259   /* Add the type encodings of the super classes */
260   __objc_class_structure_encoding (class->super_class, type, size, current);
261
262   ivars = class->ivars;
263   if (! ivars)
264     return;
265
266   ivar_count = ivars->ivar_count;
267
268   for (i = 0; i < ivar_count; i++)
269     {
270       struct objc_ivar *ivar = &(ivars->ivar_list[i]);
271       const char *ivar_type = ivar->ivar_type;
272       int len = strlen (ivar_type);
273
274       if (*current + len + 1 >= *size)
275         {
276           /* Increase the size of the encoding string so that it
277              contains this ivar's type. */
278           *size = ROUND (*current + len + 1, 10);
279           *type = objc_realloc (*type, *size);
280         }
281       strcat (*type + *current, ivar_type);
282       *current += len;
283     }
284 }
285
286
287 /* Allocates the memory that will hold the type description for class
288    and calls the __objc_class_structure_encoding that generates this
289    value. */
290 void
291 __objc_generate_gc_type_description (Class class)
292 {
293   GC_bitmap mask;
294   int bits_no, size;
295   int type_size = 10, current;
296   char *class_structure_type;
297
298   if (! CLS_ISCLASS (class))
299     return;
300
301   /* We have to create a mask in which each bit counts for a pointer member.
302      We take into consideration all the non-pointer instance variables and we
303      round them up to the alignment. */
304
305   /* The number of bits in the mask is the size of an instance in bytes divided
306      by the size of a pointer. */
307   bits_no = (ROUND (class_getInstanceSize (class), sizeof (void *))
308              / sizeof (void *));
309   size = ROUND (bits_no, BITS_PER_WORD) / BITS_PER_WORD;
310   mask = objc_atomic_malloc (size * sizeof (int));
311   memset (mask, 0, size * sizeof (int));
312
313   class_structure_type = objc_atomic_malloc (type_size);
314   *class_structure_type = current = 0;
315   __objc_class_structure_encoding (class, &class_structure_type,
316                                    &type_size, &current);
317   if (current + 1 == type_size)
318     class_structure_type = objc_realloc (class_structure_type, ++type_size);
319   strcat (class_structure_type + current, "}");
320 #ifdef DEBUG
321   printf ("type description for '%s' is %s\n", class->name, class_structure_type);
322 #endif
323   
324   __objc_gc_type_description_from_type (mask, class_structure_type);
325   objc_free (class_structure_type);
326
327 #ifdef DEBUG
328   printf ("  mask for '%s', type '%s' (bits %d, mask size %d) is:",
329           class_structure_type, class->name, bits_no, size);
330   {
331     int i;
332     for (i = 0; i < size; i++)
333       printf (" %lx", mask[i]);
334   }
335   puts ("");
336 #endif
337
338   class->gc_object_type = (void *) GC_make_descriptor (mask, bits_no);
339 }
340
341
342 /* Returns YES if type denotes a pointer type, NO otherwise */
343 static inline BOOL
344 __objc_ivar_pointer (const char *type)
345 {
346   type = objc_skip_type_qualifiers (type);
347
348   return (*type == _C_ID
349           || *type == _C_CLASS
350           || *type == _C_SEL
351           || *type == _C_PTR
352           || *type == _C_CHARPTR
353           || *type == _C_ATOM);
354 }
355
356
357 /* Mark the instance variable whose name is given by ivarname as a
358    weak pointer (a pointer hidden to the garbage collector) if
359    gc_invisible is true. If gc_invisible is false it unmarks the
360    instance variable and makes it a normal pointer, visible to the
361    garbage collector.
362
363    This operation only makes sense on instance variables that are
364    pointers.  */
365 void
366 class_ivar_set_gcinvisible (Class class, const char *ivarname,
367                             BOOL gc_invisible)
368 {
369   int i, ivar_count;
370   struct objc_ivar_list *ivars;
371
372   if (! class || ! ivarname)
373     return;
374
375   ivars = class->ivars;
376   if (! ivars)
377     return;
378
379   ivar_count = ivars->ivar_count;
380
381   for (i = 0; i < ivar_count; i++)
382     {
383       struct objc_ivar *ivar = &(ivars->ivar_list[i]);
384       const char *type;
385
386       if (! ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
387         continue;
388
389       assert (ivar->ivar_type);
390       type = ivar->ivar_type;
391
392       /* Skip the variable name */
393       if (*type == '"')
394         {
395           for (type++; *type++ != '"';)
396             /* do nothing */;
397         }
398
399       if (*type == _C_GCINVISIBLE)
400         {
401           char *new_type;
402           size_t len;
403
404           if (gc_invisible || ! __objc_ivar_pointer (type))
405             return;     /* The type of the variable already matches the
406                            requested gc_invisible type */
407
408           /* The variable is gc_invisible so we make it gc visible.  */
409           new_type = objc_atomic_malloc (strlen(ivar->ivar_type));
410           len = (type - ivar->ivar_type);
411           memcpy (new_type, ivar->ivar_type, len);
412           new_type[len] = 0;
413           strcat (new_type, type + 1);
414           ivar->ivar_type = new_type;
415         }
416       else
417         {
418           char *new_type;
419           size_t len;
420
421           if (! gc_invisible || ! __objc_ivar_pointer (type))
422             return;     /* The type of the variable already matches the
423                            requested gc_invisible type */
424
425           /* The variable is gc visible so we make it gc_invisible.  */
426           new_type = objc_malloc (strlen(ivar->ivar_type) + 2);
427
428           /* Copy the variable name.  */
429           len = (type - ivar->ivar_type);
430           memcpy (new_type, ivar->ivar_type, len);
431           /* Add '!'.  */
432           new_type[len++] = _C_GCINVISIBLE;
433           /* Copy the original types.  */
434           strcpy (new_type + len, type);
435
436           ivar->ivar_type = new_type;
437         }
438
439       __objc_generate_gc_type_description (class);
440       return;
441     }
442
443   /* Search the instance variable in the superclasses */
444   class_ivar_set_gcinvisible (class->super_class, ivarname, gc_invisible);
445 }
446
447 #else /* !OBJC_WITH_GC */
448
449 void
450 __objc_generate_gc_type_description (Class class __attribute__ ((__unused__)))
451 {
452 }
453
454 void class_ivar_set_gcinvisible (Class class __attribute__ ((__unused__)),
455                                  const char *ivarname __attribute__ ((__unused__)),
456                                  BOOL gc_invisible __attribute__ ((__unused__)))
457 {
458 }
459
460 #endif /* OBJC_WITH_GC */