Bug 1750790 - Use a linked list to hold unprocessed loading events. r=mhowell

Bug 1750791 changed the data strucutre of processed loading events to a linked
list.  This patch does the same for unprocessed loading events.

Differential Revision: https://phabricator.services.mozilla.com/D140584
This commit is contained in:
Toshihito Kikuchi 2022-03-09 21:41:19 +00:00
parent 42e4421792
commit 05cc5ccd6d
2 changed files with 41 additions and 39 deletions

View file

@ -311,7 +311,8 @@ void UntrustedModulesProcessor::Enqueue(
MutexAutoLock lock(mUnprocessedMutex); MutexAutoLock lock(mUnprocessedMutex);
Unused << mUnprocessedModuleLoads.emplaceBack(std::move(aModLoadInfo)); mUnprocessedModuleLoads.insertBack(
new UnprocessedModuleLoadInfoContainer(std::move(aModLoadInfo)));
ScheduleNonEmptyQueueProcessing(lock); ScheduleNonEmptyQueueProcessing(lock);
} }
@ -327,7 +328,8 @@ void UntrustedModulesProcessor::Enqueue(ModuleLoadInfoVec&& aEvents) {
MutexAutoLock lock(mUnprocessedMutex); MutexAutoLock lock(mUnprocessedMutex);
for (auto& event : aEvents) { for (auto& event : aEvents) {
Unused << mUnprocessedModuleLoads.emplaceBack(std::move(event)); mUnprocessedModuleLoads.insertBack(
new UnprocessedModuleLoadInfoContainer(std::move(event)));
} }
ScheduleNonEmptyQueueProcessing(lock); ScheduleNonEmptyQueueProcessing(lock);
@ -580,33 +582,14 @@ void UntrustedModulesProcessor::BackgroundProcessModuleLoadQueueChildProcess() {
MOZ_ASSERT(NS_SUCCEEDED(rv)); MOZ_ASSERT(NS_SUCCEEDED(rv));
} }
UntrustedModulesProcessor::LoadsVec UnprocessedModuleLoads UntrustedModulesProcessor::ExtractLoadingEventsToProcess(
UntrustedModulesProcessor::ExtractLoadingEventsToProcess(size_t aMaxLength) { size_t aMaxLength) {
LoadsVec loadsToProcess; UnprocessedModuleLoads loadsToProcess;
MutexAutoLock lock(mUnprocessedMutex); MutexAutoLock lock(mUnprocessedMutex);
CancelScheduledProcessing(lock); CancelScheduledProcessing(lock);
// The potential size of mProcessedModuleLoads if all of the unprocessed loadsToProcess.splice(0, mUnprocessedModuleLoads, 0, aMaxLength);
// events are from third-party modules.
const size_t newDataLength =
mProcessedModuleLoads.mNumEvents + mUnprocessedModuleLoads.length();
if (newDataLength <= aMaxLength) {
loadsToProcess.swap(mUnprocessedModuleLoads);
} else {
// To prevent mProcessedModuleLoads from exceeding |aMaxLength|,
// we process the first items in the mUnprocessedModuleLoads,
// leaving the the remaining events for the next time.
const size_t capacity =
aMaxLength > mProcessedModuleLoads.mNumEvents
? (aMaxLength - mProcessedModuleLoads.mNumEvents)
: 0;
auto moveRangeBegin = mUnprocessedModuleLoads.begin();
auto moveRangeEnd = moveRangeBegin + capacity;
Unused << loadsToProcess.moveAppend(moveRangeBegin, moveRangeEnd);
mUnprocessedModuleLoads.erase(moveRangeBegin, moveRangeEnd);
}
return loadsToProcess; return loadsToProcess;
} }
@ -620,9 +603,9 @@ void UntrustedModulesProcessor::ProcessModuleLoadQueue() {
return; return;
} }
LoadsVec loadsToProcess = UnprocessedModuleLoads loadsToProcess =
ExtractLoadingEventsToProcess(UntrustedModulesData::kMaxEvents); ExtractLoadingEventsToProcess(UntrustedModulesData::kMaxEvents);
if (!IsReadyForBackgroundProcessing() || loadsToProcess.empty()) { if (!IsReadyForBackgroundProcessing() || loadsToProcess.isEmpty()) {
return; return;
} }
@ -639,7 +622,9 @@ void UntrustedModulesProcessor::ProcessModuleLoadQueue() {
uint32_t sanitizationFailures = 0; uint32_t sanitizationFailures = 0;
uint32_t trustTestFailures = 0; uint32_t trustTestFailures = 0;
for (glue::EnhancedModuleLoadInfo& entry : loadsToProcess) { for (UnprocessedModuleLoadInfoContainer* container : loadsToProcess) {
glue::EnhancedModuleLoadInfo& entry = container->mInfo;
if (!IsReadyForBackgroundProcessing()) { if (!IsReadyForBackgroundProcessing()) {
return; return;
} }
@ -779,9 +764,9 @@ UntrustedModulesProcessor::ProcessModuleLoadQueueChildProcess(
AssertRunningOnLazyIdleThread(); AssertRunningOnLazyIdleThread();
MOZ_ASSERT(!XRE_IsParentProcess()); MOZ_ASSERT(!XRE_IsParentProcess());
LoadsVec loadsToProcess = UnprocessedModuleLoads loadsToProcess =
ExtractLoadingEventsToProcess(UntrustedModulesData::kMaxEvents); ExtractLoadingEventsToProcess(UntrustedModulesData::kMaxEvents);
if (loadsToProcess.empty()) { if (loadsToProcess.isEmpty()) {
// Nothing to process // Nothing to process
return GetModulesTrustPromise::CreateAndResolve(Nothing(), __func__); return GetModulesTrustPromise::CreateAndResolve(Nothing(), __func__);
} }
@ -794,7 +779,9 @@ UntrustedModulesProcessor::ProcessModuleLoadQueueChildProcess(
nsTHashtable<nsStringCaseInsensitiveHashKey> moduleNtPathSet; nsTHashtable<nsStringCaseInsensitiveHashKey> moduleNtPathSet;
// Build a set of modules to be processed by the parent // Build a set of modules to be processed by the parent
for (glue::EnhancedModuleLoadInfo& entry : loadsToProcess) { for (UnprocessedModuleLoadInfoContainer* container : loadsToProcess) {
glue::EnhancedModuleLoadInfo& entry = container->mInfo;
if (!IsReadyForBackgroundProcessing()) { if (!IsReadyForBackgroundProcessing()) {
return GetModulesTrustPromise::CreateAndReject( return GetModulesTrustPromise::CreateAndReject(
NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__); NS_ERROR_ILLEGAL_DURING_SHUTDOWN, __func__);
@ -875,7 +862,7 @@ void UntrustedModulesProcessor::CompleteProcessing(
ModulesMap& modules = aModulesAndLoads.mModMapResult.ref().mModules; ModulesMap& modules = aModulesAndLoads.mModMapResult.ref().mModules;
const uint32_t& trustTestFailures = const uint32_t& trustTestFailures =
aModulesAndLoads.mModMapResult.ref().mTrustTestFailures; aModulesAndLoads.mModMapResult.ref().mTrustTestFailures;
LoadsVec& loads = aModulesAndLoads.mLoads; UnprocessedModuleLoads& loads = aModulesAndLoads.mLoads;
if (modules.IsEmpty() && !trustTestFailures) { if (modules.IsEmpty() && !trustTestFailures) {
// No data, nothing to save. // No data, nothing to save.
@ -894,7 +881,8 @@ void UntrustedModulesProcessor::CompleteProcessing(
uint32_t sanitizationFailures = 0; uint32_t sanitizationFailures = 0;
if (!modules.IsEmpty()) { if (!modules.IsEmpty()) {
for (auto&& item : loads) { for (UnprocessedModuleLoadInfoContainer* container : loads) {
glue::EnhancedModuleLoadInfo& item = container->mInfo;
if (!IsReadyForBackgroundProcessing()) { if (!IsReadyForBackgroundProcessing()) {
return; return;
} }

View file

@ -35,6 +35,22 @@ using ModulesTrustPromise = MozPromise<ModulesMapResult, nsresult, true>;
using GetModulesTrustIpcPromise = using GetModulesTrustIpcPromise =
MozPromise<Maybe<ModulesMapResult>, ipc::ResponseRejectReason, true>; MozPromise<Maybe<ModulesMapResult>, ipc::ResponseRejectReason, true>;
struct UnprocessedModuleLoadInfoContainer final
: public LinkedListElement<UnprocessedModuleLoadInfoContainer> {
glue::EnhancedModuleLoadInfo mInfo;
template <typename T>
explicit UnprocessedModuleLoadInfoContainer(T&& aInfo)
: mInfo(std::move(aInfo)) {}
UnprocessedModuleLoadInfoContainer(
const UnprocessedModuleLoadInfoContainer&) = delete;
UnprocessedModuleLoadInfoContainer& operator=(
const UnprocessedModuleLoadInfoContainer&) = delete;
};
using UnprocessedModuleLoads =
AutoCleanLinkedList<UnprocessedModuleLoadInfoContainer>;
class UntrustedModulesProcessor final : public nsIObserver { class UntrustedModulesProcessor final : public nsIObserver {
public: public:
static RefPtr<UntrustedModulesProcessor> Create( static RefPtr<UntrustedModulesProcessor> Create(
@ -84,20 +100,18 @@ class UntrustedModulesProcessor final : public nsIObserver {
void BackgroundProcessModuleLoadQueue(); void BackgroundProcessModuleLoadQueue();
void ProcessModuleLoadQueue(); void ProcessModuleLoadQueue();
using LoadsVec = Vector<glue::EnhancedModuleLoadInfo>;
// Extract the loading events from mUnprocessedModuleLoads to process and // Extract the loading events from mUnprocessedModuleLoads to process and
// move to mProcessedModuleLoads. It's guaranteed that the total length of // move to mProcessedModuleLoads. It's guaranteed that the total length of
// mProcessedModuleLoads will not exceed |aMaxLength|. // mProcessedModuleLoads will not exceed |aMaxLength|.
LoadsVec ExtractLoadingEventsToProcess(size_t aMaxLength); UnprocessedModuleLoads ExtractLoadingEventsToProcess(size_t aMaxLength);
class ModulesMapResultWithLoads final { class ModulesMapResultWithLoads final {
public: public:
ModulesMapResultWithLoads(Maybe<ModulesMapResult>&& aModMapResult, ModulesMapResultWithLoads(Maybe<ModulesMapResult>&& aModMapResult,
LoadsVec&& aLoads) UnprocessedModuleLoads&& aLoads)
: mModMapResult(std::move(aModMapResult)), mLoads(std::move(aLoads)) {} : mModMapResult(std::move(aModMapResult)), mLoads(std::move(aLoads)) {}
Maybe<ModulesMapResult> mModMapResult; Maybe<ModulesMapResult> mModMapResult;
LoadsVec mLoads; UnprocessedModuleLoads mLoads;
}; };
using GetModulesTrustPromise = using GetModulesTrustPromise =
@ -140,7 +154,7 @@ class UntrustedModulesProcessor final : public nsIObserver {
Mutex mModuleCacheMutex; Mutex mModuleCacheMutex;
// The members in this group are protected by mUnprocessedMutex // The members in this group are protected by mUnprocessedMutex
Vector<glue::EnhancedModuleLoadInfo> mUnprocessedModuleLoads; UnprocessedModuleLoads mUnprocessedModuleLoads;
nsCOMPtr<nsIRunnable> mIdleRunnable; nsCOMPtr<nsIRunnable> mIdleRunnable;
// This member must only be touched on mThread // This member must only be touched on mThread