In gcc/objc/: 2010-12-08 Nicola Pero <nicola.pero@meta-innovation.com>
[official-gcc.git] / libobjc / gc.c
blobed5effbb437f9071cabcda272ac552c2d6e00a1f
1 /* Basic data types for Objective C.
2 Copyright (C) 1998, 2002, 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
3 Contributed by Ovidiu Predescu.
5 This file is part of GCC.
7 GCC 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 3, or (at your option)
10 any later version.
12 GCC 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.
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.
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/>. */
26 #include "objc-private/common.h"
27 #include "objc/objc.h"
29 #if OBJC_WITH_GC
31 #include "tconfig.h"
32 #include <assert.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include "objc/encoding.h"
37 #include <gc.h>
38 #include <limits.h>
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 #define BITS_PER_WORD (CHAR_BIT * sizeof (word))
45 #include <gc_typed.h>
47 /* The following functions set up in `mask` the corresponding pointers.
48 The offset is incremented with the size of the type. */
50 #define ROUND(V, A) \
51 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
52 __a * ((__v+__a - 1)/__a); })
54 #define SET_BIT_FOR_OFFSET(mask, offset) \
55 GC_set_bit (mask, offset / sizeof (void *))
57 /* Some prototypes */
58 static void
59 __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset);
60 static void
61 __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
64 static void
65 __objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
67 int i, len = atoi (type + 1);
69 while (isdigit (*++type))
70 /* do nothing */; /* skip the size of the array */
72 switch (*type) {
73 case _C_ARY_B:
74 for (i = 0; i < len; i++)
75 __objc_gc_setup_array (mask, type, offset);
76 break;
78 case _C_STRUCT_B:
79 for (i = 0; i < len; i++)
80 __objc_gc_setup_struct (mask, type, offset);
81 break;
83 case _C_UNION_B:
84 for (i = 0; i < len; i++)
85 __objc_gc_setup_union (mask, type, offset);
86 break;
88 default:
89 break;
93 static void
94 __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset)
96 struct objc_struct_layout layout;
97 unsigned int position;
98 const char *mtype;
100 objc_layout_structure (type, &layout);
102 while (objc_layout_structure_next_member (&layout))
104 BOOL gc_invisible = NO;
106 objc_layout_structure_get_info (&layout, &position, NULL, &mtype);
108 /* Skip the variable name */
109 if (*mtype == '"')
111 for (mtype++; *mtype++ != '"';)
112 /* do nothing */;
115 if (*mtype == _C_GCINVISIBLE)
117 gc_invisible = YES;
118 mtype++;
121 /* Add to position the offset of this structure */
122 position += offset;
124 switch (*mtype) {
125 case _C_ID:
126 case _C_CLASS:
127 case _C_SEL:
128 case _C_PTR:
129 case _C_CHARPTR:
130 case _C_ATOM:
131 if (! gc_invisible)
132 SET_BIT_FOR_OFFSET (mask, position);
133 break;
135 case _C_ARY_B:
136 __objc_gc_setup_array (mask, mtype, position);
137 break;
139 case _C_STRUCT_B:
140 __objc_gc_setup_struct (mask, mtype, position);
141 break;
143 case _C_UNION_B:
144 __objc_gc_setup_union (mask, mtype, position);
145 break;
147 default:
148 break;
153 static void
154 __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
156 /* Sub-optimal, quick implementation: assume the union is made of
157 pointers, set up the mask accordingly. */
159 int i, size, align;
161 /* Skip the variable name */
162 if (*type == '"')
164 for (type++; *type++ != '"';)
165 /* do nothing */;
168 size = objc_sizeof_type (type);
169 align = objc_alignof_type (type);
171 offset = ROUND (offset, align);
172 for (i = 0; i < size; i += sizeof (void *))
174 SET_BIT_FOR_OFFSET (mask, offset);
175 offset += sizeof (void *);
180 /* Iterates over the types in the structure that represents the class
181 encoding and sets the bits in mask according to each ivar type. */
182 static void
183 __objc_gc_type_description_from_type (GC_bitmap mask, const char *type)
185 struct objc_struct_layout layout;
186 unsigned int offset, align;
187 const char *ivar_type;
189 objc_layout_structure (type, &layout);
191 while (objc_layout_structure_next_member (&layout))
193 BOOL gc_invisible = NO;
195 objc_layout_structure_get_info (&layout, &offset, &align, &ivar_type);
197 /* Skip the variable name */
198 if (*ivar_type == '"')
200 for (ivar_type++; *ivar_type++ != '"';)
201 /* do nothing */;
204 if (*ivar_type == _C_GCINVISIBLE)
206 gc_invisible = YES;
207 ivar_type++;
210 switch (*ivar_type) {
211 case _C_ID:
212 case _C_CLASS:
213 case _C_SEL:
214 case _C_PTR:
215 case _C_CHARPTR:
216 if (! gc_invisible)
217 SET_BIT_FOR_OFFSET (mask, offset);
218 break;
220 case _C_ARY_B:
221 __objc_gc_setup_array (mask, ivar_type, offset);
222 break;
224 case _C_STRUCT_B:
225 __objc_gc_setup_struct (mask, ivar_type, offset);
226 break;
228 case _C_UNION_B:
229 __objc_gc_setup_union (mask, ivar_type, offset);
230 break;
232 default:
233 break;
238 /* Computes in *type the full type encoding of this class including
239 its super classes. '*size' gives the total number of bytes allocated
240 into *type, '*current' the number of bytes used so far by the
241 encoding. */
242 static void
243 __objc_class_structure_encoding (Class class, char **type, int *size,
244 int *current)
246 int i, ivar_count;
247 struct objc_ivar_list *ivars;
249 if (! class)
251 strcat (*type, "{");
252 (*current)++;
253 return;
256 /* Add the type encodings of the super classes */
257 __objc_class_structure_encoding (class->super_class, type, size, current);
259 ivars = class->ivars;
260 if (! ivars)
261 return;
263 ivar_count = ivars->ivar_count;
265 for (i = 0; i < ivar_count; i++)
267 struct objc_ivar *ivar = &(ivars->ivar_list[i]);
268 const char *ivar_type = ivar->ivar_type;
269 int len = strlen (ivar_type);
271 if (*current + len + 1 >= *size)
273 /* Increase the size of the encoding string so that it
274 contains this ivar's type. */
275 *size = ROUND (*current + len + 1, 10);
276 *type = objc_realloc (*type, *size);
278 strcat (*type + *current, ivar_type);
279 *current += len;
284 /* Allocates the memory that will hold the type description for class
285 and calls the __objc_class_structure_encoding that generates this
286 value. */
287 void
288 __objc_generate_gc_type_description (Class class)
290 GC_bitmap mask;
291 int bits_no, size;
292 int type_size = 10, current;
293 char *class_structure_type;
295 if (! CLS_ISCLASS (class))
296 return;
298 /* We have to create a mask in which each bit counts for a pointer member.
299 We take into consideration all the non-pointer instance variables and we
300 round them up to the alignment. */
302 /* The number of bits in the mask is the size of an instance in bytes divided
303 by the size of a pointer. */
304 bits_no = (ROUND (class_get_instance_size (class), sizeof (void *))
305 / sizeof (void *));
306 size = ROUND (bits_no, BITS_PER_WORD) / BITS_PER_WORD;
307 mask = objc_atomic_malloc (size * sizeof (int));
308 memset (mask, 0, size * sizeof (int));
310 class_structure_type = objc_atomic_malloc (type_size);
311 *class_structure_type = current = 0;
312 __objc_class_structure_encoding (class, &class_structure_type,
313 &type_size, &current);
314 if (current + 1 == type_size)
315 class_structure_type = objc_realloc (class_structure_type, ++type_size);
316 strcat (class_structure_type + current, "}");
317 #ifdef DEBUG
318 printf ("type description for '%s' is %s\n", class->name, class_structure_type);
319 #endif
321 __objc_gc_type_description_from_type (mask, class_structure_type);
322 objc_free (class_structure_type);
324 #ifdef DEBUG
325 printf (" mask for '%s', type '%s' (bits %d, mask size %d) is:",
326 class_structure_type, class->name, bits_no, size);
328 int i;
329 for (i = 0; i < size; i++)
330 printf (" %lx", mask[i]);
332 puts ("");
333 #endif
335 class->gc_object_type = (void *) GC_make_descriptor (mask, bits_no);
339 /* Returns YES if type denotes a pointer type, NO otherwise */
340 static inline BOOL
341 __objc_ivar_pointer (const char *type)
343 type = objc_skip_type_qualifiers (type);
345 return (*type == _C_ID
346 || *type == _C_CLASS
347 || *type == _C_SEL
348 || *type == _C_PTR
349 || *type == _C_CHARPTR
350 || *type == _C_ATOM);
354 /* Mark the instance variable whose name is given by ivarname as a
355 weak pointer (a pointer hidden to the garbage collector) if
356 gc_invisible is true. If gc_invisible is false it unmarks the
357 instance variable and makes it a normal pointer, visible to the
358 garbage collector.
360 This operation only makes sense on instance variables that are
361 pointers. */
362 void
363 class_ivar_set_gcinvisible (Class class, const char *ivarname,
364 BOOL gc_invisible)
366 int i, ivar_count;
367 struct objc_ivar_list *ivars;
369 if (! class || ! ivarname)
370 return;
372 ivars = class->ivars;
373 if (! ivars)
374 return;
376 ivar_count = ivars->ivar_count;
378 for (i = 0; i < ivar_count; i++)
380 struct objc_ivar *ivar = &(ivars->ivar_list[i]);
381 const char *type;
383 if (! ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
384 continue;
386 assert (ivar->ivar_type);
387 type = ivar->ivar_type;
389 /* Skip the variable name */
390 if (*type == '"')
392 for (type++; *type++ != '"';)
393 /* do nothing */;
396 if (*type == _C_GCINVISIBLE)
398 char *new_type;
399 size_t len;
401 if (gc_invisible || ! __objc_ivar_pointer (type))
402 return; /* The type of the variable already matches the
403 requested gc_invisible type */
405 /* The variable is gc_invisible so we make it gc visible. */
406 new_type = objc_atomic_malloc (strlen(ivar->ivar_type));
407 len = (type - ivar->ivar_type);
408 memcpy (new_type, ivar->ivar_type, len);
409 new_type[len] = 0;
410 strcat (new_type, type + 1);
411 ivar->ivar_type = new_type;
413 else
415 char *new_type;
416 size_t len;
418 if (! gc_invisible || ! __objc_ivar_pointer (type))
419 return; /* The type of the variable already matches the
420 requested gc_invisible type */
422 /* The variable is gc visible so we make it gc_invisible. */
423 new_type = objc_malloc (strlen(ivar->ivar_type) + 2);
424 len = (type - ivar->ivar_type);
425 memcpy (new_type, ivar->ivar_type, len);
426 new_type[len] = 0;
427 strcat (new_type, "!");
428 strcat (new_type, type);
429 ivar->ivar_type = new_type;
432 __objc_generate_gc_type_description (class);
433 return;
436 /* Search the instance variable in the superclasses */
437 class_ivar_set_gcinvisible (class->super_class, ivarname, gc_invisible);
440 #else /* !OBJC_WITH_GC */
442 void
443 __objc_generate_gc_type_description (Class class __attribute__ ((__unused__)))
447 void class_ivar_set_gcinvisible (Class class __attribute__ ((__unused__)),
448 const char *ivarname __attribute__ ((__unused__)),
449 BOOL gc_invisible __attribute__ ((__unused__)))
453 #endif /* OBJC_WITH_GC */