Bug 1299066: Fix the frame constructor breakage, avoid linear search in the frame constructor (prefer indexing). r?bz draft
authorEmilio Cobos Álvarez <ecoal95@gmail.com>
Tue, 30 Aug 2016 00:21:38 -0700
changeset 407300 8f12f35af4e50831f425c7c8319369048b14e27a
parent 407275 10ee4b1cbe82227141a1a2223829ddda4ed63bbf
child 529836 b1dd1aa3faf98947e04fd32be28e317c42df2970
push id27922
push userbmo:ecoal95@gmail.com
push dateTue, 30 Aug 2016 07:25:01 +0000
reviewersbz
bugs1299066
milestone51.0a1
Bug 1299066: Fix the frame constructor breakage, avoid linear search in the frame constructor (prefer indexing). r?bz MozReview-Commit-ID: JEsLjN07Quc
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/style/nsStyleConsts.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -376,22 +376,24 @@ static inline nsContainerFrame*
 GetFieldSetBlockFrame(nsIFrame* aFieldsetFrame)
 {
   // Depends on the fieldset child frame order - see ConstructFieldSetFrame() below.
   nsIFrame* firstChild = aFieldsetFrame->PrincipalChildList().FirstChild();
   nsIFrame* inner = firstChild && firstChild->GetNextSibling() ? firstChild->GetNextSibling() : firstChild;
   return inner ? inner->GetContentInsertionFrame() : nullptr;
 }
 
-#define FCDATA_DECL(_flags, _func)                          \
+#define FCDATA_DECL(_flags, _func)                            \
   { _flags, { (FrameCreationFunc)_func }, nullptr, nullptr }
 #define FCDATA_WITH_WRAPPING_BLOCK(_flags, _func, _anon_box)  \
   { _flags | FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS,        \
       { (FrameCreationFunc)_func }, nullptr, &_anon_box }
 
+#define UNREACHABLE_FCDATA()                                  \
+  { 0, { (FrameCreationFunc)nullptr }, nullptr, nullptr }
 //----------------------------------------------------------------------
 
 /**
  * True if aFrame is an actual inline frame in the sense of non-replaced
  * display:inline CSS boxes.  In other words, it can be affected by {ib}
  * splitting and can contain first-letter frames.  Basically, this is either an
  * inline frame (positioned or otherwise) or an line frame (this last because
  * it can contain first-letter and because inserting blocks in the middle of it
@@ -2166,21 +2168,21 @@ MakeTablePartAbsoluteContainingBlockIfNe
 
 nsIFrame*
 nsCSSFrameConstructor::ConstructTableRowOrRowGroup(nsFrameConstructorState& aState,
                                                    FrameConstructionItem&   aItem,
                                                    nsContainerFrame*        aParentFrame,
                                                    const nsStyleDisplay*    aDisplay,
                                                    nsFrameItems&            aFrameItems)
 {
-  NS_PRECONDITION(aDisplay->mDisplay == StyleDisplay::TableRow ||
-                  aDisplay->mDisplay == StyleDisplay::TableRowGroup ||
-                  aDisplay->mDisplay == StyleDisplay::TableFooterGroup ||
-                  aDisplay->mDisplay == StyleDisplay::TableHeaderGroup,
-                  "Unexpected call");
+  MOZ_ASSERT(aDisplay->mDisplay == StyleDisplay::TableRow ||
+             aDisplay->mDisplay == StyleDisplay::TableRowGroup ||
+             aDisplay->mDisplay == StyleDisplay::TableFooterGroup ||
+             aDisplay->mDisplay == StyleDisplay::TableHeaderGroup,
+             "Not a row or row group");
   MOZ_ASSERT(aItem.mStyleContext->StyleDisplay() == aDisplay,
              "Display style doesn't match style context");
   nsIContent* const content = aItem.mContent;
   nsStyleContext* const styleContext = aItem.mStyleContext;
   const uint32_t nameSpaceID = aItem.mNameSpaceID;
 
   nsContainerFrame* newFrame;
   if (aDisplay->mDisplay == StyleDisplay::TableRow) {
@@ -2251,18 +2253,18 @@ nsCSSFrameConstructor::ConstructTableCol
 
 nsIFrame*
 nsCSSFrameConstructor::ConstructTableCell(nsFrameConstructorState& aState,
                                           FrameConstructionItem&   aItem,
                                           nsContainerFrame*        aParentFrame,
                                           const nsStyleDisplay*    aDisplay,
                                           nsFrameItems&            aFrameItems)
 {
-  NS_PRECONDITION(aDisplay->mDisplay == StyleDisplay::TableCell,
-                  "Unexpected call");
+  MOZ_ASSERT(aDisplay->mDisplay == StyleDisplay::TableCell,
+             "Unexpected call");
 
   nsIContent* const content = aItem.mContent;
   nsStyleContext* const styleContext = aItem.mStyleContext;
   const uint32_t nameSpaceID = aItem.mNameSpaceID;
 
   nsTableFrame* tableFrame =
     static_cast<nsTableRowFrame*>(aParentFrame)->GetTableFrame();
   nsContainerFrame* newFrame;
@@ -2579,17 +2581,16 @@ nsCSSFrameConstructor::ConstructDocEleme
     newFrame = contentFrame;
     processChildren = true;
 
     newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
     if (display->IsAbsPosContainingBlock(newFrame)) {
       state.PushAbsoluteContainingBlock(contentFrame, newFrame,
                                         absoluteSaveState);
     }
-
   } else if (display->mDisplay == StyleDisplay::Table) {
     // We're going to call the right function ourselves, so no need to give a
     // function to this FrameConstructionData.
 
     // XXXbz on the other hand, if we converted this whole function to
     // FrameConstructionData/Item, then we'd need the right function
     // here... but would probably be able to get away with less code in this
     // function in general.
@@ -4307,22 +4308,22 @@ bool IsXULDisplayType(const nsStyleDispl
 #define SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func)                   \
   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                             \
               FCDATA_MAY_NEED_SCROLLFRAME, _func)
 
 #define SIMPLE_XUL_CREATE(_tag, _func)            \
   { &nsGkAtoms::_tag, SIMPLE_XUL_FCDATA(_func) }
 #define SCROLLABLE_XUL_CREATE(_tag, _func)            \
   { &nsGkAtoms::_tag, SCROLLABLE_XUL_FCDATA(_func) }
-#define SIMPLE_XUL_INT_CREATE(_int, _func)      \
-  { _int, SIMPLE_XUL_FCDATA(_func) }
-#define SCROLLABLE_XUL_INT_CREATE(_int, _func)                          \
-  { _int, SCROLLABLE_XUL_FCDATA(_func) }
-#define SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(_int, _func)         \
-  { _int, SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func) }
+#define SIMPLE_XUL_DISPLAY_CREATE(_int, _func)      \
+  FCDATA_FOR_DISPLAY(_int, SIMPLE_XUL_FCDATA(_func))
+#define SCROLLABLE_XUL_DISPLAY_CREATE(_int, _func)                          \
+  FCDATA_FOR_DISPLAY(_int, SCROLLABLE_XUL_FCDATA(_func))
+#define SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(_int, _func)         \
+  FCDATA_FOR_DISPLAY(_int, SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func))
 
 static
 nsIFrame* NS_NewGridBoxFrame(nsIPresShell* aPresShell,
                              nsStyleContext* aStyleContext)
 {
   nsCOMPtr<nsBoxLayout> layout;
   NS_NewGridLayout2(aPresShell, getter_AddRefs(layout));
   return NS_NewBoxFrame(aPresShell, aStyleContext, false, layout);
@@ -4478,59 +4479,68 @@ nsCSSFrameConstructor::FindXULListBoxBod
   return &sListBoxBodyData;
 }
 
 /* static */
 const nsCSSFrameConstructor::FrameConstructionData*
 nsCSSFrameConstructor::FindXULListItemData(Element* aElement,
                                            nsStyleContext* aStyleContext)
 {
-  if (aStyleContext->StyleDisplay()->mDisplay !=
-        StyleDisplay::XulGridLine) {
+  if (aStyleContext->StyleDisplay()->mDisplay != StyleDisplay::XulGridLine) {
     return nullptr;
   }
 
   static const FrameConstructionData sListItemData =
     SCROLLABLE_XUL_FCDATA(NS_NewListItemFrame);
   return &sListItemData;
 }
 
 #endif /* MOZ_XUL */
 
 /* static */
 const nsCSSFrameConstructor::FrameConstructionData*
 nsCSSFrameConstructor::FindXULDisplayData(const nsStyleDisplay* aDisplay,
                                           Element* aElement,
                                           nsStyleContext* aStyleContext)
 {
-  static const FrameConstructionDataByInt sXULDisplayData[] = {
-    SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(StyleDisplay::InlineBox,
-                                               NS_NewBoxFrame),
-    SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(StyleDisplay::Box,
-                                               NS_NewBoxFrame),
+  static const FrameConstructionDataByDisplay sXULDisplayData[] = {
+    SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(StyleDisplay::Box,
+                                                   NS_NewBoxFrame),
+    SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(StyleDisplay::InlineBox,
+                                                   NS_NewBoxFrame),
 #ifdef MOZ_XUL
-    SCROLLABLE_XUL_INT_CREATE(StyleDisplay::InlineXulGrid, NS_NewGridBoxFrame),
-    SCROLLABLE_XUL_INT_CREATE(StyleDisplay::XulGrid, NS_NewGridBoxFrame),
-    SCROLLABLE_XUL_INT_CREATE(StyleDisplay::XulGridGroup,
-                              NS_NewGridRowGroupFrame),
-    SCROLLABLE_XUL_INT_CREATE(StyleDisplay::XulGridLine,
-                              NS_NewGridRowLeafFrame),
-    SIMPLE_XUL_INT_CREATE(StyleDisplay::Deck, NS_NewDeckFrame),
-    SCROLLABLE_XUL_INT_CREATE(StyleDisplay::Groupbox, NS_NewGroupBoxFrame),
-    SCROLLABLE_XUL_INT_CREATE(StyleDisplay::InlineStack, NS_NewStackFrame),
-    SCROLLABLE_XUL_INT_CREATE(StyleDisplay::Stack, NS_NewStackFrame),
-    { StyleDisplay::Popup,
+    SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::XulGrid, NS_NewGridBoxFrame),
+    SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::InlineXulGrid, NS_NewGridBoxFrame),
+    SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::XulGridGroup,
+                                  NS_NewGridRowGroupFrame),
+    SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::XulGridLine,
+                                  NS_NewGridRowLeafFrame),
+    SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::Stack, NS_NewStackFrame),
+    SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::InlineStack, NS_NewStackFrame),
+    SIMPLE_XUL_DISPLAY_CREATE(StyleDisplay::Deck, NS_NewDeckFrame),
+    SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::Groupbox, NS_NewGroupBoxFrame),
+    FCDATA_FOR_DISPLAY(StyleDisplay::Popup,
       FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_IS_POPUP |
-                  FCDATA_SKIP_ABSPOS_PUSH, NS_NewMenuPopupFrame) }
+                  FCDATA_SKIP_ABSPOS_PUSH, NS_NewMenuPopupFrame))
 #endif /* MOZ_XUL */
   };
 
-  // Processing by display here:
-  return FindDataByInt(aDisplay->mDisplay, aElement, aStyleContext,
-                       sXULDisplayData, ArrayLength(sXULDisplayData));
+  if (aDisplay->mDisplay < StyleDisplay::Box) {
+    return nullptr;
+  }
+
+  MOZ_ASSERT(aDisplay->mDisplay <= StyleDisplay::Popup,
+             "Someone added a new display value?");
+
+  const FrameConstructionDataByDisplay& data =
+    sXULDisplayData[size_t(aDisplay->mDisplay) - size_t(StyleDisplay::Box)];
+  MOZ_ASSERT(aDisplay->mDisplay == data.mDisplay,
+             "Did someone mess with the order?");
+
+  return &data.mData;
 }
 
 already_AddRefed<nsStyleContext>
 nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState,
                                                 nsIContent*              aContent,
                                                 nsStyleContext*          aContentStyle,
                                                 nsContainerFrame*        aParentFrame,
                                                 nsIAtom*                 aScrolledPseudo,
@@ -4724,102 +4734,117 @@ nsCSSFrameConstructor::FindDisplayData(c
     }
     if (aDisplay->mDisplay == StyleDisplay::Grid) {
       static const FrameConstructionData sNonScrollableGridData =
         FCDATA_DECL(0, NS_NewGridContainerFrame);
       return &sNonScrollableGridData;
     }
   }
 
-  static const FrameConstructionDataByInt sDisplayData[] = {
-    // To keep the hash table small don't add inline frames (they're
-    // typically things like FONT and B), because we can quickly
-    // find them if we need to.
-    // XXXbz the "quickly" part is a bald-faced lie!
-    { StyleDisplay::Inline,
+  // To keep the hash table small don't add inline frames (they're
+  // typically things like FONT and B), because we can quickly
+  // find them if we need to.
+  // XXXbz the "quickly" part is a bald-faced lie!
+  //
+  // NOTE: Make sure to keep this up to date with the StyleDisplay definition!
+  static const FrameConstructionDataByDisplay sDisplayData[] = {
+    FCDATA_FOR_DISPLAY(StyleDisplay::None_, UNREACHABLE_FCDATA()),
+    FCDATA_FOR_DISPLAY(StyleDisplay::Block, UNREACHABLE_FCDATA()),
+    FCDATA_FOR_DISPLAY(StyleDisplay::Inline,
       FULL_CTOR_FCDATA(FCDATA_IS_INLINE | FCDATA_IS_LINE_PARTICIPANT,
-                       &nsCSSFrameConstructor::ConstructInline) },
-    { StyleDisplay::Flex,
-      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame) },
-    { StyleDisplay::InlineFlex,
-      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame) },
-    { StyleDisplay::WebkitBox,
-      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame) },
-    { StyleDisplay::WebkitInlineBox,
-      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame) },
-    { StyleDisplay::Grid,
-      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame) },
-    { StyleDisplay::InlineGrid,
-      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame) },
-    { StyleDisplay::Ruby,
-      FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT,
-                  NS_NewRubyFrame) },
-    { StyleDisplay::RubyBase,
-      FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
-                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer),
-                  NS_NewRubyBaseFrame) },
-    { StyleDisplay::RubyBaseContainer,
-      FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
-                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby),
-                  NS_NewRubyBaseContainerFrame) },
-    { StyleDisplay::RubyText,
-      FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
-                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer),
-                  NS_NewRubyTextFrame) },
-    { StyleDisplay::RubyTextContainer,
-      FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby),
-                  NS_NewRubyTextContainerFrame) },
-    { StyleDisplay::Table,
-      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
-    { StyleDisplay::InlineTable,
-      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
+                       &nsCSSFrameConstructor::ConstructInline)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::InlineBlock, UNREACHABLE_FCDATA()),
+    FCDATA_FOR_DISPLAY(StyleDisplay::ListItem, UNREACHABLE_FCDATA()),
+    FCDATA_FOR_DISPLAY(StyleDisplay::Table,
+      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::InlineTable,
+      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable)),
     // NOTE: In the unlikely event that we add another table-part here that has
     // a desired-parent-type (& hence triggers table fixup), we'll need to also
     // update the flexbox chunk in nsStyleContext::ApplyStyleFixups().
-    { StyleDisplay::TableRowGroup,
-      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
-                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
-                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup) },
-    { StyleDisplay::TableHeaderGroup,
+    FCDATA_FOR_DISPLAY(StyleDisplay::TableRowGroup,
       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
-                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup) },
-    { StyleDisplay::TableFooterGroup,
+                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::TableColumn,
       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
-                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
-                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup) },
-    { StyleDisplay::TableColumnGroup,
+                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup),
+                       &nsCSSFrameConstructor::ConstructTableCol)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::TableColumnGroup,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
                   FCDATA_SKIP_ABSPOS_PUSH |
                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
-                  NS_NewTableColGroupFrame) },
-    { StyleDisplay::TableColumn,
+                  NS_NewTableColGroupFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::TableHeaderGroup,
       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
-                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup),
-                       &nsCSSFrameConstructor::ConstructTableCol) },
-    { StyleDisplay::TableRow,
+                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
+                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::TableFooterGroup,
+      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
+                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
+                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::TableRow,
       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
-                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup) },
-    { StyleDisplay::TableCell,
+                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::TableCell,
       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
-                       &nsCSSFrameConstructor::ConstructTableCell) },
-    { StyleDisplay::Contents,
-      FULL_CTOR_FCDATA(FCDATA_IS_CONTENTS, nullptr/*never called*/) }
+                       &nsCSSFrameConstructor::ConstructTableCell)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::TableCaption, UNREACHABLE_FCDATA()),
+    FCDATA_FOR_DISPLAY(StyleDisplay::Flex,
+      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::InlineFlex,
+      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::Grid,
+      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::InlineGrid,
+      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::Ruby,
+      FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT, NS_NewRubyFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::RubyBase,
+      FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
+                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer),
+                  NS_NewRubyBaseFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::RubyBaseContainer,
+      FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
+                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby),
+                  NS_NewRubyBaseContainerFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::RubyText,
+      FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT |
+                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer),
+                  NS_NewRubyTextFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::RubyTextContainer,
+      FCDATA_DECL(FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby),
+                  NS_NewRubyTextContainerFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::Contents,
+      FULL_CTOR_FCDATA(FCDATA_IS_CONTENTS, nullptr/*never called*/)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::WebkitBox,
+      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
+    FCDATA_FOR_DISPLAY(StyleDisplay::WebkitInlineBox,
+      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame)),
   };
+  static_assert(ArrayLength(sDisplayData) == size_t(StyleDisplay::WebkitInlineBox) + 1,
+                "Be sure to update sDisplayData if you touch StyleDisplay");
+
+  MOZ_ASSERT(size_t(aDisplay->mDisplay) < ArrayLength(sDisplayData),
+             "XUL display data should have already been handled");
 
   // See the mDisplay fixup code in nsRuleNode::ComputeDisplayData.
   MOZ_ASSERT(aDisplay->mDisplay != StyleDisplay::Contents ||
              !aElement->IsRootOfNativeAnonymousSubtree(),
              "display:contents on anonymous content is unsupported");
 
-  return FindDataByInt(aDisplay->mDisplay,
-                       aElement, aStyleContext, sDisplayData,
-                       ArrayLength(sDisplayData));
+  const FrameConstructionDataByDisplay& data =
+    sDisplayData[size_t(aDisplay->mDisplay)];
+
+  MOZ_ASSERT(data.mDisplay == aDisplay->mDisplay,
+             "Someone messed the order in the display values");
+
+  return &data.mData;
 }
 
 nsIFrame*
 nsCSSFrameConstructor::ConstructScrollableBlock(nsFrameConstructorState& aState,
                                                 FrameConstructionItem&   aItem,
                                                 nsContainerFrame*        aParentFrame,
                                                 const nsStyleDisplay*    aDisplay,
                                                 nsFrameItems&            aFrameItems)
@@ -5494,18 +5519,18 @@ nsCSSFrameConstructor::AddPageBreakItem(
   // that's easier to re-resolve and it doesn't matter in practice.
   // (Getting different parents can result in framechange hints, e.g.,
   // for user-modify.)
   RefPtr<nsStyleContext> pseudoStyle =
     mPresShell->StyleSet()->
       ResolveAnonymousBoxStyle(nsCSSAnonBoxes::pageBreak,
                                aMainStyleContext->GetParent());
 
-  NS_ASSERTION(pseudoStyle->StyleDisplay()->mDisplay ==
-                 StyleDisplay::Block, "Unexpected display");
+  MOZ_ASSERT(pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block,
+             "Unexpected display");
 
   static const FrameConstructionData sPageBreakData =
     FCDATA_DECL(FCDATA_SKIP_FRAMESET, NS_NewPageBreakFrame);
 
   // Lie about the tag and namespace so we don't trigger anything
   // interesting during frame construction.
   aItems.AppendItem(&sPageBreakData, aContent, nsCSSAnonBoxes::pageBreak,
                     kNameSpaceID_None, nullptr, pseudoStyle.forget(),
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -725,16 +725,31 @@ private:
   /* Structure representing a mapping of an integer to a
      FrameConstructionData. There are no magic integer values here. */
   struct FrameConstructionDataByInt {
     /* Could be used for display or whatever else */
     const int32_t mInt;
     const FrameConstructionData mData;
   };
 
+  struct FrameConstructionDataByDisplay {
+#ifdef DEBUG
+    const mozilla::StyleDisplay mDisplay;
+#endif
+    const FrameConstructionData mData;
+  };
+
+#ifdef DEBUG
+#define FCDATA_FOR_DISPLAY(_display, _fcdata) \
+  { _display, _fcdata }
+#else
+#define FCDATA_FOR_DISPLAY(_display, _fcdata) \
+  { _fcdata }
+#endif
+
   /* Structure that has a FrameConstructionData and style context pseudo-type
      for a table pseudo-frame */
   struct PseudoParentData {
     const FrameConstructionData mFCData;
     nsICSSAnonBoxPseudo * const * const mPseudoType;
   };
   /* Array of such structures that we use to properly construct table
      pseudo-frames as needed */
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -480,16 +480,19 @@ enum class FillMode : uint32_t;
 #define NS_STYLE_WRITING_MODE_SIDEWAYS_RL         \
           (NS_STYLE_WRITING_MODE_VERTICAL_RL |    \
            NS_STYLE_WRITING_MODE_SIDEWAYS_MASK)
 #define NS_STYLE_WRITING_MODE_SIDEWAYS_LR         \
           (NS_STYLE_WRITING_MODE_VERTICAL_LR |    \
            NS_STYLE_WRITING_MODE_SIDEWAYS_MASK)
 
 // See nsStyleDisplay
+//
+// NOTE: Order is important! If you change it, make sure to take a look at
+// the FrameConstructorDataByDisplay stuff, and ensure it's still correct!
 enum class StyleDisplay : uint8_t {
   None_ = 0,
   Block,
   Inline,
   InlineBlock,
   ListItem,
   Table,
   InlineTable,