2001-06-20 Alexandre Petit-Bianco <apbianco@redhat.com>
[official-gcc.git] / boehm-gc / include / new_gc_alloc.h
blob1187f0b69f7130ca214cddad556bea1d3553035c
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 revision of gc_alloc.h for SGI STL versions > 3.0
16 // Unlike earlier versions, it supplements the standard "alloc.h"
17 // instead of replacing it.
19 // This is sloppy about variable names used in header files.
20 // It also doesn't yet understand the new header file names or
21 // namespaces.
23 // This assumes the collector has been compiled with -DATOMIC_UNCOLLECTABLE.
24 // The user should also consider -DREDIRECT_MALLOC=GC_uncollectable_malloc,
25 // to ensure that object allocated through malloc are traced.
27 // Some of this could be faster in the explicit deallocation case.
28 // In particular, we spend too much time clearing objects on the
29 // free lists. That could be avoided.
31 // This uses template classes with static members, and hence does not work
32 // with g++ 2.7.2 and earlier.
34 // Unlike its predecessor, this one simply defines
35 // gc_alloc
36 // single_client_gc_alloc
37 // traceable_alloc
38 // single_client_traceable_alloc
40 // It does not redefine alloc. Nor does it change the default allocator,
41 // though the user may wish to do so. (The argument against changing
42 // the default allocator is that it may introduce subtle link compatibility
43 // problems. The argument for changing it is that the usual default
44 // allocator is usually a very bad choice for a garbage collected environment.)
46 // This code assumes that the collector itself has been compiled with a
47 // compiler that defines __STDC__ .
50 #ifndef GC_ALLOC_H
52 #include "gc.h"
53 #include <stack> // A more portable way to get stl_alloc.h .
55 #define GC_ALLOC_H
57 #include <stddef.h>
58 #include <string.h>
60 // The following need to match collector data structures.
61 // We can't include gc_priv.h, since that pulls in way too much stuff.
62 // This should eventually be factored out into another include file.
64 extern "C" {
65 extern void ** const GC_objfreelist_ptr;
66 extern void ** const GC_aobjfreelist_ptr;
67 extern void ** const GC_uobjfreelist_ptr;
68 extern void ** const GC_auobjfreelist_ptr;
70 extern void GC_incr_words_allocd(size_t words);
71 extern void GC_incr_mem_freed(size_t words);
73 extern char * GC_generic_malloc_words_small(size_t word, int kind);
76 // Object kinds; must match PTRFREE, NORMAL, UNCOLLECTABLE, and
77 // AUNCOLLECTABLE in gc_priv.h.
79 enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
80 GC_AUNCOLLECTABLE = 3 };
82 enum { GC_max_fast_bytes = 255 };
84 enum { GC_bytes_per_word = sizeof(char *) };
86 enum { GC_byte_alignment = 8 };
88 enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
90 inline void * &GC_obj_link(void * p)
91 { return *(void **)p; }
93 // Compute a number of words >= n+1 bytes.
94 // The +1 allows for pointers one past the end.
95 inline size_t GC_round_up(size_t n)
97 return ((n + GC_byte_alignment)/GC_byte_alignment)*GC_word_alignment;
100 // The same but don't allow for extra byte.
101 inline size_t GC_round_up_uncollectable(size_t n)
103 return ((n + GC_byte_alignment - 1)/GC_byte_alignment)*GC_word_alignment;
106 template <int dummy>
107 class GC_aux_template {
108 public:
109 // File local count of allocated words. Occasionally this is
110 // added into the global count. A separate count is necessary since the
111 // real one must be updated with a procedure call.
112 static size_t GC_words_recently_allocd;
114 // Same for uncollectable mmory. Not yet reflected in either
115 // GC_words_recently_allocd or GC_non_gc_bytes.
116 static size_t GC_uncollectable_words_recently_allocd;
118 // Similar counter for explicitly deallocated memory.
119 static size_t GC_mem_recently_freed;
121 // Again for uncollectable memory.
122 static size_t GC_uncollectable_mem_recently_freed;
124 static void * GC_out_of_line_malloc(size_t nwords, int kind);
127 template <int dummy>
128 size_t GC_aux_template<dummy>::GC_words_recently_allocd = 0;
130 template <int dummy>
131 size_t GC_aux_template<dummy>::GC_uncollectable_words_recently_allocd = 0;
133 template <int dummy>
134 size_t GC_aux_template<dummy>::GC_mem_recently_freed = 0;
136 template <int dummy>
137 size_t GC_aux_template<dummy>::GC_uncollectable_mem_recently_freed = 0;
139 template <int dummy>
140 void * GC_aux_template<dummy>::GC_out_of_line_malloc(size_t nwords, int kind)
142 GC_words_recently_allocd += GC_uncollectable_words_recently_allocd;
143 GC_non_gc_bytes +=
144 GC_bytes_per_word * GC_uncollectable_words_recently_allocd;
145 GC_uncollectable_words_recently_allocd = 0;
147 GC_mem_recently_freed += GC_uncollectable_mem_recently_freed;
148 GC_non_gc_bytes -=
149 GC_bytes_per_word * GC_uncollectable_mem_recently_freed;
150 GC_uncollectable_mem_recently_freed = 0;
152 GC_incr_words_allocd(GC_words_recently_allocd);
153 GC_words_recently_allocd = 0;
155 GC_incr_mem_freed(GC_mem_recently_freed);
156 GC_mem_recently_freed = 0;
158 return GC_generic_malloc_words_small(nwords, kind);
161 typedef GC_aux_template<0> GC_aux;
163 // A fast, single-threaded, garbage-collected allocator
164 // We assume the first word will be immediately overwritten.
165 // In this version, deallocation is not a noop, and explicit
166 // deallocation is likely to help performance.
167 template <int dummy>
168 class single_client_gc_alloc_template {
169 public:
170 static void * allocate(size_t n)
172 size_t nwords = GC_round_up(n);
173 void ** flh;
174 void * op;
176 if (n > GC_max_fast_bytes) return GC_malloc(n);
177 flh = GC_objfreelist_ptr + nwords;
178 if (0 == (op = *flh)) {
179 return GC_aux::GC_out_of_line_malloc(nwords, GC_NORMAL);
181 *flh = GC_obj_link(op);
182 GC_aux::GC_words_recently_allocd += nwords;
183 return op;
185 static void * ptr_free_allocate(size_t n)
187 size_t nwords = GC_round_up(n);
188 void ** flh;
189 void * op;
191 if (n > GC_max_fast_bytes) return GC_malloc_atomic(n);
192 flh = GC_aobjfreelist_ptr + nwords;
193 if (0 == (op = *flh)) {
194 return GC_aux::GC_out_of_line_malloc(nwords, GC_PTRFREE);
196 *flh = GC_obj_link(op);
197 GC_aux::GC_words_recently_allocd += nwords;
198 return op;
200 static void deallocate(void *p, size_t n)
202 size_t nwords = GC_round_up(n);
203 void ** flh;
205 if (n > GC_max_fast_bytes) {
206 GC_free(p);
207 } else {
208 flh = GC_objfreelist_ptr + nwords;
209 GC_obj_link(p) = *flh;
210 memset((char *)p + GC_bytes_per_word, 0,
211 GC_bytes_per_word * (nwords - 1));
212 *flh = p;
213 GC_aux::GC_mem_recently_freed += nwords;
216 static void ptr_free_deallocate(void *p, size_t n)
218 size_t nwords = GC_round_up(n);
219 void ** flh;
221 if (n > GC_max_fast_bytes) {
222 GC_free(p);
223 } else {
224 flh = GC_aobjfreelist_ptr + nwords;
225 GC_obj_link(p) = *flh;
226 *flh = p;
227 GC_aux::GC_mem_recently_freed += nwords;
232 typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
234 // Once more, for uncollectable objects.
235 template <int dummy>
236 class single_client_traceable_alloc_template {
237 public:
238 static void * allocate(size_t n)
240 size_t nwords = GC_round_up_uncollectable(n);
241 void ** flh;
242 void * op;
244 if (n > GC_max_fast_bytes) return GC_malloc_uncollectable(n);
245 flh = GC_uobjfreelist_ptr + nwords;
246 if (0 == (op = *flh)) {
247 return GC_aux::GC_out_of_line_malloc(nwords, GC_UNCOLLECTABLE);
249 *flh = GC_obj_link(op);
250 GC_aux::GC_uncollectable_words_recently_allocd += nwords;
251 return op;
253 static void * ptr_free_allocate(size_t n)
255 size_t nwords = GC_round_up_uncollectable(n);
256 void ** flh;
257 void * op;
259 if (n > GC_max_fast_bytes) return GC_malloc_atomic_uncollectable(n);
260 flh = GC_auobjfreelist_ptr + nwords;
261 if (0 == (op = *flh)) {
262 return GC_aux::GC_out_of_line_malloc(nwords, GC_AUNCOLLECTABLE);
264 *flh = GC_obj_link(op);
265 GC_aux::GC_uncollectable_words_recently_allocd += nwords;
266 return op;
268 static void deallocate(void *p, size_t n)
270 size_t nwords = GC_round_up_uncollectable(n);
271 void ** flh;
273 if (n > GC_max_fast_bytes) {
274 GC_free(p);
275 } else {
276 flh = GC_uobjfreelist_ptr + nwords;
277 GC_obj_link(p) = *flh;
278 *flh = p;
279 GC_aux::GC_uncollectable_mem_recently_freed += nwords;
282 static void ptr_free_deallocate(void *p, size_t n)
284 size_t nwords = GC_round_up_uncollectable(n);
285 void ** flh;
287 if (n > GC_max_fast_bytes) {
288 GC_free(p);
289 } else {
290 flh = GC_auobjfreelist_ptr + nwords;
291 GC_obj_link(p) = *flh;
292 *flh = p;
293 GC_aux::GC_uncollectable_mem_recently_freed += nwords;
298 typedef single_client_traceable_alloc_template<0> single_client_traceable_alloc;
300 template < int dummy >
301 class gc_alloc_template {
302 public:
303 static void * allocate(size_t n) { return GC_malloc(n); }
304 static void * ptr_free_allocate(size_t n)
305 { return GC_malloc_atomic(n); }
306 static void deallocate(void *, size_t) { }
307 static void ptr_free_deallocate(void *, size_t) { }
310 typedef gc_alloc_template < 0 > gc_alloc;
312 template < int dummy >
313 class traceable_alloc_template {
314 public:
315 static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
316 static void * ptr_free_allocate(size_t n)
317 { return GC_malloc_atomic_uncollectable(n); }
318 static void deallocate(void *p, size_t) { GC_free(p); }
319 static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
322 typedef traceable_alloc_template < 0 > traceable_alloc;
324 // We want to specialize simple_alloc so that it does the right thing
325 // for all pointerfree types. At the moment there is no portable way to
326 // even approximate that. The following approximation should work for
327 // SGI compilers, and recent versions of g++.
329 # define __GC_SPECIALIZE(T,alloc) \
330 class simple_alloc<T, alloc> { \
331 public: \
332 static T *allocate(size_t n) \
333 { return 0 == n? 0 : \
334 (T*) alloc::ptr_free_allocate(n * sizeof (T)); } \
335 static T *allocate(void) \
336 { return (T*) alloc::ptr_free_allocate(sizeof (T)); } \
337 static void deallocate(T *p, size_t n) \
338 { if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
339 static void deallocate(T *p) \
340 { alloc::ptr_free_deallocate(p, sizeof (T)); } \
343 __STL_BEGIN_NAMESPACE
345 __GC_SPECIALIZE(char, gc_alloc)
346 __GC_SPECIALIZE(int, gc_alloc)
347 __GC_SPECIALIZE(unsigned, gc_alloc)
348 __GC_SPECIALIZE(float, gc_alloc)
349 __GC_SPECIALIZE(double, gc_alloc)
351 __GC_SPECIALIZE(char, traceable_alloc)
352 __GC_SPECIALIZE(int, traceable_alloc)
353 __GC_SPECIALIZE(unsigned, traceable_alloc)
354 __GC_SPECIALIZE(float, traceable_alloc)
355 __GC_SPECIALIZE(double, traceable_alloc)
357 __GC_SPECIALIZE(char, single_client_gc_alloc)
358 __GC_SPECIALIZE(int, single_client_gc_alloc)
359 __GC_SPECIALIZE(unsigned, single_client_gc_alloc)
360 __GC_SPECIALIZE(float, single_client_gc_alloc)
361 __GC_SPECIALIZE(double, single_client_gc_alloc)
363 __GC_SPECIALIZE(char, single_client_traceable_alloc)
364 __GC_SPECIALIZE(int, single_client_traceable_alloc)
365 __GC_SPECIALIZE(unsigned, single_client_traceable_alloc)
366 __GC_SPECIALIZE(float, single_client_traceable_alloc)
367 __GC_SPECIALIZE(double, single_client_traceable_alloc)
369 __STL_END_NAMESPACE
371 #ifdef __STL_USE_STD_ALLOCATORS
373 __STL_BEGIN_NAMESPACE
375 template <class _T>
376 struct _Alloc_traits<_T, gc_alloc >
378 static const bool _S_instanceless = true;
379 typedef simple_alloc<_T, gc_alloc > _Alloc_type;
380 typedef __allocator<_T, gc_alloc > allocator_type;
383 inline bool operator==(const gc_alloc&,
384 const gc_alloc&)
386 return true;
389 inline bool operator!=(const gc_alloc&,
390 const gc_alloc&)
392 return false;
395 template <class _T>
396 struct _Alloc_traits<_T, single_client_gc_alloc >
398 static const bool _S_instanceless = true;
399 typedef simple_alloc<_T, single_client_gc_alloc > _Alloc_type;
400 typedef __allocator<_T, single_client_gc_alloc > allocator_type;
403 inline bool operator==(const single_client_gc_alloc&,
404 const single_client_gc_alloc&)
406 return true;
409 inline bool operator!=(const single_client_gc_alloc&,
410 const single_client_gc_alloc&)
412 return false;
415 template <class _T>
416 struct _Alloc_traits<_T, traceable_alloc >
418 static const bool _S_instanceless = true;
419 typedef simple_alloc<_T, traceable_alloc > _Alloc_type;
420 typedef __allocator<_T, traceable_alloc > allocator_type;
423 inline bool operator==(const traceable_alloc&,
424 const traceable_alloc&)
426 return true;
429 inline bool operator!=(const traceable_alloc&,
430 const traceable_alloc&)
432 return false;
435 template <class _T>
436 struct _Alloc_traits<_T, single_client_traceable_alloc >
438 static const bool _S_instanceless = true;
439 typedef simple_alloc<_T, single_client_traceable_alloc > _Alloc_type;
440 typedef __allocator<_T, single_client_traceable_alloc > allocator_type;
443 inline bool operator==(const single_client_traceable_alloc&,
444 const single_client_traceable_alloc&)
446 return true;
449 inline bool operator!=(const single_client_traceable_alloc&,
450 const single_client_traceable_alloc&)
452 return false;
455 __STL_END_NAMESPACE
457 #endif /* __STL_USE_STD_ALLOCATORS */
459 #endif /* GC_ALLOC_H */