Bug 1362599 - Remember which languages were used and force-cache when reset; r?heycam
MozReview-Commit-ID: 8cPRd8xUHEp
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -232,16 +232,17 @@ nsPresContext::nsPresContext(nsIDocument
mFocusTextColor(mDefaultColor),
mBodyTextColor(mDefaultColor),
mViewportScrollbarOverrideNode(nullptr),
mViewportStyleScrollbar(NS_STYLE_OVERFLOW_AUTO, NS_STYLE_OVERFLOW_AUTO),
mFocusRingWidth(1),
mExistThrottledUpdates(false),
// mImageAnimationMode is initialised below, in constructor body
mImageAnimationModePref(imgIContainer::kNormalAnimMode),
+ mFontGroupCacheDirty(true),
mInterruptChecksToSkip(0),
mElementsRestyled(0),
mFramesConstructed(0),
mFramesReflowed(0),
mInteractionTimeEnabled(true),
mTelemetryScrollLastY(0),
mTelemetryScrollMaxY(0),
mTelemetryScrollTotalY(0),
@@ -618,16 +619,17 @@ nsPresContext::GetUserPreferences()
// * use fonts?
mUseDocumentFonts =
Preferences::GetInt("browser.display.use_document_fonts") != 0;
mPrefScrollbarSide = Preferences::GetInt("layout.scrollbar.side");
mLangGroupFontPrefs.Reset();
+ mFontGroupCacheDirty = true;
StaticPresData::Get()->ResetCachedFontPrefs();
// * image animation
const nsAdoptingCString& animatePref =
Preferences::GetCString("image.animation_mode");
if (animatePref.EqualsLiteral("normal"))
mImageAnimationModePref = imgIContainer::kNormalAnimMode;
else if (animatePref.EqualsLiteral("none"))
@@ -1061,16 +1063,17 @@ nsPresContext::UpdateCharSet(const nsCSt
mLanguage = mLangService->LookupCharSet(aCharSet);
// this will be a language group (or script) code rather than a true language code
// bug 39570: moved from nsLanguageAtomService::LookupCharSet()
if (mLanguage == nsGkAtoms::Unicode) {
mLanguage = mLangService->GetLocaleLanguage();
}
mLangGroupFontPrefs.Reset();
+ mFontGroupCacheDirty = true;
}
switch (GET_BIDI_OPTION_TEXTTYPE(GetBidi())) {
case IBMBIDI_TEXTTYPE_LOGICAL:
SetVisualMode(false);
break;
@@ -1971,16 +1974,43 @@ void nsPresContext::StopEmulatingMedium(
nsIAtom* previousMedium = Medium();
mIsEmulatingMedia = false;
if (Medium() != previousMedium) {
MediaFeatureValuesChanged(nsRestyleHint(0), nsChangeHint(0));
}
}
void
+nsPresContext::ForceCacheLang(nsIAtom *aLanguage)
+{
+ // force it to be cached
+ GetDefaultFont(kPresContext_DefaultVariableFont_ID, aLanguage);
+ if (!mLanguagesUsed.Contains(aLanguage)) {
+ mLanguagesUsed.PutEntry(aLanguage);
+ }
+}
+
+void
+nsPresContext::CacheAllLangs()
+{
+ if (mFontGroupCacheDirty) {
+ nsCOMPtr<nsIAtom> thisLang = nsStyleFont::GetLanguage(this);
+ GetDefaultFont(kPresContext_DefaultVariableFont_ID, thisLang.get());
+ GetDefaultFont(kPresContext_DefaultVariableFont_ID, nsGkAtoms::x_math);
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1362599#c12
+ GetDefaultFont(kPresContext_DefaultVariableFont_ID, nsGkAtoms::Unicode);
+ for (auto iter = mLanguagesUsed.Iter(); !iter.Done(); iter.Next()) {
+
+ GetDefaultFont(kPresContext_DefaultVariableFont_ID, iter.Get()->GetKey());
+ }
+ }
+ mFontGroupCacheDirty = false;
+}
+
+void
nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint,
nsRestyleHint aRestyleHint)
{
if (!mShell) {
// We must have been torn down. Nothing to do here.
return;
}
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -368,16 +368,19 @@ public:
const nsFont* GetDefaultFont(uint8_t aFontID,
nsIAtom *aLanguage) const
{
nsIAtom* lang = aLanguage ? aLanguage : mLanguage.get();
return StaticPresData::Get()->GetDefaultFontHelper(aFontID, lang,
GetFontPrefsForLang(lang));
}
+ void ForceCacheLang(nsIAtom *aLanguage);
+ void CacheAllLangs();
+
/** Get a cached boolean pref, by its type */
// * - initially created for bugs 31816, 20760, 22963
bool GetCachedBoolPref(nsPresContext_CachedBoolPrefType aPrefType) const
{
// If called with a constant parameter, the compiler should optimize
// this switch statement away.
switch (aPrefType) {
case kPresContext_UseDocumentFonts:
@@ -1415,16 +1418,19 @@ protected:
// Most documents will only use one (or very few) language groups. Rather
// than have the overhead of a hash lookup, we simply look along what will
// typically be a very short (usually of length 1) linked list. There are 31
// language groups, so in the worst case scenario we'll need to traverse 31
// link items.
LangGroupFontPrefs mLangGroupFontPrefs;
+ bool mFontGroupCacheDirty;
+ nsTHashtable<nsRefPtrHashKey<nsIAtom>> mLanguagesUsed;
+
nscoord mBorderWidthTable[3];
uint32_t mInterruptChecksToSkip;
// Counters for tests and tools that want to detect frame construction
// or reflow.
uint64_t mElementsRestyled;
uint64_t mFramesConstructed;
--- a/layout/style/ServoSpecifiedValues.cpp
+++ b/layout/style/ServoSpecifiedValues.cpp
@@ -46,18 +46,17 @@ void
ServoSpecifiedValues::SetIdentStringValue(nsCSSPropertyID aId,
const nsString& aValue)
{
nsCOMPtr<nsIAtom> atom = NS_Atomize(aValue);
Servo_DeclarationBlock_SetIdentStringValue(mDecl, aId, atom);
if (aId == eCSSProperty__x_lang) {
// This forces the lang prefs result to be cached
// so that we can access them off main thread during traversal
- mPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID,
- atom);
+ mPresContext->ForceCacheLang(atom);
}
}
void
ServoSpecifiedValues::SetKeywordValue(nsCSSPropertyID aId, int32_t aValue)
{
Servo_DeclarationBlock_SetKeywordValue(mDecl, aId, aValue);
}
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -262,16 +262,17 @@ ServoStyleSet::PreTraverseSync()
// This is lazily computed and pseudo matching needs to access
// it so force computation early.
mPresContext->Document()->GetDocumentState();
// Ensure that the @font-face data is not stale
mPresContext->Document()->GetUserFontSet();
UpdateStylistIfNeeded();
+ mPresContext->CacheAllLangs();
}
void
ServoStyleSet::PreTraverse(Element* aRoot)
{
PreTraverseSync();
// Process animation stuff that we should avoid doing during the parallel
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1632,16 +1632,17 @@ pub extern "C" fn Servo_DeclarationBlock
*mut nsIAtom) {
use style::properties::{PropertyDeclaration, LonghandId};
use style::properties::longhands::_x_lang::computed_value::T as Lang;
let long = get_longhand_from_id!(property);
let prop = match_wrap_declared! { long,
XLang => Lang(Atom::from(value)),
};
+
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
decls.push(prop, Importance::Normal);
})
}
#[no_mangle]
#[allow(unreachable_code)]
pub extern "C" fn Servo_DeclarationBlock_SetKeywordValue(declarations: