vector.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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 "common.h"
  11. #include <string.h>
  12. namespace scudo {
  13. // A low-level vector based on map. May incur a significant memory overhead for
  14. // small vectors. The current implementation supports only POD types.
  15. template <typename T> class VectorNoCtor {
  16. public:
  17. constexpr void init(uptr InitialCapacity = 0) {
  18. Data = &LocalData[0];
  19. CapacityBytes = sizeof(LocalData);
  20. if (InitialCapacity > capacity())
  21. reserve(InitialCapacity);
  22. }
  23. void destroy() {
  24. if (Data != &LocalData[0])
  25. unmap(Data, CapacityBytes, 0, &MapData);
  26. }
  27. T &operator[](uptr I) {
  28. DCHECK_LT(I, Size);
  29. return Data[I];
  30. }
  31. const T &operator[](uptr I) const {
  32. DCHECK_LT(I, Size);
  33. return Data[I];
  34. }
  35. void push_back(const T &Element) {
  36. DCHECK_LE(Size, capacity());
  37. if (Size == capacity()) {
  38. const uptr NewCapacity = roundUpToPowerOfTwo(Size + 1);
  39. reallocate(NewCapacity);
  40. }
  41. memcpy(&Data[Size++], &Element, sizeof(T));
  42. }
  43. T &back() {
  44. DCHECK_GT(Size, 0);
  45. return Data[Size - 1];
  46. }
  47. void pop_back() {
  48. DCHECK_GT(Size, 0);
  49. Size--;
  50. }
  51. uptr size() const { return Size; }
  52. const T *data() const { return Data; }
  53. T *data() { return Data; }
  54. constexpr uptr capacity() const { return CapacityBytes / sizeof(T); }
  55. void reserve(uptr NewSize) {
  56. // Never downsize internal buffer.
  57. if (NewSize > capacity())
  58. reallocate(NewSize);
  59. }
  60. void resize(uptr NewSize) {
  61. if (NewSize > Size) {
  62. reserve(NewSize);
  63. memset(&Data[Size], 0, sizeof(T) * (NewSize - Size));
  64. }
  65. Size = NewSize;
  66. }
  67. void clear() { Size = 0; }
  68. bool empty() const { return size() == 0; }
  69. const T *begin() const { return data(); }
  70. T *begin() { return data(); }
  71. const T *end() const { return data() + size(); }
  72. T *end() { return data() + size(); }
  73. private:
  74. void reallocate(uptr NewCapacity) {
  75. DCHECK_GT(NewCapacity, 0);
  76. DCHECK_LE(Size, NewCapacity);
  77. NewCapacity = roundUpTo(NewCapacity * sizeof(T), getPageSizeCached());
  78. T *NewData = reinterpret_cast<T *>(
  79. map(nullptr, NewCapacity, "scudo:vector", 0, &MapData));
  80. memcpy(NewData, Data, Size * sizeof(T));
  81. destroy();
  82. Data = NewData;
  83. CapacityBytes = NewCapacity;
  84. }
  85. T *Data = nullptr;
  86. T LocalData[256 / sizeof(T)] = {};
  87. uptr CapacityBytes = 0;
  88. uptr Size = 0;
  89. [[no_unique_address]] MapPlatformData MapData = {};
  90. };
  91. template <typename T> class Vector : public VectorNoCtor<T> {
  92. public:
  93. constexpr Vector() { VectorNoCtor<T>::init(); }
  94. explicit Vector(uptr Count) {
  95. VectorNoCtor<T>::init(Count);
  96. this->resize(Count);
  97. }
  98. ~Vector() { VectorNoCtor<T>::destroy(); }
  99. // Disallow copies and moves.
  100. Vector(const Vector &) = delete;
  101. Vector &operator=(const Vector &) = delete;
  102. Vector(Vector &&) = delete;
  103. Vector &operator=(Vector &&) = delete;
  104. };
  105. } // namespace scudo
  106. #endif // SCUDO_VECTOR_H_