mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1017418 (part 2) - Avoid more slop in nsTArray. r=froydnj.
This commit is contained in:
parent
7c04dbe0fe
commit
1f6501ee8c
@ -99,6 +99,44 @@ bool nsTArray_base<Alloc, Copy>::UsesAutoArrayBuffer() const {
|
||||
bool
|
||||
IsTwiceTheRequiredBytesRepresentableAsUint32(size_t capacity, size_t elemSize);
|
||||
|
||||
template<class Alloc, class Copy>
|
||||
void
|
||||
nsTArray_base<Alloc, Copy>::GoodSizeForCapacity(size_t capacity,
|
||||
size_t elemSize,
|
||||
size_t& nbytes,
|
||||
size_t& newCapacity)
|
||||
{
|
||||
// We increase our capacity so that |capacity * elemSize + sizeof(Header)| is
|
||||
// a size that minimizes slop -- if |nbytes| is less than |pageSize| we round
|
||||
// up to the next power of two, otherwise we round up to the next multiple of
|
||||
// |pageSize|.
|
||||
const size_t pageSizeBytes = 12;
|
||||
const size_t pageSize = 1 << pageSizeBytes;
|
||||
|
||||
nbytes = capacity * elemSize + sizeof(Header);
|
||||
if (nbytes >= pageSize) {
|
||||
// Round up to the next multiple of pageSize.
|
||||
nbytes = pageSize * ((nbytes + pageSize - 1) / pageSize);
|
||||
} else {
|
||||
// Round up to the next power of two. See
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||
nbytes = nbytes - 1;
|
||||
nbytes |= nbytes >> 1;
|
||||
nbytes |= nbytes >> 2;
|
||||
nbytes |= nbytes >> 4;
|
||||
nbytes |= nbytes >> 8;
|
||||
nbytes |= nbytes >> 16;
|
||||
nbytes++;
|
||||
|
||||
MOZ_ASSERT((nbytes & (nbytes - 1)) == 0,
|
||||
"nsTArray's allocation size should be a power of two!");
|
||||
}
|
||||
|
||||
// How many elements can we fit in |nbytes|?
|
||||
newCapacity = (nbytes - sizeof(Header)) / elemSize;
|
||||
MOZ_ASSERT(newCapacity >= capacity, "Didn't enlarge the array enough!");
|
||||
}
|
||||
|
||||
template<class Alloc, class Copy>
|
||||
typename Alloc::ResultTypeProxy
|
||||
nsTArray_base<Alloc, Copy>::EnsureCapacity(size_type capacity, size_type elemSize) {
|
||||
@ -116,68 +154,38 @@ nsTArray_base<Alloc, Copy>::EnsureCapacity(size_type capacity, size_type elemSiz
|
||||
return Alloc::FailureResult();
|
||||
}
|
||||
|
||||
if (mHdr == EmptyHdr()) {
|
||||
// Malloc() new data
|
||||
Header *header = static_cast<Header*>
|
||||
(Alloc::Malloc(sizeof(Header) + capacity * elemSize));
|
||||
if (!header)
|
||||
return Alloc::FailureResult();
|
||||
header->mLength = 0;
|
||||
header->mCapacity = capacity;
|
||||
header->mIsAutoArray = 0;
|
||||
mHdr = header;
|
||||
|
||||
return Alloc::SuccessResult();
|
||||
}
|
||||
|
||||
// We increase our capacity so |capacity * elemSize + sizeof(Header)| is the
|
||||
// next power of two, if this value is less than pageSize bytes, or otherwise
|
||||
// so it's the next multiple of pageSize.
|
||||
const size_t pageSizeBytes = 12;
|
||||
const size_t pageSize = 1 << pageSizeBytes;
|
||||
|
||||
size_t minBytes = capacity * elemSize + sizeof(Header);
|
||||
size_t bytesToAlloc;
|
||||
if (minBytes >= pageSize) {
|
||||
// Round up to the next multiple of pageSize.
|
||||
bytesToAlloc = pageSize * ((minBytes + pageSize - 1) / pageSize);
|
||||
}
|
||||
else {
|
||||
// Round up to the next power of two. See
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||
bytesToAlloc = minBytes - 1;
|
||||
bytesToAlloc |= bytesToAlloc >> 1;
|
||||
bytesToAlloc |= bytesToAlloc >> 2;
|
||||
bytesToAlloc |= bytesToAlloc >> 4;
|
||||
bytesToAlloc |= bytesToAlloc >> 8;
|
||||
bytesToAlloc |= bytesToAlloc >> 16;
|
||||
bytesToAlloc++;
|
||||
|
||||
MOZ_ASSERT((bytesToAlloc & (bytesToAlloc - 1)) == 0,
|
||||
"nsTArray's allocation size should be a power of two!");
|
||||
}
|
||||
size_t nbytes, newCapacity;
|
||||
GoodSizeForCapacity(capacity, elemSize, nbytes, newCapacity);
|
||||
|
||||
Header *header;
|
||||
if (UsesAutoArrayBuffer() || !Copy::allowRealloc) {
|
||||
// Malloc() and copy
|
||||
header = static_cast<Header*>(Alloc::Malloc(bytesToAlloc));
|
||||
if (!header)
|
||||
if (mHdr == EmptyHdr()) {
|
||||
// Malloc() new data
|
||||
header = static_cast<Header*>(Alloc::Malloc(nbytes));
|
||||
if (!header) {
|
||||
return Alloc::FailureResult();
|
||||
}
|
||||
header->mLength = 0;
|
||||
header->mIsAutoArray = 0;
|
||||
|
||||
} else if (UsesAutoArrayBuffer() || !Copy::allowRealloc) {
|
||||
// Malloc() and copy
|
||||
header = static_cast<Header*>(Alloc::Malloc(nbytes));
|
||||
if (!header) {
|
||||
return Alloc::FailureResult();
|
||||
}
|
||||
Copy::CopyHeaderAndElements(header, mHdr, Length(), elemSize);
|
||||
|
||||
if (!UsesAutoArrayBuffer())
|
||||
if (!UsesAutoArrayBuffer()) {
|
||||
Alloc::Free(mHdr);
|
||||
}
|
||||
} else {
|
||||
// Realloc() existing data
|
||||
header = static_cast<Header*>(Alloc::Realloc(mHdr, bytesToAlloc));
|
||||
if (!header)
|
||||
header = static_cast<Header*>(Alloc::Realloc(mHdr, nbytes));
|
||||
if (!header) {
|
||||
return Alloc::FailureResult();
|
||||
}
|
||||
}
|
||||
|
||||
// How many elements can we fit in bytesToAlloc?
|
||||
size_t newCapacity = (bytesToAlloc - sizeof(Header)) / elemSize;
|
||||
MOZ_ASSERT(newCapacity >= capacity, "Didn't enlarge the array enough!");
|
||||
header->mCapacity = newCapacity;
|
||||
|
||||
mHdr = header;
|
||||
@ -215,12 +223,17 @@ nsTArray_base<Alloc, Copy>::ShrinkCapacity(size_type elemSize, size_t elemAlign)
|
||||
return;
|
||||
}
|
||||
|
||||
size_type size = sizeof(Header) + length * elemSize;
|
||||
void *ptr = Alloc::Realloc(mHdr, size);
|
||||
if (!ptr)
|
||||
return;
|
||||
mHdr = static_cast<Header*>(ptr);
|
||||
mHdr->mCapacity = length;
|
||||
// Only shrink if it would actually result in us using less memory.
|
||||
size_t nbytes, newCapacity;
|
||||
GoodSizeForCapacity(length, elemSize, nbytes, newCapacity);
|
||||
if (newCapacity < Capacity()) {
|
||||
void *ptr = Alloc::Realloc(mHdr, nbytes);
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
mHdr = static_cast<Header*>(ptr);
|
||||
mHdr->mCapacity = newCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Alloc, class Copy>
|
||||
|
@ -391,13 +391,25 @@ protected:
|
||||
|
||||
~nsTArray_base();
|
||||
|
||||
// For a required capacity, computes how many bytes should be allocated to
|
||||
// minimize slop, and how many elements will fit in that space.
|
||||
// @param capacity The required capacity.
|
||||
// @param elemSize The size of an array element.
|
||||
// @param capacity The computed size, in bytes (outparam).
|
||||
// @param capacity The resulting capacity (outparam).
|
||||
void GoodSizeForCapacity(size_t capacity, size_t elemSize,
|
||||
size_t& nbytes, size_t& newCapacity);
|
||||
|
||||
// Resize the storage if necessary to achieve the requested capacity.
|
||||
// @param capacity The requested number of array elements.
|
||||
// @param elemSize The size of an array element.
|
||||
// @return False if insufficient memory is available; true otherwise.
|
||||
typename Alloc::ResultTypeProxy EnsureCapacity(size_type capacity, size_type elemSize);
|
||||
|
||||
// Resize the storage to the minimum required amount.
|
||||
// Resize the storage to the minimum required amount. Note that this won't
|
||||
// reallocate the storage buffer if it wouldn't actually result in us using
|
||||
// less memory, which is the case when the number of bytes removed is less
|
||||
// than the slop that would result from the new size.
|
||||
// @param elemSize The size of an array element.
|
||||
// @param elemAlign The alignment in bytes of an array element.
|
||||
void ShrinkCapacity(size_type elemSize, size_t elemAlign);
|
||||
@ -1368,10 +1380,10 @@ public:
|
||||
// Allocation
|
||||
//
|
||||
|
||||
// This method may increase the capacity of this array object by the
|
||||
// specified amount. This method may be called in advance of several
|
||||
// AppendElement operations to minimize heap re-allocations. This method
|
||||
// will not reduce the number of elements in this array.
|
||||
// This method may increase the capacity of this array object to the
|
||||
// specified amount, or possibly more. This method may be called in advance
|
||||
// of several AppendElement operations to minimize heap re-allocations. This
|
||||
// method will not reduce the number of elements in this array.
|
||||
// @param capacity The desired capacity of this array.
|
||||
// @return True if the operation succeeded; false if we ran out of memory
|
||||
typename Alloc::ResultType SetCapacity(size_type capacity) {
|
||||
|
@ -115,12 +115,8 @@ static bool test_basic_array(ElementType *data,
|
||||
}
|
||||
if (!ary.AppendElements(copy))
|
||||
return false;
|
||||
size_t cap = ary.Capacity();
|
||||
ary.RemoveElementsAt(copy.Length(), copy.Length());
|
||||
ary.Compact();
|
||||
if (ary.Capacity() == cap)
|
||||
return false;
|
||||
|
||||
ary.Clear();
|
||||
if (ary.IndexOf(extra) != ary.NoIndex)
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user