~ubuntu-branches/ubuntu/quantal/libgc/quantal

« back to all changes in this revision

Viewing changes to include/gc_alloc.h

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger
  • Date: 2011-02-19 12:19:56 UTC
  • mfrom: (1.3.2 upstream) (0.1.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20110219121956-67rb69xlt5nud3v2
Tags: 1:7.1-5
Upload to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
50
 
template<class T, class alloc>
51
 
class simple_alloc {
52
 
 
53
 
public:
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
 
 
70
 
extern "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
 
 
85
 
enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
86
 
       GC_AUNCOLLECTABLE = 3 };
87
 
 
88
 
enum { GC_max_fast_bytes = 255 };
89
 
 
90
 
enum { GC_bytes_per_word = sizeof(char *) };
91
 
 
92
 
enum { GC_byte_alignment = 8 };
93
 
 
94
 
enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
95
 
 
96
 
inline 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.
101
 
inline 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.
107
 
inline 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
 
 
112
 
template <int dummy>
113
 
class GC_aux_template {
114
 
public:
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
 
 
133
 
template <int dummy>
134
 
size_t GC_aux_template<dummy>::GC_words_recently_allocd = 0;
135
 
 
136
 
template <int dummy>
137
 
size_t GC_aux_template<dummy>::GC_uncollectable_words_recently_allocd = 0;
138
 
 
139
 
template <int dummy>
140
 
size_t GC_aux_template<dummy>::GC_mem_recently_freed = 0;
141
 
 
142
 
template <int dummy>
143
 
size_t GC_aux_template<dummy>::GC_uncollectable_mem_recently_freed = 0;
144
 
 
145
 
template <int dummy>
146
 
void * 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
 
 
167
 
typedef 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.
173
 
template <int dummy>
174
 
class 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
 
 
238
 
typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
239
 
 
240
 
// Once more, for uncollectable objects.
241
 
template <int dummy>
242
 
class 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
 
 
304
 
typedef single_client_alloc_template<0> single_client_alloc;
305
 
 
306
 
template < int dummy >
307
 
class 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
 
 
316
 
typedef gc_alloc_template < 0 > gc_alloc;
317
 
 
318
 
template < int dummy >
319
 
class 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
 
 
328
 
typedef 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) \
338
 
class simple_alloc<T, alloc> { \
339
 
public: \
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 */