summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2020-11-19 17:48:59 +0000
committerMoonchild <moonchild@palemoon.org>2020-11-19 17:48:59 +0000
commit887fface569f29650e51369cfc2bb3fd23d3f101 (patch)
tree6a0f22f87779a791947df585db1bb884bf00d365
parent4782e8dfa2a5863f84c66f405c48eb2b99ac3622 (diff)
downloaduxp-887fface569f29650e51369cfc2bb3fd23d3f101.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 27fd38db0b..2eaea8029b 100644
--- a/xpcom/glue/nsTArray-inl.h
+++ b/xpcom/glue/nsTArray-inl.h
@@ -248,12 +248,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;
}