Bug 1170325 - Convert js::Vector into a template alias to mozilla::Vector with a single customized default argument. Also get rid of the CRTP support in mozilla::Vector (through mozilla::VectorBase) now that template aliasing is good enough, and make mozilla::Vector final so that people will use composition and not inheritance with it. (Inheritance plays poorly with movability and a few other things, in addition to messing up template argument deduction matching.) r=Waldo, patch sort of a tag-team between him and me

This commit is contained in:
Nick Fitzgerald 2015-07-13 12:42:52 -07:00
parent 1c73cd386d
commit 4c67f636ce
10 changed files with 303 additions and 255 deletions

View File

@ -43,14 +43,11 @@ public:
}
/**
* Get the deferred tasks in |mDeferredTasks|. See |mDeferredTasks|
* for more information.
* Clears |mDeferredTasks|.
* Get the deferred tasks in |mDeferredTasks| and place them in |aTasks|. See
* |mDeferredTasks| for more information. Clears |mDeferredTasks|.
*/
Vector<Task*> TakeDeferredTasks() {
Vector<Task*> result;
mDeferredTasks.swap(result);
return result;
void TakeDeferredTasks(Vector<Task*>& aTasks) {
mDeferredTasks.swap(aTasks);
}
/**

View File

@ -2880,7 +2880,7 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
if (mAnimation) {
bool continueAnimation = mAnimation->Sample(mFrameMetrics, sampleTimeDelta);
*aOutDeferredTasks = mAnimation->TakeDeferredTasks();
mAnimation->TakeDeferredTasks(*aOutDeferredTasks);
if (continueAnimation) {
if (mPaintThrottler->TimeSinceLastRequest(aSampleTime) >
mAnimation->mRepaintInterval) {

View File

@ -33,26 +33,96 @@ template <typename T,
size_t MinInlineCapacity = 0,
typename AllocPolicy = TempAllocPolicy,
typename GCPolicy = DefaultGCPolicy<T>>
class TraceableVector
: public mozilla::VectorBase<T,
MinInlineCapacity,
AllocPolicy,
TraceableVector<T, MinInlineCapacity, AllocPolicy, GCPolicy>>,
public JS::Traceable
class TraceableVector : public JS::Traceable
{
using Base = mozilla::VectorBase<T, MinInlineCapacity, AllocPolicy, TraceableVector>;
mozilla::Vector<T, MinInlineCapacity, AllocPolicy> vector;
public:
explicit TraceableVector(AllocPolicy alloc = AllocPolicy()) : Base(alloc) {}
TraceableVector(TraceableVector&& vec) : Base(mozilla::Forward<TraceableVector>(vec)) {}
explicit TraceableVector(AllocPolicy alloc = AllocPolicy())
: vector(alloc)
{}
TraceableVector(TraceableVector&& vec)
: vector(mozilla::Move(vec.vector))
{}
TraceableVector& operator=(TraceableVector&& vec) {
return Base::operator=(mozilla::Forward<TraceableVector>(vec));
vector = mozilla::Move(vec.vector);
return *this;
}
size_t length() const { return vector.length(); }
bool empty() const { return vector.empty(); }
size_t capacity() const { return vector.capacity(); }
T* begin() { return vector.begin(); }
const T* begin() const { return vector.begin(); }
T* end() { return vector.end(); }
const T* end() const { return vector.end(); }
T& operator[](size_t i) { return vector[i]; }
const T& operator[](size_t i) const { return vector[i]; }
T& back() { return vector.back(); }
const T& back() const { return vector.back(); }
bool initCapacity(size_t cap) { return vector.initCapacity(cap); }
bool reserve(size_t req) { return vector.reserve(req); }
void shrinkBy(size_t amount) { return vector.shrinkBy(amount); }
bool growBy(size_t amount) { return vector.growBy(amount); }
bool resize(size_t newLen) { return vector.resize(newLen); }
void clear() { return vector.clear(); }
template<typename U> bool append(U&& item) { return vector.append(mozilla::Forward<U>(item)); }
template<typename... Args>
bool
emplaceBack(Args&&... args) {
return vector.emplaceBack(mozilla::Forward<Args>(args)...);
}
template<typename U>
void infallibleAppend(U&& aU) {
return vector.infallibleAppend(mozilla::Forward<U>(aU));
}
void infallibleAppendN(const T& aT, size_t aN) {
return vector.infallibleAppendN(aT, aN);
}
template<typename U> void
infallibleAppend(const U* aBegin, const U* aEnd) {
return vector.infallibleAppend(aBegin, aEnd);
}
template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
return vector.infallibleAppend(aBegin, aLength);
}
bool appendN(const T& val, size_t count) { return vector.appendN(val, count); }
template<typename U> bool append(const U* aBegin, const U* aEnd) {
return vector.append(aBegin, aEnd);
}
template<typename U> bool append(const U* aBegin, size_t aLength) {
return vector.append(aBegin, aLength);
}
void popBack() { return vector.popBack(); }
T popCopy() { return vector.popCopy(); }
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
return vector.sizeOfExcludingThis(mallocSizeOf);
}
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
return vector.sizeOfIncludingThis(mallocSizeOf);
}
static void trace(TraceableVector* vec, JSTracer* trc) { vec->trace(trc); }
void trace(JSTracer* trc) {
for (size_t i = 0; i < this->length(); ++i)
GCPolicy::trace(trc, &Base::operator[](i), "vector element");
for (auto& elem : vector)
GCPolicy::trace(trc, &elem, "vector element");
}
};
@ -114,8 +184,8 @@ class MutableTraceableVectorOperations
template<typename... Args> bool emplaceBack(Args&&... aArgs) {
return vec().emplaceBack(mozilla::Forward<Args...>(aArgs...));
}
template<typename U, size_t O, class BP, class UV>
bool appendAll(const mozilla::VectorBase<U, O, BP, UV>& aU) { return vec().appendAll(aU); }
template<typename U, size_t O, class BP>
bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vec().appendAll(aU); }
bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); }
template<typename U> bool append(const U* aBegin, const U* aEnd) {
return vec().append(aBegin, aEnd);

View File

@ -19,47 +19,32 @@ namespace js {
class TempAllocPolicy;
// If we had C++11 template aliases, we could just use this:
//
// template <typename T,
// size_t MinInlineCapacity = 0,
// class AllocPolicy = TempAllocPolicy>
// using Vector = mozilla::Vector<T, MinInlineCapacity, AllocPolicy>;
//
// ...and get rid of all the CRTP madness in mozilla::Vector(Base). But we
// can't because compiler support's not up to snuff. (Template aliases are in
// gcc 4.7 and clang 3.0 and are expected to be in MSVC 2013.) Instead, have a
// completely separate class inheriting from mozilla::Vector, and throw CRTP at
// the problem til things work.
//
// This workaround presents a couple issues. First, because js::Vector is a
// distinct type from mozilla::Vector, overload resolution, method calls, etc.
// are affected. *Hopefully* this won't be too bad in practice. (A bunch of
// places had to be fixed when mozilla::Vector was introduced, but it wasn't a
// crazy number.) Second, mozilla::Vector's interface has to be made subclass-
// ready via CRTP -- or rather, via mozilla::VectorBase, which basically no one
// should use. :-) Third, we have to redefine the constructors and the non-
// inherited operators. Blech. Happily there aren't too many of these, so it
// isn't the end of the world.
namespace detail {
template <typename T>
struct TypeIsGCThing : mozilla::FalseType
{};
// Uncomment this once we actually can assert it:
//template <>
//struct TypeIsGCThing<JS::Value> : mozilla::TrueType
//{};
} // namespace detail
template <typename T,
size_t MinInlineCapacity = 0,
class AllocPolicy = TempAllocPolicy>
class Vector
: public mozilla::VectorBase<T,
MinInlineCapacity,
AllocPolicy,
Vector<T, MinInlineCapacity, AllocPolicy> >
{
typedef typename mozilla::VectorBase<T, MinInlineCapacity, AllocPolicy, Vector> Base;
public:
explicit Vector(AllocPolicy alloc = AllocPolicy()) : Base(alloc) {}
Vector(Vector&& vec) : Base(mozilla::Move(vec)) {}
Vector& operator=(Vector&& vec) {
return Base::operator=(mozilla::Move(vec));
}
};
class AllocPolicy = TempAllocPolicy
// 1800 is MSVC2013. Optimistically assume MSVC2015 (1900) is fixed.
// If you're porting to MSVC2015 and this doesn't work, extend the
// condition to encompass that additional version (but *do* keep the
// version-check so we know when MSVC's fixed).
#if !defined(_MSC_VER) || (1800 <= _MSC_VER && _MSC_VER <= 1800)
// Don't use this with JS::Value! Use JS::AutoValueVector instead.
, typename = typename mozilla::EnableIf<!detail::TypeIsGCThing<T>::value>::Type
#endif
>
using Vector = mozilla::Vector<T, MinInlineCapacity, AllocPolicy>;
} // namespace js

View File

@ -23,6 +23,7 @@
#include "mozilla/EnumeratedRange.h"
#include "mozilla/PodOperations.h"
#include "mozilla/TaggedAnonymousMemory.h"
#include "mozilla/Vector.h"
#include "jslibmath.h"
#include "jsmath.h"
@ -1132,7 +1133,7 @@ AsmJSModule::Name::clone(ExclusiveContext* cx, Name* out) const
template <class T, size_t N>
size_t
SerializedVectorSize(const Vector<T, N, SystemAllocPolicy>& vec)
SerializedVectorSize(const mozilla::Vector<T, N, SystemAllocPolicy>& vec)
{
size_t size = sizeof(uint32_t);
for (size_t i = 0; i < vec.length(); i++)
@ -1142,7 +1143,7 @@ SerializedVectorSize(const Vector<T, N, SystemAllocPolicy>& vec)
template <class T, size_t N>
uint8_t*
SerializeVector(uint8_t* cursor, const Vector<T, N, SystemAllocPolicy>& vec)
SerializeVector(uint8_t* cursor, const mozilla::Vector<T, N, SystemAllocPolicy>& vec)
{
cursor = WriteScalar<uint32_t>(cursor, vec.length());
for (size_t i = 0; i < vec.length(); i++)
@ -1152,7 +1153,8 @@ SerializeVector(uint8_t* cursor, const Vector<T, N, SystemAllocPolicy>& vec)
template <class T, size_t N>
const uint8_t*
DeserializeVector(ExclusiveContext* cx, const uint8_t* cursor, Vector<T, N, SystemAllocPolicy>* vec)
DeserializeVector(ExclusiveContext* cx, const uint8_t* cursor,
mozilla::Vector<T, N, SystemAllocPolicy>* vec)
{
uint32_t length;
cursor = ReadScalar<uint32_t>(cursor, &length);
@ -1167,8 +1169,8 @@ DeserializeVector(ExclusiveContext* cx, const uint8_t* cursor, Vector<T, N, Syst
template <class T, size_t N>
bool
CloneVector(ExclusiveContext* cx, const Vector<T, N, SystemAllocPolicy>& in,
Vector<T, N, SystemAllocPolicy>* out)
CloneVector(ExclusiveContext* cx, const mozilla::Vector<T, N, SystemAllocPolicy>& in,
mozilla::Vector<T, N, SystemAllocPolicy>* out)
{
if (!out->resize(in.length()))
return false;
@ -1179,27 +1181,27 @@ CloneVector(ExclusiveContext* cx, const Vector<T, N, SystemAllocPolicy>& in,
return true;
}
template <class T, size_t N, class AllocPolicy, class ThisVector>
template <class T, size_t N, class AllocPolicy>
size_t
SerializedPodVectorSize(const mozilla::VectorBase<T, N, AllocPolicy, ThisVector>& vec)
SerializedPodVectorSize(const mozilla::Vector<T, N, AllocPolicy>& vec)
{
return sizeof(uint32_t) +
vec.length() * sizeof(T);
}
template <class T, size_t N, class AllocPolicy, class ThisVector>
template <class T, size_t N, class AllocPolicy>
uint8_t*
SerializePodVector(uint8_t* cursor, const mozilla::VectorBase<T, N, AllocPolicy, ThisVector>& vec)
SerializePodVector(uint8_t* cursor, const mozilla::Vector<T, N, AllocPolicy>& vec)
{
cursor = WriteScalar<uint32_t>(cursor, vec.length());
cursor = WriteBytes(cursor, vec.begin(), vec.length() * sizeof(T));
return cursor;
}
template <class T, size_t N, class AllocPolicy, class ThisVector>
template <class T, size_t N, class AllocPolicy>
const uint8_t*
DeserializePodVector(ExclusiveContext* cx, const uint8_t* cursor,
mozilla::VectorBase<T, N, AllocPolicy, ThisVector>* vec)
mozilla::Vector<T, N, AllocPolicy>* vec)
{
uint32_t length;
cursor = ReadScalar<uint32_t>(cursor, &length);
@ -1211,8 +1213,8 @@ DeserializePodVector(ExclusiveContext* cx, const uint8_t* cursor,
template <class T, size_t N>
bool
ClonePodVector(ExclusiveContext* cx, const Vector<T, N, SystemAllocPolicy>& in,
Vector<T, N, SystemAllocPolicy>* out)
ClonePodVector(ExclusiveContext* cx, const mozilla::Vector<T, N, SystemAllocPolicy>& in,
mozilla::Vector<T, N, SystemAllocPolicy>* out)
{
if (!out->resize(in.length()))
return false;

View File

@ -9,6 +9,7 @@
#include "mozilla/FloatingPoint.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/NumericLimits.h"
#include "mozilla/Vector.h"
#include <math.h>
#include <stdint.h>
@ -40,6 +41,7 @@
#include "builtin/TypedObject.h"
#include "ctypes/Library.h"
#include "gc/Zone.h"
#include "js/Vector.h"
#include "jsatominlines.h"
#include "jsobjinlines.h"
@ -2658,7 +2660,7 @@ jsvalToPtrExplicit(JSContext* cx, Value val, uintptr_t* result)
template<class IntegerType, class CharType, size_t N, class AP>
void
IntegerToString(IntegerType i, int radix, Vector<CharType, N, AP>& result)
IntegerToString(IntegerType i, int radix, mozilla::Vector<CharType, N, AP>& result)
{
JS_STATIC_ASSERT(NumericLimits<IntegerType>::is_exact);
@ -3654,7 +3656,7 @@ BuildTypeSource(JSContext* cx,
const FieldInfoHash* fields = StructType::GetFieldInfo(typeObj);
size_t length = fields->count();
Array<const FieldInfoHash::Entry*, 64> fieldsArray;
Vector<const FieldInfoHash::Entry*, 64, SystemAllocPolicy> fieldsArray;
if (!fieldsArray.resize(length))
break;
@ -3812,7 +3814,7 @@ BuildDataSource(JSContext* cx,
// be able to ImplicitConvert successfully.
const FieldInfoHash* fields = StructType::GetFieldInfo(typeObj);
size_t length = fields->count();
Array<const FieldInfoHash::Entry*, 64> fieldsArray;
Vector<const FieldInfoHash::Entry*, 64, SystemAllocPolicy> fieldsArray;
if (!fieldsArray.resize(length))
return false;
@ -6510,7 +6512,7 @@ FunctionType::ConstructData(JSContext* cx,
return JS_FreezeObject(cx, dataObj);
}
typedef Array<AutoValue, 16> AutoValueAutoArray;
typedef Vector<AutoValue, 16, SystemAllocPolicy> AutoValueAutoArray;
static bool
ConvertArgument(JSContext* cx,

View File

@ -7,6 +7,7 @@
#define ctypes_CTypes_h
#include "mozilla/UniquePtr.h"
#include "mozilla/Vector.h"
#include "ffi.h"
#include "jsalloc.h"
@ -25,14 +26,6 @@ namespace ctypes {
** Utility classes
*******************************************************************************/
// Container class for Vector, using SystemAllocPolicy.
template<class T, size_t N = 0>
class Array : public Vector<T, N, SystemAllocPolicy>
{
static_assert(!mozilla::IsSame<T, JS::Value>::value,
"use JS::AutoValueVector instead");
};
// String and AutoString classes, based on Vector.
typedef Vector<char16_t, 0, SystemAllocPolicy> String;
typedef Vector<char16_t, 64, SystemAllocPolicy> AutoString;
@ -42,7 +35,7 @@ typedef Vector<char, 64, SystemAllocPolicy> AutoCString;
// Convenience functions to append, insert, and compare Strings.
template <class T, size_t N, class AP, size_t ArrayLength>
void
AppendString(Vector<T, N, AP>& v, const char (&array)[ArrayLength])
AppendString(mozilla::Vector<T, N, AP>& v, const char (&array)[ArrayLength])
{
// Don't include the trailing '\0'.
size_t alen = ArrayLength - 1;
@ -56,7 +49,7 @@ AppendString(Vector<T, N, AP>& v, const char (&array)[ArrayLength])
template <class T, size_t N, class AP>
void
AppendChars(Vector<T, N, AP>& v, const char c, size_t count)
AppendChars(mozilla::Vector<T, N, AP>& v, const char c, size_t count)
{
size_t vlen = v.length();
if (!v.resize(vlen + count))
@ -68,7 +61,7 @@ AppendChars(Vector<T, N, AP>& v, const char c, size_t count)
template <class T, size_t N, class AP>
void
AppendUInt(Vector<T, N, AP>& v, unsigned n)
AppendUInt(mozilla::Vector<T, N, AP>& v, unsigned n)
{
char array[16];
size_t alen = JS_snprintf(array, 16, "%u", n);
@ -82,14 +75,14 @@ AppendUInt(Vector<T, N, AP>& v, unsigned n)
template <class T, size_t N, size_t M, class AP>
void
AppendString(Vector<T, N, AP>& v, Vector<T, M, AP>& w)
AppendString(mozilla::Vector<T, N, AP>& v, mozilla::Vector<T, M, AP>& w)
{
v.append(w.begin(), w.length());
}
template <size_t N, class AP>
void
AppendString(Vector<char16_t, N, AP>& v, JSString* str)
AppendString(mozilla::Vector<char16_t, N, AP>& v, JSString* str)
{
MOZ_ASSERT(str);
JSLinearString* linear = str->ensureLinear(nullptr);
@ -104,7 +97,7 @@ AppendString(Vector<char16_t, N, AP>& v, JSString* str)
template <size_t N, class AP>
void
AppendString(Vector<char, N, AP>& v, JSString* str)
AppendString(mozilla::Vector<char, N, AP>& v, JSString* str)
{
MOZ_ASSERT(str);
size_t vlen = v.length();
@ -130,7 +123,7 @@ AppendString(Vector<char, N, AP>& v, JSString* str)
template <class T, size_t N, class AP, size_t ArrayLength>
void
PrependString(Vector<T, N, AP>& v, const char (&array)[ArrayLength])
PrependString(mozilla::Vector<T, N, AP>& v, const char (&array)[ArrayLength])
{
// Don't include the trailing '\0'.
size_t alen = ArrayLength - 1;
@ -148,7 +141,7 @@ PrependString(Vector<T, N, AP>& v, const char (&array)[ArrayLength])
template <size_t N, class AP>
void
PrependString(Vector<char16_t, N, AP>& v, JSString* str)
PrependString(mozilla::Vector<char16_t, N, AP>& v, JSString* str)
{
MOZ_ASSERT(str);
size_t vlen = v.length();
@ -306,12 +299,12 @@ struct FunctionInfo
// A fixed array of known parameter types, excluding any variadic
// parameters (if mIsVariadic).
Array<JS::Heap<JSObject*> > mArgTypes;
Vector<JS::Heap<JSObject*>, 0, SystemAllocPolicy> mArgTypes;
// A variable array of ffi_type*s corresponding to both known parameter
// types and dynamic (variadic) parameter types. Longer than mArgTypes
// only if mIsVariadic.
Array<ffi_type*> mFFITypes;
Vector<ffi_type*, 0, SystemAllocPolicy> mFFITypes;
// Flag indicating whether the function behaves like a C function with
// ... as the final formal parameter.

View File

@ -537,7 +537,7 @@ struct Callback {
};
template<typename F>
class CallbackVector : public Vector<Callback<F>, 4, SystemAllocPolicy> {};
using CallbackVector = Vector<Callback<F>, 4, SystemAllocPolicy>;
template <typename T, typename Iter0, typename Iter1>
class ChainedIter

View File

@ -31,8 +31,8 @@
namespace mozilla {
template<typename T, size_t N, class AllocPolicy, class ThisVector>
class VectorBase;
template<typename T, size_t N, class AllocPolicy>
class Vector;
namespace detail {
@ -52,7 +52,7 @@ static bool CapacityHasExcessSpace(size_t aCapacity)
* This template class provides a default implementation for vector operations
* when the element type is not known to be a POD, as judged by IsPod.
*/
template<typename T, size_t N, class AP, class ThisVector, bool IsPod>
template<typename T, size_t N, class AP, bool IsPod>
struct VectorImpl
{
/*
@ -138,7 +138,7 @@ struct VectorImpl
* not overflow.
*/
static inline bool
growTo(VectorBase<T, N, AP, ThisVector>& aV, size_t aNewCap)
growTo(Vector<T, N, AP>& aV, size_t aNewCap)
{
MOZ_ASSERT(!aV.usingInlineStorage());
MOZ_ASSERT(!CapacityHasExcessSpace<T>(aNewCap));
@ -165,8 +165,8 @@ struct VectorImpl
* vector operations when the element type is known to be a POD, as judged by
* IsPod.
*/
template<typename T, size_t N, class AP, class ThisVector>
struct VectorImpl<T, N, AP, ThisVector, true>
template<typename T, size_t N, class AP>
struct VectorImpl<T, N, AP, true>
{
static inline void new_(T* aDst)
{
@ -229,7 +229,7 @@ struct VectorImpl<T, N, AP, ThisVector, true>
}
static inline bool
growTo(VectorBase<T, N, AP, ThisVector>& aV, size_t aNewCap)
growTo(Vector<T, N, AP>& aV, size_t aNewCap)
{
MOZ_ASSERT(!aV.usingInlineStorage());
MOZ_ASSERT(!CapacityHasExcessSpace<T>(aNewCap));
@ -251,20 +251,33 @@ struct VectorTesting;
} // namespace detail
/*
* A CRTP base class for vector-like classes. Unless you really really want
* your own vector class -- and you almost certainly don't -- you should use
* mozilla::Vector instead!
* STL-like container providing a short-lived, dynamic buffer. Vector calls the
* constructors/destructors of all elements stored in its internal buffer, so
* non-PODs may be safely used. Additionally, Vector will store the first N
* elements in-place before resorting to dynamic allocation.
*
* See mozilla::Vector for interface requirements.
* T requirements:
* - default and copy constructible, assignable, destructible
* - operations do not throw
* MinInlineCapacity requirements:
* - any value, however, MinInlineCapacity is clamped to min/max values
* AllocPolicy:
* - see "Allocation policies" in AllocPolicy.h (defaults to
* mozilla::MallocAllocPolicy)
*
* Vector is not reentrant: T member functions called during Vector member
* functions must not call back into the same object!
*/
template<typename T, size_t N, class AllocPolicy, class ThisVector>
class VectorBase : private AllocPolicy
template<typename T,
size_t MinInlineCapacity = 0,
class AllocPolicy = MallocAllocPolicy>
class Vector final : private AllocPolicy
{
/* utilities */
static const bool kElemIsPod = IsPod<T>::value;
typedef detail::VectorImpl<T, N, AllocPolicy, ThisVector, kElemIsPod> Impl;
friend struct detail::VectorImpl<T, N, AllocPolicy, ThisVector, kElemIsPod>;
typedef detail::VectorImpl<T, MinInlineCapacity, AllocPolicy, kElemIsPod> Impl;
friend struct detail::VectorImpl<T, MinInlineCapacity, AllocPolicy, kElemIsPod>;
friend struct detail::VectorTesting;
@ -298,11 +311,11 @@ class VectorBase : private AllocPolicy
};
static const size_t kInlineCapacity =
tl::Min<N, kMaxInlineBytes / ElemSize<N, 0>::value>::value;
tl::Min<MinInlineCapacity, kMaxInlineBytes / ElemSize<MinInlineCapacity, 0>::value>::value;
/* Calculate inline buffer size; avoid 0-sized array. */
static const size_t kInlineBytes =
tl::Max<1, kInlineCapacity * ElemSize<N, 0>::value>::value;
tl::Max<1, kInlineCapacity * ElemSize<MinInlineCapacity, 0>::value>::value;
/* member data */
@ -338,7 +351,7 @@ class VectorBase : private AllocPolicy
bool usingInlineStorage() const
{
return mBegin == const_cast<VectorBase*>(this)->inlineStorage();
return mBegin == const_cast<Vector*>(this)->inlineStorage();
}
T* inlineStorage()
@ -379,20 +392,20 @@ class VectorBase : private AllocPolicy
/* Append operations guaranteed to succeed due to pre-reserved space. */
template<typename U> void internalAppend(U&& aU);
template<typename U, size_t O, class BP, class UV>
void internalAppendAll(const VectorBase<U, O, BP, UV>& aU);
template<typename U, size_t O, class BP>
void internalAppendAll(const Vector<U, O, BP>& aU);
void internalAppendN(const T& aT, size_t aN);
template<typename U> void internalAppend(const U* aBegin, size_t aLength);
public:
static const size_t sMaxInlineStorage = N;
static const size_t sMaxInlineStorage = MinInlineCapacity;
typedef T ElementType;
explicit VectorBase(AllocPolicy = AllocPolicy());
explicit VectorBase(ThisVector&&); /* Move constructor. */
ThisVector& operator=(ThisVector&&); /* Move assignment. */
~VectorBase();
explicit Vector(AllocPolicy = AllocPolicy());
Vector(Vector&&); /* Move constructor. */
Vector& operator=(Vector&&); /* Move assignment. */
~Vector();
/* accessors */
@ -400,7 +413,7 @@ public:
AllocPolicy& allocPolicy() { return *this; }
enum { InlineLength = N };
enum { InlineLength = MinInlineCapacity };
size_t length() const { return mLength; }
@ -462,7 +475,7 @@ public:
class Range
{
friend class VectorBase;
friend class Vector;
T* mCur;
T* mEnd;
Range(T* aCur, T* aEnd)
@ -482,7 +495,7 @@ public:
class ConstRange
{
friend class VectorBase;
friend class Vector;
const T* mCur;
const T* mEnd;
ConstRange(const T* aCur, const T* aEnd)
@ -576,8 +589,8 @@ public:
return true;
}
template<typename U, size_t O, class BP, class UV>
bool appendAll(const VectorBase<U, O, BP, UV>& aU);
template<typename U, size_t O, class BP>
bool appendAll(const Vector<U, O, BP>& aU);
bool appendN(const T& aT, size_t aN);
template<typename U> bool append(const U* aBegin, const U* aEnd);
template<typename U> bool append(const U* aBegin, size_t aLength);
@ -678,15 +691,11 @@ public:
*/
size_t sizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
void swap(ThisVector& aOther);
void swap(Vector& aOther);
private:
VectorBase(const VectorBase&) = delete;
void operator=(const VectorBase&) = delete;
/* Move-construct/assign only from our derived class, ThisVector. */
VectorBase(VectorBase&&) = delete;
void operator=(VectorBase&&) = delete;
Vector(const Vector&) = delete;
void operator=(const Vector&) = delete;
};
/* This does the re-entrancy check plus several other sanity checks. */
@ -699,9 +708,9 @@ private:
/* Vector Implementation */
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE
VectorBase<T, N, AP, TV>::VectorBase(AP aAP)
Vector<T, N, AP>::Vector(AP aAP)
: AP(aAP)
, mLength(0)
, mCapacity(kInlineCapacity)
@ -714,9 +723,9 @@ VectorBase<T, N, AP, TV>::VectorBase(AP aAP)
}
/* Move constructor. */
template<typename T, size_t N, class AllocPolicy, class TV>
template<typename T, size_t N, class AllocPolicy>
MOZ_ALWAYS_INLINE
VectorBase<T, N, AllocPolicy, TV>::VectorBase(TV&& aRhs)
Vector<T, N, AllocPolicy>::Vector(Vector&& aRhs)
: AllocPolicy(Move(aRhs))
#ifdef DEBUG
, mEntered(false)
@ -752,20 +761,19 @@ VectorBase<T, N, AllocPolicy, TV>::VectorBase(TV&& aRhs)
}
/* Move assignment. */
template<typename T, size_t N, class AP, class TV>
MOZ_ALWAYS_INLINE TV&
VectorBase<T, N, AP, TV>::operator=(TV&& aRhs)
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE Vector<T, N, AP>&
Vector<T, N, AP>::operator=(Vector&& aRhs)
{
MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited");
TV* tv = static_cast<TV*>(this);
tv->~TV();
new(tv) TV(Move(aRhs));
return *tv;
this->~Vector();
new(this) Vector(Move(aRhs));
return *this;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE
VectorBase<T, N, AP, TV>::~VectorBase()
Vector<T, N, AP>::~Vector()
{
MOZ_REENTRANCY_GUARD_ET_AL;
Impl::destroy(beginNoCheck(), endNoCheck());
@ -779,9 +787,9 @@ VectorBase<T, N, AP, TV>::~VectorBase()
* move all elements in the inline buffer to this new buffer,
* and fail on OOM.
*/
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline bool
VectorBase<T, N, AP, TV>::convertToHeapStorage(size_t aNewCap)
Vector<T, N, AP>::convertToHeapStorage(size_t aNewCap)
{
MOZ_ASSERT(usingInlineStorage());
@ -803,9 +811,9 @@ VectorBase<T, N, AP, TV>::convertToHeapStorage(size_t aNewCap)
return true;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_NEVER_INLINE bool
VectorBase<T, N, AP, TV>::growStorageBy(size_t aIncr)
Vector<T, N, AP>::growStorageBy(size_t aIncr)
{
MOZ_ASSERT(mLength + aIncr > mCapacity);
@ -885,9 +893,9 @@ grow:
return Impl::growTo(*this, newCap);
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline bool
VectorBase<T, N, AP, TV>::initCapacity(size_t aRequest)
Vector<T, N, AP>::initCapacity(size_t aRequest)
{
MOZ_ASSERT(empty());
MOZ_ASSERT(usingInlineStorage());
@ -906,9 +914,9 @@ VectorBase<T, N, AP, TV>::initCapacity(size_t aRequest)
return true;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline bool
VectorBase<T, N, AP, TV>::reserve(size_t aRequest)
Vector<T, N, AP>::reserve(size_t aRequest)
{
MOZ_REENTRANCY_GUARD_ET_AL;
if (aRequest > mCapacity) {
@ -930,9 +938,9 @@ VectorBase<T, N, AP, TV>::reserve(size_t aRequest)
return true;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline void
VectorBase<T, N, AP, TV>::shrinkBy(size_t aIncr)
Vector<T, N, AP>::shrinkBy(size_t aIncr)
{
MOZ_REENTRANCY_GUARD_ET_AL;
MOZ_ASSERT(aIncr <= mLength);
@ -940,9 +948,9 @@ VectorBase<T, N, AP, TV>::shrinkBy(size_t aIncr)
mLength -= aIncr;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE bool
VectorBase<T, N, AP, TV>::growBy(size_t aIncr)
Vector<T, N, AP>::growBy(size_t aIncr)
{
MOZ_REENTRANCY_GUARD_ET_AL;
if (aIncr > mCapacity - mLength) {
@ -966,9 +974,9 @@ VectorBase<T, N, AP, TV>::growBy(size_t aIncr)
return true;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE bool
VectorBase<T, N, AP, TV>::growByUninitialized(size_t aIncr)
Vector<T, N, AP>::growByUninitialized(size_t aIncr)
{
MOZ_REENTRANCY_GUARD_ET_AL;
if (aIncr > mCapacity - mLength) {
@ -984,9 +992,9 @@ VectorBase<T, N, AP, TV>::growByUninitialized(size_t aIncr)
return true;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE void
VectorBase<T, N, AP, TV>::infallibleGrowByUninitialized(size_t aIncr)
Vector<T, N, AP>::infallibleGrowByUninitialized(size_t aIncr)
{
MOZ_ASSERT(mLength + aIncr <= mCapacity);
mLength += aIncr;
@ -997,9 +1005,9 @@ VectorBase<T, N, AP, TV>::infallibleGrowByUninitialized(size_t aIncr)
#endif
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline bool
VectorBase<T, N, AP, TV>::resize(size_t aNewLength)
Vector<T, N, AP>::resize(size_t aNewLength)
{
size_t curLength = mLength;
if (aNewLength > curLength) {
@ -1009,9 +1017,9 @@ VectorBase<T, N, AP, TV>::resize(size_t aNewLength)
return true;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE bool
VectorBase<T, N, AP, TV>::resizeUninitialized(size_t aNewLength)
Vector<T, N, AP>::resizeUninitialized(size_t aNewLength)
{
size_t curLength = mLength;
if (aNewLength > curLength) {
@ -1021,18 +1029,18 @@ VectorBase<T, N, AP, TV>::resizeUninitialized(size_t aNewLength)
return true;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline void
VectorBase<T, N, AP, TV>::clear()
Vector<T, N, AP>::clear()
{
MOZ_REENTRANCY_GUARD_ET_AL;
Impl::destroy(beginNoCheck(), endNoCheck());
mLength = 0;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline void
VectorBase<T, N, AP, TV>::clearAndFree()
Vector<T, N, AP>::clearAndFree()
{
clear();
@ -1047,26 +1055,25 @@ VectorBase<T, N, AP, TV>::clearAndFree()
#endif
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline bool
VectorBase<T, N, AP, TV>::canAppendWithoutRealloc(size_t aNeeded) const
Vector<T, N, AP>::canAppendWithoutRealloc(size_t aNeeded) const
{
return mLength + aNeeded <= mCapacity;
}
template<typename T, size_t N, class AP, class TV>
template<typename U, size_t O, class BP, class UV>
template<typename T, size_t N, class AP>
template<typename U, size_t O, class BP>
MOZ_ALWAYS_INLINE void
VectorBase<T, N, AP, TV>::internalAppendAll(
const VectorBase<U, O, BP, UV>& aOther)
Vector<T, N, AP>::internalAppendAll(const Vector<U, O, BP>& aOther)
{
internalAppend(aOther.begin(), aOther.length());
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
template<typename U>
MOZ_ALWAYS_INLINE void
VectorBase<T, N, AP, TV>::internalAppend(U&& aU)
Vector<T, N, AP>::internalAppend(U&& aU)
{
MOZ_ASSERT(mLength + 1 <= mReserved);
MOZ_ASSERT(mReserved <= mCapacity);
@ -1074,9 +1081,9 @@ VectorBase<T, N, AP, TV>::internalAppend(U&& aU)
++mLength;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE bool
VectorBase<T, N, AP, TV>::appendN(const T& aT, size_t aNeeded)
Vector<T, N, AP>::appendN(const T& aT, size_t aNeeded)
{
MOZ_REENTRANCY_GUARD_ET_AL;
if (mLength + aNeeded > mCapacity) {
@ -1096,9 +1103,9 @@ VectorBase<T, N, AP, TV>::appendN(const T& aT, size_t aNeeded)
return true;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE void
VectorBase<T, N, AP, TV>::internalAppendN(const T& aT, size_t aNeeded)
Vector<T, N, AP>::internalAppendN(const T& aT, size_t aNeeded)
{
MOZ_ASSERT(mLength + aNeeded <= mReserved);
MOZ_ASSERT(mReserved <= mCapacity);
@ -1106,10 +1113,10 @@ VectorBase<T, N, AP, TV>::internalAppendN(const T& aT, size_t aNeeded)
mLength += aNeeded;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
template<typename U>
inline T*
VectorBase<T, N, AP, TV>::insert(T* aP, U&& aVal)
Vector<T, N, AP>::insert(T* aP, U&& aVal)
{
MOZ_ASSERT(begin() <= aP);
MOZ_ASSERT(aP <= end());
@ -1133,9 +1140,9 @@ VectorBase<T, N, AP, TV>::insert(T* aP, U&& aVal)
return begin() + pos;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline void
VectorBase<T, N, AP, TV>::erase(T* aIt)
Vector<T, N, AP>::erase(T* aIt)
{
MOZ_ASSERT(begin() <= aIt);
MOZ_ASSERT(aIt < end());
@ -1146,9 +1153,9 @@ VectorBase<T, N, AP, TV>::erase(T* aIt)
popBack();
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline void
VectorBase<T, N, AP, TV>::erase(T* aBegin, T* aEnd)
Vector<T, N, AP>::erase(T* aBegin, T* aEnd)
{
MOZ_ASSERT(begin() <= aBegin);
MOZ_ASSERT(aBegin <= aEnd);
@ -1159,10 +1166,10 @@ VectorBase<T, N, AP, TV>::erase(T* aBegin, T* aEnd)
shrinkBy(aEnd - aBegin);
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
template<typename U>
MOZ_ALWAYS_INLINE bool
VectorBase<T, N, AP, TV>::append(const U* aInsBegin, const U* aInsEnd)
Vector<T, N, AP>::append(const U* aInsBegin, const U* aInsEnd)
{
MOZ_REENTRANCY_GUARD_ET_AL;
size_t aNeeded = PointerRangeSize(aInsBegin, aInsEnd);
@ -1183,10 +1190,10 @@ VectorBase<T, N, AP, TV>::append(const U* aInsBegin, const U* aInsEnd)
return true;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
template<typename U>
MOZ_ALWAYS_INLINE void
VectorBase<T, N, AP, TV>::internalAppend(const U* aInsBegin, size_t aInsLength)
Vector<T, N, AP>::internalAppend(const U* aInsBegin, size_t aInsLength)
{
MOZ_ASSERT(mLength + aInsLength <= mReserved);
MOZ_ASSERT(mReserved <= mCapacity);
@ -1194,10 +1201,10 @@ VectorBase<T, N, AP, TV>::internalAppend(const U* aInsBegin, size_t aInsLength)
mLength += aInsLength;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
template<typename U>
MOZ_ALWAYS_INLINE bool
VectorBase<T, N, AP, TV>::append(U&& aU)
Vector<T, N, AP>::append(U&& aU)
{
MOZ_REENTRANCY_GUARD_ET_AL;
if (mLength == mCapacity) {
@ -1217,25 +1224,25 @@ VectorBase<T, N, AP, TV>::append(U&& aU)
return true;
}
template<typename T, size_t N, class AP, class TV>
template<typename U, size_t O, class BP, class UV>
template<typename T, size_t N, class AP>
template<typename U, size_t O, class BP>
MOZ_ALWAYS_INLINE bool
VectorBase<T, N, AP, TV>::appendAll(const VectorBase<U, O, BP, UV>& aOther)
Vector<T, N, AP>::appendAll(const Vector<U, O, BP>& aOther)
{
return append(aOther.begin(), aOther.length());
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
template<class U>
MOZ_ALWAYS_INLINE bool
VectorBase<T, N, AP, TV>::append(const U* aInsBegin, size_t aInsLength)
Vector<T, N, AP>::append(const U* aInsBegin, size_t aInsLength)
{
return append(aInsBegin, aInsBegin + aInsLength);
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE void
VectorBase<T, N, AP, TV>::popBack()
Vector<T, N, AP>::popBack()
{
MOZ_REENTRANCY_GUARD_ET_AL;
MOZ_ASSERT(!empty());
@ -1243,18 +1250,18 @@ VectorBase<T, N, AP, TV>::popBack()
endNoCheck()->~T();
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE T
VectorBase<T, N, AP, TV>::popCopy()
Vector<T, N, AP>::popCopy()
{
T ret = back();
popBack();
return ret;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline T*
VectorBase<T, N, AP, TV>::extractRawBuffer()
Vector<T, N, AP>::extractRawBuffer()
{
T* ret;
if (usingInlineStorage()) {
@ -1278,9 +1285,9 @@ VectorBase<T, N, AP, TV>::extractRawBuffer()
return ret;
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline void
VectorBase<T, N, AP, TV>::replaceRawBuffer(T* aP, size_t aLength)
Vector<T, N, AP>::replaceRawBuffer(T* aP, size_t aLength)
{
MOZ_REENTRANCY_GUARD_ET_AL;
@ -1313,23 +1320,23 @@ VectorBase<T, N, AP, TV>::replaceRawBuffer(T* aP, size_t aLength)
#endif
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline size_t
VectorBase<T, N, AP, TV>::sizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
Vector<T, N, AP>::sizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
return usingInlineStorage() ? 0 : aMallocSizeOf(beginNoCheck());
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline size_t
VectorBase<T, N, AP, TV>::sizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
Vector<T, N, AP>::sizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
return aMallocSizeOf(this) + sizeOfExcludingThis(aMallocSizeOf);
}
template<typename T, size_t N, class AP, class TV>
template<typename T, size_t N, class AP>
inline void
VectorBase<T, N, AP, TV>::swap(TV& aOther)
Vector<T, N, AP>::swap(Vector& aOther)
{
static_assert(N == 0,
"still need to implement this for N != 0");
@ -1354,44 +1361,6 @@ VectorBase<T, N, AP, TV>::swap(TV& aOther)
#endif
}
/*
* STL-like container providing a short-lived, dynamic buffer. Vector calls the
* constructors/destructors of all elements stored in its internal buffer, so
* non-PODs may be safely used. Additionally, Vector will store the first N
* elements in-place before resorting to dynamic allocation.
*
* T requirements:
* - default and copy constructible, assignable, destructible
* - operations do not throw
* N requirements:
* - any value, however, N is clamped to min/max values
* AllocPolicy:
* - see "Allocation policies" in AllocPolicy.h (defaults to
* mozilla::MallocAllocPolicy)
*
* Vector is not reentrant: T member functions called during Vector member
* functions must not call back into the same object!
*/
template<typename T,
size_t MinInlineCapacity = 0,
class AllocPolicy = MallocAllocPolicy>
class Vector
: public VectorBase<T,
MinInlineCapacity,
AllocPolicy,
Vector<T, MinInlineCapacity, AllocPolicy> >
{
typedef VectorBase<T, MinInlineCapacity, AllocPolicy, Vector> Base;
public:
explicit Vector(AllocPolicy alloc = AllocPolicy()) : Base(alloc) {}
Vector(Vector&& vec) : Base(Move(vec)) {}
Vector& operator=(Vector&& aOther)
{
return Base::operator=(Move(aOther));
}
};
} // namespace mozilla
#ifdef _MSC_VER

View File

@ -47,10 +47,14 @@ public:
/* HangStack stores an array of const char pointers,
with optional internal storage for strings. */
class HangStack : public mozilla::Vector<const char*, 8>
class HangStack
{
public:
static const size_t sMaxInlineStorage = 8;
private:
typedef mozilla::Vector<const char*, 8> Base;
typedef mozilla::Vector<const char*, sMaxInlineStorage> Impl;
Impl mImpl;
// Stack entries can either be a static const char*
// or a pointer to within this buffer.
@ -60,7 +64,7 @@ public:
HangStack() { }
HangStack(HangStack&& aOther)
: Base(mozilla::Move(aOther))
: mImpl(mozilla::Move(aOther.mImpl))
, mBuffer(mozilla::Move(aOther.mBuffer))
{
}
@ -78,8 +82,34 @@ public:
return !operator==(aOther);
}
const char*& operator[](size_t aIndex) {
return mImpl[aIndex];
}
const char* const& operator[](size_t aIndex) const {
return mImpl[aIndex];
}
size_t capacity() const { return mImpl.capacity(); }
size_t length() const { return mImpl.length(); }
bool empty() const { return mImpl.empty(); }
bool canAppendWithoutRealloc(size_t aNeeded) const {
return mImpl.canAppendWithoutRealloc(aNeeded);
}
void infallibleAppend(const char* aEntry) { mImpl.infallibleAppend(aEntry); }
bool reserve(size_t aRequest) { return mImpl.reserve(aRequest); }
const char** begin() { return mImpl.begin(); }
const char* const* begin() const { return mImpl.begin(); }
const char** end() { return mImpl.end(); }
const char* const* end() const { return mImpl.end(); }
const char*& back() { return mImpl.back(); }
void erase(const char** aEntry) { mImpl.erase(aEntry); }
void erase(const char** aBegin, const char** aEnd) {
mImpl.erase(aBegin, aEnd);
}
void clear() {
Base::clear();
mImpl.clear();
mBuffer.clear();
}