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