зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1685677 - Don't unnecessarily materialize a flattened array of OriginInfo*. r=dom-workers-and-storage-reviewers,janv
Differential Revision: https://phabricator.services.mozilla.com/D101151
This commit is contained in:
Родитель
991f534d51
Коммит
b9443d148e
|
@ -7,6 +7,7 @@
|
|||
#include "ActorsParent.h"
|
||||
|
||||
// Local includes
|
||||
#include "Flatten.h"
|
||||
#include "InitializationTypes.h"
|
||||
#include "OriginScope.h"
|
||||
#include "QuotaCommon.h"
|
||||
|
@ -7115,11 +7116,11 @@ QuotaManager::CollectLRUOriginInfosUntil(Collect&& aCollect, Pred&& aPred) {
|
|||
return originInfos;
|
||||
}
|
||||
|
||||
QuotaManager::OriginInfosFlatTraversable
|
||||
QuotaManager::OriginInfosNestedTraversable
|
||||
QuotaManager::LockedGetOriginInfosExceedingGroupLimit() const {
|
||||
mQuotaMutex.AssertCurrentThreadOwns();
|
||||
|
||||
OriginInfosFlatTraversable originInfos;
|
||||
OriginInfosNestedTraversable originInfos;
|
||||
|
||||
for (const auto& entry : mGroupInfoPairs) {
|
||||
const auto& pair = entry.GetData();
|
||||
|
@ -7146,9 +7147,7 @@ QuotaManager::LockedGetOriginInfosExceedingGroupLimit() const {
|
|||
MOZ_ASSERT(quotaManager, "Shouldn't be null!");
|
||||
|
||||
if (groupUsage > quotaManager->GetGroupLimit()) {
|
||||
// XXX Instead of appending into a flat array, return an array of
|
||||
// arrays.
|
||||
originInfos.AppendElements(CollectLRUOriginInfosUntil(
|
||||
originInfos.AppendElement(CollectLRUOriginInfosUntil(
|
||||
[&temporaryGroupInfo, &defaultGroupInfo](auto inserter) {
|
||||
MaybeInsertOriginInfos(std::move(inserter), temporaryGroupInfo,
|
||||
defaultGroupInfo,
|
||||
|
@ -7170,7 +7169,7 @@ QuotaManager::LockedGetOriginInfosExceedingGroupLimit() const {
|
|||
|
||||
QuotaManager::OriginInfosFlatTraversable
|
||||
QuotaManager::LockedGetOriginInfosExceedingGlobalLimit(
|
||||
const OriginInfosFlatTraversable& aAlreadyDoomedOriginInfos,
|
||||
const OriginInfosNestedTraversable& aAlreadyDoomedOriginInfos,
|
||||
const uint64_t aAlreadyDoomedUsage) const {
|
||||
mQuotaMutex.AssertCurrentThreadOwns();
|
||||
|
||||
|
@ -7186,7 +7185,13 @@ QuotaManager::LockedGetOriginInfosExceedingGlobalLimit(
|
|||
inserter, pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY),
|
||||
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT),
|
||||
[&aAlreadyDoomedOriginInfos](const auto& originInfo) {
|
||||
return !aAlreadyDoomedOriginInfos.Contains(originInfo) &&
|
||||
return !std::any_of(aAlreadyDoomedOriginInfos.cbegin(),
|
||||
aAlreadyDoomedOriginInfos.cend(),
|
||||
// XXX This should capture originInfo by
|
||||
// value, but it can't due to Bug 1421435.
|
||||
[&originInfo](const auto& array) {
|
||||
return array.Contains(originInfo);
|
||||
}) &&
|
||||
!originInfo->LockedPersisted();
|
||||
});
|
||||
}
|
||||
|
@ -7203,24 +7208,28 @@ QuotaManager::LockedGetOriginInfosExceedingGlobalLimit(
|
|||
});
|
||||
}
|
||||
|
||||
QuotaManager::OriginInfosFlatTraversable
|
||||
QuotaManager::OriginInfosNestedTraversable
|
||||
QuotaManager::GetOriginInfosExceedingLimits() const {
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
|
||||
auto originInfos = LockedGetOriginInfosExceedingGroupLimit();
|
||||
|
||||
const uint64_t doomedUsage =
|
||||
std::accumulate(originInfos.cbegin(), originInfos.cend(), uint64_t(0),
|
||||
[](uint64_t oldValue, const auto& originInfo) {
|
||||
return oldValue + originInfo->LockedUsage();
|
||||
});
|
||||
const uint64_t doomedUsage = std::accumulate(
|
||||
originInfos.cbegin(), originInfos.cend(), uint64_t(0),
|
||||
[](uint64_t oldValue, const auto& currentOriginInfos) {
|
||||
return std::accumulate(currentOriginInfos.cbegin(),
|
||||
currentOriginInfos.cend(), oldValue,
|
||||
[](uint64_t oldValue, const auto& originInfo) {
|
||||
return oldValue + originInfo->LockedUsage();
|
||||
});
|
||||
});
|
||||
|
||||
// Evicting origins that exceed their group limit also affects the global
|
||||
// temporary storage usage. If the global temporary storage limit would still
|
||||
// be exceeded after evicting the origins that were already selected, we need
|
||||
// to specifically evict origins to get below the global limit.
|
||||
if (mTemporaryStorageUsage - doomedUsage > mTemporaryStorageLimit) {
|
||||
originInfos.AppendElements(
|
||||
originInfos.AppendElement(
|
||||
LockedGetOriginInfosExceedingGlobalLimit(originInfos, doomedUsage));
|
||||
}
|
||||
|
||||
|
@ -7228,13 +7237,12 @@ QuotaManager::GetOriginInfosExceedingLimits() const {
|
|||
}
|
||||
|
||||
void QuotaManager::ClearOrigins(
|
||||
const OriginInfosFlatTraversable& aDoomedOriginInfos) {
|
||||
const OriginInfosNestedTraversable& aDoomedOriginInfos) {
|
||||
AssertIsOnIOThread();
|
||||
|
||||
// XXX Does this need to be done a) in order and/or b) sequentially?
|
||||
// XXX We don't need to concatenate the results of the two steps. It would be
|
||||
// sufficient to chain the ranges for iteration.
|
||||
for (const auto& doomedOriginInfo : aDoomedOriginInfos) {
|
||||
for (const auto& doomedOriginInfo :
|
||||
Flatten<OriginInfosFlatTraversable::elem_type>(aDoomedOriginInfos)) {
|
||||
#ifdef DEBUG
|
||||
{
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
|
@ -7249,14 +7257,16 @@ void QuotaManager::ClearOrigins(
|
|||
{
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
|
||||
for (const auto& doomedOriginInfo : aDoomedOriginInfos) {
|
||||
for (const auto& doomedOriginInfo :
|
||||
Flatten<OriginInfosFlatTraversable::elem_type>(aDoomedOriginInfos)) {
|
||||
LockedRemoveQuotaForOrigin(
|
||||
doomedOriginInfo->mGroupInfo->mPersistenceType,
|
||||
{doomedOriginInfo->mGroupInfo->mGroup, doomedOriginInfo->mOrigin});
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& doomedOriginInfo : aDoomedOriginInfos) {
|
||||
for (const auto& doomedOriginInfo :
|
||||
Flatten<OriginInfosFlatTraversable::elem_type>(aDoomedOriginInfos)) {
|
||||
OriginClearCompleted(doomedOriginInfo->mGroupInfo->mPersistenceType,
|
||||
doomedOriginInfo->mOrigin, Nullable<Client::Type>());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DOM_QUOTA_FLATTEN_H_
|
||||
#define DOM_QUOTA_FLATTEN_H_
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
// XXX This should be moved to MFBT.
|
||||
|
||||
namespace mozilla::dom::quota {
|
||||
|
||||
namespace detail {
|
||||
|
||||
using std::begin;
|
||||
using std::end;
|
||||
|
||||
template <typename T, typename NestedRange>
|
||||
auto Flatten(const NestedRange& aRange) -> std::enable_if_t<
|
||||
std::is_same_v<T, typename decltype(begin(
|
||||
std::declval<const NestedRange&>()))::value_type>,
|
||||
const NestedRange&> {
|
||||
return aRange;
|
||||
}
|
||||
|
||||
template <typename T, typename NestedRange>
|
||||
struct FlatIter {
|
||||
using OuterIterator = decltype(begin(std::declval<const NestedRange&>()));
|
||||
using InnerIterator =
|
||||
decltype(begin(*begin(std::declval<const NestedRange&>())));
|
||||
|
||||
explicit FlatIter(const NestedRange& aRange, OuterIterator aIter)
|
||||
: mOuterIter{std::move(aIter)}, mOuterEnd{end(aRange)} {
|
||||
InitInner();
|
||||
}
|
||||
|
||||
const T& operator*() const { return *mInnerIter; }
|
||||
|
||||
FlatIter& operator++() {
|
||||
if (mInnerIter != mInnerEnd) {
|
||||
++mInnerIter;
|
||||
} else {
|
||||
++mOuterIter;
|
||||
InitInner();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator!=(const FlatIter& aOther) const {
|
||||
return mOuterIter != aOther.mOuterIter || mInnerIter != aOther.mInnerIter;
|
||||
}
|
||||
|
||||
private:
|
||||
void InitInner() {
|
||||
if (mOuterIter != mOuterEnd) {
|
||||
const auto& innerRange = *mOuterIter;
|
||||
|
||||
mInnerIter = begin(innerRange);
|
||||
mInnerEnd = end(innerRange);
|
||||
}
|
||||
}
|
||||
|
||||
OuterIterator mOuterIter;
|
||||
const OuterIterator mOuterEnd;
|
||||
|
||||
InnerIterator mInnerIter;
|
||||
InnerIterator mInnerEnd;
|
||||
};
|
||||
|
||||
template <typename T, typename NestedRange>
|
||||
struct FlatRange {
|
||||
explicit FlatRange(const NestedRange& aRange) : mRange{aRange} {}
|
||||
|
||||
auto begin() const {
|
||||
using std::begin;
|
||||
return FlatIter<T, NestedRange>{mRange, begin(mRange)};
|
||||
}
|
||||
auto end() const {
|
||||
using std::end;
|
||||
return FlatIter<T, NestedRange>{mRange, end(mRange)};
|
||||
}
|
||||
|
||||
private:
|
||||
const NestedRange& mRange;
|
||||
};
|
||||
|
||||
template <typename T, typename NestedRange>
|
||||
auto Flatten(const NestedRange& aRange) -> std::enable_if_t<
|
||||
!std::is_same_v<T, typename decltype(begin(
|
||||
std::declval<const NestedRange&>()))::value_type>,
|
||||
FlatRange<T, NestedRange>> {
|
||||
return FlatRange<T, NestedRange>{aRange};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T, typename NestedRange>
|
||||
auto Flatten(const NestedRange& aRange) {
|
||||
return detail::Flatten<T>(aRange);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom::quota
|
||||
|
||||
#endif
|
|
@ -563,15 +563,18 @@ class QuotaManager final : public BackgroundThreadObject {
|
|||
using OriginInfosFlatTraversable =
|
||||
nsTArray<NotNull<RefPtr<const OriginInfo>>>;
|
||||
|
||||
OriginInfosFlatTraversable LockedGetOriginInfosExceedingGroupLimit() const;
|
||||
using OriginInfosNestedTraversable =
|
||||
nsTArray<nsTArray<NotNull<RefPtr<const OriginInfo>>>>;
|
||||
|
||||
OriginInfosNestedTraversable LockedGetOriginInfosExceedingGroupLimit() const;
|
||||
|
||||
OriginInfosFlatTraversable LockedGetOriginInfosExceedingGlobalLimit(
|
||||
const OriginInfosFlatTraversable& aAlreadyDoomedOriginInfos,
|
||||
const OriginInfosNestedTraversable& aAlreadyDoomedOriginInfos,
|
||||
uint64_t aAlreadyDoomedUsage) const;
|
||||
|
||||
OriginInfosFlatTraversable GetOriginInfosExceedingLimits() const;
|
||||
OriginInfosNestedTraversable GetOriginInfosExceedingLimits() const;
|
||||
|
||||
void ClearOrigins(const OriginInfosFlatTraversable& aDoomedOriginInfos);
|
||||
void ClearOrigins(const OriginInfosNestedTraversable& aDoomedOriginInfos);
|
||||
|
||||
void CleanupTemporaryStorage();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче