Title: [199552] trunk/Source/WebCore
Revision
199552
Author
[email protected]
Date
2016-04-14 14:09:19 -0700 (Thu, 14 Apr 2016)

Log Message

Collapsed border cache invalidation can lead to O(n^2) during style resolve
https://bugs.webkit.org/show_bug.cgi?id=156570

Reviewed by Darin Adler.

RenderTable::invalidateCollapsedBorders traverses all cells. It is called when table cell border changes.
This can result in O(n^2) during style resolve.

* rendering/RenderTable.cpp:
(WebCore::RenderTable::layout):
(WebCore::RenderTable::invalidateCollapsedBorders):

    For cell border style change invalidate the hasEmptyCollapsedBorder bits only for the neighbouring cells.
    They are the only ones that can be affected.

* rendering/RenderTable.h:
(WebCore::RenderTable::collapsedBordersAreValid):
(WebCore::RenderTable::collapsedEmptyBorderIsPresent):
(WebCore::RenderTable::currentBorderValue):
* rendering/RenderTableCell.cpp:
(WebCore::RenderTableCell::styleDidChange):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (199551 => 199552)


--- trunk/Source/WebCore/ChangeLog	2016-04-14 20:49:12 UTC (rev 199551)
+++ trunk/Source/WebCore/ChangeLog	2016-04-14 21:09:19 UTC (rev 199552)
@@ -1,3 +1,27 @@
+2016-04-14  Antti Koivisto  <[email protected]>
+
+        Collapsed border cache invalidation can lead to O(n^2) during style resolve
+        https://bugs.webkit.org/show_bug.cgi?id=156570
+
+        Reviewed by Darin Adler.
+
+        RenderTable::invalidateCollapsedBorders traverses all cells. It is called when table cell border changes.
+        This can result in O(n^2) during style resolve.
+
+        * rendering/RenderTable.cpp:
+        (WebCore::RenderTable::layout):
+        (WebCore::RenderTable::invalidateCollapsedBorders):
+
+            For cell border style change invalidate the hasEmptyCollapsedBorder bits only for the neighbouring cells.
+            They are the only ones that can be affected.
+
+        * rendering/RenderTable.h:
+        (WebCore::RenderTable::collapsedBordersAreValid):
+        (WebCore::RenderTable::collapsedEmptyBorderIsPresent):
+        (WebCore::RenderTable::currentBorderValue):
+        * rendering/RenderTableCell.cpp:
+        (WebCore::RenderTableCell::styleDidChange):
+
 2016-04-14  Manuel Rego Casasnovas  <[email protected]>
 
         [css-grid] Implement CSSGridTemplateAreasValue::equals

Modified: trunk/Source/WebCore/rendering/RenderTable.cpp (199551 => 199552)


--- trunk/Source/WebCore/rendering/RenderTable.cpp	2016-04-14 20:49:12 UTC (rev 199551)
+++ trunk/Source/WebCore/rendering/RenderTable.cpp	2016-04-14 21:09:19 UTC (rev 199552)
@@ -586,14 +586,32 @@
     clearNeedsLayout();
 }
 
-void RenderTable::invalidateCollapsedBorders()
+void RenderTable::invalidateCollapsedBorders(RenderTableCell* cellWithStyleChange)
 {
     m_collapsedBordersValid = false;
     m_collapsedBorders.clear();
+
+    for (auto& section : childrenOfType<RenderTableSection>(*this))
+        section.clearCachedCollapsedBorders();
+
+    if (!m_collapsedEmptyBorderIsPresent)
+        return;
+
+    if (cellWithStyleChange) {
+        // It is enough to invalidate just the surrounding cells when cell border style changes.
+        cellWithStyleChange->invalidateHasEmptyCollapsedBorders();
+        if (auto* below = cellBelow(cellWithStyleChange))
+            below->invalidateHasEmptyCollapsedBorders();
+        if (auto* above = cellAbove(cellWithStyleChange))
+            above->invalidateHasEmptyCollapsedBorders();
+        if (auto* before = cellBefore(cellWithStyleChange))
+            before->invalidateHasEmptyCollapsedBorders();
+        if (auto* after = cellAfter(cellWithStyleChange))
+            after->invalidateHasEmptyCollapsedBorders();
+        return;
+    }
+
     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
-        section.clearCachedCollapsedBorders();
-        if (!m_collapsedEmptyBorderIsPresent)
-            continue;
         for (auto* row = section.firstRow(); row; row = row->nextRow()) {
             for (auto* cell = row->firstCell(); cell; cell = cell->nextCell()) {
                 ASSERT(cell->table() == this);

Modified: trunk/Source/WebCore/rendering/RenderTable.h (199551 => 199552)


--- trunk/Source/WebCore/rendering/RenderTable.h	2016-04-14 20:49:12 UTC (rev 199551)
+++ trunk/Source/WebCore/rendering/RenderTable.h	2016-04-14 21:09:19 UTC (rev 199552)
@@ -239,7 +239,7 @@
  
     typedef Vector<CollapsedBorderValue> CollapsedBorderValues;
     bool collapsedBordersAreValid() const { return m_collapsedBordersValid; }
-    void invalidateCollapsedBorders();
+    void invalidateCollapsedBorders(RenderTableCell* cellWithStyleChange = nullptr);
     void collapsedEmptyBorderIsPresent() { m_collapsedEmptyBorderIsPresent = true; }
     const CollapsedBorderValue* currentBorderValue() const { return m_currentBorder; }
     

Modified: trunk/Source/WebCore/rendering/RenderTableCell.cpp (199551 => 199552)


--- trunk/Source/WebCore/rendering/RenderTableCell.cpp	2016-04-14 20:49:12 UTC (rev 199551)
+++ trunk/Source/WebCore/rendering/RenderTableCell.cpp	2016-04-14 21:09:19 UTC (rev 199552)
@@ -423,7 +423,7 @@
     // If border was changed, notify table.
     RenderTable* table = this->table();
     if (table && oldStyle && oldStyle->border() != style().border())
-        table->invalidateCollapsedBorders();
+        table->invalidateCollapsedBorders(this);
 }
 
 // The following rules apply for resolving conflicts and figuring out which border
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to