Annotation of OpenXM_contrib/gc/gc_alloc.h, Revision 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>