From a6763e74514d611ad3d768d7528fbd88dc0f2694 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Thu, 19 Nov 2020 17:48:59 +0000 Subject: [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. --- xpcom/glue/nsTArray-inl.h | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/xpcom/glue/nsTArray-inl.h b/xpcom/glue/nsTArray-inl.h index 7e667a327..6fdfdcb7c 100644 --- a/xpcom/glue/nsTArray-inl.h +++ b/xpcom/glue/nsTArray-inl.h @@ -249,12 +249,28 @@ nsTArray_base::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(nsTArrayFallibleAllocator::Malloc(newSize)); + if (!newHeader) { + return; + } + + Copy::MoveNonOverlappingRegionWithHeader(newHeader, mHdr, Length(), aElemSize); + + nsTArrayFallibleAllocator::Free(mHdr); + } else { + // Realloc() existing data + newHeader = static_cast(nsTArrayFallibleAllocator::Realloc(mHdr, newSize)); + if (!newHeader) { + return; + } } - mHdr = static_cast(ptr); + + mHdr = newHeader; mHdr->mCapacity = length; } -- cgit v1.2.3