From 4c67f636cea2d2341f664e4f33be07b40280e1db Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Mon, 13 Jul 2015 12:42:52 -0700 Subject: [PATCH] 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 --- gfx/layers/apz/src/AsyncPanZoomAnimation.h | 11 +- gfx/layers/apz/src/AsyncPanZoomController.cpp | 2 +- js/public/TraceableVector.h | 98 +++++- js/public/Vector.h | 61 ++-- js/src/asmjs/AsmJSModule.cpp | 28 +- js/src/ctypes/CTypes.cpp | 10 +- js/src/ctypes/CTypes.h | 29 +- js/src/gc/GCRuntime.h | 2 +- mfbt/Vector.h | 279 ++++++++---------- .../components/telemetry/ThreadHangStats.h | 38 ++- 10 files changed, 303 insertions(+), 255 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomAnimation.h b/gfx/layers/apz/src/AsyncPanZoomAnimation.h index 27caa20da91..baa3643cf3c 100644 --- a/gfx/layers/apz/src/AsyncPanZoomAnimation.h +++ b/gfx/layers/apz/src/AsyncPanZoomAnimation.h @@ -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 TakeDeferredTasks() { - Vector result; - mDeferredTasks.swap(result); - return result; + void TakeDeferredTasks(Vector& aTasks) { + mDeferredTasks.swap(aTasks); } /** diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 9b72f217d6f..ad816df735b 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -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) { diff --git a/js/public/TraceableVector.h b/js/public/TraceableVector.h index 7382b08ec04..79bade658e8 100644 --- a/js/public/TraceableVector.h +++ b/js/public/TraceableVector.h @@ -33,26 +33,96 @@ template > -class TraceableVector - : public mozilla::VectorBase>, - public JS::Traceable +class TraceableVector : public JS::Traceable { - using Base = mozilla::VectorBase; + mozilla::Vector vector; public: - explicit TraceableVector(AllocPolicy alloc = AllocPolicy()) : Base(alloc) {} - TraceableVector(TraceableVector&& vec) : Base(mozilla::Forward(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(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 bool append(U&& item) { return vector.append(mozilla::Forward(item)); } + + template + bool + emplaceBack(Args&&... args) { + return vector.emplaceBack(mozilla::Forward(args)...); + } + + template + void infallibleAppend(U&& aU) { + return vector.infallibleAppend(mozilla::Forward(aU)); + } + void infallibleAppendN(const T& aT, size_t aN) { + return vector.infallibleAppendN(aT, aN); + } + template void + infallibleAppend(const U* aBegin, const U* aEnd) { + return vector.infallibleAppend(aBegin, aEnd); + } + template 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 bool append(const U* aBegin, const U* aEnd) { + return vector.append(aBegin, aEnd); + } + template 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 bool emplaceBack(Args&&... aArgs) { return vec().emplaceBack(mozilla::Forward(aArgs...)); } - template - bool appendAll(const mozilla::VectorBase& aU) { return vec().appendAll(aU); } + template + bool appendAll(const mozilla::Vector& aU) { return vec().appendAll(aU); } bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); } template bool append(const U* aBegin, const U* aEnd) { return vec().append(aBegin, aEnd); diff --git a/js/public/Vector.h b/js/public/Vector.h index 7789816a1c9..07f2240f47f 100644 --- a/js/public/Vector.h +++ b/js/public/Vector.h @@ -19,47 +19,32 @@ namespace js { class TempAllocPolicy; -// If we had C++11 template aliases, we could just use this: -// -// template -// using Vector = mozilla::Vector; -// -// ...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 +struct TypeIsGCThing : mozilla::FalseType +{}; + +// Uncomment this once we actually can assert it: +//template <> +//struct TypeIsGCThing : mozilla::TrueType +//{}; + +} // namespace detail template -class Vector - : public mozilla::VectorBase > -{ - typedef typename mozilla::VectorBase 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::value>::Type +#endif + > +using Vector = mozilla::Vector; } // namespace js diff --git a/js/src/asmjs/AsmJSModule.cpp b/js/src/asmjs/AsmJSModule.cpp index 87a3b83d9fc..350827042ee 100644 --- a/js/src/asmjs/AsmJSModule.cpp +++ b/js/src/asmjs/AsmJSModule.cpp @@ -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 size_t -SerializedVectorSize(const Vector& vec) +SerializedVectorSize(const mozilla::Vector& vec) { size_t size = sizeof(uint32_t); for (size_t i = 0; i < vec.length(); i++) @@ -1142,7 +1143,7 @@ SerializedVectorSize(const Vector& vec) template uint8_t* -SerializeVector(uint8_t* cursor, const Vector& vec) +SerializeVector(uint8_t* cursor, const mozilla::Vector& vec) { cursor = WriteScalar(cursor, vec.length()); for (size_t i = 0; i < vec.length(); i++) @@ -1152,7 +1153,8 @@ SerializeVector(uint8_t* cursor, const Vector& vec) template const uint8_t* -DeserializeVector(ExclusiveContext* cx, const uint8_t* cursor, Vector* vec) +DeserializeVector(ExclusiveContext* cx, const uint8_t* cursor, + mozilla::Vector* vec) { uint32_t length; cursor = ReadScalar(cursor, &length); @@ -1167,8 +1169,8 @@ DeserializeVector(ExclusiveContext* cx, const uint8_t* cursor, Vector bool -CloneVector(ExclusiveContext* cx, const Vector& in, - Vector* out) +CloneVector(ExclusiveContext* cx, const mozilla::Vector& in, + mozilla::Vector* out) { if (!out->resize(in.length())) return false; @@ -1179,27 +1181,27 @@ CloneVector(ExclusiveContext* cx, const Vector& in, return true; } -template +template size_t -SerializedPodVectorSize(const mozilla::VectorBase& vec) +SerializedPodVectorSize(const mozilla::Vector& vec) { return sizeof(uint32_t) + vec.length() * sizeof(T); } -template +template uint8_t* -SerializePodVector(uint8_t* cursor, const mozilla::VectorBase& vec) +SerializePodVector(uint8_t* cursor, const mozilla::Vector& vec) { cursor = WriteScalar(cursor, vec.length()); cursor = WriteBytes(cursor, vec.begin(), vec.length() * sizeof(T)); return cursor; } -template +template const uint8_t* DeserializePodVector(ExclusiveContext* cx, const uint8_t* cursor, - mozilla::VectorBase* vec) + mozilla::Vector* vec) { uint32_t length; cursor = ReadScalar(cursor, &length); @@ -1211,8 +1213,8 @@ DeserializePodVector(ExclusiveContext* cx, const uint8_t* cursor, template bool -ClonePodVector(ExclusiveContext* cx, const Vector& in, - Vector* out) +ClonePodVector(ExclusiveContext* cx, const mozilla::Vector& in, + mozilla::Vector* out) { if (!out->resize(in.length())) return false; diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index bec3a757205..d9489f0bad2 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -9,6 +9,7 @@ #include "mozilla/FloatingPoint.h" #include "mozilla/MemoryReporting.h" #include "mozilla/NumericLimits.h" +#include "mozilla/Vector.h" #include #include @@ -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 void -IntegerToString(IntegerType i, int radix, Vector& result) +IntegerToString(IntegerType i, int radix, mozilla::Vector& result) { JS_STATIC_ASSERT(NumericLimits::is_exact); @@ -3654,7 +3656,7 @@ BuildTypeSource(JSContext* cx, const FieldInfoHash* fields = StructType::GetFieldInfo(typeObj); size_t length = fields->count(); - Array fieldsArray; + Vector 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 fieldsArray; + Vector fieldsArray; if (!fieldsArray.resize(length)) return false; @@ -6510,7 +6512,7 @@ FunctionType::ConstructData(JSContext* cx, return JS_FreezeObject(cx, dataObj); } -typedef Array AutoValueAutoArray; +typedef Vector AutoValueAutoArray; static bool ConvertArgument(JSContext* cx, diff --git a/js/src/ctypes/CTypes.h b/js/src/ctypes/CTypes.h index 6ff6ccf17c8..728baf9c6c8 100644 --- a/js/src/ctypes/CTypes.h +++ b/js/src/ctypes/CTypes.h @@ -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 Array : public Vector -{ - static_assert(!mozilla::IsSame::value, - "use JS::AutoValueVector instead"); -}; - // String and AutoString classes, based on Vector. typedef Vector String; typedef Vector AutoString; @@ -42,7 +35,7 @@ typedef Vector AutoCString; // Convenience functions to append, insert, and compare Strings. template void -AppendString(Vector& v, const char (&array)[ArrayLength]) +AppendString(mozilla::Vector& v, const char (&array)[ArrayLength]) { // Don't include the trailing '\0'. size_t alen = ArrayLength - 1; @@ -56,7 +49,7 @@ AppendString(Vector& v, const char (&array)[ArrayLength]) template void -AppendChars(Vector& v, const char c, size_t count) +AppendChars(mozilla::Vector& v, const char c, size_t count) { size_t vlen = v.length(); if (!v.resize(vlen + count)) @@ -68,7 +61,7 @@ AppendChars(Vector& v, const char c, size_t count) template void -AppendUInt(Vector& v, unsigned n) +AppendUInt(mozilla::Vector& v, unsigned n) { char array[16]; size_t alen = JS_snprintf(array, 16, "%u", n); @@ -82,14 +75,14 @@ AppendUInt(Vector& v, unsigned n) template void -AppendString(Vector& v, Vector& w) +AppendString(mozilla::Vector& v, mozilla::Vector& w) { v.append(w.begin(), w.length()); } template void -AppendString(Vector& v, JSString* str) +AppendString(mozilla::Vector& v, JSString* str) { MOZ_ASSERT(str); JSLinearString* linear = str->ensureLinear(nullptr); @@ -104,7 +97,7 @@ AppendString(Vector& v, JSString* str) template void -AppendString(Vector& v, JSString* str) +AppendString(mozilla::Vector& v, JSString* str) { MOZ_ASSERT(str); size_t vlen = v.length(); @@ -130,7 +123,7 @@ AppendString(Vector& v, JSString* str) template void -PrependString(Vector& v, const char (&array)[ArrayLength]) +PrependString(mozilla::Vector& v, const char (&array)[ArrayLength]) { // Don't include the trailing '\0'. size_t alen = ArrayLength - 1; @@ -148,7 +141,7 @@ PrependString(Vector& v, const char (&array)[ArrayLength]) template void -PrependString(Vector& v, JSString* str) +PrependString(mozilla::Vector& 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 > mArgTypes; + Vector, 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 mFFITypes; + Vector mFFITypes; // Flag indicating whether the function behaves like a C function with // ... as the final formal parameter. diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 7a0fe93a5ab..d7cf559b987 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -537,7 +537,7 @@ struct Callback { }; template -class CallbackVector : public Vector, 4, SystemAllocPolicy> {}; +using CallbackVector = Vector, 4, SystemAllocPolicy>; template class ChainedIter diff --git a/mfbt/Vector.h b/mfbt/Vector.h index d18bfa70bd5..c801ef11c35 100644 --- a/mfbt/Vector.h +++ b/mfbt/Vector.h @@ -31,8 +31,8 @@ namespace mozilla { -template -class VectorBase; +template +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 +template struct VectorImpl { /* @@ -138,7 +138,7 @@ struct VectorImpl * not overflow. */ static inline bool - growTo(VectorBase& aV, size_t aNewCap) + growTo(Vector& aV, size_t aNewCap) { MOZ_ASSERT(!aV.usingInlineStorage()); MOZ_ASSERT(!CapacityHasExcessSpace(aNewCap)); @@ -165,8 +165,8 @@ struct VectorImpl * vector operations when the element type is known to be a POD, as judged by * IsPod. */ -template -struct VectorImpl +template +struct VectorImpl { static inline void new_(T* aDst) { @@ -229,7 +229,7 @@ struct VectorImpl } static inline bool - growTo(VectorBase& aV, size_t aNewCap) + growTo(Vector& aV, size_t aNewCap) { MOZ_ASSERT(!aV.usingInlineStorage()); MOZ_ASSERT(!CapacityHasExcessSpace(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 -class VectorBase : private AllocPolicy +template +class Vector final : private AllocPolicy { /* utilities */ static const bool kElemIsPod = IsPod::value; - typedef detail::VectorImpl Impl; - friend struct detail::VectorImpl; + typedef detail::VectorImpl Impl; + friend struct detail::VectorImpl; friend struct detail::VectorTesting; @@ -298,11 +311,11 @@ class VectorBase : private AllocPolicy }; static const size_t kInlineCapacity = - tl::Min::value>::value; + tl::Min::value>::value; /* Calculate inline buffer size; avoid 0-sized array. */ static const size_t kInlineBytes = - tl::Max<1, kInlineCapacity * ElemSize::value>::value; + tl::Max<1, kInlineCapacity * ElemSize::value>::value; /* member data */ @@ -338,7 +351,7 @@ class VectorBase : private AllocPolicy bool usingInlineStorage() const { - return mBegin == const_cast(this)->inlineStorage(); + return mBegin == const_cast(this)->inlineStorage(); } T* inlineStorage() @@ -379,20 +392,20 @@ class VectorBase : private AllocPolicy /* Append operations guaranteed to succeed due to pre-reserved space. */ template void internalAppend(U&& aU); - template - void internalAppendAll(const VectorBase& aU); + template + void internalAppendAll(const Vector& aU); void internalAppendN(const T& aT, size_t aN); template 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 - bool appendAll(const VectorBase& aU); + template + bool appendAll(const Vector& aU); bool appendN(const T& aT, size_t aN); template bool append(const U* aBegin, const U* aEnd); template 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 +template MOZ_ALWAYS_INLINE -VectorBase::VectorBase(AP aAP) +Vector::Vector(AP aAP) : AP(aAP) , mLength(0) , mCapacity(kInlineCapacity) @@ -714,9 +723,9 @@ VectorBase::VectorBase(AP aAP) } /* Move constructor. */ -template +template MOZ_ALWAYS_INLINE -VectorBase::VectorBase(TV&& aRhs) +Vector::Vector(Vector&& aRhs) : AllocPolicy(Move(aRhs)) #ifdef DEBUG , mEntered(false) @@ -752,20 +761,19 @@ VectorBase::VectorBase(TV&& aRhs) } /* Move assignment. */ -template -MOZ_ALWAYS_INLINE TV& -VectorBase::operator=(TV&& aRhs) +template +MOZ_ALWAYS_INLINE Vector& +Vector::operator=(Vector&& aRhs) { MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited"); - TV* tv = static_cast(this); - tv->~TV(); - new(tv) TV(Move(aRhs)); - return *tv; + this->~Vector(); + new(this) Vector(Move(aRhs)); + return *this; } -template +template MOZ_ALWAYS_INLINE -VectorBase::~VectorBase() +Vector::~Vector() { MOZ_REENTRANCY_GUARD_ET_AL; Impl::destroy(beginNoCheck(), endNoCheck()); @@ -779,9 +787,9 @@ VectorBase::~VectorBase() * move all elements in the inline buffer to this new buffer, * and fail on OOM. */ -template +template inline bool -VectorBase::convertToHeapStorage(size_t aNewCap) +Vector::convertToHeapStorage(size_t aNewCap) { MOZ_ASSERT(usingInlineStorage()); @@ -803,9 +811,9 @@ VectorBase::convertToHeapStorage(size_t aNewCap) return true; } -template +template MOZ_NEVER_INLINE bool -VectorBase::growStorageBy(size_t aIncr) +Vector::growStorageBy(size_t aIncr) { MOZ_ASSERT(mLength + aIncr > mCapacity); @@ -885,9 +893,9 @@ grow: return Impl::growTo(*this, newCap); } -template +template inline bool -VectorBase::initCapacity(size_t aRequest) +Vector::initCapacity(size_t aRequest) { MOZ_ASSERT(empty()); MOZ_ASSERT(usingInlineStorage()); @@ -906,9 +914,9 @@ VectorBase::initCapacity(size_t aRequest) return true; } -template +template inline bool -VectorBase::reserve(size_t aRequest) +Vector::reserve(size_t aRequest) { MOZ_REENTRANCY_GUARD_ET_AL; if (aRequest > mCapacity) { @@ -930,9 +938,9 @@ VectorBase::reserve(size_t aRequest) return true; } -template +template inline void -VectorBase::shrinkBy(size_t aIncr) +Vector::shrinkBy(size_t aIncr) { MOZ_REENTRANCY_GUARD_ET_AL; MOZ_ASSERT(aIncr <= mLength); @@ -940,9 +948,9 @@ VectorBase::shrinkBy(size_t aIncr) mLength -= aIncr; } -template +template MOZ_ALWAYS_INLINE bool -VectorBase::growBy(size_t aIncr) +Vector::growBy(size_t aIncr) { MOZ_REENTRANCY_GUARD_ET_AL; if (aIncr > mCapacity - mLength) { @@ -966,9 +974,9 @@ VectorBase::growBy(size_t aIncr) return true; } -template +template MOZ_ALWAYS_INLINE bool -VectorBase::growByUninitialized(size_t aIncr) +Vector::growByUninitialized(size_t aIncr) { MOZ_REENTRANCY_GUARD_ET_AL; if (aIncr > mCapacity - mLength) { @@ -984,9 +992,9 @@ VectorBase::growByUninitialized(size_t aIncr) return true; } -template +template MOZ_ALWAYS_INLINE void -VectorBase::infallibleGrowByUninitialized(size_t aIncr) +Vector::infallibleGrowByUninitialized(size_t aIncr) { MOZ_ASSERT(mLength + aIncr <= mCapacity); mLength += aIncr; @@ -997,9 +1005,9 @@ VectorBase::infallibleGrowByUninitialized(size_t aIncr) #endif } -template +template inline bool -VectorBase::resize(size_t aNewLength) +Vector::resize(size_t aNewLength) { size_t curLength = mLength; if (aNewLength > curLength) { @@ -1009,9 +1017,9 @@ VectorBase::resize(size_t aNewLength) return true; } -template +template MOZ_ALWAYS_INLINE bool -VectorBase::resizeUninitialized(size_t aNewLength) +Vector::resizeUninitialized(size_t aNewLength) { size_t curLength = mLength; if (aNewLength > curLength) { @@ -1021,18 +1029,18 @@ VectorBase::resizeUninitialized(size_t aNewLength) return true; } -template +template inline void -VectorBase::clear() +Vector::clear() { MOZ_REENTRANCY_GUARD_ET_AL; Impl::destroy(beginNoCheck(), endNoCheck()); mLength = 0; } -template +template inline void -VectorBase::clearAndFree() +Vector::clearAndFree() { clear(); @@ -1047,26 +1055,25 @@ VectorBase::clearAndFree() #endif } -template +template inline bool -VectorBase::canAppendWithoutRealloc(size_t aNeeded) const +Vector::canAppendWithoutRealloc(size_t aNeeded) const { return mLength + aNeeded <= mCapacity; } -template -template +template +template MOZ_ALWAYS_INLINE void -VectorBase::internalAppendAll( - const VectorBase& aOther) +Vector::internalAppendAll(const Vector& aOther) { internalAppend(aOther.begin(), aOther.length()); } -template +template template MOZ_ALWAYS_INLINE void -VectorBase::internalAppend(U&& aU) +Vector::internalAppend(U&& aU) { MOZ_ASSERT(mLength + 1 <= mReserved); MOZ_ASSERT(mReserved <= mCapacity); @@ -1074,9 +1081,9 @@ VectorBase::internalAppend(U&& aU) ++mLength; } -template +template MOZ_ALWAYS_INLINE bool -VectorBase::appendN(const T& aT, size_t aNeeded) +Vector::appendN(const T& aT, size_t aNeeded) { MOZ_REENTRANCY_GUARD_ET_AL; if (mLength + aNeeded > mCapacity) { @@ -1096,9 +1103,9 @@ VectorBase::appendN(const T& aT, size_t aNeeded) return true; } -template +template MOZ_ALWAYS_INLINE void -VectorBase::internalAppendN(const T& aT, size_t aNeeded) +Vector::internalAppendN(const T& aT, size_t aNeeded) { MOZ_ASSERT(mLength + aNeeded <= mReserved); MOZ_ASSERT(mReserved <= mCapacity); @@ -1106,10 +1113,10 @@ VectorBase::internalAppendN(const T& aT, size_t aNeeded) mLength += aNeeded; } -template +template template inline T* -VectorBase::insert(T* aP, U&& aVal) +Vector::insert(T* aP, U&& aVal) { MOZ_ASSERT(begin() <= aP); MOZ_ASSERT(aP <= end()); @@ -1133,9 +1140,9 @@ VectorBase::insert(T* aP, U&& aVal) return begin() + pos; } -template +template inline void -VectorBase::erase(T* aIt) +Vector::erase(T* aIt) { MOZ_ASSERT(begin() <= aIt); MOZ_ASSERT(aIt < end()); @@ -1146,9 +1153,9 @@ VectorBase::erase(T* aIt) popBack(); } -template +template inline void -VectorBase::erase(T* aBegin, T* aEnd) +Vector::erase(T* aBegin, T* aEnd) { MOZ_ASSERT(begin() <= aBegin); MOZ_ASSERT(aBegin <= aEnd); @@ -1159,10 +1166,10 @@ VectorBase::erase(T* aBegin, T* aEnd) shrinkBy(aEnd - aBegin); } -template +template template MOZ_ALWAYS_INLINE bool -VectorBase::append(const U* aInsBegin, const U* aInsEnd) +Vector::append(const U* aInsBegin, const U* aInsEnd) { MOZ_REENTRANCY_GUARD_ET_AL; size_t aNeeded = PointerRangeSize(aInsBegin, aInsEnd); @@ -1183,10 +1190,10 @@ VectorBase::append(const U* aInsBegin, const U* aInsEnd) return true; } -template +template template MOZ_ALWAYS_INLINE void -VectorBase::internalAppend(const U* aInsBegin, size_t aInsLength) +Vector::internalAppend(const U* aInsBegin, size_t aInsLength) { MOZ_ASSERT(mLength + aInsLength <= mReserved); MOZ_ASSERT(mReserved <= mCapacity); @@ -1194,10 +1201,10 @@ VectorBase::internalAppend(const U* aInsBegin, size_t aInsLength) mLength += aInsLength; } -template +template template MOZ_ALWAYS_INLINE bool -VectorBase::append(U&& aU) +Vector::append(U&& aU) { MOZ_REENTRANCY_GUARD_ET_AL; if (mLength == mCapacity) { @@ -1217,25 +1224,25 @@ VectorBase::append(U&& aU) return true; } -template -template +template +template MOZ_ALWAYS_INLINE bool -VectorBase::appendAll(const VectorBase& aOther) +Vector::appendAll(const Vector& aOther) { return append(aOther.begin(), aOther.length()); } -template +template template MOZ_ALWAYS_INLINE bool -VectorBase::append(const U* aInsBegin, size_t aInsLength) +Vector::append(const U* aInsBegin, size_t aInsLength) { return append(aInsBegin, aInsBegin + aInsLength); } -template +template MOZ_ALWAYS_INLINE void -VectorBase::popBack() +Vector::popBack() { MOZ_REENTRANCY_GUARD_ET_AL; MOZ_ASSERT(!empty()); @@ -1243,18 +1250,18 @@ VectorBase::popBack() endNoCheck()->~T(); } -template +template MOZ_ALWAYS_INLINE T -VectorBase::popCopy() +Vector::popCopy() { T ret = back(); popBack(); return ret; } -template +template inline T* -VectorBase::extractRawBuffer() +Vector::extractRawBuffer() { T* ret; if (usingInlineStorage()) { @@ -1278,9 +1285,9 @@ VectorBase::extractRawBuffer() return ret; } -template +template inline void -VectorBase::replaceRawBuffer(T* aP, size_t aLength) +Vector::replaceRawBuffer(T* aP, size_t aLength) { MOZ_REENTRANCY_GUARD_ET_AL; @@ -1313,23 +1320,23 @@ VectorBase::replaceRawBuffer(T* aP, size_t aLength) #endif } -template +template inline size_t -VectorBase::sizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const +Vector::sizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { return usingInlineStorage() ? 0 : aMallocSizeOf(beginNoCheck()); } -template +template inline size_t -VectorBase::sizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const +Vector::sizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { return aMallocSizeOf(this) + sizeOfExcludingThis(aMallocSizeOf); } -template +template inline void -VectorBase::swap(TV& aOther) +Vector::swap(Vector& aOther) { static_assert(N == 0, "still need to implement this for N != 0"); @@ -1354,44 +1361,6 @@ VectorBase::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 -class Vector - : public VectorBase > -{ - typedef VectorBase 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 diff --git a/toolkit/components/telemetry/ThreadHangStats.h b/toolkit/components/telemetry/ThreadHangStats.h index 2513c347b4a..6ab077fa62c 100644 --- a/toolkit/components/telemetry/ThreadHangStats.h +++ b/toolkit/components/telemetry/ThreadHangStats.h @@ -47,10 +47,14 @@ public: /* HangStack stores an array of const char pointers, with optional internal storage for strings. */ -class HangStack : public mozilla::Vector +class HangStack { +public: + static const size_t sMaxInlineStorage = 8; + private: - typedef mozilla::Vector Base; + typedef mozilla::Vector 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(); }