summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2020-11-19 17:48:59 +0000
committerMoonchild <moonchild@palemoon.org>2020-11-19 22:46:22 +0000
commita6763e74514d611ad3d768d7528fbd88dc0f2694 (patch)
tree6ba60a696fad3925f26f4d6215d7ab04b26e4ccc
parent727f4372a9b3f8cfd4e8c7077a85b60041090b57 (diff)
downloaduxp-a6763e74514d611ad3d768d7528fbd88dc0f2694.tar.gz
[xpcom] Don't use realloc for shrinking nsTArrays when allowRealloc is false.
The original patch handled the grow case but not the shrink case. When the current and new allocation sizes are in different size classes, jemalloc's realloc will move the allocation when shrinking, not just truncate the existing one. Based on work by Jon Coppeard.
-rw-r--r--xpcom/glue/nsTArray-inl.h26
1 files changed, 21 insertions, 5 deletions
diff --git a/xpcom/glue/nsTArray-inl.h b/xpcom/glue/nsTArray-inl.h
index 7e667a3276..6fdfdcb7c0 100644
--- a/xpcom/glue/nsTArray-inl.h
+++ b/xpcom/glue/nsTArray-inl.h
@@ -249,12 +249,28 @@ nsTArray_base<Alloc, Copy>::ShrinkCapacity(size_type aElemSize,
return;
}
- size_type size = sizeof(Header) + length * aElemSize;
- void* ptr = nsTArrayFallibleAllocator::Realloc(mHdr, size);
- if (!ptr) {
- return;
+ size_type newSize = sizeof(Header) + length * aElemSize;
+
+ Header* newHeader;
+ if (!Copy::allowRealloc) {
+ // Malloc() and copy
+ newHeader = static_cast<Header*>(nsTArrayFallibleAllocator::Malloc(newSize));
+ if (!newHeader) {
+ return;
+ }
+
+ Copy::MoveNonOverlappingRegionWithHeader(newHeader, mHdr, Length(), aElemSize);
+
+ nsTArrayFallibleAllocator::Free(mHdr);
+ } else {
+ // Realloc() existing data
+ newHeader = static_cast<Header*>(nsTArrayFallibleAllocator::Realloc(mHdr, newSize));
+ if (!newHeader) {
+ return;
+ }
}
- mHdr = static_cast<Header*>(ptr);
+
+ mHdr = newHeader;
mHdr->mCapacity = length;
}