[BACK]Return to new_gc_alloc.h CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gc / include

Annotation of OpenXM_contrib/gc/include/new_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 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: #ifdef _SGI_SOURCE
        !           322:
        !           323: // We want to specialize simple_alloc so that it does the right thing
        !           324: // for all pointerfree types.  At the moment there is no portable way to
        !           325: // even approximate that.  The following approximation should work for
        !           326: // SGI compilers, and perhaps some others.
        !           327:
        !           328: # define __GC_SPECIALIZE(T,alloc) \
        !           329: class simple_alloc<T, alloc> { \
        !           330: public: \
        !           331:     static T *allocate(size_t n) \
        !           332:        { return 0 == n? 0 : \
        !           333:                         (T*) alloc::ptr_free_allocate(n * sizeof (T)); } \
        !           334:     static T *allocate(void) \
        !           335:        { return (T*) alloc::ptr_free_allocate(sizeof (T)); } \
        !           336:     static void deallocate(T *p, size_t n) \
        !           337:        { if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
        !           338:     static void deallocate(T *p) \
        !           339:        { alloc::ptr_free_deallocate(p, sizeof (T)); } \
        !           340: };
        !           341:
        !           342: __GC_SPECIALIZE(char, gc_alloc)
        !           343: __GC_SPECIALIZE(int, gc_alloc)
        !           344: __GC_SPECIALIZE(unsigned, gc_alloc)
        !           345: __GC_SPECIALIZE(float, gc_alloc)
        !           346: __GC_SPECIALIZE(double, gc_alloc)
        !           347:
        !           348: __GC_SPECIALIZE(char, traceable_alloc)
        !           349: __GC_SPECIALIZE(int, traceable_alloc)
        !           350: __GC_SPECIALIZE(unsigned, traceable_alloc)
        !           351: __GC_SPECIALIZE(float, traceable_alloc)
        !           352: __GC_SPECIALIZE(double, traceable_alloc)
        !           353:
        !           354: __GC_SPECIALIZE(char, single_client_gc_alloc)
        !           355: __GC_SPECIALIZE(int, single_client_gc_alloc)
        !           356: __GC_SPECIALIZE(unsigned, single_client_gc_alloc)
        !           357: __GC_SPECIALIZE(float, single_client_gc_alloc)
        !           358: __GC_SPECIALIZE(double, single_client_gc_alloc)
        !           359:
        !           360: __GC_SPECIALIZE(char, single_client_traceable_alloc)
        !           361: __GC_SPECIALIZE(int, single_client_traceable_alloc)
        !           362: __GC_SPECIALIZE(unsigned, single_client_traceable_alloc)
        !           363: __GC_SPECIALIZE(float, single_client_traceable_alloc)
        !           364: __GC_SPECIALIZE(double, single_client_traceable_alloc)
        !           365:
        !           366: #ifdef __STL_USE_STD_ALLOCATORS
        !           367:
        !           368: __STL_BEGIN_NAMESPACE
        !           369:
        !           370: template <class _T>
        !           371: struct _Alloc_traits<_T, gc_alloc >
        !           372: {
        !           373:   static const bool _S_instanceless = true;
        !           374:   typedef simple_alloc<_T, gc_alloc > _Alloc_type;
        !           375:   typedef __allocator<_T, gc_alloc > allocator_type;
        !           376: };
        !           377:
        !           378: inline bool operator==(const gc_alloc&,
        !           379:                        const gc_alloc&)
        !           380: {
        !           381:   return true;
        !           382: }
        !           383:
        !           384: inline bool operator!=(const gc_alloc&,
        !           385:                        const gc_alloc&)
        !           386: {
        !           387:   return false;
        !           388: }
        !           389:
        !           390: template <class _T>
        !           391: struct _Alloc_traits<_T, single_client_gc_alloc >
        !           392: {
        !           393:   static const bool _S_instanceless = true;
        !           394:   typedef simple_alloc<_T, single_client_gc_alloc > _Alloc_type;
        !           395:   typedef __allocator<_T, single_client_gc_alloc > allocator_type;
        !           396: };
        !           397:
        !           398: inline bool operator==(const single_client_gc_alloc&,
        !           399:                        const single_client_gc_alloc&)
        !           400: {
        !           401:   return true;
        !           402: }
        !           403:
        !           404: inline bool operator!=(const single_client_gc_alloc&,
        !           405:                        const single_client_gc_alloc&)
        !           406: {
        !           407:   return false;
        !           408: }
        !           409:
        !           410: template <class _T>
        !           411: struct _Alloc_traits<_T, traceable_alloc >
        !           412: {
        !           413:   static const bool _S_instanceless = true;
        !           414:   typedef simple_alloc<_T, traceable_alloc > _Alloc_type;
        !           415:   typedef __allocator<_T, traceable_alloc > allocator_type;
        !           416: };
        !           417:
        !           418: inline bool operator==(const traceable_alloc&,
        !           419:                        const traceable_alloc&)
        !           420: {
        !           421:   return true;
        !           422: }
        !           423:
        !           424: inline bool operator!=(const traceable_alloc&,
        !           425:                        const traceable_alloc&)
        !           426: {
        !           427:   return false;
        !           428: }
        !           429:
        !           430: template <class _T>
        !           431: struct _Alloc_traits<_T, single_client_traceable_alloc >
        !           432: {
        !           433:   static const bool _S_instanceless = true;
        !           434:   typedef simple_alloc<_T, single_client_traceable_alloc > _Alloc_type;
        !           435:   typedef __allocator<_T, single_client_traceable_alloc > allocator_type;
        !           436: };
        !           437:
        !           438: inline bool operator==(const single_client_traceable_alloc&,
        !           439:                        const single_client_traceable_alloc&)
        !           440: {
        !           441:   return true;
        !           442: }
        !           443:
        !           444: inline bool operator!=(const single_client_traceable_alloc&,
        !           445:                        const single_client_traceable_alloc&)
        !           446: {
        !           447:   return false;
        !           448: }
        !           449:
        !           450: __STL_END_NAMESPACE
        !           451:
        !           452: #endif /* __STL_USE_STD_ALLOCATORS */
        !           453:
        !           454: #endif /* _SGI_SOURCE */
        !           455:
        !           456: #endif /* GC_ALLOC_H */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>