[LFC][TFC] Cache table's width constraint values.
https://bugs.webkit.org/show_bug.cgi?id=203135
<rdar://problem/56396352>

Reviewed by Antti Koivisto.

This patch ensures that when computedIntrinsicWidthConstraints is called from both the preferred width and the actual layout codepaths during a layout frame, we don't
end up building up the grid twice.

* layout/tableformatting/TableFormattingContext.cpp:
(WebCore::Layout::TableFormattingContext::computedIntrinsicWidthConstraints):
(WebCore::Layout::TableFormattingContext::computePreferredWidthForColumns):
(WebCore::Layout::TableFormattingContext::computeAndDistributeExtraHorizontalSpace):
* layout/tableformatting/TableGrid.cpp:
(WebCore::Layout::TableGrid::widthConstraints):
(WebCore::Layout::TableGrid::widthConstraints const): Deleted.
* layout/tableformatting/TableGrid.h:
(WebCore::Layout::TableGrid::hasComputedWidthConstraints const):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251282 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 29cccb7..0c37301 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,5 +1,26 @@
 2019-10-18  Zalan Bujtas  <zalan@apple.com>
 
+        [LFC][TFC] Cache table's width constraint values.
+        https://bugs.webkit.org/show_bug.cgi?id=203135
+        <rdar://problem/56396352>
+
+        Reviewed by Antti Koivisto.
+
+        This patch ensures that when computedIntrinsicWidthConstraints is called from both the preferred width and the actual layout codepaths during a layout frame, we don't
+        end up building up the grid twice.
+
+        * layout/tableformatting/TableFormattingContext.cpp:
+        (WebCore::Layout::TableFormattingContext::computedIntrinsicWidthConstraints):
+        (WebCore::Layout::TableFormattingContext::computePreferredWidthForColumns):
+        (WebCore::Layout::TableFormattingContext::computeAndDistributeExtraHorizontalSpace):
+        * layout/tableformatting/TableGrid.cpp:
+        (WebCore::Layout::TableGrid::widthConstraints):
+        (WebCore::Layout::TableGrid::widthConstraints const): Deleted.
+        * layout/tableformatting/TableGrid.h:
+        (WebCore::Layout::TableGrid::hasComputedWidthConstraints const):
+
+2019-10-18  Zalan Bujtas  <zalan@apple.com>
+
         [LFC][BFC] TableFormattingContext::computedIntrinsicWidthConstraints should not expect a valid containing block's width
         https://bugs.webkit.org/show_bug.cgi?id=203131
         <rdar://problem/56394676>
diff --git a/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp b/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp
index 26796cb..3ebb43c 100644
--- a/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp
+++ b/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp
@@ -161,16 +161,14 @@
     // Tables have a slighty different concept of shrink to fit. It's really only different with non-auto "width" values, where
     // a generic shrink-to fit block level box like a float box would be just sized to the computed value of "width", tables
     // can actually be streched way over.
-
-    // 1. Ensure each cell slot is occupied by at least one cell.
-    ensureTableGrid();
-    // 2. Compute the minimum/maximum width of each column.
-    computePreferredWidthForColumns();
-    // 3. Compute the minimum/maximum width of the table box.
     auto& grid = formattingState().tableGrid();
-    auto tableWidthConstraints = grid.widthConstraints();
-    tableWidthConstraints.expand(grid.totalHorizontalSpacing());
-    return tableWidthConstraints;
+    if (!grid.hasComputedWidthConstraints()) {
+        // 1. Ensure each cell slot is occupied by at least one cell.
+        ensureTableGrid();
+        // 2. Compute the minimum/maximum width of each column.
+        computePreferredWidthForColumns();
+    }
+    return grid.widthConstraints();
 }
 
 void TableFormattingContext::ensureTableGrid()
@@ -221,6 +219,7 @@
 {
     auto& formattingState = this->formattingState();
     auto& grid = formattingState.tableGrid();
+    ASSERT(!grid.hasComputedWidthConstraints());
 
     // 1. Calculate the minimum content width (MCW) of each cell: the formatted content may span any number of lines but may not overflow the cell box.
     //    If the specified 'width' (W) of the cell is greater than MCW, W is the minimum cell width. A value of 'auto' means that MCW is the minimum cell width.
@@ -275,6 +274,7 @@
 void TableFormattingContext::computeAndDistributeExtraHorizontalSpace()
 {
     auto& grid = formattingState().tableGrid();
+    ASSERT(grid.hasComputedWidthConstraints());
     auto tableWidthConstraints = grid.widthConstraints();
     auto tableMinimumContentWidth = tableWidthConstraints.minimum - grid.totalHorizontalSpacing();
 
diff --git a/Source/WebCore/layout/tableformatting/TableGrid.cpp b/Source/WebCore/layout/tableformatting/TableGrid.cpp
index 9995c42..e80dc55 100644
--- a/Source/WebCore/layout/tableformatting/TableGrid.cpp
+++ b/Source/WebCore/layout/tableformatting/TableGrid.cpp
@@ -173,14 +173,17 @@
     UNUSED_PARAM(tableCellBox);
 }
 
-FormattingContext::IntrinsicWidthConstraints TableGrid::widthConstraints() const
+FormattingContext::IntrinsicWidthConstraints TableGrid::widthConstraints()
 {
-    // FIXME: We should probably cache this value.
-    auto widthConstraints = FormattingContext::IntrinsicWidthConstraints { };
+    // FIXME: Add constraint invalidation for incremental layouts.
+    if (m_intrinsicWidthConstraints)
+        return *m_intrinsicWidthConstraints;
+
+    m_intrinsicWidthConstraints = FormattingContext::IntrinsicWidthConstraints { };
     for (auto& column : m_columnsContext.columns())
-        widthConstraints += column.widthConstraints();
-    widthConstraints.expand(totalHorizontalSpacing()); 
-    return widthConstraints;
+        *m_intrinsicWidthConstraints += column.widthConstraints();
+    m_intrinsicWidthConstraints->expand(totalHorizontalSpacing());
+    return *m_intrinsicWidthConstraints;
 }
 
 }
diff --git a/Source/WebCore/layout/tableformatting/TableGrid.h b/Source/WebCore/layout/tableformatting/TableGrid.h
index b0ca0de..27f4030 100644
--- a/Source/WebCore/layout/tableformatting/TableGrid.h
+++ b/Source/WebCore/layout/tableformatting/TableGrid.h
@@ -150,7 +150,8 @@
     };
     SlotInfo* slot(SlotPosition);
 
-    FormattingContext::IntrinsicWidthConstraints widthConstraints() const;
+    bool hasComputedWidthConstraints() const { return m_intrinsicWidthConstraints.hasValue(); }
+    FormattingContext::IntrinsicWidthConstraints widthConstraints();
 
 private:
     using SlotMap = WTF::HashMap<SlotPosition, std::unique_ptr<SlotInfo>>;
@@ -161,6 +162,7 @@
     RowList m_rows;
     LayoutUnit m_horizontalSpacing;
     LayoutUnit m_verticalSpacing;
+    Optional<FormattingContext::IntrinsicWidthConstraints> m_intrinsicWidthConstraints;
 };
 
 }