From 0fd7a7ea1af6763f286e793d1ca3fa99680b5bfd Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Tue, 19 Apr 2022 14:20:21 +0000 Subject: [PATCH] Bug 1756474 - Add locking to gfxPlatformFontList and gfxFontFamily, to allow use from worker threads. r=lsalzman We use a recursive-mutex in gfxPlatformFontList as some of its methods may be called from classes like gfxFontEntry that are used both from layout code (which does not explictly lock the font-list) and internally by font-list code that is already holding the lock. Differential Revision: https://phabricator.services.mozilla.com/D143869 --- gfx/thebes/gfxDWriteFontList.cpp | 19 ++- gfx/thebes/gfxDWriteFontList.h | 9 +- gfx/thebes/gfxFT2FontList.cpp | 35 +++-- gfx/thebes/gfxFT2FontList.h | 31 ++-- gfx/thebes/gfxFcPlatformFontList.cpp | 32 ++-- gfx/thebes/gfxFcPlatformFontList.h | 33 +++-- gfx/thebes/gfxFont.cpp | 33 +++-- gfx/thebes/gfxFont.h | 20 +-- gfx/thebes/gfxFontEntry.cpp | 82 +++++++---- gfx/thebes/gfxFontEntry.h | 95 +++++++----- gfx/thebes/gfxFontInfoLoader.cpp | 21 +-- gfx/thebes/gfxGDIFontList.cpp | 40 ++--- gfx/thebes/gfxGDIFontList.h | 5 +- gfx/thebes/gfxMacPlatformFontList.h | 34 +++-- gfx/thebes/gfxMacPlatformFontList.mm | 51 ++++--- gfx/thebes/gfxPlatformFontList.cpp | 179 ++++++++++++++-------- gfx/thebes/gfxPlatformFontList.h | 213 ++++++++++++++++++--------- gfx/thebes/gfxUserFontSet.h | 7 +- layout/mathml/nsMathMLChar.cpp | 2 + 19 files changed, 600 insertions(+), 341 deletions(-) diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp index d38f900f2707..20db97358f6e 100644 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -132,11 +132,13 @@ static HRESULT GetDirectWriteFaceName(IDWriteFont* aFont, return S_OK; } -void gfxDWriteFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) { +void gfxDWriteFontFamily::FindStyleVariationsLocked( + FontInfoData* aFontInfoData) { HRESULT hr; if (mHasStyles) { return; } + mHasStyles = true; gfxPlatformFontList* fp = gfxPlatformFontList::PlatformFontList(); @@ -188,7 +190,7 @@ void gfxDWriteFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) { fe->SetupVariationRanges(); - AddFontEntry(fe); + AddFontEntryLocked(fe); // postscript/fullname if needed nsAutoCString psname, fullname; @@ -1839,7 +1841,7 @@ void gfxDWriteFontList::GetFontsFromCollection( // if this fails/doesn't exist, we'll have used name index 0, // so that's the one we'll want to skip here names->FindLocaleName(L"en-us", &englishIdx, &exists); - + AutoTArray otherFamilyNames; for (nameIndex = 0; nameIndex < nameCount; nameIndex++) { UINT32 nameLen; AutoTArray localizedName; @@ -1866,9 +1868,12 @@ void gfxDWriteFontList::GetFontsFromCollection( NS_ConvertUTF16toUTF8 locName(localizedName.Elements()); if (!familyName.Equals(locName)) { - AddOtherFamilyName(fam, locName); + otherFamilyNames.AppendElement(locName); } } + if (!otherFamilyNames.IsEmpty()) { + AddOtherFamilyNames(fam, otherFamilyNames); + } } // at this point, all family names have been read in @@ -2010,7 +2015,7 @@ void gfxDWriteFontList::GetDirectWriteSubstitutes() { } } -bool gfxDWriteFontList::FindAndAddFamilies( +bool gfxDWriteFontList::FindAndAddFamiliesLocked( nsPresContext* aPresContext, StyleGenericFontFamily aGeneric, const nsACString& aFamily, nsTArray* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage, @@ -2037,7 +2042,7 @@ bool gfxDWriteFontList::FindAndAddFamilies( return false; } - return gfxPlatformFontList::FindAndAddFamilies( + return gfxPlatformFontList::FindAndAddFamiliesLocked( aPresContext, aGeneric, keyName, aOutput, aFlags, aStyle, aLanguage, aDevToCssSize); } @@ -2046,6 +2051,8 @@ void gfxDWriteFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const { gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes); + AutoLock lock(mLock); + // We are a singleton, so include the font loader singleton's memory. MOZ_ASSERT(static_cast(this) == gfxPlatformFontList::PlatformFontList()); diff --git a/gfx/thebes/gfxDWriteFontList.h b/gfx/thebes/gfxDWriteFontList.h index ec4c57457e44..e04de357c007 100644 --- a/gfx/thebes/gfxDWriteFontList.h +++ b/gfx/thebes/gfxDWriteFontList.h @@ -63,7 +63,7 @@ class gfxDWriteFontFamily final : public gfxFontFamily { mForceGDIClassic(false) {} virtual ~gfxDWriteFontFamily(); - void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) final; + void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr) final; void LocalizedName(nsACString& aLocalizedName) final; @@ -194,7 +194,7 @@ class gfxDWriteFontEntry final : public gfxFontEntry { hb_blob_t* GetFontTable(uint32_t aTableTag) override; - nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr); + nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr) override; bool IsCJKFont(); @@ -387,7 +387,8 @@ class gfxDWriteFontList final : public gfxPlatformFontList { const mozilla::fontlist::Family* aFamily) override; void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily, - bool aNeedFullnamePostscriptNames) override; + bool aNeedFullnamePostscriptNames) + REQUIRES(mLock) override; bool ReadFaceNames(mozilla::fontlist::Family* aFamily, mozilla::fontlist::Face* aFace, nsCString& aPSName, @@ -414,7 +415,7 @@ class gfxDWriteFontList final : public gfxPlatformFontList { IDWriteGdiInterop* GetGDIInterop() { return mGDIInterop; } bool UseGDIFontTableAccess() const; - bool FindAndAddFamilies( + bool FindAndAddFamiliesLocked( nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric, const nsACString& aFamily, nsTArray* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr, diff --git a/gfx/thebes/gfxFT2FontList.cpp b/gfx/thebes/gfxFT2FontList.cpp index 900124db663d..b26de0539965 100644 --- a/gfx/thebes/gfxFT2FontList.cpp +++ b/gfx/thebes/gfxFT2FontList.cpp @@ -618,6 +618,7 @@ void FT2FontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, */ void FT2FontFamily::AddFacesToFontList(nsTArray* aFontList) { + AutoReadLock lock(mLock); for (int i = 0, n = mAvailableFonts.Length(); i < n; ++i) { const FT2FontEntry* fe = static_cast(mAvailableFonts[i].get()); @@ -1168,7 +1169,9 @@ void gfxFT2FontList::AppendFacesFromFontFile(const nsCString& aFileName, CollectFunc unshared = [](const FontListEntry& aFLE, const nsCString& aPSName, const nsCString& aFullName, StandardFile aStdFile) { - PlatformFontList()->AppendFaceFromFontListEntry(aFLE, aStdFile); + auto* pfl = PlatformFontList(); + pfl->mLock.AssertCurrentThreadIn(); + pfl->AppendFaceFromFontListEntry(aFLE, aStdFile); }; CollectFunc shared = [](const FontListEntry& aFLE, const nsCString& aPSName, const nsCString& aFullName, StandardFile aStdFile) { @@ -1339,7 +1342,9 @@ void gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive, CollectFunc unshared = [](const FontListEntry& aFLE, const nsCString& aPSName, const nsCString& aFullName, StandardFile aStdFile) { - PlatformFontList()->AppendFaceFromFontListEntry(aFLE, aStdFile); + auto* pfl = PlatformFontList(); + pfl->mLock.AssertCurrentThreadIn(); + pfl->AppendFaceFromFontListEntry(aFLE, aStdFile); }; CollectFunc shared = [](const FontListEntry& aFLE, const nsCString& aPSName, @@ -1382,17 +1387,15 @@ void gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive, // Called on each family after all fonts are added to the list; // if aSortFaces is true this will sort faces to give priority to "standard" // font files. -static void FinalizeFamilyMemberList(nsCStringHashKey::KeyType aKey, - const RefPtr& aFamily, - bool aSortFaces) { - gfxFontFamily* family = aFamily.get(); +void FT2FontFamily::FinalizeMemberList(bool aSortFaces) { + AutoWriteLock lock(mLock); - family->SetHasStyles(true); + SetHasStyles(true); if (aSortFaces) { - family->SortAvailableFonts(); + SortAvailableFonts(); } - family->CheckForSimpleFamily(); + CheckForSimpleFamily(); } void gfxFT2FontList::FindFonts() { @@ -1640,6 +1643,7 @@ void gfxFT2FontList::AppendFaceFromFontListEntry(const FontListEntry& aFLE, } void gfxFT2FontList::ReadSystemFontList(dom::SystemFontList* aList) { + AutoLock lock(mLock); for (const auto& entry : mFontFamilies) { auto family = static_cast(entry.GetData().get()); family->AddFacesToFontList(&aList->entries()); @@ -1669,9 +1673,8 @@ nsresult gfxFT2FontList::InitFontListForPlatform() { // Finalize the families by sorting faces into standard order // and marking "simple" families. for (const auto& entry : mFontFamilies) { - nsCStringHashKey::KeyType key = entry.GetKey(); - const RefPtr& family = entry.GetData(); - FinalizeFamilyMemberList(key, family, /* aSortFaces */ true); + auto* family = static_cast(entry.GetData().get()); + family->FinalizeMemberList(/* aSortFaces */ true); } return NS_OK; @@ -1689,9 +1692,8 @@ nsresult gfxFT2FontList::InitFontListForPlatform() { // We don't need to sort faces (because they were already sorted by the // chrome process, so we just maintain the existing order) for (const auto& entry : mFontFamilies) { - nsCStringHashKey::KeyType key = entry.GetKey(); - const RefPtr& family = entry.GetData(); - FinalizeFamilyMemberList(key, family, /* aSortFaces */ false); + auto* family = static_cast(entry.GetData().get()); + family->FinalizeMemberList(/* aSortFaces */ false); } LOG(("got font list from chrome process: %" PRIdPTR " faces in %" PRIu32 @@ -1747,10 +1749,13 @@ gfxFontEntry* gfxFT2FontList::LookupLocalFont(nsPresContext* aPresContext, WeightRange aWeightForEntry, StretchRange aStretchForEntry, SlantStyleRange aStyleForEntry) { + AutoLock lock(mLock); + if (SharedFontList()) { return LookupInSharedFaceNameList(aPresContext, aFontName, aWeightForEntry, aStretchForEntry, aStyleForEntry); } + // walk over list of names FT2FontEntry* fontEntry = nullptr; FontVisibility level = diff --git a/gfx/thebes/gfxFT2FontList.h b/gfx/thebes/gfxFT2FontList.h index 890aa83a35a7..66933edb6834 100644 --- a/gfx/thebes/gfxFT2FontList.h +++ b/gfx/thebes/gfxFT2FontList.h @@ -128,6 +128,8 @@ class FT2FontFamily final : public gfxFontFamily { // Append this family's faces to the IPC fontlist void AddFacesToFontList(nsTArray* aFontList); + + void FinalizeMemberList(bool aSortFaces); }; class gfxFT2FontList final : public gfxPlatformFontList { @@ -172,23 +174,26 @@ class gfxFT2FontList final : public gfxPlatformFontList { typedef enum { kUnknown, kStandard } StandardFile; // initialize font lists - nsresult InitFontListForPlatform() override; + nsresult InitFontListForPlatform() REQUIRES(mLock) override; void AppendFaceFromFontListEntry(const FontListEntry& aFLE, - StandardFile aStdFile); + StandardFile aStdFile) REQUIRES(mLock); void AppendFacesFromBlob(const nsCString& aFileName, StandardFile aStdFile, hb_blob_t* aBlob, FontNameCache* aCache, - uint32_t aTimestamp, uint32_t aFilesize); + uint32_t aTimestamp, uint32_t aFilesize) + REQUIRES(mLock); void AppendFacesFromFontFile(const nsCString& aFileName, - FontNameCache* aCache, StandardFile aStdFile); + FontNameCache* aCache, StandardFile aStdFile) + REQUIRES(mLock); void AppendFacesFromOmnijarEntry(nsZipArchive* aReader, const nsCString& aEntryName, - FontNameCache* aCache, bool aJarChanged); + FontNameCache* aCache, bool aJarChanged) + REQUIRES(mLock); - void InitSharedFontListForPlatform() override; + void InitSharedFontListForPlatform() REQUIRES(mLock) override; void CollectInitData(const FontListEntry& aFLE, const nsCString& aPSName, const nsCString& aFullName, StandardFile aStdFile); @@ -212,21 +217,23 @@ class gfxFT2FontList final : public gfxPlatformFontList { bool AppendFacesFromCachedFaceList(CollectFunc aCollectFace, const nsCString& aFileName, const nsCString& aFaceList, - StandardFile aStdFile); + StandardFile aStdFile) REQUIRES(mLock); void AddFaceToList(const nsCString& aEntryName, uint32_t aIndex, StandardFile aStdFile, hb_face_t* aFace, - nsCString& aFaceList); + nsCString& aFaceList) REQUIRES(mLock); - void FindFonts(); + void FindFonts() REQUIRES(mLock); - void FindFontsInOmnijar(FontNameCache* aCache); + void FindFontsInOmnijar(FontNameCache* aCache) REQUIRES(mLock); - void FindFontsInDir(const nsCString& aDir, FontNameCache* aFNC); + void FindFontsInDir(const nsCString& aDir, FontNameCache* aFNC) + REQUIRES(mLock); FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext, const gfxFontStyle* aStyle, - nsAtom* aLanguage = nullptr) override; + nsAtom* aLanguage = nullptr) + REQUIRES(mLock) override; nsTHashSet mSkipSpaceLookupCheckFamilies; diff --git a/gfx/thebes/gfxFcPlatformFontList.cpp b/gfx/thebes/gfxFcPlatformFontList.cpp index eea764ef5935..d100df915751 100644 --- a/gfx/thebes/gfxFcPlatformFontList.cpp +++ b/gfx/thebes/gfxFcPlatformFontList.cpp @@ -1015,7 +1015,8 @@ nsresult gfxFontconfigFontEntry::CopyFontTable(uint32_t aTableTag, return gfxFT2FontEntryBase::CopyFaceTable(GetFTFace(), aTableTag, aBuffer); } -void gfxFontconfigFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) { +void gfxFontconfigFontFamily::FindStyleVariationsLocked( + FontInfoData* aFontInfoData) { if (mHasStyles) { return; } @@ -1039,7 +1040,7 @@ void gfxFontconfigFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) { fontEntry->SetupVariationRanges(); } - AddFontEntry(fontEntry); + AddFontEntryLocked(fontEntry); if (fontEntry->IsNormalStyle()) { numRegularFaces++; @@ -1226,6 +1227,7 @@ bool gfxFontconfigFontFamily::SupportsLangGroup(nsAtom* aLangGroup) const { // will contain the font entries, each of which holds a reference to its // pattern. We only check the first pattern in each list, because support // for langs is considered to be consistent across all faces in a family. + AutoReadLock lock(mLock); FcPattern* fontPattern; if (mFontPatterns.Length()) { fontPattern = mFontPatterns[0]; @@ -1248,6 +1250,7 @@ gfxFontconfigFontFamily::~gfxFontconfigFontFamily() { template void gfxFontconfigFontFamily::AddFacesToFontList(Func aAddPatternFunc) { + AutoReadLock lock(mLock); if (HasStyles()) { for (auto& fe : mAvailableFonts) { if (!fe) { @@ -1431,14 +1434,17 @@ void gfxFcPlatformFontList::AddPatternToFontList( // will usually not match FcChar8* otherName; int n = (cIndex == 0 ? 1 : 0); + AutoTArray otherFamilyNames; while (FcPatternGetString(aFont, FC_FAMILY, n, &otherName) == FcResultMatch) { - nsAutoCString otherFamilyName(ToCharPtr(otherName)); - AddOtherFamilyName(aFontFamily, otherFamilyName); + otherFamilyNames.AppendElement(nsCString(ToCharPtr(otherName))); n++; if (n == int(cIndex)) { n++; // skip over canonical name } } + if (!otherFamilyNames.IsEmpty()) { + AddOtherFamilyNames(aFontFamily, otherFamilyNames); + } const bool singleName = n == 1; @@ -1576,6 +1582,8 @@ nsresult gfxFcPlatformFontList::InitFontListForPlatform() { } void gfxFcPlatformFontList::ReadSystemFontList(dom::SystemFontList* retValue) { + AutoLock lock(mLock); + // Fontconfig versions below 2.9 drop the FC_FILE element in FcNameUnparse // (see https://bugs.freedesktop.org/show_bug.cgi?id=26718), so when using // an older version, we manually append it to the unparsed pattern. @@ -2039,6 +2047,8 @@ gfxFontEntry* gfxFcPlatformFontList::LookupLocalFont( nsPresContext* aPresContext, const nsACString& aFontName, WeightRange aWeightForEntry, StretchRange aStretchForEntry, SlantStyleRange aStyleForEntry) { + AutoLock lock(mLock); + nsAutoCString keyName(aFontName); ToLowerCase(keyName); @@ -2071,7 +2081,7 @@ gfxFontEntry* gfxFcPlatformFontList::MakePlatformFont( std::move(face)); } -bool gfxFcPlatformFontList::FindAndAddFamilies( +bool gfxFcPlatformFontList::FindAndAddFamiliesLocked( nsPresContext* aPresContext, StyleGenericFontFamily aGeneric, const nsACString& aFamily, nsTArray* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage, @@ -2184,7 +2194,7 @@ bool gfxFcPlatformFontList::FindAndAddFamilies( if (terminator && FcStrCmp(substName, terminator) == 0) { break; } - gfxPlatformFontList::FindAndAddFamilies( + gfxPlatformFontList::FindAndAddFamiliesLocked( aPresContext, aGeneric, nsDependentCString(ToCharPtr(substName)), &cachedFamilies, aFlags, aStyle, aLanguage); } @@ -2340,6 +2350,7 @@ void gfxFcPlatformFontList::AddGenericFonts( } } + AutoLock lock(mLock); PrefFontList* prefFonts = FindGenericFamilies(aPresContext, genericToLookup, aLanguage); NS_ASSERTION(prefFonts, "null generic font list"); @@ -2349,9 +2360,9 @@ void gfxFcPlatformFontList::AddGenericFonts( } } -void gfxFcPlatformFontList::ClearLangGroupPrefFonts() { - ClearGenericMappings(); - gfxPlatformFontList::ClearLangGroupPrefFonts(); +void gfxFcPlatformFontList::ClearLangGroupPrefFontsLocked() { + ClearGenericMappingsLocked(); + gfxPlatformFontList::ClearLangGroupPrefFontsLocked(); mAlwaysUseFontconfigGenerics = PrefFontListsUseOnlyGenerics(); } @@ -2411,9 +2422,10 @@ gfxPlatformFontList::PrefFontList* gfxFcPlatformFontList::FindGenericFamilies( FcPatternGetString(font, FC_FAMILY, 0, &mappedGeneric); if (mappedGeneric) { + mLock.AssertCurrentThreadIn(); nsAutoCString mappedGenericName(ToCharPtr(mappedGeneric)); AutoTArray genericFamilies; - if (gfxPlatformFontList::FindAndAddFamilies( + if (gfxPlatformFontList::FindAndAddFamiliesLocked( aPresContext, StyleGenericFontFamily::None, mappedGenericName, &genericFamilies, FindFamiliesFlags(0))) { diff --git a/gfx/thebes/gfxFcPlatformFontList.h b/gfx/thebes/gfxFcPlatformFontList.h index 3e592ddc88b8..90f62a47d6d9 100644 --- a/gfx/thebes/gfxFcPlatformFontList.h +++ b/gfx/thebes/gfxFcPlatformFontList.h @@ -175,7 +175,8 @@ class gfxFontconfigFontFamily final : public gfxFontFamily { template void AddFacesToFontList(Func aAddPatternFunc); - void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) override; + void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr) + REQUIRES(mLock) override; // Families are constructed initially with just references to patterns. // When necessary, these are enumerated within FindStyleVariations. @@ -244,8 +245,8 @@ class gfxFcPlatformFontList final : public gfxPlatformFontList { } // initialize font lists - nsresult InitFontListForPlatform() override; - void InitSharedFontListForPlatform() override; + nsresult InitFontListForPlatform() REQUIRES(mLock) override; + void InitSharedFontListForPlatform() REQUIRES(mLock) override; void GetFontList(nsAtom* aLangGroup, const nsACString& aGenericFamily, nsTArray& aListOfFonts) override; @@ -269,11 +270,12 @@ class gfxFcPlatformFontList final : public gfxPlatformFontList { const uint8_t* aFontData, uint32_t aLength) override; - bool FindAndAddFamilies( + bool FindAndAddFamiliesLocked( nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric, const nsACString& aFamily, nsTArray* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr, - nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0) override; + nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0) + REQUIRES(mLock) override; bool GetStandardFamilyName(const nsCString& aFontName, nsACString& aFamilyName) override; @@ -285,10 +287,16 @@ class gfxFcPlatformFontList final : public gfxPlatformFontList { mozilla::StyleGenericFontFamily, nsAtom* aLanguage, nsTArray& aFamilyList) override; - void ClearLangGroupPrefFonts() override; + void ClearLangGroupPrefFontsLocked() REQUIRES(mLock) override; // clear out cached generic-lang ==> family-list mappings - void ClearGenericMappings() { mGenericMappings.Clear(); } + void ClearGenericMappings() { + AutoLock lock(mLock); + ClearGenericMappingsLocked(); + } + void ClearGenericMappingsLocked() REQUIRES(mLock) { + mGenericMappings.Clear(); + } // map lang group ==> lang string // When aForFontEnumerationThread is true, this method will avoid using @@ -310,28 +318,29 @@ class gfxFcPlatformFontList final : public gfxPlatformFontList { // Add all the font families found in a font set. // aAppFonts indicates whether this is the system or application fontset. void AddFontSetFamilies(FcFontSet* aFontSet, const SandboxPolicy* aPolicy, - bool aAppFonts); + bool aAppFonts) REQUIRES(mLock); // Helper for above, to add a single font pattern. void AddPatternToFontList(FcPattern* aFont, FcChar8*& aLastFamilyName, nsACString& aFamilyName, RefPtr& aFontFamily, - bool aAppFonts); + bool aAppFonts) REQUIRES(mLock); // figure out which families fontconfig maps a generic to // (aGeneric assumed already lowercase) PrefFontList* FindGenericFamilies(nsPresContext* aPresContext, const nsCString& aGeneric, - nsAtom* aLanguage); + nsAtom* aLanguage) REQUIRES(mLock); // are all pref font settings set to use fontconfig generics? - bool PrefFontListsUseOnlyGenerics(); + bool PrefFontListsUseOnlyGenerics() REQUIRES(mLock); static void CheckFontUpdates(nsITimer* aTimer, void* aThis); FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext, const gfxFontStyle* aStyle, - nsAtom* aLanguage = nullptr) override; + nsAtom* aLanguage = nullptr) + REQUIRES(mLock) override; enum class DistroID : int8_t { Unknown = 0, diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 0e18237dd19d..93458f889a10 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -234,7 +234,7 @@ bool gfxFontCache::HashEntry::KeyEquals(const KeyTypePointer aKey) const { gfxFont* gfxFontCache::Lookup(const gfxFontEntry* aFontEntry, const gfxFontStyle* aStyle, const gfxCharacterMap* aUnicodeRangeMap) { - AutoReadLock lock(mCacheLock); + MutexAutoLock lock(mMutex); Key key(aFontEntry, aStyle, aUnicodeRangeMap); HashEntry* entry = mFonts.GetEntry(key); @@ -247,7 +247,7 @@ gfxFont* gfxFontCache::Lookup(const gfxFontEntry* aFontEntry, void gfxFontCache::AddNew(gfxFont* aFont) { gfxFont* oldFont; { - AutoWriteLock lock(mCacheLock); + MutexAutoLock lock(mMutex); Key key(aFont->GetFontEntry(), aFont->GetStyle(), aFont->GetUnicodeRangeMap()); @@ -287,7 +287,7 @@ void gfxFontCache::NotifyReleased(gfxFont* aFont) { void gfxFontCache::NotifyExpiredLocked(gfxFont* aFont, const AutoLock& aLock) { aFont->ClearCachedWords(); RemoveObjectLocked(aFont, aLock); - DestroyFont(aFont); + DestroyFontLocked(aFont); } void gfxFontCache::NotifyExpired(gfxFont* aFont) { @@ -296,14 +296,29 @@ void gfxFontCache::NotifyExpired(gfxFont* aFont) { DestroyFont(aFont); } -void gfxFontCache::DestroyFont(gfxFont* aFont) { - AutoWriteLock lock(mCacheLock); +void gfxFontCache::DestroyFontLocked(gfxFont* aFont) { Key key(aFont->GetFontEntry(), aFont->GetStyle(), aFont->GetUnicodeRangeMap()); HashEntry* entry = mFonts.GetEntry(key); if (entry && entry->mFont == aFont) { mFonts.RemoveEntry(entry); } + NS_ASSERTION(aFont->GetRefCount() == 0, + "Destroying with non-zero ref count!"); + MutexAutoUnlock unlock(mMutex); + delete aFont; +} + +void gfxFontCache::DestroyFont(gfxFont* aFont) { + { + MutexAutoLock lock(mMutex); + Key key(aFont->GetFontEntry(), aFont->GetStyle(), + aFont->GetUnicodeRangeMap()); + HashEntry* entry = mFonts.GetEntry(key); + if (entry && entry->mFont == aFont) { + mFonts.RemoveEntry(entry); + } + } NS_ASSERTION(aFont->GetRefCount() == 0, "Destroying with non-zero ref count!"); delete aFont; @@ -319,7 +334,7 @@ void gfxFontCache::WordCacheExpirationTimerCallback(nsITimer* aTimer, void gfxFontCache::AgeCachedWords() { bool allEmpty = true; { - AutoReadLock lock(mCacheLock); + MutexAutoLock lock(mMutex); for (const auto& entry : mFonts) { allEmpty = entry.mFont->AgeCachedWords() && allEmpty; } @@ -331,7 +346,7 @@ void gfxFontCache::AgeCachedWords() { void gfxFontCache::FlushShapedWordCaches() { { - AutoReadLock lock(mCacheLock); + MutexAutoLock lock(mMutex); for (const auto& entry : mFonts) { entry.mFont->ClearCachedWords(); } @@ -340,7 +355,7 @@ void gfxFontCache::FlushShapedWordCaches() { } void gfxFontCache::NotifyGlyphsChanged() { - AutoReadLock lock(mCacheLock); + MutexAutoLock lock(mMutex); for (const auto& entry : mFonts) { entry.mFont->NotifyGlyphsChanged(); } @@ -350,7 +365,7 @@ void gfxFontCache::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, FontCacheSizes* aSizes) const { // TODO: add the overhead of the expiration tracker (generation arrays) - AutoReadLock lock(mCacheLock); + MutexAutoLock lock(*const_cast(&mMutex)); aSizes->mFontInstances += mFonts.ShallowSizeOfExcludingThis(aMallocSizeOf); for (const auto& entry : mFonts) { entry.mFont->AddSizeOfExcludingThis(aMallocSizeOf, aSizes); diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index c72a7b65c4c4..e28796cc72b2 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -348,7 +348,7 @@ class gfxFontCache final // into the expiration queues and removed. void Flush() { { - mozilla::AutoWriteLock lock(mCacheLock); + mozilla::MutexAutoLock lock(mMutex); mFonts.Clear(); } AgeAllGenerations(); @@ -361,7 +361,7 @@ class gfxFontCache final void RunWordCacheExpirationTimer() { if (!mTimerRunning) { - mozilla::AutoWriteLock lock(mCacheLock); + mozilla::MutexAutoLock lock(mMutex); if (!mTimerRunning && mWordCacheExpirationTimer) { mWordCacheExpirationTimer->InitWithNamedFuncCallback( WordCacheExpirationTimerCallback, this, @@ -373,7 +373,7 @@ class gfxFontCache final } void PauseWordCacheExpirationTimer() { if (mTimerRunning) { - mozilla::AutoWriteLock lock(mCacheLock); + mozilla::MutexAutoLock lock(mMutex); if (mTimerRunning && mWordCacheExpirationTimer) { mWordCacheExpirationTimer->Cancel(); mTimerRunning = false; @@ -396,13 +396,7 @@ class gfxFontCache final RemoveObjectLocked(aFont, lock); } - mozilla::RWLock& GetCacheLock() { return mCacheLock; } - protected: - // Guards the global font hashtable, separately from the expiration-tracker - // records. - mutable mozilla::RWLock mCacheLock = mozilla::RWLock("fontCacheLock"); - class MemoryReporter final : public nsIMemoryReporter { ~MemoryReporter() = default; @@ -427,10 +421,12 @@ class gfxFontCache final // This gets called when the timeout has expired on a zero-refcount // font; we just delete it. - void NotifyExpiredLocked(gfxFont* aFont, const AutoLock&) override; + void NotifyExpiredLocked(gfxFont* aFont, const AutoLock&) + REQUIRES(mMutex) override; void NotifyExpired(gfxFont* aFont); void DestroyFont(gfxFont* aFont); + void DestroyFontLocked(gfxFont* aFont) REQUIRES(mMutex); static gfxFontCache* gGlobalCache; @@ -469,11 +465,11 @@ class gfxFontCache final gfxFont* MOZ_UNSAFE_REF("tracking for deferred deletion") mFont; }; - nsTHashtable mFonts GUARDED_BY(mCacheLock); + nsTHashtable mFonts GUARDED_BY(mMutex); static void WordCacheExpirationTimerCallback(nsITimer* aTimer, void* aCache); - nsCOMPtr mWordCacheExpirationTimer GUARDED_BY(mCacheLock); + nsCOMPtr mWordCacheExpirationTimer GUARDED_BY(mMutex); std::atomic mTimerRunning = false; }; diff --git a/gfx/thebes/gfxFontEntry.cpp b/gfx/thebes/gfxFontEntry.cpp index 345a7c7b2518..d0f1ba95080a 100644 --- a/gfx/thebes/gfxFontEntry.cpp +++ b/gfx/thebes/gfxFontEntry.cpp @@ -56,9 +56,8 @@ using namespace mozilla::unicode; using mozilla::services::GetObserverService; void gfxCharacterMap::NotifyReleased() { - gfxPlatformFontList* fontlist = gfxPlatformFontList::PlatformFontList(); if (mShared) { - fontlist->RemoveCmap(this); + gfxPlatformFontList::PlatformFontList()->RemoveCmap(this); } delete this; } @@ -1541,12 +1540,14 @@ class FontEntryStandardFaceComparator { }; void gfxFontFamily::SortAvailableFonts() { + MOZ_ASSERT(mLock.LockedForWritingByCurrentThread()); mAvailableFonts.Sort(FontEntryStandardFaceComparator()); } bool gfxFontFamily::HasOtherFamilyNames() { // need to read in other family names to determine this if (!mOtherFamilyNamesInitialized) { + AutoWriteLock lock(mLock); ReadOtherFamilyNames( gfxPlatformFontList::PlatformFontList()); // sets mHasOtherFamilyNames } @@ -1588,9 +1589,12 @@ void gfxFontFamily::FindAllFontsForStyle( const gfxFontStyle& aFontStyle, nsTArray& aFontEntryList, bool aIgnoreSizeTolerance) { if (!mHasStyles) { - FindStyleVariations(); // collect faces for the family, if not already done + FindStyleVariations(); // collect faces for the family, if not already + // done } + AutoReadLock lock(mLock); + NS_ASSERTION(mAvailableFonts.Length() > 0, "font family with no faces!"); NS_ASSERTION(aFontEntryList.IsEmpty(), "non-empty fontlist passed in"); @@ -1696,6 +1700,7 @@ void gfxFontFamily::FindAllFontsForStyle( } void gfxFontFamily::CheckForSimpleFamily() { + MOZ_ASSERT(mLock.LockedForWritingByCurrentThread()); // already checked this family if (mIsSimpleFamily) { return; @@ -1749,6 +1754,8 @@ void gfxFontFamily::CheckForSimpleFamily() { #ifdef DEBUG bool gfxFontFamily::ContainsFace(gfxFontEntry* aFontEntry) { + AutoReadLock lock(mLock); + uint32_t i, numFonts = mAvailableFonts.Length(); for (i = 0; i < numFonts; i++) { if (mAvailableFonts[i] == aFontEntry) { @@ -1773,10 +1780,15 @@ void gfxFontFamily::LocalizedName(nsACString& aLocalizedName) { } void gfxFontFamily::FindFontForChar(GlobalFontMatch* aMatchData) { - if (mFamilyCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) { - // none of the faces in the family support the required char, - // so bail out immediately - return; + gfxPlatformFontList::PlatformFontList()->mLock.AssertCurrentThreadIn(); + + { + AutoReadLock lock(mLock); + if (mFamilyCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) { + // none of the faces in the family support the required char, + // so bail out immediately + return; + } } nsCString charAndName; @@ -1866,6 +1878,7 @@ void gfxFontFamily::SearchAllFontsForChar(GlobalFontMatch* aMatchData) { if (!mFamilyCharacterMapInitialized) { ReadAllCMAPs(); } + AutoReadLock lock(mLock); if (!mFamilyCharacterMap.test(aMatchData->mCh)) { return; } @@ -1914,20 +1927,27 @@ bool gfxFontFamily::ReadOtherFamilyNamesForFace( gfxFontUtils::ReadOtherFamilyNamesForFace(mName, nameData, dataLength, otherFamilyNames, useFullName); - uint32_t n = otherFamilyNames.Length(); - for (uint32_t i = 0; i < n; i++) { - aPlatformFontList->AddOtherFamilyName(this, otherFamilyNames[i]); + if (!otherFamilyNames.IsEmpty()) { + aPlatformFontList->AddOtherFamilyNames(this, otherFamilyNames); } - return n != 0; + return !otherFamilyNames.IsEmpty(); } void gfxFontFamily::ReadOtherFamilyNames( gfxPlatformFontList* aPlatformFontList) { - if (mOtherFamilyNamesInitialized) return; + if (mOtherFamilyNamesInitialized) { + return; + } + + AutoWriteLock lock(mLock); + if (mOtherFamilyNamesInitialized) { + return; + } + mOtherFamilyNamesInitialized = true; - FindStyleVariations(); + FindStyleVariationsLocked(); // read in other family names for the first face in the list uint32_t i, numFonts = mAvailableFonts.Length(); @@ -1950,7 +1970,9 @@ void gfxFontFamily::ReadOtherFamilyNames( // read in other names for the first face in the list with the assumption // that if extra names don't exist in that face then they don't exist in // other faces for the same font - if (!mHasOtherFamilyNames) return; + if (!mHasOtherFamilyNames) { + return; + } // read in names for all faces, needed to catch cases where fonts have // family names for individual weights (e.g. Hiragino Kaku Gothic Pro W6) @@ -2012,6 +2034,8 @@ bool gfxFontFamily::CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList) { // we already did this, so there's nothing more to add return false; } + aFontList->mLock.AssertCurrentThreadIn(); + AutoWriteLock lock(mLock); mCheckedForLegacyFamilyNames = true; bool added = false; const uint32_t kNAME = TRUETYPE_TAG('n', 'a', 'm', 'e'); @@ -2041,22 +2065,23 @@ bool gfxFontFamily::CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList) { void gfxFontFamily::ReadFaceNames(gfxPlatformFontList* aPlatformFontList, bool aNeedFullnamePostscriptNames, FontInfoData* aFontInfoData) { + aPlatformFontList->mLock.AssertCurrentThreadIn(); + // if all needed names have already been read, skip if (mOtherFamilyNamesInitialized && (mFaceNamesInitialized || !aNeedFullnamePostscriptNames)) { return; } + AutoWriteLock lock(mLock); + bool asyncFontLoaderDisabled = false; if (!mOtherFamilyNamesInitialized && aFontInfoData && aFontInfoData->mLoadOtherNames && !asyncFontLoaderDisabled) { const auto* otherFamilyNames = aFontInfoData->GetOtherFamilyNames(mName); - if (otherFamilyNames) { - uint32_t i, n = otherFamilyNames->Length(); - for (i = 0; i < n; i++) { - aPlatformFontList->AddOtherFamilyName(this, (*otherFamilyNames)[i]); - } + if (otherFamilyNames && otherFamilyNames->Length()) { + aPlatformFontList->AddOtherFamilyNames(this, *otherFamilyNames); } mOtherFamilyNamesInitialized = true; } @@ -2067,7 +2092,7 @@ void gfxFontFamily::ReadFaceNames(gfxPlatformFontList* aPlatformFontList, return; } - FindStyleVariations(aFontInfoData); + FindStyleVariationsLocked(aFontInfoData); // check again, as style enumeration code may have loaded names if (mOtherFamilyNamesInitialized && @@ -2091,10 +2116,10 @@ void gfxFontFamily::ReadFaceNames(gfxPlatformFontList* aPlatformFontList, aFontInfoData && aFontInfoData->mLoadFaceNames) { aFontInfoData->GetFaceNames(fe->Name(), fullname, psname); if (!fullname.IsEmpty()) { - aPlatformFontList->AddFullname(fe, fullname); + aPlatformFontList->AddFullnameLocked(fe, fullname); } if (!psname.IsEmpty()) { - aPlatformFontList->AddPostscriptName(fe, psname); + aPlatformFontList->AddPostscriptNameLocked(fe, psname); } foundFaceNames = true; @@ -2113,12 +2138,12 @@ void gfxFontFamily::ReadFaceNames(gfxPlatformFontList* aPlatformFontList, if (aNeedFullnamePostscriptNames && !foundFaceNames) { if (gfxFontUtils::ReadCanonicalName(nameTable, gfxFontUtils::NAME_ID_FULL, fullname) == NS_OK) { - aPlatformFontList->AddFullname(fe, fullname); + aPlatformFontList->AddFullnameLocked(fe, fullname); } if (gfxFontUtils::ReadCanonicalName( nameTable, gfxFontUtils::NAME_ID_POSTSCRIPT, psname) == NS_OK) { - aPlatformFontList->AddPostscriptName(fe, psname); + aPlatformFontList->AddPostscriptNameLocked(fe, psname); } } @@ -2147,16 +2172,20 @@ void gfxFontFamily::ReadFaceNames(gfxPlatformFontList* aPlatformFontList, gfxFontEntry* gfxFontFamily::FindFont(const nsACString& aPostscriptName) { // find the font using a simple linear search + AutoReadLock lock(mLock); uint32_t numFonts = mAvailableFonts.Length(); for (uint32_t i = 0; i < numFonts; i++) { gfxFontEntry* fe = mAvailableFonts[i].get(); - if (fe && fe->Name() == aPostscriptName) return fe; + if (fe && fe->Name() == aPostscriptName) { + return fe; + } } return nullptr; } void gfxFontFamily::ReadAllCMAPs(FontInfoData* aFontInfoData) { - FindStyleVariations(aFontInfoData); + AutoWriteLock lock(mLock); + FindStyleVariationsLocked(aFontInfoData); uint32_t i, numFonts = mAvailableFonts.Length(); for (i = 0; i < numFonts; i++) { @@ -2174,6 +2203,7 @@ void gfxFontFamily::ReadAllCMAPs(FontInfoData* aFontInfoData) { void gfxFontFamily::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const { + AutoReadLock lock(mLock); aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf); aSizes->mCharMapsSize += mFamilyCharacterMap.SizeOfExcludingThis(aMallocSizeOf); diff --git a/gfx/thebes/gfxFontEntry.h b/gfx/thebes/gfxFontEntry.h index 26d1391fe246..d86b4d9d19c9 100644 --- a/gfx/thebes/gfxFontEntry.h +++ b/gfx/thebes/gfxFontEntry.h @@ -790,10 +790,8 @@ class gfxFontEntry { }; using FontTableCache = nsTHashtable; - mozilla::Atomic mFontTableCache GUARDED_BY(mLock); - FontTableCache* GetFontTableCache() const NO_THREAD_SAFETY_ANALYSIS { - return mFontTableCache; - } + mozilla::Atomic mFontTableCache; + FontTableCache* GetFontTableCache() const { return mFontTableCache; } }; MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxFontEntry::RangeFlags) @@ -851,17 +849,12 @@ class gfxFontFamily { gfxFontFamily(const nsACString& aName, FontVisibility aVisibility) : mName(aName), + mLock("gfxFontFamily lock"), mVisibility(aVisibility), - mOtherFamilyNamesInitialized(false), - mHasOtherFamilyNames(false), - mFaceNamesInitialized(false), - mHasStyles(false), mIsSimpleFamily(false), mIsBadUnderlineFamily(false), - mFamilyCharacterMapInitialized(false), mSkipDefaultFeatureSpaceCheck(false), - mCheckForFallbackFaces(false), - mCheckedForLegacyFamilyNames(false) {} + mCheckForFallbackFaces(false) {} const nsCString& Name() const { return mName; } @@ -874,11 +867,20 @@ class gfxFontFamily { // faces in a large family into separate "styled families" because of // GDI's 4-faces-per-family limitation). If found, the styled family // name will be added to the font list's "other family names" table. + // Note that the caller must already hold the gfxPlatformFontList lock. bool CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList); - nsTArray>& GetFontList() { return mAvailableFonts; } + nsTArray>& GetFontList() { + mozilla::AutoReadLock lock(mLock); + return mAvailableFonts; + } void AddFontEntry(RefPtr aFontEntry) { + mozilla::AutoWriteLock lock(mLock); + AddFontEntryLocked(aFontEntry); + } + + void AddFontEntryLocked(RefPtr aFontEntry) REQUIRES(mLock) { // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces // of Times New Roman, because of buggy table in those fonts if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() && @@ -916,8 +918,10 @@ class gfxFontFamily { nsTArray& aFontEntryList, bool aIgnoreSizeTolerance = false); - // checks for a matching font within the family - // used as part of the font fallback process + // Checks for a matching font within the family; used as part of the font + // fallback process. + // Note that when this is called, the caller must already be holding the + // gfxPlatformFontList lock. void FindFontForChar(GlobalFontMatch* aMatchData); // checks all fonts for a matching font within the family @@ -929,36 +933,51 @@ class gfxFontFamily { // set when other family names have been read in void SetOtherFamilyNamesInitialized() { mOtherFamilyNamesInitialized = true; } - // read in other localized family names, fullnames and Postscript names - // for all faces and append to lookup tables + // Read in other localized family names, fullnames and Postscript names + // for all faces and append to lookup tables. + // Note that when this is called, the caller must already be holding the + // gfxPlatformFontList lock. virtual void ReadFaceNames(gfxPlatformFontList* aPlatformFontList, bool aNeedFullnamePostscriptNames, FontInfoData* aFontInfoData = nullptr); - // find faces belonging to this family (platform implementations override - // this; should be made pure virtual once all subclasses have been updated) - virtual void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) {} + // Find faces belonging to this family (platform implementations override). + // This is a no-op in cases where the family is explicitly populated by other + // means, rather than being asked to find its faces via system API. + virtual void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr) + REQUIRES(mLock){}; + void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) { + if (mHasStyles) { + return; + } + mozilla::AutoWriteLock lock(mLock); + FindStyleVariationsLocked(aFontInfoData); + } // search for a specific face using the Postscript name gfxFontEntry* FindFont(const nsACString& aPostscriptName); - // read in cmaps for all the faces + // Read in cmaps for all the faces. + // Note that when this is called, the caller must already be holding the + // gfxPlatformFontList lock. void ReadAllCMAPs(FontInfoData* aFontInfoData = nullptr); bool TestCharacterMap(uint32_t aCh) { if (!mFamilyCharacterMapInitialized) { ReadAllCMAPs(); } + mozilla::AutoReadLock lock(mLock); return mFamilyCharacterMap.test(aCh); } - void ResetCharacterMap() { + void ResetCharacterMap() REQUIRES(mLock) { mFamilyCharacterMap.reset(); mFamilyCharacterMapInitialized = false; } // mark this family as being in the "bad" underline offset blocklist void SetBadUnderlineFamily() { + mozilla::AutoWriteLock lock(mLock); mIsBadUnderlineFamily = true; if (mHasStyles) { SetBadUnderlineFonts(); @@ -971,12 +990,12 @@ class gfxFontFamily { bool CheckForFallbackFaces() const { return mCheckForFallbackFaces; } // sort available fonts to put preferred (standard) faces towards the end - void SortAvailableFonts(); + void SortAvailableFonts() REQUIRES(mLock); // check whether the family fits into the simple 4-face model, // so we can use simplified style-matching; // if so set the mIsSimpleFamily flag (defaults to False before we've checked) - void CheckForSimpleFamily(); + void CheckForSimpleFamily() REQUIRES(mLock); // For memory reporter virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, @@ -1019,31 +1038,33 @@ class gfxFontFamily { bool useFullName = false); // set whether this font family is in "bad" underline offset blocklist. - void SetBadUnderlineFonts() { - uint32_t i, numFonts = mAvailableFonts.Length(); - for (i = 0; i < numFonts; i++) { - if (mAvailableFonts[i]) { - mAvailableFonts[i]->mIsBadUnderlineFont = true; + void SetBadUnderlineFonts() REQUIRES(mLock) { + for (auto& f : mAvailableFonts) { + if (f) { + f->mIsBadUnderlineFont = true; } } } nsCString mName; - nsTArray> mAvailableFonts; - gfxSparseBitSet mFamilyCharacterMap; + nsTArray> mAvailableFonts GUARDED_BY(mLock); + gfxSparseBitSet mFamilyCharacterMap GUARDED_BY(mLock); + + mutable mozilla::RWLock mLock; FontVisibility mVisibility; - bool mOtherFamilyNamesInitialized : 1; - bool mHasOtherFamilyNames : 1; - bool mFaceNamesInitialized : 1; - bool mHasStyles : 1; - bool mIsSimpleFamily : 1; + mozilla::Atomic mOtherFamilyNamesInitialized; + mozilla::Atomic mFaceNamesInitialized; + mozilla::Atomic mHasStyles; + mozilla::Atomic mFamilyCharacterMapInitialized; + mozilla::Atomic mCheckedForLegacyFamilyNames; + mozilla::Atomic mHasOtherFamilyNames; + + bool mIsSimpleFamily : 1 GUARDED_BY(mLock); bool mIsBadUnderlineFamily : 1; - bool mFamilyCharacterMapInitialized : 1; bool mSkipDefaultFeatureSpaceCheck : 1; bool mCheckForFallbackFaces : 1; // check other faces for character - bool mCheckedForLegacyFamilyNames : 1; enum { // for "simple" families, the faces are stored in mAvailableFonts diff --git a/gfx/thebes/gfxFontInfoLoader.cpp b/gfx/thebes/gfxFontInfoLoader.cpp index 7684c798abdb..01394dda0b2d 100644 --- a/gfx/thebes/gfxFontInfoLoader.cpp +++ b/gfx/thebes/gfxFontInfoLoader.cpp @@ -143,14 +143,24 @@ void gfxFontInfoLoader::StartLoader(uint32_t aDelay) { return; } - NS_ASSERTION(!mFontInfo, "fontinfo should be null when starting font loader"); - // sanity check if (mState != stateInitial && mState != stateTimerOff && mState != stateTimerOnDelay) { CancelLoader(); } + // Create mFontInfo when we're initially called to set up the delay, rather + // than when called by the DelayedStartCallback, because on the initial call + // we know we'll be holding the gfxPlatformFontList lock. + if (!mFontInfo) { + mFontInfo = CreateFontInfoData(); + if (!mFontInfo) { + // The platform doesn't want anything loaded, so just bail out. + mState = stateTimerOff; + return; + } + } + AddShutdownObserver(); // Caller asked for a delay? ==> start async thread after a delay @@ -195,13 +205,6 @@ void gfxFontInfoLoader::StartLoader(uint32_t aDelay) { "Bug 1508626 - Initializing font loader after shutdown but " "before observer"); - mFontInfo = CreateFontInfoData(); - if (!mFontInfo) { - // The platform doesn't want anything loaded, so just bail out. - mState = stateTimerOff; - return; - } - // initialize InitLoader(); diff --git a/gfx/thebes/gfxGDIFontList.cpp b/gfx/thebes/gfxGDIFontList.cpp index dcd36893ada3..682f9baf3bc0 100644 --- a/gfx/thebes/gfxGDIFontList.cpp +++ b/gfx/thebes/gfxGDIFontList.cpp @@ -119,7 +119,9 @@ GDIFontEntry::GDIFontEntry(const nsACString& aFaceName, mStyleRange = aStyle; mWeightRange = aWeight; mStretchRange = aStretch; - if (IsType1()) mForceGDI = true; + if (IsType1()) { + mForceGDI = true; + } mIsDataUserFont = aUserFontData != nullptr; InitLogFont(aFaceName, aFontType); @@ -372,10 +374,8 @@ GDIFontEntry* GDIFontEntry::CreateFontEntry(const nsACString& aName, gfxUserFontData* aUserFontData) { // jtdfix - need to set charset, unicode ranges, pitch/family - GDIFontEntry* fe = new GDIFontEntry(aName, aFontType, aStyle, aWeight, - aStretch, aUserFontData); - - return fe; + return new GDIFontEntry(aName, aFontType, aStyle, aWeight, aStretch, + aUserFontData); } void GDIFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, @@ -454,9 +454,12 @@ int CALLBACK GDIFontFamily::FamilyAddStylesProc( SlantStyleRange(italicStyle), WeightRange(FontWeight(int32_t(logFont.lfWeight))), StretchRange(FontStretch::Normal()), nullptr); - if (!fe) return 1; + if (!fe) { + return 1; + } - ff->AddFontEntry(fe); + MOZ_ASSERT(ff->mLock.LockedForWritingByCurrentThread()); + ff->AddFontEntryLocked(fe); if (nmetrics->ntmFontSig.fsUsb[0] != 0x00000000 && nmetrics->ntmFontSig.fsUsb[1] != 0x00000000 && @@ -482,8 +485,10 @@ int CALLBACK GDIFontFamily::FamilyAddStylesProc( return 1; } -void GDIFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) { - if (mHasStyles) return; +void GDIFontFamily::FindStyleVariationsLocked(FontInfoData* aFontInfoData) { + if (mHasStyles) { + return; + } mHasStyles = true; HDC hdc = GetDC(nullptr); @@ -838,13 +843,11 @@ gfxFontEntry* gfxGDIFontList::MakePlatformFont(const nsACString& aFontName, return fe; } -bool gfxGDIFontList::FindAndAddFamilies(nsPresContext* aPresContext, - StyleGenericFontFamily aGeneric, - const nsACString& aFamily, - nsTArray* aOutput, - FindFamiliesFlags aFlags, - gfxFontStyle* aStyle, nsAtom* aLanguage, - gfxFloat aDevToCssSize) { +bool gfxGDIFontList::FindAndAddFamiliesLocked( + nsPresContext* aPresContext, StyleGenericFontFamily aGeneric, + const nsACString& aFamily, nsTArray* aOutput, + FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage, + gfxFloat aDevToCssSize) { NS_ConvertUTF8toUTF16 key16(aFamily); BuildKeyNameFromFontName(key16); NS_ConvertUTF16toUTF8 keyName(key16); @@ -861,7 +864,7 @@ bool gfxGDIFontList::FindAndAddFamilies(nsPresContext* aPresContext, return false; } - return gfxPlatformFontList::FindAndAddFamilies( + return gfxPlatformFontList::FindAndAddFamiliesLocked( aPresContext, aGeneric, aFamily, aOutput, aFlags, aStyle, aLanguage, aDevToCssSize); } @@ -897,6 +900,9 @@ FontFamily gfxGDIFontList::GetDefaultFontForPlatform( void gfxGDIFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const { gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes); + + AutoLock lock(mLock); + aSizes->mFontListSize += SizeOfFontFamilyTableExcludingThis(mFontSubstitutes, aMallocSizeOf); aSizes->mFontListSize += diff --git a/gfx/thebes/gfxGDIFontList.h b/gfx/thebes/gfxGDIFontList.h index f8bc48119d16..a7f0eb16dd73 100644 --- a/gfx/thebes/gfxGDIFontList.h +++ b/gfx/thebes/gfxGDIFontList.h @@ -193,7 +193,8 @@ class GDIFontFamily final : public gfxFontFamily { mWindowsPitch(0), mCharset() {} - virtual void FindStyleVariations(FontInfoData* aFontInfoData = nullptr); + void FindStyleVariationsLocked( + FontInfoData* aFontInfoData = nullptr) override; bool FilterForFontList(nsAtom* aLangGroup, const nsACString& aGeneric) const final { @@ -304,7 +305,7 @@ class gfxGDIFontList final : public gfxPlatformFontList { gfxFontFamily* CreateFontFamily(const nsACString& aName, FontVisibility aVisibility) const override; - bool FindAndAddFamilies( + bool FindAndAddFamiliesLocked( nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric, const nsACString& aFamily, nsTArray* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr, diff --git a/gfx/thebes/gfxMacPlatformFontList.h b/gfx/thebes/gfxMacPlatformFontList.h index 1201224cbb10..fc7dbd072894 100644 --- a/gfx/thebes/gfxMacPlatformFontList.h +++ b/gfx/thebes/gfxMacPlatformFontList.h @@ -140,11 +140,12 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList { const uint8_t* aFontData, uint32_t aLength) override; - bool FindAndAddFamilies( + bool FindAndAddFamiliesLocked( nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric, const nsACString& aFamily, nsTArray* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr, - nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0) override; + nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0) + REQUIRES(mLock) override; // lookup the system font for a particular system font type and set // the name and style characteristics @@ -163,7 +164,8 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList { protected: FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext, const gfxFontStyle* aStyle, - nsAtom* aLanguage = nullptr) override; + nsAtom* aLanguage = nullptr) + REQUIRES(mLock) override; private: friend class gfxPlatformMac; @@ -172,22 +174,23 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList { virtual ~gfxMacPlatformFontList(); // initialize font lists - nsresult InitFontListForPlatform() override; - void InitSharedFontListForPlatform() override; + nsresult InitFontListForPlatform() REQUIRES(mLock) override; + void InitSharedFontListForPlatform() REQUIRES(mLock) override; // handle commonly used fonts for which the name table should be loaded at // startup - void PreloadNamesList(); + void PreloadNamesList() REQUIRES(mLock); // special case font faces treated as font families (set via prefs) - void InitSingleFaceList(); - void InitAliasesForSingleFaceList(); + void InitSingleFaceList() REQUIRES(mLock); + void InitAliasesForSingleFaceList() REQUIRES(mLock); // initialize system fonts - void InitSystemFontNames(); + void InitSystemFontNames() REQUIRES(mLock); // helper function to lookup in both hidden system fonts and normal fonts - gfxFontFamily* FindSystemFontFamily(const nsACString& aFamily); + gfxFontFamily* FindSystemFontFamily(const nsACString& aFamily) + REQUIRES(mLock); FontVisibility GetVisibilityForFamily(const nsACString& aName) const; @@ -201,7 +204,8 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList { const uint32_t aCh, Script aRunScript, const gfxFontStyle* aMatchStyle, - FontFamily& aMatchedFamily) override; + FontFamily& aMatchedFamily) + REQUIRES(mLock) override; bool UsesSystemFallback() override { return true; } @@ -212,9 +216,10 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList { // file is included in .cpp files, so we can't use objective C classes here. // But CFStringRef and NSString* are the same thing anyway (they're // toll-free bridged). - void AddFamily(CFStringRef aFamily); + void AddFamily(CFStringRef aFamily) REQUIRES(mLock); - void AddFamily(const nsACString& aFamilyName, FontVisibility aVisibility); + void AddFamily(const nsACString& aFamilyName, FontVisibility aVisibility) + REQUIRES(mLock); gfxFontEntry* CreateFontEntry( mozilla::fontlist::Face* aFace, @@ -226,7 +231,8 @@ class gfxMacPlatformFontList final : public gfxPlatformFontList { bool aLoadCmaps) const override; void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily, - bool aNeedFullnamePostscriptNames) override; + bool aNeedFullnamePostscriptNames) + REQUIRES(mLock) override; enum { kATSGenerationInitial = -1 }; diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm index 34f8e470b427..5db303334af0 100644 --- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -583,14 +583,14 @@ void MacOSFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, class gfxMacFontFamily final : public gfxFontFamily { public: - gfxMacFontFamily(const nsACString& aName, FontVisibility aVisibility, double aSizeHint) + gfxMacFontFamily(const nsACString& aName, FontVisibility aVisibility, double aSizeHint = 0.0) : gfxFontFamily(aName, aVisibility), mSizeHint(aSizeHint) {} virtual ~gfxMacFontFamily() = default; - virtual void LocalizedName(nsACString& aLocalizedName); + void LocalizedName(nsACString& aLocalizedName) override; - virtual void FindStyleVariations(FontInfoData* aFontInfoData = nullptr); + void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr) REQUIRES(mLock) override; protected: double mSizeHint; @@ -634,7 +634,7 @@ static inline int GetWeightOverride(const nsAString& aPSName) { return Preferences::GetInt(prefName.get(), 0); } -void gfxMacFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) { +void gfxMacFontFamily::FindStyleVariationsLocked(FontInfoData* aFontInfoData) { if (mHasStyles) { return; } @@ -735,7 +735,7 @@ void gfxMacFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) { } // insert into font entry array of family - AddFontEntry(fontEntry); + AddFontEntryLocked(fontEntry); } SortAvailableFonts(); @@ -760,16 +760,20 @@ class gfxSingleFaceMacFontFamily final : public gfxFontFamily { virtual ~gfxSingleFaceMacFontFamily() = default; - virtual void LocalizedName(nsACString& aLocalizedName); + void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr) REQUIRES(mLock) override{}; - virtual void ReadOtherFamilyNames(gfxPlatformFontList* aPlatformFontList); + void LocalizedName(nsACString& aLocalizedName) override; - virtual bool IsSingleFaceFamily() const { return true; } + void ReadOtherFamilyNames(gfxPlatformFontList* aPlatformFontList) override; + + bool IsSingleFaceFamily() const override { return true; } }; void gfxSingleFaceMacFontFamily::LocalizedName(nsACString& aLocalizedName) { nsAutoreleasePool localPool; + AutoReadLock lock(mLock); + if (!HasOtherFamilyNames()) { aLocalizedName = mName; return; @@ -797,6 +801,7 @@ void gfxSingleFaceMacFontFamily::ReadOtherFamilyNames(gfxPlatformFontList* aPlat return; } + AutoWriteLock lock(mLock); gfxFontEntry* fe = mAvailableFonts[0]; if (!fe) { return; @@ -888,7 +893,8 @@ void gfxMacPlatformFontList::AddFamily(CFStringRef aFamily) { AddFamily(nameUtf8, GetVisibilityForFamily(nameUtf8)); } -void gfxMacPlatformFontList::ReadSystemFontList(dom::SystemFontList* aList) { +void gfxMacPlatformFontList::ReadSystemFontList(dom::SystemFontList* aList) + NO_THREAD_SAFETY_ANALYSIS { // Note: We rely on the records for mSystemTextFontFamilyName and // mSystemDisplayFontFamilyName (if present) being *before* the main // font list, so that those names are known in the content process @@ -1203,7 +1209,7 @@ static NSString* GetRealFamilyName(NSFont* aFont) { // so we expect the system font to be a variable-weight face rather than requiring // a number of discrete faces of different weights. static gfxFontFamily* CreateFamilyForSystemFont(NSFont* aFont, const nsACString& aFamilyName) { - gfxFontFamily* familyEntry = new gfxFontFamily(aFamilyName, FontVisibility::Unknown); + gfxFontFamily* familyEntry = new gfxMacFontFamily(aFamilyName, FontVisibility::Unknown); NSString* psNameNS = [[aFont fontDescriptor] postscriptName]; nsAutoString nameUTF16; @@ -1366,7 +1372,7 @@ gfxFontEntry* gfxMacPlatformFontList::PlatformGlobalFontFallback(nsPresContext* if (family) { fontlist::Face* face = family->FindFaceForStyle(SharedFontList(), *aMatchStyle); if (face) { - fontEntry = GetOrCreateFontEntry(face, family); + fontEntry = GetOrCreateFontEntryLocked(face, family); } if (fontEntry) { if (fontEntry->HasCharacter(aCh)) { @@ -1437,6 +1443,8 @@ gfxFontEntry* gfxMacPlatformFontList::LookupLocalFont(nsPresContext* aPresContex return nullptr; } + AutoLock lock(mLock); + nsAutoreleasePool localPool; NSString* faceName = GetNSStringForString(NS_ConvertUTF8toUTF16(aFontName)); @@ -1521,12 +1529,10 @@ gfxFontEntry* gfxMacPlatformFontList::MakePlatformFont(const nsACString& aFontNa // WebCore/platform/graphics/mac/FontCacheMac.mm static const char kSystemFont_system[] = "-apple-system"; -bool gfxMacPlatformFontList::FindAndAddFamilies(nsPresContext* aPresContext, - StyleGenericFontFamily aGeneric, - const nsACString& aFamily, - nsTArray* aOutput, - FindFamiliesFlags aFlags, gfxFontStyle* aStyle, - nsAtom* aLanguage, gfxFloat aDevToCssSize) { +bool gfxMacPlatformFontList::FindAndAddFamiliesLocked( + nsPresContext* aPresContext, StyleGenericFontFamily aGeneric, const nsACString& aFamily, + nsTArray* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle, + nsAtom* aLanguage, gfxFloat aDevToCssSize) { if (aFamily.EqualsLiteral(kSystemFont_system)) { // Search for special system font name, -apple-system. This is not done via // the shared fontlist on Catalina or later, because the hidden system font @@ -1539,9 +1545,9 @@ bool gfxMacPlatformFontList::FindAndAddFamilies(nsPresContext* aPresContext, : mSystemTextFontFamilyName; if (SharedFontList() && !nsCocoaFeatures::OnCatalinaOrLater()) { FindFamiliesFlags flags = aFlags | FindFamiliesFlags::eSearchHiddenFamilies; - return gfxPlatformFontList::FindAndAddFamilies(aPresContext, aGeneric, systemFontFamilyName, - aOutput, flags, aStyle, aLanguage, - aDevToCssSize); + return gfxPlatformFontList::FindAndAddFamiliesLocked(aPresContext, aGeneric, + systemFontFamilyName, aOutput, flags, + aStyle, aLanguage, aDevToCssSize); } else { if (auto* fam = FindSystemFontFamily(systemFontFamilyName)) { aOutput->AppendElement(fam); @@ -1551,8 +1557,8 @@ bool gfxMacPlatformFontList::FindAndAddFamilies(nsPresContext* aPresContext, return false; } - return gfxPlatformFontList::FindAndAddFamilies(aPresContext, aGeneric, aFamily, aOutput, aFlags, - aStyle, aLanguage, aDevToCssSize); + return gfxPlatformFontList::FindAndAddFamiliesLocked(aPresContext, aGeneric, aFamily, aOutput, + aFlags, aStyle, aLanguage, aDevToCssSize); } void gfxMacPlatformFontList::LookupSystemFont(LookAndFeel::FontID aSystemFontID, @@ -1730,6 +1736,7 @@ already_AddRefed gfxMacPlatformFontList::CreateFontInfoData() { bool loadCmaps = !UsesSystemFallback() || gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); + mLock.AssertCurrentThreadIn(); RefPtr fi = new MacFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps); return fi.forget(); } diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index c65b1978caa7..d5ff5121585a 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -264,7 +264,7 @@ bool gfxPlatformFontList::Initialize(gfxPlatformFontList* aList) { } gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames) - : mFontFamiliesMutex("gfxPlatformFontList::mFontFamiliesMutex"), + : mLock("gfxPlatformFontList lock"), mFontFamilies(64), mOtherFamilyNames(16), mSharedCmaps(8) { @@ -305,7 +305,7 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames) gfxPlatformFontList::~gfxPlatformFontList() { mSharedCmaps.Clear(); - ClearLangGroupPrefFonts(); + ClearLangGroupPrefFontsLocked(); NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer"); @@ -375,6 +375,7 @@ void gfxPlatformFontList::ApplyWhitelist() { void gfxPlatformFontList::ApplyWhitelist( nsTArray& aFamilies) { + mLock.AssertCurrentThreadIn(); mFontFamilyWhitelistActive = !mEnabledFontsList.IsEmpty(); if (!mFontFamilyWhitelistActive) { return; @@ -435,6 +436,7 @@ void gfxPlatformFontList::CheckFamilyList(const char* aList[], size_t aCount) { bool gfxPlatformFontList::AddWithLegacyFamilyName(const nsACString& aLegacyName, gfxFontEntry* aFontEntry, FontVisibility aVisibility) { + mLock.AssertCurrentThreadIn(); bool added = false; nsAutoCString key; ToLowerCase(aLegacyName, key); @@ -455,7 +457,14 @@ bool gfxPlatformFontList::AddWithLegacyFamilyName(const nsACString& aLegacyName, } bool gfxPlatformFontList::InitFontList() { - MutexAutoLock lock(mFontFamiliesMutex); + // If the startup font-list-init thread is still running, we need to wait + // for it to finish before trying to reinitialize here. + if (sInitFontListThread && !IsInitFontListThread()) { + PR_JoinThread(sInitFontListThread); + sInitFontListThread = nullptr; + } + + AutoLock lock(mLock); if (LOG_FONTINIT_ENABLED()) { LOG_FONTINIT(("(fontinit) system fontlist initialization\n")); @@ -507,7 +516,7 @@ bool gfxPlatformFontList::InitFontList() { mExtraNames->mPostscriptNames.Clear(); } mFaceNameListsInitialized = false; - ClearLangGroupPrefFonts(); + ClearLangGroupPrefFontsLocked(); CancelLoader(); // Clear cached family records that will no longer be valid. @@ -576,14 +585,15 @@ bool gfxPlatformFontList::InitFontList() { // Set up mDefaultFontEntry as a "last resort" default that we can use // to avoid crashing if the font list is otherwise unusable. gfxFontStyle defStyle; - FontFamily fam = GetDefaultFont(nullptr, &defStyle); + FontFamily fam = GetDefaultFontLocked(nullptr, &defStyle); + gfxFontEntry* fe; if (fam.mIsShared) { auto face = fam.mShared->FindFaceForStyle(SharedFontList(), defStyle); - mDefaultFontEntry = - face ? GetOrCreateFontEntry(face, fam.mShared) : nullptr; + fe = face ? GetOrCreateFontEntryLocked(face, fam.mShared) : nullptr; } else { - mDefaultFontEntry = fam.mUnshared->FindFontForStyle(defStyle); + fe = fam.mUnshared->FindFontForStyle(defStyle); } + mDefaultFontEntry = fe; return true; } @@ -610,6 +620,7 @@ void gfxPlatformFontList::InitializeCodepointsWithNoFonts() { void gfxPlatformFontList::FontListChanged() { MOZ_ASSERT(!XRE_IsParentProcess()); + AutoLock lock(mLock); InitializeCodepointsWithNoFonts(); if (SharedFontList()) { // If we're using a shared local face-name list, this may have changed @@ -641,8 +652,10 @@ class InitOtherFamilyNamesForStylo : public mozilla::Runnable { if (!list) { return NS_OK; } + bool initialized = false; dom::ContentChild::GetSingleton()->SendInitOtherFamilyNames( - list->GetGeneration(), mDefer, &pfl->mOtherFamilyNamesInitialized); + list->GetGeneration(), mDefer, &initialized); + pfl->mOtherFamilyNamesInitialized.compareExchange(false, initialized); return NS_OK; } @@ -660,9 +673,11 @@ bool gfxPlatformFontList::InitOtherFamilyNames( if (SharedFontList() && !XRE_IsParentProcess()) { if (NS_IsMainThread()) { + bool initialized; dom::ContentChild::GetSingleton()->SendInitOtherFamilyNames( SharedFontList()->GetGeneration(), aDeferOtherFamilyNamesLoading, - &mOtherFamilyNamesInitialized); + &initialized); + mOtherFamilyNamesInitialized.compareExchange(false, initialized); } else { NS_DispatchToMainThread( new InitOtherFamilyNamesForStylo(aDeferOtherFamilyNamesLoading)); @@ -836,6 +851,7 @@ void gfxPlatformFontList::UpdateFontList(bool aFullRebuild) { MOZ_ASSERT(NS_IsMainThread()); if (aFullRebuild) { InitFontList(); + AutoLock lock(mLock); RebuildLocalFonts(); } else { // The font list isn't being fully rebuilt, we're just being notified that @@ -843,6 +859,7 @@ void gfxPlatformFontList::UpdateFontList(bool aFullRebuild) { // done. We only care about this if we have previously encountered a // fallback that required cmaps that were not yet available, and so we // asked for the async cmap loader to run. + AutoLock lock(mLock); if (mStartedLoadingCmapsFrom != 0xffffffffu) { InitializeCodepointsWithNoFonts(); mStartedLoadingCmapsFrom = 0xffffffffu; @@ -864,6 +881,8 @@ bool gfxPlatformFontList::IsVisibleToCSS(const fontlist::Family& aFamily, void gfxPlatformFontList::GetFontList(nsAtom* aLangGroup, const nsACString& aGenericFamily, nsTArray& aListOfFonts) { + AutoLock lock(mLock); + if (SharedFontList()) { fontlist::FontList* list = SharedFontList(); const fontlist::Family* families = list->Families(); @@ -882,7 +901,6 @@ void gfxPlatformFontList::GetFontList(nsAtom* aLangGroup, return; } - MutexAutoLock lock(mFontFamiliesMutex); for (const RefPtr& family : mFontFamilies.Values()) { if (!IsVisibleToCSS(*family, FontVisibility::User)) { continue; @@ -900,6 +918,7 @@ void gfxPlatformFontList::GetFontList(nsAtom* aLangGroup, void gfxPlatformFontList::GetFontFamilyList( nsTArray>& aFamilyArray) { + AutoLock lock(mLock); MOZ_ASSERT(aFamilyArray.IsEmpty()); // This doesn't use ToArray, because the caller passes an AutoTArray. aFamilyArray.SetCapacity(mFontFamilies.Count()); @@ -912,6 +931,7 @@ gfxFont* gfxPlatformFontList::SystemFindFontForChar( nsPresContext* aPresContext, uint32_t aCh, uint32_t aNextCh, Script aRunScript, eFontPresentation aPresentation, const gfxFontStyle* aStyle, FontVisibility* aVisibility) { + AutoLock lock(mLock); FontVisibility level = aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User; MOZ_ASSERT(!mCodepointsWithNoFonts[level].test(aCh), @@ -928,7 +948,7 @@ gfxFont* gfxPlatformFontList::SystemFindFontForChar( fontlist::Face* face = fallbackFamily.mShared->FindFaceForStyle(SharedFontList(), *aStyle); if (face) { - fontEntry = GetOrCreateFontEntry(face, fallbackFamily.mShared); + fontEntry = GetOrCreateFontEntryLocked(face, fallbackFamily.mShared); *aVisibility = fallbackFamily.mShared->Visibility(); } } else if (!fallbackFamily.mIsShared && fallbackFamily.mUnshared) { @@ -1357,9 +1377,11 @@ class LoadCmapsRunnable : public CancelableRunnable { RefPtr task = this; NS_DispatchToMainThreadQueue(task.forget(), EventQueuePriority::Idle); } else { + pfl->Lock(); pfl->CancelLoadCmapsTask(); pfl->InitializeCodepointsWithNoFonts(); dom::ContentParent::NotifyUpdatedFonts(false); + pfl->Unlock(); } return NS_OK; } @@ -1416,7 +1438,7 @@ gfxFontFamily* gfxPlatformFontList::CheckFamily(gfxFontFamily* aFamily) { } if (aFamily && aFamily->GetFontList().Length() == 0) { - // failed to load any faces for this family, so discard it + // Failed to load any faces for this family, so discard it. nsAutoCString key; GenerateFontListKey(aFamily->Name(), key); mFontFamilies.Remove(key); @@ -1426,7 +1448,7 @@ gfxFontFamily* gfxPlatformFontList::CheckFamily(gfxFontFamily* aFamily) { return aFamily; } -bool gfxPlatformFontList::FindAndAddFamilies( +bool gfxPlatformFontList::FindAndAddFamiliesLocked( nsPresContext* aPresContext, StyleGenericFontFamily aGeneric, const nsACString& aFamily, nsTArray* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage, @@ -1437,6 +1459,7 @@ bool gfxPlatformFontList::FindAndAddFamilies( bool allowHidden = bool(aFlags & FindFamiliesFlags::eSearchHiddenFamilies); FontVisibility visibilityLevel = aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User; + if (SharedFontList()) { fontlist::Family* family = SharedFontList()->FindFamily(key); // If not found, and other family names have not yet been initialized, @@ -1471,12 +1494,7 @@ bool gfxPlatformFontList::FindAndAddFamilies( } if (!family && !mOtherFamilyNamesInitialized && !(aFlags & FindFamiliesFlags::eNoAddToNamesMissedWhenSearching)) { - // localized family names load timed out, add name to list of - // names to check after localized names are loaded - if (!mOtherNamesMissed) { - mOtherNamesMissed = MakeUnique>(2); - } - mOtherNamesMissed->Insert(key); + AddToMissedNames(key); } } // Check whether the family we found is actually allowed to be looked up, @@ -1539,10 +1557,7 @@ bool gfxPlatformFontList::FindAndAddFamilies( !(aFlags & FindFamiliesFlags::eNoAddToNamesMissedWhenSearching)) { // localized family names load timed out, add name to list of // names to check after localized names are loaded - if (!mOtherNamesMissed) { - mOtherNamesMissed = MakeUnique>(2); - } - mOtherNamesMissed->Insert(key); + AddToMissedNames(key); } if (familyEntry) { if (isBlockedByVisibilityLevel(familyEntry)) { @@ -1594,6 +1609,13 @@ bool gfxPlatformFontList::FindAndAddFamilies( return false; } +void gfxPlatformFontList::AddToMissedNames(const nsCString& aKey) { + if (!mOtherNamesMissed) { + mOtherNamesMissed = MakeUnique>(2); + } + mOtherNamesMissed->Insert(aKey); +} + fontlist::Family* gfxPlatformFontList::FindSharedFamily( nsPresContext* aPresContext, const nsACString& aFamily, FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage, @@ -1602,8 +1624,9 @@ fontlist::Family* gfxPlatformFontList::FindSharedFamily( return nullptr; } AutoTArray families; - if (!FindAndAddFamilies(aPresContext, StyleGenericFontFamily::None, aFamily, - &families, aFlags, aStyle, aLanguage, aDevToCss) || + if (!FindAndAddFamiliesLocked(aPresContext, StyleGenericFontFamily::None, + aFamily, &families, aFlags, aStyle, aLanguage, + aDevToCss) || !families[0].mFamily.mIsShared) { return nullptr; } @@ -1707,6 +1730,7 @@ gfxFontEntry* gfxPlatformFontList::FindFontForFamily( const gfxFontStyle* aStyle) { nsAutoCString key; GenerateFontListKey(aFamily, key); + FontFamily family = FindFamily(aPresContext, key); if (family.IsNull()) { return nullptr; @@ -1716,12 +1740,12 @@ gfxFontEntry* gfxPlatformFontList::FindFontForFamily( if (!face) { return nullptr; } - return GetOrCreateFontEntry(face, family.mShared); + return GetOrCreateFontEntryLocked(face, family.mShared); } return family.mUnshared->FindFontForStyle(*aStyle); } -gfxFontEntry* gfxPlatformFontList::GetOrCreateFontEntry( +gfxFontEntry* gfxPlatformFontList::GetOrCreateFontEntryLocked( fontlist::Face* aFace, const fontlist::Family* aFamily) { return mFontEntries .LookupOrInsertWith(aFace, @@ -1729,25 +1753,28 @@ gfxFontEntry* gfxPlatformFontList::GetOrCreateFontEntry( .get(); } -void gfxPlatformFontList::AddOtherFamilyName( - gfxFontFamily* aFamilyEntry, const nsCString& aOtherFamilyName) { - nsAutoCString key; - GenerateFontListKey(aOtherFamilyName, key); +void gfxPlatformFontList::AddOtherFamilyNames( + gfxFontFamily* aFamilyEntry, const nsTArray& aOtherFamilyNames) { + AutoLock lock(mLock); - mOtherFamilyNames.LookupOrInsertWith(key, [&] { - LOG_FONTLIST( - ("(fontlist-otherfamily) canonical family: %s, " - "other family: %s\n", - aFamilyEntry->Name().get(), aOtherFamilyName.get())); - if (mBadUnderlineFamilyNames.ContainsSorted(key)) { - aFamilyEntry->SetBadUnderlineFamily(); - } - return RefPtr{aFamilyEntry}; - }); + for (const auto& name : aOtherFamilyNames) { + nsAutoCString key; + GenerateFontListKey(name, key); + + mOtherFamilyNames.LookupOrInsertWith(key, [&] { + LOG_FONTLIST( + ("(fontlist-otherfamily) canonical family: %s, other family: %s\n", + aFamilyEntry->Name().get(), name.get())); + if (mBadUnderlineFamilyNames.ContainsSorted(key)) { + aFamilyEntry->SetBadUnderlineFamily(); + } + return RefPtr{aFamilyEntry}; + }); + } } -void gfxPlatformFontList::AddFullname(gfxFontEntry* aFontEntry, - const nsCString& aFullname) { +void gfxPlatformFontList::AddFullnameLocked(gfxFontEntry* aFontEntry, + const nsCString& aFullname) { mExtraNames->mFullnames.LookupOrInsertWith(aFullname, [&] { LOG_FONTLIST(("(fontlist-fullname) name: %s, fullname: %s\n", aFontEntry->Name().get(), aFullname.get())); @@ -1755,8 +1782,8 @@ void gfxPlatformFontList::AddFullname(gfxFontEntry* aFontEntry, }); } -void gfxPlatformFontList::AddPostscriptName(gfxFontEntry* aFontEntry, - const nsCString& aPostscriptName) { +void gfxPlatformFontList::AddPostscriptNameLocked( + gfxFontEntry* aFontEntry, const nsCString& aPostscriptName) { mExtraNames->mPostscriptNames.LookupOrInsertWith(aPostscriptName, [&] { LOG_FONTLIST(("(fontlist-postscript) name: %s, psname: %s\n", aFontEntry->Name().get(), aPostscriptName.get())); @@ -1766,6 +1793,7 @@ void gfxPlatformFontList::AddPostscriptName(gfxFontEntry* aFontEntry, bool gfxPlatformFontList::GetStandardFamilyName(const nsCString& aFontName, nsACString& aFamilyName) { + AutoLock lock(mLock); FontFamily family = FindFamily(nullptr, aFontName); if (family.IsNull()) { return false; @@ -1794,6 +1822,8 @@ FamilyAndGeneric gfxPlatformFontList::GetDefaultFontFamily( return FamilyAndGeneric(); } + AutoLock lock(mLock); + nsAutoCString value; AutoTArray names; if (mFontPrefs->LookupNameList(PrefName(aGenericFamily, aLangGroup), value)) { @@ -1819,7 +1849,7 @@ ShmemCharMapHashEntry::ShmemCharMapHashEntry(const gfxSparseBitSet* aCharMap) SharedBitSet::Create(mCharMap.ToPtr(mList), len, *aCharMap); } -fontlist::Pointer gfxPlatformFontList::GetShmemCharMap( +fontlist::Pointer gfxPlatformFontList::GetShmemCharMapLocked( const gfxSparseBitSet* aCmap) { auto* entry = mShmemCharMaps.GetEntry(aCmap); if (!entry) { @@ -1828,22 +1858,18 @@ fontlist::Pointer gfxPlatformFontList::GetShmemCharMap( return entry->GetCharMap(); } +// lookup cmap in the shared cmap set, adding if not already present gfxCharacterMap* gfxPlatformFontList::FindCharMap(gfxCharacterMap* aCmap) { + AutoLock lock(mLock); aCmap->CalcHash(); - gfxCharacterMap* cmap = AddCmap(aCmap); + gfxCharacterMap* cmap = mSharedCmaps.PutEntry(aCmap)->GetKey(); cmap->mShared = true; return cmap; } -// add a cmap to the shared cmap set -gfxCharacterMap* gfxPlatformFontList::AddCmap(const gfxCharacterMap* aCharMap) { - CharMapHashKey* found = - mSharedCmaps.PutEntry(const_cast(aCharMap)); - return found->GetKey(); -} - // remove the cmap from the shared cmap set void gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap) { + AutoLock lock(mLock); // skip lookups during teardown if (mSharedCmaps.Count() == 0) { return; @@ -1939,8 +1965,9 @@ void gfxPlatformFontList::GetFontFamiliesFromGenericFamilies( // lookup and add platform fonts uniquely for (const nsCString& genericFamily : aGenericNameFamilies) { AutoTArray families; - FindAndAddFamilies(aPresContext, aGenericType, genericFamily, &families, - FindFamiliesFlags(0), nullptr, aLangGroup); + FindAndAddFamiliesLocked(aPresContext, aGenericType, genericFamily, + &families, FindFamiliesFlags(0), nullptr, + aLangGroup); for (const FamilyAndGeneric& f : families) { if (!aGenericFamilies->Contains(f.mFamily)) { aGenericFamilies->AppendElement(f.mFamily); @@ -1949,7 +1976,8 @@ void gfxPlatformFontList::GetFontFamiliesFromGenericFamilies( } } -gfxPlatformFontList::PrefFontList* gfxPlatformFontList::GetPrefFontsLangGroup( +gfxPlatformFontList::PrefFontList* +gfxPlatformFontList::GetPrefFontsLangGroupLocked( nsPresContext* aPresContext, StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang) { if (aGenericType == StyleGenericFontFamily::MozEmoji || @@ -1977,6 +2005,8 @@ gfxPlatformFontList::PrefFontList* gfxPlatformFontList::GetPrefFontsLangGroup( void gfxPlatformFontList::AddGenericFonts( nsPresContext* aPresContext, StyleGenericFontFamily aGenericType, nsAtom* aLanguage, nsTArray& aFamilyList) { + AutoLock lock(mLock); + // map lang ==> langGroup nsAtom* langGroup = GetLangGroup(aLanguage); @@ -1985,7 +2015,7 @@ void gfxPlatformFontList::AddGenericFonts( // lookup pref fonts PrefFontList* prefFonts = - GetPrefFontsLangGroup(aPresContext, aGenericType, prefLang); + GetPrefFontsLangGroupLocked(aPresContext, aGenericType, prefLang); if (!prefFonts->IsEmpty()) { aFamilyList.SetCapacity(aFamilyList.Length() + prefFonts->Length()); @@ -2181,6 +2211,7 @@ bool gfxPlatformFontList::IsLangCJK(eFontPrefLang aLang) { void gfxPlatformFontList::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang) { + AutoLock lock(mLock); if (IsLangCJK(aCharLang)) { AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang); } else { @@ -2351,6 +2382,8 @@ StyleGenericFontFamily gfxPlatformFontList::GetDefaultGeneric( return StyleGenericFontFamily::MozEmoji; } + AutoLock lock(mLock); + // initialize lang group pref font defaults (i.e. serif/sans-serif) if (MOZ_UNLIKELY(mDefaultGenericsLangGroup.IsEmpty())) { mDefaultGenericsLangGroup.AppendElements(ArrayLength(gPrefLangNames)); @@ -2375,6 +2408,12 @@ StyleGenericFontFamily gfxPlatformFontList::GetDefaultGeneric( FontFamily gfxPlatformFontList::GetDefaultFont(nsPresContext* aPresContext, const gfxFontStyle* aStyle) { + AutoLock lock(mLock); + return GetDefaultFontLocked(aPresContext, aStyle); +} + +FontFamily gfxPlatformFontList::GetDefaultFontLocked( + nsPresContext* aPresContext, const gfxFontStyle* aStyle) { FontFamily family = GetDefaultFontForPlatform(aPresContext, aStyle); if (!family.IsNull()) { return family; @@ -2461,6 +2500,7 @@ void gfxPlatformFontList::InitLoader() { 20 // max time for one pass through RunLoader = 20ms bool gfxPlatformFontList::LoadFontInfo() { + AutoLock lock(mLock); TimeStamp start = TimeStamp::Now(); uint32_t i, endIndex = mNumFamilies; fontlist::FontList* list = SharedFontList(); @@ -2528,6 +2568,8 @@ bool gfxPlatformFontList::LoadFontInfo() { } void gfxPlatformFontList::CleanupLoader() { + AutoLock lock(mLock); + mFontFamiliesToLoad.Clear(); mNumFamilies = 0; bool rebuilt = false, forceReflow = false; @@ -2535,7 +2577,10 @@ void gfxPlatformFontList::CleanupLoader() { // if had missed face names that are now available, force reflow all if (mFaceNamesMissed) { rebuilt = std::any_of(mFaceNamesMissed->cbegin(), mFaceNamesMissed->cend(), - [&](const auto& key) { return FindFaceName(key); }); + [&](const auto& key) { + mLock.AssertCurrentThreadIn(); + return FindFaceName(key); + }); if (rebuilt) { RebuildLocalFonts(); } @@ -2547,6 +2592,7 @@ void gfxPlatformFontList::CleanupLoader() { forceReflow = std::any_of( mOtherNamesMissed->cbegin(), mOtherNamesMissed->cend(), [&](const auto& key) { + mLock.AssertCurrentThreadIn(); return FindUnsharedFamily( nullptr, key, (FindFamiliesFlags::eForceOtherFamilyNamesLoading | @@ -2580,8 +2626,11 @@ void gfxPlatformFontList::GetPrefsAndStartLoader() { StartLoader(delay); } else { NS_DispatchToMainThread(NS_NewRunnableFunction( - "StartLoader callback", - [delay, fontList = this] { fontList->StartLoader(delay); })); + "StartLoader callback", [delay, fontList = this] { + fontList->Lock(); + fontList->StartLoader(delay); + fontList->Unlock(); + })); } } @@ -2594,7 +2643,7 @@ void gfxPlatformFontList::RebuildLocalFonts(bool aForgetLocalFaces) { } } -void gfxPlatformFontList::ClearLangGroupPrefFonts() { +void gfxPlatformFontList::ClearLangGroupPrefFontsLocked() { for (uint32_t i = eFontPrefLang_First; i < eFontPrefLang_First + eFontPrefLang_Count; i++) { auto& prefFontsLangGroup = mLangGroupPrefFonts[i]; @@ -2642,6 +2691,8 @@ size_t gfxPlatformFontList::SizeOfFontEntryTableExcludingThis( void gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const { + AutoLock lock(mLock); + aSizes->mFontListSize += mFontFamilies.ShallowSizeOfExcludingThis(aMallocSizeOf); for (const auto& entry : mFontFamilies) { @@ -2717,6 +2768,8 @@ void gfxPlatformFontList::InitOtherFamilyNamesInternal( return; } + AutoLock lock(mLock); + if (aDeferOtherFamilyNamesLoading) { TimeStamp start = TimeStamp::Now(); bool timedOut = false; diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index 3bfef70d5cad..cd53bb30104a 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -24,8 +24,8 @@ #include "mozilla/EnumeratedArray.h" #include "mozilla/FontPropertyTypes.h" #include "mozilla/MemoryReporting.h" -#include "mozilla/Mutex.h" #include "mozilla/RangedArray.h" +#include "mozilla/RecursiveMutex.h" #include "nsLanguageAtomService.h" #include "base/shared_memory.h" @@ -164,6 +164,8 @@ class gfxPlatformFontList : public gfxFontInfoLoader { typedef mozilla::WeightRange WeightRange; typedef mozilla::intl::Script Script; + using AutoLock = mozilla::RecursiveMutexAutoLock; + // Class used to hold cached copies of the font-name prefs, so that they can // be accessed from non-main-thread callers who are not allowed to touch the // Preferences service. @@ -265,7 +267,11 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // but not completely invalidated. void UpdateFontList(bool aFullRebuild = true); - virtual void ClearLangGroupPrefFonts(); + void ClearLangGroupPrefFonts() { + AutoLock lock(mLock); + ClearLangGroupPrefFontsLocked(); + } + virtual void ClearLangGroupPrefFontsLocked() REQUIRES(mLock); void GetFontFamilyList(nsTArray>& aFamilyArray); @@ -307,15 +313,25 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // Find family(ies) matching aFamily and append to the aOutput array // (there may be multiple results in the case of fontconfig aliases, etc). // Return true if any match was found and appended, false if none. - virtual bool FindAndAddFamilies( + bool FindAndAddFamilies( nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric, const nsACString& aFamily, nsTArray* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr, - nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0); + nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0) { + AutoLock lock(mLock); + return FindAndAddFamiliesLocked(aPresContext, aGeneric, aFamily, aOutput, + aFlags, aStyle, aLanguage, aDevToCssSize); + } + virtual bool FindAndAddFamiliesLocked( + nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric, + const nsACString& aFamily, nsTArray* aOutput, + FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr, + nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0) + REQUIRES(mLock); gfxFontEntry* FindFontForFamily(nsPresContext* aPresContext, const nsACString& aFamily, - const gfxFontStyle* aStyle); + const gfxFontStyle* aStyle) REQUIRES(mLock); mozilla::fontlist::FontList* SharedFontList() const { return mSharedFontList.get(); @@ -371,13 +387,24 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // name lookup table methods - void AddOtherFamilyName(gfxFontFamily* aFamilyEntry, - const nsCString& aOtherFamilyName); + void AddOtherFamilyNames(gfxFontFamily* aFamilyEntry, + const nsTArray& aOtherFamilyNames); - void AddFullname(gfxFontEntry* aFontEntry, const nsCString& aFullname); + void AddFullname(gfxFontEntry* aFontEntry, const nsCString& aFullname) { + AutoLock lock(mLock); + AddFullnameLocked(aFontEntry, aFullname); + } + void AddFullnameLocked(gfxFontEntry* aFontEntry, const nsCString& aFullname) + REQUIRES(mLock); void AddPostscriptName(gfxFontEntry* aFontEntry, - const nsCString& aPostscriptName); + const nsCString& aPostscriptName) { + AutoLock lock(mLock); + AddPostscriptNameLocked(aFontEntry, aPostscriptName); + } + void AddPostscriptNameLocked(gfxFontEntry* aFontEntry, + const nsCString& aPostscriptName) + REQUIRES(mLock); bool NeedFullnamePostscriptNames() { return mExtraNames != nullptr; } @@ -400,10 +427,15 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // get the system default font family FontFamily GetDefaultFont(nsPresContext* aPresContext, const gfxFontStyle* aStyle); + FontFamily GetDefaultFontLocked(nsPresContext* aPresContext, + const gfxFontStyle* aStyle) REQUIRES(mLock); // get the "ultimate" default font, for use if the font list is otherwise // unusable (e.g. in the middle of being updated) - gfxFontEntry* GetDefaultFontEntry() { return mDefaultFontEntry.get(); } + gfxFontEntry* GetDefaultFontEntry() { + AutoLock lock(mLock); + return mDefaultFontEntry.get(); + } /** * Look up a font by name on the host platform. @@ -456,24 +488,28 @@ class gfxPlatformFontList : public gfxFontInfoLoader { virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const; - mozilla::fontlist::Pointer GetShmemCharMap(const gfxSparseBitSet* aCmap); + mozilla::fontlist::Pointer GetShmemCharMap(const gfxSparseBitSet* aCmap) { + AutoLock lock(mLock); + return GetShmemCharMapLocked(aCmap); + } + mozilla::fontlist::Pointer GetShmemCharMapLocked(const gfxSparseBitSet* aCmap) + REQUIRES(mLock); - // search for existing cmap that matches the input - // return the input if no match is found + // Search for existing cmap that matches the input; return the input if no + // match is found. gfxCharacterMap* FindCharMap(gfxCharacterMap* aCmap); - // add a cmap to the shared cmap set - gfxCharacterMap* AddCmap(const gfxCharacterMap* aCharMap); - - // remove the cmap from the shared cmap set + // Remove the cmap from the shared cmap set. void RemoveCmap(const gfxCharacterMap* aCharMap); - // keep track of userfont sets to notify when global fontlist changes occur + // Keep track of userfont sets to notify when global fontlist changes occur. void AddUserFontSet(gfxUserFontSet* aUserFontSet) { + AutoLock lock(mLock); mUserFontSetList.Insert(aUserFontSet); } void RemoveUserFontSet(gfxUserFontSet* aUserFontSet) { + AutoLock lock(mLock); mUserFontSetList.Remove(aUserFontSet); } @@ -496,15 +532,32 @@ class gfxPlatformFontList : public gfxFontInfoLoader { * make one, and adds it to the cache. */ gfxFontEntry* GetOrCreateFontEntry(mozilla::fontlist::Face* aFace, - const mozilla::fontlist::Family* aFamily); + const mozilla::fontlist::Family* aFamily) { + AutoLock lock(mLock); + return GetOrCreateFontEntryLocked(aFace, aFamily); + } + gfxFontEntry* GetOrCreateFontEntryLocked( + mozilla::fontlist::Face* aFace, const mozilla::fontlist::Family* aFamily) + REQUIRES(mLock); - const FontPrefs* GetFontPrefs() const { return mFontPrefs.get(); } + const FontPrefs* GetFontPrefs() const REQUIRES(mLock) { + return mFontPrefs.get(); + } - bool EmojiPrefHasUserValue() const { return mFontPrefs->EmojiHasUserValue(); } + bool EmojiPrefHasUserValue() const { + AutoLock lock(mLock); + return mFontPrefs->EmojiHasUserValue(); + } PrefFontList* GetPrefFontsLangGroup( nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType, - eFontPrefLang aPrefLang); + eFontPrefLang aPrefLang) { + AutoLock lock(mLock); + return GetPrefFontsLangGroupLocked(aPresContext, aGenericType, aPrefLang); + } + PrefFontList* GetPrefFontsLangGroupLocked( + nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType, + eFontPrefLang aPrefLang) REQUIRES(mLock); // in some situations, need to make decisions about ambiguous characters, may // need to look at multiple pref langs @@ -555,6 +608,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader { mozilla::StyleGenericFontFamily aGenericType); bool SkipFontFallbackForChar(FontVisibility aVisibility, uint32_t aCh) const { + AutoLock lock(mLock); return mCodepointsWithNoFonts[aVisibility].test(aCh); } @@ -566,7 +620,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader { FontVisibility aVisibility) const; // (Re-)initialize the set of codepoints that we know cannot be rendered. - void InitializeCodepointsWithNoFonts(); + void InitializeCodepointsWithNoFonts() REQUIRES(mLock); // If using the shared font list, returns a generation count that is // incremented if/when the platform list is reinitialized (e.g. because @@ -581,6 +635,13 @@ class gfxPlatformFontList : public gfxFontInfoLoader { return PR_GetCurrentThread() == sInitFontListThread; } + void Lock() CAPABILITY_ACQUIRE(mLock) { mLock.Lock(); } + void Unlock() CAPABILITY_RELEASE(mLock) { mLock.Unlock(); } + + // This is only public because some external callers want to be able to + // assert about the locked status. + mutable mozilla::RecursiveMutex mLock; + protected: friend class mozilla::fontlist::FontList; friend class InitOtherFamilyNamesForStylo; @@ -680,20 +741,20 @@ class gfxPlatformFontList : public gfxFontInfoLoader { nsPresContext* aPresContext, const nsACString& aFamily, FindFamiliesFlags aFlags = FindFamiliesFlags(0), gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr, - gfxFloat aDevToCssSize = 1.0); + gfxFloat aDevToCssSize = 1.0) REQUIRES(mLock); gfxFontFamily* FindUnsharedFamily( nsPresContext* aPresContext, const nsACString& aFamily, FindFamiliesFlags aFlags = FindFamiliesFlags(0), gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr, - gfxFloat aDevToCssSize = 1.0) { + gfxFloat aDevToCssSize = 1.0) REQUIRES(mLock) { if (SharedFontList()) { return nullptr; } AutoTArray families; - if (FindAndAddFamilies(aPresContext, mozilla::StyleGenericFontFamily::None, - aFamily, &families, aFlags, aStyle, aLanguage, - aDevToCssSize)) { + if (FindAndAddFamiliesLocked( + aPresContext, mozilla::StyleGenericFontFamily::None, aFamily, + &families, aFlags, aStyle, aLanguage, aDevToCssSize)) { return families[0].mFamily.mUnshared; } return nullptr; @@ -703,7 +764,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader { FindFamiliesFlags aFlags = FindFamiliesFlags(0), gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr, - gfxFloat aDevToCssSize = 1.0) { + gfxFloat aDevToCssSize = 1.0) REQUIRES(mLock) { if (SharedFontList()) { return FontFamily(FindSharedFamily(aPresContext, aFamily, aFlags, aStyle, aLanguage, aDevToCssSize)); @@ -714,7 +775,8 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // Lookup family name in global family list without substitutions or // localized family name lookup. Used for common font fallback families. - gfxFontFamily* FindFamilyByCanonicalName(const nsACString& aFamily) { + gfxFontFamily* FindFamilyByCanonicalName(const nsACString& aFamily) + REQUIRES(mLock) { nsAutoCString key; gfxFontFamily* familyEntry; GenerateFontListKey(aFamily, key); @@ -729,14 +791,15 @@ class gfxPlatformFontList : public gfxFontInfoLoader { uint32_t aNextCh, Script aRunScript, eFontPresentation aPresentation, const gfxFontStyle* aMatchStyle, - FontFamily& aMatchedFamily); + FontFamily& aMatchedFamily) REQUIRES(mLock); // Search fonts system-wide for a given character, null if not found. gfxFont* GlobalFontFallback(nsPresContext* aPresContext, uint32_t aCh, uint32_t aNextCh, Script aRunScript, eFontPresentation aPresentation, const gfxFontStyle* aMatchStyle, - uint32_t& aCmapCount, FontFamily& aMatchedFamily); + uint32_t& aCmapCount, FontFamily& aMatchedFamily) + REQUIRES(mLock); // Platform-specific implementation of global font fallback, if any; // this may return nullptr in which case the default cmap-based fallback @@ -752,45 +815,52 @@ class gfxPlatformFontList : public gfxFontInfoLoader { virtual bool UsesSystemFallback() { return false; } void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t& aLen, - eFontPrefLang aCharLang, eFontPrefLang aPageLang); + eFontPrefLang aCharLang, eFontPrefLang aPageLang) + REQUIRES(mLock); // verifies that a family contains a non-zero font count - gfxFontFamily* CheckFamily(gfxFontFamily* aFamily); + gfxFontFamily* CheckFamily(gfxFontFamily* aFamily) REQUIRES(mLock); // initialize localized family names void InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading); void CancelInitOtherFamilyNamesTask(); + void AddToMissedNames(const nsCString& aKey) REQUIRES(mLock); + // search through font families, looking for a given name, initializing // facename lists along the way. first checks all families with names // close to face name, then searchs all families if not found. - gfxFontEntry* SearchFamiliesForFaceName(const nsACString& aFaceName); + gfxFontEntry* SearchFamiliesForFaceName(const nsACString& aFaceName) + REQUIRES(mLock); // helper method for finding fullname/postscript names in facename lists - gfxFontEntry* FindFaceName(const nsACString& aFaceName); + gfxFontEntry* FindFaceName(const nsACString& aFaceName) REQUIRES(mLock); // look up a font by name, for cases where platform font list // maintains explicit mappings of fullname/psname ==> font - virtual gfxFontEntry* LookupInFaceNameLists(const nsACString& aFontName); + virtual gfxFontEntry* LookupInFaceNameLists(const nsACString& aFaceName) + REQUIRES(mLock); gfxFontEntry* LookupInSharedFaceNameList(nsPresContext* aPresContext, const nsACString& aFaceName, WeightRange aWeightForEntry, StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry); + SlantStyleRange aStyleForEntry) + REQUIRES(mLock); // load the bad underline blocklist from pref. void LoadBadUnderlineList(); void GenerateFontListKey(const nsACString& aKeyName, nsACString& aResult); - virtual void GetFontFamilyNames(nsTArray& aFontFamilyNames); + virtual void GetFontFamilyNames(nsTArray& aFontFamilyNames) + REQUIRES(mLock); // helper function to map lang to lang group nsAtom* GetLangGroup(nsAtom* aLanguage); // gfxFontInfoLoader overrides, used to load in font cmaps - void InitLoader() override; + void InitLoader() REQUIRES(mLock) override; bool LoadFontInfo() override; void CleanupLoader() override; @@ -800,23 +870,23 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // If aForgetLocalFaces is true, all gfxFontEntries for src:local fonts must // be discarded (not potentially reused to satisfy the rebuilt rules), // because they may no longer be valid. - void RebuildLocalFonts(bool aForgetLocalFaces = false); + void RebuildLocalFonts(bool aForgetLocalFaces = false) REQUIRES(mLock); void ResolveGenericFontNames(nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang, - PrefFontList* aGenericFamilies); + PrefFontList* aGenericFamilies) REQUIRES(mLock); void ResolveEmojiFontNames(nsPresContext* aPresContext, - PrefFontList* aGenericFamilies); + PrefFontList* aGenericFamilies) REQUIRES(mLock); void GetFontFamiliesFromGenericFamilies( nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType, nsTArray& aGenericNameFamilies, nsAtom* aLangGroup, - PrefFontList* aFontFamilies); + PrefFontList* aFontFamilies) REQUIRES(mLock); - virtual nsresult InitFontListForPlatform() = 0; - virtual void InitSharedFontListForPlatform() {} + virtual nsresult InitFontListForPlatform() REQUIRES(mLock) = 0; + virtual void InitSharedFontListForPlatform() REQUIRES(mLock) {} virtual gfxFontEntry* CreateFontEntry( mozilla::fontlist::Face* aFace, @@ -831,7 +901,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader { * There are separate implementations of this for the per-process font list * and for the shared-memory font list. */ - void ApplyWhitelist(); + void ApplyWhitelist() REQUIRES(mLock); void ApplyWhitelist(nsTArray& aFamilies); // Create a new gfxFontFamily of the appropriate subclass for the platform, @@ -850,7 +920,8 @@ class gfxPlatformFontList : public gfxFontInfoLoader { * case this method is unused. */ virtual void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily, - bool aNeedFullnamePostscriptNames) {} + bool aNeedFullnamePostscriptNames) + REQUIRES(mLock) {} typedef nsRefPtrHashtable FontFamilyTable; typedef nsRefPtrHashtable FontEntryTable; @@ -864,26 +935,24 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // Platform-specific helper for GetDefaultFont(...). virtual FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext, const gfxFontStyle* aStyle, - nsAtom* aLanguage = nullptr) = 0; - - // Protects mFontFamilies. - mozilla::Mutex mFontFamiliesMutex MOZ_UNANNOTATED; + nsAtom* aLanguage = nullptr) + REQUIRES(mLock) = 0; // canonical family name ==> family entry (unique, one name per family entry) - FontFamilyTable mFontFamilies; + FontFamilyTable mFontFamilies GUARDED_BY(mLock); // other family name ==> family entry (not unique, can have multiple names per // family entry, only names *other* than the canonical names are stored here) - FontFamilyTable mOtherFamilyNames; + FontFamilyTable mOtherFamilyNames GUARDED_BY(mLock); // flag set after InitOtherFamilyNames is called upon first name lookup miss - bool mOtherFamilyNamesInitialized = false; + mozilla::Atomic mOtherFamilyNamesInitialized; // The pending InitOtherFamilyNames() task. RefPtr mPendingOtherFamilyNameTask; // flag set after fullname and Postcript name lists are populated - bool mFaceNameListsInitialized = false; + mozilla::Atomic mFaceNameListsInitialized; struct ExtraNames { ExtraNames() = default; @@ -893,13 +962,16 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // Postscript name ==> font entry (unique, one name per font entry) FontEntryTable mPostscriptNames{64}; }; - mozilla::UniquePtr mExtraNames; + // The lock is needed to guard access to the actual name tables, but does not + // need to be held to just test whether mExtraNames is non-null as it is set + // during initialization before other threads have a chance to see it. + mozilla::UniquePtr mExtraNames PT_GUARDED_BY(mLock); // face names missed when face name loading takes a long time - mozilla::UniquePtr> mFaceNamesMissed; + mozilla::UniquePtr> mFaceNamesMissed GUARDED_BY(mLock); // localized family names missed when face name loading takes a long time - mozilla::UniquePtr> mOtherNamesMissed; + mozilla::UniquePtr> mOtherNamesMissed GUARDED_BY(mLock); typedef mozilla::RangedArray, size_t(mozilla::StyleGenericFontFamily::None), @@ -908,28 +980,28 @@ class gfxPlatformFontList : public gfxFontInfoLoader { PrefFontsForLangGroup; mozilla::RangedArray - mLangGroupPrefFonts; - mozilla::UniquePtr mEmojiPrefFont; + mLangGroupPrefFonts GUARDED_BY(mLock); + mozilla::UniquePtr mEmojiPrefFont GUARDED_BY(mLock); // When system-wide font lookup fails for a character, cache it to skip future // searches. This is an array of bitsets, one for each FontVisibility level. mozilla::EnumeratedArray - mCodepointsWithNoFonts; + mCodepointsWithNoFonts GUARDED_BY(mLock); // the family to use for U+FFFD fallback, to avoid expensive search every time // on pages with lots of problems mozilla::EnumeratedArray - mReplacementCharFallbackFamily; + mReplacementCharFallbackFamily GUARDED_BY(mLock); // Sorted array of lowercased family names; use ContainsSorted to test nsTArray mBadUnderlineFamilyNames; // character map data shared across families // contains weak ptrs to cmaps shared by font entry objects - nsTHashtable mSharedCmaps; + nsTHashtable mSharedCmaps GUARDED_BY(mLock); - nsTHashtable mShmemCharMaps; + nsTHashtable mShmemCharMaps GUARDED_BY(mLock); // data used as part of the font cmap loading process nsTArray> mFontFamiliesToLoad; @@ -940,12 +1012,13 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // see bugs 636957, 1070983, 1189129 uint32_t mFontlistInitCount = 0; // num times InitFontList called - nsTHashSet mUserFontSetList; + nsTHashSet mUserFontSetList GUARDED_BY(mLock); nsLanguageAtomService* mLangService = nullptr; - nsTArray mCJKPrefLangs; - nsTArray mDefaultGenericsLangGroup; + nsTArray mCJKPrefLangs GUARDED_BY(mLock); + nsTArray mDefaultGenericsLangGroup + GUARDED_BY(mLock); nsTArray mEnabledFontsList; @@ -956,11 +1029,11 @@ class gfxPlatformFontList : public gfxFontInfoLoader { mLocalNameTable; nsRefPtrHashtable, gfxFontEntry> - mFontEntries; + mFontEntries GUARDED_BY(mLock); mozilla::UniquePtr mFontPrefs; - RefPtr mDefaultFontEntry; + RefPtr mDefaultFontEntry GUARDED_BY(mLock); RefPtr mLoadCmapsRunnable; uint32_t mStartedLoadingCmapsFrom = 0xffffffffu; diff --git a/gfx/thebes/gfxUserFontSet.h b/gfx/thebes/gfxUserFontSet.h index e9248f18eaf7..02e9c0acec0b 100644 --- a/gfx/thebes/gfxUserFontSet.h +++ b/gfx/thebes/gfxUserFontSet.h @@ -172,6 +172,7 @@ class gfxUserFontFamily : public gfxFontFamily { // add the given font entry to the end of the family's list void AddFontEntry(gfxFontEntry* aFontEntry) { + mozilla::AutoWriteLock lock(mLock); MOZ_ASSERT(!mIsSimpleFamily, "not valid for user-font families"); // keep ref while removing existing entry RefPtr fe = aFontEntry; @@ -196,12 +197,16 @@ class gfxUserFontFamily : public gfxFontFamily { } void RemoveFontEntry(gfxFontEntry* aFontEntry) { + mozilla::AutoWriteLock lock(mLock); MOZ_ASSERT(!mIsSimpleFamily, "not valid for user-font families"); mAvailableFonts.RemoveElement(aFontEntry); } // Remove all font entries from the family - void DetachFontEntries() { mAvailableFonts.Clear(); } + void DetachFontEntries() { + mozilla::AutoWriteLock lock(mLock); + mAvailableFonts.Clear(); + } }; class gfxUserFontEntry; diff --git a/layout/mathml/nsMathMLChar.cpp b/layout/mathml/nsMathMLChar.cpp index 8583c84639df..f0a20faba444 100644 --- a/layout/mathml/nsMathMLChar.cpp +++ b/layout/mathml/nsMathMLChar.cpp @@ -1493,12 +1493,14 @@ nsresult nsMathMLChar::StretchInternal( AutoTArray mathFallbacks; nsAutoCString value; gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList(); + pfl->Lock(); if (pfl->GetFontPrefs()->LookupName("serif.x-math"_ns, value)) { gfxFontUtils::ParseFontList(value, mathFallbacks); } if (pfl->GetFontPrefs()->LookupNameList("serif.x-math"_ns, value)) { gfxFontUtils::ParseFontList(value, mathFallbacks); } + pfl->Unlock(); InsertMathFallbacks(font.family.families, mathFallbacks); #ifdef NOISY_SEARCH