#include "gc.h"
#ifndef GC_ALLOC_H
#define GC_ALLOC_H
#define __ALLOC_H // Prevent inclusion of the default version. Ugly.
#define __SGI_STL_ALLOC_H
#define __SGI_STL_INTERNAL_ALLOC_H
#ifndef __ALLOC
# define __ALLOC alloc
#endif
#include <stddef.h>
#include <string.h>
template<class T, class alloc>
class simple_alloc {
public:
static T *allocate(size_t n)
{ return 0 == n? 0 : (T*) alloc::allocate(n * sizeof (T)); }
static T *allocate(void)
{ return (T*) alloc::allocate(sizeof (T)); }
static void deallocate(T *p, size_t n)
{ if (0 != n) alloc::deallocate(p, n * sizeof (T)); }
static void deallocate(T *p)
{ alloc::deallocate(p, sizeof (T)); }
};
#include "gc.h"
extern "C" {
extern void ** const GC_objfreelist_ptr;
extern void ** const GC_aobjfreelist_ptr;
extern void ** const GC_uobjfreelist_ptr;
extern void ** const GC_auobjfreelist_ptr;
extern void GC_incr_words_allocd(size_t words);
extern void GC_incr_mem_freed(size_t words);
extern char * GC_generic_malloc_words_small(size_t word, int kind);
}
enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
GC_AUNCOLLECTABLE = 3 };
enum { GC_max_fast_bytes = 255 };
enum { GC_bytes_per_word = sizeof(char *) };
enum { GC_byte_alignment = 8 };
enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
inline void * &GC_obj_link(void * p)
{ return *(void **)p; }
inline size_t GC_round_up(size_t n)
{
return ((n + GC_byte_alignment)/GC_byte_alignment)*GC_word_alignment;
}
inline size_t GC_round_up_uncollectable(size_t n)
{
return ((n + GC_byte_alignment - 1)/GC_byte_alignment)*GC_word_alignment;
}
template <int dummy>
class GC_aux_template {
public:
static size_t GC_words_recently_allocd;
static size_t GC_uncollectable_words_recently_allocd;
static size_t GC_mem_recently_freed;
static size_t GC_uncollectable_mem_recently_freed;
static void * GC_out_of_line_malloc(size_t nwords, int kind);
};
template <int dummy>
size_t GC_aux_template<dummy>::GC_words_recently_allocd = 0;
template <int dummy>
size_t GC_aux_template<dummy>::GC_uncollectable_words_recently_allocd = 0;
template <int dummy>
size_t GC_aux_template<dummy>::GC_mem_recently_freed = 0;
template <int dummy>
size_t GC_aux_template<dummy>::GC_uncollectable_mem_recently_freed = 0;
template <int dummy>
void * GC_aux_template<dummy>::GC_out_of_line_malloc(size_t nwords, int kind)
{
GC_words_recently_allocd += GC_uncollectable_words_recently_allocd;
GC_non_gc_bytes +=
GC_bytes_per_word * GC_uncollectable_words_recently_allocd;
GC_uncollectable_words_recently_allocd = 0;
GC_mem_recently_freed += GC_uncollectable_mem_recently_freed;
GC_non_gc_bytes -=
GC_bytes_per_word * GC_uncollectable_mem_recently_freed;
GC_uncollectable_mem_recently_freed = 0;
GC_incr_words_allocd(GC_words_recently_allocd);
GC_words_recently_allocd = 0;
GC_incr_mem_freed(GC_mem_recently_freed);
GC_mem_recently_freed = 0;
return GC_generic_malloc_words_small(nwords, kind);
}
typedef GC_aux_template<0> GC_aux;
template <int dummy>
class single_client_gc_alloc_template {
public:
static void * allocate(size_t n)
{
size_t nwords = GC_round_up(n);
void ** flh;
void * op;
if (n > GC_max_fast_bytes) return GC_malloc(n);
flh = GC_objfreelist_ptr + nwords;
if (0 == (op = *flh)) {
return GC_aux::GC_out_of_line_malloc(nwords, GC_NORMAL);
}
*flh = GC_obj_link(op);
GC_aux::GC_words_recently_allocd += nwords;
return op;
}
static void * ptr_free_allocate(size_t n)
{
size_t nwords = GC_round_up(n);
void ** flh;
void * op;
if (n > GC_max_fast_bytes) return GC_malloc_atomic(n);
flh = GC_aobjfreelist_ptr + nwords;
if (0 == (op = *flh)) {
return GC_aux::GC_out_of_line_malloc(nwords, GC_PTRFREE);
}
*flh = GC_obj_link(op);
GC_aux::GC_words_recently_allocd += nwords;
return op;
}
static void deallocate(void *p, size_t n)
{
size_t nwords = GC_round_up(n);
void ** flh;
if (n > GC_max_fast_bytes) {
GC_free(p);
} else {
flh = GC_objfreelist_ptr + nwords;
GC_obj_link(p) = *flh;
memset((char *)p + GC_bytes_per_word, 0,
GC_bytes_per_word * (nwords - 1));
*flh = p;
GC_aux::GC_mem_recently_freed += nwords;
}
}
static void ptr_free_deallocate(void *p, size_t n)
{
size_t nwords = GC_round_up(n);
void ** flh;
if (n > GC_max_fast_bytes) {
GC_free(p);
} else {
flh = GC_aobjfreelist_ptr + nwords;
GC_obj_link(p) = *flh;
*flh = p;
GC_aux::GC_mem_recently_freed += nwords;
}
}
};
typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
template <int dummy>
class single_client_alloc_template {
public:
static void * allocate(size_t n)
{
size_t nwords = GC_round_up_uncollectable(n);
void ** flh;
void * op;
if (n > GC_max_fast_bytes) return GC_malloc_uncollectable(n);
flh = GC_uobjfreelist_ptr + nwords;
if (0 == (op = *flh)) {
return GC_aux::GC_out_of_line_malloc(nwords, GC_UNCOLLECTABLE);
}
*flh = GC_obj_link(op);
GC_aux::GC_uncollectable_words_recently_allocd += nwords;
return op;
}
static void * ptr_free_allocate(size_t n)
{
size_t nwords = GC_round_up_uncollectable(n);
void ** flh;
void * op;
if (n > GC_max_fast_bytes) return GC_malloc_atomic_uncollectable(n);
flh = GC_auobjfreelist_ptr + nwords;
if (0 == (op = *flh)) {
return GC_aux::GC_out_of_line_malloc(nwords, GC_AUNCOLLECTABLE);
}
*flh = GC_obj_link(op);
GC_aux::GC_uncollectable_words_recently_allocd += nwords;
return op;
}
static void deallocate(void *p, size_t n)
{
size_t nwords = GC_round_up_uncollectable(n);
void ** flh;
if (n > GC_max_fast_bytes) {
GC_free(p);
} else {
flh = GC_uobjfreelist_ptr + nwords;
GC_obj_link(p) = *flh;
*flh = p;
GC_aux::GC_uncollectable_mem_recently_freed += nwords;
}
}
static void ptr_free_deallocate(void *p, size_t n)
{
size_t nwords = GC_round_up_uncollectable(n);
void ** flh;
if (n > GC_max_fast_bytes) {
GC_free(p);
} else {
flh = GC_auobjfreelist_ptr + nwords;
GC_obj_link(p) = *flh;
*flh = p;
GC_aux::GC_uncollectable_mem_recently_freed += nwords;
}
}
};
typedef single_client_alloc_template<0> single_client_alloc;
template < int dummy >
class gc_alloc_template {
public:
static void * allocate(size_t n) { return GC_malloc(n); }
static void * ptr_free_allocate(size_t n)
{ return GC_malloc_atomic(n); }
static void deallocate(void *, size_t) { }
static void ptr_free_deallocate(void *, size_t) { }
};
typedef gc_alloc_template < 0 > gc_alloc;
template < int dummy >
class alloc_template {
public:
static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
static void * ptr_free_allocate(size_t n)
{ return GC_malloc_atomic_uncollectable(n); }
static void deallocate(void *p, size_t) { GC_free(p); }
static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
};
typedef alloc_template < 0 > alloc;
#ifdef _SGI_SOURCE
# define __GC_SPECIALIZE(T,alloc) \
class simple_alloc<T, alloc> { \
public: \
static T *allocate(size_t n) \
{ return 0 == n? 0 : \
(T*) alloc::ptr_free_allocate(n * sizeof (T)); } \
static T *allocate(void) \
{ return (T*) alloc::ptr_free_allocate(sizeof (T)); } \
static void deallocate(T *p, size_t n) \
{ if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
static void deallocate(T *p) \
{ alloc::ptr_free_deallocate(p, sizeof (T)); } \
};
__GC_SPECIALIZE(char, gc_alloc)
__GC_SPECIALIZE(int, gc_alloc)
__GC_SPECIALIZE(unsigned, gc_alloc)
__GC_SPECIALIZE(float, gc_alloc)
__GC_SPECIALIZE(double, gc_alloc)
__GC_SPECIALIZE(char, alloc)
__GC_SPECIALIZE(int, alloc)
__GC_SPECIALIZE(unsigned, alloc)
__GC_SPECIALIZE(float, alloc)
__GC_SPECIALIZE(double, alloc)
__GC_SPECIALIZE(char, single_client_gc_alloc)
__GC_SPECIALIZE(int, single_client_gc_alloc)
__GC_SPECIALIZE(unsigned, single_client_gc_alloc)
__GC_SPECIALIZE(float, single_client_gc_alloc)
__GC_SPECIALIZE(double, single_client_gc_alloc)
__GC_SPECIALIZE(char, single_client_alloc)
__GC_SPECIALIZE(int, single_client_alloc)
__GC_SPECIALIZE(unsigned, single_client_alloc)
__GC_SPECIALIZE(float, single_client_alloc)
__GC_SPECIALIZE(double, single_client_alloc)
#ifdef __STL_USE_STD_ALLOCATORS
???copy stuff from stl_alloc.h or remove it to a different file ???
#endif
#endif
#endif