Annotation of OpenXM_contrib2/asir2000/gc5.3/include/new_gc_alloc.h, Revision 1.1
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: //
! 23: // This assumes the collector has been compiled with -DATOMIC_UNCOLLECTABLE
! 24: // and -DALL_INTERIOR_POINTERS. We also recommend
! 25: // -DREDIRECT_MALLOC=GC_uncollectable_malloc.
! 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: //
! 46:
! 47: #ifndef GC_ALLOC_H
! 48:
! 49: #include "gc.h"
! 50: #include <alloc.h>
! 51:
! 52: #define GC_ALLOC_H
! 53:
! 54: #include <stddef.h>
! 55: #include <string.h>
! 56:
! 57: // The following need to match collector data structures.
! 58: // We can't include gc_priv.h, since that pulls in way too much stuff.
! 59: // This should eventually be factored out into another include file.
! 60:
! 61: extern "C" {
! 62: extern void ** const GC_objfreelist_ptr;
! 63: extern void ** const GC_aobjfreelist_ptr;
! 64: extern void ** const GC_uobjfreelist_ptr;
! 65: extern void ** const GC_auobjfreelist_ptr;
! 66:
! 67: extern void GC_incr_words_allocd(size_t words);
! 68: extern void GC_incr_mem_freed(size_t words);
! 69:
! 70: extern char * GC_generic_malloc_words_small(size_t word, int kind);
! 71: }
! 72:
! 73: // Object kinds; must match PTRFREE, NORMAL, UNCOLLECTABLE, and
! 74: // AUNCOLLECTABLE in gc_priv.h.
! 75:
! 76: enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
! 77: GC_AUNCOLLECTABLE = 3 };
! 78:
! 79: enum { GC_max_fast_bytes = 255 };
! 80:
! 81: enum { GC_bytes_per_word = sizeof(char *) };
! 82:
! 83: enum { GC_byte_alignment = 8 };
! 84:
! 85: enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
! 86:
! 87: inline void * &GC_obj_link(void * p)
! 88: { return *(void **)p; }
! 89:
! 90: // Compute a number of words >= n+1 bytes.
! 91: // The +1 allows for pointers one past the end.
! 92: inline size_t GC_round_up(size_t n)
! 93: {
! 94: return ((n + GC_byte_alignment)/GC_byte_alignment)*GC_word_alignment;
! 95: }
! 96:
! 97: // The same but don't allow for extra byte.
! 98: inline size_t GC_round_up_uncollectable(size_t n)
! 99: {
! 100: return ((n + GC_byte_alignment - 1)/GC_byte_alignment)*GC_word_alignment;
! 101: }
! 102:
! 103: template <int dummy>
! 104: class GC_aux_template {
! 105: public:
! 106: // File local count of allocated words. Occasionally this is
! 107: // added into the global count. A separate count is necessary since the
! 108: // real one must be updated with a procedure call.
! 109: static size_t GC_words_recently_allocd;
! 110:
! 111: // Same for uncollectable mmory. Not yet reflected in either
! 112: // GC_words_recently_allocd or GC_non_gc_bytes.
! 113: static size_t GC_uncollectable_words_recently_allocd;
! 114:
! 115: // Similar counter for explicitly deallocated memory.
! 116: static size_t GC_mem_recently_freed;
! 117:
! 118: // Again for uncollectable memory.
! 119: static size_t GC_uncollectable_mem_recently_freed;
! 120:
! 121: static void * GC_out_of_line_malloc(size_t nwords, int kind);
! 122: };
! 123:
! 124: template <int dummy>
! 125: size_t GC_aux_template<dummy>::GC_words_recently_allocd = 0;
! 126:
! 127: template <int dummy>
! 128: size_t GC_aux_template<dummy>::GC_uncollectable_words_recently_allocd = 0;
! 129:
! 130: template <int dummy>
! 131: size_t GC_aux_template<dummy>::GC_mem_recently_freed = 0;
! 132:
! 133: template <int dummy>
! 134: size_t GC_aux_template<dummy>::GC_uncollectable_mem_recently_freed = 0;
! 135:
! 136: template <int dummy>
! 137: void * GC_aux_template<dummy>::GC_out_of_line_malloc(size_t nwords, int kind)
! 138: {
! 139: GC_words_recently_allocd += GC_uncollectable_words_recently_allocd;
! 140: GC_non_gc_bytes +=
! 141: GC_bytes_per_word * GC_uncollectable_words_recently_allocd;
! 142: GC_uncollectable_words_recently_allocd = 0;
! 143:
! 144: GC_mem_recently_freed += GC_uncollectable_mem_recently_freed;
! 145: GC_non_gc_bytes -=
! 146: GC_bytes_per_word * GC_uncollectable_mem_recently_freed;
! 147: GC_uncollectable_mem_recently_freed = 0;
! 148:
! 149: GC_incr_words_allocd(GC_words_recently_allocd);
! 150: GC_words_recently_allocd = 0;
! 151:
! 152: GC_incr_mem_freed(GC_mem_recently_freed);
! 153: GC_mem_recently_freed = 0;
! 154:
! 155: return GC_generic_malloc_words_small(nwords, kind);
! 156: }
! 157:
! 158: typedef GC_aux_template<0> GC_aux;
! 159:
! 160: // A fast, single-threaded, garbage-collected allocator
! 161: // We assume the first word will be immediately overwritten.
! 162: // In this version, deallocation is not a noop, and explicit
! 163: // deallocation is likely to help performance.
! 164: template <int dummy>
! 165: class single_client_gc_alloc_template {
! 166: public:
! 167: static void * allocate(size_t n)
! 168: {
! 169: size_t nwords = GC_round_up(n);
! 170: void ** flh;
! 171: void * op;
! 172:
! 173: if (n > GC_max_fast_bytes) return GC_malloc(n);
! 174: flh = GC_objfreelist_ptr + nwords;
! 175: if (0 == (op = *flh)) {
! 176: return GC_aux::GC_out_of_line_malloc(nwords, GC_NORMAL);
! 177: }
! 178: *flh = GC_obj_link(op);
! 179: GC_aux::GC_words_recently_allocd += nwords;
! 180: return op;
! 181: }
! 182: static void * ptr_free_allocate(size_t n)
! 183: {
! 184: size_t nwords = GC_round_up(n);
! 185: void ** flh;
! 186: void * op;
! 187:
! 188: if (n > GC_max_fast_bytes) return GC_malloc_atomic(n);
! 189: flh = GC_aobjfreelist_ptr + nwords;
! 190: if (0 == (op = *flh)) {
! 191: return GC_aux::GC_out_of_line_malloc(nwords, GC_PTRFREE);
! 192: }
! 193: *flh = GC_obj_link(op);
! 194: GC_aux::GC_words_recently_allocd += nwords;
! 195: return op;
! 196: }
! 197: static void deallocate(void *p, size_t n)
! 198: {
! 199: size_t nwords = GC_round_up(n);
! 200: void ** flh;
! 201:
! 202: if (n > GC_max_fast_bytes) {
! 203: GC_free(p);
! 204: } else {
! 205: flh = GC_objfreelist_ptr + nwords;
! 206: GC_obj_link(p) = *flh;
! 207: memset((char *)p + GC_bytes_per_word, 0,
! 208: GC_bytes_per_word * (nwords - 1));
! 209: *flh = p;
! 210: GC_aux::GC_mem_recently_freed += nwords;
! 211: }
! 212: }
! 213: static void ptr_free_deallocate(void *p, size_t n)
! 214: {
! 215: size_t nwords = GC_round_up(n);
! 216: void ** flh;
! 217:
! 218: if (n > GC_max_fast_bytes) {
! 219: GC_free(p);
! 220: } else {
! 221: flh = GC_aobjfreelist_ptr + nwords;
! 222: GC_obj_link(p) = *flh;
! 223: *flh = p;
! 224: GC_aux::GC_mem_recently_freed += nwords;
! 225: }
! 226: }
! 227: };
! 228:
! 229: typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
! 230:
! 231: // Once more, for uncollectable objects.
! 232: template <int dummy>
! 233: class single_client_traceable_alloc_template {
! 234: public:
! 235: static void * allocate(size_t n)
! 236: {
! 237: size_t nwords = GC_round_up_uncollectable(n);
! 238: void ** flh;
! 239: void * op;
! 240:
! 241: if (n > GC_max_fast_bytes) return GC_malloc_uncollectable(n);
! 242: flh = GC_uobjfreelist_ptr + nwords;
! 243: if (0 == (op = *flh)) {
! 244: return GC_aux::GC_out_of_line_malloc(nwords, GC_UNCOLLECTABLE);
! 245: }
! 246: *flh = GC_obj_link(op);
! 247: GC_aux::GC_uncollectable_words_recently_allocd += nwords;
! 248: return op;
! 249: }
! 250: static void * ptr_free_allocate(size_t n)
! 251: {
! 252: size_t nwords = GC_round_up_uncollectable(n);
! 253: void ** flh;
! 254: void * op;
! 255:
! 256: if (n > GC_max_fast_bytes) return GC_malloc_atomic_uncollectable(n);
! 257: flh = GC_auobjfreelist_ptr + nwords;
! 258: if (0 == (op = *flh)) {
! 259: return GC_aux::GC_out_of_line_malloc(nwords, GC_AUNCOLLECTABLE);
! 260: }
! 261: *flh = GC_obj_link(op);
! 262: GC_aux::GC_uncollectable_words_recently_allocd += nwords;
! 263: return op;
! 264: }
! 265: static void deallocate(void *p, size_t n)
! 266: {
! 267: size_t nwords = GC_round_up_uncollectable(n);
! 268: void ** flh;
! 269:
! 270: if (n > GC_max_fast_bytes) {
! 271: GC_free(p);
! 272: } else {
! 273: flh = GC_uobjfreelist_ptr + nwords;
! 274: GC_obj_link(p) = *flh;
! 275: *flh = p;
! 276: GC_aux::GC_uncollectable_mem_recently_freed += nwords;
! 277: }
! 278: }
! 279: static void ptr_free_deallocate(void *p, size_t n)
! 280: {
! 281: size_t nwords = GC_round_up_uncollectable(n);
! 282: void ** flh;
! 283:
! 284: if (n > GC_max_fast_bytes) {
! 285: GC_free(p);
! 286: } else {
! 287: flh = GC_auobjfreelist_ptr + nwords;
! 288: GC_obj_link(p) = *flh;
! 289: *flh = p;
! 290: GC_aux::GC_uncollectable_mem_recently_freed += nwords;
! 291: }
! 292: }
! 293: };
! 294:
! 295: typedef single_client_traceable_alloc_template<0> single_client_traceable_alloc;
! 296:
! 297: template < int dummy >
! 298: class gc_alloc_template {
! 299: public:
! 300: static void * allocate(size_t n) { return GC_malloc(n); }
! 301: static void * ptr_free_allocate(size_t n)
! 302: { return GC_malloc_atomic(n); }
! 303: static void deallocate(void *, size_t) { }
! 304: static void ptr_free_deallocate(void *, size_t) { }
! 305: };
! 306:
! 307: typedef gc_alloc_template < 0 > gc_alloc;
! 308:
! 309: template < int dummy >
! 310: class traceable_alloc_template {
! 311: public:
! 312: static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
! 313: static void * ptr_free_allocate(size_t n)
! 314: { return GC_malloc_atomic_uncollectable(n); }
! 315: static void deallocate(void *p, size_t) { GC_free(p); }
! 316: static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
! 317: };
! 318:
! 319: typedef traceable_alloc_template < 0 > traceable_alloc;
! 320:
! 321: // We want to specialize simple_alloc so that it does the right thing
! 322: // for all pointerfree types. At the moment there is no portable way to
! 323: // even approximate that. The following approximation should work for
! 324: // SGI compilers, and recent versions of g++.
! 325:
! 326: # define __GC_SPECIALIZE(T,alloc) \
! 327: class simple_alloc<T, alloc> { \
! 328: public: \
! 329: static T *allocate(size_t n) \
! 330: { return 0 == n? 0 : \
! 331: (T*) alloc::ptr_free_allocate(n * sizeof (T)); } \
! 332: static T *allocate(void) \
! 333: { return (T*) alloc::ptr_free_allocate(sizeof (T)); } \
! 334: static void deallocate(T *p, size_t n) \
! 335: { if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
! 336: static void deallocate(T *p) \
! 337: { alloc::ptr_free_deallocate(p, sizeof (T)); } \
! 338: };
! 339:
! 340: __GC_SPECIALIZE(char, gc_alloc)
! 341: __GC_SPECIALIZE(int, gc_alloc)
! 342: __GC_SPECIALIZE(unsigned, gc_alloc)
! 343: __GC_SPECIALIZE(float, gc_alloc)
! 344: __GC_SPECIALIZE(double, gc_alloc)
! 345:
! 346: __GC_SPECIALIZE(char, traceable_alloc)
! 347: __GC_SPECIALIZE(int, traceable_alloc)
! 348: __GC_SPECIALIZE(unsigned, traceable_alloc)
! 349: __GC_SPECIALIZE(float, traceable_alloc)
! 350: __GC_SPECIALIZE(double, traceable_alloc)
! 351:
! 352: __GC_SPECIALIZE(char, single_client_gc_alloc)
! 353: __GC_SPECIALIZE(int, single_client_gc_alloc)
! 354: __GC_SPECIALIZE(unsigned, single_client_gc_alloc)
! 355: __GC_SPECIALIZE(float, single_client_gc_alloc)
! 356: __GC_SPECIALIZE(double, single_client_gc_alloc)
! 357:
! 358: __GC_SPECIALIZE(char, single_client_traceable_alloc)
! 359: __GC_SPECIALIZE(int, single_client_traceable_alloc)
! 360: __GC_SPECIALIZE(unsigned, single_client_traceable_alloc)
! 361: __GC_SPECIALIZE(float, single_client_traceable_alloc)
! 362: __GC_SPECIALIZE(double, single_client_traceable_alloc)
! 363:
! 364: #ifdef __STL_USE_STD_ALLOCATORS
! 365:
! 366: __STL_BEGIN_NAMESPACE
! 367:
! 368: template <class _T>
! 369: struct _Alloc_traits<_T, gc_alloc >
! 370: {
! 371: static const bool _S_instanceless = true;
! 372: typedef simple_alloc<_T, gc_alloc > _Alloc_type;
! 373: typedef __allocator<_T, gc_alloc > allocator_type;
! 374: };
! 375:
! 376: inline bool operator==(const gc_alloc&,
! 377: const gc_alloc&)
! 378: {
! 379: return true;
! 380: }
! 381:
! 382: inline bool operator!=(const gc_alloc&,
! 383: const gc_alloc&)
! 384: {
! 385: return false;
! 386: }
! 387:
! 388: template <class _T>
! 389: struct _Alloc_traits<_T, single_client_gc_alloc >
! 390: {
! 391: static const bool _S_instanceless = true;
! 392: typedef simple_alloc<_T, single_client_gc_alloc > _Alloc_type;
! 393: typedef __allocator<_T, single_client_gc_alloc > allocator_type;
! 394: };
! 395:
! 396: inline bool operator==(const single_client_gc_alloc&,
! 397: const single_client_gc_alloc&)
! 398: {
! 399: return true;
! 400: }
! 401:
! 402: inline bool operator!=(const single_client_gc_alloc&,
! 403: const single_client_gc_alloc&)
! 404: {
! 405: return false;
! 406: }
! 407:
! 408: template <class _T>
! 409: struct _Alloc_traits<_T, traceable_alloc >
! 410: {
! 411: static const bool _S_instanceless = true;
! 412: typedef simple_alloc<_T, traceable_alloc > _Alloc_type;
! 413: typedef __allocator<_T, traceable_alloc > allocator_type;
! 414: };
! 415:
! 416: inline bool operator==(const traceable_alloc&,
! 417: const traceable_alloc&)
! 418: {
! 419: return true;
! 420: }
! 421:
! 422: inline bool operator!=(const traceable_alloc&,
! 423: const traceable_alloc&)
! 424: {
! 425: return false;
! 426: }
! 427:
! 428: template <class _T>
! 429: struct _Alloc_traits<_T, single_client_traceable_alloc >
! 430: {
! 431: static const bool _S_instanceless = true;
! 432: typedef simple_alloc<_T, single_client_traceable_alloc > _Alloc_type;
! 433: typedef __allocator<_T, single_client_traceable_alloc > allocator_type;
! 434: };
! 435:
! 436: inline bool operator==(const single_client_traceable_alloc&,
! 437: const single_client_traceable_alloc&)
! 438: {
! 439: return true;
! 440: }
! 441:
! 442: inline bool operator!=(const single_client_traceable_alloc&,
! 443: const single_client_traceable_alloc&)
! 444: {
! 445: return false;
! 446: }
! 447:
! 448: __STL_END_NAMESPACE
! 449:
! 450: #endif /* __STL_USE_STD_ALLOCATORS */
! 451:
! 452: #endif /* GC_ALLOC_H */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>