Bug 1370802: Make the lang rule operate on atoms, not strings. r=heycam
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 16 Jun 2017 23:59:08 +0200
changeset 415785 c1f31a96126f1f50e7f8514146582385912ab1c9
parent 415784 fd9e6e55b4f488889e836b60b3fa64368edec657
child 415786 499a91e7887f2523775153a4e114dac26c9eb854
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1370802
milestone56.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 1370802: Make the lang rule operate on atoms, not strings. r=heycam MozReview-Commit-ID: KG9i4Mc3ovN
layout/style/nsHTMLStyleSheet.cpp
layout/style/nsHTMLStyleSheet.h
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -151,17 +151,18 @@ GetDiscretelyAnimatedCSSValue(nsCSSPrope
 NS_IMPL_ISUPPORTS(nsHTMLStyleSheet::LangRule, nsIStyleRule)
 
 /* virtual */ void
 nsHTMLStyleSheet::LangRule::MapRuleInfoInto(nsRuleData* aRuleData)
 {
   if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) {
     nsCSSValue* lang = aRuleData->ValueForLang();
     if (lang->GetUnit() == eCSSUnit_Null) {
-      lang->SetStringValue(mLang, eCSSUnit_Ident);
+      nsCOMPtr<nsIAtom> langAtom = mLang;
+      lang->SetAtomIdentValue(langAtom.forget());
     }
   }
 }
 
 /* virtual */ bool
 nsHTMLStyleSheet::LangRule::MightMapInheritedStyleData()
 {
   return true;
@@ -179,17 +180,17 @@ GetDiscretelyAnimatedCSSValue(nsCSSPrope
 /* virtual */ void
 nsHTMLStyleSheet::LangRule::List(FILE* out, int32_t aIndent) const
 {
   nsAutoCString str;
   for (int32_t index = aIndent; --index >= 0; ) {
     str.AppendLiteral("  ");
   }
   str.AppendLiteral("[lang rule] { language: \"");
-  AppendUTF16toUTF8(mLang, str);
+  AppendUTF16toUTF8(nsDependentAtomString(mLang), str);
   str.AppendLiteral("\" }\n");
   fprintf_stderr(out, "%s", str.get());
 }
 #endif
 
 // -----------------------------------------------------------
 
 struct MappedAttrTableEntry : public PLDHashEntryHdr {
@@ -237,47 +238,47 @@ static const PLDHashTableOps MappedAttrT
 
 struct LangRuleTableEntry : public PLDHashEntryHdr {
   RefPtr<nsHTMLStyleSheet::LangRule> mRule;
 };
 
 static PLDHashNumber
 LangRuleTable_HashKey(const void *key)
 {
-  const nsString *lang = static_cast<const nsString*>(key);
-  return HashString(*lang);
+  auto* lang = static_cast<const nsIAtom*>(key);
+  return lang->hash();
 }
 
 static void
 LangRuleTable_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
 {
   LangRuleTableEntry *entry = static_cast<LangRuleTableEntry*>(hdr);
 
   entry->~LangRuleTableEntry();
   memset(entry, 0, sizeof(LangRuleTableEntry));
 }
 
 static bool
 LangRuleTable_MatchEntry(const PLDHashEntryHdr *hdr, const void *key)
 {
-  const nsString *lang = static_cast<const nsString*>(key);
+  auto* lang = static_cast<const nsIAtom*>(key);
   const LangRuleTableEntry *entry = static_cast<const LangRuleTableEntry*>(hdr);
 
-  return entry->mRule->mLang == *lang;
+  return entry->mRule->mLang == lang;
 }
 
 static void
 LangRuleTable_InitEntry(PLDHashEntryHdr *hdr, const void *key)
 {
-  const nsString *lang = static_cast<const nsString*>(key);
+  auto* lang = static_cast<const nsIAtom*>(key);
 
-  LangRuleTableEntry *entry = new (KnownNotNull, hdr) LangRuleTableEntry();
+  LangRuleTableEntry* entry = new (KnownNotNull, hdr) LangRuleTableEntry();
 
   // Create the unique rule for this language
-  entry->mRule = new nsHTMLStyleSheet::LangRule(*lang);
+  entry->mRule = new nsHTMLStyleSheet::LangRule(const_cast<nsIAtom*>(lang));
 }
 
 static const PLDHashTableOps LangRuleTable_Ops = {
   LangRuleTable_HashKey,
   LangRuleTable_MatchEntry,
   PLDHashTable::MoveEntryStub,
   LangRuleTable_ClearEntry,
   LangRuleTable_InitEntry
@@ -345,26 +346,27 @@ nsHTMLStyleSheet::RulesMatching(ElementR
   // considered style.
   if (!ruleWalker->AuthorStyleDisabled() || aData->mElement->IsSVGElement()) {
     aData->mElement->WalkContentStyleRules(ruleWalker);
   }
 
   // http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#language
   // says that the xml:lang attribute overrides HTML's lang attribute,
   // so we need to do this after WalkContentStyleRules.
-  nsString lang;
-  if (aData->mElement->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang, lang)) {
-    ruleWalker->Forward(LangRuleFor(lang));
+  const nsAttrValue* langAttr =
+    aData->mElement->GetParsedAttr(nsGkAtoms::lang, kNameSpaceID_XML);
+  if (langAttr) {
+    MOZ_ASSERT(langAttr->Type() == nsAttrValue::eAtom);
+    ruleWalker->Forward(LangRuleFor(langAttr->GetAtomValue()));
   }
 
   // Set the language to "x-math" on the <math> element, so that appropriate
   // font settings are used for MathML.
   if (aData->mElement->IsMathMLElement(nsGkAtoms::math)) {
-    nsGkAtoms::x_math->ToString(lang);
-    ruleWalker->Forward(LangRuleFor(lang));
+    ruleWalker->Forward(LangRuleFor(nsGkAtoms::x_math));
   }
 }
 
 // Test if style is dependent on content state
 /* virtual */ nsRestyleHint
 nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData)
 {
   if (aData->mElement->IsHTMLElement(nsGkAtoms::a) &&
@@ -584,20 +586,29 @@ nsHTMLStyleSheet::CalculateMappedServoDe
       // Only handle cases which haven't been filled in already
       continue;
     }
     attr->mAttributes->LazilyResolveServoDeclaration(aPresContext);
   }
 }
 
 nsIStyleRule*
-nsHTMLStyleSheet::LangRuleFor(const nsString& aLanguage)
+nsHTMLStyleSheet::LangRuleFor(const nsIAtom* aLanguage)
 {
+  Maybe<nsCOMPtr<nsIAtom>> lowerAtom;
+  nsDependentAtomString langString(aLanguage);
+  if (nsContentUtils::StringContainsASCIIUpper(langString)) {
+    nsString dest;
+    nsContentUtils::ASCIIToLower(langString, dest);
+    lowerAtom.emplace(NS_AtomizeMainThread(dest));
+  }
+
+  const nsIAtom* key = lowerAtom ? *lowerAtom : aLanguage;
   auto entry =
-    static_cast<LangRuleTableEntry*>(mLangRuleTable.Add(&aLanguage, fallible));
+    static_cast<LangRuleTableEntry*>(mLangRuleTable.Add(key, fallible));
   if (!entry) {
     NS_ASSERTION(false, "out of memory");
     return nullptr;
   }
   return entry->mRule;
 }
 
 size_t
--- a/layout/style/nsHTMLStyleSheet.h
+++ b/layout/style/nsHTMLStyleSheet.h
@@ -9,16 +9,17 @@
  * HTML attributes
  */
 
 #ifndef nsHTMLStyleSheet_h_
 #define nsHTMLStyleSheet_h_
 
 #include "nsColor.h"
 #include "nsCOMPtr.h"
+#include "nsIAtom.h"
 #include "nsIStyleRule.h"
 #include "nsIStyleRuleProcessor.h"
 #include "PLDHashTable.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsString.h"
 
 class nsIDocument;
@@ -73,19 +74,19 @@ public:
   already_AddRefed<nsMappedAttributes>
     UniqueMappedAttributes(nsMappedAttributes* aMapped);
   void DropMappedAttributes(nsMappedAttributes* aMapped);
   // For each mapped presentation attribute in the cache, resolve
   // the attached ServoDeclarationBlock by running the mapping
   // and converting the ruledata to Servo specified values.
   void CalculateMappedServoDeclarations(nsPresContext* aPresContext);
 
-  nsIStyleRule* LangRuleFor(const nsString& aLanguage);
+  nsIStyleRule* LangRuleFor(const nsIAtom* aLanguage);
 
-private: 
+private:
   nsHTMLStyleSheet(const nsHTMLStyleSheet& aCopy) = delete;
   nsHTMLStyleSheet& operator=(const nsHTMLStyleSheet& aCopy) = delete;
 
   ~nsHTMLStyleSheet() {}
 
   class HTMLColorRule;
   friend class HTMLColorRule;
   class HTMLColorRule final : public nsIStyleRule {
@@ -164,30 +165,30 @@ public: // for mLangRuleTable structures
   // Rule to handle xml:lang attributes, of which we have exactly one
   // per language string, maintained in mLangRuleTable.
   // We also create one extra rule for the "x-math" language string, used on
   // <math> elements.
   class LangRule final : public nsIStyleRule {
   private:
     ~LangRule() {}
   public:
-    explicit LangRule(const nsSubstring& aLang) : mLang(aLang) {}
+    explicit LangRule(nsIAtom* aLang) : mLang(aLang) {}
 
     NS_DECL_ISUPPORTS
 
     // nsIStyleRule interface
     virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
     virtual bool MightMapInheritedStyleData() override;
     virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
                                                nsCSSValue* aValue) override;
   #ifdef DEBUG
     virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
   #endif
 
-    nsString mLang;
+    nsCOMPtr<nsIAtom> mLang;
   };
 
 private:
   nsIDocument*            mDocument;
   RefPtr<HTMLColorRule> mLinkRule;
   RefPtr<HTMLColorRule> mVisitedRule;
   RefPtr<HTMLColorRule> mActiveRule;
   RefPtr<RawServoDeclarationBlock> mServoUnvisitedLinkDecl;