1 /*
2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
4 * Copyright 1996 Silicon Graphics. All rights reserved.
5 *
6 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
7 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
8 *
9 * Permission is hereby granted to use or copy this program
10 * for any purpose, provided the above notices are retained on all copies.
11 * Permission to modify the code and to distribute modified code is granted,
12 * provided the above notices are retained, and a notice that the code was
13 * modified is included with the above copyright notice.
14 */
15 16 /*
17 * Some simple primitives for allocation with explicit type information.
18 * Facilities for dynamic type inference may be added later.
19 * Should be used only for extremely performance critical applications,
20 * or if conservative collector leakage is otherwise a problem (unlikely).
21 * Note that this is implemented completely separately from the rest
22 * of the collector, and is not linked in unless referenced.
23 * This does not currently support `GC_DEBUG` in any interesting way.
24 *
25 * Note for cris and m68k architectures (and for bcc and wcc compilers):
26 * this API expects all pointers in the type (`T`) are aligned by the size
27 * of a pointer (which might differ from `ALIGNMENT`).
28 */
29 30 #ifndef GC_TYPED_H
31 #define GC_TYPED_H
32 33 #ifndef GC_H
34 # include "gc.h"
35 #endif
36 37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 41 /** The size of `GC_word` (not a pointer) type in bits. */
42 #define GC_WORDSZ (8 * sizeof(GC_word))
43 44 /** The size of a type `t` in pointers. The value is rounded down. */
45 #define GC_SIZEOF_IN_PTRS(t) (sizeof(t) / sizeof(void *))
46 47 /** The offset of a field in pointers. */
48 #define GC_OFFSETOF_IN_PTRS(t, f) (offsetof(t, f) / sizeof(void *))
49 50 /**
51 * The bitmap type. The least significant bit of the first `GC_word` is one
52 * if the first "pointer-sized" word in the object may be a pointer.
53 */
54 typedef GC_word *GC_bitmap;
55 56 /**
57 * The number of elements (of `GC_word` type) of a bitmap array to
58 * create for a given type `t`. The bitmap is intended to be passed to
59 * `GC_make_descriptor()`.
60 */
61 #define GC_BITMAP_SIZE(t) ((GC_SIZEOF_IN_PTRS(t) + GC_WORDSZ - 1) / GC_WORDSZ)
62 63 /**
64 * The setter and getter of the bitmap. The `bm` argument should be of
65 * `GC_bitmap` type; `i` argument should be of some `unsigned` type and
66 * should not have side effects.
67 */
68 #define GC_set_bit(bm, i) \
69 ((bm)[(i) / GC_WORDSZ] |= (GC_word)1 << ((i) % GC_WORDSZ))
70 #define GC_get_bit(bm, i) (((bm)[(i) / GC_WORDSZ] >> ((i) % GC_WORDSZ)) & 1)
71 72 typedef GC_word GC_descr;
73 74 /**
75 * Return a type descriptor for the object whose layout is described
76 * by the first argument. The least significant bit of the first
77 * `GC_word` is one if the first "pointer-sized" word in the object may
78 * be a pointer. The second argument (`number_of_bits_in_bitmap`)
79 * specifies the number of meaningful bits in the bitmap.
80 * The actual object may be larger (but not smaller); any additional
81 * "pointer-sized" words in the object are assumed not to contain
82 * pointers. Returns a conservative approximation in the (unlikely)
83 * case of insufficient memory to build the descriptor. Calls to
84 * `GC_make_descriptor()` may consume some amount of a finite resource.
85 * This is intended to be called once per a type, not once per an
86 * allocation.
87 *
88 * It is possible to generate a descriptor for a client type `T` with
89 * aligned pointer fields `f1`, `f2`, ... as follows:
90 * ```
91 * GC_descr t_descr;
92 * {
93 * GC_word bm[GC_BITMAP_SIZE(T)] = { 0 };
94 * GC_set_bit(bm, GC_OFFSETOF_IN_PTRS(T, f1));
95 * GC_set_bit(bm, GC_OFFSETOF_IN_PTRS(T, f2));
96 * ...
97 * t_descr = GC_make_descriptor(bm, GC_SIZEOF_IN_PTRS(T));
98 * }
99 * ```
100 */
101 GC_API GC_descr GC_CALL
102 GC_make_descriptor(const GC_word * /* `GC_bitmap` `bm` */,
103 size_t /* `number_of_bits_in_bitmap` */);
104 105 /**
106 * Allocate an object whose layout is described by `d`. The size
107 * (`size_in_bytes`) may *not* be less than the number of meaningful
108 * bits in the bitmap of `d` multiplied by the size of a pointer.
109 * The returned object is cleared. The returned object may *not* be
110 * passed to `GC_realloc()`.
111 */
112 GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
113 GC_malloc_explicitly_typed(size_t /* `size_in_bytes` */,
114 GC_descr /* `d` */);
115 116 /** The ignore-off-page variant of `GC_malloc_explicitly_typed()`. */
117 GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
118 GC_malloc_explicitly_typed_ignore_off_page(size_t /* `size_in_bytes` */,
119 GC_descr /* `d` */);
120 121 /**
122 * Allocate an array of `nelements` elements, each of the given size
123 * (`element_size_in_bytes`), and with the given descriptor (`d`).
124 * The element size must be a multiple of the byte alignment required
125 * for pointers. (E.g. on a 32-bit machine with 16-bit aligned
126 * pointers, `element_size_in_bytes` must be a multiple of 2.)
127 * The element size may *not* be less than the number of meaningful
128 * bits in the bitmap of `d` multiplied by the size of a pointer.
129 * The returned object is cleared.
130 */
131 GC_API GC_ATTR_MALLOC GC_ATTR_CALLOC_SIZE(1, 2) void *GC_CALL
132 GC_calloc_explicitly_typed(size_t /* `nelements` */,
133 size_t /* `element_size_in_bytes` */,
134 GC_descr /* d */);
135 136 #define GC_CALLOC_TYPED_DESCR_PTRS 1
137 #define GC_CALLOC_TYPED_DESCR_WORDS 8 /*< includes space for pointers */
138 139 #ifdef GC_BUILD
140 struct GC_calloc_typed_descr_s;
141 # define GC_calloc_typed_descr_s GC_calloc_typed_descr_opaque_s
142 #endif
143 144 struct GC_calloc_typed_descr_s {
145 GC_uintptr_t opaque_p[GC_CALLOC_TYPED_DESCR_PTRS];
146 GC_word opaque[GC_CALLOC_TYPED_DESCR_WORDS - GC_CALLOC_TYPED_DESCR_PTRS];
147 };
148 #undef GC_calloc_typed_descr_s
149 150 /**
151 * This is same as `GC_calloc_explicitly_typed` but more optimal in
152 * terms of the performance and memory usage if the client needs to
153 * allocate multiple typed object arrays with the same layout and
154 * number of elements. The client should call it to be prepared for
155 * the subsequent allocations by `GC_calloc_do_explicitly_typed()`, one
156 * or many. The result of the preparation is stored to `*pctd`, even
157 * in case of a failure. The prepared structure could be just dropped
158 * when no longer needed. Returns 0 on failure, 1 on success; the
159 * result could be ignored (as it is also stored to `*pctd` and checked
160 * later by `GC_calloc_do_explicitly_typed()`).
161 */
162 GC_API int GC_CALL GC_calloc_prepare_explicitly_typed(
163 struct GC_calloc_typed_descr_s * /* `pctd` */, size_t /* `sizeof_ctd` */,
164 size_t /* `nelements` */, size_t /* `element_size_in_bytes` */, GC_descr);
165 166 /** The actual object allocation for the prepared description. */
167 GC_API GC_ATTR_MALLOC void *GC_CALL GC_calloc_do_explicitly_typed(
168 const struct GC_calloc_typed_descr_s * /* `pctd` */,
169 size_t /* `sizeof_ctd` */);
170 171 #ifdef GC_DEBUG
172 # define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) ((void)(d), GC_MALLOC(bytes))
173 # define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \
174 GC_MALLOC_EXPLICITLY_TYPED(bytes, d)
175 # define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
176 ((void)(d), GC_MALLOC((n) * (bytes)))
177 #else
178 # define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \
179 GC_malloc_explicitly_typed(bytes, d)
180 # define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \
181 GC_malloc_explicitly_typed_ignore_off_page(bytes, d)
182 # define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
183 GC_calloc_explicitly_typed(n, bytes, d)
184 #endif
185 186 /* Deprecated. Use `GC_SIZEOF_IN_PTRS()` instead. */
187 #define GC_WORD_LEN(t) GC_SIZEOF_IN_PTRS(t)
188 189 /* Deprecated. Use `GC_OFFSETOF_IN_PTRS()` instead. */
190 #define GC_WORD_OFFSET(t, f) GC_OFFSETOF_IN_PTRS(t, f)
191 192 #ifdef __cplusplus
193 } /* extern "C" */
194 #endif
195 196 #endif /* GC_TYPED_H */
197