pr49994-3.c: Add -mbackchain for s390 and s390x.
[gcc.git] / boehm-gc / include / new_gc_alloc.h
1 /*
2 * Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved.
3 *
4 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
6 *
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.
12 */
13
14 //
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.
18 //
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.
22 //
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.
26 //
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.
30 //
31 // This uses template classes with static members, and hence does not work
32 // with g++ 2.7.2 and earlier.
33 //
34 // Unlike its predecessor, this one simply defines
35 // gc_alloc
36 // single_client_gc_alloc
37 // traceable_alloc
38 // single_client_traceable_alloc
39 //
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.)
45 //
46 // This code assumes that the collector itself has been compiled with a
47 // compiler that defines __STDC__ .
48 //
49
50 #ifndef GC_ALLOC_H
51
52 #include "gc.h"
53
54 #if (__GNUC__ < 3)
55 # include <stack> // A more portable way to get stl_alloc.h .
56 #else
57 # include <bits/stl_alloc.h>
58 # ifndef __STL_BEGIN_NAMESPACE
59 # define __STL_BEGIN_NAMESPACE namespace std {
60 # define __STL_END_NAMESPACE };
61 # endif
62 #ifndef __STL_USE_STD_ALLOCATORS
63 #define __STL_USE_STD_ALLOCATORS
64 #endif
65 #endif
66
67 /* A hack to deal with gcc 3.1. If you are using gcc3.1 and later, */
68 /* you should probably really use gc_allocator.h instead. */
69 #if defined (__GNUC__) && \
70 (__GNUC > 3 || (__GNUC__ == 3 && (__GNUC_MINOR__ >= 1)))
71 # define simple_alloc __simple_alloc
72 #endif
73
74
75
76 #define GC_ALLOC_H
77
78 #include <stddef.h>
79 #include <string.h>
80
81 // The following need to match collector data structures.
82 // We can't include gc_priv.h, since that pulls in way too much stuff.
83 // This should eventually be factored out into another include file.
84
85 extern "C" {
86 extern void ** const GC_objfreelist_ptr;
87 extern void ** const GC_aobjfreelist_ptr;
88 extern void ** const GC_uobjfreelist_ptr;
89 extern void ** const GC_auobjfreelist_ptr;
90
91 extern void GC_incr_words_allocd(size_t words);
92 extern void GC_incr_mem_freed(size_t words);
93
94 extern char * GC_generic_malloc_words_small(size_t word, int kind);
95 }
96
97 // Object kinds; must match PTRFREE, NORMAL, UNCOLLECTABLE, and
98 // AUNCOLLECTABLE in gc_priv.h.
99
100 enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
101 GC_AUNCOLLECTABLE = 3 };
102
103 enum { GC_max_fast_bytes = 255 };
104
105 enum { GC_bytes_per_word = sizeof(char *) };
106
107 enum { GC_byte_alignment = 8 };
108
109 enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
110
111 inline void * &GC_obj_link(void * p)
112 { return *reinterpret_cast<void **>(p); }
113
114 // Compute a number of words >= n+1 bytes.
115 // The +1 allows for pointers one past the end.
116 inline size_t GC_round_up(size_t n)
117 {
118 return ((n + GC_byte_alignment)/GC_byte_alignment)*GC_word_alignment;
119 }
120
121 // The same but don't allow for extra byte.
122 inline size_t GC_round_up_uncollectable(size_t n)
123 {
124 return ((n + GC_byte_alignment - 1)/GC_byte_alignment)*GC_word_alignment;
125 }
126
127 template <int dummy>
128 class GC_aux_template {
129 public:
130 // File local count of allocated words. Occasionally this is
131 // added into the global count. A separate count is necessary since the
132 // real one must be updated with a procedure call.
133 static size_t GC_words_recently_allocd;
134
135 // Same for uncollectable mmory. Not yet reflected in either
136 // GC_words_recently_allocd or GC_non_gc_bytes.
137 static size_t GC_uncollectable_words_recently_allocd;
138
139 // Similar counter for explicitly deallocated memory.
140 static size_t GC_mem_recently_freed;
141
142 // Again for uncollectable memory.
143 static size_t GC_uncollectable_mem_recently_freed;
144
145 static void * GC_out_of_line_malloc(size_t nwords, int kind);
146 };
147
148 template <int dummy>
149 size_t GC_aux_template<dummy>::GC_words_recently_allocd = 0;
150
151 template <int dummy>
152 size_t GC_aux_template<dummy>::GC_uncollectable_words_recently_allocd = 0;
153
154 template <int dummy>
155 size_t GC_aux_template<dummy>::GC_mem_recently_freed = 0;
156
157 template <int dummy>
158 size_t GC_aux_template<dummy>::GC_uncollectable_mem_recently_freed = 0;
159
160 template <int dummy>
161 void * GC_aux_template<dummy>::GC_out_of_line_malloc(size_t nwords, int kind)
162 {
163 GC_words_recently_allocd += GC_uncollectable_words_recently_allocd;
164 GC_non_gc_bytes +=
165 GC_bytes_per_word * GC_uncollectable_words_recently_allocd;
166 GC_uncollectable_words_recently_allocd = 0;
167
168 GC_mem_recently_freed += GC_uncollectable_mem_recently_freed;
169 GC_non_gc_bytes -=
170 GC_bytes_per_word * GC_uncollectable_mem_recently_freed;
171 GC_uncollectable_mem_recently_freed = 0;
172
173 GC_incr_words_allocd(GC_words_recently_allocd);
174 GC_words_recently_allocd = 0;
175
176 GC_incr_mem_freed(GC_mem_recently_freed);
177 GC_mem_recently_freed = 0;
178
179 return GC_generic_malloc_words_small(nwords, kind);
180 }
181
182 typedef GC_aux_template<0> GC_aux;
183
184 // A fast, single-threaded, garbage-collected allocator
185 // We assume the first word will be immediately overwritten.
186 // In this version, deallocation is not a noop, and explicit
187 // deallocation is likely to help performance.
188 template <int dummy>
189 class single_client_gc_alloc_template {
190 public:
191 static void * allocate(size_t n)
192 {
193 size_t nwords = GC_round_up(n);
194 void ** flh;
195 void * op;
196
197 if (n > GC_max_fast_bytes) return GC_malloc(n);
198 flh = GC_objfreelist_ptr + nwords;
199 if (0 == (op = *flh)) {
200 return GC_aux::GC_out_of_line_malloc(nwords, GC_NORMAL);
201 }
202 *flh = GC_obj_link(op);
203 GC_aux::GC_words_recently_allocd += nwords;
204 return op;
205 }
206 static void * ptr_free_allocate(size_t n)
207 {
208 size_t nwords = GC_round_up(n);
209 void ** flh;
210 void * op;
211
212 if (n > GC_max_fast_bytes) return GC_malloc_atomic(n);
213 flh = GC_aobjfreelist_ptr + nwords;
214 if (0 == (op = *flh)) {
215 return GC_aux::GC_out_of_line_malloc(nwords, GC_PTRFREE);
216 }
217 *flh = GC_obj_link(op);
218 GC_aux::GC_words_recently_allocd += nwords;
219 return op;
220 }
221 static void deallocate(void *p, size_t n)
222 {
223 size_t nwords = GC_round_up(n);
224 void ** flh;
225
226 if (n > GC_max_fast_bytes) {
227 GC_free(p);
228 } else {
229 flh = GC_objfreelist_ptr + nwords;
230 GC_obj_link(p) = *flh;
231 memset(reinterpret_cast<char *>(p) + GC_bytes_per_word, 0,
232 GC_bytes_per_word * (nwords - 1));
233 *flh = p;
234 GC_aux::GC_mem_recently_freed += nwords;
235 }
236 }
237 static void ptr_free_deallocate(void *p, size_t n)
238 {
239 size_t nwords = GC_round_up(n);
240 void ** flh;
241
242 if (n > GC_max_fast_bytes) {
243 GC_free(p);
244 } else {
245 flh = GC_aobjfreelist_ptr + nwords;
246 GC_obj_link(p) = *flh;
247 *flh = p;
248 GC_aux::GC_mem_recently_freed += nwords;
249 }
250 }
251 };
252
253 typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
254
255 // Once more, for uncollectable objects.
256 template <int dummy>
257 class single_client_traceable_alloc_template {
258 public:
259 static void * allocate(size_t n)
260 {
261 size_t nwords = GC_round_up_uncollectable(n);
262 void ** flh;
263 void * op;
264
265 if (n > GC_max_fast_bytes) return GC_malloc_uncollectable(n);
266 flh = GC_uobjfreelist_ptr + nwords;
267 if (0 == (op = *flh)) {
268 return GC_aux::GC_out_of_line_malloc(nwords, GC_UNCOLLECTABLE);
269 }
270 *flh = GC_obj_link(op);
271 GC_aux::GC_uncollectable_words_recently_allocd += nwords;
272 return op;
273 }
274 static void * ptr_free_allocate(size_t n)
275 {
276 size_t nwords = GC_round_up_uncollectable(n);
277 void ** flh;
278 void * op;
279
280 if (n > GC_max_fast_bytes) return GC_malloc_atomic_uncollectable(n);
281 flh = GC_auobjfreelist_ptr + nwords;
282 if (0 == (op = *flh)) {
283 return GC_aux::GC_out_of_line_malloc(nwords, GC_AUNCOLLECTABLE);
284 }
285 *flh = GC_obj_link(op);
286 GC_aux::GC_uncollectable_words_recently_allocd += nwords;
287 return op;
288 }
289 static void deallocate(void *p, size_t n)
290 {
291 size_t nwords = GC_round_up_uncollectable(n);
292 void ** flh;
293
294 if (n > GC_max_fast_bytes) {
295 GC_free(p);
296 } else {
297 flh = GC_uobjfreelist_ptr + nwords;
298 GC_obj_link(p) = *flh;
299 *flh = p;
300 GC_aux::GC_uncollectable_mem_recently_freed += nwords;
301 }
302 }
303 static void ptr_free_deallocate(void *p, size_t n)
304 {
305 size_t nwords = GC_round_up_uncollectable(n);
306 void ** flh;
307
308 if (n > GC_max_fast_bytes) {
309 GC_free(p);
310 } else {
311 flh = GC_auobjfreelist_ptr + nwords;
312 GC_obj_link(p) = *flh;
313 *flh = p;
314 GC_aux::GC_uncollectable_mem_recently_freed += nwords;
315 }
316 }
317 };
318
319 typedef single_client_traceable_alloc_template<0> single_client_traceable_alloc;
320
321 template < int dummy >
322 class gc_alloc_template {
323 public:
324 static void * allocate(size_t n) { return GC_malloc(n); }
325 static void * ptr_free_allocate(size_t n)
326 { return GC_malloc_atomic(n); }
327 static void deallocate(void *, size_t) { }
328 static void ptr_free_deallocate(void *, size_t) { }
329 };
330
331 typedef gc_alloc_template < 0 > gc_alloc;
332
333 template < int dummy >
334 class traceable_alloc_template {
335 public:
336 static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
337 static void * ptr_free_allocate(size_t n)
338 { return GC_malloc_atomic_uncollectable(n); }
339 static void deallocate(void *p, size_t) { GC_free(p); }
340 static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
341 };
342
343 typedef traceable_alloc_template < 0 > traceable_alloc;
344
345 // We want to specialize simple_alloc so that it does the right thing
346 // for all pointerfree types. At the moment there is no portable way to
347 // even approximate that. The following approximation should work for
348 // SGI compilers, and recent versions of g++.
349
350 # define __GC_SPECIALIZE(T,alloc) \
351 class simple_alloc<T, alloc> { \
352 public: \
353 static T *allocate(size_t n) \
354 { return 0 == n? 0 : \
355 reinterpret_cast<T*>(alloc::ptr_free_allocate(n * sizeof (T))); } \
356 static T *allocate(void) \
357 { return reinterpret_cast<T*>(alloc::ptr_free_allocate(sizeof (T))); } \
358 static void deallocate(T *p, size_t n) \
359 { if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
360 static void deallocate(T *p) \
361 { alloc::ptr_free_deallocate(p, sizeof (T)); } \
362 };
363
364 __STL_BEGIN_NAMESPACE
365
366 __GC_SPECIALIZE(char, gc_alloc)
367 __GC_SPECIALIZE(int, gc_alloc)
368 __GC_SPECIALIZE(unsigned, gc_alloc)
369 __GC_SPECIALIZE(float, gc_alloc)
370 __GC_SPECIALIZE(double, gc_alloc)
371
372 __GC_SPECIALIZE(char, traceable_alloc)
373 __GC_SPECIALIZE(int, traceable_alloc)
374 __GC_SPECIALIZE(unsigned, traceable_alloc)
375 __GC_SPECIALIZE(float, traceable_alloc)
376 __GC_SPECIALIZE(double, traceable_alloc)
377
378 __GC_SPECIALIZE(char, single_client_gc_alloc)
379 __GC_SPECIALIZE(int, single_client_gc_alloc)
380 __GC_SPECIALIZE(unsigned, single_client_gc_alloc)
381 __GC_SPECIALIZE(float, single_client_gc_alloc)
382 __GC_SPECIALIZE(double, single_client_gc_alloc)
383
384 __GC_SPECIALIZE(char, single_client_traceable_alloc)
385 __GC_SPECIALIZE(int, single_client_traceable_alloc)
386 __GC_SPECIALIZE(unsigned, single_client_traceable_alloc)
387 __GC_SPECIALIZE(float, single_client_traceable_alloc)
388 __GC_SPECIALIZE(double, single_client_traceable_alloc)
389
390 __STL_END_NAMESPACE
391
392 #ifdef __STL_USE_STD_ALLOCATORS
393
394 __STL_BEGIN_NAMESPACE
395
396 template <class _Tp>
397 struct _Alloc_traits<_Tp, gc_alloc >
398 {
399 static const bool _S_instanceless = true;
400 typedef simple_alloc<_Tp, gc_alloc > _Alloc_type;
401 typedef __allocator<_Tp, gc_alloc > allocator_type;
402 };
403
404 inline bool operator==(const gc_alloc&,
405 const gc_alloc&)
406 {
407 return true;
408 }
409
410 inline bool operator!=(const gc_alloc&,
411 const gc_alloc&)
412 {
413 return false;
414 }
415
416 template <class _Tp>
417 struct _Alloc_traits<_Tp, single_client_gc_alloc >
418 {
419 static const bool _S_instanceless = true;
420 typedef simple_alloc<_Tp, single_client_gc_alloc > _Alloc_type;
421 typedef __allocator<_Tp, single_client_gc_alloc > allocator_type;
422 };
423
424 inline bool operator==(const single_client_gc_alloc&,
425 const single_client_gc_alloc&)
426 {
427 return true;
428 }
429
430 inline bool operator!=(const single_client_gc_alloc&,
431 const single_client_gc_alloc&)
432 {
433 return false;
434 }
435
436 template <class _Tp>
437 struct _Alloc_traits<_Tp, traceable_alloc >
438 {
439 static const bool _S_instanceless = true;
440 typedef simple_alloc<_Tp, traceable_alloc > _Alloc_type;
441 typedef __allocator<_Tp, traceable_alloc > allocator_type;
442 };
443
444 inline bool operator==(const traceable_alloc&,
445 const traceable_alloc&)
446 {
447 return true;
448 }
449
450 inline bool operator!=(const traceable_alloc&,
451 const traceable_alloc&)
452 {
453 return false;
454 }
455
456 template <class _Tp>
457 struct _Alloc_traits<_Tp, single_client_traceable_alloc >
458 {
459 static const bool _S_instanceless = true;
460 typedef simple_alloc<_Tp, single_client_traceable_alloc > _Alloc_type;
461 typedef __allocator<_Tp, single_client_traceable_alloc > allocator_type;
462 };
463
464 inline bool operator==(const single_client_traceable_alloc&,
465 const single_client_traceable_alloc&)
466 {
467 return true;
468 }
469
470 inline bool operator!=(const single_client_traceable_alloc&,
471 const single_client_traceable_alloc&)
472 {
473 return false;
474 }
475
476 __STL_END_NAMESPACE
477
478 #endif /* __STL_USE_STD_ALLOCATORS */
479
480 #endif /* GC_ALLOC_H */