diff --git a/dom/performance/PerformanceObserver.cpp b/dom/performance/PerformanceObserver.cpp index 7084ca0fba..6c5a60feed 100644 --- a/dom/performance/PerformanceObserver.cpp +++ b/dom/performance/PerformanceObserver.cpp @@ -10,9 +10,11 @@ #include "mozilla/dom/PerformanceEntryBinding.h" #include "mozilla/dom/PerformanceObserverBinding.h" #include "nsIScriptError.h" +#include "nsHashKeys.h" #include "nsPIDOMWindow.h" #include "nsQueryObject.h" #include "nsString.h" +#include "nsTHashtable.h" #include "PerformanceEntry.h" #include "PerformanceObserverEntryList.h" #include "WorkerPrivate.h" @@ -225,19 +227,28 @@ void PerformanceObserver::Observe(const PerformanceObserverInit& aOptions, } /* 3.3.1.5.2 */ + nsTHashtable requestedTypes(entryTypes.Length()); + for (const auto& type : entryTypes) { + requestedTypes.PutEntry(type); + } + nsTArray validEntryTypes; for (const char16_t* name : sValidTypeNames) { nsDependentString validTypeName(name); - if (entryTypes.Contains(validTypeName) && - !validEntryTypes.Contains(validTypeName)) { + if (requestedTypes.GetEntry(validTypeName)) { validEntryTypes.AppendElement(validTypeName); } } + nsTHashtable validTypeSet(validEntryTypes.Length()); + for (const auto& validType : validEntryTypes) { + validTypeSet.PutEntry(validType); + } + nsAutoString invalidTypesJoined; bool addComma = false; for (const auto& type : entryTypes) { - if (!validEntryTypes.Contains(type)) { + if (!validTypeSet.GetEntry(type)) { if (addComma) { invalidTypesJoined.AppendLiteral(", "); } @@ -289,13 +300,13 @@ void PerformanceObserver::Observe(const PerformanceObserverInit& aOptions, /* 3.3.1.6.4, 3.3.1.6.4 */ bool didUpdateOptionsList = false; - nsTArray updatedOptionsList; + nsTArray updatedOptionsList(mOptions.Length() + 1); for (auto& option : mOptions) { if (option.mType.WasPassed() && option.mType.Value() == type) { updatedOptionsList.AppendElement(aOptions); didUpdateOptionsList = true; } else { - updatedOptionsList.AppendElement(option); + updatedOptionsList.AppendElement(Move(option)); } } if (!didUpdateOptionsList) { diff --git a/gfx/layers/LayerSorter.cpp b/gfx/layers/LayerSorter.cpp index ce180c374e..82a301d5b4 100644 --- a/gfx/layers/LayerSorter.cpp +++ b/gfx/layers/LayerSorter.cpp @@ -103,13 +103,23 @@ static LayerSortOrder CompareDepth(Layer* aOne, Layer* aTwo) { // Could we just check Contains() on the bounds rects. ie, is it possible // for layers to overlap without intersections (in 2d space) and yet still // have their bounds rects not completely enclose each other? - nsTArray points; + AutoTArray points; + auto appendUniquePoint = [&points](const gfxPoint& aPoint) { + static const gfxFloat kDuplicateEpsilon = 0.01; + for (const auto& point : points) { + if (fabs(point.x - aPoint.x) < kDuplicateEpsilon && + fabs(point.y - aPoint.y) < kDuplicateEpsilon) { + return; + } + } + points.AppendElement(aPoint); + }; for (uint32_t i = 0; i < 4; i++) { if (ourTransformedRect.Contains(otherTransformedRect.mPoints[i])) { - points.AppendElement(otherTransformedRect.mPoints[i]); + appendUniquePoint(otherTransformedRect.mPoints[i]); } if (otherTransformedRect.Contains(ourTransformedRect.mPoints[i])) { - points.AppendElement(ourTransformedRect.mPoints[i]); + appendUniquePoint(ourTransformedRect.mPoints[i]); } } @@ -123,7 +133,7 @@ static LayerSortOrder CompareDepth(Layer* aOne, Layer* aTwo) { gfxLineSegment two(otherTransformedRect.mPoints[j], otherTransformedRect.mPoints[(j + 1) % 4]); if (one.Intersects(two, intersection)) { - points.AppendElement(intersection); + appendUniquePoint(intersection); } } } diff --git a/netwerk/base/ThrottleQueue.cpp b/netwerk/base/ThrottleQueue.cpp index 8f07186235..233a95b15a 100644 --- a/netwerk/base/ThrottleQueue.cpp +++ b/netwerk/base/ThrottleQueue.cpp @@ -30,6 +30,8 @@ public: NS_DECL_NSIASYNCINPUTSTREAM void AllowInput(); + bool IsQueued() const; + void SetQueued(bool aQueued); private: @@ -41,6 +43,7 @@ private: nsCOMPtr mCallback; nsCOMPtr mEventTarget; + bool mIsQueued; }; NS_IMPL_ISUPPORTS(ThrottleInputStream, nsIAsyncInputStream, nsIInputStream, nsISeekableStream) @@ -49,6 +52,7 @@ ThrottleInputStream::ThrottleInputStream(nsIInputStream *aStream, ThrottleQueue* : mStream(aStream) , mQueue(aQueue) , mClosedStatus(NS_OK) + , mIsQueued(false) { MOZ_ASSERT(aQueue != nullptr); } @@ -233,6 +237,18 @@ ThrottleInputStream::AllowInput() callbackEvent->OnInputStreamReady(this); } +bool +ThrottleInputStream::IsQueued() const +{ + return mIsQueued; +} + +void +ThrottleInputStream::SetQueued(bool aQueued) +{ + mIsQueued = aQueued; +} + //----------------------------------------------------------------------------- NS_IMPL_ISUPPORTS(ThrottleQueue, nsIInputChannelThrottleQueue, nsITimerCallback) @@ -348,6 +364,7 @@ ThrottleQueue::Notify(nsITimer* aTimer) // Optimistically notify all the waiting readers, and then let them // requeue if there isn't enough bandwidth. for (size_t i = 0; i < events.Length(); ++i) { + events[i]->SetQueued(false); events[i]->AllowInput(); } @@ -359,7 +376,8 @@ void ThrottleQueue::QueueStream(ThrottleInputStream* aStream) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); - if (mAsyncEvents.IndexOf(aStream) == mAsyncEvents.NoIndex) { + if (!aStream->IsQueued()) { + aStream->SetQueued(true); mAsyncEvents.AppendElement(aStream); if (!mTimerArmed) { @@ -386,7 +404,12 @@ void ThrottleQueue::DequeueStream(ThrottleInputStream* aStream) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); + if (!aStream->IsQueued()) { + return; + } + mAsyncEvents.RemoveElement(aStream); + aStream->SetQueued(false); } } diff --git a/xpcom/threads/TimerThread.cpp b/xpcom/threads/TimerThread.cpp index ca0cd3cb9c..30ab2f89a9 100644 --- a/xpcom/threads/TimerThread.cpp +++ b/xpcom/threads/TimerThread.cpp @@ -354,8 +354,7 @@ TimerThread::Shutdown() // might potentially call some code reentering the same lock // that leads to unexpected behavior or deadlock. // See bug 422472. - timers.AppendElements(mTimers); - mTimers.Clear(); + timers.SwapElements(mTimers); } uint32_t timersCount = timers.Length();