Optimize RenderTable::colToEffCol() for tables without colspans
authorlvidacs.u-szeged@partner.samsung.com <lvidacs.u-szeged@partner.samsung.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Mar 2014 23:16:28 +0000 (23:16 +0000)
committerlvidacs.u-szeged@partner.samsung.com <lvidacs.u-szeged@partner.samsung.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Mar 2014 23:16:28 +0000 (23:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=129298

Reviewed by Simon Fraser.

Create an alternative fast path to RenderTable colToEffCol() and effColToCol()
when there is no colspan or colspan does not exceed the width of table.
Blink merge https://codereview.chromium.org/154243002 by rhogan

PerformanceTests:

* Layout/large-table-with-collapsed-borders-and-colspans-wider-than-table.html: Added.
* Layout/large-table-with-collapsed-borders-and-colspans.html: Added.
* Layout/large-table-with-collapsed-borders-and-no-colspans.html: Added.
* Layout/resources/large-table-with-collapsed-borders.css: Added.
* Layout/resources/large-table-with-collapsed-borders.js: Added.

Source/WebCore:

* rendering/RenderTable.cpp:
(WebCore::RenderTable::RenderTable):
(WebCore::RenderTable::appendColumn):
(WebCore::RenderTable::recalcSections):
* rendering/RenderTable.h:
(WebCore::RenderTable::colToEffCol):
(WebCore::RenderTable::effColToCol):
(WebCore::RenderTable::hasCellColspanThatDeterminesTableWidth):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@166016 268f45cc-cd09-0410-ab3c-d52691b4dbfc

PerformanceTests/ChangeLog
PerformanceTests/Layout/large-table-with-collapsed-borders-and-colspans-wider-than-table.html [new file with mode: 0644]
PerformanceTests/Layout/large-table-with-collapsed-borders-and-colspans.html [new file with mode: 0644]
PerformanceTests/Layout/large-table-with-collapsed-borders-and-no-colspans.html [new file with mode: 0644]
PerformanceTests/Layout/resources/large-table-with-collapsed-borders.css [new file with mode: 0644]
PerformanceTests/Layout/resources/large-table-with-collapsed-borders.js [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderTable.cpp
Source/WebCore/rendering/RenderTable.h

index 8769a63..ea6669c 100644 (file)
@@ -1,3 +1,20 @@
+2014-03-20  Laszlo Vidacs  <lvidacs.u-szeged@partner.samsung.com>
+
+        Optimize RenderTable::colToEffCol() for tables without colspans
+        https://bugs.webkit.org/show_bug.cgi?id=129298
+
+        Reviewed by Simon Fraser.
+
+        Create an alternative fast path to RenderTable colToEffCol() and effColToCol()
+        when there is no colspan or colspan does not exceed the width of table.
+        Blink merge https://codereview.chromium.org/154243002 by rhogan
+
+        * Layout/large-table-with-collapsed-borders-and-colspans-wider-than-table.html: Added.
+        * Layout/large-table-with-collapsed-borders-and-colspans.html: Added.
+        * Layout/large-table-with-collapsed-borders-and-no-colspans.html: Added.
+        * Layout/resources/large-table-with-collapsed-borders.css: Added.
+        * Layout/resources/large-table-with-collapsed-borders.js: Added.
+
 2014-03-14  Maciej Stachowiak  <mjs@apple.com>
 
         Replace "Apple Computer, Inc." with "Apple Inc." in copyright headers
diff --git a/PerformanceTests/Layout/large-table-with-collapsed-borders-and-colspans-wider-than-table.html b/PerformanceTests/Layout/large-table-with-collapsed-borders-and-colspans-wider-than-table.html
new file mode 100644 (file)
index 0000000..5596244
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Table layout performance with collapsed borders and a cell with a colspan wider than the other rows in the table.</title>
+        <link rel="stylesheet" href="resources/large-table-with-collapsed-borders.css" TYPE="text/css"></link>
+        <script src="../resources/runner.js"></script>
+        <script src="resources/large-table-with-collapsed-borders.js"></script>
+    </head>
+    <body>
+        <pre id="log"></pre>
+        <script>
+            PerfTestRunner.measureTime({run: createTableTestFunction(400, 100, 500)});
+        </script>
+    </body>
+</html>
diff --git a/PerformanceTests/Layout/large-table-with-collapsed-borders-and-colspans.html b/PerformanceTests/Layout/large-table-with-collapsed-borders-and-colspans.html
new file mode 100644 (file)
index 0000000..5ccbbe1
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Table layout performance with collapsed borders and a cell with a colspan that can be accomodated by the width given by other rows in the table.</title>
+        <link rel="stylesheet" href="resources/large-table-with-collapsed-borders.css" TYPE="text/css"></link>
+        <script src="../resources/runner.js"></script>
+        <script src="resources/large-table-with-collapsed-borders.js"></script>
+    </head>
+    <body>
+        <pre id="log"></pre>
+        <script>
+            PerfTestRunner.measureTime({run: createTableTestFunction(400, 100, 50)});
+        </script>
+    </body>
+</html>
diff --git a/PerformanceTests/Layout/large-table-with-collapsed-borders-and-no-colspans.html b/PerformanceTests/Layout/large-table-with-collapsed-borders-and-no-colspans.html
new file mode 100644 (file)
index 0000000..24eeb10
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Table layout performance with collapsed borders and no cells with colspan.</title>
+        <link rel="stylesheet" href="resources/large-table-with-collapsed-borders.css" TYPE="text/css"></link>
+        <script src="../resources/runner.js"></script>
+        <script src="resources/large-table-with-collapsed-borders.js"></script>
+    </head>
+    <body>
+        <pre id="log"></pre>
+        <script>
+            PerfTestRunner.measureTime({run: createTableTestFunction(400, 100, 0)});
+        </script>
+    </body>
+</html>
diff --git a/PerformanceTests/Layout/resources/large-table-with-collapsed-borders.css b/PerformanceTests/Layout/resources/large-table-with-collapsed-borders.css
new file mode 100644 (file)
index 0000000..b936e5d
--- /dev/null
@@ -0,0 +1,14 @@
+html, body {
+    margin: 0;
+}
+
+table {
+    border-collapse: collapse;
+    border : 1px solid red;
+}
+td {
+    border : 1px solid blue;
+    width: 5px;
+    height: 5px;
+}
+
diff --git a/PerformanceTests/Layout/resources/large-table-with-collapsed-borders.js b/PerformanceTests/Layout/resources/large-table-with-collapsed-borders.js
new file mode 100644 (file)
index 0000000..373432d
--- /dev/null
@@ -0,0 +1,32 @@
+(function() {
+    function createElement(tag, parent, className, id) {
+        var el = document.createElement(tag);
+        el.className = className;
+        if (id)
+            el.id = id;
+        parent.appendChild(el);
+        return el;
+    }
+
+    function createTable(width, height, colspan) {
+        var table = createElement("table", document.body, "table");
+        for (var y = 0; y < height; ++y) {
+            var tr = createElement("tr", table, "tr");
+            for (var x = 0; x < width; ++x) {
+                var td = createElement("td", tr, "td");
+                if (colspan > 0 && x==10 && y==0)
+                    table.rows[y].cells[x].colSpan = colspan;
+            }
+        }
+        return table;
+    }
+
+    function createTestFunction(width, height, colspan) {
+        return function() {
+            var table = createTable(width, height, colspan);
+            table.clientHeight;
+        }
+    }
+
+    window.createTableTestFunction = createTestFunction;
+})();
index d847b3b..2a4ef85 100644 (file)
@@ -1,3 +1,23 @@
+2014-03-20  Laszlo Vidacs  <lvidacs.u-szeged@partner.samsung.com>
+
+        Optimize RenderTable::colToEffCol() for tables without colspans
+        https://bugs.webkit.org/show_bug.cgi?id=129298
+
+        Reviewed by Simon Fraser.
+
+        Create an alternative fast path to RenderTable colToEffCol() and effColToCol()
+        when there is no colspan or colspan does not exceed the width of table.
+        Blink merge https://codereview.chromium.org/154243002 by rhogan
+
+        * rendering/RenderTable.cpp:
+        (WebCore::RenderTable::RenderTable):
+        (WebCore::RenderTable::appendColumn):
+        (WebCore::RenderTable::recalcSections):
+        * rendering/RenderTable.h:
+        (WebCore::RenderTable::colToEffCol):
+        (WebCore::RenderTable::effColToCol):
+        (WebCore::RenderTable::hasCellColspanThatDeterminesTableWidth):
+
 2014-03-20  Simon Fraser  <simon.fraser@apple.com>
 
         FrameView::paintContents() is not called for composited content
index 2511ee6..5d0afb2 100644 (file)
@@ -60,6 +60,7 @@ RenderTable::RenderTable(Element& element, PassRef<RenderStyle> style)
     , m_needsSectionRecalc(false)
     , m_columnLogicalWidthChanged(false)
     , m_columnRenderersValid(false)
+    , m_hasCellColspanThatDeterminesTableWidth(false)
     , m_hSpacing(0)
     , m_vSpacing(0)
     , m_borderStart(0)
@@ -82,6 +83,7 @@ RenderTable::RenderTable(Document& document, PassRef<RenderStyle> style)
     , m_needsSectionRecalc(false)
     , m_columnLogicalWidthChanged(false)
     , m_columnRenderersValid(false)
+    , m_hasCellColspanThatDeterminesTableWidth(false)
     , m_hSpacing(0)
     , m_vSpacing(0)
     , m_borderStart(0)
@@ -831,6 +833,10 @@ void RenderTable::appendColumn(unsigned span)
     unsigned newColumnIndex = m_columns.size();
     m_columns.append(ColumnStruct(span));
 
+    // Unless the table has cell(s) with colspan that exceed the number of columns afforded
+    // by the other rows in the table we can use the fast path when mapping columns to effective columns.
+    m_hasCellColspanThatDeterminesTableWidth = m_hasCellColspanThatDeterminesTableWidth || span > 1;
+
     // Propagate the change in our columns representation to the sections that don't need
     // cell recalc. If they do, they will be synced up directly with m_columns later.
     for (auto& section : childrenOfType<RenderTableSection>(*this)) {
@@ -989,6 +995,7 @@ void RenderTable::recalcSections() const
     m_foot = 0;
     m_firstBody = 0;
     m_hasColElements = false;
+    m_hasCellColspanThatDeterminesTableWidth = hasCellColspanThatDeterminesTableWidth();
 
     // We need to get valid pointers to caption, head, foot and first body again
     RenderObject* nextSibling;
index a446e45..09e0bd8 100644 (file)
@@ -173,6 +173,9 @@ public:
     
     unsigned colToEffCol(unsigned column) const
     {
+        if (!m_hasCellColspanThatDeterminesTableWidth)
+            return column;
+
         unsigned effColumn = 0;
         unsigned numColumns = numEffCols();
         for (unsigned c = 0; effColumn < numColumns && c + m_columns[effColumn].span - 1 < column; ++effColumn)
@@ -182,6 +185,9 @@ public:
     
     unsigned effColToCol(unsigned effCol) const
     {
+        if (!m_hasCellColspanThatDeterminesTableWidth)
+            return effCol;
+
         unsigned c = 0;
         for (unsigned i = 0; i < effCol; i++)
             c += m_columns[i].span;
@@ -345,6 +351,16 @@ private:
 
     bool m_columnLogicalWidthChanged : 1;
     mutable bool m_columnRenderersValid: 1;
+    mutable bool m_hasCellColspanThatDeterminesTableWidth : 1;
+
+    bool hasCellColspanThatDeterminesTableWidth() const
+    {
+        for (unsigned c = 0; c < numEffCols(); c++) {
+            if (m_columns[c].span > 1)
+                return true;
+        }
+        return false;
+    }
 
     short m_hSpacing;
     short m_vSpacing;