aboutsummaryrefslogtreecommitdiff
path: root/src/common/memory.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/memory.h')
-rw-r--r--src/common/memory.h52
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