Bug 1393189 part 1 - Statically initialize builtin style table with their name atom included. r?dholbert draft
authorXidorn Quan <me@upsuper.org>
Tue, 29 Aug 2017 14:44:14 +1000
changeset 656370 cd3dc60cb7a2bf23b6f7a5dbdfb4c992c15796a7
parent 655506 ecc2d3e6c6185891f01d38fb444258dcd3dcc7ff
child 656371 ee1fef0b9b5af8718792d532185f4229b9f38a23
push id77188
push userxquan@mozilla.com
push dateThu, 31 Aug 2017 04:04:58 +0000
reviewersdholbert
bugs1393189, 966166
milestone57.0a1
Bug 1393189 part 1 - Statically initialize builtin style table with their name atom included. r?dholbert Doing this at compile time would save a bit of our startup time, which I've promised to do since @counter-style was initially implemented, see bug 966166 comment 103 (the paragraph with "constexpr"). Also, having this implemented here makes using atom instead of string on name of builtin counter styles easier, for later patches. MozReview-Commit-ID: C9HYcuShBQv
dom/base/nsGkAtomList.h
layout/build/nsLayoutStatics.cpp
layout/style/BuiltinCounterStyleList.h
layout/style/CounterStyleManager.cpp
layout/style/CounterStyleManager.h
layout/style/nsStyleConsts.h
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -343,16 +343,18 @@ GK_ATOM(dir, "dir")
 GK_ATOM(dirAutoSetBy, "dirAutoSetBy")
 GK_ATOM(directionality, "directionality")
 GK_ATOM(directory, "directory")
 GK_ATOM(disableOutputEscaping, "disable-output-escaping")
 GK_ATOM(disabled, "disabled")
 GK_ATOM(disableglobalhistory, "disableglobalhistory")
 GK_ATOM(disablehistory, "disablehistory")
 GK_ATOM(disablefullscreen, "disablefullscreen")
+GK_ATOM(disclosure_closed, "disclosure-closed")
+GK_ATOM(disclosure_open, "disclosure-open")
 GK_ATOM(display, "display")
 GK_ATOM(displayMode, "display-mode")
 GK_ATOM(distinct, "distinct")
 GK_ATOM(div, "div")
 GK_ATOM(dl, "dl")
 GK_ATOM(docAbstract, "doc-abstract")
 GK_ATOM(docAcknowledgments, "doc-acknowledgments")
 GK_ATOM(docAfterword, "doc-afterword")
@@ -437,16 +439,17 @@ GK_ATOM(empty, "empty")
 GK_ATOM(encoding, "encoding")
 GK_ATOM(enctype, "enctype")
 GK_ATOM(end, "end")
 GK_ATOM(endEvent, "endEvent")
 GK_ATOM(end_after, "end_after")
 GK_ATOM(end_before, "end_before")
 GK_ATOM(equalsize, "equalsize")
 GK_ATOM(error, "error")
+GK_ATOM(ethiopic_numeric, "ethiopic-numeric")
 GK_ATOM(even, "even")
 GK_ATOM(event, "event")
 GK_ATOM(events, "events")
 GK_ATOM(excludeResultPrefixes, "exclude-result-prefixes")
 GK_ATOM(excludes, "excludes")
 GK_ATOM(expr, "expr")
 GK_ATOM(extends, "extends")
 GK_ATOM(extensionElementPrefixes, "extension-element-prefixes")
@@ -518,16 +521,17 @@ GK_ATOM(handler, "handler")
 GK_ATOM(handlers, "handlers")
 GK_ATOM(HARD, "HARD")
 GK_ATOM(haspopup, "haspopup")
 GK_ATOM(hasSameNode, "has-same-node")
 GK_ATOM(hbox, "hbox")
 GK_ATOM(head, "head")
 GK_ATOM(header, "header")
 GK_ATOM(headers, "headers")
+GK_ATOM(hebrew, "hebrew")
 GK_ATOM(height, "height")
 GK_ATOM(hgroup, "hgroup")
 GK_ATOM(hidden, "hidden")
 GK_ATOM(hidechrome, "hidechrome")
 GK_ATOM(hidecolumnpicker, "hidecolumnpicker")
 GK_ATOM(high, "high")
 GK_ATOM(highest, "highest")
 GK_ATOM(horizontal, "horizontal")
@@ -582,30 +586,35 @@ GK_ATOM(is, "is")
 GK_ATOM(iscontainer, "iscontainer")
 GK_ATOM(isempty, "isempty")
 GK_ATOM(ismap, "ismap")
 GK_ATOM(itemid, "itemid")
 GK_ATOM(itemprop, "itemprop")
 GK_ATOM(itemref, "itemref")
 GK_ATOM(itemscope, "itemscope")
 GK_ATOM(itemtype, "itemtype")
+GK_ATOM(japanese_formal, "japanese-formal")
+GK_ATOM(japanese_informal, "japanese-informal")
 GK_ATOM(kbd, "kbd")
 GK_ATOM(keepcurrentinview, "keepcurrentinview")
 GK_ATOM(keepobjectsalive, "keepobjectsalive")
 GK_ATOM(key, "key")
 GK_ATOM(keycode, "keycode")
 GK_ATOM(keystatuseschange, "keystatuseschange")
 GK_ATOM(keydown, "keydown")
 GK_ATOM(keygen, "keygen")
 GK_ATOM(keypress, "keypress")
 GK_ATOM(keyset, "keyset")
 GK_ATOM(keysystem, "keysystem")
 GK_ATOM(keytext, "keytext")
 GK_ATOM(keyup, "keyup")
 GK_ATOM(kind, "kind")
+GK_ATOM(korean_hangul_formal, "korean-hangul-formal")
+GK_ATOM(korean_hanja_formal, "korean-hanja-formal")
+GK_ATOM(korean_hanja_informal, "korean-hanja-informal")
 GK_ATOM(label, "label")
 GK_ATOM(labels, "labels")
 GK_ATOM(lang, "lang")
 GK_ATOM(language, "language")
 GK_ATOM(last, "last")
 GK_ATOM(layer, "layer")
 GK_ATOM(LayerActivity, "LayerActivity")
 GK_ATOM(layout, "layout")
@@ -1226,16 +1235,18 @@ GK_ATOM(self, "self")
 GK_ATOM(seltype, "seltype")
 GK_ATOM(setcookie, "set-cookie")
 GK_ATOM(setter, "setter")
 GK_ATOM(shape, "shape")
 GK_ATOM(show, "show")
 GK_ATOM(showcaret, "showcaret")
 GK_ATOM(showresizer, "showresizer")
 GK_ATOM(simple, "simple")
+GK_ATOM(simp_chinese_formal, "simp-chinese-formal")
+GK_ATOM(simp_chinese_informal, "simp-chinese-informal")
 GK_ATOM(single, "single")
 GK_ATOM(size, "size")
 GK_ATOM(sizes, "sizes")
 GK_ATOM(sizemode, "sizemode")
 GK_ATOM(sizetopopup, "sizetopopup")
 GK_ATOM(slider, "slider")
 GK_ATOM(small, "small")
 GK_ATOM(smooth, "smooth")
@@ -1340,16 +1351,18 @@ GK_ATOM(tooltip, "tooltip")
 GK_ATOM(tooltiptext, "tooltiptext")
 GK_ATOM(top, "top")
 GK_ATOM(topleft, "topleft")
 GK_ATOM(topmargin, "topmargin")
 GK_ATOM(toppadding, "toppadding")
 GK_ATOM(topright, "topright")
 GK_ATOM(tr, "tr")
 GK_ATOM(track, "track")
+GK_ATOM(trad_chinese_formal, "trad-chinese-formal")
+GK_ATOM(trad_chinese_informal, "trad-chinese-informal")
 GK_ATOM(trailing, "trailing")
 GK_ATOM(transform, "transform")
 GK_ATOM(transform_3d, "transform-3d")
 GK_ATOM(transformiix, "transformiix")
 GK_ATOM(translate, "translate")
 GK_ATOM(transparent, "transparent")
 GK_ATOM(tree, "tree")
 GK_ATOM(treecell, "treecell")
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -62,17 +62,16 @@
 #include "nsSVGUtils.h"
 #include "nsMathMLAtoms.h"
 #include "nsMathMLOperators.h"
 #include "Navigator.h"
 #include "StorageObserver.h"
 #include "CacheObserver.h"
 #include "DisplayItemClip.h"
 #include "ActiveLayerTracker.h"
-#include "CounterStyleManager.h"
 #include "FrameLayerBuilder.h"
 #include "AnimationCommon.h"
 #include "LayerAnimationInfo.h"
 
 #include "AudioChannelService.h"
 #include "mozilla/dom/PromiseDebugging.h"
 #include "mozilla/dom/WebCryptoThreadPool.h"
 
@@ -281,18 +280,16 @@ nsLayoutStatics::Initialize()
   nsGenericHTMLFrameElement::InitStatics();
 
 #ifdef MOZ_XUL
   nsMenuBarListener::InitializeStatics();
 #endif
 
   CacheObserver::Init();
 
-  CounterStyleManager::InitializeBuiltinCounterStyles();
-
   IMEStateManager::Init();
 
   ServiceWorkerRegistrar::Initialize();
 
 #ifdef DEBUG
   GeckoStyleContext::Initialize();
   mozilla::LayerAnimationInfo::Initialize();
 #endif
new file mode 100644
--- /dev/null
+++ b/layout/style/BuiltinCounterStyleList.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* a list of all builtin counter styles */
+
+/* Each entry is defined as a BUILTIN_COUNTER_STYLE macro with the
+ * following parameters:
+ * - 'value_' which is final part of name of NS_STYLE_LIST_STYLE_* macros
+ * - 'atom_' which is the corresponding atom in nsGkAtoms table
+ *
+ * Users of this list should define the following macro before including
+ * this file: BUILTIN_COUNTER_STYLE(value_, atom_)
+ */
+
+// none and decimal are not redefinable, so they have to be builtin.
+BUILTIN_COUNTER_STYLE(NONE, none)
+BUILTIN_COUNTER_STYLE(DECIMAL, decimal)
+// the following graphic styles are processed in a different way.
+BUILTIN_COUNTER_STYLE(DISC, disc)
+BUILTIN_COUNTER_STYLE(CIRCLE, circle)
+BUILTIN_COUNTER_STYLE(SQUARE, square)
+BUILTIN_COUNTER_STYLE(DISCLOSURE_CLOSED, disclosure_closed)
+BUILTIN_COUNTER_STYLE(DISCLOSURE_OPEN, disclosure_open)
+// the following counter styles require specific algorithms to generate.
+BUILTIN_COUNTER_STYLE(HEBREW, hebrew)
+BUILTIN_COUNTER_STYLE(JAPANESE_INFORMAL, japanese_informal)
+BUILTIN_COUNTER_STYLE(JAPANESE_FORMAL, japanese_formal)
+BUILTIN_COUNTER_STYLE(KOREAN_HANGUL_FORMAL, korean_hangul_formal)
+BUILTIN_COUNTER_STYLE(KOREAN_HANJA_INFORMAL, korean_hanja_informal)
+BUILTIN_COUNTER_STYLE(KOREAN_HANJA_FORMAL, korean_hanja_formal)
+BUILTIN_COUNTER_STYLE(SIMP_CHINESE_INFORMAL, simp_chinese_informal)
+BUILTIN_COUNTER_STYLE(SIMP_CHINESE_FORMAL, simp_chinese_formal)
+BUILTIN_COUNTER_STYLE(TRAD_CHINESE_INFORMAL, trad_chinese_informal)
+BUILTIN_COUNTER_STYLE(TRAD_CHINESE_FORMAL, trad_chinese_formal)
+BUILTIN_COUNTER_STYLE(ETHIOPIC_NUMERIC, ethiopic_numeric)
--- a/layout/style/CounterStyleManager.cpp
+++ b/layout/style/CounterStyleManager.cpp
@@ -570,31 +570,22 @@ SystemUsesNegativeSign(uint8_t aSystem)
     default:
       return false;
   }
 }
 
 class BuiltinCounterStyle : public CounterStyle
 {
 public:
-  friend class CounterStyleManager;
-
-  // will be initialized by CounterStyleManager::InitializeBuiltinCounterStyles
-  constexpr BuiltinCounterStyle()
-    : CounterStyle(NS_STYLE_LIST_STYLE_NONE)
+  constexpr BuiltinCounterStyle(int32_t aStyle, nsIAtom** aName)
+    : CounterStyle(aStyle)
+    , mName(aName)
   {
   }
 
-protected:
-  constexpr explicit BuiltinCounterStyle(int32_t aStyle)
-    : CounterStyle(aStyle)
-  {
-  }
-
-public:
   virtual void GetStyleName(nsAString& aResult) override;
   virtual void GetPrefix(nsAString& aResult) override;
   virtual void GetSuffix(nsAString& aResult) override;
   virtual void GetSpokenCounterText(CounterValue aOrdinal,
                                     WritingMode aWritingMode,
                                     nsAString& aResult,
                                     bool& aIsBullet) override;
   virtual bool IsBullet() override;
@@ -606,16 +597,30 @@ public:
   virtual CounterStyle* GetFallback() override;
   virtual uint8_t GetSpeakAs() override;
   virtual bool UseNegativeSign() override;
 
   virtual bool GetInitialCounterText(CounterValue aOrdinal,
                                      WritingMode aWritingMode,
                                      nsAString& aResult,
                                      bool& aIsRTL) override;
+
+protected:
+  BuiltinCounterStyle(const BuiltinCounterStyle& aOther)
+    : CounterStyle(aOther.mStyle)
+    , mName(aOther.mName)
+  {
+  }
+
+private:
+  // The atom for the name of the builtin counter style.
+  // Extra indirection to point to nsGkAtoms members rather than the
+  // nsIAtom, because members of nsGkAtoms are updated at runtime but
+  // we want to construct BuiltinCounterStyle at compile time.
+  nsIAtom** const mName;
 };
 
 /* virtual */ void
 BuiltinCounterStyle::GetStyleName(nsAString& aResult)
 {
   MOZ_ASSERT(mStyle != NS_STYLE_LIST_STYLE_CUSTOM);
   const nsCString& str =
     nsCSSProps::ValueToKeyword(mStyle, nsCSSProps::kListStyleKTable);
@@ -951,21 +956,45 @@ BuiltinCounterStyle::GetInitialCounterTe
       return EthiopicToText(aOrdinal, aResult);
 
     default:
       NS_NOTREACHED("Unknown builtin counter style");
       return false;
   }
 }
 
+// MSVC 2015 has a bug that vtable pointer of constexpr objects is null,
+// which would cause startup crash. So const is used instead here for
+// pre-2017 version of MSVC to workaround this issue.
+#if !defined(_MSC_VER) || _MSC_VER >= 1910
+static constexpr BuiltinCounterStyle gBuiltinStyleTable[] =
+#else
+static const BuiltinCounterStyle gBuiltinStyleTable[] =
+#endif
+{
+#define BUILTIN_COUNTER_STYLE(value_, atom_) \
+  { NS_STYLE_LIST_STYLE_ ## value_, &nsGkAtoms::atom_ },
+#include "BuiltinCounterStyleList.h"
+#undef BUILTIN_COUNTER_STYLE
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1910
+#define BUILTIN_COUNTER_STYLE(value_, atom_) \
+  static_assert(gBuiltinStyleTable[NS_STYLE_LIST_STYLE_ ## value_].GetStyle() \
+                == NS_STYLE_LIST_STYLE_ ## value_, "Builtin counter style " \
+                #atom_ " has unmatched index and value.");
+#include "BuiltinCounterStyleList.h"
+#undef BUILTIN_COUNTER_STYLE
+#endif
+
 class DependentBuiltinCounterStyle final : public BuiltinCounterStyle
 {
 public:
   DependentBuiltinCounterStyle(int32_t aStyle, CounterStyleManager* aManager)
-    : BuiltinCounterStyle(aStyle),
+    : BuiltinCounterStyle(gBuiltinStyleTable[aStyle]),
       mManager(aManager)
   {
     NS_ASSERTION(IsDependentStyle(), "Not a dependent builtin style");
     MOZ_ASSERT(!IsCustomStyle(), "Not a builtin style");
   }
 
   virtual CounterStyle* GetFallback() override;
 
@@ -1964,40 +1993,30 @@ CounterStyle::GetSpokenCounterText(Count
 CounterStyle::CallFallbackStyle(CounterValue aOrdinal,
                                 WritingMode aWritingMode,
                                 nsAString& aResult,
                                 bool& aIsRTL)
 {
   GetFallback()->GetCounterText(aOrdinal, aWritingMode, aResult, aIsRTL);
 }
 
-static BuiltinCounterStyle gBuiltinStyleTable[NS_STYLE_LIST_STYLE__MAX];
-
 CounterStyleManager::CounterStyleManager(nsPresContext* aPresContext)
   : mPresContext(aPresContext)
 {
   // Insert the static styles into cache table
   mStyles.Put(nsGkAtoms::none, GetNoneStyle());
   mStyles.Put(nsGkAtoms::decimal, GetDecimalStyle());
   mStyles.Put(nsGkAtoms::disc, GetDiscStyle());
 }
 
 CounterStyleManager::~CounterStyleManager()
 {
   MOZ_ASSERT(!mPresContext, "Disconnect should have been called");
 }
 
-/* static */ void
-CounterStyleManager::InitializeBuiltinCounterStyles()
-{
-  for (uint32_t i = 0; i < NS_STYLE_LIST_STYLE__MAX; ++i) {
-    gBuiltinStyleTable[i].mStyle = i;
-  }
-}
-
 void
 CounterStyleManager::DestroyCounterStyle(CounterStyle* aCounterStyle)
 {
   if (aCounterStyle->IsCustomStyle()) {
     MOZ_ASSERT(!aCounterStyle->AsAnonymous(), "Anonymous counter styles "
                "are not managed by CounterStyleManager");
     static_cast<CustomCounterStyle*>(aCounterStyle)->Destroy();
   } else if (aCounterStyle->IsDependentStyle()) {
@@ -2054,21 +2073,23 @@ CounterStyleManager::BuildCounterStyle(n
   }
   mStyles.Put(aName, data);
   return data;
 }
 
 /* static */ CounterStyle*
 CounterStyleManager::GetBuiltinStyle(int32_t aStyle)
 {
-  MOZ_ASSERT(0 <= aStyle && aStyle < NS_STYLE_LIST_STYLE__MAX,
+  MOZ_ASSERT(0 <= aStyle && size_t(aStyle) < sizeof(gBuiltinStyleTable),
              "Require a valid builtin style constant");
   MOZ_ASSERT(!gBuiltinStyleTable[aStyle].IsDependentStyle(),
              "Cannot get dependent builtin style");
-  return &gBuiltinStyleTable[aStyle];
+  // No method of BuiltinCounterStyle mutates the struct itself, so it
+  // should be fine to cast const away.
+  return const_cast<BuiltinCounterStyle*>(&gBuiltinStyleTable[aStyle]);
 }
 
 bool
 CounterStyleManager::NotifyRuleChanged()
 {
   bool changed = false;
   for (auto iter = mStyles.Iter(); !iter.Done(); iter.Next()) {
     CounterStyle* style = iter.Data();
--- a/layout/style/CounterStyleManager.h
+++ b/layout/style/CounterStyleManager.h
@@ -39,17 +39,17 @@ protected:
   {
   }
 
 private:
   CounterStyle(const CounterStyle& aOther) = delete;
   void operator=(const CounterStyle& other) = delete;
 
 public:
-  int32_t GetStyle() const { return mStyle; }
+  constexpr int32_t GetStyle() const { return mStyle; }
   bool IsNone() const { return mStyle == NS_STYLE_LIST_STYLE_NONE; }
   bool IsCustomStyle() const { return mStyle == NS_STYLE_LIST_STYLE_CUSTOM; }
   // A style is dependent if it depends on the counter style manager.
   // Custom styles are certainly dependent. In addition, some builtin
   // styles are dependent for fallback.
   bool IsDependentStyle() const;
 
   virtual void GetStyleName(nsAString& aResult) = 0;
@@ -93,17 +93,17 @@ public:
   virtual bool GetInitialCounterText(CounterValue aOrdinal,
                                      WritingMode aWritingMode,
                                      nsAString& aResult,
                                      bool& aIsRTL) = 0;
 
   virtual AnonymousCounterStyle* AsAnonymous() { return nullptr; }
 
 protected:
-  int32_t mStyle;
+  const int32_t mStyle;
 };
 
 class AnonymousCounterStyle final : public CounterStyle
 {
 public:
   explicit AnonymousCounterStyle(const nsAString& aContent);
   AnonymousCounterStyle(uint8_t aSystem, nsTArray<nsString> aSymbols);
   explicit AnonymousCounterStyle(const nsCSSValue::Array* aValue);
@@ -309,18 +309,16 @@ private:
 
 class CounterStyleManager final
 {
 private:
   ~CounterStyleManager();
 public:
   explicit CounterStyleManager(nsPresContext* aPresContext);
 
-  static void InitializeBuiltinCounterStyles();
-
   void Disconnect();
 
   bool IsInitial() const
   {
     // only 'none', 'decimal', and 'disc'
     return mStyles.Count() == 3;
   }
 
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -790,17 +790,16 @@ enum class StyleGridTrackBreadth : uint8
 #define NS_STYLE_LIST_STYLE_KOREAN_HANGUL_FORMAL  10
 #define NS_STYLE_LIST_STYLE_KOREAN_HANJA_INFORMAL 11
 #define NS_STYLE_LIST_STYLE_KOREAN_HANJA_FORMAL   12
 #define NS_STYLE_LIST_STYLE_SIMP_CHINESE_INFORMAL 13
 #define NS_STYLE_LIST_STYLE_SIMP_CHINESE_FORMAL   14
 #define NS_STYLE_LIST_STYLE_TRAD_CHINESE_INFORMAL 15
 #define NS_STYLE_LIST_STYLE_TRAD_CHINESE_FORMAL   16
 #define NS_STYLE_LIST_STYLE_ETHIOPIC_NUMERIC      17
-#define NS_STYLE_LIST_STYLE__MAX                  18
 // These styles are handled as custom styles defined in counterstyles.css.
 // They are preserved here only for html attribute map.
 #define NS_STYLE_LIST_STYLE_LOWER_ROMAN           100
 #define NS_STYLE_LIST_STYLE_UPPER_ROMAN           101
 #define NS_STYLE_LIST_STYLE_LOWER_ALPHA           102
 #define NS_STYLE_LIST_STYLE_UPPER_ALPHA           103
 
 // See nsStyleList