mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 01:05:45 +00:00
Bug 1519861 - Improve mozilla::GetTabSizes - r=smaug
Introduces a generation number in dom::base::Document as well as a cached version of TabSizes we can Get and Set. When the document is changed, the cache is invalidated. This change improves about:performance speed by avoiding a heavy recursive call on big DOM trees via GetTabSizes() calls. If the page does not change, the cached values are returned. Differential Revision: https://phabricator.services.mozilla.com/D20526 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
120c38f502
commit
48840088a2
@ -1341,7 +1341,9 @@ Document::Document(const char* aContentType)
|
||||
mIgnoreOpensDuringUnloadCounter(0),
|
||||
mDocLWTheme(Doc_Theme_Uninitialized),
|
||||
mSavedResolution(1.0f),
|
||||
mPendingInitialTranslation(false) {
|
||||
mPendingInitialTranslation(false),
|
||||
mGeneration(0),
|
||||
mCachedTabSizeGeneration(0) {
|
||||
MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p created", this));
|
||||
|
||||
SetIsInDocument();
|
||||
@ -12549,6 +12551,24 @@ bool Document::StorageAccessSandboxed() const {
|
||||
(GetSandboxFlags() & SANDBOXED_STORAGE_ACCESS) != 0;
|
||||
}
|
||||
|
||||
bool Document::GetCachedSizes(nsTabSizes* aSizes) {
|
||||
if (mCachedTabSizeGeneration == 0 ||
|
||||
GetGeneration() != mCachedTabSizeGeneration) {
|
||||
return false;
|
||||
}
|
||||
aSizes->mDom += mCachedTabSizes.mDom;
|
||||
aSizes->mStyle += mCachedTabSizes.mStyle;
|
||||
aSizes->mOther += mCachedTabSizes.mOther;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Document::SetCachedSizes(nsTabSizes* aSizes) {
|
||||
mCachedTabSizes.mDom = aSizes->mDom;
|
||||
mCachedTabSizes.mStyle = aSizes->mStyle;
|
||||
mCachedTabSizes.mOther = aSizes->mOther;
|
||||
mCachedTabSizeGeneration = GetGeneration();
|
||||
}
|
||||
|
||||
already_AddRefed<nsAtom> Document::GetContentLanguageAsAtomForStyle() const {
|
||||
nsAutoString contentLang;
|
||||
GetContentLanguage(contentLang);
|
||||
|
@ -1490,6 +1490,21 @@ class Document : public nsINode,
|
||||
// flag.
|
||||
bool StorageAccessSandboxed() const;
|
||||
|
||||
// Increments the document generation.
|
||||
inline void Changed() { ++mGeneration; }
|
||||
|
||||
// Returns the current generation.
|
||||
inline int32_t GetGeneration() const { return mGeneration; }
|
||||
|
||||
// Adds cached sizes values to aSizes if there's any
|
||||
// cached value and if the document generation hasn't
|
||||
// changed since the cache was created.
|
||||
// Returns true if sizes were added.
|
||||
bool GetCachedSizes(nsTabSizes* aSizes);
|
||||
|
||||
// Sets the cache sizes for the current generation.
|
||||
void SetCachedSizes(nsTabSizes* aSizes);
|
||||
|
||||
protected:
|
||||
friend class nsUnblockOnloadEvent;
|
||||
|
||||
@ -4641,6 +4656,13 @@ class Document : public nsINode,
|
||||
|
||||
bool mPendingInitialTranslation;
|
||||
|
||||
// Document generation. Gets incremented everytime it changes.
|
||||
int32_t mGeneration;
|
||||
|
||||
// Cached TabSizes values for the document.
|
||||
int32_t mCachedTabSizeGeneration;
|
||||
nsTabSizes mCachedTabSizes;
|
||||
|
||||
public:
|
||||
// Needs to be public because the bindings code pokes at it.
|
||||
js::ExpandoAndGeneration mExpandoAndGeneration;
|
||||
|
@ -136,6 +136,7 @@ void nsNodeUtils::CharacterDataWillChange(
|
||||
void nsNodeUtils::CharacterDataChanged(nsIContent* aContent,
|
||||
const CharacterDataChangeInfo& aInfo) {
|
||||
Document* doc = aContent->OwnerDoc();
|
||||
doc->Changed();
|
||||
IMPL_MUTATION_NOTIFICATION(CharacterDataChanged, aContent, (aContent, aInfo),
|
||||
IsRemoveNotification::No);
|
||||
}
|
||||
@ -152,6 +153,7 @@ void nsNodeUtils::AttributeChanged(Element* aElement, int32_t aNameSpaceID,
|
||||
nsAtom* aAttribute, int32_t aModType,
|
||||
const nsAttrValue* aOldValue) {
|
||||
Document* doc = aElement->OwnerDoc();
|
||||
doc->Changed();
|
||||
IMPL_MUTATION_NOTIFICATION(
|
||||
AttributeChanged, aElement,
|
||||
(aElement, aNameSpaceID, aAttribute, aModType, aOldValue),
|
||||
@ -170,7 +172,7 @@ void nsNodeUtils::AttributeSetToCurrentValue(Element* aElement,
|
||||
void nsNodeUtils::ContentAppended(nsIContent* aContainer,
|
||||
nsIContent* aFirstNewContent) {
|
||||
Document* doc = aContainer->OwnerDoc();
|
||||
|
||||
doc->Changed();
|
||||
IMPL_MUTATION_NOTIFICATION(ContentAppended, aContainer, (aFirstNewContent),
|
||||
IsRemoveNotification::No);
|
||||
}
|
||||
@ -188,6 +190,7 @@ void nsNodeUtils::ContentInserted(nsINode* aContainer, nsIContent* aChild) {
|
||||
MOZ_ASSERT(aContainer->IsContent() || aContainer->IsDocument(),
|
||||
"container must be an nsIContent or an Document");
|
||||
Document* doc = aContainer->OwnerDoc();
|
||||
doc->Changed();
|
||||
IMPL_MUTATION_NOTIFICATION(ContentInserted, aContainer, (aChild),
|
||||
IsRemoveNotification::No);
|
||||
}
|
||||
@ -197,6 +200,7 @@ void nsNodeUtils::ContentRemoved(nsINode* aContainer, nsIContent* aChild,
|
||||
MOZ_ASSERT(aContainer->IsContent() || aContainer->IsDocument(),
|
||||
"container must be an nsIContent or an Document");
|
||||
Document* doc = aContainer->OwnerDoc();
|
||||
doc->Changed();
|
||||
MOZ_ASSERT(aChild->GetParentNode() == aContainer,
|
||||
"We expect the parent link to be still around at this point");
|
||||
IMPL_MUTATION_NOTIFICATION(ContentRemoved, aContainer,
|
||||
|
@ -60,22 +60,41 @@ nsTArray<RefPtr<PerformanceInfoPromise>> CollectPerformanceInfo() {
|
||||
return promises;
|
||||
}
|
||||
|
||||
nsresult GetTabSizes(nsGlobalWindowOuter* aWindow, nsTabSizes* aSizes) {
|
||||
void AddWindowTabSizes(nsGlobalWindowOuter* aWindow, nsTabSizes* aSizes) {
|
||||
Document* document = aWindow->GetDocument();
|
||||
if (document && document->GetCachedSizes(aSizes)) {
|
||||
// We got a cached version
|
||||
return;
|
||||
}
|
||||
// We measure the sizes on a fresh nsTabSizes instance
|
||||
// because we want to cache the value and aSizes might
|
||||
// already have some values from other windows.
|
||||
nsTabSizes sizes;
|
||||
|
||||
// Measure the window.
|
||||
SizeOfState state(moz_malloc_size_of);
|
||||
nsWindowSizes windowSizes(state);
|
||||
aWindow->AddSizeOfIncludingThis(windowSizes);
|
||||
|
||||
// Measure the inner window, if there is one.
|
||||
nsGlobalWindowInner* inner = aWindow->GetCurrentInnerWindowInternal();
|
||||
if (inner != nullptr) {
|
||||
inner->AddSizeOfIncludingThis(windowSizes);
|
||||
}
|
||||
windowSizes.addToTabSizes(&sizes);
|
||||
if (document) {
|
||||
document->SetCachedSizes(&sizes);
|
||||
}
|
||||
aSizes->mDom += sizes.mDom;
|
||||
aSizes->mStyle += sizes.mStyle;
|
||||
aSizes->mOther += sizes.mOther;
|
||||
}
|
||||
|
||||
nsresult GetTabSizes(nsGlobalWindowOuter* aWindow, nsTabSizes* aSizes) {
|
||||
// Add the window (and inner window) sizes. Might be cached.
|
||||
AddWindowTabSizes(aWindow, aSizes);
|
||||
|
||||
windowSizes.addToTabSizes(aSizes);
|
||||
nsDOMWindowList* frames = aWindow->GetFrames();
|
||||
uint32_t length = frames->GetLength();
|
||||
|
||||
// Measure this window's descendents.
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> child = frames->IndexedGetter(i);
|
||||
|
Loading…
Reference in New Issue
Block a user