Bug 1536176 - Use nsStaticAtom in nsLanguageAtomService. r=jfkthame
authorEmilio Cobos Álvarez <emilio@crisal.io>
Tue, 19 Mar 2019 12:48:31 +0000
changeset 465107 fa8777d9e0e163ce41f29fd4618cbc6358738ce6
parent 465106 8d9b4e8dce578a417cc0f2f98eaebe3cef47370f
child 465108 7976a9441fb9faa2045c38d16c3b4df7f6c79ac2
push id35732
push useropoprus@mozilla.com
push dateWed, 20 Mar 2019 10:52:37 +0000
treeherdermozilla-central@708979f9c3f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1536176
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1536176 - Use nsStaticAtom in nsLanguageAtomService. r=jfkthame All lang groups are static, no point in doing refcounting. Differential Revision: https://phabricator.services.mozilla.com/D23954
intl/locale/nsLanguageAtomService.cpp
intl/locale/nsLanguageAtomService.h
layout/base/StaticPresData.h
layout/style/GeckoBindings.cpp
--- a/intl/locale/nsLanguageAtomService.cpp
+++ b/intl/locale/nsLanguageAtomService.cpp
@@ -16,35 +16,36 @@
 using namespace mozilla;
 using mozilla::intl::OSPreferences;
 
 static constexpr nsUConvProp encodingsGroups[] = {
 #include "encodingsgroups.properties.h"
 };
 
 // List of mozilla internal x-* tags that map to themselves (see bug 256257)
-static constexpr const char* kLangGroups[] = {
+static constexpr nsStaticAtom* kLangGroups[] = {
     // This list must be sorted!
-    "x-armn",  "x-cyrillic", "x-devanagari", "x-geor", "x-math",
-    "x-tamil", "x-unicode",  "x-western"
+    nsGkAtoms::x_armn,  nsGkAtoms::x_cyrillic, nsGkAtoms::x_devanagari,
+    nsGkAtoms::x_geor,  nsGkAtoms::x_math,     nsGkAtoms::x_tamil,
+    nsGkAtoms::Unicode, nsGkAtoms::x_western
     // These self-mappings are not necessary unless somebody use them to specify
     // lang in (X)HTML/XML documents, which they shouldn't. (see bug 256257)
     // x-beng=x-beng
     // x-cans=x-cans
     // x-ethi=x-ethi
     // x-guru=x-guru
     // x-gujr=x-gujr
     // x-khmr=x-khmr
     // x-mlym=x-mlym
 };
 
 // Map ISO 15924 script codes from BCP47 lang tag to mozilla's langGroups.
 static constexpr struct {
   const char* mTag;
-  nsAtom* mAtom;
+  nsStaticAtom* mAtom;
 } kScriptLangGroup[] = {
     // This list must be sorted by script code!
     {"Arab", nsGkAtoms::ar},
     {"Armn", nsGkAtoms::x_armn},
     {"Beng", nsGkAtoms::x_beng},
     {"Cans", nsGkAtoms::x_cans},
     {"Cyrl", nsGkAtoms::x_cyrillic},
     {"Deva", nsGkAtoms::x_devanagari},
@@ -81,17 +82,18 @@ nsLanguageAtomService* nsLanguageAtomSer
   static UniquePtr<nsLanguageAtomService> gLangAtomService;
   if (!gLangAtomService) {
     gLangAtomService = MakeUnique<nsLanguageAtomService>();
     ClearOnShutdown(&gLangAtomService);
   }
   return gLangAtomService.get();
 }
 
-nsAtom* nsLanguageAtomService::LookupLanguage(const nsACString& aLanguage) {
+nsStaticAtom* nsLanguageAtomService::LookupLanguage(
+    const nsACString& aLanguage) {
   nsAutoCString lowered(aLanguage);
   ToLowerCase(lowered);
 
   RefPtr<nsAtom> lang = NS_Atomize(lowered);
   return GetLanguageGroup(lang);
 }
 
 already_AddRefed<nsAtom> nsLanguageAtomService::LookupCharSet(
@@ -123,78 +125,73 @@ nsAtom* nsLanguageAtomService::GetLocale
         mLocaleLanguage = NS_Atomize(locale);
       }
     }
   } while (0);
 
   return mLocaleLanguage;
 }
 
-nsAtom* nsLanguageAtomService::GetLanguageGroup(nsAtom* aLanguage,
-                                                bool* aNeedsToCache) {
-  nsAtom* retVal = mLangToGroup.GetWeak(aLanguage);
-
-  if (!retVal) {
-    if (aNeedsToCache) {
-      *aNeedsToCache = true;
-      return nullptr;
-    }
-    RefPtr<nsAtom> uncached = GetUncachedLanguageGroup(aLanguage);
-    retVal = uncached.get();
-
-    AssertIsMainThreadOrServoFontMetricsLocked();
-    // The hashtable will keep an owning reference to the atom
-    mLangToGroup.Put(aLanguage, uncached);
+nsStaticAtom* nsLanguageAtomService::GetLanguageGroup(nsAtom* aLanguage,
+                                                      bool* aNeedsToCache) {
+  if (nsStaticAtom* group = mLangToGroup.Get(aLanguage)) {
+    return group;
   }
-
-  return retVal;
+  if (aNeedsToCache) {
+    *aNeedsToCache = true;
+    return nullptr;
+  }
+  AssertIsMainThreadOrServoFontMetricsLocked();
+  nsStaticAtom* group = GetUncachedLanguageGroup(aLanguage);
+  mLangToGroup.Put(aLanguage, group);
+  return group;
 }
 
-already_AddRefed<nsAtom> nsLanguageAtomService::GetUncachedLanguageGroup(
+nsStaticAtom* nsLanguageAtomService::GetUncachedLanguageGroup(
     nsAtom* aLanguage) const {
   nsAutoCString langStr;
   aLanguage->ToUTF8String(langStr);
   ToLowerCase(langStr);
 
-  RefPtr<nsAtom> langGroup;
   if (langStr[0] == 'x' && langStr[1] == '-') {
     // Internal x-* langGroup codes map to themselves (see bug 256257)
-    size_t unused;
-    if (BinarySearchIf(
-            kLangGroups, 0, ArrayLength(kLangGroups),
-            [&langStr](const char* tag) -> int { return langStr.Compare(tag); },
-            &unused)) {
-      langGroup = NS_Atomize(langStr);
-      return langGroup.forget();
+    for (nsStaticAtom* langGroup : kLangGroups) {
+      if (langGroup == aLanguage) {
+        return langGroup;
+      }
+      if (aLanguage->IsAsciiLowercase()) {
+        continue;
+      }
+      // Do the slow ascii-case-insensitive comparison just if needed.
+      nsDependentAtomString string(langGroup);
+      if (string.EqualsASCII(langStr.get(), langStr.Length())) {
+        return langGroup;
+      }
     }
   } else {
     // If the lang code can be parsed as BCP47, look up its (likely) script
     Locale loc(langStr);
     if (loc.IsWellFormed()) {
       if (loc.GetScript().IsEmpty()) {
         loc.AddLikelySubtags();
       }
       if (loc.GetScript().EqualsLiteral("Hant")) {
         if (loc.GetRegion().EqualsLiteral("HK")) {
-          langGroup = nsGkAtoms::HongKongChinese;
-        } else {
-          langGroup = nsGkAtoms::Taiwanese;
+          return nsGkAtoms::HongKongChinese;
         }
-        return langGroup.forget();
+        return nsGkAtoms::Taiwanese;
       } else {
         size_t foundIndex;
         const nsCString& script = loc.GetScript();
         if (BinarySearchIf(kScriptLangGroup, 0, ArrayLength(kScriptLangGroup),
                            [script](const auto& entry) -> int {
                              return script.Compare(entry.mTag);
                            },
                            &foundIndex)) {
-          langGroup = kScriptLangGroup[foundIndex].mAtom;
-          return langGroup.forget();
+          return kScriptLangGroup[foundIndex].mAtom;
         }
       }
     }
   }
 
   // Fall back to x-unicode if no match was found
-  langGroup = nsGkAtoms::Unicode;
-  return langGroup.forget();
+  return nsGkAtoms::Unicode;
 }
--- a/intl/locale/nsLanguageAtomService.h
+++ b/intl/locale/nsLanguageAtomService.h
@@ -9,31 +9,31 @@
  */
 
 #ifndef nsLanguageAtomService_h_
 #define nsLanguageAtomService_h_
 
 #include "mozilla/NotNull.h"
 #include "nsCOMPtr.h"
 #include "nsAtom.h"
-#include "nsRefPtrHashtable.h"
+#include "nsDataHashtable.h"
 
 namespace mozilla {
 class Encoding;
 }
 
 class nsLanguageAtomService final {
   using Encoding = mozilla::Encoding;
   template <typename T>
   using NotNull = mozilla::NotNull<T>;
 
  public:
   static nsLanguageAtomService* GetService();
 
-  nsAtom* LookupLanguage(const nsACString& aLanguage);
+  nsStaticAtom* LookupLanguage(const nsACString& aLanguage);
   already_AddRefed<nsAtom> LookupCharSet(NotNull<const Encoding*> aCharSet);
   nsAtom* GetLocaleLanguage();
 
   // Returns the language group that the specified language is a part of.
   //
   // aNeedsToCache is used for two things.  If null, it indicates that
   // the nsLanguageAtomService is safe to cache the result of the
   // language group lookup, either because we're on the main thread,
@@ -42,17 +42,18 @@ class nsLanguageAtomService final {
   // cache the result of the language group lookup (because we're on
   // a style worker thread without the lock acquired).  In this case,
   // GetLanguageGroup will store true in *aNeedsToCache true if we
   // would have cached the result of a new lookup, and false if we
   // were able to use an existing cached result.  Thus, callers that
   // get a true *aNeedsToCache outparam value should make an effort
   // to re-call GetLanguageGroup when it is safe to cache, to avoid
   // recomputing the language group again later.
-  nsAtom* GetLanguageGroup(nsAtom* aLanguage, bool* aNeedsToCache = nullptr);
-  already_AddRefed<nsAtom> GetUncachedLanguageGroup(nsAtom* aLanguage) const;
+  nsStaticAtom* GetLanguageGroup(nsAtom* aLanguage,
+                                 bool* aNeedsToCache = nullptr);
+  nsStaticAtom* GetUncachedLanguageGroup(nsAtom* aLanguage) const;
 
  private:
-  nsRefPtrHashtable<nsRefPtrHashKey<nsAtom>, nsAtom> mLangToGroup;
+  nsDataHashtable<nsRefPtrHashKey<nsAtom>, nsStaticAtom*> mLangToGroup;
   RefPtr<nsAtom> mLocaleLanguage;
 };
 
 #endif
--- a/layout/base/StaticPresData.h
+++ b/layout/base/StaticPresData.h
@@ -100,17 +100,17 @@ struct LangGroupFontPrefs {
         return &mDefaultFantasyFont;
         break;
       default:
         MOZ_ASSERT_UNREACHABLE("invalid font id");
         return nullptr;
     }
   }
 
-  RefPtr<nsAtom> mLangGroup;
+  nsStaticAtom* mLangGroup;
   nscoord mMinimumFontSize;
   nsFont mDefaultVariableFont;
   nsFont mDefaultFixedFont;
   nsFont mDefaultSerifFont;
   nsFont mDefaultSansSerifFont;
   nsFont mDefaultMonospaceFont;
   nsFont mDefaultCursiveFont;
   nsFont mDefaultFantasyFont;
@@ -146,23 +146,22 @@ class StaticPresData {
    * a style worker thread without the lock acquired).  In this case,
    * GetLanguageGroup will store true in *aNeedsToCache true if we
    * would have cached the result of a new lookup, and false if we
    * were able to use an existing cached result.  Thus, callers that
    * get a true *aNeedsToCache outparam value should make an effort
    * to re-call GetLanguageGroup when it is safe to cache, to avoid
    * recomputing the language group again later.
    */
-  nsAtom* GetLangGroup(nsAtom* aLanguage, bool* aNeedsToCache = nullptr) const;
+  nsStaticAtom* GetLangGroup(nsAtom* aLanguage, bool* aNeedsToCache = nullptr) const;
 
   /**
    * Same as GetLangGroup, but will not cache the result
-   *
    */
-  already_AddRefed<nsAtom> GetUncachedLangGroup(nsAtom* aLanguage) const;
+  nsStaticAtom* GetUncachedLangGroup(nsAtom* aLanguage) const;
 
   /**
    * Fetch the user's font preferences for the given aLanguage's
    * langugage group.
    *
    * The original code here is pretty old, and includes an optimization
    * whereby language-specific prefs are read per-document, and the
    * results are stored in a linked list, which is assumed to be very short
@@ -178,16 +177,16 @@ class StaticPresData {
   const LangGroupFontPrefs* GetFontPrefsForLangHelper(
       nsAtom* aLanguage, const LangGroupFontPrefs* aPrefs,
       bool* aNeedsToCache = nullptr) const;
   const nsFont* GetDefaultFontHelper(uint8_t aFontID, nsAtom* aLanguage,
                                      const LangGroupFontPrefs* aPrefs) const;
 
  private:
   StaticPresData();
-  ~StaticPresData() {}
+  ~StaticPresData() = default;
 
   nsLanguageAtomService* mLangService;
 };
 
 }  // namespace mozilla
 
 #endif  // mozilla_StaticPresData_h
--- a/layout/style/GeckoBindings.cpp
+++ b/layout/style/GeckoBindings.cpp
@@ -1962,23 +1962,21 @@ void FontSizePrefs::CopyFrom(const LangG
   mDefaultSansSerifSize = prefs.mDefaultSansSerifFont.size;
   mDefaultMonospaceSize = prefs.mDefaultMonospaceFont.size;
   mDefaultCursiveSize = prefs.mDefaultCursiveFont.size;
   mDefaultFantasySize = prefs.mDefaultFantasyFont.size;
 }
 
 FontSizePrefs Gecko_GetBaseSize(nsAtom* aLanguage) {
   LangGroupFontPrefs prefs;
-  RefPtr<nsAtom> langGroupAtom =
+  nsStaticAtom* langGroupAtom =
       StaticPresData::Get()->GetUncachedLangGroup(aLanguage);
-
   prefs.Initialize(langGroupAtom);
   FontSizePrefs sizes;
   sizes.CopyFrom(prefs);
-
   return sizes;
 }
 
 RawGeckoElementBorrowedOrNull Gecko_GetBindingParent(
     RawGeckoElementBorrowed aElement) {
   nsIContent* parent = aElement->GetBindingParent();
   return parent ? parent->AsElement() : nullptr;
 }