1 //===-- vector.h ------------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef SCUDO_VECTOR_H_
10 #define SCUDO_VECTOR_H_
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.
23 // NOTE: This class is not meant to be used directly, use Vector<T> instead.
24 template <typename T
> class VectorNoCtor
{
26 T
&operator[](uptr I
) {
30 const T
&operator[](uptr I
) const {
34 void push_back(const T
&Element
) {
35 DCHECK_LE(Size
, capacity());
36 if (Size
== capacity()) {
37 const uptr NewCapacity
= roundUpPowerOfTwo(Size
+ 1);
38 reallocate(NewCapacity
);
40 memcpy(&Data
[Size
++], &Element
, sizeof(T
));
44 return Data
[Size
- 1];
50 uptr
size() const { return Size
; }
51 const T
*data() const { return Data
; }
52 T
*data() { return Data
; }
53 constexpr uptr
capacity() const { return CapacityBytes
/ sizeof(T
); }
54 void reserve(uptr NewSize
) {
55 // Never downsize internal buffer.
56 if (NewSize
> capacity())
59 void resize(uptr NewSize
) {
62 memset(&Data
[Size
], 0, sizeof(T
) * (NewSize
- Size
));
67 void clear() { Size
= 0; }
68 bool empty() const { return size() == 0; }
70 const T
*begin() const { return data(); }
71 T
*begin() { return data(); }
72 const T
*end() const { return data() + size(); }
73 T
*end() { return data() + size(); }
76 constexpr void init(uptr InitialCapacity
= 0) {
78 CapacityBytes
= sizeof(LocalData
);
79 if (InitialCapacity
> capacity())
80 reserve(InitialCapacity
);
83 if (Data
!= &LocalData
[0])
84 ExternalBuffer
.unmap(ExternalBuffer
.getBase(),
85 ExternalBuffer
.getCapacity());
89 void reallocate(uptr NewCapacity
) {
90 DCHECK_GT(NewCapacity
, 0);
91 DCHECK_LE(Size
, NewCapacity
);
93 MemMapT NewExternalBuffer
;
94 NewCapacity
= roundUp(NewCapacity
* sizeof(T
), getPageSizeCached());
95 NewExternalBuffer
.map(/*Addr=*/0U, NewCapacity
, "scudo:vector");
96 T
*NewExternalData
= reinterpret_cast<T
*>(NewExternalBuffer
.getBase());
98 memcpy(NewExternalData
, Data
, Size
* sizeof(T
));
101 Data
= NewExternalData
;
102 CapacityBytes
= NewCapacity
;
103 ExternalBuffer
= NewExternalBuffer
;
107 uptr CapacityBytes
= 0;
110 T LocalData
[256 / sizeof(T
)] = {};
111 MemMapT ExternalBuffer
;
114 template <typename T
> class Vector
: public VectorNoCtor
<T
> {
116 constexpr Vector() { VectorNoCtor
<T
>::init(); }
117 explicit Vector(uptr Count
) {
118 VectorNoCtor
<T
>::init(Count
);
121 ~Vector() { VectorNoCtor
<T
>::destroy(); }
122 // Disallow copies and moves.
123 Vector(const Vector
&) = delete;
124 Vector
&operator=(const Vector
&) = delete;
125 Vector(Vector
&&) = delete;
126 Vector
&operator=(Vector
&&) = delete;
131 #endif // SCUDO_VECTOR_H_