From 8a230137451df2fba1bf4e60e89c5c26ca492150 Mon Sep 17 00:00:00 2001 From: Christopher Bathgate Date: Sun, 26 Mar 2017 16:46:00 -0400 Subject: [PATCH 01/22] Bug 1318223 - Use NonOwningAnimationTarget in OwningElementRef. r=boris, r=birtles --HG-- extra : amend_source : efe698c05bcee0c34d99b8242d8f147373cf2584 --- dom/animation/AnimationTarget.h | 8 +++++++ layout/style/AnimationCommon.h | 39 +++++++++++++++++---------------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/dom/animation/AnimationTarget.h b/dom/animation/AnimationTarget.h index dbfef2e10c55..084a4d7eb022 100644 --- a/dom/animation/AnimationTarget.h +++ b/dom/animation/AnimationTarget.h @@ -40,12 +40,20 @@ struct OwningAnimationTarget struct NonOwningAnimationTarget { + NonOwningAnimationTarget() = default; + NonOwningAnimationTarget(dom::Element* aElement, CSSPseudoElementType aType) : mElement(aElement), mPseudoType(aType) { } explicit NonOwningAnimationTarget(const OwningAnimationTarget& aOther) : mElement(aOther.mElement), mPseudoType(aOther.mPseudoType) { } + bool operator==(const NonOwningAnimationTarget& aOther) const + { + return mElement == aOther.mElement && + mPseudoType == aOther.mPseudoType; + } + // mElement represents the parent element of a pseudo-element, not the // generated content element. dom::Element* MOZ_NON_OWNING_REF mElement = nullptr; diff --git a/layout/style/AnimationCommon.h b/layout/style/AnimationCommon.h index 6dc14b9d663f..806d9baa043b 100644 --- a/layout/style/AnimationCommon.h +++ b/layout/style/AnimationCommon.h @@ -13,6 +13,7 @@ #include "mozilla/LinkedList.h" #include "mozilla/MemoryReporting.h" #include "mozilla/dom/Animation.h" +#include "mozilla/AnimationTarget.h" #include "mozilla/Attributes.h" // For MOZ_NON_OWNING_REF #include "mozilla/Assertions.h" #include "mozilla/TimingParams.h" @@ -111,48 +112,48 @@ protected: class OwningElementRef final { public: - OwningElementRef() - : mElement(nullptr) - , mPseudoType(CSSPseudoElementType::NotPseudo) + OwningElementRef() = default; + + explicit OwningElementRef(const NonOwningAnimationTarget& aTarget) + : mTarget(aTarget) { } OwningElementRef(dom::Element& aElement, CSSPseudoElementType aPseudoType) - : mElement(&aElement) - , mPseudoType(aPseudoType) + : mTarget(&aElement, aPseudoType) { } bool Equals(const OwningElementRef& aOther) const { - return mElement == aOther.mElement && - mPseudoType == aOther.mPseudoType; + return mTarget == aOther.mTarget; } bool LessThan(const OwningElementRef& aOther) const { - MOZ_ASSERT(mElement && aOther.mElement, + MOZ_ASSERT(mTarget.mElement && aOther.mTarget.mElement, "Elements to compare should not be null"); - if (mElement != aOther.mElement) { - return nsContentUtils::PositionIsBefore(mElement, aOther.mElement); + if (mTarget.mElement != aOther.mTarget.mElement) { + return nsContentUtils::PositionIsBefore(mTarget.mElement, + aOther.mTarget.mElement); } - return mPseudoType == CSSPseudoElementType::NotPseudo || - (mPseudoType == CSSPseudoElementType::before && - aOther.mPseudoType == CSSPseudoElementType::after); + return mTarget.mPseudoType == CSSPseudoElementType::NotPseudo || + (mTarget.mPseudoType == CSSPseudoElementType::before && + aOther.mTarget.mPseudoType == CSSPseudoElementType::after); } - bool IsSet() const { return !!mElement; } + bool IsSet() const { return !!mTarget.mElement; } void GetElement(dom::Element*& aElement, - CSSPseudoElementType& aPseudoType) const { - aElement = mElement; - aPseudoType = mPseudoType; + CSSPseudoElementType& aPseudoType) const + { + aElement = mTarget.mElement; + aPseudoType = mTarget.mPseudoType; } private: - dom::Element* MOZ_NON_OWNING_REF mElement; - CSSPseudoElementType mPseudoType; + NonOwningAnimationTarget mTarget; }; template From 1e922328d3a93230e34caba8bdf986815bac9cf9 Mon Sep 17 00:00:00 2001 From: Gregory Moore Date: Mon, 20 Mar 2017 12:35:42 -0700 Subject: [PATCH 02/22] Bug 1271991 - Store recording state locally in Telemetry.cpp to avoid excessive locking in CanRecord{Base, Extended}(). r=chutten --- toolkit/components/telemetry/Telemetry.cpp | 48 +++++++++++++++++----- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/toolkit/components/telemetry/Telemetry.cpp b/toolkit/components/telemetry/Telemetry.cpp index 5487fd0ab15f..47507a31ab29 100644 --- a/toolkit/components/telemetry/Telemetry.cpp +++ b/toolkit/components/telemetry/Telemetry.cpp @@ -928,6 +928,8 @@ public: static void RecordIceCandidates(const uint32_t iceCandidateBitmask, const bool success); + static bool CanRecordBase(); + static bool CanRecordExtended(); private: TelemetryImpl(); ~TelemetryImpl(); @@ -959,6 +961,8 @@ private: Mutex mHashMutex; HangReports mHangReports; Mutex mHangReportsMutex; + Atomic mCanRecordBase; + Atomic mCanRecordExtended; #if defined(ENABLE_STACK_CAPTURE) // Stores data about stacks captured on demand. @@ -1246,6 +1250,8 @@ TelemetryImpl::TelemetryImpl() , mCachedTelemetryData(false) , mLastShutdownTime(0) , mFailedLockCount(0) + , mCanRecordBase(false) + , mCanRecordExtended(false) { // We expect TelemetryHistogram::InitializeGlobalState() to have been // called before we get to this point. @@ -2274,15 +2280,18 @@ TelemetryImpl::GetKeyedHistogramById(const nsACString &name, JSContext *cx, */ NS_IMETHODIMP TelemetryImpl::GetCanRecordBase(bool *ret) { - *ret = TelemetryHistogram::CanRecordBase(); + *ret = mCanRecordBase; return NS_OK; } NS_IMETHODIMP TelemetryImpl::SetCanRecordBase(bool canRecord) { - TelemetryHistogram::SetCanRecordBase(canRecord); - TelemetryScalar::SetCanRecordBase(canRecord); - TelemetryEvent::SetCanRecordBase(canRecord); + if (canRecord != mCanRecordBase) { + TelemetryHistogram::SetCanRecordBase(canRecord); + TelemetryScalar::SetCanRecordBase(canRecord); + TelemetryEvent::SetCanRecordBase(canRecord); + mCanRecordBase = canRecord; + } return NS_OK; } @@ -2295,15 +2304,18 @@ TelemetryImpl::SetCanRecordBase(bool canRecord) { */ NS_IMETHODIMP TelemetryImpl::GetCanRecordExtended(bool *ret) { - *ret = TelemetryHistogram::CanRecordExtended(); + *ret = mCanRecordExtended; return NS_OK; } NS_IMETHODIMP TelemetryImpl::SetCanRecordExtended(bool canRecord) { - TelemetryHistogram::SetCanRecordExtended(canRecord); - TelemetryScalar::SetCanRecordExtended(canRecord); - TelemetryEvent::SetCanRecordExtended(canRecord); + if (canRecord != mCanRecordExtended) { + TelemetryHistogram::SetCanRecordExtended(canRecord); + TelemetryScalar::SetCanRecordExtended(canRecord); + TelemetryEvent::SetCanRecordExtended(canRecord); + mCanRecordExtended = canRecord; + } return NS_OK; } @@ -2696,6 +2708,22 @@ TelemetryImpl::RecordThreadHangStats(Telemetry::ThreadHangStats& aStats) mozilla::Unused << sTelemetry->mThreadHangStats.append(Move(aStats)); } +bool +TelemetryImpl::CanRecordBase() +{ + bool canRecordBase; + nsresult rv = sTelemetry->GetCanRecordBase(&canRecordBase); + return NS_SUCCEEDED(rv) && canRecordBase; +} + +bool +TelemetryImpl::CanRecordExtended() +{ + bool canRecordExtended; + nsresult rv = sTelemetry->GetCanRecordExtended(&canRecordExtended); + return NS_SUCCEEDED(rv) && canRecordExtended; +} + NS_IMPL_ISUPPORTS(TelemetryImpl, nsITelemetry, nsIMemoryReporter) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelemetry, TelemetryImpl::CreateTelemetryInstance) @@ -3378,13 +3406,13 @@ GetHistogramName(HistogramID id) bool CanRecordBase() { - return TelemetryHistogram::CanRecordBase(); + return TelemetryImpl::CanRecordBase(); } bool CanRecordExtended() { - return TelemetryHistogram::CanRecordExtended(); + return TelemetryImpl::CanRecordExtended(); } void From 457d2d7ac1e506163b91ec722fc4a0b7b72190bc Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Wed, 1 Mar 2017 06:12:00 -0500 Subject: [PATCH 03/22] Bug 1316358 - Mark HSTS priming requests as urgent start. r=kmckinley --- netwerk/protocol/http/HSTSPrimerListener.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/netwerk/protocol/http/HSTSPrimerListener.cpp b/netwerk/protocol/http/HSTSPrimerListener.cpp index e466c920bc3f..c9765d60a26c 100644 --- a/netwerk/protocol/http/HSTSPrimerListener.cpp +++ b/netwerk/protocol/http/HSTSPrimerListener.cpp @@ -306,6 +306,13 @@ HSTSPrimingListener::StartHSTSPriming(nsIChannel* aRequestChannel, nsCOMPtr internal = do_QueryInterface(primingChannel); NS_ENSURE_STATE(internal); + // Since this is a perfomrance critical request (blocks the page load) we + // want to get the response ASAP. + nsCOMPtr classOfService(do_QueryInterface(primingChannel)); + if (classOfService) { + classOfService->AddClassFlags(nsIClassOfService::UrgentStart); + } + // Currently using HEAD per the draft, but under discussion to change to GET // with credentials so if the upgrade is approved the result is already cached. rv = httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("HEAD")); From 99ed04a411b70d38ba4d1d0074f7756cc5d91624 Mon Sep 17 00:00:00 2001 From: Kershaw Chang Date: Mon, 27 Mar 2017 04:09:00 -0400 Subject: [PATCH 04/22] Bug 1312782 - Part 1: Implement window id to pending transactions table. r=honzab --- modules/libpref/init/all.js | 4 + .../protocol/http/ConnectionDiagnostics.cpp | 24 +- netwerk/protocol/http/NullHttpTransaction.h | 6 + netwerk/protocol/http/nsAHttpTransaction.h | 5 + netwerk/protocol/http/nsHttpConnectionMgr.cpp | 473 ++++++++++++++---- netwerk/protocol/http/nsHttpConnectionMgr.h | 59 ++- netwerk/protocol/http/nsHttpHandler.cpp | 14 + netwerk/protocol/http/nsHttpHandler.h | 8 + netwerk/protocol/http/nsHttpTransaction.h | 2 +- 9 files changed, 481 insertions(+), 114 deletions(-) diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index f1b094d2e619..7720de45a6e9 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1624,6 +1624,10 @@ pref("network.http.keep_empty_response_headers_as_empty_string", true); // Max size, in bytes, for received HTTP response header. pref("network.http.max_response_header_size", 393216); +// The ratio of the transaction count for the focused window and the count of +// all available active connections. +pref("network.http.focused_window_transaction_ratio", "0.9"); + // default values for FTP // in a DSCP environment this should be 40 (0x28, or AF11), per RFC-4594, // Section 4.8 "High-Throughput Data Service Class", and 80 (0x50, or AF22) diff --git a/netwerk/protocol/http/ConnectionDiagnostics.cpp b/netwerk/protocol/http/ConnectionDiagnostics.cpp index b3d216983318..1ade0c2b88ff 100644 --- a/netwerk/protocol/http/ConnectionDiagnostics.cpp +++ b/netwerk/protocol/http/ConnectionDiagnostics.cpp @@ -58,7 +58,7 @@ nsHttpConnectionMgr::OnMsgPrintDiagnostics(int32_t, ARefBase *) mLogData.AppendPrintf(" RestrictConnections = %d\n", RestrictConnections(ent)); mLogData.AppendPrintf(" Pending Q Length = %" PRIuSIZE "\n", - ent->mPendingQ.Length()); + ent->PendingQLength()); mLogData.AppendPrintf(" Active Conns Length = %" PRIuSIZE "\n", ent->mActiveConns.Length()); mLogData.AppendPrintf(" Idle Conns Length = %" PRIuSIZE "\n", @@ -83,9 +83,17 @@ nsHttpConnectionMgr::OnMsgPrintDiagnostics(int32_t, ARefBase *) mLogData.AppendPrintf(" :: Half Open #%u\n", i); ent->mHalfOpens[i]->PrintDiagnostics(mLogData); } - for (i = 0; i < ent->mPendingQ.Length(); ++i) { - mLogData.AppendPrintf(" :: Pending Transaction #%u\n", i); - ent->mPendingQ[i]->PrintDiagnostics(mLogData); + i = 0; + for (auto it = ent->mPendingTransactionTable.Iter(); + !it.Done(); + it.Next()) { + mLogData.AppendPrintf(" :: Pending Transactions with Window ID = %" + PRIu64 "\n", it.Key()); + for (uint32_t j = 0; j < it.UserData()->Length(); ++j) { + mLogData.AppendPrintf(" ::: Pending Transaction #%u\n", i); + it.UserData()->ElementAt(j)->PrintDiagnostics(mLogData); + ++i; + } } for (i = 0; i < ent->mCoalescingKeys.Length(); ++i) { mLogData.AppendPrintf(" :: Coalescing Key #%u %s\n", @@ -198,10 +206,10 @@ nsHttpTransaction::PrintDiagnostics(nsCString &log) nsAutoCString requestURI; mRequestHead->RequestURI(requestURI); - log.AppendPrintf(" ::: uri = %s\n", requestURI.get()); - log.AppendPrintf(" caps = 0x%x\n", mCaps); - log.AppendPrintf(" priority = %d\n", mPriority); - log.AppendPrintf(" restart count = %u\n", mRestartCount); + log.AppendPrintf(" :::: uri = %s\n", requestURI.get()); + log.AppendPrintf(" caps = 0x%x\n", mCaps); + log.AppendPrintf(" priority = %d\n", mPriority); + log.AppendPrintf(" restart count = %u\n", mRestartCount); } void diff --git a/netwerk/protocol/http/NullHttpTransaction.h b/netwerk/protocol/http/NullHttpTransaction.h index 934643266314..aff588a61d57 100644 --- a/netwerk/protocol/http/NullHttpTransaction.h +++ b/netwerk/protocol/http/NullHttpTransaction.h @@ -50,6 +50,12 @@ public: return PR_SecondsToInterval(15); } + // We have to override this function because |mTransaction| in nsHalfOpenSocket + // could be either nsHttpTransaction or NullHttpTransaction. + // NullHttpTransaction will be activated on the connection immediately after + // creation and be never put in a pending queue, so it's OK to just return 0. + uint64_t TopLevelOuterContentWindowId() override { return 0; } + protected: virtual ~NullHttpTransaction(); diff --git a/netwerk/protocol/http/nsAHttpTransaction.h b/netwerk/protocol/http/nsAHttpTransaction.h index e9eb4d1e4717..3b887b811355 100644 --- a/netwerk/protocol/http/nsAHttpTransaction.h +++ b/netwerk/protocol/http/nsAHttpTransaction.h @@ -183,6 +183,11 @@ public: virtual MOZ_MUST_USE nsresult Finish0RTT(bool aRestart, bool aAlpnChanged) { return NS_ERROR_NOT_IMPLEMENTED; } + + virtual uint64_t TopLevelOuterContentWindowId() { + MOZ_ASSERT(false); + return 0; + } }; NS_DEFINE_STATIC_IID_ACCESSOR(nsAHttpTransaction, NS_AHTTPTRANSACTION_IID) diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index 4aaf5fb35a9d..ca8159b8b3dc 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -35,6 +35,7 @@ #include "mozilla/Unused.h" #include "nsIURI.h" +#include "mozilla/Move.h" #include "mozilla/Telemetry.h" namespace mozilla { @@ -550,7 +551,7 @@ nsHttpConnectionMgr::ClearConnectionHistory() ent->mActiveConns.Length() == 0 && ent->mHalfOpens.Length() == 0 && ent->mUrgentStartQ.Length() == 0 && - ent->mPendingQ.Length() == 0) { + ent->PendingQLength() == 0) { iter.Remove(); } } @@ -635,10 +636,18 @@ nsHttpConnectionMgr::LookupConnectionEntry(nsHttpConnectionInfo *ci, return preferred; } - if (trans && - (preferred->mPendingQ.Contains(trans, PendingComparator()) || - preferred->mUrgentStartQ.Contains(trans, PendingComparator()))) { - return preferred; + if (trans) { + if (preferred->mUrgentStartQ.Contains(trans, PendingComparator())) { + return preferred; + } + + nsTArray> *infoArray; + if (preferred->mPendingTransactionTable.Get( + trans->TopLevelOuterContentWindowId(), &infoArray)) { + if (infoArray->Contains(trans, PendingComparator())) { + return preferred; + } + } } // Neither conn nor trans found in preferred, use the default entry @@ -879,15 +888,17 @@ nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry) } //----------------------------------------------------------------------------- -void +bool nsHttpConnectionMgr::DispatchPendingQ(nsTArray > &pendingQ, nsConnectionEntry *ent, - bool &dispatchedSuccessfully, bool considerAll) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); + PendingTransactionInfo *pendingTransInfo = nullptr; nsresult rv; + bool dispatchedSuccessfully = false; + // if !considerAll iterate the pending list until one is dispatched successfully. // Keep iterating afterwards only until a transaction fails to dispatch. // if considerAll == true then try and dispatch all items. @@ -971,6 +982,35 @@ nsHttpConnectionMgr::DispatchPendingQ(nsTArraymActiveConns.Length() + ent->UnconnectedHalfOpens(); + + uint16_t maxPersistConns; + + if (ent->mConnInfo->UsingHttpProxy() && !ent->mConnInfo->UsingConnect()) { + maxPersistConns = mMaxPersistConnsPerProxy; + } else { + maxPersistConns = mMaxPersistConnsPerHost; + } + + LOG(("nsHttpConnectionMgr::AvailableNewConnectionCount " + "total connection count = %d, limit %d\n", + totalCount, maxPersistConns)); + + return maxPersistConns > totalCount + ? maxPersistConns - totalCount + : 0; } bool @@ -983,17 +1023,112 @@ nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent, bool consid "queued=%" PRIuSIZE "]\n", ent->mConnInfo->HashKey().get(), ent, ent->mActiveConns.Length(), ent->mIdleConns.Length(), ent->mUrgentStartQ.Length(), - ent->mPendingQ.Length())); + ent->PendingQLength())); ProcessSpdyPendingQ(ent); bool dispatchedSuccessfully = false; - DispatchPendingQ(ent->mUrgentStartQ, ent, dispatchedSuccessfully, considerAll); + if (!ent->mUrgentStartQ.IsEmpty()) { + dispatchedSuccessfully = DispatchPendingQ(ent->mUrgentStartQ, + ent, + considerAll); + } + if (dispatchedSuccessfully && !considerAll) { return dispatchedSuccessfully; } - DispatchPendingQ(ent->mPendingQ, ent, dispatchedSuccessfully, considerAll); + + uint32_t availableConnections = AvailableNewConnectionCount(ent); + // No need to try dispatching if we reach the active connection limit. + if (!availableConnections) { + return dispatchedSuccessfully; + } + + uint32_t maxFocusedWindowConnections = + availableConnections * gHttpHandler->FocusedWindowTransactionRatio(); + MOZ_ASSERT(maxFocusedWindowConnections < availableConnections); + + if (!maxFocusedWindowConnections) { + maxFocusedWindowConnections = 1; + } + + // Only need to dispatch transactions for either focused or + // non-focused window because considerAll is false. + if (!considerAll) { + nsTArray> pendingQ; + ent->AppendPendingQForFocusedWindow( + mCurrentTopLevelOuterContentWindowId, + pendingQ, + maxFocusedWindowConnections); + + if (pendingQ.IsEmpty()) { + ent->AppendPendingQForNonFocusedWindows( + mCurrentTopLevelOuterContentWindowId, + pendingQ, + availableConnections); + } + + dispatchedSuccessfully |= + DispatchPendingQ(pendingQ, ent, considerAll); + + // Put the leftovers into connection entry + for (const auto& transactionInfo : pendingQ) { + ent->InsertTransaction(transactionInfo); + } + + return dispatchedSuccessfully; + } + + uint32_t maxNonFocusedWindowConnections = + availableConnections - maxFocusedWindowConnections; + nsTArray> pendingQ; + nsTArray> remainingPendingQ; + + ent->AppendPendingQForFocusedWindow( + mCurrentTopLevelOuterContentWindowId, + pendingQ, + maxFocusedWindowConnections); + + if (maxNonFocusedWindowConnections) { + ent->AppendPendingQForNonFocusedWindows( + mCurrentTopLevelOuterContentWindowId, + remainingPendingQ, + maxNonFocusedWindowConnections); + } + + // If the slots for the non-focused window are not filled up to + // the availability, try to use the remaining available connections + // for the focused window (with preference for the focused window). + if (remainingPendingQ.Length() < maxNonFocusedWindowConnections) { + ent->AppendPendingQForFocusedWindow( + mCurrentTopLevelOuterContentWindowId, + pendingQ, + maxNonFocusedWindowConnections - remainingPendingQ.Length()); + } + + MOZ_ASSERT(pendingQ.Length() + remainingPendingQ.Length() <= + availableConnections); + + LOG(("nsHttpConnectionMgr::ProcessPendingQForEntry " + "pendingQ.Length()=%" PRIuSIZE + ", remainingPendingQ.Length()=%" PRIuSIZE "\n", + pendingQ.Length(), remainingPendingQ.Length())); + + // Append elements in |remainingPendingQ| to |pendingQ|. The order in + // |pendingQ| is like: [focusedWindowTrans...nonFocusedWindowTrans]. + pendingQ.AppendElements(Move(remainingPendingQ)); + + dispatchedSuccessfully |= + DispatchPendingQ(pendingQ, ent, considerAll); + + // Put the leftovers into connection entry + for (const auto& transactionInfo : pendingQ) { + ent->InsertTransaction(transactionInfo); + } + + // Only remove empty pendingQ when considerAll is true. + ent->RemoveEmptyPendingQ(); return dispatchedSuccessfully; } @@ -1021,23 +1156,10 @@ nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, uint32_t ca LOG(("nsHttpConnectionMgr::AtActiveConnectionLimit [ci=%s caps=%x]\n", ci->HashKey().get(), caps)); - // Add in the in-progress tcp connections, we will assume they are - // keepalive enabled. - // Exclude half-open's that has already created a usable connection. - // This prevents the limit being stuck on ipv6 connections that - // eventually time out after typical 21 seconds of no ACK+SYN reply. - uint32_t totalCount = - ent->mActiveConns.Length() + ent->UnconnectedHalfOpens(); - - uint16_t maxPersistConns; - - if (ci->UsingHttpProxy() && !ci->UsingConnect()) - maxPersistConns = mMaxPersistConnsPerProxy; - else - maxPersistConns = mMaxPersistConnsPerHost; + uint32_t availableConnections = AvailableNewConnectionCount(ent); if (caps & NS_HTTP_URGENT_START) { - if (totalCount >= static_cast(mMaxUrgentStartQ + maxPersistConns)) { + if (availableConnections > static_cast(mMaxUrgentStartQ)) { LOG(("The number of total connections are greater than or equal to sum of " "max urgent-start queue length and the number of max persistent connections.\n")); return true; @@ -1062,11 +1184,8 @@ nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, uint32_t ca return true; } - LOG((" connection count = %d, limit %d\n", totalCount, maxPersistConns)); - - // use >= just to be safe - bool result = (totalCount >= maxPersistConns); - LOG((" result: %s", result ? "true" : "false")); + bool result = !availableConnections; + LOG(("AtActiveConnectionLimit result: %s", result ? "true" : "false")); return result; } @@ -1711,15 +1830,15 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) if (trans->Caps() & NS_HTTP_URGENT_START) { LOG((" adding transaction to pending queue " "[trans=%p urgent-start-count=%" PRIuSIZE "]\n", - trans, ent->mUrgentStartQ.Length()+1)); + trans, ent->mUrgentStartQ.Length() + 1)); // put this transaction on the urgent-start queue... InsertTransactionSorted(ent->mUrgentStartQ, pendingTransInfo); } else { LOG((" adding transaction to pending queue " "[trans=%p pending-count=%" PRIuSIZE "]\n", - trans, ent->mPendingQ.Length()+1)); + trans, ent->PendingQLength() + 1)); // put this transaction on the pending queue... - InsertTransactionSorted(ent->mPendingQ, pendingTransInfo); + ent->InsertTransaction(pendingTransInfo); } return NS_OK; } @@ -1893,11 +2012,21 @@ nsHttpConnectionMgr::ProcessSpdyPendingQ(nsConnectionEntry *ent) if (!conn || !conn->CanDirectlyActivate()) { return; } + DispatchSpdyPendingQ(ent->mUrgentStartQ, ent, conn); if (!conn->CanDirectlyActivate()) { return; } - DispatchSpdyPendingQ(ent->mPendingQ, ent, conn); + + nsTArray> pendingQ; + // XXX Get all transactions for SPDY currently. + ent->AppendPendingQForNonFocusedWindows(0, pendingQ); + DispatchSpdyPendingQ(pendingQ, ent, conn); + + // Put the leftovers back in the pending queue. + for (const auto& transactionInfo : pendingQ) { + ent->InsertTransaction(transactionInfo); + } } void @@ -2012,11 +2141,16 @@ nsHttpConnectionMgr::OnMsgShutdown(int32_t, ARefBase *param) } // Close all pending transactions. - while (ent->mPendingQ.Length()) { - PendingTransactionInfo *pendingTransInfo = ent->mPendingQ[0]; - pendingTransInfo->mTransaction->Close(NS_ERROR_ABORT); - ent->mPendingQ.RemoveElementAt(0); + for (auto it = ent->mPendingTransactionTable.Iter(); + !it.Done(); + it.Next()) { + while (it.UserData()->Length()) { + PendingTransactionInfo *pendingTransInfo = (*it.UserData())[0]; + pendingTransInfo->mTransaction->Close(NS_ERROR_ABORT); + it.UserData()->RemoveElementAt(0); + } } + ent->mPendingTransactionTable.Clear(); // Close all half open tcp connections. for (int32_t i = int32_t(ent->mHalfOpens.Length()) - 1; i >= 0; i--) { @@ -2083,14 +2217,18 @@ nsHttpConnectionMgr::OnMsgReschedTransaction(int32_t priority, ARefBase *param) if (ent) { int32_t caps = trans->Caps(); - nsTArray> *pendingQ; + nsTArray> *pendingQ = nullptr; if (caps & NS_HTTP_URGENT_START) { pendingQ = &(ent->mUrgentStartQ); } else { - pendingQ = &(ent->mPendingQ); + pendingQ = + ent->mPendingTransactionTable.Get( + trans->TopLevelOuterContentWindowId()); } - int32_t index = pendingQ->IndexOf(trans, 0, PendingComparator()); + int32_t index = pendingQ + ? pendingQ->IndexOf(trans, 0, PendingComparator()) + : -1; if (index >= 0) { RefPtr pendingTransInfo = (*pendingQ)[index]; pendingQ->RemoveElementAt(index); @@ -2127,29 +2265,25 @@ nsHttpConnectionMgr::OnMsgCancelTransaction(int32_t reason, ARefBase *param) int32_t transIndex; // We will abandon all half-open sockets belonging to the given // transaction. + nsTArray> *infoArray; RefPtr pendingTransInfo; if (caps & NS_HTTP_URGENT_START) { - transIndex = ent->mUrgentStartQ.IndexOf(trans, 0, - PendingComparator()); - if (transIndex >=0) { - LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]" - " found in urgentStart queue\n", trans)); - pendingTransInfo = ent->mUrgentStartQ[transIndex]; - // We do not need to ReleaseClaimedSockets while we are - // going to close them all any way! - ent->mUrgentStartQ.RemoveElementAt(transIndex); - } + infoArray = &ent->mUrgentStartQ; } else { - transIndex = ent->mPendingQ.IndexOf(trans, 0, - PendingComparator()); - if (transIndex >=0) { - LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]" - " found in pending queue\n", trans)); - pendingTransInfo = ent->mPendingQ[transIndex]; - // We do not need to ReleaseClaimedSockets while we are - // going to close them all any way! - ent->mPendingQ.RemoveElementAt(transIndex); - } + infoArray = ent->mPendingTransactionTable.Get( + trans->TopLevelOuterContentWindowId()); + } + + transIndex = infoArray + ? infoArray->IndexOf(trans, 0, PendingComparator()) + : -1; + if (transIndex >=0) { + LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]" + " found in urgentStart queue\n", trans)); + pendingTransInfo = (*infoArray)[transIndex]; + // We do not need to ReleaseClaimedSockets while we are + // going to close them all any way! + infoArray->RemoveElementAt(transIndex); } // Abandon all half-open sockets belonging to the given transaction. @@ -2228,6 +2362,21 @@ nsHttpConnectionMgr::CancelTransactions(nsHttpConnectionInfo *ci, nsresult code) return PostEvent(&nsHttpConnectionMgr::OnMsgCancelTransactions, intReason, ci); } +void +nsHttpConnectionMgr::CancelTransactionsHelper( + nsTArray> &pendingQ, + const nsHttpConnectionInfo *ci, + const nsHttpConnectionMgr::nsConnectionEntry *ent, + nsresult reason) +{ + for (const auto& pendingTransInfo : pendingQ) { + LOG(("nsHttpConnectionMgr::OnMsgCancelTransactions %s %p %p\n", + ci->HashKey().get(), ent, pendingTransInfo->mTransaction.get())); + pendingTransInfo->mTransaction->Close(reason); + } + pendingQ.Clear(); +} + void nsHttpConnectionMgr::OnMsgCancelTransactions(int32_t code, ARefBase *param) { @@ -2240,23 +2389,14 @@ nsHttpConnectionMgr::OnMsgCancelTransactions(int32_t code, ARefBase *param) return; } - for (uint32_t i = ent->mUrgentStartQ.Length(); i > 0;) { - --i; - PendingTransactionInfo *pendingTransInfo = ent->mUrgentStartQ[i]; - LOG(("nsHttpConnectionMgr::OnMsgCancelTransactions %s %p %p\n", - ci->HashKey().get(), ent, pendingTransInfo->mTransaction.get())); - pendingTransInfo->mTransaction->Close(reason); - ent->mUrgentStartQ.RemoveElementAt(i); - } + CancelTransactionsHelper(ent->mUrgentStartQ, ci, ent, reason); - for (uint32_t i = ent->mPendingQ.Length(); i > 0;) { - --i; - PendingTransactionInfo *pendingTransInfo = ent->mPendingQ[i]; - LOG(("nsHttpConnectionMgr::OnMsgCancelTransactions %s %p %p\n", - ci->HashKey().get(), ent, pendingTransInfo->mTransaction.get())); - pendingTransInfo->mTransaction->Close(reason); - ent->mPendingQ.RemoveElementAt(i); + for (auto it = ent->mPendingTransactionTable.Iter(); + !it.Done(); + it.Next()) { + CancelTransactionsHelper(*it.UserData(), ci, ent, reason); } + ent->mPendingTransactionTable.Clear(); } void @@ -2326,13 +2466,15 @@ nsHttpConnectionMgr::OnMsgPruneDeadConnections(int32_t, ARefBase *) ConditionallyStopPruneDeadConnectionsTimer(); } + ent->RemoveEmptyPendingQ(); + // If this entry is empty, we have too many entries busy then // we can clean it up and restart if (mCT.Count() > 125 && ent->mIdleConns.Length() == 0 && ent->mActiveConns.Length() == 0 && ent->mHalfOpens.Length() == 0 && - ent->mPendingQ.Length() == 0 && + ent->PendingQLength() == 0 && ent->mUrgentStartQ.Length() == 0 && (!ent->mUsingSpdy || mCT.Count() > 300)) { LOG((" removing empty connection entry\n")); @@ -2344,7 +2486,12 @@ nsHttpConnectionMgr::OnMsgPruneDeadConnections(int32_t, ARefBase *) ent->mIdleConns.Compact(); ent->mActiveConns.Compact(); ent->mUrgentStartQ.Compact(); - ent->mPendingQ.Compact(); + + for (auto it = ent->mPendingTransactionTable.Iter(); + !it.Done(); + it.Next()) { + it.UserData()->Compact(); + } } } } @@ -2692,7 +2839,7 @@ nsHttpConnectionMgr::TimeoutTick() " urgentStart pending=%" PRIuSIZE "\n", this, ent->mConnInfo->Origin(), ent->mIdleConns.Length(), ent->mActiveConns.Length(), ent->mHalfOpens.Length(), - ent->mPendingQ.Length(), ent->mUrgentStartQ.Length())); + ent->PendingQLength(), ent->mUrgentStartQ.Length())); // First call the tick handler for each active connection. PRIntervalTime tickTime = PR_IntervalNow(); @@ -3225,6 +3372,34 @@ nsHttpConnectionMgr::nsHalfOpenSocket::Notify(nsITimer *timer) return NS_OK; } +already_AddRefed +nsHttpConnectionMgr:: +nsHalfOpenSocket::FindTransactionHelper(bool removeWhenFound) +{ + uint32_t caps = mTransaction->Caps(); + nsTArray> *pendingQ = nullptr; + if (caps & NS_HTTP_URGENT_START) { + pendingQ = &mEnt->mUrgentStartQ; + } else { + pendingQ = + mEnt->mPendingTransactionTable.Get( + mTransaction->TopLevelOuterContentWindowId()); + } + + int32_t index = pendingQ + ? pendingQ->IndexOf(mTransaction, 0, PendingComparator()) + : -1; + + RefPtr info; + if (index != -1) { + info = (*pendingQ)[index]; + if (removeWhenFound) { + pendingQ->RemoveElementAt(index); + } + } + return info.forget(); +} + // method for nsIAsyncOutputStreamCallback NS_IMETHODIMP nsHttpConnectionMgr:: @@ -3305,28 +3480,14 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) mHasConnected = true; // if this is still in the pending list, remove it and dispatch it - uint32_t caps = mTransaction->Caps(); - int32_t index; - if (caps & NS_HTTP_URGENT_START) { - index = mEnt->mUrgentStartQ.IndexOf(mTransaction, 0, - PendingComparator()); - } else { - index = mEnt->mPendingQ.IndexOf(mTransaction, 0, PendingComparator()); - } - if (index > -1) { + RefPtr pendingTransInfo = FindTransactionHelper(true); + if (pendingTransInfo) { MOZ_ASSERT(!mSpeculative, "Speculative Half Open found mTransaction"); - RefPtr temp; - if (caps & NS_HTTP_URGENT_START) { - temp = mEnt->mUrgentStartQ[index]; - mEnt->mUrgentStartQ.RemoveElementAt(index); - } else { - temp = mEnt->mPendingQ[index]; - mEnt->mPendingQ.RemoveElementAt(index); - } + gHttpHandler->ConnMgr()->AddActiveConn(conn, mEnt); rv = gHttpHandler->ConnMgr()->DispatchTransaction(mEnt, - temp->mTransaction, + pendingTransInfo->mTransaction, conn); } else { // this transaction was dispatched off the pending q before all the @@ -3344,7 +3505,7 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) // NullHttpTransaction does not know how to drive Connect if (mEnt->mConnInfo->FirstHopSSL() && !mEnt->mUrgentStartQ.Length() && - !mEnt->mPendingQ.Length() && + !mEnt->PendingQLength() && !mEnt->mConnInfo->UsingConnect()) { LOG(("nsHalfOpenSocket::OnOutputStreamReady null transaction will " "be used to finish SSL handshake on conn %p\n", conn.get())); @@ -3383,9 +3544,10 @@ nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport *trans, MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); if (mTransaction) { + RefPtr info = FindTransactionHelper(false); if ((trans == mSocketTransport) || ((trans == mBackupTransport) && (status == NS_NET_STATUS_CONNECTED_TO) && - mEnt->mPendingQ.Contains(mTransaction, PendingComparator()))) { + info)) { // Send this status event only if the transaction is still panding, // i.e. it has not found a free already connected socket. // Sockets in halfOpen state can only get following events: @@ -3656,6 +3818,115 @@ nsConnectionEntry::ResetIPFamilyPreference() mPreferIPv6 = false; } +size_t +nsHttpConnectionMgr::nsConnectionEntry::PendingQLength() const +{ + size_t length = 0; + for (auto it = mPendingTransactionTable.ConstIter(); !it.Done(); it.Next()) { + length += it.UserData()->Length(); + } + + return length; +} + +void +nsHttpConnectionMgr:: +nsConnectionEntry::InsertTransaction(PendingTransactionInfo *info) +{ + LOG(("nsHttpConnectionMgr::nsConnectionEntry::InsertTransaction" + " trans=%p, windowId=%" PRIu64 "\n", + info->mTransaction.get(), + info->mTransaction->TopLevelOuterContentWindowId())); + + uint64_t windowId = info->mTransaction->TopLevelOuterContentWindowId(); + nsTArray> *infoArray; + if (!mPendingTransactionTable.Get(windowId, &infoArray)) { + infoArray = new nsTArray>(); + mPendingTransactionTable.Put(windowId, infoArray); + } + + gHttpHandler->ConnMgr()->InsertTransactionSorted(*infoArray, info); +} + +void +nsHttpConnectionMgr:: +nsConnectionEntry::AppendPendingQForFocusedWindow( + uint64_t windowId, + nsTArray> &result, + uint32_t maxCount) +{ + nsTArray> *infoArray = nullptr; + if (!mPendingTransactionTable.Get(windowId, &infoArray)) { + result.Clear(); + return; + } + + uint32_t countToAppend = maxCount; + countToAppend = + countToAppend > infoArray->Length() || countToAppend == 0 ? + infoArray->Length() : + countToAppend; + + result.InsertElementsAt(result.Length(), + infoArray->Elements(), + countToAppend); + infoArray->RemoveElementsAt(0, countToAppend); + + LOG(("nsConnectionEntry::AppendPendingQForFocusedWindow [ci=%s], " + "pendingQ count=%" PRIuSIZE " for focused window (id=%" PRIu64 ")\n", + mConnInfo->HashKey().get(), result.Length(), + windowId)); +} + +void +nsHttpConnectionMgr:: +nsConnectionEntry::AppendPendingQForNonFocusedWindows( + uint64_t windowId, + nsTArray> &result, + uint32_t maxCount) +{ + // XXX Adjust the order of transactions in a smarter manner. + uint32_t totalCount = 0; + for (auto it = mPendingTransactionTable.Iter(); !it.Done(); it.Next()) { + if (windowId && it.Key() == windowId) { + continue; + } + + uint32_t count = 0; + for (; count < it.UserData()->Length(); ++count) { + if (maxCount && totalCount == maxCount) { + break; + } + + // Because elements in |result| could come from multiple penndingQ, + // call |InsertTransactionSorted| to make sure the order is correct. + gHttpHandler->ConnMgr()->InsertTransactionSorted( + result, + it.UserData()->ElementAt(count)); + ++totalCount; + } + it.UserData()->RemoveElementsAt(0, count); + + if (maxCount && totalCount == maxCount) { + break; + } + } + + LOG(("nsConnectionEntry::AppendPendingQForNonFocusedWindows [ci=%s], " + "pendingQ count=%" PRIuSIZE " for non focused window\n", + mConnInfo->HashKey().get(), result.Length())); +} + +void +nsHttpConnectionMgr::nsConnectionEntry::RemoveEmptyPendingQ() +{ + for (auto it = mPendingTransactionTable.Iter(); !it.Done(); it.Next()) { + if (it.UserData()->IsEmpty()) { + it.Remove(); + } + } +} + void nsHttpConnectionMgr::MoveToWildCardConnEntry(nsHttpConnectionInfo *specificCI, nsHttpConnectionInfo *wildCardCI, @@ -3686,12 +3957,12 @@ nsHttpConnectionMgr::MoveToWildCardConnEntry(nsHttpConnectionInfo *specificCI, LOG(("nsHttpConnectionMgr::MakeConnEntryWildCard ent %p " "idle=%" PRIuSIZE " active=%" PRIuSIZE " half=%" PRIuSIZE " pending=%" PRIuSIZE "\n", ent, ent->mIdleConns.Length(), ent->mActiveConns.Length(), - ent->mHalfOpens.Length(), ent->mPendingQ.Length())); + ent->mHalfOpens.Length(), ent->PendingQLength())); LOG(("nsHttpConnectionMgr::MakeConnEntryWildCard wc-ent %p " "idle=%" PRIuSIZE " active=%" PRIuSIZE " half=%" PRIuSIZE " pending=%" PRIuSIZE "\n", wcEnt, wcEnt->mIdleConns.Length(), wcEnt->mActiveConns.Length(), - wcEnt->mHalfOpens.Length(), wcEnt->mPendingQ.Length())); + wcEnt->mHalfOpens.Length(), wcEnt->PendingQLength())); int32_t count = ent->mActiveConns.Length(); RefPtr deleteProtector(proxyConn); diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index abec89a36219..0494bc842478 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -221,7 +221,13 @@ private: RefPtr mConnInfo; nsTArray > mUrgentStartQ;// the urgent start transaction queue - nsTArray > mPendingQ; // pending transaction queue + + // This table provides a mapping from top level outer content window id + // to a queue of pending transaction information. + // Note that the window id could be 0 if the http request + // is initialized without a window. + nsClassHashtable>> mPendingTransactionTable; nsTArray > mActiveConns; // active connections nsTArray > mIdleConns; // idle persistent connections nsTArray mHalfOpens; // half open connections @@ -269,6 +275,33 @@ private: void RecordIPFamilyPreference(uint16_t family); // Resets all flags to their default values void ResetIPFamilyPreference(); + + // Return the count of pending transactions for all window ids. + size_t PendingQLength() const; + + // Add a transaction information into the pending queue in + // |mPendingTransactionTable| according to the transaction's + // top level outer content window id. + void InsertTransaction(PendingTransactionInfo *info); + + // Append transactions to the |result| whose window id + // is equal to |windowId|. + // NOTE: maxCount == 0 will get all transactions in the queue. + void AppendPendingQForFocusedWindow( + uint64_t windowId, + nsTArray> &result, + uint32_t maxCount = 0); + + // Append transactions whose window id isn't equal to |windowId|. + // NOTE: windowId == 0 will get all transactions for both + // focused and non-focused windows. + void AppendPendingQForNonFocusedWindows( + uint64_t windowId, + nsTArray> &result, + uint32_t maxCount = 0); + + // Remove the empty pendingQ in |mPendingTransactionTable|. + void RemoveEmptyPendingQ(); }; public: @@ -327,8 +360,14 @@ private: void PrintDiagnostics(nsCString &log); private: + // To find out whether |mTransaction| is still in the connection entry's + // pending queue. If the transaction is found and |removeWhenFound| is + // true, the transaction will be removed from the pending queue. + already_AddRefed + FindTransactionHelper(bool removeWhenFound); + nsConnectionEntry *mEnt; - RefPtr mTransaction; + RefPtr mTransaction; bool mDispatchedMTransaction; nsCOMPtr mSocketTransport; nsCOMPtr mStreamOut; @@ -419,10 +458,14 @@ private: MOZ_MUST_USE bool ProcessPendingQForEntry(nsConnectionEntry *, bool considerAll); - void DispatchPendingQ(nsTArray> &pendingQ, + bool DispatchPendingQ(nsTArray> &pendingQ, nsConnectionEntry *ent, - bool &dispatchedSuccessfully, bool considerAll); + + // Given the connection entry, return the available count for creating + // new connections. Return 0 if the active connection count is + // exceeded |mMaxPersistConnsPerProxy| or |mMaxPersistConnsPerHost|. + uint32_t AvailableNewConnectionCount(nsConnectionEntry * ent); bool AtActiveConnectionLimit(nsConnectionEntry *, uint32_t caps); MOZ_MUST_USE nsresult TryDispatchTransaction(nsConnectionEntry *ent, bool onlyReusedConnection, @@ -484,6 +527,14 @@ private: int32_t iparam = 0, ARefBase *vparam = nullptr); + // Used to close all transactions in the |pendingQ| with the given |reason|. + // Note that the |pendingQ| will be also cleared. + void CancelTransactionsHelper( + nsTArray> &pendingQ, + const nsHttpConnectionInfo *ci, + const nsConnectionEntry *ent, + nsresult reason); + // message handlers void OnMsgShutdown (int32_t, ARefBase *); void OnMsgShutdownConfirm (int32_t, ARefBase *); diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp index ffce09a49bd4..62c2a6f2d52c 100644 --- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -238,6 +238,7 @@ nsHttpHandler::nsHttpHandler() , mKeepEmptyResponseHeadersAsEmtpyString(false) , mDefaultHpackBuffer(4096) , mMaxHttpResponseHeaderSize(393216) + , mFocusedWindowTransactionRatio(0.9f) { LOG(("Creating nsHttpHandler [this=%p].\n", this)); @@ -1448,6 +1449,19 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref) mMaxHttpResponseHeaderSize = val; } } + + if (PREF_CHANGED(HTTP_PREF("focused_window_transaction_ratio"))) { + float ratio = 0; + rv = prefs->GetFloatPref(HTTP_PREF("focused_window_transaction_ratio"), &ratio); + if (NS_SUCCEEDED(rv)) { + if (ratio > 0 && ratio < 1) { + mFocusedWindowTransactionRatio = ratio; + } else { + NS_WARNING("Wrong value for focused_window_transaction_ratio"); + } + } + } + // // INTL options // diff --git a/netwerk/protocol/http/nsHttpHandler.h b/netwerk/protocol/http/nsHttpHandler.h index 2ff1e7ded20f..0c699559ba6b 100644 --- a/netwerk/protocol/http/nsHttpHandler.h +++ b/netwerk/protocol/http/nsHttpHandler.h @@ -358,6 +358,11 @@ public: return mMaxHttpResponseHeaderSize; } + float FocusedWindowTransactionRatio() const + { + return mFocusedWindowTransactionRatio; + } + private: virtual ~nsHttpHandler(); @@ -566,6 +571,9 @@ private: // The max size (in bytes) for received Http response header. uint32_t mMaxHttpResponseHeaderSize; + // The ratio for dispatching transactions from the focused window. + float mFocusedWindowTransactionRatio; + private: // For Rate Pacing Certain Network Events. Only assign this pointer on // socket thread. diff --git a/netwerk/protocol/http/nsHttpTransaction.h b/netwerk/protocol/http/nsHttpTransaction.h index 4bdd0284fab1..57ab68b2cf00 100644 --- a/netwerk/protocol/http/nsHttpTransaction.h +++ b/netwerk/protocol/http/nsHttpTransaction.h @@ -171,7 +171,7 @@ public: MOZ_MUST_USE bool Do0RTT() override; MOZ_MUST_USE nsresult Finish0RTT(bool aRestart, bool aAlpnChanged /* ignored */) override; - uint64_t TopLevelOuterContentWindowId() + uint64_t TopLevelOuterContentWindowId() override { return mTopLevelOuterContentWindowId; } From 790b8fd7ef74a68cb7c30f3cc5ad298aa3fc31e7 Mon Sep 17 00:00:00 2001 From: Kershaw Chang Date: Mon, 27 Mar 2017 04:10:00 -0400 Subject: [PATCH 05/22] Bug 1312782 - Part 2: Create urgent http requests until server receive all common http requests. r=honzab --- netwerk/test/unit/test_bug1312774_http1.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/netwerk/test/unit/test_bug1312774_http1.js b/netwerk/test/unit/test_bug1312774_http1.js index 1130b77e8d73..37d892274e29 100644 --- a/netwerk/test/unit/test_bug1312774_http1.js +++ b/netwerk/test/unit/test_bug1312774_http1.js @@ -69,6 +69,7 @@ function urgentStartHttpRequest(id) { } function setup_httpRequests() { + log("setup_httpRequests"); for (var i = 0; i < maxConnections ; i++) { commonHttpRequest(i); do_test_pending(); @@ -105,10 +106,12 @@ HttpResponseListener.prototype = var responseQueue = new Array(); function setup_http_server() { + log("setup_http_server"); var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); maxConnections = prefs.getIntPref("network.http.max-persistent-connections-per-server"); urgentRequests = 2; totalRequests = maxConnections + urgentRequests; + var allCommonHttpRequestReceived = false; // Start server; will be stopped at test cleanup time. server.registerPathHandler('/', function(metadata, response) { @@ -116,6 +119,11 @@ function setup_http_server() log("Server recived the response id=" + id); response.processAsync(); responseQueue.push(response); + + if (responseQueue.length == maxConnections && !allCommonHttpRequestReceived) { + allCommonHttpRequestReceived = true; + setup_urgentStartRequests(); + } // Wait for all expected requests to come but don't process then. // Collect them in a queue for later processing. We don't want to // respond to the client until all the expected requests are made @@ -140,6 +148,5 @@ function processResponse() { function run_test() { setup_http_server(); setup_httpRequests(); - setup_urgentStartRequests(); } From b9c0cd1f09a12d9fbda04b7f99b46a1a99bc648e Mon Sep 17 00:00:00 2001 From: Kershaw Chang Date: Mon, 27 Mar 2017 04:10:00 -0400 Subject: [PATCH 06/22] Bug 1312782 - Part 3: Test case. r=honzab --- netwerk/protocol/http/HttpBaseChannel.cpp | 13 ++ netwerk/protocol/http/HttpBaseChannel.h | 7 +- netwerk/protocol/http/NullHttpChannel.cpp | 12 ++ netwerk/protocol/http/nsIHttpChannel.idl | 9 + .../viewsource/nsViewSourceChannel.cpp | 14 ++ netwerk/test/unit/test_bug1312782_http1.js | 181 ++++++++++++++++++ netwerk/test/unit/xpcshell.ini | 1 + 7 files changed, 232 insertions(+), 5 deletions(-) create mode 100644 netwerk/test/unit/test_bug1312782_http1.js diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 9b94c39070d7..1dd6149fa65d 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -1372,6 +1372,19 @@ NS_IMETHODIMP HttpBaseChannel::GetTopLevelContentWindowId(uint64_t *aWindowId) return NS_OK; } +NS_IMETHODIMP HttpBaseChannel::SetTopLevelOuterContentWindowId(uint64_t aWindowId) +{ + mTopLevelOuterContentWindowId = aWindowId; + return NS_OK; +} + +NS_IMETHODIMP HttpBaseChannel::GetTopLevelOuterContentWindowId(uint64_t *aWindowId) +{ + EnsureTopLevelOuterContentWindowId(); + *aWindowId = mTopLevelOuterContentWindowId; + return NS_OK; +} + NS_IMETHODIMP HttpBaseChannel::SetTopLevelContentWindowId(uint64_t aWindowId) { mContentWindowId = aWindowId; diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index c29cbb5c04a9..3efd37911ec3 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -205,6 +205,8 @@ public: NS_IMETHOD SetChannelId(const nsACString& aChannelId) override; NS_IMETHOD GetTopLevelContentWindowId(uint64_t *aContentWindowId) override; NS_IMETHOD SetTopLevelContentWindowId(uint64_t aContentWindowId) override; + NS_IMETHOD GetTopLevelOuterContentWindowId(uint64_t *aWindowId) override; + NS_IMETHOD SetTopLevelOuterContentWindowId(uint64_t aWindowId) override; NS_IMETHOD GetIsTrackingResource(bool* aIsTrackingResource) override; // nsIHttpChannelInternal @@ -359,11 +361,6 @@ public: /* Necko internal use only... */ mIsTrackingResource = true; } - void SetTopLevelOuterContentWindowId(uint64_t aTopLevelOuterContentWindowId) - { - mTopLevelOuterContentWindowId = aTopLevelOuterContentWindowId; - } - protected: // Handle notifying listener, removing from loadgroup if request failed. void DoNotifyListener(); diff --git a/netwerk/protocol/http/NullHttpChannel.cpp b/netwerk/protocol/http/NullHttpChannel.cpp index 1fc9e8f01861..072dd1e60433 100644 --- a/netwerk/protocol/http/NullHttpChannel.cpp +++ b/netwerk/protocol/http/NullHttpChannel.cpp @@ -81,6 +81,18 @@ NullHttpChannel::SetTopLevelContentWindowId(uint64_t aWindowId) return NS_ERROR_NOT_IMPLEMENTED; } +NS_IMETHODIMP +NullHttpChannel::GetTopLevelOuterContentWindowId(uint64_t *aWindowId) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +NullHttpChannel::SetTopLevelOuterContentWindowId(uint64_t aWindowId) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + NS_IMETHODIMP NullHttpChannel::GetIsTrackingResource(bool* aIsTrackingResource) { diff --git a/netwerk/protocol/http/nsIHttpChannel.idl b/netwerk/protocol/http/nsIHttpChannel.idl index fc2ddb5961e4..930cd43f250f 100644 --- a/netwerk/protocol/http/nsIHttpChannel.idl +++ b/netwerk/protocol/http/nsIHttpChannel.idl @@ -469,4 +469,13 @@ interface nsIHttpChannel : nsIChannel * should only be relied on after the channel has established a connection. */ [infallible] readonly attribute boolean isTrackingResource; + + /** + * ID of the top-level outer content window. Identifies this channel's + * top-level window it comes from. + * + * NOTE: The setter of this attribute is currently for xpcshell test only. + * Don't alter it otherwise. + */ + [must_use] attribute uint64_t topLevelOuterContentWindowId; }; diff --git a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp index cfa4eceff625..d5ffdee7c6bb 100644 --- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp +++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp @@ -739,6 +739,20 @@ nsViewSourceChannel::SetTopLevelContentWindowId(uint64_t aWindowId) mHttpChannel->SetTopLevelContentWindowId(aWindowId); } +NS_IMETHODIMP +nsViewSourceChannel::GetTopLevelOuterContentWindowId(uint64_t *aWindowId) +{ + return !mHttpChannel ? NS_ERROR_NULL_POINTER : + mHttpChannel->GetTopLevelOuterContentWindowId(aWindowId); +} + +NS_IMETHODIMP +nsViewSourceChannel::SetTopLevelOuterContentWindowId(uint64_t aWindowId) +{ + return !mHttpChannel ? NS_ERROR_NULL_POINTER : + mHttpChannel->SetTopLevelOuterContentWindowId(aWindowId); +} + NS_IMETHODIMP nsViewSourceChannel::GetIsTrackingResource(bool* aIsTrackingResource) { diff --git a/netwerk/test/unit/test_bug1312782_http1.js b/netwerk/test/unit/test_bug1312782_http1.js new file mode 100644 index 000000000000..d5c23693ffa2 --- /dev/null +++ b/netwerk/test/unit/test_bug1312782_http1.js @@ -0,0 +1,181 @@ +// test bug 1312782. +// +// Summary: +// Assume we have 6 http requests in queue, 4 are from the focused window and +// the other 2 are from the non-focused window. We want to test that the server +// should receive 4 requests from the focused window first and then receive the +// rest 2 requests. +// +// Test step: +// 1. Create 6 dummy http requests. Server would not process responses until get +// all 6 requests. +// 2. Once server receive 6 dummy requests, create 4 http requests with the focused +// window id and 2 requests with non-focused window id. Note that the requets's +// id is a serial number starting from the focused window id. +// 3. Server starts to process the 6 dummy http requests, so the client can start to +// process the pending queue. Server will queue those http requests again and wait +// until get all 6 requests. +// 4. When the server receive all 6 requests, starts to check that the request ids of +// the first 4 requests in the queue should be all less than focused window id +// plus 4. Also, the request ids of the rest requests should be less than non-focused +// window id + 2. + +Cu.import("resource://testing-common/httpd.js"); +Cu.import("resource://gre/modules/NetUtil.jsm"); + +var Cc = Components.classes; +var Ci = Components.interfaces; +var server = new HttpServer(); +server.start(-1); +var baseURL = "http://localhost:" + server.identity.primaryPort + "/"; +var maxConnections = 0; +var debug = false; +const FOCUSED_WINDOW_ID = 123; +var NON_FOCUSED_WINDOW_ID; +var FOCUSED_WINDOW_REQUEST_COUNT; +var NON_FOCUSED_WINDOW_REQUEST_COUNT; + +function log(msg) { + if (!debug) { + return; + } + + if (msg) { + dump("TEST INFO | " + msg + "\n"); + } +} + +function make_channel(url) { + var request = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true}); + request.QueryInterface(Ci.nsIHttpChannel); + return request; +} + +function serverStopListener() { + server.stop(); +} + +function createHttpRequest(windowId, requestId) { + let uri = baseURL; + var chan = make_channel(uri); + chan.topLevelOuterContentWindowId = windowId; + var listner = new HttpResponseListener(requestId); + chan.setRequestHeader("X-ID", requestId, false); + chan.setRequestHeader("Cache-control", "no-store", false); + chan.asyncOpen2(listner); + log("Create http request id=" + requestId); +} + +function setup_dummyHttpRequests() { + log("setup_dummyHttpRequests"); + for (var i = 0; i < maxConnections ; i++) { + createHttpRequest(0, i); + do_test_pending(); + } +} + +function setup_focusedWindowHttpRequests() { + log("setup_focusedWindowHttpRequests"); + for (var i = 0; i < FOCUSED_WINDOW_REQUEST_COUNT ; i++) { + createHttpRequest(FOCUSED_WINDOW_ID, FOCUSED_WINDOW_ID + i); + do_test_pending(); + } +} + +function setup_nonFocusedWindowHttpRequests() { + log("setup_nonFocusedWindowHttpRequests"); + for (var i = 0; i < NON_FOCUSED_WINDOW_REQUEST_COUNT ; i++) { + createHttpRequest(NON_FOCUSED_WINDOW_ID, NON_FOCUSED_WINDOW_ID + i); + do_test_pending(); + } +} + +function HttpResponseListener(id) +{ + this.id = id +}; + +HttpResponseListener.prototype = +{ + onStartRequest: function (request, ctx) { + }, + + onDataAvailable: function (request, ctx, stream, off, cnt) { + }, + + onStopRequest: function (request, ctx, status) { + log("STOP id=" + this.id); + do_test_finished(); + } +}; + +function check_response_id(responses, maxWindowId) +{ + for (var i = 0; i < responses.length; i++) { + var id = responses[i].getHeader("X-ID"); + log("response id=" + id + " maxWindowId=" + maxWindowId); + do_check_true(id < maxWindowId); + } +} + +var responseQueue = new Array(); +function setup_http_server() +{ + log("setup_http_server"); + var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); + maxConnections = prefs.getIntPref("network.http.max-persistent-connections-per-server"); + FOCUSED_WINDOW_REQUEST_COUNT = Math.floor(maxConnections * 0.8); + NON_FOCUSED_WINDOW_REQUEST_COUNT = maxConnections - FOCUSED_WINDOW_REQUEST_COUNT; + NON_FOCUSED_WINDOW_ID = FOCUSED_WINDOW_ID + FOCUSED_WINDOW_REQUEST_COUNT; + + var allDummyHttpRequestReceived = false; + // Start server; will be stopped at test cleanup time. + server.registerPathHandler('/', function(metadata, response) + { + var id = metadata.getHeader("X-ID"); + log("Server recived the response id=" + id); + + response.processAsync(); + response.setHeader("X-ID", id); + responseQueue.push(response); + + if (responseQueue.length == maxConnections && !allDummyHttpRequestReceived) { + log("received all dummy http requets"); + allDummyHttpRequestReceived = true; + setup_nonFocusedWindowHttpRequests(); + setup_focusedWindowHttpRequests(); + processResponses(); + } else if (responseQueue.length == maxConnections) { + var focusedWindowResponses = responseQueue.slice(0, FOCUSED_WINDOW_REQUEST_COUNT); + var nonFocusedWindowResponses = responseQueue.slice(FOCUSED_WINDOW_REQUEST_COUNT, responseQueue.length); + check_response_id(focusedWindowResponses, FOCUSED_WINDOW_ID + FOCUSED_WINDOW_REQUEST_COUNT); + check_response_id(nonFocusedWindowResponses, NON_FOCUSED_WINDOW_ID + NON_FOCUSED_WINDOW_REQUEST_COUNT); + processResponses(); + } + + }); + + do_register_cleanup(function() { + server.stop(serverStopListener); + }); + +} + +function processResponses() { + while (responseQueue.length) { + var resposne = responseQueue.pop(); + resposne.finish(); + } +} + +function run_test() { + setup_http_server(); + setup_dummyHttpRequests(); + + var windowIdWrapper = Cc["@mozilla.org/supports-PRUint64;1"] + .createInstance(Ci.nsISupportsPRUint64); + windowIdWrapper.data = FOCUSED_WINDOW_ID; + var obsvc = Cc["@mozilla.org/observer-service;1"]. + getService(Ci.nsIObserverService); + obsvc.notifyObservers(windowIdWrapper, "net:current-toplevel-outer-content-windowid", null); +} diff --git a/netwerk/test/unit/xpcshell.ini b/netwerk/test/unit/xpcshell.ini index 3410915c176b..ab63e33390f5 100644 --- a/netwerk/test/unit/xpcshell.ini +++ b/netwerk/test/unit/xpcshell.ini @@ -384,3 +384,4 @@ skip-if = os == "android" [test_race_cache_network.js] [test_channel_priority.js] [test_bug1312774_http1.js] +[test_bug1312782_http1.js] From 42d7612ddbb5d8e3ba7b0d17982a6f4e4ac0842d Mon Sep 17 00:00:00 2001 From: Andreas Farre Date: Mon, 27 Mar 2017 06:29:00 -0400 Subject: [PATCH 07/22] Bug 1350699 - Update test now that IdleDeadline interface is exposed. r=smaug MozReview-Commit-ID: 4RHPQrhxLRE --- dom/tests/mochitest/general/test_interfaces.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/tests/mochitest/general/test_interfaces.js b/dom/tests/mochitest/general/test_interfaces.js index b9964ed26e52..714e6f6f83e5 100644 --- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -548,7 +548,7 @@ var interfaceNamesInGlobalScope = // IMPORTANT: Do not change this list without review from a DOM peer! "HTMLVideoElement", // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "IdleDeadline", nightly: true}, + {name: "IdleDeadline"}, // IMPORTANT: Do not change this list without review from a DOM peer! "IDBCursor", // IMPORTANT: Do not change this list without review from a DOM peer! From 481bc71c415919d5375124aba8a0b766d7128ce0 Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Mon, 27 Mar 2017 22:30:28 +0200 Subject: [PATCH 08/22] Backed out changeset 810aeb2601d6 (bug 1271991) for bustage in Telemetry.cpp on OSX. r=backout on a CLOSED TREE --- toolkit/components/telemetry/Telemetry.cpp | 48 +++++----------------- 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/toolkit/components/telemetry/Telemetry.cpp b/toolkit/components/telemetry/Telemetry.cpp index 47507a31ab29..5487fd0ab15f 100644 --- a/toolkit/components/telemetry/Telemetry.cpp +++ b/toolkit/components/telemetry/Telemetry.cpp @@ -928,8 +928,6 @@ public: static void RecordIceCandidates(const uint32_t iceCandidateBitmask, const bool success); - static bool CanRecordBase(); - static bool CanRecordExtended(); private: TelemetryImpl(); ~TelemetryImpl(); @@ -961,8 +959,6 @@ private: Mutex mHashMutex; HangReports mHangReports; Mutex mHangReportsMutex; - Atomic mCanRecordBase; - Atomic mCanRecordExtended; #if defined(ENABLE_STACK_CAPTURE) // Stores data about stacks captured on demand. @@ -1250,8 +1246,6 @@ TelemetryImpl::TelemetryImpl() , mCachedTelemetryData(false) , mLastShutdownTime(0) , mFailedLockCount(0) - , mCanRecordBase(false) - , mCanRecordExtended(false) { // We expect TelemetryHistogram::InitializeGlobalState() to have been // called before we get to this point. @@ -2280,18 +2274,15 @@ TelemetryImpl::GetKeyedHistogramById(const nsACString &name, JSContext *cx, */ NS_IMETHODIMP TelemetryImpl::GetCanRecordBase(bool *ret) { - *ret = mCanRecordBase; + *ret = TelemetryHistogram::CanRecordBase(); return NS_OK; } NS_IMETHODIMP TelemetryImpl::SetCanRecordBase(bool canRecord) { - if (canRecord != mCanRecordBase) { - TelemetryHistogram::SetCanRecordBase(canRecord); - TelemetryScalar::SetCanRecordBase(canRecord); - TelemetryEvent::SetCanRecordBase(canRecord); - mCanRecordBase = canRecord; - } + TelemetryHistogram::SetCanRecordBase(canRecord); + TelemetryScalar::SetCanRecordBase(canRecord); + TelemetryEvent::SetCanRecordBase(canRecord); return NS_OK; } @@ -2304,18 +2295,15 @@ TelemetryImpl::SetCanRecordBase(bool canRecord) { */ NS_IMETHODIMP TelemetryImpl::GetCanRecordExtended(bool *ret) { - *ret = mCanRecordExtended; + *ret = TelemetryHistogram::CanRecordExtended(); return NS_OK; } NS_IMETHODIMP TelemetryImpl::SetCanRecordExtended(bool canRecord) { - if (canRecord != mCanRecordExtended) { - TelemetryHistogram::SetCanRecordExtended(canRecord); - TelemetryScalar::SetCanRecordExtended(canRecord); - TelemetryEvent::SetCanRecordExtended(canRecord); - mCanRecordExtended = canRecord; - } + TelemetryHistogram::SetCanRecordExtended(canRecord); + TelemetryScalar::SetCanRecordExtended(canRecord); + TelemetryEvent::SetCanRecordExtended(canRecord); return NS_OK; } @@ -2708,22 +2696,6 @@ TelemetryImpl::RecordThreadHangStats(Telemetry::ThreadHangStats& aStats) mozilla::Unused << sTelemetry->mThreadHangStats.append(Move(aStats)); } -bool -TelemetryImpl::CanRecordBase() -{ - bool canRecordBase; - nsresult rv = sTelemetry->GetCanRecordBase(&canRecordBase); - return NS_SUCCEEDED(rv) && canRecordBase; -} - -bool -TelemetryImpl::CanRecordExtended() -{ - bool canRecordExtended; - nsresult rv = sTelemetry->GetCanRecordExtended(&canRecordExtended); - return NS_SUCCEEDED(rv) && canRecordExtended; -} - NS_IMPL_ISUPPORTS(TelemetryImpl, nsITelemetry, nsIMemoryReporter) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelemetry, TelemetryImpl::CreateTelemetryInstance) @@ -3406,13 +3378,13 @@ GetHistogramName(HistogramID id) bool CanRecordBase() { - return TelemetryImpl::CanRecordBase(); + return TelemetryHistogram::CanRecordBase(); } bool CanRecordExtended() { - return TelemetryImpl::CanRecordExtended(); + return TelemetryHistogram::CanRecordExtended(); } void From dc1431e99e9befb4c7757f5b22161bbb06043a09 Mon Sep 17 00:00:00 2001 From: Florian Queze Date: Mon, 27 Mar 2017 22:46:49 +0200 Subject: [PATCH 09/22] Bug 1349307 - disable browser_all_files_referenced.js on linux32 where it causes oom crashes, rs=Gijs. --- browser/base/content/test/static/browser.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/base/content/test/static/browser.ini b/browser/base/content/test/static/browser.ini index 75fb4b904b64..2a45df22582f 100644 --- a/browser/base/content/test/static/browser.ini +++ b/browser/base/content/test/static/browser.ini @@ -3,7 +3,7 @@ support-files = head.js [browser_all_files_referenced.js] -skip-if = debug # no point in running on both opt and debug, and will likely intermittently timeout on debug +skip-if = debug || (os == 'linux' && bits == 32) # no point in running on both opt and debug, and will likely intermittently timeout on debug; oom crashes on linux32 (bug 1349307) [browser_misused_characters_in_strings.js] support-files = bug1262648_string_with_newlines.dtd From d1ff7a8b0ef85a1887b335da3f9a4339518d85c4 Mon Sep 17 00:00:00 2001 From: Florian Queze Date: Mon, 27 Mar 2017 22:46:59 +0200 Subject: [PATCH 10/22] Bug 1349508 - request a longer timeout for browser_all_files_referenced.js which takes longer on asan, rs=Gijs. --- .../base/content/test/static/browser_all_files_referenced.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/browser/base/content/test/static/browser_all_files_referenced.js b/browser/base/content/test/static/browser_all_files_referenced.js index 294b87188e8c..c357ad4d61a2 100644 --- a/browser/base/content/test/static/browser_all_files_referenced.js +++ b/browser/base/content/test/static/browser_all_files_referenced.js @@ -1,6 +1,9 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ +// Slow on asan builds. +requestLongerTimeout(5); + var isDevtools = SimpleTest.harnessParameters.subsuite == "devtools"; var gExceptionPaths = ["chrome://browser/content/defaultthemes/", From 2c4840cca60e39644d10e69f77f54cd2567d759f Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 27 Mar 2017 13:59:33 -0700 Subject: [PATCH 11/22] Fix DXGIYCbCrTextureHost not setting a TextureSourceProvider. (bug 1350251, r=mattwoodrow) --HG-- extra : rebase_source : e6426ddb660ab2df6f263ff01a959deab86d60ce --- gfx/layers/d3d11/TextureD3D11.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 5c2662f6a65a..39bae03987a3 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -895,12 +895,15 @@ void DXGIYCbCrTextureHostD3D11::SetTextureSourceProvider(TextureSourceProvider* aProvider) { if (!aProvider || !aProvider->GetD3D11Device()) { + mProvider = nullptr; mTextureSources[0] = nullptr; mTextureSources[1] = nullptr; mTextureSources[2] = nullptr; return; } + mProvider = aProvider; + if (mTextureSources[0]) { mTextureSources[0]->SetTextureSourceProvider(aProvider); } From b048f397cad29127432188a603e57efc7624b177 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 27 Mar 2017 14:02:50 -0700 Subject: [PATCH 12/22] Fix DXGITextureHostD3D11 not being able to lock without a compositor. (bug 1350247, r=mattwoodrow) --- gfx/layers/d3d11/TextureD3D11.cpp | 8 ++++++-- gfx/layers/d3d11/TextureD3D11.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 39bae03987a3..345372370eb0 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -737,20 +737,21 @@ DXGITextureHostD3D11::GetDevice() if (mFlags & TextureFlags::INVALID_COMPOSITOR) { return nullptr; } - - return mProvider->GetD3D11Device(); + return mDevice; } void DXGITextureHostD3D11::SetTextureSourceProvider(TextureSourceProvider* aProvider) { if (!aProvider || !aProvider->GetD3D11Device()) { + mDevice = nullptr; mProvider = nullptr; mTextureSource = nullptr; return; } mProvider = aProvider; + mDevice = aProvider->GetD3D11Device(); if (mTextureSource) { mTextureSource->SetTextureSourceProvider(aProvider); @@ -776,6 +777,9 @@ DXGITextureHostD3D11::LockWithoutCompositor() // Unlike the normal Lock() function, this function may be called when // mCompositor is nullptr such as during WebVR frame submission. So, there is // no 'mCompositor' checking here. + if (!mDevice) { + mDevice = DeviceManagerDx::Get()->GetCompositorDevice(); + } return LockInternal(); } diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index 48e664487697..d6e08a2c4662 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -333,6 +333,7 @@ protected: bool OpenSharedHandle(); + RefPtr mDevice; RefPtr mTexture; RefPtr mTextureSource; gfx::IntSize mSize; From 75493877fc5312caf5e517179073a005a8fe616e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 24 Mar 2017 02:36:08 +0100 Subject: [PATCH 13/22] Bug 1350147: Remove -moz-bound-element pseudo-class. r=xidorn MozReview-Commit-ID: GySVYOfoL1A --- dom/xbl/nsBindingManager.cpp | 4 ---- layout/style/nsCSSPseudoClassList.h | 1 - layout/style/nsCSSRuleProcessor.cpp | 6 ------ layout/style/nsRuleProcessorData.h | 5 ----- 4 files changed, 16 deletions(-) diff --git a/dom/xbl/nsBindingManager.cpp b/dom/xbl/nsBindingManager.cpp index 925830fd15e2..a25db8636837 100644 --- a/dom/xbl/nsBindingManager.cpp +++ b/dom/xbl/nsBindingManager.cpp @@ -675,7 +675,6 @@ nsBindingManager::WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, do { nsXBLBinding *binding = content->GetXBLBinding(); if (binding) { - aData->mTreeMatchContext.mScopedRoot = content; binding->WalkRules(aFunc, aData); // If we're not looking at our original content, allow the binding to cut // off style inheritance @@ -698,9 +697,6 @@ nsBindingManager::WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, // in the loop. *aCutOffInheritance = (content != nullptr); - // Null out the scoped root that we set repeatedly - aData->mTreeMatchContext.mScopedRoot = nullptr; - return NS_OK; } diff --git a/layout/style/nsCSSPseudoClassList.h b/layout/style/nsCSSPseudoClassList.h index 2b756001d3a6..d84364ca1040 100644 --- a/layout/style/nsCSSPseudoClassList.h +++ b/layout/style/nsCSSPseudoClassList.h @@ -70,7 +70,6 @@ CSS_PSEUDO_CLASS(empty, ":empty", 0, "") CSS_PSEUDO_CLASS(mozOnlyWhitespace, ":-moz-only-whitespace", 0, "") CSS_PSEUDO_CLASS(mozEmptyExceptChildrenWithLocalname, ":-moz-empty-except-children-with-localname", 0, "") CSS_PSEUDO_CLASS(lang, ":lang", 0, "") -CSS_PSEUDO_CLASS(mozBoundElement, ":-moz-bound-element", 0, "") CSS_PSEUDO_CLASS(root, ":root", 0, "") CSS_PSEUDO_CLASS(any, ":-moz-any", 0, "") diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index 1c2e4351589a..5133f490837f 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -1968,12 +1968,6 @@ static bool SelectorMatches(Element* aElement, } break; - case CSSPseudoClassType::mozBoundElement: - if (aTreeMatchContext.mScopedRoot != aElement) { - return false; - } - break; - case CSSPseudoClassType::root: if (aElement != aElement->OwnerDoc()->GetRootElement()) { return false; diff --git a/layout/style/nsRuleProcessorData.h b/layout/style/nsRuleProcessorData.h index f86c7289eeba..9042fe3c9a12 100644 --- a/layout/style/nsRuleProcessorData.h +++ b/layout/style/nsRuleProcessorData.h @@ -342,10 +342,6 @@ struct MOZ_STACK_CLASS TreeMatchContext { // The document we're working with. nsIDocument* const mDocument; - // Root of scoped stylesheet (set and unset by the supplier of the - // scoped stylesheet). - nsIContent* mScopedRoot; - // Whether our document is HTML (as opposed to XML of some sort, // including XHTML). // XXX XBL2 issue: Should we be caching this? What should it be for XBL2? @@ -396,7 +392,6 @@ struct MOZ_STACK_CLASS TreeMatchContext { , mHaveSpecifiedScope(false) , mVisitedHandling(aVisitedHandling) , mDocument(aDocument) - , mScopedRoot(nullptr) , mIsHTMLDocument(aDocument->IsHTMLDocument()) , mCompatMode(aDocument->GetCompatibilityMode()) , mUsingPrivateBrowsing(false) From 23e8ac47d2b3ae82934265d49be7dd7bb1b37971 Mon Sep 17 00:00:00 2001 From: Michael Layzell Date: Mon, 27 Mar 2017 17:44:27 -0400 Subject: [PATCH 14/22] Bug 1348143 - Check nsresult values more places in DataTransfer. r=enndeakin MozReview-Commit-ID: BP4avMImDB8 --- dom/events/DataTransfer.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/dom/events/DataTransfer.cpp b/dom/events/DataTransfer.cpp index 3b4f92a7cb50..7918ce89341b 100644 --- a/dom/events/DataTransfer.cpp +++ b/dom/events/DataTransfer.cpp @@ -1495,30 +1495,37 @@ DataTransfer::FillInExternalCustomTypes(nsIVariant* aData, uint32_t aIndex, return; } - stream->SetInputStream(stringStream); + rv = stream->SetInputStream(stringStream); + NS_ENSURE_SUCCESS_VOID(rv); uint32_t type; do { - stream->Read32(&type); + rv = stream->Read32(&type); + NS_ENSURE_SUCCESS_VOID(rv); if (type == eCustomClipboardTypeId_String) { uint32_t formatLength; - stream->Read32(&formatLength); + rv = stream->Read32(&formatLength); + NS_ENSURE_SUCCESS_VOID(rv); char* formatBytes; - stream->ReadBytes(formatLength, &formatBytes); + rv = stream->ReadBytes(formatLength, &formatBytes); + NS_ENSURE_SUCCESS_VOID(rv); nsAutoString format; format.Adopt(reinterpret_cast(formatBytes), formatLength / sizeof(char16_t)); uint32_t dataLength; - stream->Read32(&dataLength); + rv = stream->Read32(&dataLength); + NS_ENSURE_SUCCESS_VOID(rv); char* dataBytes; - stream->ReadBytes(dataLength, &dataBytes); + rv = stream->ReadBytes(dataLength, &dataBytes); + NS_ENSURE_SUCCESS_VOID(rv); nsAutoString data; data.Adopt(reinterpret_cast(dataBytes), dataLength / sizeof(char16_t)); RefPtr variant = new nsVariantCC(); - variant->SetAsAString(data); + rv = variant->SetAsAString(data); + NS_ENSURE_SUCCESS_VOID(rv); SetDataWithPrincipal(format, variant, aIndex, aPrincipal); } From b811e82ce68cf1b169a645e4691e109381a64efa Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Mon, 27 Mar 2017 11:53:47 -0700 Subject: [PATCH 15/22] Bug 1350464 - Don't try to poison not-yet-allocated structures when an error occurs during parsing. r=arai --HG-- extra : rebase_source : 05df0ec3dd38e73de0a8b156b0a0b5725622a350 --- js/src/frontend/TokenStream.cpp | 6 +- .../oom-tracking-line-starts-in-tokenizer.js | 143 ++++++++++++++++++ 2 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 js/src/jit-test/tests/parser/oom-tracking-line-starts-in-tokenizer.js diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index ff58490f4e64..5da0847b8623 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -1938,9 +1938,9 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier) return true; error: - flags.isDirtyLine = true; - tp->pos.end = userbuf.offset(); - MOZ_MAKE_MEM_UNDEFINED(&tp->type, sizeof(tp->type)); + // We didn't get a token, so don't set |flags.isDirtyLine|. And don't + // poison any of |*tp|: if we haven't allocated a token, |tp| could be + // uninitialized. flags.hadError = true; #ifdef DEBUG // Poisoning userbuf on error establishes an invariant: once an erroneous diff --git a/js/src/jit-test/tests/parser/oom-tracking-line-starts-in-tokenizer.js b/js/src/jit-test/tests/parser/oom-tracking-line-starts-in-tokenizer.js new file mode 100644 index 000000000000..46aa1dbd046d --- /dev/null +++ b/js/src/jit-test/tests/parser/oom-tracking-line-starts-in-tokenizer.js @@ -0,0 +1,143 @@ +// Constraints on this test's appearance: +// +// * |TokenStream::SourceCoords::add| must try to allocate memory. (This test +// ensures this happens by making the function below >=128 lines long so +// that |SourceCoords::lineStartOffsets_| must convert to heap storage. The +// precise approach doesn't matter.) +// * That allocation attempt must fail (by forced simulated OOM, here). +// +// It'd be nice to build up the function programmatically, but it appears that +// the above only happens if the provided function has a lazy script. Cursory +// attempts to relazify |Function("...")| didn't work, so this fuzzer-like +// version had to be used instead. +if ("oomTest" in this) { + oomTest(function() { + try { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } catch(e) { + ; + } + }) +} From 399c98ac3c05922faa37da2f3c2740681063589e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 27 Mar 2017 16:49:41 +1100 Subject: [PATCH 16/22] Bug 1348776 (part 1) - Fix a crash in the profiler when MOZ_PROFILING is undefined. r=mstange. Bug 1339695 part 8 unintentionally changed behaviour in profiler_init() when MOZ_PROFILING is undefined. This patch undoes that change. --HG-- extra : rebase_source : 16e992382e06fbc673555c87499c236e2b39bc7f --- tools/profiler/core/platform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp index 883b68b4c2fa..d5d05381ef1c 100644 --- a/tools/profiler/core/platform.cpp +++ b/tools/profiler/core/platform.cpp @@ -2954,7 +2954,7 @@ profiler_get_backtrace() TickSample sample(threadInfo); sample.mIsSamplingCurrentThread = true; -#if defined(HAVE_NATIVE_UNWIND) +#if defined(HAVE_NATIVE_UNWIND) || defined(USE_LUL_STACKWALK) #if defined(GP_OS_windows) || defined(GP_OS_linux) || defined(GP_OS_android) tick_context_t context; sample.PopulateContext(&context); From a8a6c5c4ba02b965e3047204991fb40507ad2e75 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 27 Mar 2017 17:04:56 +1100 Subject: [PATCH 17/22] Bug 1348776 (part 2) - Fix up HAVE_NATIVE_UNWIND. r=mstange. This patch simplifies and increases the consistency of how HAVE_NATIVE_UNWIND is used. - Its definition is moved from platform.h to platform.cpp, because the latter is the only file that uses it. - It's now defined in the same place as USE_{NS,EHABI,LUL}_STACKWALK, and used in preference to those, where possible. Also, it's now defined on Linux and Android even if MOZ_PROFILING is not. - HAVE_NATIVE_UNWIND is now used consistently and by itself for all relevant conditions, including when defining the presence and use of the "stackwalk" feature. - The patch inlines and removes is_native_unwinding_avail(). Note that MOZ_PROFILING must be defined for HAVE_NATIVE_UNWIND to be true on Windows and Mac, but not on Linux and Android. --HG-- extra : rebase_source : 5be3e5fe65706a15179a2cf46ba9451f68fff815 --- tools/profiler/core/platform.cpp | 33 ++++++++++++++------------------ tools/profiler/core/platform.h | 18 ----------------- 2 files changed, 14 insertions(+), 37 deletions(-) diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp index d5d05381ef1c..47d24eebe57d 100644 --- a/tools/profiler/core/platform.cpp +++ b/tools/profiler/core/platform.cpp @@ -53,16 +53,19 @@ #if defined(MOZ_PROFILING) && \ (defined(GP_OS_windows) || defined(GP_OS_darwin)) +# define HAVE_NATIVE_UNWIND # define USE_NS_STACKWALK #endif // This should also work on ARM Linux, but not tested there yet. #if defined(GP_PLAT_arm_android) +# define HAVE_NATIVE_UNWIND # define USE_EHABI_STACKWALK # include "EHABIStackWalk.h" #endif #if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux) +# define HAVE_NATIVE_UNWIND # define USE_LUL_STACKWALK # include "lul/LulMain.h" # include "lul/platform-linux-lul.h" @@ -972,16 +975,14 @@ Tick(PS::LockRef aLock, ProfileBuffer* aBuffer, TickSample* aSample) NotNull stack = threadInfo.Stack(); -#if defined(USE_NS_STACKWALK) || defined(USE_EHABI_STACKWALK) || \ - defined(USE_LUL_STACKWALK) +#if defined(HAVE_NATIVE_UNWIND) if (gPS->FeatureStackWalk(aLock)) { DoNativeBacktrace(aLock, aBuffer, aSample); - } else { + } else +#endif + { DoSampleStackTrace(aLock, aBuffer, aSample); } -#else - DoSampleStackTrace(aLock, aBuffer, aSample); -#endif // Don't process the PeudoStack's markers if we're synchronously sampling the // current thread. @@ -1461,16 +1462,6 @@ set_profiler_entries(PS::LockRef aLock, const char* aEntries) return true; } -static bool -is_native_unwinding_avail() -{ -# if defined(HAVE_NATIVE_UNWIND) - return true; -#else - return false; -#endif -} - static void profiler_usage(int aExitCode) { @@ -1508,7 +1499,11 @@ profiler_usage(int aExitCode) "\n" " This platform %s native unwinding.\n" "\n", - is_native_unwinding_avail() ? "supports" : "does not support\n" +#if defined(HAVE_NATIVE_UNWIND) + "supports" +#else + "does not support" +#endif ); exit(aExitCode); @@ -2295,7 +2290,7 @@ profiler_get_features() MOZ_RELEASE_ASSERT(gPS); static const char* features[] = { -#if defined(MOZ_PROFILING) && defined(HAVE_NATIVE_UNWIND) +#if defined(HAVE_NATIVE_UNWIND) // Walk the C++ stack. "stackwalk", #endif @@ -2954,7 +2949,7 @@ profiler_get_backtrace() TickSample sample(threadInfo); sample.mIsSamplingCurrentThread = true; -#if defined(HAVE_NATIVE_UNWIND) || defined(USE_LUL_STACKWALK) +#if defined(HAVE_NATIVE_UNWIND) #if defined(GP_OS_windows) || defined(GP_OS_linux) || defined(GP_OS_android) tick_context_t context; sample.PopulateContext(&context); diff --git a/tools/profiler/core/platform.h b/tools/profiler/core/platform.h index 6f3c6976d482..d89f378634b3 100644 --- a/tools/profiler/core/platform.h +++ b/tools/profiler/core/platform.h @@ -111,24 +111,6 @@ public: static tid_t GetCurrentId(); }; -// ---------------------------------------------------------------------------- -// HAVE_NATIVE_UNWIND -// -// Pseudo backtraces are available on all platforms. Native -// backtraces are available only on selected platforms. Breakpad is -// the only supported native unwinder. HAVE_NATIVE_UNWIND is set at -// build time to indicate whether native unwinding is possible on this -// platform. - -#undef HAVE_NATIVE_UNWIND -#if defined(MOZ_PROFILING) && \ - (defined(GP_OS_windows) || \ - defined(GP_OS_darwin) || \ - defined(GP_OS_linux) || \ - defined(GP_PLAT_arm_android)) -# define HAVE_NATIVE_UNWIND -#endif - // ---------------------------------------------------------------------------- // ProfilerState auxiliaries From 77f7d59908b996c837218594745f855cbfb3c4c6 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Fri, 11 Nov 2016 14:35:51 -0800 Subject: [PATCH 18/22] Bug 1283611 - Add support for NDK r13's libc++ paths. r=froydnj The inner directory in these projects was removed in r13. MozReview-Commit-ID: AxWgxXyOKJ4 --HG-- extra : rebase_source : 1290e8c709930f28f80bc201d7e72b53b8063634 --- build/autoconf/android.m4 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/build/autoconf/android.m4 b/build/autoconf/android.m4 index 4ab6d5a821b1..8a8e97b65252 100644 --- a/build/autoconf/android.m4 +++ b/build/autoconf/android.m4 @@ -101,6 +101,22 @@ if test "$OS_TARGET" = "Android"; then AC_MSG_ERROR([Couldn't find path to llvm-libc++ in the android ndk]) fi + if ! test -e "$cxx_include"; then + # NDK r13 removes the inner "libcxx" directory. + cxx_include="$cxx_base/include" + if ! test -e "$cxx_include"; then + AC_MSG_ERROR([Couldn't find path to libc++ includes in the android ndk]) + fi + fi + + if ! test -e "$cxxabi_include"; then + # NDK r13 removes the inner "libcxxabi" directory. + cxxabi_include="$cxxabi_base/include" + if ! test -e "$cxxabi_include"; then + AC_MSG_ERROR([Couldn't find path to libc++abi includes in the android ndk]) + fi + fi + STLPORT_LIBS="-L$cxx_libs -lc++_static" # NDK r12 split the libc++ runtime libraries into pieces. for lib in c++abi unwind android_support; do From dc58093a7b14fef14ed147870b3f8cbbb5ca2233 Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Mon, 27 Mar 2017 12:11:51 +0900 Subject: [PATCH 19/22] Bug 1283611 - Change order of include path to support NDK r13+ r=froydnj When using NDK r13+ with part 1, the following build error still occurs when using cmath. 0:21.01 /mozilla/android-ndk-r14b/sources/cxx-stl/llvm-libc++/include/math.h:661:105: error: 'acosl' was not declared in this scope 0:21.01 inline _LIBCPP_INLINE_VISIBILITY long double acos(long double __lcpp_x) _NOEXCEPT {return acosl(__lcpp_x);} To fix this, we need change the order of include path. MozReview-Commit-ID: AZ3ebx3pAil --HG-- extra : rebase_source : ca3ef90372a9c2b84f4a9bed3581be0f21e17d77 --- build/autoconf/android.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/autoconf/android.m4 b/build/autoconf/android.m4 index 8a8e97b65252..da629b4dd8bf 100644 --- a/build/autoconf/android.m4 +++ b/build/autoconf/android.m4 @@ -127,7 +127,7 @@ if test "$OS_TARGET" = "Android"; then # Add android/support/include/ for prototyping long double math # functions, locale-specific C library functions, multibyte support, # etc. - STLPORT_CPPFLAGS="-I$android_ndk/sources/android/support/include -I$cxx_include -I$cxxabi_include" + STLPORT_CPPFLAGS="-I$cxx_include -I$android_ndk/sources/android/support/include -I$cxxabi_include" ;; *) AC_MSG_ERROR([Bad value for --enable-android-cxx-stl]) From 220a8666bfff23b8098279c699626500f14d5cab Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Mon, 27 Mar 2017 21:33:53 -0400 Subject: [PATCH 20/22] Bug 1350794 - Avoid dereferencing aProvider when null in DataTextureSourceD3D11 constructor - Require bug 1350247 patch to land first to fix WebVR crash MozReview-Commit-ID: fEsjE22mPc --- gfx/layers/d3d11/TextureD3D11.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 345372370eb0..b38d95b6e9c6 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -809,7 +809,11 @@ DXGITextureHostD3D11::LockInternal() return false; } - mTextureSource = new DataTextureSourceD3D11(mFormat, mProvider, mTexture); + if (mProvider) { + mTextureSource = new DataTextureSourceD3D11(mFormat, mProvider, mTexture); + } else { + mTextureSource = new DataTextureSourceD3D11(mDevice, mFormat, mTexture); + } } mIsLocked = LockD3DTexture(mTextureSource->GetD3D11Texture()); From 911f9a9b92f5781b47e716a7e6b3b0934fc27ca2 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Sun, 26 Mar 2017 20:12:34 -0400 Subject: [PATCH 21/22] Bug 1350765 - Avoid recomputing the histogram ID when it's available in the caller; r=chutten --- .../telemetry/TelemetryHistogram.cpp | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/toolkit/components/telemetry/TelemetryHistogram.cpp b/toolkit/components/telemetry/TelemetryHistogram.cpp index 4f9dd4ed7bb9..8736c2eb234c 100644 --- a/toolkit/components/telemetry/TelemetryHistogram.cpp +++ b/toolkit/components/telemetry/TelemetryHistogram.cpp @@ -591,12 +591,10 @@ GetProcessFromName(const std::string& aString) } Histogram* -internal_GetSubsessionHistogram(Histogram& existing) +internal_GetSubsessionHistogram(mozilla::Telemetry::HistogramID id, + Histogram& existing) { - mozilla::Telemetry::HistogramID id; - nsresult rv - = internal_GetHistogramEnumId(existing.histogram_name().c_str(), &id); - if (NS_FAILED(rv) || gHistograms[id].keyed) { + if (gHistograms[id].keyed) { return nullptr; } @@ -639,10 +637,23 @@ internal_GetSubsessionHistogram(Histogram& existing) cache[id] = clone; return clone; } + +Histogram* +internal_GetSubsessionHistogram(Histogram& existing) +{ + mozilla::Telemetry::HistogramID id; + nsresult rv + = internal_GetHistogramEnumId(existing.histogram_name().c_str(), &id); + if (NS_FAILED(rv)) { + return nullptr; + } + return internal_GetSubsessionHistogram(id, existing); +} #endif nsresult -internal_HistogramAdd(Histogram& histogram, int32_t value, uint32_t dataset) +internal_HistogramAdd(mozilla::Telemetry::HistogramID id, + Histogram& histogram, int32_t value, uint32_t dataset) { // Check if we are allowed to record the data. bool canRecordDataset = CanRecordDataset(dataset, @@ -653,7 +664,7 @@ internal_HistogramAdd(Histogram& histogram, int32_t value, uint32_t dataset) } #if !defined(MOZ_WIDGET_ANDROID) - if (Histogram* subsession = internal_GetSubsessionHistogram(histogram)) { + if (Histogram* subsession = internal_GetSubsessionHistogram(id, histogram)) { subsession->Add(value); } #endif @@ -666,24 +677,17 @@ internal_HistogramAdd(Histogram& histogram, int32_t value, uint32_t dataset) } nsresult -internal_HistogramAdd(Histogram& histogram, int32_t value) +internal_HistogramAdd(mozilla::Telemetry::HistogramID id, + Histogram& histogram, int32_t value) { uint32_t dataset = nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN; // We only really care about the dataset of the histogram if we are not recording // extended telemetry. Otherwise, we always record histogram data. if (!internal_CanRecordExtended()) { - mozilla::Telemetry::HistogramID id; - nsresult rv - = internal_GetHistogramEnumId(histogram.histogram_name().c_str(), &id); - if (NS_FAILED(rv)) { - // If we can't look up the dataset, it might be because the histogram was added - // at runtime. Since we're not recording extended telemetry, bail out. - return NS_OK; - } dataset = gHistograms[id].dataset; } - return internal_HistogramAdd(histogram, value, dataset); + return internal_HistogramAdd(id, histogram, value, dataset); } void @@ -1323,7 +1327,7 @@ void internal_Accumulate(mozilla::Telemetry::HistogramID aHistogram, uint32_t aS Histogram *h; nsresult rv = internal_GetHistogramByEnumId(aHistogram, &h, GeckoProcessType_Default); if (NS_SUCCEEDED(rv)) { - internal_HistogramAdd(*h, aSample, gHistograms[aHistogram].dataset); + internal_HistogramAdd(aHistogram, *h, aSample, gHistograms[aHistogram].dataset); } } @@ -1345,14 +1349,14 @@ internal_Accumulate(mozilla::Telemetry::HistogramID aID, void internal_Accumulate(Histogram& aHistogram, uint32_t aSample) { - if (XRE_IsParentProcess()) { - internal_HistogramAdd(aHistogram, aSample); - return; - } - mozilla::Telemetry::HistogramID id; nsresult rv = internal_GetHistogramEnumId(aHistogram.histogram_name().c_str(), &id); if (NS_SUCCEEDED(rv)) { + if (XRE_IsParentProcess()) { + internal_HistogramAdd(id, aHistogram, aSample); + return; + } + internal_RemoteAccumulate(id, aSample); } } @@ -1381,7 +1385,7 @@ internal_AccumulateChild(GeckoProcessType aProcessType, mozilla::Telemetry::Hist Histogram* h; nsresult rv = internal_GetHistogramByEnumId(aId, &h, aProcessType); if (NS_SUCCEEDED(rv)) { - internal_HistogramAdd(*h, aSample, gHistograms[aId].dataset); + internal_HistogramAdd(aId, *h, aSample, gHistograms[aId].dataset); } else { NS_WARNING("NS_FAILED GetHistogramByEnumId for CHILD"); } From 90cfaab28daef40ae4ada759f80d95d1f51291a9 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Mon, 27 Mar 2017 20:03:32 -0700 Subject: [PATCH 22/22] Backed out changeset 9b21aa70d85f (bug 1350765) for failures in test_TelemetryHistograms.js and test_TelemetrySession.js CLOSED TREE --- .../telemetry/TelemetryHistogram.cpp | 52 +++++++++---------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/toolkit/components/telemetry/TelemetryHistogram.cpp b/toolkit/components/telemetry/TelemetryHistogram.cpp index 8736c2eb234c..4f9dd4ed7bb9 100644 --- a/toolkit/components/telemetry/TelemetryHistogram.cpp +++ b/toolkit/components/telemetry/TelemetryHistogram.cpp @@ -591,10 +591,12 @@ GetProcessFromName(const std::string& aString) } Histogram* -internal_GetSubsessionHistogram(mozilla::Telemetry::HistogramID id, - Histogram& existing) +internal_GetSubsessionHistogram(Histogram& existing) { - if (gHistograms[id].keyed) { + mozilla::Telemetry::HistogramID id; + nsresult rv + = internal_GetHistogramEnumId(existing.histogram_name().c_str(), &id); + if (NS_FAILED(rv) || gHistograms[id].keyed) { return nullptr; } @@ -637,23 +639,10 @@ internal_GetSubsessionHistogram(mozilla::Telemetry::HistogramID id, cache[id] = clone; return clone; } - -Histogram* -internal_GetSubsessionHistogram(Histogram& existing) -{ - mozilla::Telemetry::HistogramID id; - nsresult rv - = internal_GetHistogramEnumId(existing.histogram_name().c_str(), &id); - if (NS_FAILED(rv)) { - return nullptr; - } - return internal_GetSubsessionHistogram(id, existing); -} #endif nsresult -internal_HistogramAdd(mozilla::Telemetry::HistogramID id, - Histogram& histogram, int32_t value, uint32_t dataset) +internal_HistogramAdd(Histogram& histogram, int32_t value, uint32_t dataset) { // Check if we are allowed to record the data. bool canRecordDataset = CanRecordDataset(dataset, @@ -664,7 +653,7 @@ internal_HistogramAdd(mozilla::Telemetry::HistogramID id, } #if !defined(MOZ_WIDGET_ANDROID) - if (Histogram* subsession = internal_GetSubsessionHistogram(id, histogram)) { + if (Histogram* subsession = internal_GetSubsessionHistogram(histogram)) { subsession->Add(value); } #endif @@ -677,17 +666,24 @@ internal_HistogramAdd(mozilla::Telemetry::HistogramID id, } nsresult -internal_HistogramAdd(mozilla::Telemetry::HistogramID id, - Histogram& histogram, int32_t value) +internal_HistogramAdd(Histogram& histogram, int32_t value) { uint32_t dataset = nsITelemetry::DATASET_RELEASE_CHANNEL_OPTIN; // We only really care about the dataset of the histogram if we are not recording // extended telemetry. Otherwise, we always record histogram data. if (!internal_CanRecordExtended()) { + mozilla::Telemetry::HistogramID id; + nsresult rv + = internal_GetHistogramEnumId(histogram.histogram_name().c_str(), &id); + if (NS_FAILED(rv)) { + // If we can't look up the dataset, it might be because the histogram was added + // at runtime. Since we're not recording extended telemetry, bail out. + return NS_OK; + } dataset = gHistograms[id].dataset; } - return internal_HistogramAdd(id, histogram, value, dataset); + return internal_HistogramAdd(histogram, value, dataset); } void @@ -1327,7 +1323,7 @@ void internal_Accumulate(mozilla::Telemetry::HistogramID aHistogram, uint32_t aS Histogram *h; nsresult rv = internal_GetHistogramByEnumId(aHistogram, &h, GeckoProcessType_Default); if (NS_SUCCEEDED(rv)) { - internal_HistogramAdd(aHistogram, *h, aSample, gHistograms[aHistogram].dataset); + internal_HistogramAdd(*h, aSample, gHistograms[aHistogram].dataset); } } @@ -1349,14 +1345,14 @@ internal_Accumulate(mozilla::Telemetry::HistogramID aID, void internal_Accumulate(Histogram& aHistogram, uint32_t aSample) { + if (XRE_IsParentProcess()) { + internal_HistogramAdd(aHistogram, aSample); + return; + } + mozilla::Telemetry::HistogramID id; nsresult rv = internal_GetHistogramEnumId(aHistogram.histogram_name().c_str(), &id); if (NS_SUCCEEDED(rv)) { - if (XRE_IsParentProcess()) { - internal_HistogramAdd(id, aHistogram, aSample); - return; - } - internal_RemoteAccumulate(id, aSample); } } @@ -1385,7 +1381,7 @@ internal_AccumulateChild(GeckoProcessType aProcessType, mozilla::Telemetry::Hist Histogram* h; nsresult rv = internal_GetHistogramByEnumId(aId, &h, aProcessType); if (NS_SUCCEEDED(rv)) { - internal_HistogramAdd(aId, *h, aSample, gHistograms[aId].dataset); + internal_HistogramAdd(*h, aSample, gHistograms[aId].dataset); } else { NS_WARNING("NS_FAILED GetHistogramByEnumId for CHILD"); }