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
23
// This assumes the collector has been compiled with -DATOMIC_UNCOLLECTABLE
24
// and -DALL_INTERIOR_POINTERS. We also recommend
25
// -DREDIRECT_MALLOC=GC_uncollectable_malloc.
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
36
// single_client_gc_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.)
57
// The following need to match collector data structures.
58
// We can't include gc_priv.h, since that pulls in way too much stuff.
59
// This should eventually be factored out into another include file.
62
extern void ** const GC_objfreelist_ptr;
63
extern void ** const GC_aobjfreelist_ptr;
64
extern void ** const GC_uobjfreelist_ptr;
65
extern void ** const GC_auobjfreelist_ptr;
67
extern void GC_incr_words_allocd(size_t words);
68
extern void GC_incr_mem_freed(size_t words);
70
extern char * GC_generic_malloc_words_small(size_t word, int kind);
73
// Object kinds; must match PTRFREE, NORMAL, UNCOLLECTABLE, and
74
// AUNCOLLECTABLE in gc_priv.h.
76
enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
77
GC_AUNCOLLECTABLE = 3 };
79
enum { GC_max_fast_bytes = 255 };
81
enum { GC_bytes_per_word = sizeof(char *) };
83
enum { GC_byte_alignment = 8 };
85
enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
87
inline void * &GC_obj_link(void * p)
88
{ return *(void **)p; }
90
// Compute a number of words >= n+1 bytes.
91
// The +1 allows for pointers one past the end.
92
inline size_t GC_round_up(size_t n)
94
return ((n + GC_byte_alignment)/GC_byte_alignment)*GC_word_alignment;
97
// The same but don't allow for extra byte.
98
inline size_t GC_round_up_uncollectable(size_t n)
100
return ((n + GC_byte_alignment - 1)/GC_byte_alignment)*GC_word_alignment;
104
class GC_aux_template {
106
// File local count of allocated words. Occasionally this is
107
// added into the global count. A separate count is necessary since the
108
// real one must be updated with a procedure call.
109
static size_t GC_words_recently_allocd;
111
// Same for uncollectable mmory. Not yet reflected in either
112
// GC_words_recently_allocd or GC_non_gc_bytes.
113
static size_t GC_uncollectable_words_recently_allocd;
115
// Similar counter for explicitly deallocated memory.
116
static size_t GC_mem_recently_freed;
118
// Again for uncollectable memory.
119
static size_t GC_uncollectable_mem_recently_freed;
121
static void * GC_out_of_line_malloc(size_t nwords, int kind);
125
size_t GC_aux_template<dummy>::GC_words_recently_allocd = 0;
128
size_t GC_aux_template<dummy>::GC_uncollectable_words_recently_allocd = 0;
131
size_t GC_aux_template<dummy>::GC_mem_recently_freed = 0;
134
size_t GC_aux_template<dummy>::GC_uncollectable_mem_recently_freed = 0;
137
void * GC_aux_template<dummy>::GC_out_of_line_malloc(size_t nwords, int kind)
139
GC_words_recently_allocd += GC_uncollectable_words_recently_allocd;
141
GC_bytes_per_word * GC_uncollectable_words_recently_allocd;
142
GC_uncollectable_words_recently_allocd = 0;
144
GC_mem_recently_freed += GC_uncollectable_mem_recently_freed;
146
GC_bytes_per_word * GC_uncollectable_mem_recently_freed;
147
GC_uncollectable_mem_recently_freed = 0;
149
GC_incr_words_allocd(GC_words_recently_allocd);
150
GC_words_recently_allocd = 0;
152
GC_incr_mem_freed(GC_mem_recently_freed);
153
GC_mem_recently_freed = 0;
155
return GC_generic_malloc_words_small(nwords, kind);
158
typedef GC_aux_template<0> GC_aux;
160
// A fast, single-threaded, garbage-collected allocator
161
// We assume the first word will be immediately overwritten.
162
// In this version, deallocation is not a noop, and explicit
163
// deallocation is likely to help performance.
165
class single_client_gc_alloc_template {
167
static void * allocate(size_t n)
169
size_t nwords = GC_round_up(n);
173
if (n > GC_max_fast_bytes) return GC_malloc(n);
174
flh = GC_objfreelist_ptr + nwords;
175
if (0 == (op = *flh)) {
176
return GC_aux::GC_out_of_line_malloc(nwords, GC_NORMAL);
178
*flh = GC_obj_link(op);
179
GC_aux::GC_words_recently_allocd += nwords;
182
static void * ptr_free_allocate(size_t n)
184
size_t nwords = GC_round_up(n);
188
if (n > GC_max_fast_bytes) return GC_malloc_atomic(n);
189
flh = GC_aobjfreelist_ptr + nwords;
190
if (0 == (op = *flh)) {
191
return GC_aux::GC_out_of_line_malloc(nwords, GC_PTRFREE);
193
*flh = GC_obj_link(op);
194
GC_aux::GC_words_recently_allocd += nwords;
197
static void deallocate(void *p, size_t n)
199
size_t nwords = GC_round_up(n);
202
if (n > GC_max_fast_bytes) {
205
flh = GC_objfreelist_ptr + nwords;
206
GC_obj_link(p) = *flh;
207
memset((char *)p + GC_bytes_per_word, 0,
208
GC_bytes_per_word * (nwords - 1));
210
GC_aux::GC_mem_recently_freed += nwords;
213
static void ptr_free_deallocate(void *p, size_t n)
215
size_t nwords = GC_round_up(n);
218
if (n > GC_max_fast_bytes) {
221
flh = GC_aobjfreelist_ptr + nwords;
222
GC_obj_link(p) = *flh;
224
GC_aux::GC_mem_recently_freed += nwords;
229
typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
231
// Once more, for uncollectable objects.
233
class single_client_traceable_alloc_template {
235
static void * allocate(size_t n)
237
size_t nwords = GC_round_up_uncollectable(n);
241
if (n > GC_max_fast_bytes) return GC_malloc_uncollectable(n);
242
flh = GC_uobjfreelist_ptr + nwords;
243
if (0 == (op = *flh)) {
244
return GC_aux::GC_out_of_line_malloc(nwords, GC_UNCOLLECTABLE);
246
*flh = GC_obj_link(op);
247
GC_aux::GC_uncollectable_words_recently_allocd += nwords;
250
static void * ptr_free_allocate(size_t n)
252
size_t nwords = GC_round_up_uncollectable(n);
256
if (n > GC_max_fast_bytes) return GC_malloc_atomic_uncollectable(n);
257
flh = GC_auobjfreelist_ptr + nwords;
258
if (0 == (op = *flh)) {
259
return GC_aux::GC_out_of_line_malloc(nwords, GC_AUNCOLLECTABLE);
261
*flh = GC_obj_link(op);
262
GC_aux::GC_uncollectable_words_recently_allocd += nwords;
265
static void deallocate(void *p, size_t n)
267
size_t nwords = GC_round_up_uncollectable(n);
270
if (n > GC_max_fast_bytes) {
273
flh = GC_uobjfreelist_ptr + nwords;
274
GC_obj_link(p) = *flh;
276
GC_aux::GC_uncollectable_mem_recently_freed += nwords;
279
static void ptr_free_deallocate(void *p, size_t n)
281
size_t nwords = GC_round_up_uncollectable(n);
284
if (n > GC_max_fast_bytes) {
287
flh = GC_auobjfreelist_ptr + nwords;
288
GC_obj_link(p) = *flh;
290
GC_aux::GC_uncollectable_mem_recently_freed += nwords;
295
typedef single_client_traceable_alloc_template<0> single_client_traceable_alloc;
297
template < int dummy >
298
class gc_alloc_template {
300
static void * allocate(size_t n) { return GC_malloc(n); }
301
static void * ptr_free_allocate(size_t n)
302
{ return GC_malloc_atomic(n); }
303
static void deallocate(void *, size_t) { }
304
static void ptr_free_deallocate(void *, size_t) { }
307
typedef gc_alloc_template < 0 > gc_alloc;
309
template < int dummy >
310
class traceable_alloc_template {
312
static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
313
static void * ptr_free_allocate(size_t n)
314
{ return GC_malloc_atomic_uncollectable(n); }
315
static void deallocate(void *p, size_t) { GC_free(p); }
316
static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
319
typedef traceable_alloc_template < 0 > traceable_alloc;
323
// We want to specialize simple_alloc so that it does the right thing
324
// for all pointerfree types. At the moment there is no portable way to
325
// even approximate that. The following approximation should work for
326
// SGI compilers, and perhaps some others.
328
# define __GC_SPECIALIZE(T,alloc) \
329
class simple_alloc<T, alloc> { \
331
static T *allocate(size_t n) \
332
{ return 0 == n? 0 : \
333
(T*) alloc::ptr_free_allocate(n * sizeof (T)); } \
334
static T *allocate(void) \
335
{ return (T*) alloc::ptr_free_allocate(sizeof (T)); } \
336
static void deallocate(T *p, size_t n) \
337
{ if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
338
static void deallocate(T *p) \
339
{ alloc::ptr_free_deallocate(p, sizeof (T)); } \
342
__GC_SPECIALIZE(char, gc_alloc)
343
__GC_SPECIALIZE(int, gc_alloc)
344
__GC_SPECIALIZE(unsigned, gc_alloc)
345
__GC_SPECIALIZE(float, gc_alloc)
346
__GC_SPECIALIZE(double, gc_alloc)
348
__GC_SPECIALIZE(char, traceable_alloc)
349
__GC_SPECIALIZE(int, traceable_alloc)
350
__GC_SPECIALIZE(unsigned, traceable_alloc)
351
__GC_SPECIALIZE(float, traceable_alloc)
352
__GC_SPECIALIZE(double, traceable_alloc)
354
__GC_SPECIALIZE(char, single_client_gc_alloc)
355
__GC_SPECIALIZE(int, single_client_gc_alloc)
356
__GC_SPECIALIZE(unsigned, single_client_gc_alloc)
357
__GC_SPECIALIZE(float, single_client_gc_alloc)
358
__GC_SPECIALIZE(double, single_client_gc_alloc)
360
__GC_SPECIALIZE(char, single_client_traceable_alloc)
361
__GC_SPECIALIZE(int, single_client_traceable_alloc)
362
__GC_SPECIALIZE(unsigned, single_client_traceable_alloc)
363
__GC_SPECIALIZE(float, single_client_traceable_alloc)
364
__GC_SPECIALIZE(double, single_client_traceable_alloc)
366
#ifdef __STL_USE_STD_ALLOCATORS
368
__STL_BEGIN_NAMESPACE
371
struct _Alloc_traits<_T, gc_alloc >
373
static const bool _S_instanceless = true;
374
typedef simple_alloc<_T, gc_alloc > _Alloc_type;
375
typedef __allocator<_T, gc_alloc > allocator_type;
378
inline bool operator==(const gc_alloc&,
384
inline bool operator!=(const gc_alloc&,
391
struct _Alloc_traits<_T, single_client_gc_alloc >
393
static const bool _S_instanceless = true;
394
typedef simple_alloc<_T, single_client_gc_alloc > _Alloc_type;
395
typedef __allocator<_T, single_client_gc_alloc > allocator_type;
398
inline bool operator==(const single_client_gc_alloc&,
399
const single_client_gc_alloc&)
404
inline bool operator!=(const single_client_gc_alloc&,
405
const single_client_gc_alloc&)
411
struct _Alloc_traits<_T, traceable_alloc >
413
static const bool _S_instanceless = true;
414
typedef simple_alloc<_T, traceable_alloc > _Alloc_type;
415
typedef __allocator<_T, traceable_alloc > allocator_type;
418
inline bool operator==(const traceable_alloc&,
419
const traceable_alloc&)
424
inline bool operator!=(const traceable_alloc&,
425
const traceable_alloc&)
431
struct _Alloc_traits<_T, single_client_traceable_alloc >
433
static const bool _S_instanceless = true;
434
typedef simple_alloc<_T, single_client_traceable_alloc > _Alloc_type;
435
typedef __allocator<_T, single_client_traceable_alloc > allocator_type;
438
inline bool operator==(const single_client_traceable_alloc&,
439
const single_client_traceable_alloc&)
444
inline bool operator!=(const single_client_traceable_alloc&,
445
const single_client_traceable_alloc&)
452
#endif /* __STL_USE_STD_ALLOCATORS */
454
#endif /* _SGI_SOURCE */
456
#endif /* GC_ALLOC_H */