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