Bug 473390 part 18. Eliminate IsSpecialContent. r+sr=roc
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 19 Jan 2009 13:31:35 -0500
changeset 23955 cc3b3a8f35cbb972afcf4827044e5f0e557554af
parent 23954 a50d9d9c54086c0ff7cba2677f879038460e146f
child 23956 1e72b268d05eb8cc0633a67390dc53e494c21035
push id4804
push userbzbarsky@mozilla.com
push dateMon, 19 Jan 2009 18:34:53 +0000
treeherdermozilla-central@cc3b3a8f35cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs473390
milestone1.9.2a1pre
Bug 473390 part 18. Eliminate IsSpecialContent. r+sr=roc
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3079,96 +3079,59 @@ nsCSSFrameConstructor::GetParentFrame(PR
     aParentFrame = pseudoParentFrame;
     aIsPseudoParent = PR_TRUE;
   }
 
   aState.mAdditionalStateBits = savedStateBits;
   return rv;
 }
 
-/* static */
-PRBool
-nsCSSFrameConstructor::IsSpecialContent(nsIContent*     aContent,
-                                        nsIAtom*        aTag,
-                                        PRInt32         aNameSpaceID,
-                                        nsStyleContext* aStyleContext)
-{
-  // Gross hack. Return true if this is a content node that we'd create a
-  // frame for based on something other than display -- in other words if this
-  // is a node that could never have a nsTableCellFrame, for example.
-  if (FindHTMLData(aContent, aTag, aNameSpaceID, aStyleContext) ||
-      FindXULTagData(aContent, aTag, aNameSpaceID, aStyleContext)) {
-    return PR_TRUE;
-  }
-
-#ifdef MOZ_SVG
-  if (aNameSpaceID == kNameSpaceID_SVG && NS_SVGEnabled()) {
-    // All SVG content is special...
-    return PR_TRUE;
-  }
-#endif
-
-#ifdef MOZ_MATHML
-  if (FindMathMLData(aContent, aTag, aNameSpaceID, aStyleContext)) {
-    return PR_TRUE;
-  }
-#endif
-
-  return PR_FALSE;
-}
-                                      
 nsresult
 nsCSSFrameConstructor::AdjustParentFrame(nsFrameConstructorState&     aState,
                                          nsIContent*                  aChildContent,
                                          nsIFrame* &                  aParentFrame,
-                                         nsIAtom*                     aTag,
+                                         const FrameConstructionData* aFCData,
                                          PRInt32                      aNameSpaceID,
-                                         nsStyleContext*              aChildStyle,
+                                         const nsStyleDisplay*        aDisplay,
                                          nsFrameItems* &              aFrameItems,
                                          nsFrameConstructorSaveState& aSaveState,
                                          PRBool&                      aSuppressFrame,
                                          PRBool&                      aCreatedPseudo)
 {
-  NS_PRECONDITION(aChildStyle, "Must have child's style context");
+  NS_PRECONDITION(aDisplay, "Must have child's style context");
   NS_PRECONDITION(aFrameItems, "Must have frame items to work with");
 
   aSuppressFrame = PR_FALSE;
   aCreatedPseudo = PR_FALSE;
   if (!aParentFrame) {
     // Nothing to do here
     return NS_OK;
   }
 
-  PRBool childIsSpecialContent = PR_FALSE; // lazy lookup
   // Only use the outer table frame as parent if the child is going to use a
   // tableCaptionFrame, otherwise the inner table frame is the parent
   // (bug 341858).
   nsIAtom* parentType = aParentFrame->GetType();
   NS_ASSERTION(parentType != nsGkAtoms::tableOuterFrame,
                "Shouldn't be happening");
   if (parentType == nsGkAtoms::tableColGroupFrame) {
-    childIsSpecialContent = IsSpecialContent(aChildContent, aTag, aNameSpaceID,
-                                             aChildStyle);
-    if (childIsSpecialContent ||
-        (aChildStyle->GetStyleDisplay()->mDisplay !=
-         NS_STYLE_DISPLAY_TABLE_COLUMN)) {
+    if (aFCData || aDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE_COLUMN) {
       aSuppressFrame = PR_TRUE;
       return NS_OK;
     }
   }
  
   // If our parent is a table, table-row-group, or table-row, and
   // we're not table-related in any way, we have to create table
   // pseudo-frames so that we have a table cell to live in.
   if (IsTableRelated(aParentFrame->GetType(), PR_FALSE) &&
-      (!IsTableRelated(aChildStyle->GetStyleDisplay()->mDisplay, PR_TRUE) ||
+      (!IsTableRelated(aDisplay->mDisplay, PR_TRUE) ||
        // Also need to create a pseudo-parent if the child is going to end up
        // with a frame based on something other than display.
-       childIsSpecialContent || // looked it up before
-       IsSpecialContent(aChildContent, aTag, aNameSpaceID, aChildStyle))) {
+       aFCData)) {
     nsFrameState savedStateBits  = aState.mAdditionalStateBits;
     aState.mAdditionalStateBits &= ~NS_FRAME_GENERATED_CONTENT;
     nsresult rv = GetPseudoCellFrame(aNameSpaceID, aState, *aParentFrame);
     if (NS_FAILED(rv)) {
       return rv;
     }
     aState.mAdditionalStateBits = savedStateBits;
 
@@ -4855,48 +4818,64 @@ FindAncestorWithGeneratedContentPseudo(n
     nsIAtom* pseudo = f->GetStyleContext()->GetPseudoType();
     if (pseudo == nsCSSPseudoElements::before ||
         pseudo == nsCSSPseudoElements::after)
       return f;
   }
   return nsnull;
 }
 
-nsresult
-nsCSSFrameConstructor::ConstructTextFrame(nsFrameConstructorState& aState,
-                                          nsIContent*              aContent,
-                                          nsIFrame*                aParentFrame,
-                                          nsStyleContext*          aStyleContext,
-                                          nsFrameItems&            aFrameItems,
-                                          PRBool                   aPseudoParent)
-{
-  // process pending pseudo frames. whitespace doesn't have an effect.
-  if (!aPseudoParent && !aState.mPseudoFrames.IsEmpty() &&
-      !TextIsOnlyWhitespace(aContent))
-    ProcessPseudoFrames(aState, aFrameItems);
-
-  nsIFrame* newFrame = nsnull;
-
+#define FCDATA_DECL(_flags, _func) \
+  { _flags, { (FrameCreationFunc)_func } }
+#define SIMPLE_FCDATA(_func) FCDATA_DECL(0, _func)
+
+/* static */
+const nsCSSFrameConstructor::FrameConstructionData*
+nsCSSFrameConstructor::FindTextData(nsIFrame* aParentFrame)
+{
 #ifdef MOZ_SVG
   if (aParentFrame->IsFrameOfType(nsIFrame::eSVG)) {
     nsIFrame *ancestorFrame =
       nsSVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
     if (ancestorFrame) {
       nsISVGTextContentMetrics* metrics = do_QueryFrame(ancestorFrame);
-      if (!metrics) {
-        return NS_OK;
-      }
-      newFrame = NS_NewSVGGlyphFrame(mPresShell, aStyleContext);
-    }
-  }
-  else
-#endif
-  {
-    newFrame = NS_NewTextFrame(mPresShell, aStyleContext);
-  }
+      if (metrics) {
+        static const FrameConstructionData sSVGGlyphData =
+          SIMPLE_FCDATA(NS_NewSVGGlyphFrame);
+        return &sSVGGlyphData;
+      }
+    }
+    return nsnull;
+  }
+#endif
+
+  static const FrameConstructionData sTextData = SIMPLE_FCDATA(NS_NewTextFrame);
+  return &sTextData;
+}
+
+nsresult
+nsCSSFrameConstructor::ConstructTextFrame(const FrameConstructionData* aData,
+                                          nsFrameConstructorState& aState,
+                                          nsIContent*              aContent,
+                                          nsIFrame*                aParentFrame,
+                                          nsStyleContext*          aStyleContext,
+                                          nsFrameItems&            aFrameItems,
+                                          PRBool                   aPseudoParent)
+{
+  if (!aData) {
+    // Nothing to do here: suppressed text inside SVG, say
+    return NS_OK;
+  }
+
+  // process pending pseudo frames. whitespace doesn't have an effect.
+  if (!aPseudoParent && !aState.mPseudoFrames.IsEmpty() &&
+      !TextIsOnlyWhitespace(aContent))
+    ProcessPseudoFrames(aState, aFrameItems);
+
+  nsIFrame* newFrame = (*aData->mFunc.mCreationFunc)(mPresShell, aStyleContext);
 
   if (NS_UNLIKELY(!newFrame))
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsresult rv = InitAndRestoreFrame(aState, aContent, aParentFrame,
                                     nsnull, newFrame);
 
   if (NS_FAILED(rv)) {
@@ -4974,19 +4953,16 @@ nsCSSFrameConstructor::FindDataByTag(nsI
 
       return data;
     }
   }
 
   return nsnull;
 }
 
-#define FCDATA_DECL(_flags, _func) \
-  { _flags, { (FrameCreationFunc)_func } }
-#define SIMPLE_FCDATA(_func) FCDATA_DECL(0, _func)
 #define SUPPRESS_FCDATA() FCDATA_DECL(FCDATA_SUPPRESS_FRAME, nsnull)
 #define SIMPLE_INT_CREATE(_int, _func) { _int, SIMPLE_FCDATA(_func) }
 #define SIMPLE_INT_CHAIN(_int, _func)                       \
   { _int, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER, _func) }
 #define COMPLEX_INT_CREATE(_int, _func)                     \
   { _int, { FCDATA_FUNC_IS_FULL_CTOR, { nsnull }, _func } }
 
 #define SIMPLE_TAG_CREATE(_tag, _func)          \
@@ -5653,34 +5629,21 @@ nsCSSFrameConstructor::FindXULListItemDa
     SCROLLABLE_XUL_FCDATA(NS_NewListItemFrame);
   return &sListItemData;
 }
 
 #endif /* MOZ_XUL */
 
 /* static */
 const nsCSSFrameConstructor::FrameConstructionData*
-nsCSSFrameConstructor::FindXULData(nsIContent* aContent,
-                                   nsIAtom* aTag,
-                                   PRInt32 aNameSpaceID,
-                                   nsStyleContext* aStyleContext)
-{
-  const FrameConstructionData* data =
-    FindXULTagData(aContent, aTag, aNameSpaceID, aStyleContext);
-  if (data) {
-    return data;
-  }
-
-  // No data found by tag; try display
-  const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
-  PRBool isXULDisplay = IsXULDisplayType(display) &&
-    (aNameSpaceID == kNameSpaceID_XUL ||
-     !IsSpecialContent(aContent, aTag, aNameSpaceID, aStyleContext));
-
-  if (!isXULDisplay) {
+nsCSSFrameConstructor::FindXULDisplayData(const nsStyleDisplay* aDisplay,
+                                          nsIContent* aContent,
+                                          nsStyleContext* aStyleContext)
+{
+  if (!IsXULDisplayType(aDisplay)) {
     return nsnull;
   }
 
   static const FrameConstructionDataByInt sXULDisplayData[] = {
     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_BOX, NS_NewBoxFrame),
     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_BOX, NS_NewBoxFrame),
 #ifdef MOZ_XUL
     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_GRID, NS_NewGridBoxFrame),
@@ -5695,17 +5658,17 @@ nsCSSFrameConstructor::FindXULData(nsICo
     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_STACK, NS_NewStackFrame),
     { NS_STYLE_DISPLAY_POPUP,
       FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_IS_POPUP |
                   FCDATA_SKIP_ABSPOS_PUSH, NS_NewMenuPopupFrame) }
 #endif /* MOZ_XUL */
   };
 
   // Processing by display here:
-  return FindDataByInt(display->mDisplay, aContent, aStyleContext,
+  return FindDataByInt(aDisplay->mDisplay, aContent, aStyleContext,
                        sXULDisplayData, NS_ARRAY_LENGTH(sXULDisplayData));
 }
 
 nsresult
 nsCSSFrameConstructor::AddLazyChildren(nsIContent* aContent,
                                        nsLazyFrameConstructionCallback* aCallback,
                                        void* aArg, PRBool aIsSynch)
 {
@@ -6744,35 +6707,62 @@ nsCSSFrameConstructor::ConstructFrameInt
 
   // Pre-check for display "none" - if we find that, don't create
   // any frame at all
   if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
     aState.mFrameManager->SetUndisplayedContent(aContent, styleContext);
     return NS_OK;
   }
 
+  PRBool isText = aContent->IsNodeOfType(nsINode::eTEXT);
+  // Try to find frame construction data for this content
+  const FrameConstructionData* data;
+  if (isText) {
+    data = FindTextData(aParentFrame);
+  } else {
+    data = FindHTMLData(aContent, aTag, aNameSpaceID, styleContext);
+    if (!data) {
+      data = FindXULTagData(aContent, aTag, aNameSpaceID, styleContext);
+    }
+#ifdef MOZ_MATHML
+    if (!data) {
+      data = FindMathMLData(aContent, aTag, aNameSpaceID, styleContext);
+    }
+#endif
+#ifdef MOZ_SVG
+    if (!data) {
+      data = FindSVGData(aContent, aTag, aNameSpaceID, aParentFrame,
+                         styleContext);
+    }
+#endif /* MOZ_SVG */
+
+    if (data && (data->mBits & FCDATA_SUPPRESS_FRAME)) {
+      return NS_OK;
+    }
+  }
+  
   nsIFrame* adjParentFrame = aParentFrame;
   nsFrameItems* frameItems = &aFrameItems;
   PRBool pseudoParent = PR_FALSE;
   PRBool suppressFrame = PR_FALSE;
   nsFrameConstructorSaveState pseudoSaveState;
   nsresult rv = AdjustParentFrame(aState, aContent, adjParentFrame,
-                                  aTag, aNameSpaceID, styleContext,
-                                  frameItems, pseudoSaveState,
-                                  suppressFrame, pseudoParent);
+                                  data, aNameSpaceID, display, frameItems,
+                                  pseudoSaveState, suppressFrame, pseudoParent);
   if (NS_FAILED(rv) || suppressFrame) {
     return rv;
   }
 
-  if (aContent->IsNodeOfType(nsINode::eTEXT)) 
-    return ConstructTextFrame(aState, aContent, adjParentFrame, styleContext,
-                              *frameItems, pseudoParent);
+  if (isText) {
+    return ConstructTextFrame(data, aState, aContent, adjParentFrame,
+                              styleContext, *frameItems, pseudoParent);
+  }
 
 #ifdef MOZ_SVG
-  // Don't create frames for non-SVG children of SVG elements
+  // Don't create frames for non-SVG element children of SVG elements
   if (aNameSpaceID != kNameSpaceID_SVG &&
       aParentFrame &&
       aParentFrame->IsFrameOfType(nsIFrame::eSVG) &&
       !aParentFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)
       ) {
     return NS_OK;
   }
 #endif
@@ -6788,45 +6778,29 @@ nsCSSFrameConstructor::ConstructFrameInt
       aState.mPresContext->SetBidiEnabled();
   }
   // Start background loads during frame construction. This is just
   // a hint; the paint code will do the right thing in any case.
   {
     styleContext->GetStyleBackground();
   }
 
-  // Try to find frame construction data for this content
-  const FrameConstructionData* data = FindHTMLData(aContent, aTag, aNameSpaceID,
-                                                   styleContext);
-  if (!data) {
-    data = FindXULData(aContent, aTag, aNameSpaceID, styleContext);
-  }
-
-#ifdef MOZ_MATHML
+  // Now check for XUL display types
   if (!data) {
-    data = FindMathMLData(aContent, aTag, aNameSpaceID, styleContext);
-  }
-#endif /* MOZ_MATHML */
-
-#ifdef MOZ_SVG
-  if (!data) {
-    data = FindSVGData(aContent, aTag, aNameSpaceID, adjParentFrame, styleContext);
-  }
-#endif /* MOZ_SVG */
+    data = FindXULDisplayData(display, aContent, aStyleContext);
+  }
 
   if (data) {
-    if ((data->mBits & FCDATA_SUPPRESS_FRAME)
 #ifdef MOZ_XUL
-        || ((data->mBits & FCDATA_IS_POPUP) &&
-            adjParentFrame->GetType() != nsGkAtoms::menuFrame &&
-            !aState.mPopupItems.containingBlock)
+    if ((data->mBits & FCDATA_IS_POPUP) &&
+        adjParentFrame->GetType() != nsGkAtoms::menuFrame &&
+        !aState.mPopupItems.containingBlock) {
+      return NS_OK;
+    }
 #endif /* MOZ_XUL */
-        ) {
-      return NS_OK;
-    }
 
     return ConstructFrameFromData(data, aState, aContent, adjParentFrame, aTag,
                                   aNameSpaceID, styleContext, *frameItems,
                                   pseudoParent);
 
   }
   
   return ConstructFrameByDisplayType(aState, display, aContent, aNameSpaceID,
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -681,19 +681,21 @@ private:
 
   /**
    * Function to adjust aParentFrame and aFrameItems to deal with table
    * pseudo-frames that may have to be inserted.
    * @param aState the nsFrameConstructorState we're using.
    * @param aChildContent the content node we want to construct a frame for
    * @param aParentFrame the frame we think should be the parent.  This will be
    *        adjusted to point to a pseudo-frame if needed.
-   * @param aTag tag that would be used for frame construction
+   * @param aFCData the FrameConstructionData that would be used for frame
+   *        construction.  If this is null, then frame construction will be
+   *        done based on the CSS display value.   
    * @param aNameSpaceID namespace that will be used for frame construction
-   * @param aChildStyle the style context for aChildContent
+   * @param aDisplay the display style struct for aChildContent
    * @param aFrameItems the framelist we think we need to put the child frame
    *        into.  If we have to construct pseudo-frames, we'll modify the
    *        pointer to point to the list the child frame should go into.
    * @param aSaveState the nsFrameConstructorSaveState we can use for pushing a
    *        float containing block if we have to do it.
    * @param aSuppressFrame whether we should not create a frame below this
    *        parent
    * @param aCreatedPseudo whether we had to create a pseudo-parent
@@ -701,19 +703,19 @@ private:
    */
   // XXXbz this function should really go away once we rework pseudo-frame
   // handling to be better. This should simply be part of the job of
   // GetGeometricParent, and stuff like the frameitems and parent frame should
   // be kept track of in the state...
   nsresult AdjustParentFrame(nsFrameConstructorState&     aState,
                              nsIContent*                  aChildContent,
                              nsIFrame* &                  aParentFrame,
-                             nsIAtom*                     aTag,
+                             const FrameConstructionData* aFCData,
                              PRInt32                      aNameSpaceID,
-                             nsStyleContext*              aChildStyle,
+                             const nsStyleDisplay*        aDisplay,
                              nsFrameItems* &              aFrameItems,
                              nsFrameConstructorSaveState& aSaveState,
                              PRBool&                      aSuppressFrame,
                              PRBool&                      aCreatedPseudo);
 
   // END TABLE SECTION
 
 protected:
@@ -754,17 +756,20 @@ private:
                                   nsIContent*              aContent,
                                   nsIFrame*                aParentFrame,
                                   nsIAtom*                 aTag,
                                   nsStyleContext*          aStyleContext,
                                   const nsStyleDisplay*    aStyleDisplay,
                                   nsFrameItems&            aFrameItems,
                                   nsIFrame**               aNewFrame);
 
-  nsresult ConstructTextFrame(nsFrameConstructorState& aState,
+  static const FrameConstructionData* FindTextData(nsIFrame* aParentFrame);
+
+  nsresult ConstructTextFrame(const FrameConstructionData* aData,
+                              nsFrameConstructorState& aState,
                               nsIContent*              aContent,
                               nsIFrame*                aParentFrame,
                               nsStyleContext*          aStyleContext,
                               nsFrameItems&            aFrameItems,
                               PRBool                   aPseudoParent);
 
   nsresult ConstructPageBreakFrame(nsFrameConstructorState& aState,
                                    nsIContent*              aContent,
@@ -776,21 +781,16 @@ private:
   // and add it to aFrameItems. Return true if page-break-after:always is set on aStyleContext.
   // Don't do this for row groups, rows or cell, because tables handle those internally.
   PRBool PageBreakBefore(nsFrameConstructorState& aState,
                          nsIContent*              aContent,
                          nsIFrame*                aParentFrame,
                          nsStyleContext*          aStyleContext,
                          nsFrameItems&            aFrameItems);
 
-  static PRBool IsSpecialContent(nsIContent*     aContent,
-                                 nsIAtom*        aTag,
-                                 PRInt32         aNameSpaceID,
-                                 nsStyleContext* aStyleContext);
-
   // Function to find FrameConstructionData for aContent.  Will return
   // null if aContent is not HTML.
   static const FrameConstructionData* FindHTMLData(nsIContent* aContent,
                                                    nsIAtom* aTag,
                                                    PRInt32 aNameSpaceID,
                                                    nsStyleContext* aStyleContext);
   // HTML data-finding helper functions
   static const FrameConstructionData*
@@ -891,25 +891,25 @@ private:
     FindXULMenubarData(nsIContent* aContent, nsStyleContext* aStyleContext);
 #endif /* XP_MACOSX */
   static const FrameConstructionData*
     FindXULListBoxBodyData(nsIContent* aContent, nsStyleContext* aStyleContext);
   static const FrameConstructionData*
     FindXULListItemData(nsIContent* aContent, nsStyleContext* aStyleContext);
 #endif /* MOZ_XUL */
 
-  // Function to find FrameConstructionData for aContent either using
-  // FindXULTagData or using one of the XUL display types.  Will
-  // return null if aContent is not XUL and doesn't have a XUL display
-  // type (or even if it has a XUL display type but is HTML/MathML/SVG
-  // that would get a frame by tag).
-  static const FrameConstructionData* FindXULData(nsIContent* aContent,
-                                                  nsIAtom* aTag,
-                                                  PRInt32 aNameSpaceID,
-                                                  nsStyleContext* aStyleContext);
+  // Function to find FrameConstructionData for aContent using one of the XUL
+  // display types.  Will return null if aDisplay doesn't have a XUL display
+  // type.  This function performs no other checks, so should only be called if
+  // we know for sure that the content is not something that should get a frame
+  // constructed by tag.
+  static const FrameConstructionData*
+    FindXULDisplayData(const nsStyleDisplay* aDisplay,
+                       nsIContent* aContent,
+                       nsStyleContext* aStyleContext);
 
 // SVG - rods
 #ifdef MOZ_SVG
   static const FrameConstructionData* FindSVGData(nsIContent* aContent,
                                                   nsIAtom* aTag,
                                                   PRInt32 aNameSpaceID,
                                                   nsIFrame* aParentFrame,
                                                   nsStyleContext* aStyleContext);