Annotation of OpenXM_contrib2/asir2000/gc/include/new_gc_alloc.h, Revision 1.6
1.1 noro 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: //
1.3 noro 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.
1.1 noro 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: //
1.3 noro 46: // This code assumes that the collector itself has been compiled with a
47: // compiler that defines __STDC__ .
48: //
1.1 noro 49:
50: #ifndef GC_ALLOC_H
51:
52: #include "gc.h"
1.5 noro 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:
1.6 ! noro 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:
1.1 noro 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 *(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((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
1.2 noro 348: // SGI compilers, and recent versions of g++.
1.1 noro 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: (T*) alloc::ptr_free_allocate(n * sizeof (T)); } \
356: static T *allocate(void) \
357: { return (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:
1.3 noro 364: __STL_BEGIN_NAMESPACE
365:
1.1 noro 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)
1.3 noro 389:
390: __STL_END_NAMESPACE
1.1 noro 391:
392: #ifdef __STL_USE_STD_ALLOCATORS
393:
394: __STL_BEGIN_NAMESPACE
395:
396: template <class _T>
397: struct _Alloc_traits<_T, gc_alloc >
398: {
399: static const bool _S_instanceless = true;
400: typedef simple_alloc<_T, gc_alloc > _Alloc_type;
401: typedef __allocator<_T, 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 _T>
417: struct _Alloc_traits<_T, single_client_gc_alloc >
418: {
419: static const bool _S_instanceless = true;
420: typedef simple_alloc<_T, single_client_gc_alloc > _Alloc_type;
421: typedef __allocator<_T, 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 _T>
437: struct _Alloc_traits<_T, traceable_alloc >
438: {
439: static const bool _S_instanceless = true;
440: typedef simple_alloc<_T, traceable_alloc > _Alloc_type;
441: typedef __allocator<_T, 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 _T>
457: struct _Alloc_traits<_T, single_client_traceable_alloc >
458: {
459: static const bool _S_instanceless = true;
460: typedef simple_alloc<_T, single_client_traceable_alloc > _Alloc_type;
461: typedef __allocator<_T, 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 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>