Annotation of OpenXM_contrib/gc/gc_alloc.h, Revision 1.1.1.1
1.1 maekawa 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 C++ header file that is intended to replace the SGI STL
16: // alloc.h.
17: //
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.
21: //
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.
24: //
25: // This uses template classes with static members, and hence does not work
26: // with g++ 2.7.2 and earlier.
27: //
28:
29: #include "gc.h"
30:
31: #ifndef GC_ALLOC_H
32:
33: #define GC_ALLOC_H
34: #define __ALLOC_H // Prevent inclusion of the default version. Ugly.
35: #define __SGI_STL_ALLOC_H
36: #define __SGI_STL_INTERNAL_ALLOC_H
37:
38: #ifndef __ALLOC
39: # define __ALLOC alloc
40: #endif
41:
42: #include <stddef.h>
43: #include <string.h>
44:
45: // The following is just replicated from the conventional SGI alloc.h:
46:
47: template<class T, class alloc>
48: class simple_alloc {
49:
50: public:
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)); }
59: };
60:
61: #include "gc.h"
62:
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.
66:
67: extern "C" {
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;
72:
73: extern void GC_incr_words_allocd(size_t words);
74: extern void GC_incr_mem_freed(size_t words);
75:
76: extern char * GC_generic_malloc_words_small(size_t word, int kind);
77: }
78:
79: // Object kinds; must match PTRFREE, NORMAL, UNCOLLECTABLE, and
80: // AUNCOLLECTABLE in gc_priv.h.
81:
82: enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
83: GC_AUNCOLLECTABLE = 3 };
84:
85: enum { GC_max_fast_bytes = 255 };
86:
87: enum { GC_bytes_per_word = sizeof(char *) };
88:
89: enum { GC_byte_alignment = 8 };
90:
91: enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
92:
93: inline void * &GC_obj_link(void * p)
94: { return *(void **)p; }
95:
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)
99: {
100: return ((n + GC_byte_alignment)/GC_byte_alignment)*GC_word_alignment;
101: }
102:
103: // The same but don't allow for extra byte.
104: inline size_t GC_round_up_uncollectable(size_t n)
105: {
106: return ((n + GC_byte_alignment - 1)/GC_byte_alignment)*GC_word_alignment;
107: }
108:
109: template <int dummy>
110: class GC_aux_template {
111: public:
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;
116:
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;
120:
121: // Similar counter for explicitly deallocated memory.
122: static size_t GC_mem_recently_freed;
123:
124: // Again for uncollectable memory.
125: static size_t GC_uncollectable_mem_recently_freed;
126:
127: static void * GC_out_of_line_malloc(size_t nwords, int kind);
128: };
129:
130: template <int dummy>
131: size_t GC_aux_template<dummy>::GC_words_recently_allocd = 0;
132:
133: template <int dummy>
134: size_t GC_aux_template<dummy>::GC_uncollectable_words_recently_allocd = 0;
135:
136: template <int dummy>
137: size_t GC_aux_template<dummy>::GC_mem_recently_freed = 0;
138:
139: template <int dummy>
140: size_t GC_aux_template<dummy>::GC_uncollectable_mem_recently_freed = 0;
141:
142: template <int dummy>
143: void * GC_aux_template<dummy>::GC_out_of_line_malloc(size_t nwords, int kind)
144: {
145: GC_words_recently_allocd += GC_uncollectable_words_recently_allocd;
146: GC_non_gc_bytes +=
147: GC_bytes_per_word * GC_uncollectable_words_recently_allocd;
148: GC_uncollectable_words_recently_allocd = 0;
149:
150: GC_mem_recently_freed += GC_uncollectable_mem_recently_freed;
151: GC_non_gc_bytes -=
152: GC_bytes_per_word * GC_uncollectable_mem_recently_freed;
153: GC_uncollectable_mem_recently_freed = 0;
154:
155: GC_incr_words_allocd(GC_words_recently_allocd);
156: GC_words_recently_allocd = 0;
157:
158: GC_incr_mem_freed(GC_mem_recently_freed);
159: GC_mem_recently_freed = 0;
160:
161: return GC_generic_malloc_words_small(nwords, kind);
162: }
163:
164: typedef GC_aux_template<0> GC_aux;
165:
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.
170: template <int dummy>
171: class single_client_gc_alloc_template {
172: public:
173: static void * allocate(size_t n)
174: {
175: size_t nwords = GC_round_up(n);
176: void ** flh;
177: void * op;
178:
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);
183: }
184: *flh = GC_obj_link(op);
185: GC_aux::GC_words_recently_allocd += nwords;
186: return op;
187: }
188: static void * ptr_free_allocate(size_t n)
189: {
190: size_t nwords = GC_round_up(n);
191: void ** flh;
192: void * op;
193:
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);
198: }
199: *flh = GC_obj_link(op);
200: GC_aux::GC_words_recently_allocd += nwords;
201: return op;
202: }
203: static void deallocate(void *p, size_t n)
204: {
205: size_t nwords = GC_round_up(n);
206: void ** flh;
207:
208: if (n > GC_max_fast_bytes) {
209: GC_free(p);
210: } else {
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));
215: *flh = p;
216: GC_aux::GC_mem_recently_freed += nwords;
217: }
218: }
219: static void ptr_free_deallocate(void *p, size_t n)
220: {
221: size_t nwords = GC_round_up(n);
222: void ** flh;
223:
224: if (n > GC_max_fast_bytes) {
225: GC_free(p);
226: } else {
227: flh = GC_aobjfreelist_ptr + nwords;
228: GC_obj_link(p) = *flh;
229: *flh = p;
230: GC_aux::GC_mem_recently_freed += nwords;
231: }
232: }
233: };
234:
235: typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
236:
237: // Once more, for uncollectable objects.
238: template <int dummy>
239: class single_client_alloc_template {
240: public:
241: static void * allocate(size_t n)
242: {
243: size_t nwords = GC_round_up_uncollectable(n);
244: void ** flh;
245: void * op;
246:
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);
251: }
252: *flh = GC_obj_link(op);
253: GC_aux::GC_uncollectable_words_recently_allocd += nwords;
254: return op;
255: }
256: static void * ptr_free_allocate(size_t n)
257: {
258: size_t nwords = GC_round_up_uncollectable(n);
259: void ** flh;
260: void * op;
261:
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);
266: }
267: *flh = GC_obj_link(op);
268: GC_aux::GC_uncollectable_words_recently_allocd += nwords;
269: return op;
270: }
271: static void deallocate(void *p, size_t n)
272: {
273: size_t nwords = GC_round_up_uncollectable(n);
274: void ** flh;
275:
276: if (n > GC_max_fast_bytes) {
277: GC_free(p);
278: } else {
279: flh = GC_uobjfreelist_ptr + nwords;
280: GC_obj_link(p) = *flh;
281: *flh = p;
282: GC_aux::GC_uncollectable_mem_recently_freed += nwords;
283: }
284: }
285: static void ptr_free_deallocate(void *p, size_t n)
286: {
287: size_t nwords = GC_round_up_uncollectable(n);
288: void ** flh;
289:
290: if (n > GC_max_fast_bytes) {
291: GC_free(p);
292: } else {
293: flh = GC_auobjfreelist_ptr + nwords;
294: GC_obj_link(p) = *flh;
295: *flh = p;
296: GC_aux::GC_uncollectable_mem_recently_freed += nwords;
297: }
298: }
299: };
300:
301: typedef single_client_alloc_template<0> single_client_alloc;
302:
303: template < int dummy >
304: class gc_alloc_template {
305: public:
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) { }
311: };
312:
313: typedef gc_alloc_template < 0 > gc_alloc;
314:
315: template < int dummy >
316: class alloc_template {
317: public:
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); }
323: };
324:
325: typedef alloc_template < 0 > alloc;
326:
327: #ifdef _SGI_SOURCE
328:
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.
333:
334: # define __GC_SPECIALIZE(T,alloc) \
335: class simple_alloc<T, alloc> { \
336: public: \
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)); } \
346: };
347:
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)
353:
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)
359:
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)
365:
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)
371:
372: #ifdef __STL_USE_STD_ALLOCATORS
373:
374: ???copy stuff from stl_alloc.h or remove it to a different file ???
375:
376: #endif /* __STL_USE_STD_ALLOCATORS */
377:
378: #endif /* _SGI_SOURCE */
379:
380: #endif /* GC_ALLOC_H */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>