Index: src/common/memory.h |
diff --git a/src/common/memory.h b/src/common/memory.h |
index d6aa137d35c0fdb16e4af7bff2a0c5a1aea82be8..16a612b8cf36761f7179f897a1d01c3a716139af 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 |