diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 | 
| commit | eb11fae6d08f479c0799db45860a98af528fa6e7 (patch) | |
| tree | 44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/Support/SmallVector.cpp | |
| parent | b8a2042aa938069e862750553db0e4d82d25822c (diff) | |
Notes
Diffstat (limited to 'lib/Support/SmallVector.cpp')
| -rw-r--r-- | lib/Support/SmallVector.cpp | 50 | 
1 files changed, 36 insertions, 14 deletions
| diff --git a/lib/Support/SmallVector.cpp b/lib/Support/SmallVector.cpp index 74313151c762..1070c6672edc 100644 --- a/lib/Support/SmallVector.cpp +++ b/lib/Support/SmallVector.cpp @@ -14,31 +14,53 @@  #include "llvm/ADT/SmallVector.h"  using namespace llvm; +// Check that no bytes are wasted and everything is well-aligned. +namespace { +struct Struct16B { +  alignas(16) void *X; +}; +struct Struct32B { +  alignas(32) void *X; +}; +} +static_assert(sizeof(SmallVector<void *, 0>) == +                  sizeof(unsigned) * 2 + sizeof(void *), +              "wasted space in SmallVector size 0"); +static_assert(alignof(SmallVector<Struct16B, 0>) >= alignof(Struct16B), +              "wrong alignment for 16-byte aligned T"); +static_assert(alignof(SmallVector<Struct32B, 0>) >= alignof(Struct32B), +              "wrong alignment for 32-byte aligned T"); +static_assert(sizeof(SmallVector<Struct16B, 0>) >= alignof(Struct16B), +              "missing padding for 16-byte aligned T"); +static_assert(sizeof(SmallVector<Struct32B, 0>) >= alignof(Struct32B), +              "missing padding for 32-byte aligned T"); +static_assert(sizeof(SmallVector<void *, 1>) == +                  sizeof(unsigned) * 2 + sizeof(void *) * 2, +              "wasted space in SmallVector size 1"); +  /// grow_pod - This is an implementation of the grow() method which only works  /// on POD-like datatypes and is out of line to reduce code duplication. -void SmallVectorBase::grow_pod(void *FirstEl, size_t MinSizeInBytes, +void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity,                                 size_t TSize) { -  size_t CurSizeBytes = size_in_bytes(); -  size_t NewCapacityInBytes = 2 * capacity_in_bytes() + TSize; // Always grow. -  if (NewCapacityInBytes < MinSizeInBytes) -    NewCapacityInBytes = MinSizeInBytes; +  // Ensure we can fit the new capacity in 32 bits. +  if (MinCapacity > UINT32_MAX) +    report_bad_alloc_error("SmallVector capacity overflow during allocation"); + +  size_t NewCapacity = 2 * capacity() + 1; // Always grow. +  NewCapacity = +      std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX));    void *NewElts;    if (BeginX == FirstEl) { -    NewElts = malloc(NewCapacityInBytes); -    if (NewElts == nullptr) -      report_bad_alloc_error("Allocation of SmallVector element failed."); +    NewElts = safe_malloc(NewCapacity * TSize);      // Copy the elements over.  No need to run dtors on PODs. -    memcpy(NewElts, this->BeginX, CurSizeBytes); +    memcpy(NewElts, this->BeginX, size() * TSize);    } else {      // If this wasn't grown from the inline copy, grow the allocated space. -    NewElts = realloc(this->BeginX, NewCapacityInBytes); -    if (NewElts == nullptr) -      report_bad_alloc_error("Reallocation of SmallVector element failed."); +    NewElts = safe_realloc(this->BeginX, NewCapacity * TSize);    } -  this->EndX = (char*)NewElts+CurSizeBytes;    this->BeginX = NewElts; -  this->CapacityX = (char*)this->BeginX + NewCapacityInBytes; +  this->Capacity = NewCapacity;  } | 
