source: trunk/gcc/boehm-gc/include/gc_alloc.h

Last change on this file was 2, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 11.4 KB
Line 
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. This assumes SGI STL version < 3.0.
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// This code assumes that the collector itself has been compiled with a
29// compiler that defines __STDC__ .
30//
31
32#include "gc.h"
33
34#ifndef GC_ALLOC_H
35
36#define GC_ALLOC_H
37#define __ALLOC_H // Prevent inclusion of the default version. Ugly.
38#define __SGI_STL_ALLOC_H
39#define __SGI_STL_INTERNAL_ALLOC_H
40
41#ifndef __ALLOC
42# define __ALLOC alloc
43#endif
44
45#include <stddef.h>
46#include <string.h>
47
48// The following is just replicated from the conventional SGI alloc.h:
49
50template<class T, class alloc>
51class simple_alloc {
52
53public:
54 static T *allocate(size_t n)
55 { return 0 == n? 0 : (T*) alloc::allocate(n * sizeof (T)); }
56 static T *allocate(void)
57 { return (T*) alloc::allocate(sizeof (T)); }
58 static void deallocate(T *p, size_t n)
59 { if (0 != n) alloc::deallocate(p, n * sizeof (T)); }
60 static void deallocate(T *p)
61 { alloc::deallocate(p, sizeof (T)); }
62};
63
64#include "gc.h"
65
66// The following need to match collector data structures.
67// We can't include gc_priv.h, since that pulls in way too much stuff.
68// This should eventually be factored out into another include file.
69
70extern "C" {
71 extern void ** const GC_objfreelist_ptr;
72 extern void ** const GC_aobjfreelist_ptr;
73 extern void ** const GC_uobjfreelist_ptr;
74 extern void ** const GC_auobjfreelist_ptr;
75
76 extern void GC_incr_words_allocd(size_t words);
77 extern void GC_incr_mem_freed(size_t words);
78
79 extern char * GC_generic_malloc_words_small(size_t word, int kind);
80}
81
82// Object kinds; must match PTRFREE, NORMAL, UNCOLLECTABLE, and
83// AUNCOLLECTABLE in gc_priv.h.
84
85enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
86 GC_AUNCOLLECTABLE = 3 };
87
88enum { GC_max_fast_bytes = 255 };
89
90enum { GC_bytes_per_word = sizeof(char *) };
91
92enum { GC_byte_alignment = 8 };
93
94enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
95
96inline void * &GC_obj_link(void * p)
97{ return *(void **)p; }
98
99// Compute a number of words >= n+1 bytes.
100// The +1 allows for pointers one past the end.
101inline size_t GC_round_up(size_t n)
102{
103 return ((n + GC_byte_alignment)/GC_byte_alignment)*GC_word_alignment;
104}
105
106// The same but don't allow for extra byte.
107inline size_t GC_round_up_uncollectable(size_t n)
108{
109 return ((n + GC_byte_alignment - 1)/GC_byte_alignment)*GC_word_alignment;
110}
111
112template <int dummy>
113class GC_aux_template {
114public:
115 // File local count of allocated words. Occasionally this is
116 // added into the global count. A separate count is necessary since the
117 // real one must be updated with a procedure call.
118 static size_t GC_words_recently_allocd;
119
120 // Same for uncollectable mmory. Not yet reflected in either
121 // GC_words_recently_allocd or GC_non_gc_bytes.
122 static size_t GC_uncollectable_words_recently_allocd;
123
124 // Similar counter for explicitly deallocated memory.
125 static size_t GC_mem_recently_freed;
126
127 // Again for uncollectable memory.
128 static size_t GC_uncollectable_mem_recently_freed;
129
130 static void * GC_out_of_line_malloc(size_t nwords, int kind);
131};
132
133template <int dummy>
134size_t GC_aux_template<dummy>::GC_words_recently_allocd = 0;
135
136template <int dummy>
137size_t GC_aux_template<dummy>::GC_uncollectable_words_recently_allocd = 0;
138
139template <int dummy>
140size_t GC_aux_template<dummy>::GC_mem_recently_freed = 0;
141
142template <int dummy>
143size_t GC_aux_template<dummy>::GC_uncollectable_mem_recently_freed = 0;
144
145template <int dummy>
146void * GC_aux_template<dummy>::GC_out_of_line_malloc(size_t nwords, int kind)
147{
148 GC_words_recently_allocd += GC_uncollectable_words_recently_allocd;
149 GC_non_gc_bytes +=
150 GC_bytes_per_word * GC_uncollectable_words_recently_allocd;
151 GC_uncollectable_words_recently_allocd = 0;
152
153 GC_mem_recently_freed += GC_uncollectable_mem_recently_freed;
154 GC_non_gc_bytes -=
155 GC_bytes_per_word * GC_uncollectable_mem_recently_freed;
156 GC_uncollectable_mem_recently_freed = 0;
157
158 GC_incr_words_allocd(GC_words_recently_allocd);
159 GC_words_recently_allocd = 0;
160
161 GC_incr_mem_freed(GC_mem_recently_freed);
162 GC_mem_recently_freed = 0;
163
164 return GC_generic_malloc_words_small(nwords, kind);
165}
166
167typedef GC_aux_template<0> GC_aux;
168
169// A fast, single-threaded, garbage-collected allocator
170// We assume the first word will be immediately overwritten.
171// In this version, deallocation is not a noop, and explicit
172// deallocation is likely to help performance.
173template <int dummy>
174class single_client_gc_alloc_template {
175 public:
176 static void * allocate(size_t n)
177 {
178 size_t nwords = GC_round_up(n);
179 void ** flh;
180 void * op;
181
182 if (n > GC_max_fast_bytes) return GC_malloc(n);
183 flh = GC_objfreelist_ptr + nwords;
184 if (0 == (op = *flh)) {
185 return GC_aux::GC_out_of_line_malloc(nwords, GC_NORMAL);
186 }
187 *flh = GC_obj_link(op);
188 GC_aux::GC_words_recently_allocd += nwords;
189 return op;
190 }
191 static void * ptr_free_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_atomic(n);
198 flh = GC_aobjfreelist_ptr + nwords;
199 if (0 == (op = *flh)) {
200 return GC_aux::GC_out_of_line_malloc(nwords, GC_PTRFREE);
201 }
202 *flh = GC_obj_link(op);
203 GC_aux::GC_words_recently_allocd += nwords;
204 return op;
205 }
206 static void deallocate(void *p, size_t n)
207 {
208 size_t nwords = GC_round_up(n);
209 void ** flh;
210
211 if (n > GC_max_fast_bytes) {
212 GC_free(p);
213 } else {
214 flh = GC_objfreelist_ptr + nwords;
215 GC_obj_link(p) = *flh;
216 memset((char *)p + GC_bytes_per_word, 0,
217 GC_bytes_per_word * (nwords - 1));
218 *flh = p;
219 GC_aux::GC_mem_recently_freed += nwords;
220 }
221 }
222 static void ptr_free_deallocate(void *p, size_t n)
223 {
224 size_t nwords = GC_round_up(n);
225 void ** flh;
226
227 if (n > GC_max_fast_bytes) {
228 GC_free(p);
229 } else {
230 flh = GC_aobjfreelist_ptr + nwords;
231 GC_obj_link(p) = *flh;
232 *flh = p;
233 GC_aux::GC_mem_recently_freed += nwords;
234 }
235 }
236};
237
238typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
239
240// Once more, for uncollectable objects.
241template <int dummy>
242class single_client_alloc_template {
243 public:
244 static void * allocate(size_t n)
245 {
246 size_t nwords = GC_round_up_uncollectable(n);
247 void ** flh;
248 void * op;
249
250 if (n > GC_max_fast_bytes) return GC_malloc_uncollectable(n);
251 flh = GC_uobjfreelist_ptr + nwords;
252 if (0 == (op = *flh)) {
253 return GC_aux::GC_out_of_line_malloc(nwords, GC_UNCOLLECTABLE);
254 }
255 *flh = GC_obj_link(op);
256 GC_aux::GC_uncollectable_words_recently_allocd += nwords;
257 return op;
258 }
259 static void * ptr_free_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_atomic_uncollectable(n);
266 flh = GC_auobjfreelist_ptr + nwords;
267 if (0 == (op = *flh)) {
268 return GC_aux::GC_out_of_line_malloc(nwords, GC_AUNCOLLECTABLE);
269 }
270 *flh = GC_obj_link(op);
271 GC_aux::GC_uncollectable_words_recently_allocd += nwords;
272 return op;
273 }
274 static void deallocate(void *p, size_t n)
275 {
276 size_t nwords = GC_round_up_uncollectable(n);
277 void ** flh;
278
279 if (n > GC_max_fast_bytes) {
280 GC_free(p);
281 } else {
282 flh = GC_uobjfreelist_ptr + nwords;
283 GC_obj_link(p) = *flh;
284 *flh = p;
285 GC_aux::GC_uncollectable_mem_recently_freed += nwords;
286 }
287 }
288 static void ptr_free_deallocate(void *p, size_t n)
289 {
290 size_t nwords = GC_round_up_uncollectable(n);
291 void ** flh;
292
293 if (n > GC_max_fast_bytes) {
294 GC_free(p);
295 } else {
296 flh = GC_auobjfreelist_ptr + nwords;
297 GC_obj_link(p) = *flh;
298 *flh = p;
299 GC_aux::GC_uncollectable_mem_recently_freed += nwords;
300 }
301 }
302};
303
304typedef single_client_alloc_template<0> single_client_alloc;
305
306template < int dummy >
307class gc_alloc_template {
308 public:
309 static void * allocate(size_t n) { return GC_malloc(n); }
310 static void * ptr_free_allocate(size_t n)
311 { return GC_malloc_atomic(n); }
312 static void deallocate(void *, size_t) { }
313 static void ptr_free_deallocate(void *, size_t) { }
314};
315
316typedef gc_alloc_template < 0 > gc_alloc;
317
318template < int dummy >
319class alloc_template {
320 public:
321 static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
322 static void * ptr_free_allocate(size_t n)
323 { return GC_malloc_atomic_uncollectable(n); }
324 static void deallocate(void *p, size_t) { GC_free(p); }
325 static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
326};
327
328typedef alloc_template < 0 > alloc;
329
330#ifdef _SGI_SOURCE
331
332// We want to specialize simple_alloc so that it does the right thing
333// for all pointerfree types. At the moment there is no portable way to
334// even approximate that. The following approximation should work for
335// SGI compilers, and perhaps some others.
336
337# define __GC_SPECIALIZE(T,alloc) \
338class simple_alloc<T, alloc> { \
339public: \
340 static T *allocate(size_t n) \
341 { return 0 == n? 0 : \
342 (T*) alloc::ptr_free_allocate(n * sizeof (T)); } \
343 static T *allocate(void) \
344 { return (T*) alloc::ptr_free_allocate(sizeof (T)); } \
345 static void deallocate(T *p, size_t n) \
346 { if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
347 static void deallocate(T *p) \
348 { alloc::ptr_free_deallocate(p, sizeof (T)); } \
349};
350
351__GC_SPECIALIZE(char, gc_alloc)
352__GC_SPECIALIZE(int, gc_alloc)
353__GC_SPECIALIZE(unsigned, gc_alloc)
354__GC_SPECIALIZE(float, gc_alloc)
355__GC_SPECIALIZE(double, gc_alloc)
356
357__GC_SPECIALIZE(char, alloc)
358__GC_SPECIALIZE(int, alloc)
359__GC_SPECIALIZE(unsigned, alloc)
360__GC_SPECIALIZE(float, alloc)
361__GC_SPECIALIZE(double, alloc)
362
363__GC_SPECIALIZE(char, single_client_gc_alloc)
364__GC_SPECIALIZE(int, single_client_gc_alloc)
365__GC_SPECIALIZE(unsigned, single_client_gc_alloc)
366__GC_SPECIALIZE(float, single_client_gc_alloc)
367__GC_SPECIALIZE(double, single_client_gc_alloc)
368
369__GC_SPECIALIZE(char, single_client_alloc)
370__GC_SPECIALIZE(int, single_client_alloc)
371__GC_SPECIALIZE(unsigned, single_client_alloc)
372__GC_SPECIALIZE(float, single_client_alloc)
373__GC_SPECIALIZE(double, single_client_alloc)
374
375#ifdef __STL_USE_STD_ALLOCATORS
376
377???copy stuff from stl_alloc.h or remove it to a different file ???
378
379#endif /* __STL_USE_STD_ALLOCATORS */
380
381#endif /* _SGI_SOURCE */
382
383#endif /* GC_ALLOC_H */
Note: See TracBrowser for help on using the repository browser.