Index: compiler-rt/lib/scudo/standalone/tests/vector_test.cpp =================================================================== --- compiler-rt/lib/scudo/standalone/tests/vector_test.cpp +++ compiler-rt/lib/scudo/standalone/tests/vector_test.cpp @@ -23,13 +23,18 @@ } TEST(ScudoVectorTest, Stride) { + // Fill two pages of elements, to exercise the code that grows the buffer as + // needed by allocating a bigger buffer and copying the old contents in it. + scudo::uptr NumElements = + 2U * scudo::getPageSizeCached() / sizeof(scudo::uptr); + scudo::Vector V; - for (scudo::uptr I = 0; I < 1000; I++) { + for (scudo::uptr I = 0; I < NumElements; I++) { V.push_back(I); EXPECT_EQ(V.size(), I + 1U); EXPECT_EQ(V[I], I); } - for (scudo::uptr I = 0; I < 1000; I++) + for (scudo::uptr I = 0; I < NumElements; I++) EXPECT_EQ(V[I], I); } Index: compiler-rt/lib/scudo/standalone/vector.h =================================================================== --- compiler-rt/lib/scudo/standalone/vector.h +++ compiler-rt/lib/scudo/standalone/vector.h @@ -9,14 +9,16 @@ #ifndef SCUDO_VECTOR_H_ #define SCUDO_VECTOR_H_ -#include "common.h" +#include "mem_map.h" #include namespace scudo { -// A low-level vector based on map. May incur a significant memory overhead for -// small vectors. The current implementation supports only POD types. +// A low-level vector based on map. It stores the contents inline up to a fixed +// capacity, or in an external memory buffer if it grows bigger than that. May +// incur a significant memory overhead for small vectors. The current +// implementation supports only POD types. template class VectorNoCtor { public: constexpr void init(uptr InitialCapacity = 0) { @@ -27,7 +29,8 @@ } void destroy() { if (Data != &LocalData[0]) - unmap(Data, CapacityBytes, 0, &MapData); + ExternalBuffer.unmap(ExternalBuffer.getBase(), + ExternalBuffer.getCapacity()); } T &operator[](uptr I) { DCHECK_LT(I, Size); @@ -82,20 +85,26 @@ void reallocate(uptr NewCapacity) { DCHECK_GT(NewCapacity, 0); DCHECK_LE(Size, NewCapacity); + + MemMapT NewExternalBuffer; NewCapacity = roundUp(NewCapacity * sizeof(T), getPageSizeCached()); - T *NewData = reinterpret_cast( - map(nullptr, NewCapacity, "scudo:vector", 0, &MapData)); - memcpy(NewData, Data, Size * sizeof(T)); + NewExternalBuffer.map(/*Addr=*/0U, NewCapacity, "scudo:vector"); + T *NewExternalData = reinterpret_cast(NewExternalBuffer.getBase()); + + memcpy(NewExternalData, Data, Size * sizeof(T)); destroy(); - Data = NewData; + + Data = NewExternalData; CapacityBytes = NewCapacity; + ExternalBuffer = NewExternalBuffer; } T *Data = nullptr; - T LocalData[256 / sizeof(T)] = {}; uptr CapacityBytes = 0; uptr Size = 0; - [[no_unique_address]] MapPlatformData MapData = {}; + + T LocalData[256 / sizeof(T)] = {}; + MemMapT ExternalBuffer; }; template class Vector : public VectorNoCtor {