mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 877762 - GC: Post-barrier cycle collector participants - 2 Stop nsTArray memmoving Heap<T>s r=jlebar r=bz
This commit is contained in:
parent
7295df4d69
commit
82a8b49403
@ -8,22 +8,22 @@
|
||||
# error "Don't include this file directly"
|
||||
#endif
|
||||
|
||||
template<class Alloc>
|
||||
nsTArray_base<Alloc>::nsTArray_base()
|
||||
template<class Alloc, class Copy>
|
||||
nsTArray_base<Alloc, Copy>::nsTArray_base()
|
||||
: mHdr(EmptyHdr()) {
|
||||
MOZ_COUNT_CTOR(nsTArray_base);
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
nsTArray_base<Alloc>::~nsTArray_base() {
|
||||
template<class Alloc, class Copy>
|
||||
nsTArray_base<Alloc, Copy>::~nsTArray_base() {
|
||||
if (mHdr != EmptyHdr() && !UsesAutoArrayBuffer()) {
|
||||
Alloc::Free(mHdr);
|
||||
}
|
||||
MOZ_COUNT_DTOR(nsTArray_base);
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
const nsTArrayHeader* nsTArray_base<Alloc>::GetAutoArrayBufferUnsafe(size_t elemAlign) const {
|
||||
template<class Alloc, class Copy>
|
||||
const nsTArrayHeader* nsTArray_base<Alloc, Copy>::GetAutoArrayBufferUnsafe(size_t elemAlign) const {
|
||||
// Assuming |this| points to an nsAutoArray, we want to get a pointer to
|
||||
// mAutoBuf. So just cast |this| to nsAutoArray* and read &mAutoBuf!
|
||||
|
||||
@ -48,8 +48,8 @@ const nsTArrayHeader* nsTArray_base<Alloc>::GetAutoArrayBufferUnsafe(size_t elem
|
||||
return reinterpret_cast<const Header*>(autoBuf);
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
bool nsTArray_base<Alloc>::UsesAutoArrayBuffer() const {
|
||||
template<class Alloc, class Copy>
|
||||
bool nsTArray_base<Alloc, Copy>::UsesAutoArrayBuffer() const {
|
||||
if (!mHdr->mIsAutoArray) {
|
||||
return false;
|
||||
}
|
||||
@ -96,9 +96,9 @@ bool nsTArray_base<Alloc>::UsesAutoArrayBuffer() const {
|
||||
}
|
||||
|
||||
|
||||
template<class Alloc>
|
||||
template<class Alloc, class Copy>
|
||||
typename Alloc::ResultTypeProxy
|
||||
nsTArray_base<Alloc>::EnsureCapacity(size_type capacity, size_type elemSize) {
|
||||
nsTArray_base<Alloc, Copy>::EnsureCapacity(size_type capacity, size_type elemSize) {
|
||||
// This should be the most common case so test this first
|
||||
if (capacity <= mHdr->mCapacity)
|
||||
return Alloc::SuccessResult();
|
||||
@ -155,13 +155,16 @@ nsTArray_base<Alloc>::EnsureCapacity(size_type capacity, size_type elemSize) {
|
||||
}
|
||||
|
||||
Header *header;
|
||||
if (UsesAutoArrayBuffer()) {
|
||||
if (UsesAutoArrayBuffer() || !Copy::allowRealloc) {
|
||||
// Malloc() and copy
|
||||
header = static_cast<Header*>(Alloc::Malloc(bytesToAlloc));
|
||||
if (!header)
|
||||
return Alloc::FailureResult();
|
||||
|
||||
memcpy(header, mHdr, sizeof(Header) + Length() * elemSize);
|
||||
Copy::CopyHeaderAndElements(header, mHdr, Length(), elemSize);
|
||||
|
||||
if (!UsesAutoArrayBuffer())
|
||||
Alloc::Free(mHdr);
|
||||
} else {
|
||||
// Realloc() existing data
|
||||
header = static_cast<Header*>(Alloc::Realloc(mHdr, bytesToAlloc));
|
||||
@ -179,9 +182,9 @@ nsTArray_base<Alloc>::EnsureCapacity(size_type capacity, size_type elemSize) {
|
||||
return Alloc::SuccessResult();
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
template<class Alloc, class Copy>
|
||||
void
|
||||
nsTArray_base<Alloc>::ShrinkCapacity(size_type elemSize, size_t elemAlign) {
|
||||
nsTArray_base<Alloc, Copy>::ShrinkCapacity(size_type elemSize, size_t elemAlign) {
|
||||
if (mHdr == EmptyHdr() || UsesAutoArrayBuffer())
|
||||
return;
|
||||
|
||||
@ -195,7 +198,7 @@ nsTArray_base<Alloc>::ShrinkCapacity(size_type elemSize, size_t elemAlign) {
|
||||
|
||||
// Copy data, but don't copy the header to avoid overwriting mCapacity
|
||||
header->mLength = length;
|
||||
memcpy(header + 1, mHdr + 1, length * elemSize);
|
||||
Copy::CopyElements(header + 1, mHdr + 1, length, elemSize);
|
||||
|
||||
Alloc::Free(mHdr);
|
||||
mHdr = header;
|
||||
@ -217,9 +220,9 @@ nsTArray_base<Alloc>::ShrinkCapacity(size_type elemSize, size_t elemAlign) {
|
||||
mHdr->mCapacity = length;
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
template<class Alloc, class Copy>
|
||||
void
|
||||
nsTArray_base<Alloc>::ShiftData(index_type start,
|
||||
nsTArray_base<Alloc, Copy>::ShiftData(index_type start,
|
||||
size_type oldLen, size_type newLen,
|
||||
size_type elemSize, size_t elemAlign) {
|
||||
if (oldLen == newLen)
|
||||
@ -240,15 +243,14 @@ nsTArray_base<Alloc>::ShiftData(index_type start,
|
||||
start *= elemSize;
|
||||
newLen *= elemSize;
|
||||
oldLen *= elemSize;
|
||||
num *= elemSize;
|
||||
char *base = reinterpret_cast<char*>(mHdr + 1) + start;
|
||||
memmove(base + newLen, base + oldLen, num);
|
||||
Copy::MoveElements(base + newLen, base + oldLen, num, elemSize);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
template<class Alloc, class Copy>
|
||||
bool
|
||||
nsTArray_base<Alloc>::InsertSlotsAt(index_type index, size_type count,
|
||||
nsTArray_base<Alloc, Copy>::InsertSlotsAt(index_type index, size_type count,
|
||||
size_type elementSize, size_t elemAlign) {
|
||||
MOZ_ASSERT(index <= Length(), "Bogus insertion index");
|
||||
size_type newLen = Length() + count;
|
||||
@ -262,7 +264,7 @@ nsTArray_base<Alloc>::InsertSlotsAt(index_type index, size_type count,
|
||||
// Move the existing elements as needed. Note that this will
|
||||
// change our mLength, so no need to call IncrementLength.
|
||||
ShiftData(index, 0, count, elementSize, elemAlign);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -274,18 +276,18 @@ nsTArray_base<Alloc>::InsertSlotsAt(index_type index, size_type count,
|
||||
// * if array has an auto buffer and mHdr would otherwise point to sEmptyHdr,
|
||||
// array.mHdr points to array's auto buffer.
|
||||
|
||||
template<class Alloc>
|
||||
nsTArray_base<Alloc>::IsAutoArrayRestorer::IsAutoArrayRestorer(
|
||||
nsTArray_base<Alloc> &array,
|
||||
size_t elemAlign)
|
||||
template<class Alloc, class Copy>
|
||||
nsTArray_base<Alloc, Copy>::IsAutoArrayRestorer::IsAutoArrayRestorer(
|
||||
nsTArray_base<Alloc, Copy> &array,
|
||||
size_t elemAlign)
|
||||
: mArray(array),
|
||||
mElemAlign(elemAlign),
|
||||
mIsAuto(array.IsAutoArray())
|
||||
{
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
nsTArray_base<Alloc>::IsAutoArrayRestorer::~IsAutoArrayRestorer() {
|
||||
template<class Alloc, class Copy>
|
||||
nsTArray_base<Alloc, Copy>::IsAutoArrayRestorer::~IsAutoArrayRestorer() {
|
||||
// Careful: We don't want to set mIsAutoArray = 1 on sEmptyHdr.
|
||||
if (mIsAuto && mArray.mHdr == mArray.EmptyHdr()) {
|
||||
// Call GetAutoArrayBufferUnsafe() because GetAutoArrayBuffer() asserts
|
||||
@ -298,12 +300,11 @@ nsTArray_base<Alloc>::IsAutoArrayRestorer::~IsAutoArrayRestorer() {
|
||||
}
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
template<class Alloc, class Copy>
|
||||
template<class Allocator>
|
||||
typename Alloc::ResultTypeProxy
|
||||
nsTArray_base<Alloc>::SwapArrayElements(nsTArray_base<Allocator>& other,
|
||||
size_type elemSize,
|
||||
size_t elemAlign) {
|
||||
nsTArray_base<Alloc, Copy>::SwapArrayElements(nsTArray_base<Allocator, Copy>& other,
|
||||
size_type elemSize, size_t elemAlign) {
|
||||
|
||||
// EnsureNotUsingAutoArrayBuffer will set mHdr = sEmptyHdr even if we have an
|
||||
// auto buffer. We need to point mHdr back to our auto buffer before we
|
||||
@ -311,7 +312,7 @@ nsTArray_base<Alloc>::SwapArrayElements(nsTArray_base<Allocator>& other,
|
||||
// IsAutoArrayRestorer takes care of this for us.
|
||||
|
||||
IsAutoArrayRestorer ourAutoRestorer(*this, elemAlign);
|
||||
typename nsTArray_base<Allocator>::IsAutoArrayRestorer otherAutoRestorer(other, elemAlign);
|
||||
typename nsTArray_base<Allocator, Copy>::IsAutoArrayRestorer otherAutoRestorer(other, elemAlign);
|
||||
|
||||
// If neither array uses an auto buffer which is big enough to store the
|
||||
// other array's elements, then ensure that both arrays use malloc'ed storage
|
||||
@ -331,7 +332,7 @@ nsTArray_base<Alloc>::SwapArrayElements(nsTArray_base<Allocator>& other,
|
||||
return Alloc::SuccessResult();
|
||||
}
|
||||
|
||||
// Swap the two arrays using memcpy, since at least one is using an auto
|
||||
// Swap the two arrays by copying, since at least one is using an auto
|
||||
// buffer which is large enough to hold all of the other's elements. We'll
|
||||
// copy the shorter array into temporary storage.
|
||||
//
|
||||
@ -375,9 +376,9 @@ nsTArray_base<Alloc>::SwapArrayElements(nsTArray_base<Allocator>& other,
|
||||
return Alloc::FailureResult();
|
||||
}
|
||||
|
||||
memcpy(temp.Elements(), smallerElements, smallerLength * elemSize);
|
||||
memcpy(smallerElements, largerElements, largerLength * elemSize);
|
||||
memcpy(largerElements, temp.Elements(), smallerLength * elemSize);
|
||||
Copy::CopyElements(temp.Elements(), smallerElements, smallerLength, elemSize);
|
||||
Copy::CopyElements(smallerElements, largerElements, largerLength, elemSize);
|
||||
Copy::CopyElements(largerElements, temp.Elements(), smallerLength, elemSize);
|
||||
|
||||
// Swap the arrays' lengths.
|
||||
NS_ABORT_IF_FALSE((other.Length() == 0 || mHdr != EmptyHdr()) &&
|
||||
@ -390,9 +391,9 @@ nsTArray_base<Alloc>::SwapArrayElements(nsTArray_base<Allocator>& other,
|
||||
return Alloc::SuccessResult();
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
template<class Alloc, class Copy>
|
||||
bool
|
||||
nsTArray_base<Alloc>::EnsureNotUsingAutoArrayBuffer(size_type elemSize) {
|
||||
nsTArray_base<Alloc, Copy>::EnsureNotUsingAutoArrayBuffer(size_type elemSize) {
|
||||
if (UsesAutoArrayBuffer()) {
|
||||
|
||||
// If you call this on a 0-length array, we'll set that array's mHdr to
|
||||
@ -410,10 +411,10 @@ nsTArray_base<Alloc>::EnsureNotUsingAutoArrayBuffer(size_type elemSize) {
|
||||
if (!header)
|
||||
return false;
|
||||
|
||||
memcpy(header, mHdr, size);
|
||||
Copy::CopyHeaderAndElements(header, mHdr, Length(), elemSize);
|
||||
header->mCapacity = Length();
|
||||
mHdr = header;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -22,6 +22,11 @@
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include NEW_H
|
||||
|
||||
namespace JS {
|
||||
template <class T>
|
||||
class Heap;
|
||||
} /* namespace JS */
|
||||
|
||||
//
|
||||
// nsTArray is a resizable array class, like std::vector.
|
||||
//
|
||||
@ -56,6 +61,9 @@
|
||||
// T MAY define operator< for sorting.
|
||||
// T MAY define operator== for searching.
|
||||
//
|
||||
// (Note that the memmove requirement may be relaxed for certain types - see
|
||||
// nsTArray_CopyElements below.)
|
||||
//
|
||||
// For methods taking a Comparator instance, the Comparator must be a class
|
||||
// defining the following methods:
|
||||
//
|
||||
@ -342,13 +350,13 @@ struct nsTArray_SafeElementAtHelper<nsRefPtr<E>, Derived> :
|
||||
// directly. It holds common implementation code that does not depend on the
|
||||
// element type of the nsTArray.
|
||||
//
|
||||
template<class Alloc>
|
||||
template<class Alloc, class Copy>
|
||||
class nsTArray_base
|
||||
{
|
||||
// Allow swapping elements with |nsTArray_base|s created using a
|
||||
// different allocator. This is kosher because all allocators use
|
||||
// the same free().
|
||||
template<class Allocator>
|
||||
template<class Allocator, class Copier>
|
||||
friend class nsTArray_base;
|
||||
|
||||
protected:
|
||||
@ -396,7 +404,7 @@ protected:
|
||||
// @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);
|
||||
|
||||
|
||||
// This method may be called to resize a "gap" in the array by shifting
|
||||
// elements around. It updates mLength appropriately. If the resulting
|
||||
// array has zero elements, then the array's memory is free'd.
|
||||
@ -435,18 +443,18 @@ protected:
|
||||
protected:
|
||||
template<class Allocator>
|
||||
typename Alloc::ResultTypeProxy
|
||||
SwapArrayElements(nsTArray_base<Allocator>& other,
|
||||
SwapArrayElements(nsTArray_base<Allocator, Copy>& other,
|
||||
size_type elemSize,
|
||||
size_t elemAlign);
|
||||
|
||||
// This is an RAII class used in SwapArrayElements.
|
||||
class IsAutoArrayRestorer {
|
||||
public:
|
||||
IsAutoArrayRestorer(nsTArray_base<Alloc> &array, size_t elemAlign);
|
||||
IsAutoArrayRestorer(nsTArray_base<Alloc, Copy> &array, size_t elemAlign);
|
||||
~IsAutoArrayRestorer();
|
||||
|
||||
private:
|
||||
nsTArray_base<Alloc> &mArray;
|
||||
nsTArray_base<Alloc, Copy> &mArray;
|
||||
size_t mElemAlign;
|
||||
bool mIsAuto;
|
||||
};
|
||||
@ -473,7 +481,7 @@ protected:
|
||||
// Returns a Header for the built-in buffer of this nsAutoTArray, but doesn't
|
||||
// assert that we are an nsAutoTArray.
|
||||
Header* GetAutoArrayBufferUnsafe(size_t elemAlign) {
|
||||
return const_cast<Header*>(static_cast<const nsTArray_base<Alloc>*>(this)->
|
||||
return const_cast<Header*>(static_cast<const nsTArray_base<Alloc, Copy>*>(this)->
|
||||
GetAutoArrayBufferUnsafe(elemAlign));
|
||||
}
|
||||
const Header* GetAutoArrayBufferUnsafe(size_t elemAlign) const;
|
||||
@ -486,7 +494,7 @@ protected:
|
||||
// null. If the array is empty, then this will point to sEmptyHdr.
|
||||
Header *mHdr;
|
||||
|
||||
Header* Hdr() const {
|
||||
Header* Hdr() const {
|
||||
return mHdr;
|
||||
}
|
||||
|
||||
@ -563,6 +571,139 @@ struct AssignRangeAlgorithm<true, true> {
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Normally elements are copied with memcpy and memmove, but for some element
|
||||
// types that is problematic. The nsTArray_CopyElements template class can be
|
||||
// specialized to ensure that copying calls constructors and destructors
|
||||
// instead, as is done below for JS::Heap<E> elements.
|
||||
//
|
||||
|
||||
//
|
||||
// A class that defines how to copy elements using memcpy/memmove.
|
||||
//
|
||||
struct nsTArray_CopyWithMemutils
|
||||
{
|
||||
const static bool allowRealloc = true;
|
||||
|
||||
static void CopyElements(void* dest, const void* src, size_t count, size_t elemSize) {
|
||||
memcpy(dest, src, count * elemSize);
|
||||
}
|
||||
|
||||
static void CopyHeaderAndElements(void* dest, const void* src, size_t count, size_t elemSize) {
|
||||
memcpy(dest, src, sizeof(nsTArrayHeader) + count * elemSize);
|
||||
}
|
||||
|
||||
static void MoveElements(void* dest, const void* src, size_t count, size_t elemSize) {
|
||||
memmove(dest, src, count * elemSize);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// A template class that defines how to copy elements calling their constructors
|
||||
// and destructors appropriately.
|
||||
//
|
||||
template <class ElemType>
|
||||
struct nsTArray_CopyWithConstructors
|
||||
{
|
||||
typedef nsTArrayElementTraits<ElemType> traits;
|
||||
|
||||
const static bool allowRealloc = false;
|
||||
|
||||
static void CopyElements(void* dest, void* src, size_t count, size_t elemSize) {
|
||||
ElemType* destElem = static_cast<ElemType*>(dest);
|
||||
ElemType* srcElem = static_cast<ElemType*>(src);
|
||||
ElemType* destElemEnd = destElem + count;
|
||||
#ifdef DEBUG
|
||||
ElemType* srcElemEnd = srcElem + count;
|
||||
MOZ_ASSERT(srcElemEnd <= destElem || srcElemEnd > destElemEnd);
|
||||
#endif
|
||||
while (destElem != destElemEnd) {
|
||||
traits::Construct(destElem, *srcElem);
|
||||
traits::Destruct(srcElem);
|
||||
++destElem;
|
||||
++srcElem;
|
||||
}
|
||||
}
|
||||
|
||||
static void CopyHeaderAndElements(void* dest, void* src, size_t count, size_t elemSize) {
|
||||
nsTArrayHeader* destHeader = static_cast<nsTArrayHeader*>(dest);
|
||||
nsTArrayHeader* srcHeader = static_cast<nsTArrayHeader*>(src);
|
||||
*destHeader = *srcHeader;
|
||||
CopyElements(static_cast<uint8_t*>(dest) + sizeof(nsTArrayHeader),
|
||||
static_cast<uint8_t*>(src) + sizeof(nsTArrayHeader),
|
||||
count, elemSize);
|
||||
}
|
||||
|
||||
static void MoveElements(void* dest, void* src, size_t count, size_t elemSize) {
|
||||
ElemType* destElem = static_cast<ElemType*>(dest);
|
||||
ElemType* srcElem = static_cast<ElemType*>(src);
|
||||
ElemType* destElemEnd = destElem + count;
|
||||
ElemType* srcElemEnd = srcElem + count;
|
||||
if (destElem == srcElem) {
|
||||
return; // In practice, we don't do this.
|
||||
} else if (srcElemEnd > destElem && srcElemEnd < destElemEnd) {
|
||||
while (destElemEnd != destElem) {
|
||||
--destElemEnd;
|
||||
--srcElemEnd;
|
||||
traits::Construct(destElemEnd, *srcElemEnd);
|
||||
traits::Destruct(srcElem);
|
||||
}
|
||||
} else {
|
||||
CopyElements(dest, src, count, elemSize);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// The default behaviour is to use memcpy/memmove for everything.
|
||||
//
|
||||
template <class E>
|
||||
struct nsTArray_CopyElements : public nsTArray_CopyWithMemutils {};
|
||||
|
||||
//
|
||||
// JS::Heap<E> elements require constructors/destructors to be called and so is
|
||||
// specialized here.
|
||||
//
|
||||
template <class E>
|
||||
struct nsTArray_CopyElements<JS::Heap<E> > : public nsTArray_CopyWithConstructors<E> {};
|
||||
|
||||
//
|
||||
// Base class for nsTArray_Impl that is templated on element type and derived
|
||||
// nsTArray_Impl class, to allow extra conversions to be added for specific
|
||||
// types.
|
||||
//
|
||||
template <class E, class Derived>
|
||||
struct nsTArray_TypedBase : public nsTArray_SafeElementAtHelper<E, Derived> {};
|
||||
|
||||
//
|
||||
// Specialization of nsTArray_TypedBase for arrays containing JS::Heap<E>
|
||||
// elements.
|
||||
//
|
||||
// These conversions are safe because JS::Heap<E> and E share the same
|
||||
// representation, and since the result of the conversions are const references
|
||||
// we won't miss any barriers.
|
||||
//
|
||||
// The static_cast is necessary to obtain the correct address for the derived
|
||||
// class since we are a base class used in multiple inheritance.
|
||||
//
|
||||
template <class E, class Derived>
|
||||
struct nsTArray_TypedBase<JS::Heap<E>, Derived>
|
||||
: public nsTArray_SafeElementAtHelper<JS::Heap<E>, Derived>
|
||||
{
|
||||
operator const nsTArray<E>& () {
|
||||
MOZ_STATIC_ASSERT(sizeof(E) == sizeof(JS::Heap<E>),
|
||||
"JS::Heap<E> must be binary compatible with E.");
|
||||
Derived* self = static_cast<Derived*>(this);
|
||||
return *reinterpret_cast<nsTArray<E> *>(self);
|
||||
}
|
||||
|
||||
operator const FallibleTArray<E>& () {
|
||||
Derived* self = static_cast<Derived*>(this);
|
||||
return *reinterpret_cast<FallibleTArray<E> *>(self);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// nsTArray_Impl contains most of the guts supporting nsTArray, FallibleTArray,
|
||||
// nsAutoTArray, and AutoFallibleTArray.
|
||||
@ -576,16 +717,17 @@ struct AssignRangeAlgorithm<true, true> {
|
||||
// TArrays can be cast to |const nsTArray&|.
|
||||
//
|
||||
template<class E, class Alloc>
|
||||
class nsTArray_Impl : public nsTArray_base<Alloc>,
|
||||
public nsTArray_SafeElementAtHelper<E, nsTArray_Impl<E, Alloc> >
|
||||
class nsTArray_Impl : public nsTArray_base<Alloc, nsTArray_CopyElements<E> >,
|
||||
public nsTArray_TypedBase<E, nsTArray_Impl<E, Alloc> >
|
||||
{
|
||||
public:
|
||||
typedef nsTArray_base<Alloc> base_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::index_type index_type;
|
||||
typedef E elem_type;
|
||||
typedef nsTArray_Impl<E, Alloc> self_type;
|
||||
typedef nsTArrayElementTraits<E> elem_traits;
|
||||
typedef nsTArray_CopyElements<E> copy_type;
|
||||
typedef nsTArray_base<Alloc, copy_type> base_type;
|
||||
typedef typename base_type::size_type size_type;
|
||||
typedef typename base_type::index_type index_type;
|
||||
typedef E elem_type;
|
||||
typedef nsTArray_Impl<E, Alloc> self_type;
|
||||
typedef nsTArrayElementTraits<E> elem_traits;
|
||||
typedef nsTArray_SafeElementAtHelper<E, self_type> safeelementat_helper_type;
|
||||
|
||||
using safeelementat_helper_type::SafeElementAt;
|
||||
@ -716,7 +858,7 @@ public:
|
||||
const elem_type* Elements() const {
|
||||
return reinterpret_cast<const elem_type *>(Hdr() + 1);
|
||||
}
|
||||
|
||||
|
||||
// This method provides direct access to the i'th element of the array.
|
||||
// The given index must be within the array bounds.
|
||||
// @param i The index of an element in the array.
|
||||
@ -1083,7 +1225,7 @@ public:
|
||||
return AppendElements(1);
|
||||
}
|
||||
|
||||
// Move all elements from another array to the end of this array without
|
||||
// Move all elements from another array to the end of this array without
|
||||
// calling copy constructors or destructors.
|
||||
// @return A pointer to the newly appended elements, or null on OOM.
|
||||
template<class Item, class Allocator>
|
||||
@ -1093,8 +1235,8 @@ public:
|
||||
index_type otherLen = array.Length();
|
||||
if (!Alloc::Successful(this->EnsureCapacity(len + otherLen, sizeof(elem_type))))
|
||||
return nullptr;
|
||||
memcpy(Elements() + len, array.Elements(), otherLen * sizeof(elem_type));
|
||||
this->IncrementLength(otherLen);
|
||||
copy_type::CopyElements(Elements() + len, array.Elements(), otherLen, sizeof(elem_type));
|
||||
this->IncrementLength(otherLen);
|
||||
array.ShiftData(0, otherLen, 0, sizeof(elem_type), MOZ_ALIGNOF(elem_type));
|
||||
return Elements() + len;
|
||||
}
|
||||
@ -1201,7 +1343,7 @@ public:
|
||||
if (newLen > oldLen) {
|
||||
return InsertElementsAt(oldLen, newLen - oldLen) != nullptr;
|
||||
}
|
||||
|
||||
|
||||
TruncateLength(newLen);
|
||||
return true;
|
||||
}
|
||||
@ -1283,7 +1425,7 @@ typename Alloc::ResultType EnsureLengthAtLeast(size_type minLen) {
|
||||
//
|
||||
// Sorting
|
||||
//
|
||||
|
||||
|
||||
// This function is meant to be used with the NS_QuickSort function. It
|
||||
// maps the callback API expected by NS_QuickSort to the Comparator API
|
||||
// used by nsTArray_Impl. See nsTArray_Impl::Sort.
|
||||
@ -1396,8 +1538,8 @@ protected:
|
||||
|
||||
// This method invokes elem_type's copy-constructor on a range of elements.
|
||||
// @param start The index of the first element to construct.
|
||||
// @param count The number of elements to construct.
|
||||
// @param values The array of elements to copy.
|
||||
// @param count The number of elements to construct.
|
||||
// @param values The array of elements to copy.
|
||||
template<class Item>
|
||||
void AssignRange(index_type start, size_type count,
|
||||
const Item *values) {
|
||||
@ -1533,7 +1675,7 @@ protected:
|
||||
private:
|
||||
// nsTArray_base casts itself as an nsAutoArrayBase in order to get a pointer
|
||||
// to mAutoBuf.
|
||||
template<class Allocator>
|
||||
template<class Allocator, class Copier>
|
||||
friend class nsTArray_base;
|
||||
|
||||
void Init() {
|
||||
|
Loading…
Reference in New Issue
Block a user