vector.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. //===-- vector.h ------------------------------------------------*- C++ -*-===//
  2. //
  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
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef SCUDO_VECTOR_H_
  9. #define SCUDO_VECTOR_H_
  10. #include "mem_map.h"
  11. #include <string.h>
  12. namespace scudo {
  13. // A low-level vector based on map. It stores the contents inline up to a fixed
  14. // capacity, or in an external memory buffer if it grows bigger than that. May
  15. // incur a significant memory overhead for small vectors. The current
  16. // implementation supports only POD types.
  17. //
  18. // NOTE: This class is not meant to be used directly, use Vector<T> instead.
  19. template <typename T> class VectorNoCtor {
  20. public:
  21. T &operator[](uptr I) {
  22. DCHECK_LT(I, Size);
  23. return Data[I];
  24. }
  25. const T &operator[](uptr I) const {
  26. DCHECK_LT(I, Size);
  27. return Data[I];
  28. }
  29. void push_back(const T &Element) {
  30. DCHECK_LE(Size, capacity());
  31. if (Size == capacity()) {
  32. const uptr NewCapacity = roundUpPowerOfTwo(Size + 1);
  33. reallocate(NewCapacity);
  34. }
  35. memcpy(&Data[Size++], &Element, sizeof(T));
  36. }
  37. T &back() {
  38. DCHECK_GT(Size, 0);
  39. return Data[Size - 1];
  40. }
  41. void pop_back() {
  42. DCHECK_GT(Size, 0);
  43. Size--;
  44. }
  45. uptr size() const { return Size; }
  46. const T *data() const { return Data; }
  47. T *data() { return Data; }
  48. constexpr uptr capacity() const { return CapacityBytes / sizeof(T); }
  49. void reserve(uptr NewSize) {
  50. // Never downsize internal buffer.
  51. if (NewSize > capacity())
  52. reallocate(NewSize);
  53. }
  54. void resize(uptr NewSize) {
  55. if (NewSize > Size) {
  56. reserve(NewSize);
  57. memset(&Data[Size], 0, sizeof(T) * (NewSize - Size));
  58. }
  59. Size = NewSize;
  60. }
  61. void clear() { Size = 0; }
  62. bool empty() const { return size() == 0; }
  63. const T *begin() const { return data(); }
  64. T *begin() { return data(); }
  65. const T *end() const { return data() + size(); }
  66. T *end() { return data() + size(); }
  67. protected:
  68. constexpr void init(uptr InitialCapacity = 0) {
  69. Data = &LocalData[0];
  70. CapacityBytes = sizeof(LocalData);
  71. if (InitialCapacity > capacity())
  72. reserve(InitialCapacity);
  73. }
  74. void destroy() {
  75. if (Data != &LocalData[0])
  76. ExternalBuffer.unmap(ExternalBuffer.getBase(),
  77. ExternalBuffer.getCapacity());
  78. }
  79. private:
  80. void reallocate(uptr NewCapacity) {
  81. DCHECK_GT(NewCapacity, 0);
  82. DCHECK_LE(Size, NewCapacity);
  83. MemMapT NewExternalBuffer;
  84. NewCapacity = roundUp(NewCapacity * sizeof(T), getPageSizeCached());
  85. NewExternalBuffer.map(/*Addr=*/0U, NewCapacity, "scudo:vector");
  86. T *NewExternalData = reinterpret_cast<T *>(NewExternalBuffer.getBase());
  87. memcpy(NewExternalData, Data, Size * sizeof(T));
  88. destroy();
  89. Data = NewExternalData;
  90. CapacityBytes = NewCapacity;
  91. ExternalBuffer = NewExternalBuffer;
  92. }
  93. T *Data = nullptr;
  94. uptr CapacityBytes = 0;
  95. uptr Size = 0;
  96. T LocalData[256 / sizeof(T)] = {};
  97. MemMapT ExternalBuffer;
  98. };
  99. template <typename T> class Vector : public VectorNoCtor<T> {
  100. public:
  101. constexpr Vector() { VectorNoCtor<T>::init(); }
  102. explicit Vector(uptr Count) {
  103. VectorNoCtor<T>::init(Count);
  104. this->resize(Count);
  105. }
  106. ~Vector() { VectorNoCtor<T>::destroy(); }
  107. // Disallow copies and moves.
  108. Vector(const Vector &) = delete;
  109. Vector &operator=(const Vector &) = delete;
  110. Vector(Vector &&) = delete;
  111. Vector &operator=(Vector &&) = delete;
  112. };
  113. } // namespace scudo
  114. #endif // SCUDO_VECTOR_H_