mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-05 00:25:27 +00:00
a886770a11
Destroying large arrays of css::Rules during page teardown can take multiple milliseconds in incremental CC. To reduce CC pauses, this patch introduces a new class nsIncrementalClearCOMRuleArray that uses the deferred finalizer to incrementally destroy these rule arrays.
81 lines
2.3 KiB
C++
81 lines
2.3 KiB
C++
/* -*- 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/. */
|
|
|
|
#include "mozilla/IncrementalClearCOMRuleArray.h"
|
|
|
|
#include "nsCycleCollector.h"
|
|
#include "mozilla/DeferredFinalize.h"
|
|
#include "nsTArray.h"
|
|
#include "nsCCUncollectableMarker.h"
|
|
|
|
using namespace mozilla;
|
|
|
|
typedef nsCOMArray<css::Rule> RuleArray;
|
|
typedef nsTArray<RuleArray> RuleArrayArray;
|
|
|
|
|
|
// These methods are based on those in DeferredFinalizerImpl.
|
|
|
|
static void*
|
|
AppendRulesArrayPointer(void* aData, void* aObject)
|
|
{
|
|
RuleArrayArray* rulesArray = static_cast<RuleArrayArray*>(aData);
|
|
RuleArray* oldRules = static_cast<RuleArray*>(aObject);
|
|
|
|
if (!rulesArray) {
|
|
rulesArray = new RuleArrayArray();
|
|
}
|
|
|
|
RuleArray* newRules = rulesArray->AppendElement();
|
|
newRules->SwapElements(*oldRules);
|
|
|
|
return rulesArray;
|
|
}
|
|
|
|
// Remove up to |aSliceBudget| css::Rules from the arrays, starting at
|
|
// the end of the last array.
|
|
static bool
|
|
DeferredFinalizeRulesArray(uint32_t aSliceBudget, void* aData)
|
|
{
|
|
MOZ_ASSERT(aSliceBudget > 0, "nonsensical/useless call with aSliceBudget == 0");
|
|
RuleArrayArray* rulesArray = static_cast<RuleArrayArray*>(aData);
|
|
|
|
size_t newOuterLen = rulesArray->Length();
|
|
|
|
while (aSliceBudget > 0 && newOuterLen > 0) {
|
|
RuleArray& lastArray = rulesArray->ElementAt(newOuterLen - 1);
|
|
uint32_t innerLen = lastArray.Length();
|
|
uint32_t currSlice = std::min(innerLen, aSliceBudget);
|
|
uint32_t newInnerLen = innerLen - currSlice;
|
|
lastArray.TruncateLength(newInnerLen);
|
|
aSliceBudget -= currSlice;
|
|
if (newInnerLen == 0) {
|
|
newOuterLen -= 1;
|
|
}
|
|
}
|
|
|
|
rulesArray->TruncateLength(newOuterLen);
|
|
|
|
if (newOuterLen == 0) {
|
|
delete rulesArray;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void
|
|
IncrementalClearCOMRuleArray::Clear()
|
|
{
|
|
// Destroy the array incrementally if it is long and we
|
|
// haven't started shutting down.
|
|
if (Length() > 10 && nsCCUncollectableMarker::sGeneration) {
|
|
DeferredFinalize(AppendRulesArrayPointer, DeferredFinalizeRulesArray, this);
|
|
} else {
|
|
nsCOMArray<css::Rule>::Clear();
|
|
}
|
|
MOZ_ASSERT(Length() == 0);
|
|
}
|