|
9 | 9 | #ifndef SCUDO_VECTOR_H_ |
10 | 10 | #define SCUDO_VECTOR_H_ |
11 | 11 |
|
12 | | -#include "common.h" |
| 12 | +#include "mem_map.h" |
13 | 13 |
|
14 | 14 | #include <string.h> |
15 | 15 |
|
16 | 16 | namespace scudo { |
17 | 17 |
|
18 | | -// A low-level vector based on map. May incur a significant memory overhead for |
19 | | -// small vectors. The current implementation supports only POD types. |
| 18 | +// A low-level vector based on map. It stores the contents inline up to a fixed |
| 19 | +// capacity, or in an external memory buffer if it grows bigger than that. May |
| 20 | +// incur a significant memory overhead for small vectors. The current |
| 21 | +// implementation supports only POD types. |
| 22 | +// |
| 23 | +// NOTE: This class is not meant to be used directly, use Vector<T> instead. |
20 | 24 | template <typename T> class VectorNoCtor { |
21 | 25 | public: |
22 | | - constexpr void init(uptr InitialCapacity = 0) { |
23 | | - Data = &LocalData[0]; |
24 | | - CapacityBytes = sizeof(LocalData); |
25 | | - if (InitialCapacity > capacity()) |
26 | | - reserve(InitialCapacity); |
27 | | - } |
28 | | - void destroy() { |
29 | | - if (Data != &LocalData[0]) |
30 | | - unmap(Data, CapacityBytes, 0, &MapData); |
31 | | - } |
32 | 26 | T &operator[](uptr I) { |
33 | 27 | DCHECK_LT(I, Size); |
34 | 28 | return Data[I]; |
@@ -78,24 +72,43 @@ template <typename T> class VectorNoCtor { |
78 | 72 | const T *end() const { return data() + size(); } |
79 | 73 | T *end() { return data() + size(); } |
80 | 74 |
|
| 75 | +protected: |
| 76 | + constexpr void init(uptr InitialCapacity = 0) { |
| 77 | + Data = &LocalData[0]; |
| 78 | + CapacityBytes = sizeof(LocalData); |
| 79 | + if (InitialCapacity > capacity()) |
| 80 | + reserve(InitialCapacity); |
| 81 | + } |
| 82 | + void destroy() { |
| 83 | + if (Data != &LocalData[0]) |
| 84 | + ExternalBuffer.unmap(ExternalBuffer.getBase(), |
| 85 | + ExternalBuffer.getCapacity()); |
| 86 | + } |
| 87 | + |
81 | 88 | private: |
82 | 89 | void reallocate(uptr NewCapacity) { |
83 | 90 | DCHECK_GT(NewCapacity, 0); |
84 | 91 | DCHECK_LE(Size, NewCapacity); |
| 92 | + |
| 93 | + MemMapT NewExternalBuffer; |
85 | 94 | NewCapacity = roundUp(NewCapacity * sizeof(T), getPageSizeCached()); |
86 | | - T *NewData = reinterpret_cast<T *>( |
87 | | - map(nullptr, NewCapacity, "scudo:vector", 0, &MapData)); |
88 | | - memcpy(NewData, Data, Size * sizeof(T)); |
| 95 | + NewExternalBuffer.map(/*Addr=*/0U, NewCapacity, "scudo:vector"); |
| 96 | + T *NewExternalData = reinterpret_cast<T *>(NewExternalBuffer.getBase()); |
| 97 | + |
| 98 | + memcpy(NewExternalData, Data, Size * sizeof(T)); |
89 | 99 | destroy(); |
90 | | - Data = NewData; |
| 100 | + |
| 101 | + Data = NewExternalData; |
91 | 102 | CapacityBytes = NewCapacity; |
| 103 | + ExternalBuffer = NewExternalBuffer; |
92 | 104 | } |
93 | 105 |
|
94 | 106 | T *Data = nullptr; |
95 | | - T LocalData[256 / sizeof(T)] = {}; |
96 | 107 | uptr CapacityBytes = 0; |
97 | 108 | uptr Size = 0; |
98 | | - [[no_unique_address]] MapPlatformData MapData = {}; |
| 109 | + |
| 110 | + T LocalData[256 / sizeof(T)] = {}; |
| 111 | + MemMapT ExternalBuffer; |
99 | 112 | }; |
100 | 113 |
|
101 | 114 | template <typename T> class Vector : public VectorNoCtor<T> { |
|
0 commit comments