diff options
Diffstat (limited to 'src/common/memory.h')
-rw-r--r-- | src/common/memory.h | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/src/common/memory.h b/src/common/memory.h index d6aa137d..16a612b8 100644 --- a/src/common/memory.h +++ b/src/common/memory.h @@ -64,7 +64,8 @@ class PageAllocator { : page_size_(getpagesize()), last_(NULL), current_page_(NULL), - page_offset_(0) { + page_offset_(0), + pages_allocated_(0) { } ~PageAllocator() { @@ -112,6 +113,8 @@ class PageAllocator { return false; } + unsigned long pages_allocated() { return pages_allocated_; } + private: uint8_t *GetNPages(size_t num_pages) { #if defined(__x86_64__) || defined(__aarch64__) || defined(__aarch64__) || \ @@ -136,6 +139,8 @@ class PageAllocator { header->num_pages = num_pages; last_ = header; + pages_allocated_ += num_pages; + return reinterpret_cast<uint8_t*>(a); } @@ -157,6 +162,7 @@ class PageAllocator { PageHeader *last_; uint8_t *current_page_; size_t page_offset_; + unsigned long pages_allocated_; }; // Wrapper to use with STL containers @@ -165,12 +171,30 @@ struct PageStdAllocator : public std::allocator<T> { typedef typename std::allocator<T>::pointer pointer; typedef typename std::allocator<T>::size_type size_type; - explicit PageStdAllocator(PageAllocator& allocator): allocator_(allocator) {} + explicit PageStdAllocator(PageAllocator& allocator) : allocator_(allocator), + stackdata_(NULL), + stackdata_size_(0) + {} + template <class Other> PageStdAllocator(const PageStdAllocator<Other>& other) - : allocator_(other.allocator_) {} + : allocator_(other.allocator_), + stackdata_(nullptr), + stackdata_size_(0) + {} + + explicit PageStdAllocator(PageAllocator& allocator, + pointer stackdata, + size_type stackdata_size) : allocator_(allocator), + stackdata_(stackdata), + stackdata_size_(stackdata_size) + {} inline pointer allocate(size_type n, const void* = 0) { - return static_cast<pointer>(allocator_.Alloc(sizeof(T) * n)); + const size_type size = sizeof(T) * n; + if (size <= stackdata_size_) { + return stackdata_; + } + return static_cast<pointer>(allocator_.Alloc(size)); } inline void deallocate(pointer, size_type) { @@ -188,6 +212,8 @@ struct PageStdAllocator : public std::allocator<T> { template<typename Other> friend struct PageStdAllocator; PageAllocator& allocator_; + pointer stackdata_; + size_type stackdata_size_; }; // A wasteful vector is a std::vector, except that it allocates memory from a @@ -200,6 +226,24 @@ class wasteful_vector : public std::vector<T, PageStdAllocator<T> > { : std::vector<T, PageStdAllocator<T> >(PageStdAllocator<T>(*allocator)) { std::vector<T, PageStdAllocator<T> >::reserve(size_hint); } + protected: + wasteful_vector(PageStdAllocator<T> allocator) + : std::vector<T, PageStdAllocator<T> >(allocator) {} +}; + +// auto_wasteful_vector allocates space on the stack for N entries to avoid +// using the PageAllocator for small data, while still allowing for larger data. +template<class T, unsigned int N> +class auto_wasteful_vector : public wasteful_vector<T> { + T stackdata_[N]; + public: + auto_wasteful_vector(PageAllocator* allocator) + : wasteful_vector<T>( + PageStdAllocator<T>(*allocator, + &stackdata_[0], + sizeof(stackdata_))) { + std::vector<T, PageStdAllocator<T> >::reserve(N); + } }; } // namespace google_breakpad |