root/gc/include/gc_alloc.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. GC_obj_link
  2. GC_round_up
  3. GC_round_up_uncollectable
  4. GC_out_of_line_malloc

   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 */

/* [<][>][^][v][top][bottom][index][help] */