aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/SmallVector.cpp
diff options
context:
space:
mode:
authorAlina Sbirlea <asbirlea@google.com>2022-08-23 15:39:09 -0700
committerAlina Sbirlea <asbirlea@google.com>2022-10-06 15:37:43 -0700
commit0fbeca0ee6f0cdc37b89e5b06fbb3ca6caf26f66 (patch)
tree66c81482b86a5852227183db1cb8edc7bc734ff6 /llvm/lib/Support/SmallVector.cpp
parent6d65ac500946c44457bbd2b2cfa7d0a6482e51f2 (diff)
downloadllvm-0fbeca0ee6f0cdc37b89e5b06fbb3ca6caf26f66.zip
llvm-0fbeca0ee6f0cdc37b89e5b06fbb3ca6caf26f66.tar.gz
llvm-0fbeca0ee6f0cdc37b89e5b06fbb3ca6caf26f66.tar.bz2
[SmallVector] Reallocate if assigned memory is right after the current vector, created with capacity 0
Potential solution for https://github.com/llvm/llvm-project/issues/57324. Differential Revision: https://reviews.llvm.org/D132512
Diffstat (limited to 'llvm/lib/Support/SmallVector.cpp')
-rw-r--r--llvm/lib/Support/SmallVector.cpp29
1 files changed, 25 insertions, 4 deletions
diff --git a/llvm/lib/Support/SmallVector.cpp b/llvm/lib/Support/SmallVector.cpp
index 062e965..f7e7e80 100644
--- a/llvm/lib/Support/SmallVector.cpp
+++ b/llvm/lib/Support/SmallVector.cpp
@@ -108,12 +108,29 @@ static size_t getNewCapacity(size_t MinSize, size_t TSize, size_t OldCapacity) {
return std::clamp(NewCapacity, MinSize, MaxSize);
}
+template <class Size_T>
+void *SmallVectorBase<Size_T>::replaceAllocation(void *NewElts, size_t TSize,
+ size_t NewCapacity,
+ size_t VSize) {
+ void *NewEltsReplace = llvm::safe_malloc(NewCapacity * TSize);
+ if (VSize)
+ memcpy(NewEltsReplace, NewElts, VSize * TSize);
+ free(NewElts);
+ return NewEltsReplace;
+}
+
// Note: Moving this function into the header may cause performance regression.
template <class Size_T>
-void *SmallVectorBase<Size_T>::mallocForGrow(size_t MinSize, size_t TSize,
+void *SmallVectorBase<Size_T>::mallocForGrow(void *FirstEl, size_t MinSize,
+ size_t TSize,
size_t &NewCapacity) {
NewCapacity = getNewCapacity<Size_T>(MinSize, TSize, this->capacity());
- return llvm::safe_malloc(NewCapacity * TSize);
+ // Even if capacity is not 0 now, if the vector was originally created with
+ // capacity 0, it's possible for the malloc to return FirstEl.
+ void *NewElts = llvm::safe_malloc(NewCapacity * TSize);
+ if (NewElts == FirstEl)
+ NewElts = replaceAllocation(NewElts, TSize, NewCapacity);
+ return NewElts;
}
// Note: Moving this function into the header may cause performance regression.
@@ -123,13 +140,17 @@ void SmallVectorBase<Size_T>::grow_pod(void *FirstEl, size_t MinSize,
size_t NewCapacity = getNewCapacity<Size_T>(MinSize, TSize, this->capacity());
void *NewElts;
if (BeginX == FirstEl) {
- NewElts = safe_malloc(NewCapacity * TSize);
+ NewElts = llvm::safe_malloc(NewCapacity * TSize);
+ if (NewElts == FirstEl)
+ NewElts = replaceAllocation(NewElts, TSize, NewCapacity);
// Copy the elements over. No need to run dtors on PODs.
memcpy(NewElts, this->BeginX, size() * TSize);
} else {
// If this wasn't grown from the inline copy, grow the allocated space.
- NewElts = safe_realloc(this->BeginX, NewCapacity * TSize);
+ NewElts = llvm::safe_realloc(this->BeginX, NewCapacity * TSize);
+ if (NewElts == FirstEl)
+ NewElts = replaceAllocation(NewElts, TSize, NewCapacity, size());
}
this->BeginX = NewElts;