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 8769a63b2a0dd731c3fe217d7afab2c9f04e6b54..ea6669c7d477c147d3354e038ff653e1a41a59d0 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 d847b3bcc1c8c05e5fbe788ed935e251417fd09d..2a4ef85bfa556603109f405cfcb9fd3f23e26ca0 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 2511ee6e0598d8edf85ed80c16a8e29f0958b916..5d0afb24aba77ec1a28878266a5c63f86f913457 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 a446e45910dd92ba4126985b4bcdc5611e982631..09e0bd8ff3febb452aaa3645220a44978c613ad9 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;