Bug 1373095 - Devirtualize GetRowSpan/GetColSpan. r=bz
authorMats Palmgren <mats@mozilla.com>
Sat, 17 Jun 2017 02:49:09 +0200
changeset 415634 c0bb73483afb3d1b17f37a8d8453df43a26b37bb
parent 415633 d69a2c18f84151a36937d0a3cf63dba9cd3f574c
child 415635 1ffc1664addf6f15928b3e5382d0061ed9d4f347
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)
reviewersbz
bugs1373095
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 1373095 - Devirtualize GetRowSpan/GetColSpan. r=bz MozReview-Commit-ID: 7EUqrFMMe9c
dom/mathml/nsMathMLElement.cpp
layout/mathml/nsMathMLmtableFrame.cpp
layout/mathml/nsMathMLmtableFrame.h
layout/tables/celldata.h
layout/tables/nsITableCellLayout.h
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableCellFrame.h
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -4,16 +4,17 @@
  * 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/. */
 
 
 #include "nsMathMLElement.h"
 #include "base/compiler_specific.h"
 #include "mozilla/ArrayUtils.h"
 #include "nsGkAtoms.h"
+#include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
 #include "nsCRT.h"
 #include "nsLayoutStylesheetCache.h"
 #include "nsRuleData.h"
 #include "nsCSSValue.h"
 #include "nsCSSParser.h"
 #include "nsMappedAttributes.h"
 #include "nsStyleConsts.h"
 #include "nsIDocument.h"
@@ -141,31 +142,43 @@ nsMathMLElement::UnbindFromTree(bool aDe
 }
 
 bool
 nsMathMLElement::ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult)
 {
+  MOZ_ASSERT(IsMathMLElement());
+
   if (aNamespaceID == kNameSpaceID_None) {
-    if (IsMathMLElement(nsGkAtoms::math) && aAttribute == nsGkAtoms::mode) {
+    if (mNodeInfo->Equals(nsGkAtoms::math) && aAttribute == nsGkAtoms::mode) {
       WarnDeprecated(nsGkAtoms::mode->GetUTF16String(),
                      nsGkAtoms::display->GetUTF16String(), OwnerDoc());
     }
     if (aAttribute == nsGkAtoms::color) {
       WarnDeprecated(nsGkAtoms::color->GetUTF16String(),
                      nsGkAtoms::mathcolor_->GetUTF16String(), OwnerDoc());
     }
     if (aAttribute == nsGkAtoms::color ||
         aAttribute == nsGkAtoms::mathcolor_ ||
         aAttribute == nsGkAtoms::background ||
         aAttribute == nsGkAtoms::mathbackground_) {
       return aResult.ParseColor(aValue);
     }
+    if (mNodeInfo->Equals(nsGkAtoms::mtd_)) {
+      if (aAttribute == nsGkAtoms::columnspan_) {
+        aResult.ParseClampedNonNegativeInt(aValue, 1, 1, MAX_COLSPAN);
+        return true;
+      }
+      if (aAttribute == nsGkAtoms::rowspan) {
+        aResult.ParseClampedNonNegativeInt(aValue, 1, 0, MAX_ROWSPAN);
+        return true;
+      }
+    }
   }
 
   return nsMathMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
                                              aValue, aResult);
 }
 
 static Element::MappedAttributeEntry sMtableStyles[] = {
   { &nsGkAtoms::width },
@@ -200,16 +213,18 @@ static Element::MappedAttributeEntry sCo
 static Element::MappedAttributeEntry sDirStyles[] = {
   { &nsGkAtoms::dir },
   { nullptr }
 };
 
 bool
 nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
+  MOZ_ASSERT(IsMathMLElement());
+
   static const MappedAttributeEntry* const mtableMap[] = {
     sMtableStyles,
     sCommonPresStyles
   };
   static const MappedAttributeEntry* const tokenMap[] = {
     sTokenStyles,
     sCommonPresStyles,
     sDirStyles
@@ -231,20 +246,20 @@ nsMathMLElement::IsAttributeMapped(const
   // We don't support mglyph (yet).
   if (IsAnyOfMathMLElements(nsGkAtoms::ms_, nsGkAtoms::mi_, nsGkAtoms::mn_,
                             nsGkAtoms::mo_, nsGkAtoms::mtext_,
                             nsGkAtoms::mspace_))
     return FindAttributeDependence(aAttribute, tokenMap);
   if (IsAnyOfMathMLElements(nsGkAtoms::mstyle_, nsGkAtoms::math))
     return FindAttributeDependence(aAttribute, mstyleMap);
 
-  if (IsMathMLElement(nsGkAtoms::mtable_))
+  if (mNodeInfo->Equals(nsGkAtoms::mtable_))
     return FindAttributeDependence(aAttribute, mtableMap);
 
-  if (IsMathMLElement(nsGkAtoms::mrow_))
+  if (mNodeInfo->Equals(nsGkAtoms::mrow_))
     return FindAttributeDependence(aAttribute, mrowMap);
 
   if (IsAnyOfMathMLElements(nsGkAtoms::maction_,
                             nsGkAtoms::maligngroup_,
                             nsGkAtoms::malignmark_,
                             nsGkAtoms::menclose_,
                             nsGkAtoms::merror_,
                             nsGkAtoms::mfenced_,
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -1156,57 +1156,16 @@ nsMathMLmtdFrame::Init(nsIContent*      
 {
   nsTableCellFrame::Init(aContent, aParent, aPrevInFlow);
 
   // We want to use the ancestor <math> element's font inflation to avoid
   // individual cells having their own varying font inflation.
   RemoveStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
 }
 
-int32_t
-nsMathMLmtdFrame::GetRowSpan()
-{
-  int32_t rowspan = 1;
-
-  // Don't look at the content's rowspan if we're not an mtd or a pseudo cell.
-  if (mContent->IsMathMLElement(nsGkAtoms::mtd_) &&
-      !StyleContext()->GetPseudo()) {
-    nsAutoString value;
-    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rowspan, value);
-    if (!value.IsEmpty()) {
-      nsresult error;
-      rowspan = value.ToInteger(&error);
-      if (NS_FAILED(error) || rowspan < 0)
-        rowspan = 1;
-      rowspan = std::min(rowspan, MAX_ROWSPAN);
-    }
-  }
-  return rowspan;
-}
-
-int32_t
-nsMathMLmtdFrame::GetColSpan()
-{
-  int32_t colspan = 1;
-
-  // Don't look at the content's colspan if we're not an mtd or a pseudo cell.
-  if (mContent->IsMathMLElement(nsGkAtoms::mtd_) &&
-      !StyleContext()->GetPseudo()) {
-    nsAutoString value;
-    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::columnspan_, value);
-    if (!value.IsEmpty()) {
-      nsresult error;
-      colspan = value.ToInteger(&error);
-      if (NS_FAILED(error) || colspan <= 0 || colspan > MAX_COLSPAN)
-        colspan = 1;
-    }
-  }
-  return colspan;
-}
-
 nsresult
 nsMathMLmtdFrame::AttributeChanged(int32_t  aNameSpaceID,
                                    nsIAtom* aAttribute,
                                    int32_t  aModType)
 {
   // Attributes specific to <mtd>:
   // groupalign  : Not yet supported
   // rowalign    : here
--- a/layout/mathml/nsMathMLmtableFrame.h
+++ b/layout/mathml/nsMathMLmtableFrame.h
@@ -261,18 +261,16 @@ public:
                    nsIAtom* aAttribute,
                    int32_t  aModType) override;
 
   virtual uint8_t GetVerticalAlign() const override;
   virtual nsresult ProcessBorders(nsTableFrame*           aFrame,
                                   nsDisplayListBuilder*   aBuilder,
                                   const nsDisplayListSet& aLists) override;
 
-  virtual int32_t GetRowSpan() override;
-  virtual int32_t GetColSpan() override;
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsTableCellFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
   }
 
   virtual LogicalMargin GetBorderWidth(WritingMode aWM) const override;
 
   virtual nsMargin GetBorderOverflow() override;
--- a/layout/tables/celldata.h
+++ b/layout/tables/celldata.h
@@ -1,30 +1,27 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 #ifndef CellData_h__
 #define CellData_h__
 
 #include "nsISupports.h"
+#include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
 #include "nsCoord.h"
 #include "mozilla/gfx/Types.h"
 #include "mozilla/WritingModes.h"
 #include <stdint.h>
 
 class nsTableCellFrame;
 class nsCellMap;
 class BCCellData;
 
 
-#define MAX_ROWSPAN 65534 // the cellmap can not handle more.
-#define MAX_COLSPAN 1000 // limit as IE and opera do.  If this ever changes,
-                         // change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly.
-
 /**
   * Data stored by nsCellMap to rationalize rowspan and colspan cells.
   */
 class CellData
 {
 public:
   /** Initialize the mOrigCell pointer
     * @param aOrigCell  the table cell frame which will be stored in mOrigCell.
--- a/layout/tables/nsITableCellLayout.h
+++ b/layout/tables/nsITableCellLayout.h
@@ -2,16 +2,20 @@
 /* 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/. */
 #ifndef nsITableCellLayout_h__
 #define nsITableCellLayout_h__
 
 #include "nsQueryFrame.h"
 
+#define MAX_ROWSPAN 65534 // the cellmap can not handle more.
+#define MAX_COLSPAN 1000 // limit as IE and opera do.  If this ever changes,
+                         // change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly.
+
 /**
  * nsITableCellLayout
  * interface for layout objects that act like table cells.
  *
  * @author  sclark
  */
 class nsITableCellLayout
 {
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -704,43 +704,49 @@ nsTableCellFrame::GetCellBaseline() cons
   nscoord borderPadding = GetUsedBorderAndPadding().top;
   nscoord result;
   if (nsLayoutUtils::GetFirstLineBaseline(GetWritingMode(), inner, &result))
     return result + borderPadding;
   return inner->GetContentRectRelativeToSelf().YMost() +
          borderPadding;
 }
 
-int32_t nsTableCellFrame::GetRowSpan()
+int32_t
+nsTableCellFrame::GetRowSpan()
 {
   int32_t rowSpan=1;
-  nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent);
 
   // Don't look at the content's rowspan if we're a pseudo cell
-  if (hc && !StyleContext()->GetPseudo()) {
-    const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::rowspan);
+  if (!StyleContext()->GetPseudo()) {
+    dom::Element* elem = mContent->AsElement();
+    const nsAttrValue* attr = elem->GetParsedAttr(nsGkAtoms::rowspan);
     // Note that we don't need to check the tag name, because only table cells
-    // and table headers parse the "rowspan" attribute into an integer.
+    // (including MathML <mtd>) and table headers parse the "rowspan" attribute
+    // into an integer.
     if (attr && attr->Type() == nsAttrValue::eInteger) {
        rowSpan = attr->GetIntegerValue();
     }
   }
   return rowSpan;
 }
 
-int32_t nsTableCellFrame::GetColSpan()
+int32_t
+nsTableCellFrame::GetColSpan()
 {
   int32_t colSpan=1;
-  nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent);
 
   // Don't look at the content's colspan if we're a pseudo cell
-  if (hc && !StyleContext()->GetPseudo()) {
-    const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::colspan);
+  if (!StyleContext()->GetPseudo()) {
+    dom::Element* elem = mContent->AsElement();
+    const nsAttrValue* attr = elem->GetParsedAttr(
+      MOZ_UNLIKELY(elem->IsMathMLElement()) ? nsGkAtoms::columnspan_
+                                            : nsGkAtoms::colspan);
     // Note that we don't need to check the tag name, because only table cells
-    // and table headers parse the "colspan" attribute into an integer.
+    // (including MathML <mtd>) and table headers parse the "colspan" attribute
+    // into an integer.
     if (attr && attr->Type() == nsAttrValue::eInteger) {
        colSpan = attr->GetIntegerValue();
     }
   }
   return colSpan;
 }
 
 /* virtual */ nscoord
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -145,21 +145,21 @@ public:
   /**
    * Get the first-line baseline of the cell relative to its block-start border
    * edge, as if the cell were vertically aligned to the top of the row.
    */
   nscoord GetCellBaseline() const;
 
   /**
    * return the cell's specified row span. this is what was specified in the
-   * content model or in the style info, and is always >= 1.
+   * content model or in the style info, and is always >= 0.
    * to get the effective row span (the actual value that applies), use GetEffectiveRowSpan()
    * @see nsTableFrame::GetEffectiveRowSpan()
    */
-  virtual int32_t GetRowSpan();
+  int32_t GetRowSpan();
 
   // there is no set row index because row index depends on the cell's parent row only
 
   // Update the style on the block wrappers around our kids.
   virtual void DoUpdateStyleOfOwnedAnonBoxes(
     mozilla::ServoStyleSet& aStyleSet,
     nsStyleChangeList& aChangeList,
     nsChangeHint aHintForThisFrame) override;
@@ -177,17 +177,17 @@ public:
   virtual nsresult GetRowIndex(int32_t &aRowIndex) const override;
 
   /**
    * return the cell's specified col span. this is what was specified in the
    * content model or in the style info, and is always >= 1.
    * to get the effective col span (the actual value that applies), use GetEffectiveColSpan()
    * @see nsTableFrame::GetEffectiveColSpan()
    */
-  virtual int32_t GetColSpan();
+  int32_t GetColSpan();
 
   /** return the cell's column index (starting at 0 for the first column) */
   virtual nsresult GetColIndex(int32_t &aColIndex) const override;
   void SetColIndex(int32_t aColIndex);
 
   /** return the available isize given to this frame during its last reflow */
   inline nscoord GetPriorAvailISize();