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.
34 #define __ALLOC_H // Prevent inclusion of the default version. Ugly.
35 #define __SGI_STL_ALLOC_H
36 #define __SGI_STL_INTERNAL_ALLOC_H
39 # define __ALLOC alloc
45 // The following is just replicated from the conventional SGI alloc.h:
47 template<class T
, class alloc
>
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
)); }
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.
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
;
110 class GC_aux_template
{
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
);
131 size_t GC_aux_template
<dummy
>::GC_words_recently_allocd
= 0;
134 size_t GC_aux_template
<dummy
>::GC_uncollectable_words_recently_allocd
= 0;
137 size_t GC_aux_template
<dummy
>::GC_mem_recently_freed
= 0;
140 size_t GC_aux_template
<dummy
>::GC_uncollectable_mem_recently_freed
= 0;
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
;
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
;
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.
171 class single_client_gc_alloc_template
{
173 static void * allocate(size_t n
)
175 size_t nwords
= GC_round_up(n
);
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
;
188 static void * ptr_free_allocate(size_t n
)
190 size_t nwords
= GC_round_up(n
);
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
;
203 static void deallocate(void *p
, size_t n
)
205 size_t nwords
= GC_round_up(n
);
208 if (n
> GC_max_fast_bytes
) {
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));
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
);
224 if (n
> GC_max_fast_bytes
) {
227 flh
= GC_aobjfreelist_ptr
+ nwords
;
228 GC_obj_link(p
) = *flh
;
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.
239 class single_client_alloc_template
{
241 static void * allocate(size_t n
)
243 size_t nwords
= GC_round_up_uncollectable(n
);
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
;
256 static void * ptr_free_allocate(size_t n
)
258 size_t nwords
= GC_round_up_uncollectable(n
);
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
;
271 static void deallocate(void *p
, size_t n
)
273 size_t nwords
= GC_round_up_uncollectable(n
);
276 if (n
> GC_max_fast_bytes
) {
279 flh
= GC_uobjfreelist_ptr
+ nwords
;
280 GC_obj_link(p
) = *flh
;
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
);
290 if (n
> GC_max_fast_bytes
) {
293 flh
= GC_auobjfreelist_ptr
+ nwords
;
294 GC_obj_link(p
) = *flh
;
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
{
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
{
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
;
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> { \
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 */