diff options
Diffstat (limited to 'gcc/alloc-pool.h')
-rw-r--r-- | gcc/alloc-pool.h | 124 |
1 files changed, 90 insertions, 34 deletions
diff --git a/gcc/alloc-pool.h b/gcc/alloc-pool.h index 03bde63..70105ba 100644 --- a/gcc/alloc-pool.h +++ b/gcc/alloc-pool.h @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see #ifndef ALLOC_POOL_H #define ALLOC_POOL_H +#include "memory-block.h" extern void dump_alloc_pool_statistics (void); @@ -95,18 +96,53 @@ struct pool_usage: public mem_usage extern mem_alloc_description<pool_usage> pool_allocator_usage; +#if 0 +/* If a pool with custom block size is needed, one might use the following + template. An instance of this template can be used as a parameter for + instantiating base_pool_allocator template: + + typedef custom_block_allocator <128*1024> huge_block_allocator; + ... + static base_pool_allocator <huge_block_allocator> + value_pool ("value", 16384); + + Right now it's not used anywhere in the code, and is given here as an + example). */ + +template <size_t BlockSize> +class custom_block_allocator +{ +public: + static const size_t block_size = BlockSize; + + static inline void * + allocate () ATTRIBUTE_MALLOC + { + return XNEWVEC (char, BlockSize); + } + + static inline void + release (void *block) + { + XDELETEVEC (block); + } +}; +#endif + /* Generic pool allocator. */ -class pool_allocator + +template <typename TBlockAllocator> +class base_pool_allocator { public: - /* Default constructor for pool allocator called NAME. Each block - has NUM elements. */ - pool_allocator (const char *name, size_t num, size_t size CXX_MEM_STAT_INFO); - ~pool_allocator (); + /* Default constructor for pool allocator called NAME. */ + base_pool_allocator (const char *name, size_t size CXX_MEM_STAT_INFO); + ~base_pool_allocator (); void release (); void release_if_empty (); void *allocate () ATTRIBUTE_MALLOC; void remove (void *object); + size_t num_elts_current (); private: struct allocation_pool_list @@ -151,7 +187,7 @@ private: }; /* Align X to 8. */ - size_t + static inline size_t align_eight (size_t x) { return (((x+7) >> 3) << 3); @@ -180,8 +216,6 @@ private: size_t m_blocks_allocated; /* List of blocks that are used to allocate new objects. */ allocation_pool_list *m_block_list; - /* The number of elements in a block. */ - size_t m_block_size; /* Size of a pool elements in bytes. */ size_t m_elt_size; /* Size in bytes that should be allocated for each element. */ @@ -192,24 +226,24 @@ private: mem_location m_location; }; +template <typename TBlockAllocator> inline -pool_allocator::pool_allocator (const char *name, size_t num, - size_t size MEM_STAT_DECL): - m_name (name), m_id (0), m_elts_per_block (num), m_returned_free_list (NULL), +base_pool_allocator <TBlockAllocator>::base_pool_allocator ( + const char *name, size_t size MEM_STAT_DECL): + m_name (name), m_id (0), m_elts_per_block (0), m_returned_free_list (NULL), m_virgin_free_list (NULL), m_virgin_elts_remaining (0), m_elts_allocated (0), - m_elts_free (0), m_blocks_allocated (0), m_block_list (NULL), - m_block_size (0), m_size (size), m_initialized (false), - m_location (ALLOC_POOL_ORIGIN, false PASS_MEM_STAT) {} + m_elts_free (0), m_blocks_allocated (0), m_block_list (NULL), m_size (size), + m_initialized (false), m_location (ALLOC_POOL_ORIGIN, false PASS_MEM_STAT) {} /* Initialize a pool allocator. */ +template <typename TBlockAllocator> inline void -pool_allocator::initialize () +base_pool_allocator <TBlockAllocator>::initialize () { gcc_checking_assert (!m_initialized); m_initialized = true; - size_t header_size; size_t size = m_size; gcc_checking_assert (m_name); @@ -218,15 +252,12 @@ pool_allocator::initialize () if (size < sizeof (allocation_pool_list*)) size = sizeof (allocation_pool_list*); - /* Now align the size to a multiple of 4. */ + /* Now align the size to a multiple of 8. */ size = align_eight (size); /* Add the aligned size of ID. */ size += offsetof (allocation_object, u.data); - /* Um, we can't really allocate 0 elements per block. */ - gcc_checking_assert (m_elts_per_block); - m_elt_size = size; if (GATHER_STATISTICS) @@ -239,9 +270,10 @@ pool_allocator::initialize () } /* List header size should be a multiple of 8. */ - header_size = align_eight (sizeof (allocation_pool_list)); + size_t header_size = align_eight (sizeof (allocation_pool_list)); - m_block_size = (size * m_elts_per_block) + header_size; + m_elts_per_block = (TBlockAllocator::block_size - header_size) / size; + gcc_checking_assert (m_elts_per_block != 0); #ifdef ENABLE_CHECKING /* Increase the last used ID and use it for this pool. @@ -255,8 +287,9 @@ pool_allocator::initialize () } /* Free all memory allocated for the given memory pool. */ +template <typename TBlockAllocator> inline void -pool_allocator::release () +base_pool_allocator <TBlockAllocator>::release () { if (!m_initialized) return; @@ -267,7 +300,7 @@ pool_allocator::release () for (block = m_block_list; block != NULL; block = next_block) { next_block = block->next; - free (block); + TBlockAllocator::release (block); } if (GATHER_STATISTICS) @@ -285,21 +318,24 @@ pool_allocator::release () m_block_list = NULL; } -void -inline pool_allocator::release_if_empty () +template <typename TBlockAllocator> +inline void +base_pool_allocator <TBlockAllocator>::release_if_empty () { if (m_elts_free == m_elts_allocated) release (); } -inline pool_allocator::~pool_allocator () +template <typename TBlockAllocator> +inline base_pool_allocator <TBlockAllocator>::~base_pool_allocator () { release (); } /* Allocates one element from the pool specified. */ +template <typename TBlockAllocator> inline void* -pool_allocator::allocate () +base_pool_allocator <TBlockAllocator>::allocate () { if (!m_initialized) initialize (); @@ -327,7 +363,7 @@ pool_allocator::allocate () allocation_pool_list *block_header; /* Make the block. */ - block = XNEWVEC (char, m_block_size); + block = reinterpret_cast<char *> (TBlockAllocator::allocate ()); block_header = (allocation_pool_list*) block; block += align_eight (sizeof (allocation_pool_list)); @@ -378,8 +414,9 @@ pool_allocator::allocate () } /* Puts PTR back on POOL's free list. */ +template <typename TBlockAllocator> inline void -pool_allocator::remove (void *object) +base_pool_allocator <TBlockAllocator>::remove (void *object) { gcc_checking_assert (m_initialized); @@ -412,15 +449,28 @@ pool_allocator::remove (void *object) } } +/* Number of elements currently active (not returned to pool). Used for cheap + consistency checks. */ +template <typename TBlockAllocator> +inline size_t +base_pool_allocator <TBlockAllocator>::num_elts_current () +{ + return m_elts_allocated - m_elts_free; +} + +/* Specialization of base_pool_allocator which should be used in most cases. + Another specialization may be needed, if object size is greater than + memory_block_pool::block_size (64 KB). */ +typedef base_pool_allocator <memory_block_pool> pool_allocator; + /* Type based memory pool allocator. */ template <typename T> class object_allocator { public: - /* Default constructor for pool allocator called NAME. Each block - has NUM elements. */ - object_allocator (const char *name, size_t num CXX_MEM_STAT_INFO): - m_allocator (name, num, sizeof (T) PASS_MEM_STAT) {} + /* Default constructor for pool allocator called NAME. */ + object_allocator (const char *name CXX_MEM_STAT_INFO): + m_allocator (name, sizeof (T) PASS_MEM_STAT) {} inline void release () @@ -448,6 +498,12 @@ public: m_allocator.remove (object); } + inline size_t + num_elts_current () + { + return m_allocator.num_elts_current (); + } + private: pool_allocator m_allocator; }; |