Files
palemoon27/layout/style/RuleProcessorCache.cpp
roytam1 279b2f1b52 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1136897 - Don't evict expired entries from disk. r=michal (6af5d87e8)
- Bug 1188745 - Rename nsTArray::SizeOfExcludingThis() as ShallowSizeOfExcludingThis(). r=froydnj. (3dbb2875a)
- Bug 1150810 part 1 - Move DocumentTimeline methods up to AnimationTimeline; r=jwatt (3d8c679af)
- Bug 1171817 part 1 - Cancel animations when destroying the property holding them; r=dbaron (6f28fbf46)
- Bug 1171817 part 2 - Add CSSAnimation::GetOwningElement; r=dbaron (700decca6)
- Bug 1171817 part 3 - Add CSSTransition::GetOwningElement; r=dbaron (e6da3c726)
- Bug 1171817 part 4 - Add const version of AsCSSAnimation/AsCSSTransition methods; r=dbaron (f264ebad7)
- Bug 1171817 part 5 - Add a sequence number member to Animations; r=dbaron (b041eeb6b)
- Bug 1171817 part 6 - Add Animation::HasLowerCompositeOrderThan; r=dbaron (df97cf295)
- Bug 1171817 part 7 - Add Animation::IsUsingCustomCompositeOrder; r=dbaron (5735f03a2)
- Bug 1171817 part 8 - Override sequence numbers for CSS animations; r=dbaron (50671de0f)
- Bug 1171817 part 9 - Add override of HasLowerCompositeOrderThan for CSS animations; r=dbaron (b467ffd3c)
- Bug 1171817 part 10 - Override sequence numbers for transitions; r=dbron (3703102f6)
- Bug 1171817 part 11 - Add CSSTransition::TransitionProperty(); r=dbaron (c889aa8ec)
- Bug 1171817 part 13 - Add override of HasLowerCompositeOrderThan for CSS transitions; r=dbaron (8c628cac4)
- Bug 1171817 part 14 - Add AnimationPtrComparator class; r=dbaron (c522180c9)
- Bug 1171817 part 15 - Factor out common code for comparing owning elements into a separate class; r=dbaron (132998a2c)
- Bug 1171817 part 16 - Always cancel transitions before removing them; r=dbaron (01113a650)
- Bug 1150810 part 2 - Replace references to DocumentTimeline with AnimationTimeline; r=jwatt (d377ba63f)
- Bug 1150810 part 3 - Make IsPossiblyOrphanedPendingAnimation return true when there is no rendered doc; r=jwatt (63b2b6760)
- Bug 1150810 part 4 - Store global on Animation; r=smaug, jwatt (fd099d639)
- Bug 1150810 part 5 - Handle Timeline() returning null; r=jwatt (641bd865d)
2021-03-26 17:01:09 +08:00

285 lines
7.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/. */
/*
* cache of re-usable nsCSSRuleProcessors for given sets of style sheets
*/
#include "RuleProcessorCache.h"
#include <algorithm>
#include "nsCSSRuleProcessor.h"
#include "nsThreadUtils.h"
using namespace mozilla;
NS_IMPL_ISUPPORTS(RuleProcessorCache, nsIMemoryReporter)
MOZ_DEFINE_MALLOC_SIZE_OF(RuleProcessorCacheMallocSizeOf)
NS_IMETHODIMP
RuleProcessorCache::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize)
{
return MOZ_COLLECT_REPORT(
"explicit/layout/rule-processor-cache", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(RuleProcessorCacheMallocSizeOf),
"Memory used for cached rule processors.");
}
RuleProcessorCache::~RuleProcessorCache()
{
UnregisterWeakMemoryReporter(this);
for (Entry& e : mEntries) {
for (DocumentEntry& de : e.mDocumentEntries) {
if (de.mRuleProcessor->GetExpirationState()->IsTracked()) {
mExpirationTracker.RemoveObject(de.mRuleProcessor);
}
de.mRuleProcessor->SetInRuleProcessorCache(false);
}
}
}
void
RuleProcessorCache::InitMemoryReporter()
{
RegisterWeakMemoryReporter(this);
}
/* static */ bool
RuleProcessorCache::EnsureGlobal()
{
MOZ_ASSERT(NS_IsMainThread());
if (gShutdown) {
return false;
}
if (!gRuleProcessorCache) {
gRuleProcessorCache = new RuleProcessorCache;
gRuleProcessorCache->InitMemoryReporter();
}
return true;
}
/* static */ void
RuleProcessorCache::RemoveSheet(CSSStyleSheet* aSheet)
{
if (!EnsureGlobal()) {
return;
}
gRuleProcessorCache->DoRemoveSheet(aSheet);
}
#ifdef DEBUG
/* static */ bool
RuleProcessorCache::HasRuleProcessor(nsCSSRuleProcessor* aRuleProcessor)
{
if (!EnsureGlobal()) {
return false;
}
return gRuleProcessorCache->DoHasRuleProcessor(aRuleProcessor);
}
#endif
/* static */ void
RuleProcessorCache::RemoveRuleProcessor(nsCSSRuleProcessor* aRuleProcessor)
{
if (!EnsureGlobal()) {
return;
}
gRuleProcessorCache->DoRemoveRuleProcessor(aRuleProcessor);
}
/* static */ nsCSSRuleProcessor*
RuleProcessorCache::GetRuleProcessor(const nsTArray<CSSStyleSheet*>& aSheets,
nsPresContext* aPresContext)
{
if (!EnsureGlobal()) {
return nullptr;
}
return gRuleProcessorCache->DoGetRuleProcessor(aSheets, aPresContext);
}
/* static */ void
RuleProcessorCache::PutRuleProcessor(
const nsTArray<CSSStyleSheet*>& aSheets,
nsTArray<css::DocumentRule*>&& aDocumentRulesInSheets,
const nsDocumentRuleResultCacheKey& aCacheKey,
nsCSSRuleProcessor* aRuleProcessor)
{
if (!EnsureGlobal()) {
return;
}
gRuleProcessorCache->DoPutRuleProcessor(aSheets, Move(aDocumentRulesInSheets),
aCacheKey, aRuleProcessor);
}
/* static */ void
RuleProcessorCache::StartTracking(nsCSSRuleProcessor* aRuleProcessor)
{
if (!EnsureGlobal()) {
return;
}
return gRuleProcessorCache->DoStartTracking(aRuleProcessor);
}
/* static */ void
RuleProcessorCache::StopTracking(nsCSSRuleProcessor* aRuleProcessor)
{
if (!EnsureGlobal()) {
return;
}
return gRuleProcessorCache->DoStopTracking(aRuleProcessor);
}
void
RuleProcessorCache::DoRemoveSheet(CSSStyleSheet* aSheet)
{
Entry* last = std::remove_if(mEntries.begin(), mEntries.end(),
HasSheet_ThenRemoveRuleProcessors(this, aSheet));
mEntries.TruncateLength(last - mEntries.begin());
}
nsCSSRuleProcessor*
RuleProcessorCache::DoGetRuleProcessor(const nsTArray<CSSStyleSheet*>& aSheets,
nsPresContext* aPresContext)
{
for (Entry& e : mEntries) {
if (e.mSheets == aSheets) {
for (DocumentEntry& de : e.mDocumentEntries) {
if (de.mCacheKey.Matches(aPresContext, e.mDocumentRulesInSheets)) {
return de.mRuleProcessor;
}
}
// Entry::mSheets is unique; if we matched aSheets but didn't
// find a matching DocumentEntry, we won't find one later in
// mEntries.
return nullptr;
}
}
return nullptr;
}
void
RuleProcessorCache::DoPutRuleProcessor(
const nsTArray<CSSStyleSheet*>& aSheets,
nsTArray<css::DocumentRule*>&& aDocumentRulesInSheets,
const nsDocumentRuleResultCacheKey& aCacheKey,
nsCSSRuleProcessor* aRuleProcessor)
{
MOZ_ASSERT(!aRuleProcessor->IsInRuleProcessorCache());
Entry* entry = nullptr;
for (Entry& e : mEntries) {
if (e.mSheets == aSheets) {
entry = &e;
break;
}
}
if (!entry) {
entry = mEntries.AppendElement();
entry->mSheets = aSheets;
entry->mDocumentRulesInSheets = aDocumentRulesInSheets;
for (CSSStyleSheet* sheet : aSheets) {
sheet->SetInRuleProcessorCache();
}
} else {
MOZ_ASSERT(entry->mDocumentRulesInSheets == aDocumentRulesInSheets,
"DocumentRule array shouldn't have changed");
}
#ifdef DEBUG
for (DocumentEntry& de : entry->mDocumentEntries) {
MOZ_ASSERT(de.mCacheKey != aCacheKey,
"should not have duplicate document cache keys");
}
#endif
DocumentEntry* documentEntry = entry->mDocumentEntries.AppendElement();
documentEntry->mCacheKey = aCacheKey;
documentEntry->mRuleProcessor = aRuleProcessor;
aRuleProcessor->SetInRuleProcessorCache(true);
}
#ifdef DEBUG
bool
RuleProcessorCache::DoHasRuleProcessor(nsCSSRuleProcessor* aRuleProcessor)
{
for (Entry& e : mEntries) {
for (DocumentEntry& de : e.mDocumentEntries) {
if (de.mRuleProcessor == aRuleProcessor) {
return true;
}
}
}
return false;
}
#endif
void
RuleProcessorCache::DoRemoveRuleProcessor(nsCSSRuleProcessor* aRuleProcessor)
{
MOZ_ASSERT(aRuleProcessor->IsInRuleProcessorCache());
aRuleProcessor->SetInRuleProcessorCache(false);
mExpirationTracker.RemoveObjectIfTracked(aRuleProcessor);
for (Entry& e : mEntries) {
for (size_t i = 0; i < e.mDocumentEntries.Length(); i++) {
if (e.mDocumentEntries[i].mRuleProcessor == aRuleProcessor) {
e.mDocumentEntries.RemoveElementAt(i);
return;
}
}
}
MOZ_ASSERT_UNREACHABLE("should have found rule processor");
}
void
RuleProcessorCache::DoStartTracking(nsCSSRuleProcessor* aRuleProcessor)
{
mExpirationTracker.AddObject(aRuleProcessor);
}
void
RuleProcessorCache::DoStopTracking(nsCSSRuleProcessor* aRuleProcessor)
{
mExpirationTracker.RemoveObjectIfTracked(aRuleProcessor);
}
size_t
RuleProcessorCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
size_t n = aMallocSizeOf(this);
int count = 0;
n += mEntries.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (Entry& e : mEntries) {
n += e.mDocumentEntries.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (DocumentEntry& de : e.mDocumentEntries) {
count++;
n += de.mRuleProcessor->SizeOfIncludingThis(aMallocSizeOf);
}
}
return n;
}
void
RuleProcessorCache::ExpirationTracker::RemoveObjectIfTracked(
nsCSSRuleProcessor* aRuleProcessor)
{
if (aRuleProcessor->GetExpirationState()->IsTracked()) {
RemoveObject(aRuleProcessor);
}
}
bool RuleProcessorCache::gShutdown = false;
mozilla::StaticRefPtr<RuleProcessorCache> RuleProcessorCache::gRuleProcessorCache;