зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1654991 - Simplify move constructor of nsTArray_Impl. r=froydnj
The move constructor of nsTArray_Impl (and therefore of nsTArray) was implemented using SwapElements, which is a rather generic and therefore complex method (in the sense of template instantiation and code generation), which doesn't make use of the knowledge that the target array does not have inline storage and is empty with 0 capacity. Therefore, a new specialized method, MoveConstructNonAutoArray, is introduced that does use this knowledge. This adds another method to maintain, but given that the move constructor is a frequently used operation that is expected to have a small compile-time and run-time cost (potentially used implicitly), this seems like a reasonable trade-off. Differential Revision: https://phabricator.services.mozilla.com/D84804
This commit is contained in:
Родитель
32848c3a4f
Коммит
fcbd7f145f
|
@ -506,6 +506,38 @@ nsTArray_base<Alloc, RelocationStrategy>::SwapArrayElements(
|
|||
return ActualAlloc::SuccessResult();
|
||||
}
|
||||
|
||||
template <class Alloc, class RelocationStrategy>
|
||||
template <class Allocator>
|
||||
void nsTArray_base<Alloc, RelocationStrategy>::MoveConstructNonAutoArray(
|
||||
nsTArray_base<Allocator, RelocationStrategy>& aOther, size_type aElemSize,
|
||||
size_t aElemAlign) {
|
||||
// We know that we are not an (Copyable)AutoTArray and we know that we are
|
||||
// empty, so don't use SwapArrayElements which doesn't know either of these
|
||||
// facts and is very complex.
|
||||
|
||||
// aOther might be an (Copyable)AutoTArray though, and it might use its inline
|
||||
// buffer.
|
||||
const bool otherUsesAutoArrayBuffer = aOther.UsesAutoArrayBuffer();
|
||||
if (otherUsesAutoArrayBuffer) {
|
||||
// Use nsTArrayInfallibleAllocator regardless of Alloc because this is
|
||||
// called from a move constructor, which cannot report an error to the
|
||||
// caller.
|
||||
aOther.template EnsureNotUsingAutoArrayBuffer<nsTArrayInfallibleAllocator>(
|
||||
aElemSize);
|
||||
}
|
||||
|
||||
const bool otherIsAuto = otherUsesAutoArrayBuffer || aOther.IsAutoArray();
|
||||
mHdr = aOther.mHdr;
|
||||
|
||||
if (otherIsAuto) {
|
||||
mHdr->mIsAutoArray = false;
|
||||
aOther.mHdr = aOther.GetAutoArrayBufferUnsafe(aElemAlign);
|
||||
aOther.mHdr->mLength = 0;
|
||||
} else {
|
||||
aOther.mHdr = aOther.EmptyHdr();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Alloc, class RelocationStrategy>
|
||||
template <typename ActualAlloc>
|
||||
bool nsTArray_base<Alloc, RelocationStrategy>::EnsureNotUsingAutoArrayBuffer(
|
||||
|
|
|
@ -512,6 +512,11 @@ class nsTArray_base {
|
|||
nsTArray_base<Allocator, RelocationStrategy>& aOther, size_type aElemSize,
|
||||
size_t aElemAlign);
|
||||
|
||||
template <class Allocator>
|
||||
void MoveConstructNonAutoArray(
|
||||
nsTArray_base<Allocator, RelocationStrategy>& aOther, size_type aElemSize,
|
||||
size_t aElemAlign);
|
||||
|
||||
// This is an RAII class used in SwapArrayElements.
|
||||
class IsAutoArrayRestorer {
|
||||
public:
|
||||
|
@ -1007,8 +1012,13 @@ class nsTArray_Impl
|
|||
// Initialize this array with an r-value.
|
||||
// Allow different types of allocators, since the allocator doesn't matter.
|
||||
template <typename Allocator>
|
||||
explicit nsTArray_Impl(nsTArray_Impl<E, Allocator>&& aOther) {
|
||||
SwapElements(aOther);
|
||||
explicit nsTArray_Impl(nsTArray_Impl<E, Allocator>&& aOther) noexcept {
|
||||
// We cannot be a (Copyable)AutoTArray because that overrides this ctor.
|
||||
MOZ_ASSERT(!this->IsAutoArray());
|
||||
|
||||
// This does not use SwapArrayElements because that's unnecessarily complex.
|
||||
this->MoveConstructNonAutoArray(aOther, sizeof(elem_type),
|
||||
MOZ_ALIGNOF(elem_type));
|
||||
}
|
||||
|
||||
// The array's copy-constructor performs a 'deep' copy of the given array.
|
||||
|
|
Загрузка…
Ссылка в новой задаче