2001-01-25 Richard Henderson <rth@redhat.com>
[official-gcc.git] / boehm-gc / gc_alloc.h
blob1f1d54aff95608531e53fb5f30bf5d1a1da18130
1 /*
2 * Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved.
4 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
7 * Permission is hereby granted to use or copy this program
8 * for any purpose, provided the above notices are retained on all copies.
9 * Permission to modify the code and to distribute modified code is granted,
10 * provided the above notices are retained, and a notice that the code was
11 * modified is included with the above copyright notice.
15 // This is a C++ header file that is intended to replace the SGI STL
16 // alloc.h. This assumes SGI STL version < 3.0.
18 // This assumes the collector has been compiled with -DATOMIC_UNCOLLECTABLE
19 // and -DALL_INTERIOR_POINTERS. We also recommend
20 // -DREDIRECT_MALLOC=GC_uncollectable_malloc.
22 // Some of this could be faster in the explicit deallocation case. In particular,
23 // we spend too much time clearing objects on the free lists. That could be avoided.
25 // This uses template classes with static members, and hence does not work
26 // with g++ 2.7.2 and earlier.
29 #include "gc.h"
31 #ifndef GC_ALLOC_H
33 #define GC_ALLOC_H
34 #define __ALLOC_H // Prevent inclusion of the default version. Ugly.
35 #define __SGI_STL_ALLOC_H
36 #define __SGI_STL_INTERNAL_ALLOC_H
38 #ifndef __ALLOC
39 # define __ALLOC alloc
40 #endif
42 #include <stddef.h>
43 #include <string.h>
45 // The following is just replicated from the conventional SGI alloc.h:
47 template<class T, class alloc>
48 class simple_alloc {
50 public:
51 static T *allocate(size_t n)
52 { return 0 == n? 0 : (T*) alloc::allocate(n * sizeof (T)); }
53 static T *allocate(void)
54 { return (T*) alloc::allocate(sizeof (T)); }
55 static void deallocate(T *p, size_t n)
56 { if (0 != n) alloc::deallocate(p, n * sizeof (T)); }
57 static void deallocate(T *p)
58 { alloc::deallocate(p, sizeof (T)); }
61 #include "gc.h"
63 // The following need to match collector data structures.
64 // We can't include gc_priv.h, since that pulls in way too much stuff.
65 // This should eventually be factored out into another include file.
67 extern "C" {
68 extern void ** const GC_objfreelist_ptr;
69 extern void ** const GC_aobjfreelist_ptr;
70 extern void ** const GC_uobjfreelist_ptr;
71 extern void ** const GC_auobjfreelist_ptr;
73 extern void GC_incr_words_allocd(size_t words);
74 extern void GC_incr_mem_freed(size_t words);
76 extern char * GC_generic_malloc_words_small(size_t word, int kind);
79 // Object kinds; must match PTRFREE, NORMAL, UNCOLLECTABLE, and
80 // AUNCOLLECTABLE in gc_priv.h.
82 enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
83 GC_AUNCOLLECTABLE = 3 };
85 enum { GC_max_fast_bytes = 255 };
87 enum { GC_bytes_per_word = sizeof(char *) };
89 enum { GC_byte_alignment = 8 };
91 enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
93 inline void * &GC_obj_link(void * p)
94 { return *(void **)p; }
96 // Compute a number of words >= n+1 bytes.
97 // The +1 allows for pointers one past the end.
98 inline size_t GC_round_up(size_t n)
100 return ((n + GC_byte_alignment)/GC_byte_alignment)*GC_word_alignment;
103 // The same but don't allow for extra byte.
104 inline size_t GC_round_up_uncollectable(size_t n)
106 return ((n + GC_byte_alignment - 1)/GC_byte_alignment)*GC_word_alignment;
109 template <int dummy>
110 class GC_aux_template {
111 public:
112 // File local count of allocated words. Occasionally this is
113 // added into the global count. A separate count is necessary since the
114 // real one must be updated with a procedure call.
115 static size_t GC_words_recently_allocd;
117 // Same for uncollectable mmory. Not yet reflected in either
118 // GC_words_recently_allocd or GC_non_gc_bytes.
119 static size_t GC_uncollectable_words_recently_allocd;
121 // Similar counter for explicitly deallocated memory.
122 static size_t GC_mem_recently_freed;
124 // Again for uncollectable memory.
125 static size_t GC_uncollectable_mem_recently_freed;
127 static void * GC_out_of_line_malloc(size_t nwords, int kind);
130 template <int dummy>
131 size_t GC_aux_template<dummy>::GC_words_recently_allocd = 0;
133 template <int dummy>
134 size_t GC_aux_template<dummy>::GC_uncollectable_words_recently_allocd = 0;
136 template <int dummy>
137 size_t GC_aux_template<dummy>::GC_mem_recently_freed = 0;
139 template <int dummy>
140 size_t GC_aux_template<dummy>::GC_uncollectable_mem_recently_freed = 0;
142 template <int dummy>
143 void * GC_aux_template<dummy>::GC_out_of_line_malloc(size_t nwords, int kind)
145 GC_words_recently_allocd += GC_uncollectable_words_recently_allocd;
146 GC_non_gc_bytes +=
147 GC_bytes_per_word * GC_uncollectable_words_recently_allocd;
148 GC_uncollectable_words_recently_allocd = 0;
150 GC_mem_recently_freed += GC_uncollectable_mem_recently_freed;
151 GC_non_gc_bytes -=
152 GC_bytes_per_word * GC_uncollectable_mem_recently_freed;
153 GC_uncollectable_mem_recently_freed = 0;
155 GC_incr_words_allocd(GC_words_recently_allocd);
156 GC_words_recently_allocd = 0;
158 GC_incr_mem_freed(GC_mem_recently_freed);
159 GC_mem_recently_freed = 0;
161 return GC_generic_malloc_words_small(nwords, kind);
164 typedef GC_aux_template<0> GC_aux;
166 // A fast, single-threaded, garbage-collected allocator
167 // We assume the first word will be immediately overwritten.
168 // In this version, deallocation is not a noop, and explicit
169 // deallocation is likely to help performance.
170 template <int dummy>
171 class single_client_gc_alloc_template {
172 public:
173 static void * allocate(size_t n)
175 size_t nwords = GC_round_up(n);
176 void ** flh;
177 void * op;
179 if (n > GC_max_fast_bytes) return GC_malloc(n);
180 flh = GC_objfreelist_ptr + nwords;
181 if (0 == (op = *flh)) {
182 return GC_aux::GC_out_of_line_malloc(nwords, GC_NORMAL);
184 *flh = GC_obj_link(op);
185 GC_aux::GC_words_recently_allocd += nwords;
186 return op;
188 static void * ptr_free_allocate(size_t n)
190 size_t nwords = GC_round_up(n);
191 void ** flh;
192 void * op;
194 if (n > GC_max_fast_bytes) return GC_malloc_atomic(n);
195 flh = GC_aobjfreelist_ptr + nwords;
196 if (0 == (op = *flh)) {
197 return GC_aux::GC_out_of_line_malloc(nwords, GC_PTRFREE);
199 *flh = GC_obj_link(op);
200 GC_aux::GC_words_recently_allocd += nwords;
201 return op;
203 static void deallocate(void *p, size_t n)
205 size_t nwords = GC_round_up(n);
206 void ** flh;
208 if (n > GC_max_fast_bytes) {
209 GC_free(p);
210 } else {
211 flh = GC_objfreelist_ptr + nwords;
212 GC_obj_link(p) = *flh;
213 memset((char *)p + GC_bytes_per_word, 0,
214 GC_bytes_per_word * (nwords - 1));
215 *flh = p;
216 GC_aux::GC_mem_recently_freed += nwords;
219 static void ptr_free_deallocate(void *p, size_t n)
221 size_t nwords = GC_round_up(n);
222 void ** flh;
224 if (n > GC_max_fast_bytes) {
225 GC_free(p);
226 } else {
227 flh = GC_aobjfreelist_ptr + nwords;
228 GC_obj_link(p) = *flh;
229 *flh = p;
230 GC_aux::GC_mem_recently_freed += nwords;
235 typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
237 // Once more, for uncollectable objects.
238 template <int dummy>
239 class single_client_alloc_template {
240 public:
241 static void * allocate(size_t n)
243 size_t nwords = GC_round_up_uncollectable(n);
244 void ** flh;
245 void * op;
247 if (n > GC_max_fast_bytes) return GC_malloc_uncollectable(n);
248 flh = GC_uobjfreelist_ptr + nwords;
249 if (0 == (op = *flh)) {
250 return GC_aux::GC_out_of_line_malloc(nwords, GC_UNCOLLECTABLE);
252 *flh = GC_obj_link(op);
253 GC_aux::GC_uncollectable_words_recently_allocd += nwords;
254 return op;
256 static void * ptr_free_allocate(size_t n)
258 size_t nwords = GC_round_up_uncollectable(n);
259 void ** flh;
260 void * op;
262 if (n > GC_max_fast_bytes) return GC_malloc_atomic_uncollectable(n);
263 flh = GC_auobjfreelist_ptr + nwords;
264 if (0 == (op = *flh)) {
265 return GC_aux::GC_out_of_line_malloc(nwords, GC_AUNCOLLECTABLE);
267 *flh = GC_obj_link(op);
268 GC_aux::GC_uncollectable_words_recently_allocd += nwords;
269 return op;
271 static void deallocate(void *p, size_t n)
273 size_t nwords = GC_round_up_uncollectable(n);
274 void ** flh;
276 if (n > GC_max_fast_bytes) {
277 GC_free(p);
278 } else {
279 flh = GC_uobjfreelist_ptr + nwords;
280 GC_obj_link(p) = *flh;
281 *flh = p;
282 GC_aux::GC_uncollectable_mem_recently_freed += nwords;
285 static void ptr_free_deallocate(void *p, size_t n)
287 size_t nwords = GC_round_up_uncollectable(n);
288 void ** flh;
290 if (n > GC_max_fast_bytes) {
291 GC_free(p);
292 } else {
293 flh = GC_auobjfreelist_ptr + nwords;
294 GC_obj_link(p) = *flh;
295 *flh = p;
296 GC_aux::GC_uncollectable_mem_recently_freed += nwords;
301 typedef single_client_alloc_template<0> single_client_alloc;
303 template < int dummy >
304 class gc_alloc_template {
305 public:
306 static void * allocate(size_t n) { return GC_malloc(n); }
307 static void * ptr_free_allocate(size_t n)
308 { return GC_malloc_atomic(n); }
309 static void deallocate(void *, size_t) { }
310 static void ptr_free_deallocate(void *, size_t) { }
313 typedef gc_alloc_template < 0 > gc_alloc;
315 template < int dummy >
316 class alloc_template {
317 public:
318 static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
319 static void * ptr_free_allocate(size_t n)
320 { return GC_malloc_atomic_uncollectable(n); }
321 static void deallocate(void *p, size_t) { GC_free(p); }
322 static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
325 typedef alloc_template < 0 > alloc;
327 #ifdef _SGI_SOURCE
329 // We want to specialize simple_alloc so that it does the right thing
330 // for all pointerfree types. At the moment there is no portable way to
331 // even approximate that. The following approximation should work for
332 // SGI compilers, and perhaps some others.
334 # define __GC_SPECIALIZE(T,alloc) \
335 class simple_alloc<T, alloc> { \
336 public: \
337 static T *allocate(size_t n) \
338 { return 0 == n? 0 : \
339 (T*) alloc::ptr_free_allocate(n * sizeof (T)); } \
340 static T *allocate(void) \
341 { return (T*) alloc::ptr_free_allocate(sizeof (T)); } \
342 static void deallocate(T *p, size_t n) \
343 { if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
344 static void deallocate(T *p) \
345 { alloc::ptr_free_deallocate(p, sizeof (T)); } \
348 __GC_SPECIALIZE(char, gc_alloc)
349 __GC_SPECIALIZE(int, gc_alloc)
350 __GC_SPECIALIZE(unsigned, gc_alloc)
351 __GC_SPECIALIZE(float, gc_alloc)
352 __GC_SPECIALIZE(double, gc_alloc)
354 __GC_SPECIALIZE(char, alloc)
355 __GC_SPECIALIZE(int, alloc)
356 __GC_SPECIALIZE(unsigned, alloc)
357 __GC_SPECIALIZE(float, alloc)
358 __GC_SPECIALIZE(double, alloc)
360 __GC_SPECIALIZE(char, single_client_gc_alloc)
361 __GC_SPECIALIZE(int, single_client_gc_alloc)
362 __GC_SPECIALIZE(unsigned, single_client_gc_alloc)
363 __GC_SPECIALIZE(float, single_client_gc_alloc)
364 __GC_SPECIALIZE(double, single_client_gc_alloc)
366 __GC_SPECIALIZE(char, single_client_alloc)
367 __GC_SPECIALIZE(int, single_client_alloc)
368 __GC_SPECIALIZE(unsigned, single_client_alloc)
369 __GC_SPECIALIZE(float, single_client_alloc)
370 __GC_SPECIALIZE(double, single_client_alloc)
372 #ifdef __STL_USE_STD_ALLOCATORS
374 ???copy stuff from stl_alloc.h or remove it to a different file ???
376 #endif /* __STL_USE_STD_ALLOCATORS */
378 #endif /* _SGI_SOURCE */
380 #endif /* GC_ALLOC_H */