Bug 77999 - Part 5: Cache eAgentSheet and eUserSheet rule processors in the RuleProcessorCache. r=dbaron

Ignoring sheets added by add-ons, all sheets in the eAgentSheet and
eUserSheet levels should come from the nsLayoutStylesheetCache and thus
allow multiple documents to make use of a shared rule processor.
This commit is contained in:
Cameron McCormack 2015-06-26 13:52:48 +10:00
parent 0274cb2bf2
commit 941e794b58

View File

@ -15,6 +15,7 @@
#include "mozilla/CSSStyleSheet.h"
#include "mozilla/EventStates.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/RuleProcessorCache.h"
#include "nsIDocumentInlines.h"
#include "nsRuleWalker.h"
#include "nsStyleContext.h"
@ -181,6 +182,19 @@ nsStyleSet::~nsStyleSet()
static_cast<CSSStyleSheet*>(mSheets[type][i])->DropStyleSet(this);
}
}
// drop reference to cached rule processors
nsCSSRuleProcessor* rp;
rp = static_cast<nsCSSRuleProcessor*>(mRuleProcessors[eAgentSheet].get());
if (rp) {
MOZ_ASSERT(rp->IsShared());
rp->ReleaseStyleSetRef();
}
rp = static_cast<nsCSSRuleProcessor*>(mRuleProcessors[eUserSheet].get());
if (rp) {
MOZ_ASSERT(rp->IsShared());
rp->ReleaseStyleSetRef();
}
}
size_t
@ -190,7 +204,16 @@ nsStyleSet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
for (int i = 0; i < eSheetTypeCount; i++) {
if (mRuleProcessors[i]) {
n += mRuleProcessors[i]->SizeOfIncludingThis(aMallocSizeOf);
bool shared = false;
if (i == eAgentSheet || i == eUserSheet) {
// The only two origins we consider caching rule processors for.
nsCSSRuleProcessor* rp =
static_cast<nsCSSRuleProcessor*>(mRuleProcessors[i].get());
shared = rp->IsShared();
}
if (!shared) {
n += mRuleProcessors[i]->SizeOfIncludingThis(aMallocSizeOf);
}
}
// mSheets is a C-style array of nsCOMArrays. We do not own the sheets in
// the nsCOMArrays (either the nsLayoutStyleSheetCache singleton or our
@ -364,7 +387,15 @@ nsStyleSet::GatherRuleProcessors(sheetType aType)
{
nsCOMPtr<nsIStyleRuleProcessor> oldRuleProcessor(mRuleProcessors[aType]);
nsTArray<nsCOMPtr<nsIStyleRuleProcessor>> oldScopedDocRuleProcessors;
if (aType == eAgentSheet || aType == eUserSheet) {
// drop reference to cached rule processor
nsCSSRuleProcessor* rp =
static_cast<nsCSSRuleProcessor*>(mRuleProcessors[aType].get());
if (rp) {
MOZ_ASSERT(rp->IsShared());
rp->ReleaseStyleSetRef();
}
}
mRuleProcessors[aType] = nullptr;
if (aType == eScopedDocSheet) {
for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) {
@ -477,10 +508,43 @@ nsStyleSet::GatherRuleProcessors(sheetType aType)
if (mSheets[aType].Count()) {
switch (aType) {
case eAgentSheet:
case eUserSheet:
case eUserSheet: {
// levels containing non-scoped CSS style sheets whose rule processors
// we want to re-use
nsCOMArray<nsIStyleSheet>& sheets = mSheets[aType];
nsTArray<nsRefPtr<CSSStyleSheet>> cssSheets(sheets.Count());
for (int32_t i = 0, i_end = sheets.Count(); i < i_end; ++i) {
nsRefPtr<CSSStyleSheet> cssSheet = do_QueryObject(sheets[i]);
NS_ASSERTION(cssSheet, "not a CSS sheet");
cssSheets.AppendElement(cssSheet);
}
nsTArray<CSSStyleSheet*> cssSheetsRaw(cssSheets.Length());
for (int32_t i = 0, i_end = cssSheets.Length(); i < i_end; ++i) {
cssSheetsRaw.AppendElement(cssSheets[i]);
}
nsCSSRuleProcessor* rp =
RuleProcessorCache::GetRuleProcessor(cssSheetsRaw, PresContext());
if (!rp) {
rp = new nsCSSRuleProcessor(cssSheets, uint8_t(aType), nullptr,
static_cast<nsCSSRuleProcessor*>(
oldRuleProcessor.get()),
true /* aIsShared */);
nsTArray<css::DocumentRule*> documentRules;
nsDocumentRuleResultCacheKey cacheKey;
rp->TakeDocumentRulesAndCacheKey(PresContext(),
documentRules, cacheKey);
RuleProcessorCache::PutRuleProcessor(cssSheetsRaw,
Move(documentRules),
cacheKey, rp);
}
mRuleProcessors[aType] = rp;
rp->AddStyleSetRef();
break;
}
case eDocSheet:
case eOverrideSheet: {
// levels containing CSS stylesheets (apart from eScopedDocSheet)
// levels containing non-scoped CSS stylesheets whose rule processors
// we don't want to re-use
nsCOMArray<nsIStyleSheet>& sheets = mSheets[aType];
nsTArray<nsRefPtr<CSSStyleSheet>> cssSheets(sheets.Count());
for (int32_t i = 0, i_end = sheets.Count(); i < i_end; ++i) {